0% found this document useful (0 votes)
6 views19 pages

Python code 3

Learn how to code on python 4
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views19 pages

Python code 3

Learn how to code on python 4
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 19

I'll create a comprehensive quiz app called "Quarix" with all the features you

requested. This will be a multi-file application with an awesome GUI


interface.
# main.py
import customtkinter as ctk
import tkinter as tk
from tkinter import messagebox
import pygame
import json
import os
import threading
import time
import random
from datetime import datetime, timedelta
import requests
import google.generativeai as genai
from PIL import Image, ImageTk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import sqlite3
from dataclasses import dataclass
from typing import List, Dict, Optional
import webbrowser

# Initialize pygame for sounds


pygame.mixer.init()

# Configure Gemini AI (You'll need to add your API key)


genai.configure(api_key="YOUR_GEMINI_API_KEY_HERE")

@dataclass
class Question:
question: str
options: List[str]
correct_answer: int
explanation: str

class DatabaseManager:
def __init__(self):
self.db_path = "quarix_data.db"
self.init_database()

def init_database(self):
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()

# Users table
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE,
email TEXT,
password TEXT,
coins INTEGER DEFAULT 0,
gems INTEGER DEFAULT 0,
streak_freezes INTEGER DEFAULT 0,
current_streak INTEGER DEFAULT 0,
last_activity DATE,
total_questions INTEGER DEFAULT 0,
correct_answers INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')

# Quiz history table


cursor.execute('''
CREATE TABLE IF NOT EXISTS quiz_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
class_level TEXT,
subject TEXT,
topic TEXT,
score REAL,
total_questions INTEGER,
correct_answers INTEGER,
date_taken TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id)
)
''')

# Daily activity table


cursor.execute('''
CREATE TABLE IF NOT EXISTS daily_activity (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
date DATE,
questions_answered INTEGER DEFAULT 0,
correct_answers INTEGER DEFAULT 0,
FOREIGN KEY (user_id) REFERENCES users (id)
)
''')

conn.commit()
conn.close()

class SoundManager:
def __init__(self):
self.sounds = {}
self.load_sounds()

def load_sounds(self):
# Create default sounds if files don't exist
try:
# You can replace these with actual sound files
self.sounds['correct'] =
pygame.mixer.Sound("sounds/correct.wav") if
os.path.exists("sounds/correct.wav") else None
self.sounds['wrong'] =
pygame.mixer.Sound("sounds/wrong.wav") if
os.path.exists("sounds/wrong.wav") else None
self.sounds['celebration'] =
pygame.mixer.Sound("sounds/celebration.wav") if
os.path.exists("sounds/celebration.wav") else None
except:
self.sounds = {'correct': None, 'wrong': None,
'celebration': None}

def play_sound(self, sound_type):


if self.sounds.get(sound_type):
self.sounds[sound_type].play()

class GeminiQuestionGenerator:
def __init__(self):
self.model = genai.GenerativeModel('gemini-pro')

def generate_questions(self, class_level, subject, topic,


num_questions):
try:
if topic.lower() == "random":
prompt = f"""
Generate {num_questions} multiple choice questions for
{class_level} level {subject}.
Cover various topics in {subject} appropriate for
{class_level}.

Format each question as:


Question: [question text]
A) [option 1]
B) [option 2]
C) [option 3]
D) [option 4]
Correct Answer: [A/B/C/D]
Explanation: [brief explanation]
---
"""
else:
prompt = f"""
Generate {num_questions} multiple choice questions
about {topic} in {subject} for {class_level} level.

Format each question as:


Question: [question text]
A) [option 1]
B) [option 2]
C) [option 3]
D) [option 4]
Correct Answer: [A/B/C/D]
Explanation: [brief explanation]
---
"""

response = self.model.generate_content(prompt)
return self.parse_questions(response.text)
except Exception as e:
print(f"Error generating questions: {e}")
return self.get_fallback_questions(num_questions)

def parse_questions(self, response_text):


questions = []
question_blocks = response_text.split('---')

for block in question_blocks:


if not block.strip():
continue

lines = [line.strip() for line in block.strip().split('\


n') if line.strip()]

if len(lines) >= 7:
question_text = lines[0].replace('Question:',
'').strip()
options = []
correct_answer = 0
explanation = ""

for i, line in enumerate(lines[1:5]):


option = line[3:].strip() if len(line) > 3 else
line
options.append(option)

for line in lines[5:]:


if 'Correct Answer:' in line:
answer_letter = line.split(':')
[1].strip().upper()
correct_answer = ord(answer_letter) - ord('A')
elif 'Explanation:' in line:
explanation = line.replace('Explanation:',
'').strip()
if question_text and len(options) == 4:
questions.append(Question(question_text, options,
correct_answer, explanation))

return questions if questions else


self.get_fallback_questions(3)

def get_fallback_questions(self, num_questions):


fallback = [
Question(
"What is 2 + 2?",
["3", "4", "5", "6"],
1,
"2 + 2 = 4 is basic addition."
),
Question(
"What is the capital of Nigeria?",
["Lagos", "Abuja", "Kano", "Port Harcourt"],
1,
"Abuja is the capital city of Nigeria."
),
Question(
"Which planet is closest to the Sun?",
["Venus", "Mercury", "Earth", "Mars"],
1,
"Mercury is the closest planet to the Sun."
)
]
return fallback[:num_questions]

class SplashScreen:
def __init__(self, parent, callback):
self.parent = parent
self.callback = callback
self.create_splash()

def create_splash(self):
# Create splash window
self.splash = ctk.CTkToplevel(self.parent)
self.splash.title("")
self.splash.geometry("800x600")
self.splash.configure(fg_color=("#1a1a2e", "#16213e"))

# Center the window


self.splash.transient(self.parent)
self.splash.grab_set()

# Create canvas for animation


self.canvas = tk.Canvas(
self.splash,
width=800,
height=600,
bg="#1a1a2e",
highlightthickness=0
)
self.canvas.pack(fill="both", expand=True)

# Start animation
self.animate_text()

def animate_text(self):
text = "Quarix Quiz"
x_start = 200
y_pos = 250

def write_letter(index):
if index < len(text):
letter = text[index]
x_pos = x_start + (index * 30)

self.canvas.create_text(
x_pos, y_pos,
text=letter,
font=("Arial", 36, "bold"),
fill="#00d4ff",
tags="title"
)

self.splash.after(200, lambda: write_letter(index +


1))
else:
self.splash.after(1000, self.show_logo)

write_letter(0)

def show_logo(self):
# Create a placeholder logo (you can replace with your actual
logo)
logo_frame = ctk.CTkFrame(
self.splash,
width=200,
height=200,
corner_radius=100,
fg_color=("#00d4ff", "#0099cc")
)
logo_frame.place(relx=0.5, rely=0.6, anchor="center")

logo_label = ctk.CTkLabel(
logo_frame,
text="Q",
font=("Arial", 72, "bold"),
text_color="white"
)
logo_label.place(relx=0.5, rely=0.5, anchor="center")

# Animate logo appearance


self.animate_logo_scale(logo_frame, 0.1)

def animate_logo_scale(self, widget, scale):


if scale <= 1.0:
# Simple scaling effect
self.splash.after(50, lambda:
self.animate_logo_scale(widget, scale + 0.1))
else:
self.splash.after(1500, self.finish_splash)

def finish_splash(self):
self.splash.destroy()
self.callback()

class QuarixApp:
def __init__(self):
# Initialize main window
ctk.set_appearance_mode("dark")
ctk.set_default_color_theme("blue")

self.root = ctk.CTk()
self.root.title("Quarix Quiz")
self.root.geometry("1200x800")
self.root.configure(fg_color=("#0f0f23", "#1a1a2e"))

# Initialize managers
self.db_manager = DatabaseManager()
self.sound_manager = SoundManager()
self.question_generator = GeminiQuestionGenerator()

# App state
self.current_user = None
self.current_questions = []
self.current_question_index = 0
self.quiz_score = 0
self.quiz_answers = []

# Hide main window initially


self.root.withdraw()

# Show splash screen


self.splash = SplashScreen(self.root, self.show_main_app)
# Class and subject data
self.class_data = {
"Primary": ["Nursery 1", "Nursery 2", "Primary 1",
"Primary 2", "Primary 3", "Primary 4", "Primary 5", "Primary 6"],
"Secondary": ["JSS 1", "JSS 2", "JSS 3", "SS 1", "SS 2",
"SS 3"],
"University": ["100 Level", "200 Level", "300 Level", "400
Level", "500 Level", "600 Level"]
}

self.subjects = [
"Mathematics", "English Language", "Physics", "Chemistry",
"Biology",
"Geography", "History", "Economics", "Government",
"Literature",
"Agricultural Science", "Computer Science", "Further
Mathematics",
"Technical Drawing", "Fine Arts", "Music", "Physical
Education",
"Home Economics", "Business Studies", "CRS"
]

def show_main_app(self):
self.root.deiconify()
self.create_main_interface()

def create_main_interface(self):
# Create main container
self.main_container = ctk.CTkFrame(self.root,
fg_color="transparent")
self.main_container.pack(fill="both", expand=True, padx=20,
pady=20)

# Create navigation
self.create_navigation()

# Create content area


self.content_frame = ctk.CTkFrame(self.main_container)
self.content_frame.pack(fill="both", expand=True, pady=(20,
0))

# Show home screen by default


self.show_home_screen()

def create_navigation(self):
nav_frame = ctk.CTkFrame(self.main_container, height=80)
nav_frame.pack(fill="x")
nav_frame.pack_propagate(False)

# Navigation buttons
nav_buttons = [
("🏠 Home", self.show_home_screen),
("🎁 Rewards", self.show_rewards_screen),
("🔥 Streak", self.show_streak_screen),
("👤 Profile", self.show_profile_screen),
("🏆 Leaderboard", self.show_leaderboard_screen)
]

for i, (text, command) in enumerate(nav_buttons):


btn = ctk.CTkButton(
nav_frame,
text=text,
command=command,
width=200,
height=50,
font=("Arial", 16, "bold"),
corner_radius=25
)
btn.pack(side="left", padx=10, pady=15)

def clear_content(self):
for widget in self.content_frame.winfo_children():
widget.destroy()

def show_home_screen(self):
self.clear_content()

# Title with streak


title_frame = ctk.CTkFrame(self.content_frame)
title_frame.pack(fill="x", padx=20, pady=20)

title_label = ctk.CTkLabel(
title_frame,
text="Welcome to Quarix Quiz! 🎯",
font=("Arial", 32, "bold"),
text_color=("#00d4ff", "#ffffff")
)
title_label.pack(pady=20)

# Streak display
streak_frame = ctk.CTkFrame(title_frame)
streak_frame.pack(pady=10)

streak_label = ctk.CTkLabel(
streak_frame,
text=f"🔥 Current Streak: {self.get_user_streak()} days",
font=("Arial", 18, "bold"),
text_color=("#ff6b35", "#ff8c42")
)
streak_label.pack(padx=20, pady=10)
# Main action buttons
actions_frame = ctk.CTkFrame(self.content_frame)
actions_frame.pack(fill="both", expand=True, padx=20, pady=20)

# Start Quiz Button


quiz_btn = ctk.CTkButton(
actions_frame,
text="🚀 Start Quiz",
command=self.start_quiz_setup,
width=300,
height=80,
font=("Arial", 24, "bold"),
corner_radius=40,
fg_color=("#00d4ff", "#0099cc"),
hover_color=("#0099cc", "#007399")
)
quiz_btn.pack(pady=30)

# Read Topic Button


topic_btn = ctk.CTkButton(
actions_frame,
text="📚 Read a Topic",
command=self.show_topics,
width=300,
height=80,
font=("Arial", 24, "bold"),
corner_radius=40,
fg_color=("#4ecdc4", "#45b7aa"),
hover_color=("#45b7aa", "#3da58a")
)
topic_btn.pack(pady=20)

# Chat with Quarix Button


chat_btn = ctk.CTkButton(
actions_frame,
text="💬 Chat with Quarix",
command=self.show_chat,
width=300,
height=80,
font=("Arial", 24, "bold"),
corner_radius=40,
fg_color=("#ff6b6b", "#e55555"),
hover_color=("#e55555", "#cc4444")
)
chat_btn.pack(pady=20)

def start_quiz_setup(self):
self.clear_content()
# Quiz setup title
title_label = ctk.CTkLabel(
self.content_frame,
text="📝 Quiz Setup",
font=("Arial", 28, "bold"),
text_color=("#00d4ff", "#ffffff")
)
title_label.pack(pady=30)

# Setup frame
setup_frame = ctk.CTkFrame(self.content_frame)
setup_frame.pack(fill="both", expand=True, padx=50, pady=20)

# Education Level Selection


level_label = ctk.CTkLabel(setup_frame, text="Select Education
Level:", font=("Arial", 18, "bold"))
level_label.pack(pady=(30, 10))

self.level_var = ctk.StringVar(value="Primary")
level_menu = ctk.CTkOptionMenu(
setup_frame,
values=list(self.class_data.keys()),
variable=self.level_var,
command=self.update_class_options,
width=300,
height=40,
font=("Arial", 16)
)
level_menu.pack(pady=10)

# Class Selection
class_label = ctk.CTkLabel(setup_frame, text="Select Class:",
font=("Arial", 18, "bold"))
class_label.pack(pady=(20, 10))

self.class_var =
ctk.StringVar(value=self.class_data["Primary"][0])
self.class_menu = ctk.CTkOptionMenu(
setup_frame,
values=self.class_data["Primary"],
variable=self.class_var,
width=300,
height=40,
font=("Arial", 16)
)
self.class_menu.pack(pady=10)

# Subject Selection
subject_label = ctk.CTkLabel(setup_frame, text="Select
Subject:", font=("Arial", 18, "bold"))
subject_label.pack(pady=(20, 10))

self.subject_var = ctk.StringVar(value=self.subjects[0])
subject_menu = ctk.CTkOptionMenu(
setup_frame,
values=self.subjects,
variable=self.subject_var,
width=300,
height=40,
font=("Arial", 16)
)
subject_menu.pack(pady=10)

# Topic Selection
topic_label = ctk.CTkLabel(setup_frame, text="Specific Topic
(or leave as Random):", font=("Arial", 18, "bold"))
topic_label.pack(pady=(20, 10))

self.topic_var = ctk.StringVar(value="Random")
topic_entry = ctk.CTkEntry(
setup_frame,
textvariable=self.topic_var,
width=300,
height=40,
font=("Arial", 16)
)
topic_entry.pack(pady=10)

# Number of Questions
questions_label = ctk.CTkLabel(setup_frame, text="Number of
Questions:", font=("Arial", 18, "bold"))
questions_label.pack(pady=(20, 10))

self.questions_var = ctk.StringVar(value="10")
questions_menu = ctk.CTkOptionMenu(
setup_frame,
values=["5", "10", "15", "20", "25", "30"],
variable=self.questions_var,
width=300,
height=40,
font=("Arial", 16)
)
questions_menu.pack(pady=10)

# Start Quiz Button


start_btn = ctk.CTkButton(
setup_frame,
text="🎯 Generate Quiz",
command=self.generate_quiz,
width=300,
height=60,
font=("Arial", 20, "bold"),
corner_radius=30,
fg_color=("#00d4ff", "#0099cc")
)
start_btn.pack(pady=40)

# Back Button
back_btn = ctk.CTkButton(
setup_frame,
text="← Back to Home",
command=self.show_home_screen,
width=200,
height=40,
font=("Arial", 16),
fg_color=("#666666", "#555555")
)
back_btn.pack(pady=10)

def update_class_options(self, selected_level):


classes = self.class_data[selected_level]
self.class_menu.configure(values=classes)
self.class_var.set(classes[0])

def generate_quiz(self):
# Show loading screen
self.show_loading_screen()

# Generate questions in a separate thread


def generate_questions_thread():
try:
class_level = self.class_var.get()
subject = self.subject_var.get()
topic = self.topic_var.get()
num_questions = int(self.questions_var.get())

self.current_questions =
self.question_generator.generate_questions(
class_level, subject, topic, num_questions
)

self.current_question_index = 0
self.quiz_score = 0
self.quiz_answers = []

# Switch to quiz screen on main thread


self.root.after(0, self.start_quiz)

except Exception as e:
self.root.after(0, lambda:
messagebox.showerror("Error", f"Failed to generate quiz: {str(e)}"))
self.root.after(0, self.show_home_screen)

threading.Thread(target=generate_questions_thread,
daemon=True).start()

def show_loading_screen(self):
self.clear_content()

loading_frame = ctk.CTkFrame(self.content_frame)
loading_frame.pack(fill="both", expand=True)

loading_label = ctk.CTkLabel(
loading_frame,
text="🤖 Generating your quiz...",
font=("Arial", 24, "bold")
)
loading_label.pack(expand=True)

# Add a progress bar


self.progress_bar = ctk.CTkProgressBar(loading_frame,
width=400)
self.progress_bar.pack(pady=20)
self.progress_bar.set(0)

# Animate progress bar


self.animate_progress()

def animate_progress(self):
current_value = self.progress_bar.get()
if current_value < 1.0:
self.progress_bar.set(current_value + 0.1)
self.root.after(200, self.animate_progress)

def start_quiz(self):
if not self.current_questions:
messagebox.showerror("Error", "No questions available!")
self.show_home_screen()
return

self.show_question()

def show_question(self):
if self.current_question_index >= len(self.current_questions):
self.show_quiz_results()
return

self.clear_content()

question = self.current_questions[self.current_question_index]
# Question header
header_frame = ctk.CTkFrame(self.content_frame)
header_frame.pack(fill="x", padx=20, pady=20)

progress_text = f"Question {self.current_question_index + 1}


of {len(self.current_questions)}"
progress_label = ctk.CTkLabel(
header_frame,
text=progress_text,
font=("Arial", 16, "bold")
)
progress_label.pack(pady=10)

# Progress bar
progress = (self.current_question_index + 1) /
len(self.current_questions)
progress_bar = ctk.CTkProgressBar(header_frame, width=400)
progress_bar.pack(pady=10)
progress_bar.set(progress)

# Question frame
question_frame = ctk.CTkFrame(self.content_frame)
question_frame.pack(fill="both", expand=True, padx=20,
pady=20)

# Question text
question_label = ctk.CTkLabel(
question_frame,
text=question.question,
font=("Arial", 20, "bold"),
wraplength=800,
justify="left"
)
question_label.pack(pady=30, padx=30)

# Answer options
self.selected_answer = ctk.IntVar(value=-1)

options_frame = ctk.CTkFrame(question_frame)
options_frame.pack(fill="both", expand=True, padx=30, pady=20)

for i, option in enumerate(question.options):


option_btn = ctk.CTkRadioButton(
options_frame,
text=f"{chr(65+i)}) {option}",
variable=self.selected_answer,
value=i,
font=("Arial", 16),
radiobutton_width=20,
radiobutton_height=20
)
option_btn.pack(pady=15, padx=20, anchor="w")

# Submit button
submit_btn = ctk.CTkButton(
question_frame,
text="Submit Answer",
command=self.submit_answer,
width=200,
height=50,
font=("Arial", 18, "bold"),
corner_radius=25
)
submit_btn.pack(pady=30)

def submit_answer(self):
if self.selected_answer.get() == -1:
messagebox.showwarning("Warning", "Please select an
answer!")
return

question = self.current_questions[self.current_question_index]
selected = self.selected_answer.get()
is_correct = selected == question.correct_answer

# Store answer
self.quiz_answers.append({
'question': question.question,
'selected': selected,
'correct': question.correct_answer,
'is_correct': is_correct,
'explanation': question.explanation
})

if is_correct:
self.quiz_score += 1
self.sound_manager.play_sound('correct')
else:
self.sound_manager.play_sound('wrong')

# Show answer feedback


self.show_answer_feedback(is_correct, question)

def show_answer_feedback(self, is_correct, question):


self.clear_content()

feedback_frame = ctk.CTkFrame(self.content_frame)
feedback_frame.pack(fill="both", expand=True, padx=20,
pady=20)
# Feedback icon and text
if is_correct:
feedback_text = "✅ Correct!"
feedback_color = "#4CAF50"
else:
feedback_text = "❌ Incorrect!"
feedback_color = "#F44336"

feedback_label = ctk.CTkLabel(
feedback_frame,
text=feedback_text,
font=("Arial", 32, "bold"),
text_color=feedback_color
)
feedback_label.pack(pady=30)

# Show correct answer


correct_answer_text = f"Correct Answer: {chr(65 +
question.correct_answer)})
{question.options[question.correct_answer]}"
correct_label = ctk.CTkLabel(
feedback_frame,
text=correct_answer_text,
font=("Arial", 18, "bold"),
wraplength=800
)
correct_label.pack(pady=20, padx=30)

# Show explanation
if question.explanation:
explanation_label = ctk.CTkLabel(
feedback_frame,
text=f"Explanation: {question.explanation}",
font=("Arial", 16),
wraplength=800,
justify="left"
)
explanation_label.pack(pady=20, padx=30)

# Next button
next_btn = ctk.CTkButton(
feedback_frame,
text="Next Question →",
command=self.next_question,
width=200,
height=50,
font=("Arial", 18, "bold")
)
next_btn.pack(pady=30)
# Auto-advance after 3 seconds
self.root.after(3000, self.next_question)

def next_question(self):
self.current_question_index += 1
self.show_question()

def show_quiz_results(self):
self.clear_content()

# Play celebration sound


self.sound_manager.play_sound('celebration')

# Calculate results
total_questions = len(self.current_questions)
correct_answers = self.quiz_score
percentage = (correct_answers / total_questions) * 100

# Save quiz to database


self.save_quiz_results(percentage, total_questions,
correct_answers)

# Results frame
results_frame = ctk.CTkFrame(self.content_frame)
results_frame.pack(fill="both", expand=True, padx=20, pady=20)

# Celebration header
celebration_label = ctk.CTkLabel(
results_frame,
text="🎉 Quiz Complete! 🎉",
font=("Arial", 36, "bold"),
text_color=("#FFD700", "#FFA500")
)
celebration_label.pack(pady=30)

# Score display
score_frame = ctk.CTkFrame(results_frame)
score_frame.pack(pady=30, padx=50, fill="x")

# Percentage score
percentage_label = ctk.CTkLabel(
score_frame,
text=f"{percentage:.1f}%",
font=("Arial", 72, "bold"),
text_color=self.get_score_color(percentage)
)
percentage_label.pack(pady=20)

# Detailed results
details_text = f"Correct: {correct_answers} | Wrong:
{total_questions - correct_answers} | Total: {total_questions}"
details_label = ctk.CTkLabel(
score_frame,
text=details_text,
font=("Arial", 20, "bold")
)
details_label.pack(pady=10)

# Performance message
performance_msg = self.get_performance_message(percentage)
performance_label = ctk.CTkLabel(

You might also like