hebdobot/review/stats.py

181 lines
5.1 KiB
Python

from dataclasses import dataclass
from datetime import datetime
import re
@dataclass
class ReviewData:
date: datetime
user_count: int
duration: int
class Board:
def __init__(self, datas={}):
self.datas = {}
self.init(datas)
def init(self, datas):
pass
def __repr__(self):
return " ".join([f"{key} ({value})" for key, value in self.datas.items()])
def __getitem__(self, key):
if key in self.datas:
return self.datas[key]
return 0
def position(self, key):
if key in self.datas:
return sorted(
self.datas, key=lambda x: self.datas[x]
).index(key) + 1
@property
def min(self):
if self.datas == {}:
return 0
return min(self.datas.keys())
@property
def max(self):
if self.datas == {}:
return 0
return max(self.datas.keys())
@property
def avg(self):
if self.datas == {}:
return 0
return self.sum / sum(self.datas.values())
@property
def sum(self):
result = 0
for data in self.datas:
result += self.datas[data] * data
return result
class UserBoard(Board):
def init(self, datas):
for data in datas:
if data.user_count is not None:
if data.user_count not in self.datas:
self.datas[data.user_count] = 0
self.datas[data.user_count] += 1
class DurationBoard(Board):
def init(self, datas):
for data in datas:
if data.duration is not None:
if data.duration not in self.datas:
self.datas[data.duration] = 0
self.datas[data.duration] += 1
class ReviewStats:
def __init__(self, filepath):
self.filepath = filepath
self.datas = []
self.users_board = None
self.durations_board = None
@property
def size(self):
return len(self.datas)
@property
def first(self):
return sorted(self.datas, key=lambda data: data.date)[0] if self.datas else None
@property
def biggest(self):
return (
sorted(self.datas, key=lambda data: data.user_count)[-1]
if self.datas
else None
)
@property
def min_users(self):
if self.datas == []:
return 0
return min(self.datas, key=lambda data: data.user_count).user_count
@property
def max_users(self):
if self.datas == []:
return 0
return max(self.datas, key=lambda data: data.user_count).user_count
@property
def avg_users(self):
if self.datas == []:
return 0
return sum([data.user_count for data in self.datas]) / self.size
@property
def min_duration(self):
if self.datas == []:
return 0
datas = [data for data in self.datas if data.duration is not None]
return min(datas, key=lambda data: data.duration).duration
@property
def max_duration(self):
if self.datas == []:
return 0
datas = [data for data in self.datas if data.duration is not None]
return max(datas, key=lambda data: data.duration).duration
@property
def avg_duration(self):
if self.datas == []:
return 0
datas = [data for data in self.datas if data.duration is not None]
return sum([data.duration for data in datas]) / len(datas)
def year_review(self, year):
return len([data for data in self.datas if data.date.year == year])
def load(self):
self.datas = []
try:
with open(self.filepath) as file_handle:
lines = file_handle.read().splitlines()
for line in lines:
if line.strip() != "":
datas = re.split(r"\s+", line)
if len(datas) == 2:
self.datas.append(
ReviewData(
datetime.strptime(datas[0], "%Y%m%d-%Hh%M"),
int(datas[1]),
None,
)
)
else:
self.datas.append(
ReviewData(
datetime.strptime(datas[0], "%Y%m%d-%Hh%M"),
int(datas[1]),
int(datas[2]) if datas[2]!="" else None,
)
)
except FileNotFoundError:
# no file, no stats
pass
self.users_board = UserBoard(self.datas)
self.durations_board = DurationBoard(self.datas)
def save(self):
with open(self.filepath, "w") as file_handle:
for data in self.datas:
file_handle.write(
f"{data.date.strftime('%Y%m%d-%Hh%M')}\t"
f"{data.user_count}\t{data.duration}\n"
)