File size: 18,063 Bytes
a7d2fe5
 
 
 
 
53650b0
4da4b6c
53650b0
a7d2fe5
 
 
 
 
 
 
 
4da4b6c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a7d2fe5
4da4b6c
a7d2fe5
4da4b6c
a7d2fe5
 
 
 
4da4b6c
a7d2fe5
 
 
 
 
 
4da4b6c
a7d2fe5
4da4b6c
 
a7d2fe5
 
 
 
 
 
4da4b6c
a7d2fe5
 
4da4b6c
 
 
 
 
a7d2fe5
 
4da4b6c
 
 
a7d2fe5
 
 
 
 
 
 
4da4b6c
a7d2fe5
4da4b6c
 
 
 
 
 
a7d2fe5
 
 
 
 
 
 
 
 
4da4b6c
 
 
 
 
 
 
 
 
a7d2fe5
 
 
4da4b6c
 
a7d2fe5
 
4da4b6c
a7d2fe5
 
 
 
 
 
 
 
 
 
 
 
 
4da4b6c
 
 
 
a7d2fe5
 
 
 
d694796
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a7d2fe5
 
 
 
 
 
 
 
 
 
 
4da4b6c
 
 
 
a7d2fe5
 
 
 
61ac5f8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a7d2fe5
 
 
7917bda
 
 
 
a7d2fe5
 
7917bda
 
 
 
 
 
 
 
 
 
a7d2fe5
7917bda
4da4b6c
a7d2fe5
 
 
 
 
4da4b6c
a7d2fe5
7917bda
 
 
 
a7d2fe5
 
7917bda
a7d2fe5
7917bda
 
 
 
 
 
 
 
 
 
a7d2fe5
 
4da4b6c
7917bda
 
 
 
4da4b6c
7917bda
 
 
4da4b6c
 
 
 
7917bda
a7d2fe5
 
 
 
 
 
 
4da4b6c
 
 
a7d2fe5
4da4b6c
 
 
 
 
 
 
 
 
 
 
a7d2fe5
 
 
 
 
 
 
 
 
4da4b6c
 
 
 
 
 
 
 
a7d2fe5
4da4b6c
a7d2fe5
 
 
 
 
4da4b6c
a7d2fe5
 
 
 
 
 
4da4b6c
 
 
a7d2fe5
 
 
 
d694796
 
 
 
 
 
 
 
 
 
a7d2fe5
 
4da4b6c
 
 
a7d2fe5
4da4b6c
 
a7d2fe5
 
 
 
61ac5f8
 
 
 
 
 
 
 
 
 
4da4b6c
 
 
 
 
 
 
 
 
 
 
a7d2fe5
 
 
4da4b6c
a7d2fe5
4da4b6c
 
 
 
a7d2fe5
 
 
 
 
 
4da4b6c
 
 
 
 
 
a7d2fe5
4da4b6c
 
a7d2fe5
 
 
 
 
4da4b6c
 
 
 
 
 
 
 
 
 
 
a7d2fe5
 
 
 
 
 
 
c2f0199
4da4b6c
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
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
import gradio as gr
import pandas as pd
from task_manager import TaskManager
import os

# AI Task Assignment System for Hugging Face Spaces
# All data is USER INPUT - AI only handles assignment optimization

# Initialize the task manager
tm = TaskManager()

def show_dashboard():
    """Display system dashboard"""
    try:
        stats = []
        
        # Show current users
        if len(tm.engine.users) > 0:
            stats.append("πŸ‘₯ **REGISTERED USERS**")
            for _, user in tm.engine.users.iterrows():
                stats.append(f"- ID {user['user_id']}: {user['name']}")
        else:
            stats.append("πŸ‘₯ **No users yet** - Add users in the 'Add User' tab")
        
        # Show current tasks
        stats.append("")
        if len(tm.engine.tasks) > 0:
            stats.append("πŸ“‹ **REGISTERED TASKS**")
            for _, task in tm.engine.tasks.iterrows():
                status = "βœ… Completed" if task['task_id'] in tm.engine.results['task_id'].values else "⏳ Pending"
                stats.append(f"- ID {task['task_id']}: {task['type']} (Complexity: {task['complexity']}, Deadline: {task['deadline']}h) [{status}]")
        else:
            stats.append("πŸ“‹ **No tasks yet** - Add tasks in the 'Add Task' tab")
        
        # Basic stats
        stats.append("")
        if len(tm.engine.results) > 0:
            stats.append("πŸ“Š **PERFORMANCE STATISTICS**")
            stats.append(f"- Total completed tasks: {len(tm.engine.results)}")
            stats.append(f"- Average quality: {tm.engine.results['quality'].mean():.2f}/5")
            stats.append(f"- Average time: {tm.engine.results['time_taken'].mean():.1f}h")
            
            # User performance
            user_stats = tm.engine.results.merge(tm.engine.users, on='user_id').groupby('name').agg({
                'quality': 'mean',
                'time_taken': 'mean',
                'task_id': 'count'
            }).round(2)
            
            stats.append("\nπŸ† **USER PERFORMANCE (AI Learning Data)**")
            for user, row in user_stats.iterrows():
                skill = "⭐Expert" if row['quality'] >= 4 else "✨Good" if row['quality'] >= 3 else "πŸ“šLearning"
                stats.append(f"- {user}: {row['quality']:.1f}/5 quality, {row['time_taken']:.1f}h avg, {int(row['task_id'])} tasks [{skill}]")
        
        # Active tasks
        if hasattr(tm.engine, 'progress_data') and tm.engine.progress_data:
            active_tasks = [task for task in tm.engine.progress_data.values() 
                           if task['status'] in ['assigned', 'in_progress']]
            if active_tasks:
                stats.append("\nπŸ”„ **ACTIVE TASKS**")
                for task in active_tasks:
                    status_icon = "πŸ”„" if task['status'] == 'in_progress' else "πŸ“‹"
                    progress = ""
                    if task.get('progress_updates'):
                        latest = task['progress_updates'][-1]
                        progress = f" ({latest['progress_percent']}%)"
                    stats.append(f"{status_icon} Task {task['task_id']}: {task['user_name']} β†’ {task['task_type']}{progress}")
        
        # AI status
        stats.append("")
        ai_status = "πŸ€– **AI Status**: " + ("Trained βœ… (Making smart assignments)" if tm.engine.is_trained else "Learning Mode ⚠️ (Need completed tasks to learn)")
        stats.append(ai_status)
        
        return "\n".join(stats)
        
    except Exception as e:
        return f"Error: {str(e)}"

def assign_tasks():
    """Assign pending tasks using AI"""
    try:
        if len(tm.engine.users) == 0:
            return "❌ No users registered! Add users first in the 'Add User' tab."
        
        if len(tm.engine.tasks) == 0:
            return "❌ No tasks registered! Add tasks first in the 'Add Task' tab."
        
        assignments = []
        
        for _, task in tm.engine.tasks.iterrows():
            task_id = task['task_id']
            
            # Check if task already completed
            completed = tm.engine.results[tm.engine.results['task_id'] == task_id]
            if len(completed) > 0:
                continue
            
            # Check if already assigned
            task_key = None
            for key, data in tm.engine.progress_data.items():
                if data['task_id'] == task_id and data['status'] in ['assigned', 'in_progress']:
                    task_key = key
                    break
            if task_key:
                continue
                
            user_id, user_name = tm.engine.assign_task(task_id)
            if user_name:
                confidence = "AI Optimized" if tm.engine.is_trained else "Random (AI learning)"
                assignments.append(f"βœ… Task {task_id} ({task['type']}) β†’ **{user_name}** [{confidence}]")
        
        if not assignments:
            return "πŸ“‹ No pending tasks to assign (all tasks are either completed or already assigned)"
            
        return "\n".join(assignments)
        
    except Exception as e:
        return f"Error: {str(e)}"

def add_user(name):
    """Add new user"""
    try:
        if not name.strip():
            return "❌ Please enter a valid name"
            
        tm.add_user(name.strip())
        
        # Return updated user list
        user_list = "\n".join([f"- ID {u['user_id']}: {u['name']}" for _, u in tm.engine.users.iterrows()])
        return f"βœ… Added user: **{name.strip()}**\n\n**Current Users:**\n{user_list}"
        
    except Exception as e:
        return f"Error: {str(e)}"

def remove_user(user_id):
    """Remove a user"""
    try:
        if user_id is None or user_id <= 0:
            return "❌ Please enter a valid User ID"
        
        success, user_name = tm.remove_user(int(user_id))
        
        if not success:
            return f"❌ User ID {int(user_id)} not found!"
        
        # Return updated user list
        if len(tm.engine.users) > 0:
            user_list = "\n".join([f"- ID {u['user_id']}: {u['name']}" for _, u in tm.engine.users.iterrows()])
        else:
            user_list = "No users remaining"
            
        return f"βœ… Removed user: **{user_name}** (ID: {int(user_id)})\n\n**Current Users:**\n{user_list}"
        
    except Exception as e:
        return f"Error: {str(e)}"

def add_task(task_type, complexity, deadline):
    """Add new task"""
    try:
        if not task_type.strip():
            return "❌ Please enter a task type"
        if not (0 <= complexity <= 1):
            return "❌ Complexity must be between 0 and 1"
        if deadline <= 0:
            return "❌ Deadline must be positive"
            
        tm.add_task(task_type.strip(), complexity, deadline)
        
        # Return updated task list
        task_list = "\n".join([f"- ID {t['task_id']}: {t['type']} (Complexity: {t['complexity']})" for _, t in tm.engine.tasks.iterrows()])
        return f"βœ… Added task: **{task_type.strip()}**\n\n**Current Tasks:**\n{task_list}"
        
    except Exception as e:
        return f"Error: {str(e)}"

def remove_task(task_id):
    """Remove a task"""
    try:
        if task_id is None or task_id <= 0:
            return "❌ Please enter a valid Task ID"
        
        success, task_name = tm.remove_task(int(task_id))
        
        if not success:
            return f"❌ Task ID {int(task_id)} not found!"
        
        # Return updated task list
        if len(tm.engine.tasks) > 0:
            task_list = "\n".join([f"- ID {t['task_id']}: {t['type']} (Complexity: {t['complexity']})" for _, t in tm.engine.tasks.iterrows()])
        else:
            task_list = "No tasks remaining"
            
        return f"βœ… Removed task: **{task_name}** (ID: {int(task_id)})\n\n**Current Tasks:**\n{task_list}"
        
    except Exception as e:
        return f"Error: {str(e)}"

def update_progress(task_id, user_id, progress, notes):
    """Update task progress"""
    try:
        if task_id is None or task_id <= 0:
            return "❌ Please enter a valid Task ID"
        if user_id is None or user_id <= 0:
            return "❌ Please enter a valid User ID"
        if not (0 <= progress <= 100):
            return "❌ Progress must be between 0 and 100"
        
        # Validate task exists
        task_df = tm.engine.tasks[tm.engine.tasks['task_id'] == int(task_id)]
        if len(task_df) == 0:
            return f"❌ Task ID {int(task_id)} not found!"
        
        # Validate user exists
        user_df = tm.engine.users[tm.engine.users['user_id'] == int(user_id)]
        if len(user_df) == 0:
            return f"❌ User ID {int(user_id)} not found!"
            
        tm.update_progress(int(task_id), int(user_id), int(progress), notes.strip() if notes else "")
        return f"βœ… Progress updated: Task {int(task_id)} β†’ {int(progress)}%"
        
    except Exception as e:
        return f"Error: {str(e)}"

def complete_task(task_id, user_id, time_taken, quality):
    """Complete a task - THIS IS HOW AI LEARNS"""
    try:
        if task_id is None or task_id <= 0:
            return "❌ Please enter a valid Task ID"
        if user_id is None or user_id <= 0:
            return "❌ Please enter a valid User ID"
        if not (1 <= quality <= 5):
            return "❌ Quality must be between 1 and 5"
        if time_taken is None or time_taken <= 0:
            return "❌ Time taken must be positive"
        
        # Validate task exists
        task_df = tm.engine.tasks[tm.engine.tasks['task_id'] == int(task_id)]
        if len(task_df) == 0:
            return f"❌ Task ID {int(task_id)} not found! Check the Dashboard for valid Task IDs."
        
        # Validate user exists
        user_df = tm.engine.users[tm.engine.users['user_id'] == int(user_id)]
        if len(user_df) == 0:
            return f"❌ User ID {int(user_id)} not found! Check the Dashboard for valid User IDs."
            
        tm.enter_result(int(task_id), int(user_id), float(time_taken), int(quality))
        
        task_name = task_df['type'].iloc[0]
        user_name = user_df['name'].iloc[0]
        
        return f"""βœ… Task completed successfully!

**Details:**
- Task: {task_name} (ID: {int(task_id)})
- Completed by: {user_name} (ID: {int(user_id)})
- Time taken: {time_taken}h
- Quality: {int(quality)}/5

🧠 **AI is learning from this result!**
Retrain the AI in the 'Train AI' tab to improve future assignments."""
        
    except Exception as e:
        return f"Error: {str(e)}"

def retrain_ai():
    """Retrain the AI model"""
    try:
        if len(tm.engine.results) == 0:
            return "❌ No completed tasks yet! Complete some tasks first so AI can learn from them."
            
        tm.retrain_ai()
        return f"""βœ… AI model retrained successfully!

**AI learned from {len(tm.engine.results)} completed tasks.**

The AI will now make smarter assignments based on:
- User performance patterns
- Task complexity matching
- Time efficiency
- Quality consistency

Try assigning new tasks to see improved recommendations!"""
        
    except Exception as e:
        return f"Error: {str(e)}"

# Create Gradio interface
with gr.Blocks(title="🧠 AI Task Assignment System") as app:
    gr.Markdown("""
    # 🧠 AI Task Assignment System
    
    **A self-learning task assignment engine powered by AI**
    
    ### How It Works:
    1. **πŸ‘€ Add Users** - Enter your team members
    2. **πŸ“‹ Add Tasks** - Enter tasks with complexity & deadlines  
    3. **🎯 Get AI Assignments** - AI recommends optimal person for each task
    4. **βœ… Complete Tasks** - Enter results (time taken, quality)
    5. **🧠 AI Learns** - System improves with every completed task
    
    > ⚑ **All data is YOUR input** - AI only handles assignment optimization based on observed performance!
    """)
    
    with gr.Tabs():
        # Dashboard Tab
        with gr.Tab("πŸ“Š Dashboard"):
            gr.Markdown("### System Overview - Users, Tasks & Performance")
            dashboard_btn = gr.Button("πŸ”„ Refresh Dashboard", variant="primary")
            dashboard_output = gr.Markdown()
            dashboard_btn.click(show_dashboard, outputs=dashboard_output)
        
        # Add User Tab
        with gr.Tab("πŸ‘€ Add User"):
            gr.Markdown("### Register a new team member")
            gr.Markdown("*Enter the name of the person you want to add to the system.*")
            user_name = gr.Textbox(label="User Name", placeholder="Enter name (e.g., John, Sarah, etc.)...")
            add_user_btn = gr.Button("βž• Add User", variant="primary")
            add_user_output = gr.Markdown()
            add_user_btn.click(add_user, inputs=user_name, outputs=add_user_output)
        
        # Remove User Tab
        with gr.Tab("πŸ—‘οΈ Remove User"):
            gr.Markdown("### Remove a team member")
            gr.Markdown("*Enter the User ID to remove. Check the Dashboard for User IDs.*")
            gr.Markdown("⚠️ **Warning:** This will also remove all task history for this user.")
            remove_user_id = gr.Number(label="User ID to Remove", precision=0, minimum=1)
            remove_user_btn = gr.Button("πŸ—‘οΈ Remove User", variant="stop")
            remove_user_output = gr.Markdown()
            remove_user_btn.click(remove_user, inputs=remove_user_id, outputs=remove_user_output)
        
        # Add Task Tab  
        with gr.Tab("πŸ“‹ Add Task"):
            gr.Markdown("### Create a new task")
            gr.Markdown("*Enter task details - AI will assign it to the best person.*")
            task_type = gr.Textbox(label="Task Name/Type", placeholder="e.g., Website Design, Data Analysis, Report Writing...")
            with gr.Row():
                task_complexity = gr.Slider(0, 1, value=0.5, label="Complexity (0=Very Easy, 1=Very Hard)")
                task_deadline = gr.Number(label="Deadline (hours)", value=24, minimum=1)
            add_task_btn = gr.Button("βž• Add Task", variant="primary")
            add_task_output = gr.Markdown()
            add_task_btn.click(add_task, inputs=[task_type, task_complexity, task_deadline], outputs=add_task_output)
        
        # Remove Task Tab
        with gr.Tab("πŸ—‘οΈ Remove Task"):
            gr.Markdown("### Remove a task")
            gr.Markdown("*Enter the Task ID to remove. Check the Dashboard for Task IDs.*")
            gr.Markdown("⚠️ **Warning:** This will also remove all completion history for this task.")
            remove_task_id = gr.Number(label="Task ID to Remove", precision=0, minimum=1)
            remove_task_btn = gr.Button("πŸ—‘οΈ Remove Task", variant="stop")
            remove_task_output = gr.Markdown()
            remove_task_btn.click(remove_task, inputs=remove_task_id, outputs=remove_task_output)
        
        # Assignment Tab
        with gr.Tab("🎯 AI Assignment"):
            gr.Markdown("""### Let AI assign pending tasks
            
AI analyzes each user's past performance and assigns tasks to the most suitable person.

*If no performance data exists yet, AI will make random assignments and learn from results.*""")
            assign_btn = gr.Button("🎯 Assign All Pending Tasks", variant="primary", size="lg") 
            assign_output = gr.Markdown()
            assign_btn.click(assign_tasks, outputs=assign_output)
        
        # Progress Update Tab
        with gr.Tab("πŸ“ˆ Update Progress"):
            gr.Markdown("### Update task progress")
            gr.Markdown("*Track how work is progressing on assigned tasks.*")
            with gr.Row():
                prog_task_id = gr.Number(label="Task ID", precision=0, minimum=1)
                prog_user_id = gr.Number(label="User ID", precision=0, minimum=1) 
            progress_pct = gr.Slider(0, 100, value=50, label="Progress %")
            progress_notes = gr.Textbox(label="Notes (optional)", placeholder="Any updates or blockers...")
            update_prog_btn = gr.Button("πŸ“ˆ Update Progress", variant="primary")
            update_prog_output = gr.Markdown()
            update_prog_btn.click(update_progress, inputs=[prog_task_id, prog_user_id, progress_pct, progress_notes], outputs=update_prog_output)
        
        # Complete Task Tab
        with gr.Tab("βœ… Complete Task"):
            gr.Markdown("""### Mark task as completed
            
**⚑ This is how AI learns!** Enter the actual results so AI can improve future assignments.""")
            with gr.Row():
                comp_task_id = gr.Number(label="Task ID", precision=0, minimum=1)
                comp_user_id = gr.Number(label="User ID (who completed it)", precision=0, minimum=1)
            with gr.Row():
                time_taken = gr.Number(label="Actual Time Taken (hours)", value=1, minimum=0.1)
                quality_score = gr.Slider(1, 5, value=3, label="Quality of Work (1=Poor, 5=Excellent)", step=1)
            complete_btn = gr.Button("βœ… Complete Task", variant="primary")
            complete_output = gr.Markdown()
            complete_btn.click(complete_task, inputs=[comp_task_id, comp_user_id, time_taken, quality_score], outputs=complete_output)
        
        # AI Training Tab
        with gr.Tab("🧠 Train AI"):
            gr.Markdown("""### Retrain AI with new data
            
After completing tasks, retrain the AI to improve its assignment accuracy.

**The AI learns:**
- Which users perform best on which task types
- Time efficiency patterns  
- Quality consistency
- Optimal user-task matching""")
            retrain_btn = gr.Button("🧠 Retrain AI Model", variant="primary", size="lg")
            retrain_output = gr.Markdown()
            retrain_btn.click(retrain_ai, outputs=retrain_output)

    # Auto-load dashboard on startup
    app.load(show_dashboard, outputs=dashboard_output)

if __name__ == "__main__":
    # Launch without theme parameter for Gradio 4.44.0 compatibility
    app.launch()