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" )