experiments

All kinds of coding experiments
Log | Files | Refs | Submodules

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