eaapi/eaapi/server/model.py

202 lines
6.0 KiB
Python

from dataclasses import dataclass
import eaapi
class Model:
def __init__(self, gamecode: str, dest: str, spec: str, rev: str, datecode: str):
self._gamecode = gamecode
self._dest = dest
self._spec = spec
self._rev = rev
self._datecode = datecode
@classmethod
def from_model_str(cls, model: str) -> "Model":
return cls(*eaapi.parse_model(model))
@property
def gamecode(self):
return self._gamecode
@property
def dest(self):
return self._dest
@property
def spec(self):
return self._spec
@property
def rev(self):
return self._rev
@property
def datecode(self):
return int(self._datecode)
@property
def year(self):
return int(self._datecode[:4])
@property
def month(self):
return int(self._datecode[4:6])
@property
def day(self):
return int(self._datecode[6:8])
@property
def minor(self):
return int(self._datecode[8:10])
def __hash__(self):
return hash(str(self))
def __eq__(self, other):
if not isinstance(other, Model):
return False
return str(other) == str(self)
def __str__(self):
return f"{self.gamecode}:{self.dest}:{self.spec}:{self.rev}:{self.datecode}"
def __repr__(self):
return f"<Model {self} at 0x{id(self):016X}>"
@dataclass
class DatecodeMatcher:
year: int | None = None
month: int | None = None
day: int | None = None
minor: int | None = None
@classmethod
def from_str(cls, datecode: str):
if len(datecode) != 10 or not datecode.isdigit():
raise ValueError("Not a valid datecode")
return cls(
int(datecode[0:4]),
int(datecode[4:6]),
int(datecode[6:8]),
int(datecode[8:10])
)
def _num_filters(self):
num = 0
if self.year is not None:
num += 1
if self.month is not None:
num += 1
if self.day is not None:
num += 1
if self.minor is not None:
num += 1
return num
def __lt__(self, other):
if self._num_filters() < other._num_filters():
return False
if self.minor is None and other.minor is not None:
return False
if self.day is None and other.day is not None:
return False
if self.month is None and other.month is not None:
return False
if self.year is None and other.year is not None:
return False
return True
def __hash__(self):
return hash(str(self))
def __str__(self):
year = self.year if self.year is not None else "----"
month = self.month if self.month is not None else "--"
day = self.day if self.day is not None else "--"
minor = self.minor if self.minor is not None else "--"
return f"{year:04}{month:02}{day:02}{minor:02}"
def matches(self, model):
if self.year is not None and model.year != self.year:
return False
if self.month is not None and model.month != self.month:
return False
if self.day is not None and model.day != self.day:
return False
if self.minor is not None and model.minor != self.minor:
return False
return True
@dataclass
class ModelMatcher:
gamecode: str | None = None
dest: str | None = None
spec: str | None = None
rev: str | None = None
datecode: list[DatecodeMatcher] | DatecodeMatcher | None = None
def _num_filters(self):
num = 0
if self.gamecode is not None:
num += 1
if self.dest is not None:
num += 1
if self.spec is not None:
num += 1
if self.rev is not None:
num += 1
if isinstance(self.datecode, list):
num += sum(i._num_filters() for i in self.datecode)
elif self.datecode is not None:
num += self.datecode._num_filters()
return num
def __lt__(self, other):
if self._num_filters() < other._num_filters():
return False
if self.datecode is None and other.datecode is not None:
return False
if self.rev is None and other.rev is not None:
return False
if self.spec is None and other.spec is not None:
return False
if self.dest is None and other.dest is not None:
return False
if self.gamecode is None and other.gamecode is not None:
return False
return True
def __hash__(self):
return hash(str(self))
def __str__(self):
gamecode = self.gamecode if self.gamecode is not None else "---"
dest = self.dest if self.dest is not None else "-"
spec = self.spec if self.spec is not None else "-"
rev = self.rev if self.rev is not None else "-"
datecode = self.datecode if self.datecode is not None else "-" * 10
if isinstance(self.datecode, list):
datecode = "/".join(str(i) for i in self.datecode)
if not datecode:
datecode = "-" * 10
return f"{gamecode:3}:{dest}:{spec}:{rev}:{datecode}"
def matches(self, model):
if self.gamecode is not None and model.gamecode != self.gamecode:
return False
if self.dest is not None and model.dest != self.dest:
return False
if self.spec is not None and model.spec != self.spec:
return False
if self.rev is not None and model.rev != self.rev:
return False
if isinstance(self.datecode, list):
return any(i.matches(model) for i in self.datecode)
if self.datecode is not None:
return self.datecode.matches(model)
return True