import gradio as gr import pandas as pd import os import cv2 import mediapipe as mp from datetime import datetime, timedelta import random import firebase_admin from firebase_admin import credentials, firestore # Firebase Initialization if not firebase_admin._apps: try: cred = credentials.Certificate("active-kids-hub-firebase-adminsdk-n54dr-c3507e5704.json") # Replace with your Firebase credentials JSON file firebase_admin.initialize_app(cred) db = firestore.client() print("Firebase initialized successfully!") except Exception as e: print(f"Error initializing Firebase: {e}") raise e # Reraise to stop further execution if Firebase setup fails # MediaPipe Pose Detection Setup mp_pose = mp.solutions.pose pose = mp_pose.Pose(static_image_mode=False, model_complexity=1, enable_segmentation=True) mp_drawing = mp.solutions.drawing_utils def analyze_pose(proof_file, task): """Analyze uploaded image/video to detect pose and validate the task.""" try: if proof_file.name.endswith(('.jpg', '.jpeg', '.png')): # Image proof image = cv2.imread(proof_file.name) if image is None: return "Invalid image file. Please retry." image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) results = pose.process(image_rgb) if results.pose_landmarks: return f"Pose detected successfully for '{task}'! Proof is valid." else: return f"No pose detected in the uploaded image for '{task}'. Please retry." elif proof_file.name.endswith(('.mp4', '.avi', '.mov')): # Video proof cap = cv2.VideoCapture(proof_file.name) pose_detected = False while cap.isOpened(): ret, frame = cap.read() if not ret: break image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results = pose.process(image_rgb) if results.pose_landmarks: pose_detected = True break cap.release() return ( f"Pose detected successfully in video for '{task}'! Proof is valid." if pose_detected else f"No pose detected in video for '{task}'. Please retry." ) else: return "Invalid file format. Please upload an image or video." except Exception as e: print(f"Error in analyze_pose: {e}") return f"Error analyzing the file: {e}" def submit_proof(username, task, proof): """Submit proof of task completion and validate using pose analysis.""" try: if not proof: return "Please upload a valid proof file (Image/Video)." # Validate if the task exists for the username in Firebase user_doc = db.collection("users").document(username.lower()).get() if not user_doc.exists: return f"User '{username}' not found. Please check the username." user_data = user_doc.to_dict() user_tasks = user_data.get("tasks", []) task_names = [t["task"] for t in user_tasks] if task not in task_names: return f"Task '{task}' not found for the user '{username}'. Please check the task name." # Check if proof has already been uploaded for the task for t in user_tasks: if t["task"] == task and t.get("proof_uploaded"): return f"Proof already uploaded for task '{task}'. Please upload a new proof if necessary." # Analyze the proof file analysis_result = analyze_pose(proof, task) if "successfully" not in analysis_result: return analysis_result # Log proof submission in Firebase (without assigning reward) try: timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") # Update the task status to 'completed' but do not assign a reward here for t in user_tasks: if t["task"] == task: t["status"] = "completed" t["timestamp"] = timestamp t["proof_uploaded"] = True # Mark that proof has been uploaded # Save updated task status in Firebase db.collection("users").document(username.lower()).set({"tasks": user_tasks}, merge=True) print(f"Proof for task '{task}' submitted successfully for {username}!") return f"Task '{task}' completed successfully! Please assign a reward in the 'Progress and Rewards Tracker' tab." except Exception as e: print(f"Error logging proof submission in Firebase: {e}") return f"Error submitting proof to Firebase: {e}" except Exception as e: print(f"Error submitting proof: {e}") return f"Error: {e}" def generate_fitness_tasks(username, age, fitness_level): """Generate a single fitness task based on user's age and fitness level.""" try: age = int(age) # Convert age to integer if not (7 <= age <= 14): return "Age must be between 7 and 14.", "" # Early return on invalid age if fitness_level not in ["beginner", "intermediate", "advanced"]: return "Please select a valid fitness level.", "" # Early return on invalid fitness level # Task definitions based on age and fitness level tasks = { (7, 10): { "beginner": {"task": "Jumping Jacks", "details": "10 reps"}, "intermediate": {"task": "Push-ups", "details": "10 reps"}, "advanced": {"task": "Squats", "details": "10 reps"}, }, (11, 12): { "beginner": {"task": "Jumping Jacks", "details": "15 reps"}, "intermediate": {"task": "Push-ups", "details": "15 reps"}, "advanced": {"task": "Squats", "details": "15 reps"}, }, (13, 14): { "beginner": {"task": "Jumping Jacks", "details": "20 reps"}, "intermediate": {"task": "Push-ups", "details": "20 reps"}, "advanced": {"task": "Squats", "details": "20 reps"}, } } # Determine the task set based on age and fitness level for age_range, level_tasks in tasks.items(): if age_range[0] <= age <= age_range[1]: selected_task = level_tasks[fitness_level] break else: return "Invalid age range. Tasks not available.", "" # Save the task in Firebase for the user user_doc = db.collection("users").document(username.lower()).get() if not user_doc.exists: return f"User '{username}' not found. Please sign up first.", "" task_list = [{"task": selected_task["task"], "details": selected_task["details"], "status": "pending", "proof_uploaded": False}] db.collection("users").document(username.lower()).set({"tasks": task_list}, merge=True) # Return task and a message task_display = f"{selected_task['task']} - {selected_task['details']}" return f"Task generated successfully for {username}.", task_display except Exception as e: print(f"Error in generate_fitness_tasks: {e}") return f"Error generating tasks: {e}", "" def view_activity_log(username): """Retrieve and display user's activity log from Firebase.""" try: # Fetch user data from Firebase user_doc = db.collection("users").document(username.lower()).get() if not user_doc.exists: return f"User '{username}' not found." user_data = user_doc.to_dict() user_tasks = user_data.get("tasks", []) # Convert task data into a pandas DataFrame for display tasks_data = [ { "Task": task["task"], "Details": task["details"], "Status": task["status"], "Timestamp": task.get("timestamp", "Not available"), "Proof Uploaded": task.get("proof_uploaded", False), "Reward": task.get("reward", "Not assigned") } for task in user_tasks ] df = pd.DataFrame(tasks_data) return df except Exception as e: print(f"Error fetching activity log: {e}") return f"Error fetching activity log: {e}" def assign_reward(username, task, reward): """Assign reward to a task for a specific user.""" try: # Fetch user data from Firebase user_doc = db.collection("users").document(username.lower()).get() if not user_doc.exists: return f"User '{username}' not found." user_data = user_doc.to_dict() user_tasks = user_data.get("tasks", []) # Check if the task exists and is completed for t in user_tasks: if t["task"] == task and t.get("status") == "completed": t["reward"] = reward # Assign the reward db.collection("users").document(username.lower()).set({"tasks": user_tasks}, merge=True) return f"Reward '{reward}' assigned to task '{task}' for user '{username}'." return f"Task '{task}' not completed or not found for user '{username}'." except Exception as e: print(f"Error assigning reward: {e}") return f"Error assigning reward: {e}" def create_app(): with gr.Blocks() as app: gr.Markdown("## Fitness Challenge App with Firebase Integration") # Sign Up / Login with gr.Tab("Sign Up / Login"): username_input = gr.Textbox(label="Enter Username") password_input = gr.Textbox(label="Enter Password", type="password") # Password field sign_up_login_btn = gr.Button("Sign Up / Login") sign_up_login_status = gr.Textbox(label="Status") def handle_sign_up_login(username, password): try: user_doc = db.collection("users").document(username.lower()).get() if user_doc.exists: stored_password = user_doc.get("password") if stored_password == password: return f"Welcome back, {username}!", None # If password matches, login success else: return "Incorrect password. Please try again.", None else: # If user does not exist, sign up db.collection("users").document(username.lower()).set({"username": username.lower(), "password": password}, merge=True) return f"Sign-up successful! Welcome, {username}!", None except Exception as e: return f"Error: {e}", None sign_up_login_btn.click(handle_sign_up_login, [username_input, password_input], sign_up_login_status) # Generate Tasks with gr.Tab("Generate Tasks"): username_gen = gr.Textbox(label="Enter Username") age = gr.Textbox(label="Enter Age (7-14)", placeholder="E.g., 10") fitness_level = gr.Radio(["beginner", "intermediate", "advanced"], label="Fitness Level") generate_btn = gr.Button("Generate Tasks") task_output = gr.Textbox(label="Task Status") task_display = gr.Textbox(label="Generated Task", interactive=False) generate_btn.click(generate_fitness_tasks, [username_gen, age, fitness_level], [task_output, task_display]) # Submit Proof with gr.Tab("Submit Proof"): username_proof = gr.Textbox(label="Enter Username") task_name = gr.Textbox(label="Enter Task Name") proof_upload = gr.File(label="Upload Proof (Image/Video)") submit_btn = gr.Button("Submit Proof") submission_status = gr.Textbox(label="Submission Status") submit_btn.click(submit_proof, [username_proof, task_name, proof_upload], submission_status) # Progress and Rewards Tracker with gr.Tab("Progress and Rewards Tracker"): username_log = gr.Textbox(label="Enter Username") log_output = gr.DataFrame(label="Progress and Rewards") log_btn = gr.Button("View Tracker") reward_selector = gr.Radio(["Toy", "Little Buck", "Chocolate"], label="Select Reward") task_to_reward = gr.Textbox(label="Task Name to Assign Reward") assign_btn = gr.Button("Assign Reward") reward_status = gr.Textbox(label="Reward Assignment Status") log_btn.click(view_activity_log, [username_log], log_output) assign_btn.click(assign_reward, [username_log, task_to_reward, reward_selector], reward_status) return app app = create_app() app.launch()