diff options
| -rw-r--r-- | build.bat | 2 | ||||
| -rw-r--r-- | main.odin | 25 | ||||
| -rw-r--r-- | test-data.ics | 28 | ||||
| -rw-r--r-- | time.odin | 19 | 
4 files changed, 48 insertions, 26 deletions
| @@ -1 +1 @@ -odin build . -out:statics.exe && statics.exe "test-data.ics" -i 2025-08 -v
\ No newline at end of file +odin build . -out:statics.exe && statics.exe "test-data.ics" -i 2025-08 -v -s Test
\ No newline at end of file @@ -12,6 +12,7 @@ Arg_Type :: enum {  	FROM,  	TO,  	IN, +	SUBSTRING,  }  Arg_Flags :: bit_set[Arg_Type] @@ -41,6 +42,7 @@ main :: proc() {  	from_filter : Filter  	in_filter : Filter  	in_filter_out : Filter +	substring : string  	file_index_buffer : [dynamic]int @@ -58,6 +60,8 @@ main :: proc() {  							parsing = .FROM  						case "-i":  							parsing = .IN +						case "-s": +							parsing = .SUBSTRING  						case "-v":  							verbose = true  						case "-h": @@ -70,6 +74,7 @@ main :: proc() {  							fmt.println("\t-t     To: Filter up to and NOT including a specific time.")  							fmt.println("\t-f     From: Filter from and including a specific time.")  							fmt.println("\t-i     In: Filter to inside a specific year, month, etc.") +							fmt.println("\t-s     Substring: Case sensitive filter based on event names.")  							fmt.println("\t-v     Verbose: Prints more info.")  							fmt.println("\t-h     Help: Show this screen.") @@ -100,7 +105,11 @@ main :: proc() {  				filters |= {.IN}  				fmt.println("IN filter set up from", momentToString(in_filter.time), "to", momentToString(in_filter_out.time))  				parsing = .NONE -				 +			case .SUBSTRING: +				substring = arg +				fmt.printfln("SUBSTRING filter set to \"{}\"", substring) +				filters |= {.SUBSTRING} +				parsing = .NONE  		}  	} @@ -119,23 +128,29 @@ main :: proc() {  		if ok {  			hours : f64 = 0  			for each_block in timeblocks { -				if verbose do fmt.println("Timeblock:", timeblockToString(each_block)) +				if verbose do fmt.println("Block:", timeblockToString(each_block))  				pass := true  				if .FROM in filters {  					pass_from := greatEq(each_block.start, from_filter.time) -					if verbose do if !pass_from do fmt.println("    FILTERED! By From filter") +					if verbose do if !pass_from do fmt.println(" └ FILTERED! By From filter.")  					pass &= pass_from  				}  				if .TO in filters {  					pass_to := lessEq(each_block.start, to_filter.time) -					if verbose do if !pass_to do fmt.println("    FILTERED! By To filter") +					if verbose do if !pass_to do fmt.println(" └ FILTERED! By To filter.")  					pass &= pass_to  				}  				if .IN in filters {  					pass_in := lessEq(in_filter.time, each_block.start) && lessEq(each_block.start, in_filter_out.time) -					if verbose do if !pass_in do fmt.println("    FILTERED! By In filter: ") +					if verbose do if !pass_in do fmt.println(" └ FILTERED! By In filter.")  					pass &= pass_in  				} +				if .SUBSTRING in filters { +					pass_substring := strings.contains(each_block.title, substring) +					if verbose do if !pass_substring do fmt.println(" └ FILTERED! By Substring filter.") +					pass &= pass_substring +				} +				//if verbose do fmt.printf("\n")  				if !pass do continue diff --git a/test-data.ics b/test-data.ics index 97dc5e8..08218da 100644 --- a/test-data.ics +++ b/test-data.ics @@ -30,7 +30,7 @@ DTSTAMP:20250809T003314Z  DTSTART;TZID=Europe/Oslo:20250809T001000  DTEND;TZID=Europe/Oslo:20250809T022500  SEQUENCE:0 -SUMMARY:Test +SUMMARY:Test stuff  STATUS:CONFIRMED  END:VEVENT  BEGIN:VEVENT @@ -39,7 +39,7 @@ DTSTAMP:20250811T003901Z  DTSTART;TZID=Europe/Oslo:20250811T020000  DTEND;TZID=Europe/Oslo:20250811T023000  SEQUENCE:0 -SUMMARY:Test +SUMMARY:Testing things  STATUS:CONFIRMED  END:VEVENT  BEGIN:VEVENT @@ -48,7 +48,7 @@ DTSTAMP:20250811T110447Z  DTSTART;TZID=Europe/Oslo:20250811T123000  DTEND;TZID=Europe/Oslo:20250811T130000  SEQUENCE:0 -SUMMARY:Test +SUMMARY:Testidge confirmed beyond belief  STATUS:CONFIRMED  END:VEVENT  BEGIN:VEVENT @@ -57,7 +57,7 @@ DTSTAMP:20250812T215300Z  DTSTART;TZID=Europe/Oslo:20250812T220000  DTEND;TZID=Europe/Oslo:20250812T233000  SEQUENCE:0 -SUMMARY:Test +SUMMARY:Testinator  STATUS:CONFIRMED  END:VEVENT  BEGIN:VEVENT @@ -66,7 +66,7 @@ DTSTAMP:20250814T022625Z  DTSTART;TZID=Europe/Oslo:20250814T025000  DTEND;TZID=Europe/Oslo:20250814T043000  SEQUENCE:0 -SUMMARY:Test +SUMMARY:Testinator 2: The Testening Returns  STATUS:CONFIRMED  END:VEVENT  BEGIN:VEVENT @@ -75,7 +75,7 @@ DTSTAMP:20250821T113931Z  DTSTART;TZID=Europe/Oslo:20250821T122000  DTEND;TZID=Europe/Oslo:20250821T132000  SEQUENCE:1 -SUMMARY:Test +SUMMARY:Testinator 3: The Grand Retesting  STATUS:CONFIRMED  END:VEVENT  BEGIN:VEVENT @@ -84,7 +84,7 @@ DTSTAMP:20250821T150315Z  DTSTART;TZID=Europe/Oslo:20250821T150000  DTEND;TZID=Europe/Oslo:20250821T164500  SEQUENCE:2 -SUMMARY:Test +SUMMARY:I don't even know  STATUS:CONFIRMED  END:VEVENT  BEGIN:VEVENT @@ -93,7 +93,7 @@ DTSTAMP:20250821T173406Z  DTSTART;TZID=Europe/Oslo:20250821T182000  DTEND;TZID=Europe/Oslo:20250821T193000  SEQUENCE:1 -SUMMARY:Test +SUMMARY:You wish these were funnier  STATUS:CONFIRMED  END:VEVENT  BEGIN:VEVENT @@ -101,7 +101,7 @@ UID:asdfasdfasdf@proton.me  DTSTAMP:20250901T203735Z  DTSTART;VALUE=DATE:20250830  SEQUENCE:0 -SUMMARY:Test +SUMMARY:THIS ONE SHOULD NOT SHOW UP AT ALL  STATUS:CONFIRMED  END:VEVENT  BEGIN:VEVENT @@ -110,7 +110,7 @@ DTSTAMP:20250908T183647Z  DTSTART;TZID=Europe/Oslo:20250908T201000  DTEND;TZID=Europe/Oslo:20250908T203000  SEQUENCE:1 -SUMMARY:Test +SUMMARY:But too bad, cuz they're not  STATUS:CONFIRMED  END:VEVENT  BEGIN:VEVENT @@ -119,7 +119,7 @@ DTSTAMP:20250910T150610Z  DTSTART;TZID=Europe/Oslo:20250910T153000  DTEND;TZID=Europe/Oslo:20250910T170000  SEQUENCE:0 -SUMMARY:Test +SUMMARY:Testsaw Ridge  STATUS:CONFIRMED  END:VEVENT  BEGIN:VEVENT @@ -129,7 +129,7 @@ DTSTART;TZID=Europe/Oslo:20250909T163000  DTEND;TZID=Europe/Oslo:20250909T171500  SEQUENCE:1  DESCRIPTION:Check start -SUMMARY:Test +SUMMARY:Test and Loathing in Las Testas  STATUS:CONFIRMED  END:VEVENT  BEGIN:VEVENT @@ -138,7 +138,7 @@ DTSTAMP:20250909T220109Z  DTSTART;TZID=Europe/Oslo:20250909T210000  DTEND;TZID=Europe/Oslo:20250909T220000  SEQUENCE:0 -SUMMARY:Test +SUMMARY:Testception  STATUS:CONFIRMED  END:VEVENT  BEGIN:VEVENT @@ -147,7 +147,7 @@ DTSTAMP:20250912T222527Z  DTSTART;TZID=Europe/Oslo:20250912T020000  DTEND;TZID=Europe/Oslo:20250912T053000  SEQUENCE:0 -SUMMARY:Test +SUMMARY:Testorininio  STATUS:CONFIRMED  END:VEVENT  END:VCALENDAR
\ No newline at end of file @@ -41,6 +41,7 @@ Timeblock :: struct {  	end   : Moment,  	value : f32,  	reason : string, +	title : string,  }  Fractionpair :: struct { @@ -92,7 +93,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)  								time_max(time_clamp(sub(planned_wrap, {0, 1, 0}), wrap, add(wrap, {0, 2, 0})), -									add(call, {0, 4, 0})), 1, ""} +									add(call, {0, 4, 0})), 1, "", ""}  									//  ^ Minimum 4 hour day ^  									// BUG: I think this is causing a bug where if the day ends at 6 and gets extended, @@ -358,8 +359,8 @@ timesplit :: proc(block: Timeblock, splitpoint: Moment) -> (first_half: Timebloc  			return  		} -	first_half = {block.start, splitpoint, block.value, block.reason} -	second_half = {splitpoint, block.end, block.value, block.reason} +	first_half = {block.start, splitpoint, block.value, block.reason, ""} +	second_half = {splitpoint, block.end, block.value, block.reason, ""}  	return  } @@ -445,6 +446,12 @@ importICS :: proc(path: string, verbose: bool = false) -> ([dynamic]Timeblock, b  			c.end.year = strconv.atoi(line[ll-15:ll-11])  		} +		if line[0:min(8, len(line))]=="SUMMARY:" { +			if verbose do fmt.println("Found a SUMMARY!") +			if verbose do fmt.println(line) +			ll := len(line) +			c.title = line[8:ll] +		}  		// TODO: This is checking if the years are 0 to make sure it hasn't read from  		//       from a line containing "DTSTART;VALUE" instead of "DTSTART;TZID" @@ -689,8 +696,8 @@ momentToString :: proc(moment: Moment) -> (output: string) {  }  timeblockToString :: proc(block: Timeblock) -> (output: string) {  	using block -	s: [3]string = {toString(start), " -> ", toString(end)} -	output = strings.concatenate(s[:]) +	s: [5]string = {} +	output = fmt.aprintf("%s -> %s  |  %0.3f hrs  |  %s", toString(start), toString(end), hourcount(block), title)  	return  }  toString :: proc{deltaToString, momentToString, timeblockToString} @@ -725,7 +732,7 @@ popBlock :: proc(workday: ^Workday, index: int, count: int = 1) {  		blocks[i] = blocks[i+count]  	}  	for i in len(blocks)-count-1..<len(blocks) { -		blocks[i] = {{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, 0, ""} +		blocks[i] = {{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, 0, "", ""}  	}  	total_timeblocks -= count  } |