File size: 12,860 Bytes
50480c6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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()