@@ -236,9 +236,9 @@ class MemberTaskInfo:
236236 # IDs of courses that this member has completed
237237 completed_courses : Set [int ]
238238
239- # Number of hours spent at the space since the day after the last task was either assigned or completed
239+ # Number of hours spent at the space since the day after the last task was completed
240240 # If the member has never completed a task, this will be a very large value.
241- time_at_space_since_last_task : timedelta = field (
241+ time_at_space_since_last_task_completed : timedelta = field (
242242 serializer = lambda td : td .total_seconds (), deserializer = lambda seconds : timedelta (seconds = seconds )
243243 )
244244
@@ -377,22 +377,28 @@ def from_member(member_id: int, now: datetime) -> "MemberTaskInfo":
377377 if last_completed_task is not None :
378378 assert len (last_assigned_tasks ) > 0
379379
380- if last_assigned_tasks :
381- day_after_last_task = last_assigned_tasks [0 ].created_at
382- day_after_last_task += timedelta (days = 1 )
383- day_after_last_task .replace (hour = 0 , minute = 0 , second = 0 , microsecond = 0 )
380+ if last_completed_task :
381+ after_last_task = last_completed_task .created_at
382+ # Start counting time spent at the space from when the last task was completed, plus some buffer time based on the task size.
383+ # 1. A member should never be automatically be delegated a task twice in a day
384+ # 2. If a member spends a lot of time at the space after completing a task, they should get a new task on their next visit
385+ # 3. If they don't spend much time at the space after completing a task, the may not get a new task on their next visit
386+ # 4. Larger tasks should have more buffer time, since they likely took more time and effort to complete.
387+ # 5. Trivial tasks should make the member get a new task immediately.
388+ after_last_task += TASK_SIZE_TO_TIME .get (last_completed_task .task_size , timedelta ())
389+ # day_after_last_task += timedelta(days=1)
390+ # day_after_last_task.replace(hour=0, minute=0, second=0, microsecond=0)
384391
385- # Count all visits after the day after the last task was assigned or completed.
386392 # and before the current time minus some margin to avoid counting ongoing visits.
387393 # This prevents us from assigning a task in the middle of a visit, instead of at the start.
388- visits = visit_events_by_member_id (day_after_last_task , now - timedelta (hours = 18 ), member_id = member_id ).get (
394+ visits = visit_events_by_member_id (after_last_task , now - timedelta (hours = 18 ), member_id = member_id ).get (
389395 member_id , []
390396 )
391- time_at_space_since_last_task = timedelta ()
397+ time_at_space_since_last_task_completed = timedelta ()
392398 for _ , duration in visits :
393- time_at_space_since_last_task += duration
399+ time_at_space_since_last_task_completed += duration
394400 else :
395- time_at_space_since_last_task = timedelta (days = 365 * 10 ) # A large value representing "infinity"
401+ time_at_space_since_last_task_completed = timedelta (days = 365 * 10 ) # A large value representing "infinity"
396402
397403 purchased_product_time_cutoff = now - timedelta (days = 365 )
398404 purchased_product_count_by_name = {}
@@ -494,7 +500,7 @@ def from_member(member_id: int, now: datetime) -> "MemberTaskInfo":
494500 purchased_product_count_by_name = purchased_product_count_by_name ,
495501 completed_card_ids = completed_card_ids ,
496502 completed_card_names = completed_card_names ,
497- time_at_space_since_last_task = time_at_space_since_last_task ,
503+ time_at_space_since_last_task_completed = time_at_space_since_last_task_completed ,
498504 preferred_rooms = preferred_rooms ,
499505 self_reported_skill_level = self_reported_skill_level ,
500506 completed_courses = completed_courses ,
@@ -1144,7 +1150,7 @@ def member_recently_received_task(ctx: TaskContext) -> bool:
11441150 # If a member has completed a task recently, don't assign them another one too soon.
11451151 # The wait depends on the size of the task
11461152 if ctx .member .last_completed_task is not None :
1147- if ctx .member .time_at_space_since_last_task < TASK_SIZE_TO_TIME [ctx .member .last_completed_task .size ]:
1153+ if ctx .member .time_at_space_since_last_task_completed < TASK_SIZE_TO_TIME [ctx .member .last_completed_task .size ]:
11481154 return True
11491155
11501156 last_assigned_task = ctx .member .last_assigned_tasks [0 ] if ctx .member .last_assigned_tasks else None
@@ -1273,9 +1279,9 @@ def score_calculation_summary(self, line_prefix: str = "", column_width: int = 0
12731279 current_score = op .value
12741280 lines .append (f"{ line_prefix } = { v_str } => { current_score :.2f} " )
12751281
1276- assert (
1277- abs ( current_score - self .score ) < 0.0001
1278- ), f"Score calculation mismatch: calculated { current_score } , expected { self . score } "
1282+ assert abs ( current_score - self . score ) < 0.0001 , (
1283+ f"Score calculation mismatch: calculated { current_score } , expected { self .score } "
1284+ )
12791285 return "\n " .join (lines )
12801286
12811287
0 commit comments