Grow-Kids / app.py
sabahat-shakeel's picture
Create app.py
50480c6 verified
raw
history blame
12.9 kB
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("growkids-f8bfe-firebase-adminsdk-koo88-8a3a33da6d") # 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()