123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- from functools import cached_property
- import inspect
- import json
- from dataclasses import asdict, dataclass
- from typing import Optional
- from dataclass_wizard import JSONWizard
- from django.contrib.auth import get_user_model
- from locations.models import GeoLocation
- User = get_user_model()
- class ScrobbleLogDataEncoder(json.JSONEncoder):
- def default(self, o):
- return o.__dict__
- class ScrobbleLogDataDecoder(json.JSONDecoder):
- def default(self, o):
- return o.__dict__
- class JSONDataclass(JSONWizard):
- @property
- def asdict(self):
- return asdict(self)
- @property
- def json(self):
- return json.dumps(self.asdict)
- @dataclass
- class ScrobbleLogData(JSONDataclass):
- description: Optional[str] = None
- class LongPlayLogData(JSONDataclass):
- serial_scrobble_id: Optional[int]
- long_play_complete: bool = False
- class WithOthersLogData(JSONDataclass):
- with_user_ids: Optional[list[int]] = None
- with_names_str: Optional[list[str]] = None
- @property
- def with_names(self) -> list[str]:
- with_names = []
- if self.with_user_ids:
- with_names += [u.full_name for u in self.with_users if u]
- if self.with_names_str:
- with_names += [u for u in self.with_names_str]
- return with_names
- @property
- def with_users(self) -> list[User]:
- with_users = []
- if self.with_user_ids:
- with_users = [
- User.objects.filter(id=i).first() for i in self.with_user_ids
- ]
- return with_users
- @dataclass
- class BoardGameScoreLogData(JSONDataclass):
- user_id: Optional[int] = None
- name_str: str = ""
- bgg_username: str = ""
- color: Optional[str] = None
- character: Optional[str] = None
- team: Optional[str] = None
- score: Optional[int] = None
- win: Optional[bool] = None
- new: Optional[bool] = None
- @property
- def user(self) -> Optional[User]:
- user = None
- if self.user_id:
- user = User.objects.filter(id=self.user_id).first()
- return user
- @property
- def name(self) -> str:
- name = self.name_str
- if self.user_id:
- name = self.user.first_name
- return name
- def __str__(self) -> str:
- out = self.name
- if self.score:
- out += f" {self.score}"
- if self.color:
- out += f" ({self.color})"
- if self.win:
- out += f" [W]"
- return out
- @dataclass
- class BoardGameLogData(LongPlayLogData):
- serial_scrobble_id: Optional[int] = None
- long_play_complete: Optional[bool] = None
- players: Optional[list[BoardGameScoreLogData]] = None
- location: Optional[str] = None
- geo_location_id: Optional[int] = None
- difficulty: Optional[int] = None
- solo: Optional[bool] = None
- two_handed: Optional[bool] = None
- @cached_property
- def geo_location(self) -> Optional[GeoLocation]:
- if self.geo_location_id:
- return GeoLocation.objects.filter(id=self.geo_location_id).first()
- @dataclass
- class BookPageLogData(JSONDataclass):
- page_number: Optional[int] = None
- end_ts: Optional[int] = None
- start_ts: Optional[int] = None
- duration: Optional[int] = None
- @dataclass
- class BookLogData(LongPlayLogData):
- long_play_complete: Optional[bool] = None
- koreader_hash: Optional[str] = None
- page_data: Optional[dict[int, BookPageLogData]] = None
- pages_read: Optional[int] = None
- page_start: Optional[int] = None
- page_end: Optional[int] = None
- serial_scrobble_id: Optional[int] = None
- @dataclass
- class LifeEventLogData(WithOthersLogData):
- with_user_ids: Optional[list[int]] = None
- with_names_str: Optional[list[str]] = None
- location: Optional[str] = None
- geo_location_id: Optional[int] = None
- details: Optional[str] = None
- def geo_location(self):
- return GeoLocation.objects.filter(id=self.geo_location_id).first()
- @dataclass
- class MoodLogData(JSONDataclass):
- reasons: Optional[str] = None
- @dataclass
- class VideoLogData(JSONDataclass):
- title: str
- video_type: str
- run_time_seconds: int
- kind: str
- year: Optional[int]
- episode_number: Optional[int] = None
- source_url: Optional[str] = None
- imdbID: Optional[str] = None
- season_number: Optional[int] = None
- cover_url: Optional[str] = None
- next_imdb_id: Optional[int] = None
- tv_series_id: Optional[str] = None
- @dataclass
- class VideoGameLogData(LongPlayLogData):
- serial_scrobble_id: Optional[int] = None
- long_play_complete: Optional[bool] = False
- console: Optional[str] = None
- emulated: Optional[bool] = False
- emulator: Optional[str] = None
- @dataclass
- class BrickSetLogData(LongPlayLogData, WithOthersLogData):
- serial_scrobble_id: Optional[int]
- long_play_complete: bool = False
- with_user_ids: Optional[list[int]] = None
- with_names_str: Optional[list[str]] = None
- @dataclass
- class TrailLogData(WithOthersLogData):
- with_user_ids: Optional[list[int]] = None
- with_names_str: Optional[list[str]] = None
- details: Optional[str] = None
- effort: Optional[str] = None
- difficulty: Optional[str] = None
- @dataclass
- class BeerLogData(WithOthersLogData):
- with_user_ids: Optional[list[int]] = None
- with_names_str: Optional[list[str]] = None
- details: Optional[str] = None
- rating: Optional[str] = None
- notes: Optional[str] = None
- @dataclass
- class FoodLogData(JSONDataclass):
- meal: Optional[str] = None
- details: Optional[str] = None
- rating: Optional[str] = None
- notes: Optional[str] = None
- @dataclass
- class PuzzleLogData(JSONDataclass):
- with_others: Optional[str] = None
- rating: Optional[str] = None
- notes: Optional[str] = None
|