feat(stats): add stats

This commit is contained in:
Pavel Korytov 2021-04-16 21:44:36 +03:00
parent 6ebf968c01
commit 2b4935ba77
5 changed files with 666 additions and 2 deletions

View file

@ -1,4 +1,6 @@
* My dotfiles
#+TITLE: My dotfiles
* Programs used
Deployed with [[https://yadm.io/][yadm]]
| Group | Program | Purpose | Status | Documented? | Notes |
@ -43,10 +45,17 @@ Deployed with [[https://yadm.io/][yadm]]
| misc | [[https://github.com/risacher/sunwait][sunwait]] | sunrise calculator | *active* | - | |
| misc | [[https://github.com/vergoh/vnstat][vnstat]] | traffic stats | *active* | - | |
* Some statistics
Run the following to show the pictures with reasonable width:
#+begin_src elisp :results none
(setq-local org-image-actual-width '(1024))
#+end_src
** History
[[./dot-stats/img/all.png]]
* Notes
- =M-u C-c C-v t= to tangle a particular block
- =M-u M-u C-c C-v t= to tangle a particular file
Uses yadm's =post_alt= hook to create symlinks

377
dot-stats/history.json Normal file
View file

@ -0,0 +1,377 @@
[
{
"title": "OS/Distro",
"elements": [
{
"name": "Manjaro",
"states": [
{
"startDate": "2020-08-24"
}
],
"color": "g"
},
{
"name": "Linux Mint",
"states": [
{
"startDate": "TODO 2018-03-12",
"endDate": "2020-08-24"
}
],
"color": "m"
},
{
"name": "Windows",
"states": [
{
"startDate": "TODO 2018-11-25",
"endDate": "2019-10-07",
"state": "dashed",
"hatchColor": "y",
"note": "Dual boot, rarely used"
},
{
"startDate": "2016-09-01",
"endDate": "TODO 2018-11-25"
}
],
"color": "b"
}
]
},
{
"title": "DE stuff",
"elements": [
{
"name": "KDE",
"color": "y",
"states": [
{
"startDate": "2018-03-12",
"endDate": "2018-08-01"
}
]
},
{
"name": "Cinnamon",
"color": "g",
"states": [
{
"startDate": "2018-08-01",
"endDate": "2020-05-08"
}
]
},
{
"name": "i3(-gaps)",
"color": "b",
"states": [
{
"startDate": "2020-05-08"
}
]
},
{
"name": "i3blocks",
"color": "b-l",
"states": [
{
"startDate": "2020-05-08",
"endDate": "2020-12-11"
}
]
},
{
"name": "polybar",
"color": "m",
"states": [
{
"startDate": "2020-12-11"
}
]
}
]
},
{
"title": "shell",
"elements": [
{
"name": "bash",
"color": "w",
"states": [
{
"startDate": "TODO 2018-03-12",
"endDate": "2020-09-09"
}
]
},
{
"name": "fish",
"color": "c",
"states": [
{
"startDate": "2020-09-09"
}
]
}
]
},
{
"title": "CLI tools",
"elements": [
{
"name": "ranger",
"states": [
{
"startDate": "2019-04-03",
"endDate": "2020-02-17"
}
],
"color": "y"
},
{
"name": "vifm",
"states": [
{
"startDate": "2020-02-17",
"endDate": "2020-11-11"
}
],
"color": "g"
},
{
"name": "tmux",
"states": [
{
"startDate": "2020-01-22"
}
],
"color": "b"
}
]
},
{
"title": "Office",
"elements": [
{
"name": "LaTeX",
"color": "b",
"states": [
{
"startDate": "2019-04-12"
}
]
},
{
"name": "Zathura",
"color": "c",
"states": [
{
"startDate": "2019-04-12"
}
]
},
{
"name": "OneNote",
"color": "m",
"states": [
{
"startDate": "2016-09-01",
"endDate": "2019-03-21"
}
]
}
]
},
{
"title": "Editor/IDE",
"elements": [
{
"name": "Emacs",
"color": "m",
"states": [
{
"startDate": "2020-10-12"
}
]
},
{
"name": "NeoVim",
"color": "g",
"states": [
{
"startDate": "2019-03-30",
"endDate": "2020-10-12"
}
]
},
{
"name": "Qt Creator",
"color": "y",
"states": [
{
"startDate": "2017-09-01",
"endDate": "2018-07-17"
},
{
"startDate": "2019-09-11",
"endDate": "2019-12-04"
}
]
},
{
"name": "Notepad++",
"color": "w",
"states": [
{
"startDate": "2017-09-01",
"endDate": "2018-05-25"
}
]
},
{
"name": "Various JetBrains",
"color": "c",
"states": [
{
"startDate": "2018-09-01",
"endDate": "2019-03-30"
}
]
},
{
"name": "DataGrip",
"color": "b",
"states": [
{
"startDate": "2020-02-01"
}
]
},
{
"name": "Jupyter (Notebook|Lab)",
"color": "r",
"states": [
{
"startDate": "2018-10-24",
"endDate": "2020-11-01"
},
{
"startDate": "2020-11-01",
"state": "dashed",
"note": "Mostly replaced by Org Mode",
"hatchColor": "w"
}
]
}
]
},
{
"title": "Browser",
"elements": [
{
"name": "Opera",
"color": "r",
"states": [
{
"startDate": "2018-09-01",
"endDate": "2019-02-01"
},
{
"startDate": "2019-09-01",
"endDate": "2020-02-11"
}
]
},
{
"name": "Chromium",
"states": [
{
"startDate": "2018-04-01",
"endDate": "2018-09-01"
}
],
"color": "c"
},
{
"name": "qutebrowser",
"color": "b",
"states": [
{
"startDate": "2020-02-11",
"endDate": "2020-12-20"
}
]
},
{
"name": "Vivaldi",
"color": "r-l",
"states": [
{
"startDate": "2019-02-01",
"endDate": "2019-09-01"
}
]
},
{
"name": "Firefox",
"color": "y",
"states": [
{
"startDate": "2017-05-14",
"endDate": "2018-04-01"
},
{
"startDate": "2020-12-20",
"state": "dashed",
"note": "+ Tridactyl",
"hatchColor": "k-l"
}
]
}
]
},
{
"title": "Misc",
"elements": [
{
"name": "ncmpcpp & mpd",
"color": "c",
"states": [
{
"startDate": "2020-07-26"
}
]
},
{
"name": "newsboat",
"color": "r",
"states": [
{
"startDate": "2021-01-22"
}
]
},
{
"name": "Mailspring",
"color": "g",
"states": [
{
"startDate": "TODO 2019-01-28",
"endDate": "2021-01-29"
}
]
},
{
"name": "notmuch",
"color": "b",
"states": [
{
"startDate": "2021-01-29"
}
]
}
]
}
]

255
dot-stats/history.org Normal file
View file

@ -0,0 +1,255 @@
#+TITLE: Program Usage History
#+PROPERTY: header-args:python :session *history*
#+PROPERTY: header-args:python+ :exports both
#+PROPERTY: header-args:python+ :tangle yes
#+PROPERTY: header-args:python+ :async yes
#+begin_src elisp :exports none
(setq-local org-image-actual-width '(1024))
#+end_src
#+RESULTS:
| 1024 |
* Init
#+begin_src python
from matplotlib import pyplot as plt
from matplotlib import dates as mdates
from pprint import pprint
from datetime import date, datetime
import copy
import json
import matplotlib as mpl
import numpy as np
import pandas as pd
mpl.rcParams['figure.dpi'] = 200
mpl.rcParams['figure.facecolor'] = '0.1'
mpl.rcParams['hatch.linewidth'] = 4.0
#+end_src
#+RESULTS:
#+begin_src python
plt.style.use('./palenight.mplstyle')
#+end_src
#+RESULTS:
** Colors
#+begin_src python
COLORS = {
'k': '#292d3e',
'r': '#f07178',
'g': '#c3e88d',
'y': '#ffcb6b',
'b': '#82aaff',
'm': '#c792ea',
'c': '#89ddff',
'w': '#d0d0d0',
'k-l': '#434758',
'r-l': '#ff8b92',
'g-l': '#ddffa7',
'y-l': '#ffe585',
'b-l': '#9cc4ff',
'm-l': '#e1acff',
'c-l': '#a3f7ff',
'w-l': '#ffffff'
}
#+end_src
#+RESULTS:
* Load data
** Read file
#+begin_src python
DATA = './history.json'
with open(DATA, 'r') as f:
data_o = json.load(f)
# pprint(data)
#+end_src
#+RESULTS:
** Some preprocessing
#+begin_src python
def preprocess_data(data):
data = copy.deepcopy(data)
for category in data:
for elem in category['elements']:
for state in elem['states']:
if 'TODO' in state['startDate']:
print(f'TODO in {elem["name"]} (startDate)')
state['startDate'] = state['startDate'].replace('TODO', '').strip()
state['startDate'] = datetime.strptime(state['startDate'], '%Y-%m-%d')
try:
if 'TODO' in state['endDate']:
print(f'TODO in {elem["name"]} (endDate)')
state['endDate'] = state['endDate'].replace('TODO', '').strip()
state['endDate'] = datetime.strptime(state['endDate'], '%Y-%m-%d')
except KeyError:
state['endDate'] = datetime.today()
try:
state['hatchColor'] = COLORS.get(state['hatchColor'], state['hatchColor'])
except KeyError:
pass
elem['states'].sort(key=lambda k: k['startDate'])
try:
elem['color'] = COLORS.get(elem['color'], elem['color'])
except KeyError:
pass
category['elements'].sort(key=lambda k: k['states'][0]['startDate'])
return data
data = preprocess_data(data_o)
#+end_src
#+RESULTS:
: TODO in Linux Mint (startDate)
: TODO in Windows (startDate)
: TODO in Windows (endDate)
: TODO in bash (startDate)
: TODO in Mailspring (startDate)
** Crop data
#+begin_src python
def crop_data(data, start_date):
data = copy.deepcopy(data)
for category in data:
for elem in category['elements']:
elem['states'] = [
state for state in elem['states']
if state['endDate'] >= start_date
]
for state in elem['states']:
if state['startDate'] <= start_date:
state['startDate'] = start_date
category['elements'] = [
element for element in category['elements']
if len(element['states']) > 0
]
data = [
category for category in data
if len(category['elements']) > 0
]
return data
data = crop_data(data, datetime(2017, 1, 1))
#+end_src
#+RESULTS:
* Plot one category
#+begin_src python
CAT_W = 0.3
def process_category(category, ax, is_last=True, notes=None):
ticks = list(range(0, -len(category['elements']), -1))
if notes is None:
notes = []
min_start_date = 10**9
for elem, k in zip(category['elements'], ticks):
for state in elem['states']:
start_date, end_date = mdates.date2num(state['startDate']), mdates.date2num(state['endDate'])
min_start_date = min(min_start_date, start_date)
kwargs = {}
kwargs['color'] = elem.get('color', None)
if state.get('state', None) == 'dashed':
kwargs['hatch'] = '//'
kwargs['edgecolor'] = state.get('hatchColor', 'y')
kwargs['lw'] = 0
note = state.get('note', None)
if note is not None:
notes.append(note)
stars = '*' * len(notes)
ax.text(end_date, k + CAT_W * 0.7, stars, size=15)
bars = ax.broken_barh(
[(start_date, end_date - start_date)],
(k - CAT_W, CAT_W * 2),
,**kwargs
)
ax.set_yticks(ticks)
ax.set_yticklabels([elem['name'] for elem in category['elements']])
ax.set_axisbelow(True)
ax.grid(True, alpha=0.25)
if not is_last:
ax.tick_params(axis='x', which='both', labelbottom=False, length=0)
else:
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
return notes
def plot_notes(fig, ax, notes, x=0.9, y = 0.03):
if len(notes) > 0:
notes_text = ''
for i, note in enumerate(notes):
notes_text += '*' * (i + 1) + ' ' + note + '\n'
ax.text(x, y, notes_text, transform=fig.transFigure, va='top', ha='right')
fig, ax = plt.subplots(figsize=(12, 3))
notes = process_category(data[0], ax)
ax.set_title(data[0]['title'])
plot_notes(fig, ax, notes)
notes
#+end_src
#+RESULTS:
:RESULTS:
| Dual boot, rarely used |
[[file:./.ob-jupyter/755e058676d772859fe9f7ed207011006268ac2b.png]]
:END:
* Plot all separately
#+begin_src python :display plain
def plot_category(category):
fig, ax = plt.subplots(figsize=(12, len(category['elements']) * 0.7 + 1))
notes = process_category(category, ax)
ax.set_title(category['title'])
plot_notes(fig, ax, notes)
return fig
def plot_separate(data):
for category in data:
fig = plot_category(category)
# fig.tight_layout()
fig.savefig(f'./img/{category["title"].replace("/", "-")}.png')
# plot_separate(data)
#+end_src
#+RESULTS:
* Plot all in one chart
#+begin_src python :file img/all.png
def plot_all(data):
fig, axes = plt.subplots(
len(data),
gridspec_kw={
'height_ratios': [len(datum['elements']) for datum in data]
},
figsize=(14, 11),
sharex=True
)
notes = []
for i, [datum, ax] in enumerate(zip(data, axes)):
is_last = i == len(data) - 1
notes = process_category(datum, ax, is_last=is_last, notes=notes)
ax.yaxis.set_label_position("right")
ax.set_ylabel(datum['title'], labelpad=16, rotation=270)
plot_notes(fig, ax, notes, y=0.09)
# fig.tight_layout()
fig.subplots_adjust(hspace=0.15)
plot_all(data)
#+end_src
#+RESULTS:
[[file:img/all.png]]

BIN
dot-stats/img/all.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

View file

@ -0,0 +1,23 @@
### FONT
text.color: D0D0D0
### AXES
axes.facecolor: 363B52
axes.edgecolor: FFFFFF
axes.labelcolor: FFFFFF
### TICKS
xtick.color: FFFFFF
ytick.color: FFFFFF
### GRIDS
grid.color: FFFFFF
### Legend
legend.facecolor: inherit
legend.edgecolor: C792EA
### FIGURE
figure.facecolor: 292D3E
savefig.facecolor: 292D3E