File size: 19,516 Bytes
b755be3
 
 
 
3382560
b755be3
 
 
 
 
 
 
 
 
 
 
 
 
 
3382560
376cac5
b755be3
 
 
 
 
3382560
99a052b
b755be3
 
 
 
 
3382560
99a052b
b755be3
 
 
 
 
3382560
99a052b
376cac5
 
 
 
 
 
 
b755be3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3382560
 
 
 
99a052b
3382560
99a052b
3382560
99a052b
b755be3
99a052b
 
b755be3
 
 
 
99a052b
 
b755be3
3382560
b755be3
 
99a052b
b755be3
 
99a052b
b755be3
 
 
 
3382560
 
b755be3
 
 
 
3382560
 
b755be3
 
 
99a052b
b755be3
 
 
 
99a052b
b755be3
 
 
99a052b
b755be3
99a052b
b755be3
 
 
3382560
 
 
 
 
 
99a052b
3382560
 
 
b755be3
 
3382560
 
b755be3
 
 
 
 
 
99a052b
b755be3
 
 
 
 
99a052b
b755be3
 
 
 
 
99a052b
b755be3
 
 
 
 
 
 
 
3382560
 
b755be3
 
3382560
b755be3
 
 
 
 
 
 
3382560
 
 
 
 
 
 
 
 
 
b755be3
 
 
3382560
99a052b
3382560
 
b755be3
3382560
 
 
 
 
 
b755be3
 
 
 
cdf0e07
99a052b
b755be3
 
 
 
 
 
99a052b
b755be3
cdf0e07
b755be3
 
 
 
3382560
 
99a052b
3382560
 
 
99a052b
3382560
 
 
99a052b
3382560
 
99a052b
3382560
99a052b
3382560
 
99a052b
3382560
 
 
99a052b
3382560
 
 
 
b755be3
 
 
99a052b
3382560
 
99a052b
3382560
 
 
b755be3
3382560
b755be3
3382560
 
 
 
 
 
 
 
 
 
99a052b
3382560
 
 
b755be3
3382560
 
 
99a052b
3382560
 
 
 
 
99a052b
3382560
 
 
b755be3
 
3382560
b755be3
3382560
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b755be3
 
 
 
3382560
 
 
 
 
 
 
 
b755be3
 
 
99a052b
3382560
 
99a052b
3382560
 
 
b755be3
 
 
 
 
 
 
99a052b
3382560
b755be3
3382560
99a052b
3382560
99a052b
3382560
 
99a052b
 
3382560
 
 
 
 
 
 
 
 
 
 
 
99a052b
3382560
 
 
99a052b
 
3382560
 
 
99a052b
3382560
 
 
 
 
99a052b
3382560
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b755be3
3382560
 
 
 
 
 
 
b755be3
3382560
 
 
 
b755be3
 
3382560
 
 
 
b755be3
3382560
 
 
 
 
b755be3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3382560
99a052b
 
 
b755be3
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
import gradio as gr
import json
import random
import string
from datetime import datetime, timedelta
from pathlib import Path

# Admin password
ADMIN_PASSWORD = "@mikaelJ46"

# Storage file for school codes
STORAGE_FILE = Path("school_codes.json")

# Platform links - UPDATE THESE WITH YOUR ACTUAL HUGGINGFACE SPACE URLS
PLATFORMS = [
    {
        "name": "Chemistry & Biology",
        "description": "Deep understanding focus with AI-powered learning",
        "subjects": ["Chemistry", "Biology"],
        "url": "https://mikaelj46-chembio.hf.space/",
        "emoji": ""
    },
    {
        "name": "Geography, History & Business",
        "description": "Comprehensive humanities and business studies",
        "subjects": ["Geography", "History", "Business"],
        "url": "https://mikaelj46-goehistbusn.hf.space/",
        "emoji": ""
    },
    {
        "name": "French & EFL",
        "description": "Language learning with AI translation and dictionary",
        "subjects": ["French", "EFL"],
        "url": "https://mikaelj46-language-app.hf.space/",
        "emoji": ""
    },
    {
        "name": "Mathematics & Physics",
        "description": "Step-by-step problem solving and practice",
        "subjects": ["Mathematics", "Physics"],
        "url": "https://mikaelj46-mathphysicstool.hf.space/",
        "emoji": ""
    },
     {
        "name": "Physical education $ ICT",
        "description": "Step-by-step problem solving and practice",
        "subjects": ["PE", "ICT"],
        "url": "https://mikaelj46-peict.hf.space/",
        "emoji": ""
    }
]

# Storage functions
def load_codes():
    """Load school codes from storage file"""
    if STORAGE_FILE.exists():
        with open(STORAGE_FILE, 'r') as f:
            return json.load(f)
    return {}

def save_codes(codes):
    """Save school codes to storage file"""
    with open(STORAGE_FILE, 'w') as f:
        json.dump(codes, f, indent=2)

def generate_code():
    """Generate random 8-character school code"""
    chars = string.ascii_uppercase + string.digits
    return ''.join(random.choice(chars) for _ in range(8))

# Authentication functions
def verify_student(school_code):
    """Verify student school code"""
    codes = load_codes()
    code = school_code.upper().strip()
    
    if code in codes:
        if codes[code]['active']:
            # Check expiry
            try:
                expiry = datetime.fromisoformat(codes[code].get('expiry_date', datetime.now().isoformat()))
                if datetime.now() < expiry:
                    return True, f" Welcome! Access granted with code: {code}", codes[code].get('name', 'Unknown School')
                else:
                    return False, " This school code has expired", None
            except:
                return True, f" Welcome! Access granted with code: {code}", codes[code].get('name', 'Unknown School')
        else:
            return False, " This school code has been deactivated", None
    return False, " Invalid school code", None

def verify_admin(password):
    """Verify admin password"""
    if password == ADMIN_PASSWORD:
        return True, " Admin access granted"
    return False, " Incorrect admin password"

def create_school_code(school_name, admin_password, expiry_days=365):
    """Admin function to create new school code"""
    if admin_password != ADMIN_PASSWORD:
        return " Invalid admin password", ""
    
    if not school_name.strip():
        return " Please enter a school name", ""
    
    codes = load_codes()
    new_code = generate_code()
    
    expiry_date = (datetime.now() + timedelta(days=expiry_days)).isoformat()
    
    codes[new_code] = {
        "name": school_name,
        "code": new_code,
        "active": True,
        "created_at": datetime.now().isoformat(),
        "expiry_date": expiry_date
    }
    
    save_codes(codes)
    return f" Code generated successfully!\n\n**School Code:** `{new_code}`\n**School Name:** {school_name}\n**Expires:** {expiry_date[:10]}", new_code

def get_all_codes(admin_password):
    """Get list of all school codes for admin"""
    if admin_password != ADMIN_PASSWORD:
        return " Invalid admin password"
    
    codes = load_codes()
    if not codes:
        return " No school codes created yet"
    
    output = f"#  All School Codes ({len(codes)})\n\n"
    for code, data in codes.items():
        status = "🟒 Active" if data['active'] else "πŸ”΄ Inactive"
        created = datetime.fromisoformat(data['created_at']).strftime("%Y-%m-%d %H:%M")
        
        # Check expiry
        try:
            expiry = datetime.fromisoformat(data.get('expiry_date', datetime.now().isoformat()))
            expiry_str = expiry.strftime("%Y-%m-%d")
            if datetime.now() >= expiry:
                status = " Expired"
        except:
            expiry_str = "N/A"
        
        output += f"### {status} `{code}`\n"
        output += f"- **School:** {data['name']}\n"
        output += f"- **Created:** {created}\n"
        output += f"- **Expires:** {expiry_str}\n\n"
    
    return output

def toggle_code_status(school_code, admin_password):
    """Toggle active status of a school code"""
    if admin_password != ADMIN_PASSWORD:
        return " Invalid admin password"
    
    codes = load_codes()
    code = school_code.upper().strip()
    
    if code not in codes:
        return " Code not found"
    
    codes[code]['active'] = not codes[code]['active']
    save_codes(codes)
    
    status = "activated" if codes[code]['active'] else "deactivated"
    return f" Code {code} has been {status}"

def create_platform_links():
    """Create HTML for platform links"""
    html = "<div style='display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-top: 20px;'>"
    
    for platform in PLATFORMS:
        subjects = ", ".join(platform['subjects'])
        html += f"""
        <div style='border: 2px solid #e5e7eb; border-radius: 12px; padding: 20px; background: white; box-shadow: 0 4px 6px rgba(0,0,0,0.1); transition: transform 0.3s;'>
            <h3 style='margin: 0 0 10px 0; color: #1976d2;'>{platform['emoji']} {platform['name']}</h3>
            <p style='color: #6b7280; font-size: 14px; margin: 10px 0;'>{platform['description']}</p>
            <p style='font-size: 12px; color: #9ca3af; margin: 10px 0;'><strong>Subjects:</strong> {subjects}</p>
            <a href='{platform['url']}' target='_blank' style='display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 10px 20px; border-radius: 8px; text-decoration: none; margin-top: 10px; font-weight: bold;'>Open Platform β†’</a>
        </div>
        """
    
    html += "</div>"
    return html

# Create the Gradio interface
with gr.Blocks(title="IGCSE/GCSE Master Platform", theme=gr.themes.Soft(), css="""
    .gradio-container {
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }
    
    .platform-card:hover {
        transform: translateY(-5px);
        box-shadow: 0 8px 12px rgba(0,0,0,0.15);
    }
""") as app:
    
    # Header
    gr.Markdown("""
    <div style="text-align: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 40px; border-radius: 15px; margin-bottom: 20px;">
        <h1 style="color: white; margin: 0; font-size: 2.5rem;"> IGCSE/GCSE Master Platform</h1>
        <p style="color: white; margin: 10px 0 0 0; font-size: 1.2rem;">AI-Powered Learning Platform for All Subjects</p>
    </div>
    
    <div style="text-align: center; margin-bottom: 30px;">
        <span style="background: #e3f2fd; color: #1976d2; padding: 8px 16px; border-radius: 20px; margin: 0 5px; font-weight: bold;">πŸ€– AI Tutors</span>
        <span style="background: #e8f5e9; color: #2e7d32; padding: 8px 16px; border-radius: 20px; margin: 0 5px; font-weight: bold;">πŸ“ Past Papers</span>
        <span style="background: #fff3e0; color: #e65100; padding: 8px 16px; border-radius: 20px; margin: 0 5px; font-weight: bold;">🎯 Practice Questions</span>
        <span style="background: #fce4ec; color: #c2185b; padding: 8px 16px; border-radius: 20px; margin: 0 5px; font-weight: bold;">πŸ’― Detailed Feedback</span>
    </div>
    """)
    
    with gr.Tabs() as tabs:
        
        # HOME TAB - REMOVED PLATFORM LINKS
        with gr.Tab(" Home"):
            gr.Markdown("""
            ## Welcome to IGCSE/GCSE Master!
            
            Our comprehensive learning platform covers all major subjects with AI tutors, practice questions, 
            past papers, and deep understanding focus.
            
            ###  Access Required
            
            To view and access our learning platforms, please log in using the **Student Login** tab with your school code.
            
            ---
            ### ✨ Platform Features:
            
            <div style='display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-top: 20px;'>
                <div style='background: #e3f2fd; padding: 20px; border-radius: 10px; border-left: 4px solid #1976d2;'>
                    <h4 style='color: #1976d2; margin-top: 0;'>Justice AI Tutors</h4>
                    <p style='color: #555; margin-bottom: 0;'>Get personalized help with deep understanding focus</p>
                </div>
                <div style='background: #e8f5e9; padding: 20px; border-radius: 10px; border-left: 4px solid #2e7d32;'>
                    <h4 style='color: #2e7d32; margin-top: 0;'> Past Papers</h4>
                    <p style='color: #555; margin-bottom: 0;'>Access real exam questions indexed by topic</p>
                </div>
                <div style='background: #fff3e0; padding: 20px; border-radius: 10px; border-left: 4px solid #e65100;'>
                    <h4 style='color: #e65100; margin-top: 0;'> Practice Questions</h4>
                    <p style='color: #555; margin-bottom: 0;'>Generate unlimited practice with detailed feedback</p>
                </div>
                
                <div style='background: #f3e5f5; padding: 20px; border-radius: 10px; border-left: 4px solid #7b1fa2;'>
                    <h4 style='color: #7b1fa2; margin-top: 0;'> Detailed Marking</h4>
                    <p style='color: #555; margin-bottom: 0;'>Comprehensive feedback on all answers</p>
                </div>
                
            </div>
            
            ---
            ###  Getting Started:
            
            **Students**: Enter your school code in the **Student Login** tab to access all platforms
            
            **Teachers & Admins**: Use your respective tabs to manage content and school codes
            """)
        
        # STUDENT LOGIN TAB
        with gr.Tab(" Student Login"):
            gr.Markdown("""
            <div style="text-align: center; padding: 20px;">
                <h2 style="color: #1976d2;"> Student Access</h2>
                <p style="color: #666;">Enter your school code to access all learning platforms</p>
            </div>
            """)
            
            student_school_state = gr.State(None)
            
            with gr.Row():
                with gr.Column(scale=1):
                    pass
                with gr.Column(scale=2):
                    with gr.Group() as student_login_section:
                        student_code_input = gr.Textbox(
                            label="Enter Your School Code",
                            placeholder="8-character code (e.g., ABC12345)",
                            max_lines=1
                        )
                        student_login_btn = gr.Button(" Verify Access", variant="primary", size="lg")
                        student_status = gr.Markdown("")
                with gr.Column(scale=1):
                    pass
            
            with gr.Group(visible=False) as student_platforms_section:
                gr.Markdown("""
                <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%); border-radius: 10px; margin-bottom: 20px;">
                    <h2 style="color: #2e7d32; margin: 0;"> Access Granted!</h2>
                </div>
                """)
                
                student_info_display = gr.Markdown("")
                
                gr.Markdown("###  Choose Your Learning Platform:")
                student_platforms_html = gr.HTML()
                
                student_logout_btn = gr.Button("πŸšͺ Logout", variant="secondary")
            
            def student_login(code):
                success, message, school_name = verify_student(code)
                if success:
                    return {
                        student_login_section: gr.update(visible=False),
                        student_platforms_section: gr.update(visible=True),
                        student_status: gr.update(value=""),
                        student_info_display: gr.update(value=f"**School:** {school_name}\n**Code:** {code.upper()}"),
                        student_platforms_html: gr.update(value=create_platform_links()),
                        student_school_state: school_name
                    }
                return {
                    student_status: gr.update(value=message),
                    student_platforms_section: gr.update(visible=False)
                }
            
            def student_logout():
                return {
                    student_login_section: gr.update(visible=True),
                    student_platforms_section: gr.update(visible=False),
                    student_code_input: gr.update(value=""),
                    student_status: gr.update(value=""),
                    student_school_state: None
                }
            
            student_login_btn.click(
                student_login,
                inputs=[student_code_input],
                outputs=[student_login_section, student_platforms_section, student_status, 
                        student_info_display, student_platforms_html, student_school_state]
            )
            
            student_logout_btn.click(
                student_logout,
                outputs=[student_login_section, student_platforms_section, student_code_input, 
                        student_status, student_school_state]
            )
        
        # ADMIN TAB
        with gr.Tab(" Admin Panel"):
            gr.Markdown("""
            <div style="text-align: center; padding: 20px;">
                <h2 style="color: #c62828;"> Administrator Panel</h2>
                <p style="color: #666;">Manage school codes and platform access</p>
            </div>
            """)
            
            admin_password_global = gr.Textbox(
                label="Admin Password",
                type="password",
                placeholder="Enter admin password"
            )
            
            admin_verify_btn = gr.Button(" Login", variant="primary")
            admin_login_status = gr.Markdown("")
            
            with gr.Group(visible=False) as admin_tools:
                gr.Markdown("###  Admin Access Granted")
                
                admin_logout_btn = gr.Button(" Logout", variant="secondary")
                
                with gr.Tabs():
                    with gr.Tab(" Create Code"):
                        gr.Markdown("###  Generate New School Code")
                        with gr.Row():
                            school_name_input = gr.Textbox(
                                label="School/Institution Name",
                                placeholder="Enter school or group name"
                            )
                        expiry_days_slider = gr.Slider(
                            minimum=30,
                            maximum=730,
                            value=365,
                            step=30,
                            label="Validity (days)"
                        )
                        create_code_btn = gr.Button(" Generate Code", variant="primary")
                        create_status = gr.Markdown("")
                    
                    with gr.Tab("πŸ“‹ Manage Codes"):
                        gr.Markdown("###  All School Codes")
                        view_codes_btn = gr.Button(" View All Codes", variant="secondary")
                        codes_display = gr.Markdown("")
                        
                        gr.Markdown("---")
                        gr.Markdown("###  Activate/Deactivate Code")
                        with gr.Row():
                            toggle_code_input = gr.Textbox(
                                label="School Code",
                                placeholder="Enter code to toggle"
                            )
                            toggle_btn = gr.Button(" Toggle Status", variant="secondary")
                        
                        toggle_status = gr.Markdown("")
            
            def admin_login(password):
                success, message = verify_admin(password)
                if success:
                    return {
                        admin_tools: gr.update(visible=True),
                        admin_login_status: gr.update(value=message),
                        admin_password_global: gr.update(visible=False),
                        admin_verify_btn: gr.update(visible=False)
                    }
                return {
                    admin_login_status: gr.update(value=message),
                    admin_tools: gr.update(visible=False)
                }
            
            def admin_logout_fn():
                return {
                    admin_tools: gr.update(visible=False),
                    admin_password_global: gr.update(visible=True, value=""),
                    admin_verify_btn: gr.update(visible=True),
                    admin_login_status: gr.update(value="")
                }
            
            admin_verify_btn.click(
                admin_login,
                inputs=[admin_password_global],
                outputs=[admin_tools, admin_login_status, admin_password_global, admin_verify_btn]
            )
            
            admin_logout_btn.click(
                admin_logout_fn,
                outputs=[admin_tools, admin_password_global, admin_verify_btn, admin_login_status]
            )
            
            create_code_btn.click(
                lambda name, days, pwd: create_school_code(name, pwd, days),
                inputs=[school_name_input, expiry_days_slider, admin_password_global],
                outputs=[create_status]
            )
            
            view_codes_btn.click(
                get_all_codes,
                inputs=[admin_password_global],
                outputs=[codes_display]
            )
            
            toggle_btn.click(
                toggle_code_status,
                inputs=[toggle_code_input, admin_password_global],
                outputs=[toggle_status]
            )
    
    # Footer
    gr.Markdown("""
    ---
    <div style='text-align: center; color: #6b7280; font-size: 14px; padding: 20px;'>
        <p style='margin: 5px 0;'><strong>Β© @mikael Jutice IGCSE/GCSE Master Platform</strong></p>
        <p style='margin: 5px 0;'>Powered by Justice AI</p>
        <p style='margin: 5px 0;'> system ensures 24/7 availability</p>
    </div>
    """)

# Launch the app
if __name__ == "__main__":
    app.launch()