diff options
| author | dam <dam@gudinoff> | 2023-04-16 17:34:26 +0100 |
|---|---|---|
| committer | dam <dam@gudinoff> | 2023-04-16 17:34:26 +0100 |
| commit | 7ad87637467a4757accae3fd4ad09c7ddb0b289e (patch) | |
| tree | 74d026cea7ed45c28817760c9a643ded4bda3c68 /ttt.jai | |
| parent | 2a893df3b65bfd01e666c0df0498dba1694ebebe (diff) | |
| download | task-time-tracker-7ad87637467a4757accae3fd4ad09c7ddb0b289e.tar.zst task-time-tracker-7ad87637467a4757accae3fd4ad09c7ddb0b289e.zip | |
Ported all features to jai.
Diffstat (limited to 'ttt.jai')
| -rw-r--r-- | ttt.jai | 248 |
1 files changed, 120 insertions, 128 deletions
@@ -36,8 +36,12 @@ NAME_SIZE :: 72; // TODO Use this instead of Task.name.count ? APP_FOLDER_NAME :: ".task_time_tracker_v2"; // TODO Using _v2 to avoid erasing my work data. DB_FILE_NAME :: "database.bin"; AR_FILE_NAME :: "archive.csv"; - DB_FILE_SIGN_STR :: "TTT:B:02"; + +ASSERT_NOT_NULL :: "Parameter '%' is null."; +ASSERT_NOT_EMPTY :: "Parameter '%' is empty."; +ASSERT_NOT_CONTAIN :: "'%' does not contain '%'."; + SECONDS_IN_MINUTE :: cast(s64)60; SECONDS_IN_HOUR :: cast(s64)60*SECONDS_IN_MINUTE; SECONDS_IN_DAY :: cast(s64)24*SECONDS_IN_HOUR; @@ -181,8 +185,8 @@ number_size :: (number: s64, base: s64 = 10) -> s64 { // WIP TODO Ues compiler time code to see the auto bake being used... just for fun, once! :D truncate_string :: (str: string, length: s64, $encoding: Text_Encoding = .UTF8) -> length: s64 #no_abc { // TODO Should I use #no_abc ? - assert(str.data != null); - assert(str.count >= length); + assert(str.data != null, ASSERT_NOT_NULL, "str"); + assert(str.count >= length, "'str.count' should be equal or greater to 'length'."); data := str.data; count := str.count; @@ -236,40 +240,44 @@ is_empty_string :: (str: string) -> bool { // Prints, on row y and column x, the time using 5 characters centered on space. // Returns the result of a call to mvprintw. -mvprintw_time :: (y: s32, x: s32, time: s64, space: s32) -> int { +mvprintw_time :: (y: s32, x: s32, time: s64, space: s32) -> int { // BUG Setting a timer to 99.9y shows 100y. TIME_CHARS :: 5; assert(space >= TIME_CHARS); + mul_f64_s64 :: inline (a: float64, b: s64) -> s64 { + return cast(s64)(a * cast(float64)b); + } + left_padding := (space - TIME_CHARS) / 2; right_padding := space - TIME_CHARS - left_padding; - if (time < 0) { + if time < 0 { return mvprintw(y, x, "%*s - %*s", left_padding, "", right_padding, ""); } - else if (time == 0) { + else if time == 0 { return mvprintw(y, x, "%*s 0 %*s", left_padding, "", right_padding, ""); } - else if (time < SECONDS_IN_MINUTE) { + else if time < SECONDS_IN_MINUTE { return mvprintw(y, x, "%*s%3jds %*s", left_padding, "", time, right_padding, ""); } - else if (time < 100 * SECONDS_IN_HOUR) { + else if time < #run mul_f64_s64(100, SECONDS_IN_HOUR) { hours := time / SECONDS_IN_HOUR; minutes := (time - (hours * SECONDS_IN_HOUR) ) / SECONDS_IN_MINUTE; return mvprintw(y, x, "%*s%02jd:%02jd%*s", left_padding, "", hours, minutes, right_padding, ""); } - else if (time < xx (9999.5 * SECONDS_IN_DAY)) { + else if time < #run mul_f64_s64(9999.5, SECONDS_IN_DAY) { value := cast(float64) time / SECONDS_IN_DAY; decimals := - ifx time >= xx 99.95 * SECONDS_IN_DAY then 0 else - ifx time >= xx 9.995 * SECONDS_IN_DAY then 1 else + ifx time >= #run mul_f64_s64(99.95, SECONDS_IN_DAY) then 0 else + ifx time >= #run mul_f64_s64(9.995, SECONDS_IN_DAY) then 1 else 2; return mvprintw(y, x, "%*s%4.*fd%*s", left_padding, "", decimals, value, right_padding, ""); } - else if (time < xx (9999.5 * SECONDS_IN_YEAR)) { + else if time < #run mul_f64_s64(9999.5, SECONDS_IN_YEAR) { value := cast(float64) time / SECONDS_IN_YEAR; decimals := - ifx time >= xx 99.95 * SECONDS_IN_YEAR then 0 else - ifx time >= xx 9.995 * SECONDS_IN_YEAR then 1 else + ifx time >= #run mul_f64_s64(99.95, SECONDS_IN_YEAR) then 0 else + ifx time >= #run mul_f64_s64(9.995, SECONDS_IN_YEAR) then 1 else 2; return mvprintw(y, x, "%*s%4.*fy%*s", left_padding, "", decimals, value, right_padding, ""); } @@ -310,7 +318,7 @@ contains_task :: inline (db: Database, task: *Task) -> bool { // Adds a task to the database and returns it. // If necessary, expands database capacity. add_task :: (db: *Database, task: Task = .{}) -> task: *Task { - assert(db != null, "Parameter 'db' is null."); + assert(db != null, ASSERT_NOT_NULL, "db"); array_add(*db.tasks, task); for * db.total_times { @@ -324,10 +332,9 @@ add_task :: (db: *Database, task: Task = .{}) -> task: *Task { // If possible, shrinks the database capacity. // Returns success. delete_task :: (db: *Database, task: *Task) -> bool { - - assert(db != null); - assert(task != null); - assert(contains_task(db, task)); + assert(db != null, ASSERT_NOT_NULL, "db"); + assert(task != null, ASSERT_NOT_NULL, "task"); + assert(contains_task(db, task), ASSERT_NOT_CONTAIN, "db", "task"); // Remove task timer values from total timers. for task.times { @@ -387,9 +394,9 @@ delete_task :: (db: *Database, task: *Task) -> bool { // Moves task to index. // Index gets clamped to [0, db->count[. move_task_to_index :: (db: *Database, task: *Task, index: s64) { - assert(db != null, "Parameter 'db' is null."); - assert(task != null, "Parameter 'task' is null."); - assert(contains_task(db, task), "Database does not contain task."); + assert(db != null, ASSERT_NOT_NULL, "db"); + assert(task != null, ASSERT_NOT_NULL, "task"); + assert(contains_task(db, task), ASSERT_NOT_CONTAIN, "db", "task"); target_index := clamp(index, 0, db.tasks.count-1); target_task := *db.tasks[target_index]; @@ -430,7 +437,7 @@ move_task_to_index :: (db: *Database, task: *Task, index: s64) { // Updates the times on the active task (and adjusts database totals). update_times :: (db: *Database) { - assert(db != null); + assert(db != null, ASSERT_NOT_NULL, "db"); if db.active_idx < 0 return; @@ -467,7 +474,7 @@ update_times :: (db: *Database) { // Recalculates database totals. update_total_times :: (db: *Database) { - assert(db != null); + assert(db != null, ASSERT_NOT_NULL, "db"); totals: []s64 = db.total_times; memset(totals.data, 0, NUM_WEEK_DAYS * size_of(s64)); @@ -485,9 +492,9 @@ update_total_times :: (db: *Database) { // Resets the times of the provided task (and adjusts database totals). reset_task_times :: (db: *Database, task: *Task) { - assert(db != null); - assert(task != null); - assert(contains_task(db, task)); + assert(db != null, ASSERT_NOT_NULL, "db"); + assert(task != null, ASSERT_NOT_NULL, "task"); + assert(contains_task(db, task), ASSERT_NOT_CONTAIN, "db", "task"); // Make sure we sync before applying the changes. update_times(db); @@ -497,40 +504,36 @@ reset_task_times :: (db: *Database, task: *Task) { <<it = 0; } } -/* + // Sets the time on the day and task provided (and adjusts database totals). -void set_task_time(database_st *db, task_st *task, int day, int64_t time) { - assert(db != NULL); - assert(task != NULL); - assert(task >= db->tasks && task - db->tasks < db->count); +set_task_time :: (db: *Database, task: *Task, day: int, time: s64) { + assert(db != null, ASSERT_NOT_NULL, "db"); + assert(task != null, ASSERT_NOT_NULL, "task"); + assert(contains_task(db, task), ASSERT_NOT_CONTAIN, "db", "task"); // Make sure we sync before applying the changes. update_times(db); - int64_t *timer = &task->times[day]; - int64_t *total = &db->total_times[day]; - *total = sub_int64(*total, *timer); - *timer = time; - *total = add_int64(*total, *timer); + db.total_times[day] = add_int64(db.total_times[day], time - task.times[day]); + task.times[day] = time; } // Adds the time on the day and task provided (and adjusts database totals). -void add_task_time(database_st *db, task_st *task, int day, int64_t time) { - assert(db != NULL); - assert(task != NULL); - assert(task >= db->tasks && task - db->tasks < db->count); +add_task_time :: (db: *Database, task: *Task, day: int, time: s64) { + assert(db != null, ASSERT_NOT_NULL, "db"); + assert(task != null, ASSERT_NOT_NULL, "task"); + assert(contains_task(db, task), ASSERT_NOT_CONTAIN, "db", "task"); // Make sure we sync before applying the changes. update_times(db); - task->times[day] = add_int64(task->times[day], time); - db->total_times[day] = add_int64(db->total_times[day], time); + db.total_times[day] = add_int64(db.total_times[day], time); + task.times[day] = add_int64(task.times[day], time); } -*/ // Resets database to the initial state and deallocates all memory taken by tasks. reset_database :: (db: *Database) { - assert(db != null, "Parameter 'db' is null."); + assert(db != null, ASSERT_NOT_NULL, "db"); array_reset(*db.tasks); <<db = .{}; } @@ -538,7 +541,7 @@ reset_database :: (db: *Database) { // Stores data from database into binary file. // Returns success. store_database :: (db: Database, path: string) -> success: bool { - assert(xx path, "Parameter 'path' is empty."); + assert(xx path, ASSERT_NOT_EMPTY, "path"); // Open file. file, open_success := file_open(path, for_writing = true); // log_errors: bool = true @@ -558,8 +561,8 @@ store_database :: (db: Database, path: string) -> success: bool { // Loads data from binary file into database. // Returns success. load_database :: (db: *Database, path: string) -> success: bool { - assert(db != null, "Parameter 'db' is null."); - assert(xx path, "Parameter 'path' is empty."); + assert(db != null, ASSERT_NOT_NULL, "db"); + assert(xx path, ASSERT_NOT_EMPTY, "path"); // Open file. file, open_success := file_open(path); // log_errors: bool = true @@ -607,7 +610,7 @@ load_database :: (db: *Database, path: string) -> success: bool { // Exports data into CSV file. // Returns success. export_to_csv :: (db: Database, path: string) -> success: bool { - assert(xx path, "Parameter 'path' is empty."); + assert(xx path, ASSERT_NOT_EMPTY, "path"); // TODO Make sure (IN ALL PROCEDURES) we're not receiving an empty path. @@ -637,8 +640,8 @@ export_to_csv :: (db: Database, path: string) -> success: bool { // Returns success. import_from_csv :: (db: *Database, path: string) -> bool { // TODO Review code. - assert(db != null, "Parameter 'db' is null."); - assert(xx path, "Parameter 'path' is empty."); + assert(db != null, ASSERT_NOT_NULL, "db"); + assert(xx path, ASSERT_NOT_EMPTY, "path"); error_code: s64; // Check file size TODO Read based on file size @@ -750,6 +753,9 @@ import_from_csv :: (db: *Database, path: string) -> bool { // } } } + + // Adjust selected task. + if (db.selected_idx < 0) db.selected_idx = 0; return true; } @@ -757,7 +763,7 @@ import_from_csv :: (db: *Database, path: string) -> bool { // Appends task to the end of the CSV file. // Returns success. append_to_csv :: (task: Task, path: string) -> success: bool { - assert(xx path, "Parameter 'path' is empty."); + assert(xx path, ASSERT_NOT_EMPTY, "path"); file, file_success := file_open(path, true, true); defer file_close(*file); @@ -785,7 +791,7 @@ append_to_csv :: (task: Task, path: string) -> success: bool { // Selects task by index. // Index gets clamped to [0, db->count[. select_task_by_index :: (db: *Database, index: s64) { - assert(db != null); + assert(db != null, ASSERT_NOT_NULL, "db"); db.selected_idx = ifx db.tasks.count == 0 then -1 else ifx index < 0 then 0 else ifx index >= db.tasks.count then db.tasks.count - 1 else @@ -794,7 +800,7 @@ select_task_by_index :: (db: *Database, index: s64) { // Selects task by delta relative to currently selected task. select_task_by_delta :: (db: *Database, delta: s64) { - assert(db != null); + assert(db != null, ASSERT_NOT_NULL, "db"); // TODO I bet there's a better way to do this... maybe use a clamp or range or something. idx := ifx (delta > 0 && db.selected_idx > S64_MAX - delta) then S64_MAX else @@ -803,19 +809,22 @@ select_task_by_delta :: (db: *Database, delta: s64) { select_task_by_index(db, idx); } + + // Selects task. select_task :: (db: *Database, task: *Task) { - assert(db != null); - assert(task != null); - assert(task >= db.tasks.data && task - db.tasks.data < db.tasks.count); + assert(db != null, ASSERT_NOT_NULL, "db"); + assert(task != null, ASSERT_NOT_NULL, "task"); + assert(contains_task(db, task), ASSERT_NOT_CONTAIN, "db", "task"); db.selected_idx = task - db.tasks.data; } // Set active task. // Passing task as NULL de-activates any previously active task. set_active_task :: (db: *Database, task: *Task) { - assert(db != null); - assert(task == null || (task >= db.tasks.data && task <= *db.tasks[db.tasks.count-1])); // TODO Improve this check. + assert(db != null, ASSERT_NOT_NULL, "db"); + if task != null + assert(contains_task(db, task), ASSERT_NOT_CONTAIN, "db", "task"); update_times(db); db.active_idx = ifx (task == null) then -1 else task - db.tasks.data; } @@ -1160,7 +1169,7 @@ read_input_int :: (row: int, style: s32, message: string) -> value: int, success // Retuns true if user presses enter, false otherwise. read_enter_confirmation :: (row: int, style: int, message: string) -> bool { - assert(message.data != null); + assert(message.data != null, ASSERT_NOT_NULL, "message"); // TODO Improve this check? attron(xx style); move(xx row, 1); @@ -1451,93 +1460,76 @@ main :: () { delete_task(db, selected_task); trigger_autosave(); } -/* - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': { - if (selected_task == NULL) { - break; - } + + case #char "1"; #through; + case #char "2"; #through; + case #char "3"; #through; + case #char "4"; #through; + case #char "5"; #through; + case #char "6"; #through; + case #char "7"; + if (selected_task == null) continue; // Prepare position to input time operation. - int selected_day = key - '1'; - int input_width = layout->columns[L_DAYS_IDX + selected_day].width; - int input_pos_x = 1 + layout->columns[L_TITLE_IDX].width; - for (int col = 0; col < selected_day; col++) { - input_pos_x += 1 + layout->columns[L_DAYS_IDX + col].width; + selected_day := key - #char "1"; + input_width := layout.columns[L_DAYS_IDX + selected_day].width; + input_pos_x := 1 + layout.columns[L_TITLE_IDX].width; + + for 0..selected_day-1 { + input_pos_x += 1 + layout.columns[L_DAYS_IDX + it].width; } - input_pos_x++; + input_pos_x += 1; // Get input string. - read_input_to_string_buffer(selected_task_row, input_pos_x, action_style, input_width); - char *input = string_buffer; + input := read_input_string(selected_task_row, input_pos_x, action_style, input_width); // TODO Temp stringzes. // Abort if input if empty. - if (is_empty_string(input) == true) { - break; - } + if is_empty_string(input) continue; - // Search for assign '=' operator and discard everything before (if found). - char *assign_str = strchr(input, '='); - bool is_assign = assign_str != NULL; - if (is_assign == true) { - input = assign_str + 1; - } + // Search for assign '=' operator and discard everything before it. + assign_idx := find_index_from_left(input, "="); + is_assign := assign_idx >= 0; + if is_assign advance(*input, assign_idx + 1); // Try to parse a number and abort if it fails. - char *parser; - long double input_float = strtold(input, &parser); - if (parser == input) { - break; - } - input = parser; + input_float, parse_success := string_to_float64(input); + if parse_success == false continue; // Try to parse a character representing the time multiplier. - long double multiplier = 1.0; - for (int i=0; i < strlen(input); i++) { - char ch = input[i]; - if (ch == 'm' || ch == 'M') { - multiplier = SECONDS_IN_MINUTE; - break; - } - else if (ch == 'h' || ch == 'H') { - multiplier = SECONDS_IN_HOUR; - break; - } - else if (ch == 'd' || ch == 'D') { - multiplier = SECONDS_IN_DAY; - break; - } - else if (ch == 'y' || ch == 'Y') { - multiplier = SECONDS_IN_YEAR; - break; + multiplier: float64 = 1.0; + for 0..input.count-1 { + ch := to_lower(input[it]); + if ch == { + case #char "m"; + multiplier = xx SECONDS_IN_MINUTE; + break; + + case #char "h"; + multiplier = xx SECONDS_IN_HOUR; + break; + + case #char "d"; + multiplier = xx SECONDS_IN_DAY; + break; + + case #char "y"; + multiplier = xx SECONDS_IN_YEAR; + break; } } // Process input and check if it's valid. - long double input_time = input_float * multiplier; - bool is_result_valid = (input_time >= (long double)INT64_MIN && input_time <= (long double)INT64_MAX); - if (is_result_valid == false) { - break; - } + input_time := input_float * multiplier; + if (input_time > xx S64_MAX || input_time < xx S64_MIN) continue; // Apply changes. - int64_t time = input_time; - int day = (selected_day + FIRST_DAY_OF_WEEK) % NUM_WEEK_DAYS; - if (is_assign == true) { - set_task_time(db, selected_task, day, time); - } - else { - add_task_time(db, selected_task, day, time); - } + time := cast(s64)input_time; + day := (selected_day + FIRST_DAY_OF_WEEK) % NUM_WEEK_DAYS; + if is_assign set_task_time(db, selected_task, day, time); + else add_task_time(db, selected_task, day, time); + trigger_autosave(); - break; - } -*/ + case #char "m"; #through; case #char "M"; if selected_task == null continue; |
