From: Dustin Walde Date: Tue, 25 Apr 2023 17:15:08 +0000 (-0700) Subject: Add groups X-Git-Url: https://git.walde.dev/?a=commitdiff_plain;h=4d8426cac5385e098d7243b47084cec5eb8aa613;p=punch Add groups --- diff --git a/tt.py b/tt.py index c0cdbfb..62e1f47 100755 --- a/tt.py +++ b/tt.py @@ -12,10 +12,15 @@ import time from typing import ( Dict, + Iterable, List, + Optional, + Tuple, + Union, ) -TimeEntries = Dict[str,List[List[str]]] +GroupNode = Tuple[str,List[Iterable['GroupNode']]] +TimeEntries = Dict[str,List[Union[List[str],GroupNode]]] TS_PATH='/home/users/.local/share/dwalde/time-sheet.csv' @@ -69,28 +74,61 @@ def list_status(entries: TimeEntries): ''' Print each punched in category, followed by the rest. ''' - cats = list(entries.keys()) - cats.sort() - - outs = [] - print("In:") - for cat in cats: - if entries[cat][-1][0] == 'in': - list_category(entries, cat) - else: - outs.append(cat) - - if len(cats) == len(outs): - print("No categories punched in.") - - if len(outs) > 0: - print("") - print("Out:") - print(f"({outs[0]}: {entries[outs[0]][0][1]})", end="") - for i in range(1, len(outs)): - cat = outs[i] - print(f", ({outs[i]}: {entries[outs[i]][0][1]})", end="") - print("") + stack = [(entries['tree'], -1)] + while len(stack) > 0: + item, depth = stack.pop() + group_id = item[0] + children = item[1] + if depth >= 0: + print("\t"*depth, end='') + text = "" + if group_id in entries: + name = entries[group_id][0][1] + last = entries[group_id][-1] + if last[0] == 'in': + text = f"\t punched in at {last[1]}" + print(group_id + ":\t" + name + " " + text) + else: + name = entries['groups'][group_id][0] + print(name) + for child in reversed(children): + stack.append((child, depth+1)) + + +def load_group_hierarchy(entries: TimeEntries): + groups = [] + tree = ('', []) + id_to_node = {'' : tree} + entries['groups'] = {} + if '' in entries: + for entry in entries['']: + if len(entry) < 2: + continue + if entry[0] == 'group': + groups.append(entry) + entries['groups'][entry[1]] = entry[2:] + for cat in entries.keys(): + if cat != '' and cat != 'groups': + groups.append([entries[cat][0][0]] + [cat] + entries[cat][0][1:]) + last_process = 0 + while len(groups) > 0 and last_process != len(groups): + skipped = [] + for group in groups: + parent = '' + if len(group) > 3: + parent = group[3] + if parent in id_to_node: + id_to_node[parent][1].append((group[1], [])) + id_to_node[group[1]] = id_to_node[parent][1][-1] + else: + skipped.append(group) + last_process = len(groups) + groups = skipped + + for v in id_to_node.values(): + v[1].sort() + + entries['tree'] = tree def load_file(): @@ -105,6 +143,7 @@ def load_file(): if row[0] not in entries: entries[row[0]] = [] entries[row[0]].append(row[1:]) + load_group_hierarchy(entries) except FileNotFoundError: pass return entries @@ -118,11 +157,13 @@ def save_file(entries: TimeEntries): with open(TS_PATH, 'w', encoding='utf-8') as file: writer = csv.writer(file) for category, items in entries.items(): + if category == 'tree' or category == 'groups': + continue for item in items: writer.writerow([category] + item) -def new_category(entries: TimeEntries, category_id: str, category_name: str): +def new_category(entries: TimeEntries, category_id: str, category_name: str, parent: Optional[str]): ''' Create a new category with name and id/abbreviation. ''' @@ -130,7 +171,24 @@ def new_category(entries: TimeEntries, category_id: str, category_name: str): print(f'{category_id} already created: {entries[category_id][0]}') exit(2) - append_entry([category_id, 'category', category_name]) + if parent is None: + parent = '' + + append_entry([category_id, 'category', category_name, parent]) + + +def new_group(entries: TimeEntries, group_id: str, + group_name: str, parent: Optional[str]): + if 'groups' in entries: + for group in entries['groups']: + if group[1] == group_id: + print(f'{group_id} alread exists.') + exit(2) + + if parent is None: + parent = '' + + append_entry(['', 'group', group_id, group_name, parent]) def punch(entries: TimeEntries, dir: str, category: str, args: List[str] = []): @@ -173,6 +231,8 @@ def try_punch_out(entries: TimeEntries) -> bool: category = None for cat, items in entries.items(): + if cat == '' or cat == 'groups' or cat == 'tree': + continue if items[-1][0] == 'in': if category is not None: print(f'At least two categories punched in ({category}, {cat}), please specify.') @@ -215,6 +275,8 @@ def query_data(entries: TimeEntries, args: List[str]): total_time = datetime.timedelta(seconds=0) for cat in categories: + if cat == '' or cat == 'groups' or cat == 'tree': + continue td = datetime.timedelta(seconds=0) punch_in = None @@ -282,10 +344,22 @@ def main(args): entries = load_file() if args[1] == 'new': - if len(args) < 4: - print('Missing args for new category: ') - exit(1) - new_category(entries, args[2], args[3]) + if args[2] == 'group': + if len(args) < 5: + print('Missing args for new group: []') + exit(1) + parent = None + if len(args) > 5: + parent = args[5] + new_group(entries, args[3], args[4], parent) + else: + if len(args) < 4: + print('Missing args for new category: []') + exit(1) + parent = None + if len(args) > 4: + parent = args[4] + new_category(entries, args[2], args[3], parent) elif args[1] == 'out': if len(args) < 3: