forked from noahvanhoucke/HelpingSantasHelpers
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathelf.py
60 lines (54 loc) · 2.93 KB
/
elf.py
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
import math
import hours as hrs
class Elf:
""" Each Elf starts with a rating of 1.0 and are available at 09:00 on Jan 1. """
def __init__(self, elfid):
self.id = elfid
self.rating = 1.0
self.next_available_time = 540 # Santa's Workshop opens Jan 1, 2014 9:00 (= 540 minutes)
self.rating_increase = 1.02
self.rating_decrease = 0.90
def update_elf(self, hrs, toy, start_minute, duration):
""" Updates the elf's productivity rating and next available time based on last toy completed.
:param hrs: Hours object for bookkeeping
:param toy: Toy object for the toy the elf just finished
:param start_minute: minute work started
:param duration: duration of work, in minutes
:return: void
"""
self.update_next_available_minute(hrs, start_minute, duration)
self.update_productivity(hrs, start_minute, int(math.ceil(toy.duration / self.rating)))
def update_next_available_minute(self, hrs, start_minute, duration):
""" Apply the resting time constraint and determine the next minute when the elf can work next.
Here, elf can only start work during sanctioned times
:param start_minute: time work started on last toy
:param duration: duration of work on last toy
:return: void
"""
sanctioned, unsanctioned = hrs.get_sanctioned_breakdown(start_minute, duration)
# enforce resting time based on the end_minute and the unsanctioned minutes that
# need to be accounted for.
end_minute = start_minute + duration
if unsanctioned == 0:
if hrs.is_sanctioned_time(end_minute):
self.next_available_time = end_minute
else:
self.next_available_time = hrs.next_sanctioned_minute(end_minute)
else:
self.next_available_time = hrs.apply_resting_period(end_minute, unsanctioned)
def update_productivity(self, hrs, start_minute, toy_required_minutes):
""" Update the elf's productivity rating based on the number of minutes the toy required that were
worked during sanctioned and unsanctioned times.
max(0.5,
min(2.0, previous_rating * (self.rating_increase ** sanctioned_hours) *
(self.rating_decrease ** unsanctioned_hours)))
:param hrs: hours object
:param start_minute: minute work started
:param toy_required_minutes: minutes required to build the toy (may be different from minutes elf worked)
:return: void
"""
# number of required minutes to build toy worked by elf, broken up by sanctioned and unsanctioned minutes
sanctioned, unsanctioned = hrs.get_sanctioned_breakdown(start_minute, toy_required_minutes)
self.rating = max(0.25,
min(4.0, self.rating * (self.rating_increase ** (sanctioned/60.0)) *
(self.rating_decrease ** (unsanctioned/60.0))))