From e12cbc76905216c33d280950f20283df1281b618 Mon Sep 17 00:00:00 2001 From: San Jacobs Date: Tue, 16 May 2023 22:28:37 +0200 Subject: Taking a massive W on this, got quite far on the odin port --- src/time.odin | 310 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 310 insertions(+) create mode 100644 src/time.odin (limited to 'src/time.odin') diff --git a/src/time.odin b/src/time.odin new file mode 100644 index 0000000..d6f6046 --- /dev/null +++ b/src/time.odin @@ -0,0 +1,310 @@ +package main + +import math "core:math" +import "core:fmt" +import "core:strings" +import "core:strconv" +import "core:slice" + +// +// --- STRUCTURES --- +// + +Weekday : enum{ + Monday, + Tuesday, + Wednesday, + Thursday, + Friday, + Saturday, + Sunday +} + +Delta :: struct { + minutes : int, + hours : int, + days : int, +} + +Moment :: struct { + minutes : int, + hours : int, + day : int, + month : int, + year : int, +} + +Timeblock :: struct { + start : Moment, + end : Moment, + valuefactor : f32, + price_reason : string, +} + +Workday :: struct { + call : Moment, + wrap : Moment, + planned_wrap : Moment, + + blocks : [15]Timeblock, + total_timeblocks : int, +} + +// +// --- BASIC OPERATIONS --- +// + +windIndividual :: proc(input_moment: ^Moment, + minutes: int, + hours: int, + days: int) { + + // Adding minutes + input_moment.minutes += minutes + for input_moment.minutes > 59 { + input_moment.minutes -= 60 + input_moment.hours += 1 + } + for input_moment.minutes < 0 { + input_moment.minutes += 60 + input_moment.hours -= 1 + } + + // Adding hours + input_moment.hours += hours + for input_moment.hours > 23 { + input_moment.hours -= 24 + input_moment.day += 1 + } + for input_moment.hours < 0 { + input_moment.hours += 24 + input_moment.day -= 1 + } + + // Adding days + input_moment.day += days + current_month_length: int = days_in(input_moment.month, input_moment.year) + + for input_moment.day > current_month_length { + input_moment.day -= current_month_length + input_moment.month += 1 + if input_moment.month > 12 { + input_moment.month -= 12 + input_moment.year += 1 + } + current_month_length = days_in(input_moment.month, input_moment.year) + } + + for input_moment.day < 1 { + input_moment.month -= 1 + if input_moment.month < 1 { + input_moment.month += 12 + input_moment.year -= 1 + } + current_month_length = days_in(input_moment.month, input_moment.year) + input_moment.day += current_month_length + } + + return +} +windDelta :: proc(moment: ^Moment, delta: Delta) { + using delta + wind(moment, minutes, hours, days) + return +} +wind :: proc{windIndividual, windDelta} + + +add :: proc(moment: Moment, delta: Delta) -> (output: Moment) { + output = moment + wind(&output, delta) + return +} +sub :: proc(moment: Moment, delta: Delta) -> (output: Moment) { + output = moment + using delta + wind(&output, minutes*-1, hours*-1, days*-1) + return +} + +gtMoment :: proc(moment_a: Moment, moment_b: Moment) -> bool { + // TODO: This is wrong + return true +} +gtDelta :: proc(delta_a: Delta, delta_b: Delta) -> bool { + // TODO: This is wrong + return true +} +gt :: proc{gtMoment, gtDelta} + +diff :: proc(moment_a: Moment, moment_b: Moment) -> (acc: Delta) { + + acc = {0, 0, 0} + if moment_a == moment_b do return + + // Uses what I call an accumulator-decumulator design + // Count how long it takes to approach a benchmark, + // and that count is the difference + + reverse: bool = gt(moment_b, moment_a) + + + // TODO: Finish writing this + + + return +} + +sortableTimeDelta :: proc(delta: Delta) -> int { + using delta + return strconv.atoi(fmt.tprintf("%2i%2i%2i", days, hours, minutes)) +} +sortableTimeMoment :: proc(moment: Moment) -> int { + using moment + return strconv.atoi(fmt.tprintf("%4i%2i%2i%2i%2i", year, month, day, hours, minutes)) +} + +deltaToString :: proc(delta: Delta) -> (output: string) { + using delta + + if hours == 0 && + days == 0 && + minutes == 0 { + return "None" + } + + cat_array : [dynamic]string + printed_prev : bool = false + + if days>0 { + buf: [5]byte + append(&cat_array, fmt.tprint(days)) + if days < 2 { + append(&cat_array, " day") + } else { + append(&cat_array, " days") + } + printed_prev = true + } + + if hours>0 { + + if printed_prev do append(&cat_array, ", ") + + buf: [5]byte + append(&cat_array, fmt.tprint(hours)) + if hours < 2 { + append(&cat_array, " hour") + } else { + append(&cat_array, " hours") + } + printed_prev = true + } + + if minutes>0 { + + if printed_prev do append(&cat_array, ", ") + + buf: [5]byte + append(&cat_array, fmt.tprint(minutes)) + if minutes < 2 { + append(&cat_array, " minute") + } else { + append(&cat_array, " minutes") + } + } + + output = strings.concatenate(cat_array[:]) + return + +} + + +momentToString :: proc(moment: Moment) -> (output: string) { + using moment + + cat_array: [dynamic]string + + output = fmt.tprintf("%i-%2i-%2i %2i:%2i", year, month, day, hours, minutes) + + return +} +timeblockToString :: proc(block: Timeblock) -> (output: string) { + using block + s: [3]string = {toString(start), " -> ", toString(end)} + output = strings.concatenate(s[:]) + return +} +toString :: proc{deltaToString, momentToString, timeblockToString} + + + +clockprintMoment :: proc(moment: Moment) -> string { + using moment + return fmt.tprintf("%2i:%2i", hours, minutes) +} +clockprintTimeblock :: proc(block: Timeblock) -> string { + using block + return fmt.tprintf("%s -> %s", timeprint(start), timeprint(end)) +} +timeprint :: proc{clockprintTimeblock, clockprintMoment} + + +// +// --- PROCEDURES --- +// + +days_in :: proc(month: int, year: int) -> int { + switch month { + case 1: + return 31; + case 2: + if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)){ + return 29; + } + return 28; + case 3: + return 31; + case 4: + return 30; + case 5: + return 31; + case 6: + return 30; + case 7: + return 31; + case 8: + return 31; + case 9: + return 30; + case 10: + return 31; + case 11: + return 30; + case 12: + return 31; + } + fmt.printf("You just found month nr: %i. Something is very wrong.\n", month) + assert(month < 13 && month > 0) + return 30 +} + +new_workday :: proc(previous_wrap : Moment, + calltime : Moment, + wraptime : Moment, + planned_wraptime : Moment) -> (workday: Workday) { + + workday.call = calltime + workday.wrap = wraptime + workday.planned_wrap = planned_wraptime + + /* + initial_block: Timeblock = { + math.max( + math.clamp(), + ) + } + */ + + return +} -- cgit v1.2.1