aboutsummaryrefslogtreecommitdiff
path: root/src/time.odin
diff options
context:
space:
mode:
authorSan Jacobs2023-05-19 04:04:33 +0200
committerSan Jacobs2023-05-19 04:04:33 +0200
commit46fdf2827e80e1dab0efd7173c9f518af8e38831 (patch)
treeaceadec2c850e3e683ee14f0003c358755b00af9 /src/time.odin
parent8351103dc23c88bc390e9dd9e9c7112e7c4b80b5 (diff)
downloadsatscalc-46fdf2827e80e1dab0efd7173c9f518af8e38831.tar.gz
satscalc-46fdf2827e80e1dab0efd7173c9f518af8e38831.tar.bz2
satscalc-46fdf2827e80e1dab0efd7173c9f518af8e38831.zip
Productivity is my middle name
Diffstat (limited to 'src/time.odin')
-rw-r--r--src/time.odin176
1 files changed, 138 insertions, 38 deletions
diff --git a/src/time.odin b/src/time.odin
index bdef718..d5fec73 100644
--- a/src/time.odin
+++ b/src/time.odin
@@ -11,14 +11,14 @@ import "core:sort"
// --- STRUCTURES ---
//
-Weekday : enum{
+Weekday :: enum{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
- Sunday
+ Sunday,
}
Delta :: struct {
@@ -38,8 +38,8 @@ Moment :: struct {
Timeblock :: struct {
start : Moment,
end : Moment,
- valuefactor : f32,
- price_reason : string,
+ value : f32,
+ reason : string,
}
Workday :: struct {
@@ -72,7 +72,7 @@ new_workday :: proc(previous_wrap : Moment,
// though so that at least one hour of the unused overtime is not counted.
// (It's unclear if an 8-hour day that ends 3 hours in counts as having 5 hours of unused overtime)
max(clamp(sub(planned_wrap, {0, 1, 0}), wrap, add(wrap, {0, 2, 0})),
- add(call, {0, 4, 0})), 0, ""}
+ add(call, {0, 4, 0})), 1, ""}
// ^ Minimum 4 hour day ^
sp_length :: 11
@@ -126,43 +126,71 @@ new_workday :: proc(previous_wrap : Moment,
j += 1
total_timeblocks = j
+ // This line is commented out because it shouldn't be needed.
//slice.sort_by(blocks[:], lessTimeblock)
- for each_block, i in blocks {
- fmt.printf("Block %2i: %s\n", i+1, toString(each_block))
- }
fmt.println(total_timeblocks)
- // TODO:
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
- // BIG BLOCK OF RULES N SHIT GOES HERE
+ for block, i in &blocks {
+ if i >= total_timeblocks do break
+
+ //using Weekday
+
+ if lessEq(block.end, splitpoints[0]) do upvalue(&block, 3, "Sleep-breach") // +200% for sleep-breach
+ if block.start.hours >= 22 do upvalue(&block, 2, "Night") // Work at night, aka. between 22:00 and 06:00
+ if (block.end.hours == 6 && block.end.minutes == 0) || block.end.hours <= 5 do upvalue(&block, 2, "Night") // is +100%
+ if greatEq(block.start, splitpoints[3]) {
+ upvalue(&block, 1.5, "Overtime")
+ if getweekday(block.start) == .Saturday do upvalue(&block, 2, "Saturday Overtime")
+ }
+ if greatEq(block.start, splitpoints[5]) do upvalue(&block, 2, "Overtime") // End of 3-hour cheap planned overtime
+ if greatEq(block.start, planned_wrap) && greatEq(block.start, splitpoints[4]) do upvalue(&block, 2, "Overtime") // Unwarned OT
+ if greatEq(block.start, splitpoints[7]) do upvalue(&block, 3, "Far overtime") // +200% beyond 14th hours is +100%
+ if getweekday(block.start) == .Saturday do upvalue(&block, 1.5, "Saturday") // Saturdays are +50%
+ if getweekday(block.start) == .Sunday do upvalue(&block, 2, "Sunday") // Sundays are +100%
+
+ if !(less(call, Moment{0, 7, call.day, call.month, call.year}) &&
+ less(min(add(call, Delta{0,8,0}), wrap), Moment{0, 17, call.day, call.month, call.year} )) {
+ // This was added for rule 6.11c, but in a world without a defined normal workday,
+ // that rule is already covered already by 6.11g, so this is empty.
+ }
+
+
+ // Holidays!
+ if (block.start.day==1) && (block.start.month==1) do upvalue(&block, 2, "New year")
+ if (block.start.day==1) && (block.start.month==5) do upvalue(&block, 2, "1st of May")
+ if (block.start.day==17) && (block.start.month==5) do upvalue(&block, 2, "17th of May")
+ if (block.start.day==25 || block.start.day==26) && block.start.month==12 do upvalue(&block, 2, "Christmas")
+ easter: Moment = gaussEaster(block.start.year)
+ if (block.start.day == sub(easter, {0,0,3}).day) && block.start.month == sub(easter, {0,0,3}).month do upvalue(&block, 2, "Maundy Thursday")
+ if (block.start.day == sub(easter, {0,0,2}).day) && block.start.month == sub(easter, {0,0,2}).month do upvalue(&block, 2, "Good Friday")
+ if (block.start.day == easter.day) && (block.start.month == easter.month) do upvalue(&block, 2, "Easter")
+ if (block.start.day == add(easter, {0,0,1}).day) && (block.start.month == add(easter, {0,0,1}).month) do upvalue(&block, 2, "Easter")
+ if (block.start.day == add(easter, {0,0,39}).day) && (block.start.month == add(easter, {0,0,39}).month) do upvalue(&block, 2, "Feast of the Ascension")
+ if (block.start.day == add(easter, {0,0,49}).day) && (block.start.month == add(easter, {0,0,49}).month) do upvalue(&block, 2, "Pentecost")
+ if (block.start.day == add(easter, {0,0,50}).day) && (block.start.month == add(easter, {0,0,50}).month) do upvalue(&block, 2, "Pentecost Monday")
+ }
+
+ for each_block, i in blocks {
+ fmt.printf("Block %2i: %s $f: %i%% %s\n", i+1, toString(each_block), int((each_block.value-1)*100), each_block.reason)
+ }
return
}
+lunch :: proc(workday: ^Workday, lunch_start: Moment, lunch_end: Moment) {
+ // TODO: Implement lunch!
+ //
+ // This version of lunch needs to fix the issue where when lunch spans multiple Timeblocks,
+ // it would... not act like a proper adult.
+ //
+ // |-------|---|-------|----|---------|--------------|
+ // |--lunch--|
+ // |-------|---|----| |-------|--------------|
+ // This ^ must work!
+}
+
windIndividual :: proc(input_moment: ^Moment,
minutes: int,
hours: int,
@@ -236,17 +264,24 @@ timesplit :: proc(block: Timeblock, splitpoint: Moment) -> (first_half: Timebloc
return
}
- first_half = {block.start, splitpoint, block.valuefactor, block.price_reason}
- second_half = {splitpoint, block.end, block.valuefactor, block.price_reason}
+ first_half = {block.start, splitpoint, block.value, block.reason}
+ second_half = {splitpoint, block.end, block.value, block.reason}
return
}
+upvalue :: proc(input_block: ^Timeblock, value: f32, reason: string) {
+ block: ^Timeblock = input_block
+ if value > block.value {
+ block.value = value
+ block.reason = reason
+ }
+}
+
//
// --- BASIC OPERATIONS ---
//
-
add :: proc(moment: Moment, delta: Delta) -> (output: Moment) {
output = moment
wind(&output, delta)
@@ -307,6 +342,16 @@ lessTimeblock :: proc(block_a: Timeblock, block_b: Timeblock) -> bool {
}
less :: proc{lessMoment, lessDelta, lessTimeblock}
+lessEqMoment :: proc(moment_a: Moment, moment_b: Moment) -> bool {
+ return moment_a==moment_b || less(moment_a, moment_b)
+}
+lessEq :: proc{lessEqMoment}
+
+greatEqMoment :: proc(moment_a: Moment, moment_b: Moment) -> bool {
+ return moment_a == moment_b || great(moment_a, moment_b)
+}
+greatEq :: proc{greatEqMoment}
+
diff :: proc(moment_a: Moment, moment_b: Moment) -> (acc: Delta) {
// TODO: Finish writing this
@@ -431,9 +476,14 @@ deltaToString :: proc(delta: Delta) -> (output: string) {
output = strings.concatenate(cat_array[:])
return
-
}
+getweekday :: proc(moment: Moment) -> Weekday {
+ y: int = moment.year
+ t: []int = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 }
+ y -= int(moment.month < 3)
+ return Weekday((y + y / 4 - y / 100 + y / 400 + t[moment.month - 1] + moment.day - 1) % 7)
+}
momentToString :: proc(moment: Moment) -> (output: string) {
using moment
@@ -495,6 +545,56 @@ days_in :: proc(month: int, year: int) -> int {
return 31;
}
fmt.printf("You just found month nr: %i. Something is very wrong.\n", month)
- assert(month < 13 && month > 0)
+ fmt.assertf(month < 13 && month > 0, "You tried to get the days in month %i!\n", month)
return 30
}
+
+gaussEaster :: proc(year: int) -> Moment {
+ // Thanks to Carl Friedrich Gauss for the algorythm
+ // Thanks rahulhegde97, bansal_rtk_, code_hunt, sanjoy_62, simranarora5sos
+ // and aashutoshparoha on GeeksForGeeks for the implementation I based this on.
+ A, B, C, P, Q, M, N, D, E: f64
+ easter_month: int = 0
+ easter_day: int = 0
+
+ A = f64(year % 19)
+ B = f64(year % 4)
+ C = f64(year % 7)
+ P = f64(math.floor(f64(year / 100.0)))
+
+ Q = math.floor((13 + 8 * P) / 25.0)
+
+ M = f64(int(15 - Q + P - math.floor(f64(P / 4))) % 30)
+
+ N = f64(int(4 + P - math.floor(P / 4)) % 7)
+
+ D = f64(int(19 * A + M) % 30)
+
+ E = f64(int(2 * B + 4 * C + 6 * D + N) % 7)
+
+ days: int = int(22 + D + E)
+ easter_day = days
+
+ if (D == 29) && (E == 6) {
+ // A corner case when D is 29
+ easter_month = 4
+ easter_day = 19
+ } else if (D == 28) && (E == 6) {
+ // Another corner case, when D is 28
+ easter_month = 4
+ easter_day = 18
+ } else {
+ // If days > 31, move to April
+ // April = 4th Month
+ if (days > 31) {
+ easter_month = 04
+ easter_day = days-31
+ } else {
+ // Otherwise, stay on March
+ // March = 3rd Month
+ easter_month = 03
+ }
+ }
+
+ return {0, 0, easter_day, easter_month, year}
+} \ No newline at end of file