178 lines
4.9 KiB
Python
178 lines
4.9 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.values())
|
||
|
|
||
|
@property
|
||
|
def max(self):
|
||
|
if self.datas == []:
|
||
|
return 0
|
||
|
return max(self.datas.values())
|
||
|
|
||
|
@property
|
||
|
def avg(self):
|
||
|
if self.datas == []:
|
||
|
return 0
|
||
|
return self.sum / len(self.datas)
|
||
|
|
||
|
@property
|
||
|
def sum(self):
|
||
|
if self.datas == []:
|
||
|
return 0
|
||
|
return sum(self.datas.values())
|
||
|
|
||
|
|
||
|
class UserBoard(Board):
|
||
|
def init(self, datas):
|
||
|
for data in datas:
|
||
|
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 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]),
|
||
|
)
|
||
|
)
|
||
|
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, "wt") 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"
|
||
|
)
|