From c129df28338644c43b0a202ff71e1ff61107e765 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Thu, 5 Sep 2024 14:41:50 +0200 Subject: WIP time2tex --- time2tex.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 time2tex.py (limited to 'time2tex.py') diff --git a/time2tex.py b/time2tex.py new file mode 100755 index 0000000..3244b8f --- /dev/null +++ b/time2tex.py @@ -0,0 +1,17 @@ +#!/bin/python3 +import sys + + +if __name__ == "__main__": + if len(sys.argv) != 2: + print("usage: time2tex ") + exit(1) + + input_file = sys.argv[1] + content = "" + with open(input_file, "r") as file: + content = file.read() + parsed = parse(content) + + + -- cgit v1.2.3 From ecf5a0fa969f37185de925e7607c7f6e7c6e1d51 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Thu, 5 Sep 2024 17:25:24 +0200 Subject: kinda working time overview script --- .gitignore | 1 + makefile | 2 + time.txt | 14 +++---- time2tex.py | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- timerep.tex | 2 +- 5 files changed, 125 insertions(+), 13 deletions(-) (limited to 'time2tex.py') diff --git a/.gitignore b/.gitignore index efdebb8..efae07a 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ *.d *.nav *.snm +*-SAVE-ERROR # output files *.pdf diff --git a/makefile b/makefile index 6c234ba..02c583e 100644 --- a/makefile +++ b/makefile @@ -12,3 +12,5 @@ LATEXMKFLAGS += -interaction=nonstopmode %.tex: %.txt ./time2tex.py $< > $@ +timerep.pdf: time.tex + diff --git a/time.txt b/time.txt index c80fabf..2d38f62 100644 --- a/time.txt +++ b/time.txt @@ -1,13 +1,13 @@ # : loek: 2024-09-02 1h4m repository scaffolding loek: 2024-09-03 25m repository scaffolding -loek: 2024-09-03 1h30m repository scaffolding / engine repository, unit testing -loek: 2024-09-04 1h30m repository scaffolding / latex example code -loek: 2024-09-04 50m poc / dynamic library linking test example -loek: 2024-09-04 45m repository scaffolding / visual studio code latex configuration -loek: 2024-09-04 20m repository scaffolding / visual studio code cmake configuration -loek: 2024-09-05 15m repository scaffolding / additional latex contributing guidelines +loek: 2024-09-03 1h30m repository scaffolding :: engine repository, unit testing +loek: 2024-09-04 1h30m repository scaffolding :: latex example code +loek: 2024-09-04 50m poc :: dynamic library linking test example +loek: 2024-09-04 45m repository scaffolding :: visual studio code latex configuration +loek: 2024-09-04 20m repository scaffolding :: visual studio code cmake configuration +loek: 2024-09-05 15m repository scaffolding :: additional latex contributing guidelines loek: 2024-09-05 1h40m project meeting +loek: 2024-09-05 1h24m time report script # vim:ft=cfg - diff --git a/time2tex.py b/time2tex.py index 3244b8f..6c8b097 100755 --- a/time2tex.py +++ b/time2tex.py @@ -1,17 +1,126 @@ #!/bin/python3 import sys +from datetime import datetime +def fmt_duration(sec): + mins = (sec + 59) // 60 # integer divide, round up + out = [] -if __name__ == "__main__": - if len(sys.argv) != 2: - print("usage: time2tex ") - exit(1) + if mins == 0: + return "--" + + hour = mins // 60 + if hour > 0: + out.append("%02dh" % (hour, )) + mins = mins % 60 + + out.append("%02dm" % (mins, )) + + return "\\,".join(out) + +def fmt_member_overview(times): + members = {} + total_time = 0 + for time in times: + if not time["name"] in members: + members[time["name"]] = 0 + members[time["name"]] += time["duration"] + total_time += time["duration"] + print("""\\section{Member overview}\n +\\begin{table} +\\centering +\\begin{tabular}{lr} +\\toprule +\\textbf{Member} & \\textbf{Tracked}\\\\ +\\midrule""") + for name, tracked in members.items(): + print(f"{name} & {fmt_duration(tracked)}\\\\") + print("\\midrule") + print(f"& sum\\quad {fmt_duration(total_time)}\\\\") + print("""\\bottomrule +\\end{tabular} +\\caption{Tracked time per group member} +\\label{tab:time-member} +\\end{table}""") + +def duration2secs(duration): + out = 0 # output (seconds) + cur = 0 # current figure (unknown) + for c in duration: + if c.isdigit(): + cur = cur * 10 + int(c) + continue + if c == "h": + out += cur * 3600 + cur = 0 + continue + if c == "m": + out += cur * 60 + cur = 0 + continue + if c == "s": + out += cur * 1 + cur = 0 + continue + + raise Exception("invalid duration format") + if cur != 0: raise Exception("invalid duration format") + return out + +def line2data(line): + # parse fields from input string + data = {} + next = line.find(':') + data["name"] = line[0:next].strip() + line = line[next+1:].strip() + next = line.find(' ') + data["date"] = line[0:next].strip() + line = line[next+1:].strip() + next = line.find(' ') + data["duration"] = line[0:next].strip() + line = line[next+1:].strip() + data["description"] = line + # deserialize parsed fields + data["name"] = data["name"].title() + data["date"] = datetime.strptime(data["date"], '%Y-%m-%d') + data["duration"] = duration2secs(data["duration"]) + data["description"] = [el.strip() for el in data["description"].split("::")] + + return data + +def parse(content): + # split content at newlines + lines = content.split("\n") + out = [] + for i, line in enumerate(lines): + line = line.strip() + if line.startswith("#"): continue + if len(line) == 0: continue + + try: out.append(line2data(line)) + except Exception as e: raise Exception(f"line {i+1}: {e}") + return out + +def fmt(times): + fmt_member_overview(times) + +def main(): input_file = sys.argv[1] content = "" with open(input_file, "r") as file: content = file.read() - parsed = parse(content) + try: parsed = parse(content) + except Exception as e: + print(f"{input_file}: {e}") + exit(1) + fmt(parsed) + +if __name__ == "__main__": + if len(sys.argv) != 2: + print("usage: time2tex ") + exit(1) + main() diff --git a/timerep.tex b/timerep.tex index dfde932..7590217 100644 --- a/timerep.tex +++ b/timerep.tex @@ -5,7 +5,7 @@ \begin{document} -AHOIHJSAIDHOISAJDSAJDJAOIS +\input{time.tex} \end{document} -- cgit v1.2.3 From d0f5249d68a184fa565540bc01e32f1b2433b77a Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Fri, 6 Sep 2024 09:16:59 +0200 Subject: add weekly time overview to time report script --- time.txt | 1 + time2tex.py | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 92 insertions(+), 17 deletions(-) (limited to 'time2tex.py') diff --git a/time.txt b/time.txt index 3d01dd8..4ef1837 100644 --- a/time.txt +++ b/time.txt @@ -9,6 +9,7 @@ loek: 2024-09-04 20m repository scaffolding :: visual studio code cmake configur loek: 2024-09-05 15m repository scaffolding :: additional latex contributing guidelines loek: 2024-09-05 1h40m project meeting loek: 2024-09-05 1h24m time report script +loek: 2024-09-06 55m time report script max: 2024-09-04 1h30m installing and configuring latex max: 2024-09-04 2h reading project info diff --git a/time2tex.py b/time2tex.py index 6c8b097..1d0cd90 100755 --- a/time2tex.py +++ b/time2tex.py @@ -1,6 +1,6 @@ #!/bin/python3 import sys -from datetime import datetime +from datetime import datetime, timedelta def fmt_duration(sec): mins = (sec + 59) // 60 # integer divide, round up @@ -18,7 +18,12 @@ def fmt_duration(sec): return "\\,".join(out) +def fmt_percentage(fac): + return f"{{\\footnotesize\\itshape({round(fac * 100)}\\%)}}" + def fmt_member_overview(times): + # calculations + out = "" members = {} total_time = 0 for time in times: @@ -26,22 +31,84 @@ def fmt_member_overview(times): members[time["name"]] = 0 members[time["name"]] += time["duration"] total_time += time["duration"] - print("""\\section{Member overview}\n -\\begin{table} -\\centering -\\begin{tabular}{lr} -\\toprule -\\textbf{Member} & \\textbf{Tracked}\\\\ -\\midrule""") + + # begin table + out += r"\begin{table}\centering" + out += r"\begin{tabular}{lr@{~}l}\toprule" + out += r"\textbf{Member} & \textbf{Tracked} &\\\midrule{}" + + # member overview for name, tracked in members.items(): - print(f"{name} & {fmt_duration(tracked)}\\\\") - print("\\midrule") - print(f"& sum\\quad {fmt_duration(total_time)}\\\\") - print("""\\bottomrule -\\end{tabular} -\\caption{Tracked time per group member} -\\label{tab:time-member} -\\end{table}""") + out += f"{name} & {fmt_duration(tracked)} & {fmt_percentage(tracked / total_time)}\\\\" + out += r"\midrule{}" + + # sum + out += f"&{fmt_duration(total_time)}&\\\\" + + # end table + out += r"\bottomrule\end{tabular}" + out += r"\caption{Tracked time per group member}\label{tab:time-member}" + out += r"\end{table}" + + return out + +def fmt_weekly_overview(times): + # calculations + out = "" + weeks = [] + member_totals = {} + total_time = sum(time["duration"] for time in times) + members = list(set(time["name"] for time in times)) + time_start = min(time["date"] for time in times) + time_end = max(time["date"] for time in times) + week_start = time_start - timedelta(days=time_start.weekday()) # round down to nearest monday + week_end = time_end + timedelta(days=7-time_end.weekday()) + + week = week_start + week_num = 1 + while week < week_end: + week_times = [time for time in times if time["date"] >= week and time["date"] < (week + timedelta(days=7))] + + week_entry = { + "num": week_num, + "members": {}, + "total": sum(time["duration"] for time in week_times) + } + + for member in members: + week_entry["members"][member] = sum(time["duration"] for time in week_times if time["name"] == member) + + weeks.append(week_entry) + week_num += 1 + week += timedelta(days=7) + for member in members: + member_totals[member] = sum(time["duration"] for time in times if time["name"] == member) + + # begin table + out += r"\begin{table}\centering" + out += f"\\begin{{tabular}}{{l{'r@{~}l' * len(members)}@{{\\qquad}}r}}\\toprule" + out += r"\textbf{Week\#}" + for member in members: + out += f"&\\textbf{{{member}}}&" + out += r"&\textbf{Subtotal}\\\midrule{}" + + for entry in weeks: + out += f"{entry['num']}" + for member in members: + out += f"&{fmt_duration(entry['members'][member])}&{fmt_percentage(entry['members'][member] / entry['total'])}" + out += f"&{fmt_duration(entry['total'])}\\\\" + + out += r"\midrule{}" + for member in members: + out += f"&{fmt_duration(member_totals[member])}&{fmt_percentage(member_totals[member] / total_time)}" + out += f"&{fmt_duration(total_time)}\\\\" + + # end table + out += r"\bottomrule\end{tabular}" + out += r"\caption{Tracked time per week}\label{tab:time-weekly}" + out += r"\end{table}" + + return out def duration2secs(duration): out = 0 # output (seconds) @@ -103,7 +170,14 @@ def parse(content): return out def fmt(times): - fmt_member_overview(times) + # TODO: Task overview + print(f""" +\\section{{Overviews}}\n +\\subsection{{Members}}\n +{fmt_member_overview(times)} +\\subsection{{Weekly}}\n +{fmt_weekly_overview(times)} +""") def main(): input_file = sys.argv[1] -- cgit v1.2.3