-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmodel.py
144 lines (124 loc) · 4.69 KB
/
model.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
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
import scipy.integrate
from scipy import optimize
import math
import json
class TaskModel:
def __init__(
self,
id,
today,
due,
work,
week_day_work,
week_end_work=0,
days=0,
gradient="+",
):
self.id = f"t{id}"
self.due_date = due
self.work = work
self.h = week_day_work
self.gradient = gradient
self.today = today
# if the task is big, more than 10 hours of work
if self.work > 10:
# get c value with least final day area
self.c = optimize.root_scalar( # c is the flexibility variable
self.c_for_huge, bracket=[0, 3], method="brentq"
).root # TODO fix the bracket
# if the task is small, less than or equal 10 hours of work
elif self.work <= 10:
# no of days needed is estimated to H / H**(1/3)
# this will make sure that the final gradient is around 1
# self.c = (3*self.work**(1/3)-1)/3
self.c = (3 * self.work ** (1 / 3) - self.work ** (2 / 3) / 2) / 3
# self.h = self.c + 1
# # TODO when this h is more than min threshold
self.h = self.c + self.work ** (2 / 3) / 2
# TODO work on c which can be customized according to users no of day
# duration
self.n = 3 * self.work / (self.h + 2 * self.c)
# the start date of the task
# d0 = D-n
self.start_day = self.due_date - self.n
# if the initial date is less than 0
if (
self.start_day < today
): # TODO make this today by getting a relative time for due date
# c gets re-evaluate according to condition
self.h = week_day_work
self.c = (3 * self.work / (self.due_date - today) - self.h) / 2
# set duration as days to due
self.n = self.due_date - today
# start date is made 0, current date
self.start_day = today
print(self.start_day, "START DAY SHOULD BE TODAY")
# if user requires a no of days and its NOT less than min
elif days != 0 and self.due_date - today + days > 0:
# TODO make sure this works
self.c = (3 * self.work / (days + today) - self.h) / 2
self.start_day = self.due_date - (days + today)
# TODO flip according to limitation
if (
gradient == "-" and self.work / (self.due_date - today) < self.h
) or (
gradient == "+" and self.work / (self.due_date - today) > self.h
):
self.h = self.c
self.c = (3 * self.work / self.n - self.h) / 2
if gradient == "0":
self.n = (
days
if days != 0
else self.work / self.work ** (1 / 3)
if self.work / self.work ** (1 / 3) < self.due_date - today
else self.due_date - today
)
self.c = self.work / self.n
self.h = self.c
self.start_day = self.due_date - self.n
# total area, for checking
total_area = scipy.integrate.quad(
self.model, self.start_day, self.due_date
)[0]
print("n: ", self.n)
print("c: ", self.c, "h: ", self.h)
print("total area: ", round(total_area, 4))
# self.generate_list()
# used to find min area for final day. Used only for default (large) tasks
def c_for_huge(self, x):
return (
-8 * x ** 3
- 4 * self.h * x ** 2
+ 16 * self.work * x ** 2
+ 2 * self.h ** 2 * x
- 6 * self.work ** 2 * x
+ 4 * self.h * self.work * x
+ self.h ** 3
- 3 * self.h * self.work ** 2
- 2 * self.h ** 2 * self.work
) / (3 * self.work ** 2 * (2 * x + self.h)) + 1
def model(self, x):
return (self.h - self.c) / (
3 * self.work / (self.h + 2 * self.c)
) ** 2 * (
x - self.due_date + 3 * self.work / (self.h + 2 * self.c)
) ** 2 + self.c
def generate_list(self):
task_days = []
def area(start, end):
return scipy.integrate.quad(self.model, start, end)[0]
task_days.append(
(
(math.floor(self.start_day)),
area(
self.start_day,
math.ceil(self.start_day)
if math.ceil(self.start_day) > self.start_day
else self.start_day + 1,
),
)
)
for n in range(math.floor(self.start_day) + 1, self.due_date):
task_days.append((n, area(n, n + 1)))
return task_days