Spaces:
Sleeping
Sleeping
Commit
Β·
7917bda
1
Parent(s):
c2f0199
Fix: Handle empty dataframes and add validation for all inputs
Browse files- app.py +38 -9
- assignment_engine.py +40 -6
- task_manager.py +10 -2
app.py
CHANGED
|
@@ -154,12 +154,24 @@ def add_task(task_type, complexity, deadline):
|
|
| 154 |
def update_progress(task_id, user_id, progress, notes):
|
| 155 |
"""Update task progress"""
|
| 156 |
try:
|
| 157 |
-
if task_id
|
| 158 |
-
return "β Please enter valid Task ID
|
|
|
|
|
|
|
| 159 |
if not (0 <= progress <= 100):
|
| 160 |
return "β Progress must be between 0 and 100"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 161 |
|
| 162 |
-
tm.update_progress(int(task_id), int(user_id), int(progress), notes.strip())
|
| 163 |
return f"β
Progress updated: Task {int(task_id)} β {int(progress)}%"
|
| 164 |
|
| 165 |
except Exception as e:
|
|
@@ -168,23 +180,40 @@ def update_progress(task_id, user_id, progress, notes):
|
|
| 168 |
def complete_task(task_id, user_id, time_taken, quality):
|
| 169 |
"""Complete a task - THIS IS HOW AI LEARNS"""
|
| 170 |
try:
|
| 171 |
-
if task_id
|
| 172 |
-
return "β Please enter valid Task ID
|
|
|
|
|
|
|
| 173 |
if not (1 <= quality <= 5):
|
| 174 |
return "β Quality must be between 1 and 5"
|
| 175 |
-
if time_taken <= 0:
|
| 176 |
return "β Time taken must be positive"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
|
| 178 |
tm.enter_result(int(task_id), int(user_id), float(time_taken), int(quality))
|
| 179 |
|
| 180 |
-
|
|
|
|
|
|
|
|
|
|
| 181 |
|
| 182 |
-
**
|
|
|
|
|
|
|
| 183 |
- Time taken: {time_taken}h
|
| 184 |
- Quality: {int(quality)}/5
|
| 185 |
|
| 186 |
π§ **AI is learning from this result!**
|
| 187 |
-
Retrain the AI in the 'AI
|
| 188 |
|
| 189 |
except Exception as e:
|
| 190 |
return f"Error: {str(e)}"
|
|
|
|
| 154 |
def update_progress(task_id, user_id, progress, notes):
|
| 155 |
"""Update task progress"""
|
| 156 |
try:
|
| 157 |
+
if task_id is None or task_id <= 0:
|
| 158 |
+
return "β Please enter a valid Task ID"
|
| 159 |
+
if user_id is None or user_id <= 0:
|
| 160 |
+
return "β Please enter a valid User ID"
|
| 161 |
if not (0 <= progress <= 100):
|
| 162 |
return "β Progress must be between 0 and 100"
|
| 163 |
+
|
| 164 |
+
# Validate task exists
|
| 165 |
+
task_df = tm.engine.tasks[tm.engine.tasks['task_id'] == int(task_id)]
|
| 166 |
+
if len(task_df) == 0:
|
| 167 |
+
return f"β Task ID {int(task_id)} not found!"
|
| 168 |
+
|
| 169 |
+
# Validate user exists
|
| 170 |
+
user_df = tm.engine.users[tm.engine.users['user_id'] == int(user_id)]
|
| 171 |
+
if len(user_df) == 0:
|
| 172 |
+
return f"β User ID {int(user_id)} not found!"
|
| 173 |
|
| 174 |
+
tm.update_progress(int(task_id), int(user_id), int(progress), notes.strip() if notes else "")
|
| 175 |
return f"β
Progress updated: Task {int(task_id)} β {int(progress)}%"
|
| 176 |
|
| 177 |
except Exception as e:
|
|
|
|
| 180 |
def complete_task(task_id, user_id, time_taken, quality):
|
| 181 |
"""Complete a task - THIS IS HOW AI LEARNS"""
|
| 182 |
try:
|
| 183 |
+
if task_id is None or task_id <= 0:
|
| 184 |
+
return "β Please enter a valid Task ID"
|
| 185 |
+
if user_id is None or user_id <= 0:
|
| 186 |
+
return "β Please enter a valid User ID"
|
| 187 |
if not (1 <= quality <= 5):
|
| 188 |
return "β Quality must be between 1 and 5"
|
| 189 |
+
if time_taken is None or time_taken <= 0:
|
| 190 |
return "β Time taken must be positive"
|
| 191 |
+
|
| 192 |
+
# Validate task exists
|
| 193 |
+
task_df = tm.engine.tasks[tm.engine.tasks['task_id'] == int(task_id)]
|
| 194 |
+
if len(task_df) == 0:
|
| 195 |
+
return f"β Task ID {int(task_id)} not found! Check the Dashboard for valid Task IDs."
|
| 196 |
+
|
| 197 |
+
# Validate user exists
|
| 198 |
+
user_df = tm.engine.users[tm.engine.users['user_id'] == int(user_id)]
|
| 199 |
+
if len(user_df) == 0:
|
| 200 |
+
return f"β User ID {int(user_id)} not found! Check the Dashboard for valid User IDs."
|
| 201 |
|
| 202 |
tm.enter_result(int(task_id), int(user_id), float(time_taken), int(quality))
|
| 203 |
|
| 204 |
+
task_name = task_df['type'].iloc[0]
|
| 205 |
+
user_name = user_df['name'].iloc[0]
|
| 206 |
+
|
| 207 |
+
return f"""β
Task completed successfully!
|
| 208 |
|
| 209 |
+
**Details:**
|
| 210 |
+
- Task: {task_name} (ID: {int(task_id)})
|
| 211 |
+
- Completed by: {user_name} (ID: {int(user_id)})
|
| 212 |
- Time taken: {time_taken}h
|
| 213 |
- Quality: {int(quality)}/5
|
| 214 |
|
| 215 |
π§ **AI is learning from this result!**
|
| 216 |
+
Retrain the AI in the 'Train AI' tab to improve future assignments."""
|
| 217 |
|
| 218 |
except Exception as e:
|
| 219 |
return f"Error: {str(e)}"
|
assignment_engine.py
CHANGED
|
@@ -41,9 +41,17 @@ class TaskAssignmentEngine:
|
|
| 41 |
if len(self.results) == 0:
|
| 42 |
print("β οΈ No results data - will use random assignment")
|
| 43 |
return None, None
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
# Merge results with task and user data
|
| 46 |
-
training_data = self.results.merge(self.tasks, on='task_id').merge(self.users, on='user_id')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
|
| 48 |
# Create features: user_id, complexity, deadline
|
| 49 |
X = training_data[['user_id', 'complexity', 'deadline']].values
|
|
@@ -59,7 +67,7 @@ class TaskAssignmentEngine:
|
|
| 59 |
y = (quality_score * 0.7 + efficiency * 0.3) # 70% quality, 30% efficiency
|
| 60 |
|
| 61 |
print(f"β
Prepared training data: {len(X)} samples")
|
| 62 |
-
return X, y
|
| 63 |
|
| 64 |
def train_model(self):
|
| 65 |
"""Train the AI model"""
|
|
@@ -97,7 +105,18 @@ class TaskAssignmentEngine:
|
|
| 97 |
|
| 98 |
def assign_task(self, task_id):
|
| 99 |
"""Assign a task to the best user"""
|
| 100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
|
| 102 |
best_user = None
|
| 103 |
best_score = -1
|
|
@@ -143,7 +162,11 @@ class TaskAssignmentEngine:
|
|
| 143 |
def start_task_tracking(self, task_id, user_id, user_name):
|
| 144 |
"""Start tracking a task"""
|
| 145 |
task_key = f"{task_id}_{user_id}"
|
| 146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
|
| 148 |
self.progress_data[task_key] = {
|
| 149 |
'task_id': task_id,
|
|
@@ -187,6 +210,17 @@ class TaskAssignmentEngine:
|
|
| 187 |
|
| 188 |
def add_result(self, task_id, user_id, time_taken, quality):
|
| 189 |
"""Add task completion result"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 190 |
# Update progress tracking with completion
|
| 191 |
task_key = f"{task_id}_{user_id}"
|
| 192 |
completion_time = datetime.now()
|
|
@@ -217,8 +251,8 @@ class TaskAssignmentEngine:
|
|
| 217 |
self.results.to_csv(self.results_file, index=False)
|
| 218 |
|
| 219 |
# Get names for display
|
| 220 |
-
task_name =
|
| 221 |
-
user_name =
|
| 222 |
|
| 223 |
print(f"β
Task Completed: {user_name} β {task_name} in {time_taken}h with quality {quality}/5")
|
| 224 |
|
|
|
|
| 41 |
if len(self.results) == 0:
|
| 42 |
print("β οΈ No results data - will use random assignment")
|
| 43 |
return None, None
|
| 44 |
+
|
| 45 |
+
if len(self.tasks) == 0 or len(self.users) == 0:
|
| 46 |
+
print("β οΈ No tasks or users - cannot prepare training data")
|
| 47 |
+
return None, None
|
| 48 |
|
| 49 |
# Merge results with task and user data
|
| 50 |
+
training_data = self.results.merge(self.tasks, on='task_id', how='inner').merge(self.users, on='user_id', how='inner')
|
| 51 |
+
|
| 52 |
+
if len(training_data) == 0:
|
| 53 |
+
print("β οΈ No valid training data after merge")
|
| 54 |
+
return None, None
|
| 55 |
|
| 56 |
# Create features: user_id, complexity, deadline
|
| 57 |
X = training_data[['user_id', 'complexity', 'deadline']].values
|
|
|
|
| 67 |
y = (quality_score * 0.7 + efficiency * 0.3) # 70% quality, 30% efficiency
|
| 68 |
|
| 69 |
print(f"β
Prepared training data: {len(X)} samples")
|
| 70 |
+
return X, y.values
|
| 71 |
|
| 72 |
def train_model(self):
|
| 73 |
"""Train the AI model"""
|
|
|
|
| 105 |
|
| 106 |
def assign_task(self, task_id):
|
| 107 |
"""Assign a task to the best user"""
|
| 108 |
+
# Check if users exist
|
| 109 |
+
if len(self.users) == 0:
|
| 110 |
+
print("β No users available")
|
| 111 |
+
return None, None
|
| 112 |
+
|
| 113 |
+
# Check if task exists
|
| 114 |
+
task_df = self.tasks[self.tasks['task_id'] == task_id]
|
| 115 |
+
if len(task_df) == 0:
|
| 116 |
+
print(f"β Task {task_id} not found")
|
| 117 |
+
return None, None
|
| 118 |
+
|
| 119 |
+
task_row = task_df.iloc[0]
|
| 120 |
|
| 121 |
best_user = None
|
| 122 |
best_score = -1
|
|
|
|
| 162 |
def start_task_tracking(self, task_id, user_id, user_name):
|
| 163 |
"""Start tracking a task"""
|
| 164 |
task_key = f"{task_id}_{user_id}"
|
| 165 |
+
task_df = self.tasks[self.tasks['task_id'] == task_id]
|
| 166 |
+
if len(task_df) == 0:
|
| 167 |
+
print(f"β Task {task_id} not found for tracking")
|
| 168 |
+
return
|
| 169 |
+
task_info = task_df.iloc[0]
|
| 170 |
|
| 171 |
self.progress_data[task_key] = {
|
| 172 |
'task_id': task_id,
|
|
|
|
| 210 |
|
| 211 |
def add_result(self, task_id, user_id, time_taken, quality):
|
| 212 |
"""Add task completion result"""
|
| 213 |
+
# Validate task and user exist
|
| 214 |
+
task_df = self.tasks[self.tasks['task_id'] == task_id]
|
| 215 |
+
user_df = self.users[self.users['user_id'] == user_id]
|
| 216 |
+
|
| 217 |
+
if len(task_df) == 0:
|
| 218 |
+
print(f"β Task {task_id} not found")
|
| 219 |
+
return False
|
| 220 |
+
if len(user_df) == 0:
|
| 221 |
+
print(f"β User {user_id} not found")
|
| 222 |
+
return False
|
| 223 |
+
|
| 224 |
# Update progress tracking with completion
|
| 225 |
task_key = f"{task_id}_{user_id}"
|
| 226 |
completion_time = datetime.now()
|
|
|
|
| 251 |
self.results.to_csv(self.results_file, index=False)
|
| 252 |
|
| 253 |
# Get names for display
|
| 254 |
+
task_name = task_df['type'].iloc[0]
|
| 255 |
+
user_name = user_df['name'].iloc[0]
|
| 256 |
|
| 257 |
print(f"β
Task Completed: {user_name} β {task_name} in {time_taken}h with quality {quality}/5")
|
| 258 |
|
task_manager.py
CHANGED
|
@@ -54,15 +54,22 @@ class TaskManager:
|
|
| 54 |
|
| 55 |
def add_user(self, name):
|
| 56 |
"""Add new user"""
|
| 57 |
-
|
|
|
|
|
|
|
|
|
|
| 58 |
new_user = pd.DataFrame({'user_id': [new_id], 'name': [name]})
|
| 59 |
self.engine.users = pd.concat([self.engine.users, new_user], ignore_index=True)
|
| 60 |
self.engine.users.to_csv("users.csv", index=False)
|
| 61 |
print(f"β
Added user: {name} (ID: {new_id})")
|
|
|
|
| 62 |
|
| 63 |
def add_task(self, task_type, complexity, deadline):
|
| 64 |
"""Add new task"""
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
| 66 |
new_task = pd.DataFrame({
|
| 67 |
'task_id': [new_id],
|
| 68 |
'type': [task_type],
|
|
@@ -72,6 +79,7 @@ class TaskManager:
|
|
| 72 |
self.engine.tasks = pd.concat([self.engine.tasks, new_task], ignore_index=True)
|
| 73 |
self.engine.tasks.to_csv("tasks.csv", index=False)
|
| 74 |
print(f"β
Added task: {task_type} (ID: {new_id}, Complexity: {complexity}, Deadline: {deadline}h)")
|
|
|
|
| 75 |
|
| 76 |
if __name__ == "__main__":
|
| 77 |
# Example usage
|
|
|
|
| 54 |
|
| 55 |
def add_user(self, name):
|
| 56 |
"""Add new user"""
|
| 57 |
+
if len(self.engine.users) == 0:
|
| 58 |
+
new_id = 1
|
| 59 |
+
else:
|
| 60 |
+
new_id = int(self.engine.users['user_id'].max()) + 1
|
| 61 |
new_user = pd.DataFrame({'user_id': [new_id], 'name': [name]})
|
| 62 |
self.engine.users = pd.concat([self.engine.users, new_user], ignore_index=True)
|
| 63 |
self.engine.users.to_csv("users.csv", index=False)
|
| 64 |
print(f"β
Added user: {name} (ID: {new_id})")
|
| 65 |
+
return new_id
|
| 66 |
|
| 67 |
def add_task(self, task_type, complexity, deadline):
|
| 68 |
"""Add new task"""
|
| 69 |
+
if len(self.engine.tasks) == 0:
|
| 70 |
+
new_id = 1
|
| 71 |
+
else:
|
| 72 |
+
new_id = int(self.engine.tasks['task_id'].max()) + 1
|
| 73 |
new_task = pd.DataFrame({
|
| 74 |
'task_id': [new_id],
|
| 75 |
'type': [task_type],
|
|
|
|
| 79 |
self.engine.tasks = pd.concat([self.engine.tasks, new_task], ignore_index=True)
|
| 80 |
self.engine.tasks.to_csv("tasks.csv", index=False)
|
| 81 |
print(f"β
Added task: {task_type} (ID: {new_id}, Complexity: {complexity}, Deadline: {deadline}h)")
|
| 82 |
+
return new_id
|
| 83 |
|
| 84 |
if __name__ == "__main__":
|
| 85 |
# Example usage
|