timetracker-report (3569B)
1 #!/usr/bin/env python3 2 import os 3 from datetime import datetime, timedelta 4 from math import floor 5 import subprocess 6 7 # HELPER FUNCTIONS ####################################################### 8 def filelocation(): 9 if (os.getenv("XDG_DATA_HOME")): 10 return os.getenv("XDG_DATA_HOME") + "/timetracker/data" 11 else: 12 return os.getenv("HOME") + "/.local/share/timetracker/data" 13 14 def timestring(secs): 15 secs /= 60 16 if (secs >= 60): 17 return str(floor(secs / 60)) + "h" + str(floor(secs % 60)).zfill(2) + \ 18 "m" 19 else: 20 return str(floor(secs % 60)) + "m" 21 22 # yellow and bold 23 def printHeading(text): 24 print("\033[33m\033[1m" + text + "\033[0m") 25 26 # example: data = [["firefox", 75], ["vim", 250], ...] 27 def printGraph(data): 28 # replace name with name and time in correct alignment 29 # 15 is enough space https://stackoverflow.com/questions/23534263/what-is-the-maximum-allowed-limit-on-the-length-of-a-process-name 30 for line in data: 31 line[0] = line[0].ljust(16, " ") + timestring(line[1]).rjust(5, " ") 32 33 width = 50; 34 # scale numbers on width 35 maximum = 0; 36 for line in data: 37 if (line[1] > maximum): maximum = line[1] 38 for line in data: 39 line[1] = round(line[1] / maximum * 50) if maximum != 0 else 0 40 41 # print the graph 42 for line in data: 43 bar = "" 44 if (line[1] == 0): bar = "▏" 45 else: bar = "▇" * line[1] 46 47 print(line[0] + " " + bar) 48 49 50 # READ AND PARSE FILE #################################################### 51 try: 52 datafile = open(filelocation(), "r") 53 except FileNotFoundError: 54 print("data is file not there (yet)") 55 exit(1) 56 57 # parse input file 58 days = {} 59 programs = [] 60 for line in datafile: 61 parts = line.split(","); 62 datestring = datetime.fromtimestamp(int(parts[0])).strftime("%Y-%m-%d") 63 if datestring not in days: 64 days[datestring] = {} 65 dayRef = days[datestring] 66 67 for part2 in parts[1:]: 68 # print(part2) 69 program = part2.split(":")[0] 70 ptime = int(part2.split(":")[1]) 71 if program not in programs: 72 programs.append(program) 73 if program in dayRef: 74 dayRef[program] += ptime 75 else: 76 dayRef[program] = ptime 77 78 79 # PRINT GRAPHS ########################################################### 80 # past week 81 printHeading("# past week") 82 tgIn = [] # graph input 83 for i in range(7): 84 day = (datetime.today() + timedelta(days=i-6)).strftime("%Y-%m-%d") 85 daySum = 0 86 if day in days: 87 for program in days[day]: 88 if program != "slock" and program != "standby": 89 daySum += days[day][program] 90 tgIn.append([day, daySum]) 91 printGraph(tgIn) 92 93 # today 94 today = datetime.today().strftime("%Y-%m-%d") 95 if today in days: 96 print() 97 printHeading("# today") 98 tgIn = [] # graph input 99 for program in sorted(days[today], key=lambda x: days[today][x], 100 reverse=True): 101 if days[today][program] >= 60: 102 tgIn.append([program, days[today][program]]) 103 printGraph(tgIn) 104 105 # average 106 print() 107 printHeading("# average") 108 # get total number of days 109 dayNum = (datetime.today() - \ 110 datetime.strptime(list(days.keys())[0], "%Y-%m-%d")).days + 1 111 tgIn = [] # graph input 112 for program in programs: 113 ptime = 0 114 for day in days: 115 for p in days[day]: 116 if p == program: 117 ptime += days[day][program] / dayNum 118 if ptime >= 60: 119 tgIn.append([program, ptime]); 120 tgIn = sorted(tgIn, key=lambda x: x[1], reverse=True) 121 printGraph(tgIn)