From 74ed85075819146fe9be4310bb709d80fa96c294 Mon Sep 17 00:00:00 2001 From: San Jacobs Date: Sat, 20 May 2023 09:03:25 +0200 Subject: Implemented lunch() like a boss The lunch() function was pretty broken in v0.2.0-alpha, so a long lunch would cause all sorts of problems. Not anymore, friends! --- src/main.odin | 19 ++++++++-- src/time.odin | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 122 insertions(+), 12 deletions(-) diff --git a/src/main.odin b/src/main.odin index 89ff39e..d64d5e3 100644 --- a/src/main.odin +++ b/src/main.odin @@ -4,12 +4,23 @@ import "core:fmt" main :: proc() { //test() - new_workday({10, 22, 1, 5, 2023}, - {00, 08, 5, 5, 2023}, - {00, 05, 6, 5, 2023}, - {30, 21, 5, 5, 2023}) + workday: = new_workday({10, 22, 4, 5, 2023}, + {00, 08, 5, 5, 2023}, + {00, 05, 6, 5, 2023}, + {30, 21, 5, 5, 2023}) + //lunch(&workday, {00, 16, 5, 5, 2023}, {00, 17, 5, 5, 2023}) + lunch(&workday, {00, 12, 5, 5, 2023}, {45, 22, 5, 5, 2023}) + //lunch(&workday, {00, 12, 5, 5, 2023}, {30, 12, 5, 5, 2023}) + //lunch(&workday, {30, 16, 5, 5, 2023}, {30, 17, 5, 5, 2023}) + //lunch(&workday, {30, 19, 5, 5, 2023}, {30, 22, 5, 5, 2023}) + for each_block, i in workday.blocks { + fmt.printf("Block %2i: %s $f: %i%% %s\n", i+1, toString(each_block), int((each_block.value-1)*100), each_block.reason) + } } +// TODO: Separate tests into different procedures +// TODO: Write dedicated tests for lunch + test :: proc() { fmt.println("\n--- TESTING PRINT STUFFS ---") diff --git a/src/time.odin b/src/time.odin index d5fec73..a3e4b3b 100644 --- a/src/time.odin +++ b/src/time.odin @@ -46,8 +46,11 @@ Workday :: struct { call : Moment, wrap : Moment, planned_wrap : Moment, - - blocks : [12]Timeblock, + + // blocks is over 12, + // because lunch breaks + // cause more blocks + blocks : [16]Timeblock, total_timeblocks : int, } @@ -180,15 +183,85 @@ new_workday :: proc(previous_wrap : Moment, } 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. + // This basically cuts out part of the workday // // |-------|---|-------|----|---------|--------------| // |--lunch--| // |-------|---|----| |-------|--------------| - // This ^ must work! + // This ^ works now! + + if lunch_start == lunch_end do return + assert(less(lunch_start, lunch_end), "ERROR: Bad Lunch! Lunch ends before it starts") + + start_index: int + end_index: int + for block, i in workday.blocks { + if (great(lunch_start, block.start) && less(lunch_start, block.end)) || (block.start == lunch_start) { + start_index = i + } + if (great(lunch_end, block.start) && less(lunch_end, block.end)) || (block.end == lunch_end) { + end_index = i + } + } + + assert(start_index <= end_index, "ERROR: Bad Lunch! start_index greater than end_index") + + span: int = end_index - start_index + + // TODO: This is bad and can definitely be simplified and done in a more principled way + // But right now it works perfectly, and is much better than it used to be in the C++ version + switch span { + case 0: + fmt.println("Start and end are in the same block") + switch { + case (lunch_start == workday.blocks[start_index].start) && (lunch_end == workday.blocks[end_index].end): + popBlock(workday, start_index) + case lunch_start == workday.blocks[start_index].start: + workday.blocks[start_index].start = lunch_end + case lunch_end == workday.blocks[end_index].end: + workday.blocks[end_index].end = lunch_start + case: + growBlocks(workday, start_index) + end_index += 1 + workday.blocks[start_index].end = lunch_start + workday.blocks[end_index].start = lunch_end + } + + case 1: + fmt.println("Start and end span one gap") + switch { + case (lunch_start == workday.blocks[start_index].start) && (lunch_end == workday.blocks[end_index].end): + popBlock(workday, start_index, 2) + case lunch_start == workday.blocks[start_index].start: + workday.blocks[end_index].start = lunch_end + popBlock(workday, start_index) + case lunch_end == workday.blocks[end_index].end: + workday.blocks[start_index].end = lunch_start + popBlock(workday, end_index) + case: + workday.blocks[end_index].start = lunch_end + workday.blocks[start_index].end = lunch_start + } + + case 2..=len(workday.blocks): + fmt.println("Start and end span more than one gap") + switch { + case (lunch_start == workday.blocks[start_index].start) && (lunch_end == workday.blocks[end_index].end): + popBlock(workday, start_index, span+1) + case lunch_start == workday.blocks[start_index].start: + workday.blocks[end_index].start = lunch_end + popBlock(workday, start_index, span) + case lunch_end == workday.blocks[end_index].end: + workday.blocks[start_index].end = lunch_start + popBlock(workday, start_index+1, span) + case: + workday.blocks[end_index].start = lunch_end + workday.blocks[start_index].end = lunch_start + popBlock(workday, start_index+1, span-1) + } + } } windIndividual :: proc(input_moment: ^Moment, @@ -244,12 +317,12 @@ windIndividual :: proc(input_moment: ^Moment, return } -windDelta :: proc(moment: ^Moment, delta: Delta) { +windByDelta :: proc(moment: ^Moment, delta: Delta) { using delta wind(moment, minutes, hours, days) return } -wind :: proc{windIndividual, windDelta} +wind :: proc{windIndividual, windByDelta} timesplit :: proc(block: Timeblock, splitpoint: Moment) -> (first_half: Timeblock, second_half: Timeblock) { // Splits a timeblock at splitpoint. @@ -514,6 +587,32 @@ clockprintTimeblock :: proc(block: Timeblock) -> string { } timeprint :: proc{clockprintTimeblock, clockprintMoment} +popBlock :: proc(workday: ^Workday, index: int, count: int = 1) { + using workday + when ODIN_DEBUG do fmt.printf("popBlock() running to remove %i block(s) from index %i\n", count, index) + for i in index..=index; i-=1 { + fmt.printf("Putting the contents of %i/%i into %i\n", i+count, len(blocks)-1, i) + blocks[i+count] = blocks[i] + } + //for i in index.. int { switch month { case 1: -- cgit v1.2.1