2024-08-10 10:45:44 +01:00
|
|
|
"""Store matching history"""
|
|
|
|
import os
|
2024-08-10 15:12:14 +01:00
|
|
|
from datetime import datetime
|
2024-08-10 10:45:44 +01:00
|
|
|
from schema import Schema, And, Use, Optional
|
2024-08-10 10:55:09 +01:00
|
|
|
from typing import Protocol
|
2024-08-10 10:58:31 +01:00
|
|
|
import files
|
2024-08-10 15:12:14 +01:00
|
|
|
import copy
|
2024-08-10 10:45:44 +01:00
|
|
|
|
2024-08-10 15:12:14 +01:00
|
|
|
_FILE = "history.json"
|
|
|
|
|
|
|
|
# Warning: Changing any of the below needs proper thought to ensure backwards compatibility
|
|
|
|
_DEFAULT_DICT = {
|
|
|
|
"history": {},
|
|
|
|
"matchees": {}
|
|
|
|
}
|
|
|
|
_TIME_FORMAT = "%a %b %d %H:%M:%S %Y"
|
|
|
|
_SCHEMA = Schema(
|
|
|
|
{
|
|
|
|
Optional("history"): {
|
|
|
|
Optional(str): { # a datetime
|
|
|
|
"groups": [
|
|
|
|
{
|
|
|
|
"members": [
|
|
|
|
# The ID of each matchee in the match
|
|
|
|
And(Use(int))
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Optional("matchees"): {
|
|
|
|
Optional(str): {
|
|
|
|
Optional("matches"): {
|
|
|
|
# Matchee ID and Datetime pair
|
|
|
|
Optional(str): And(Use(str))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
2024-08-10 10:45:44 +01:00
|
|
|
|
|
|
|
|
2024-08-10 10:55:09 +01:00
|
|
|
class Member(Protocol):
|
|
|
|
@property
|
|
|
|
def id(self) -> int:
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2024-08-10 15:12:14 +01:00
|
|
|
def ts_to_datetime(ts: str) -> datetime:
|
|
|
|
"""Convert a ts to datetime using the history format"""
|
|
|
|
return datetime.strptime(ts, _TIME_FORMAT)
|
|
|
|
|
|
|
|
|
|
|
|
def validate(dict: dict):
|
|
|
|
"""Initialise and validate the history"""
|
|
|
|
_SCHEMA.validate(dict)
|
|
|
|
|
|
|
|
|
2024-08-10 10:45:44 +01:00
|
|
|
class History():
|
2024-08-10 15:12:14 +01:00
|
|
|
def __init__(self, data: dict = _DEFAULT_DICT):
|
|
|
|
"""Initialise and validate the history"""
|
|
|
|
validate(data)
|
|
|
|
self.__dict__ = copy.deepcopy(data)
|
2024-08-10 10:45:44 +01:00
|
|
|
|
|
|
|
@property
|
2024-08-10 15:12:14 +01:00
|
|
|
def history(self) -> list[dict]:
|
|
|
|
return self.__dict__["history"]
|
2024-08-10 10:45:44 +01:00
|
|
|
|
|
|
|
@property
|
2024-08-10 10:55:09 +01:00
|
|
|
def matchees(self) -> dict[str, dict]:
|
2024-08-10 10:45:44 +01:00
|
|
|
return self.__dict__["matchees"]
|
|
|
|
|
|
|
|
def save(self) -> None:
|
|
|
|
"""Save out the history"""
|
2024-08-10 15:12:14 +01:00
|
|
|
files.save(_FILE, self.__dict__)
|
|
|
|
|
|
|
|
def oldest(self) -> datetime:
|
|
|
|
"""Grab the oldest timestamp in history"""
|
|
|
|
if not self.history:
|
|
|
|
return None
|
|
|
|
times = (ts_to_datetime(dt) for dt in self.history.keys())
|
|
|
|
return sorted(times)[0]
|
|
|
|
|
|
|
|
def log_groups_to_history(self, groups: list[list[Member]], ts: datetime = datetime.now()) -> None:
|
|
|
|
"""Log the groups"""
|
|
|
|
tmp_history = History(self.__dict__)
|
|
|
|
ts = datetime.strftime(ts, _TIME_FORMAT)
|
|
|
|
|
|
|
|
# Grab or create the hitory item for this set of groups
|
|
|
|
history_item = {}
|
|
|
|
tmp_history.history[ts] = history_item
|
|
|
|
history_item_groups = []
|
|
|
|
history_item["groups"] = history_item_groups
|
2024-08-10 10:45:44 +01:00
|
|
|
|
2024-08-10 10:55:09 +01:00
|
|
|
for group in groups:
|
2024-08-10 15:12:14 +01:00
|
|
|
|
|
|
|
# Add the group data
|
|
|
|
history_item_groups.append({
|
|
|
|
"members": list(m.id for m in group)
|
2024-08-10 10:55:09 +01:00
|
|
|
})
|
2024-08-10 15:12:14 +01:00
|
|
|
|
|
|
|
# Update the matchee data with the matches
|
2024-08-10 10:55:09 +01:00
|
|
|
for m in group:
|
2024-08-10 15:12:14 +01:00
|
|
|
matchee = tmp_history.matchees.get(str(m.id), {})
|
|
|
|
matchee_matches = matchee.get("matches", {})
|
|
|
|
|
2024-08-10 10:55:09 +01:00
|
|
|
for o in (o for o in group if o.id != m.id):
|
2024-08-10 15:12:14 +01:00
|
|
|
matchee_matches[str(o.id)] = ts
|
2024-08-10 10:55:09 +01:00
|
|
|
|
2024-08-10 15:12:14 +01:00
|
|
|
matchee["matches"] = matchee_matches
|
|
|
|
tmp_history.matchees[str(m.id)] = matchee
|
2024-08-10 10:55:09 +01:00
|
|
|
|
2024-08-10 15:12:14 +01:00
|
|
|
# Validate before storing the result
|
|
|
|
validate(self.__dict__)
|
|
|
|
self.__dict__ = tmp_history.__dict__
|
2024-08-10 10:45:44 +01:00
|
|
|
|
2024-08-10 15:12:14 +01:00
|
|
|
def save_groups_to_history(self, groups: list[list[Member]]) -> None:
|
|
|
|
"""Save out the groups to the history file"""
|
|
|
|
self.log_groups_to_history(groups)
|
|
|
|
self.save()
|
2024-08-10 10:45:44 +01:00
|
|
|
|
|
|
|
|
2024-08-10 15:12:14 +01:00
|
|
|
def load() -> History:
|
|
|
|
"""Load the history"""
|
|
|
|
return History(files.load(_FILE) if os.path.isfile(_FILE) else _DEFAULT_DICT)
|