ztats.py (4515B)
1 #!/bin/python 2 3 # Work log / statistics script. 4 # Replaced by 'wlog', or 'work'... 5 6 import sys 7 import re 8 import json 9 import datetime 10 from subprocess import call 11 12 ### TODO ### 13 # The 'sloppy' syntax is unnecessarily complicated to implement. 14 # Redesign it and stick to the following syntax: 15 # 16 # add [w=<week>] [d=<day>] <cat> <time><h/m> <info> , [w=<week>] [d=<day>] <newcat> <newtime><h/m> <newinfo> 17 ############ 18 19 # Initialize 20 datafile = "/home/vh/ntnu/workstats.json" 21 stats = [] 22 cats = [] 23 currweek = datetime.datetime.now().isocalendar()[1] 24 currday = datetime.datetime.now().isocalendar()[2] 25 26 27 # Read log file 28 with open(datafile, 'r+') as f: 29 txtdata = f.read() 30 if txtdata != "": 31 stats = json.loads(txtdata) 32 for entry in stats: 33 if entry["cat"] not in cats: 34 cats.append(entry["cat"]) 35 f.close() 36 37 # Available commands 38 def add(args): 39 entry = { 40 "week": currweek, 41 "day": currday 42 } 43 44 timescale=1 45 # search for variations of the word 'hours' and set timescale if present: 46 pattern = re.compile("^(\d*)h$|(\d*)hrs|(\d*)hours") 47 for a in args: 48 match = pattern.search(a) 49 if match: 50 timescale=60 51 if match.group(1): 52 entry["time"] = timescale*int(match.group(1)) 53 args.remove(a) 54 55 # search for manual overrides of the week or day: 56 pattern = re.compile("(?:week=|w=)(?:(\d+)|last)") 57 for a in args: 58 match = pattern.search(a) 59 if match: 60 print("match {}".format(match.group(0))) 61 print("match {}".format(match.group(1))) 62 if match.group(1) == "last": 63 entry["week"] -= 1 64 else: 65 entry["week"]=match.group(1) 66 args.remove(a) 67 #break 68 69 pattern = re.compile("(?:day=|d=)(\d)+") 70 for a in args: 71 match = pattern.search(a) 72 if match: 73 entry["day"]=match.group(1) 74 args.remove(a) 75 #break 76 # The reason for removing the breaks here is that I want the ability to 'override the overrides' 77 # When add is called recursively, it is called using w=<previous week> and d=<previous day>, 78 # so to be able to override these, I have to read the entire args list and use the last w and d. 79 80 # Search for time, if it is not already set: 81 if "time" not in entry: 82 pattern = re.compile("(\d+)") 83 for a in args: 84 match = pattern.search(a) 85 if match: 86 entry["time"]=timescale*int(match.group(1)) 87 args.remove(a) 88 break 89 90 # Use the remaining text as categories and information 91 for i, a in enumerate(args): 92 # If comma present, add new tasks recursively: 93 if a == ",": 94 args.remove(a) 95 print(args[i:]) 96 add(["w={}", "d={}".format(entry["week"], entry["day"])]+args[i:]) 97 break 98 else: 99 if "cat" not in entry: 100 entry["cat"] = a 101 cats.append(a) 102 if "info" not in entry: 103 entry["info"] = a 104 else: 105 entry["info"] +=" " + a 106 args.remove(a) 107 108 stats.append(entry) 109 print("Entry added for category '{}'.".format(entry["cat"])) 110 111 def save(args): 112 with open(datafile, 'w') as f: 113 f.write(json.dumps(stats)) 114 f.close() 115 116 def date(args): 117 print("Current week: {}".format(currweek)) 118 print(datetime.datetime.now()) 119 120 def raw(args): 121 print(stats) 122 123 def clear(args): 124 call(["clear"]) 125 126 def show(args): 127 time_by_cat = {} 128 # init 129 for c in cats: 130 time_by_cat[c] = 0 131 132 # calculate time spent on each category 133 for entry in stats: 134 time_by_cat[entry["cat"]] += entry["time"] 135 136 print("\nTotal time spent on:") 137 for cat in time_by_cat: 138 print("{:>10}:{:>9.0f}h {}m".format(cat, time_by_cat[cat]//60, time_by_cat[cat]%60)) 139 140 def hlp(args): 141 print("read the script lol") 142 143 def exit(args): 144 with open(datafile, 'w') as f: 145 f.write(json.dumps(stats)) 146 f.close() 147 148 options = { 149 "add":add, 150 "date":date, 151 "raw":raw, 152 "clear":clear, 153 "save":save, 154 "show":show, 155 "help":hlp, 156 "exit":exit, 157 } 158 159 cmd = "" 160 161 while(cmd != "exit"): 162 cmd = input("> ") 163 args = cmd.split() 164 if args[0] in options: 165 options[args[0]](args[1:]) 166 else: 167 print("Invalid command. Type 'help' for available commands.") 168