Files
vrobbler/vrobbler/apps/discgolf/models.py
Colin Powell f1c777d4ef
Some checks failed
build / test (push) Has been cancelled
[discgolf] Add trail maps and addresses
2026-06-21 01:02:43 -04:00

91 lines
2.6 KiB
Python

from dataclasses import dataclass
from typing import Optional, TypedDict
from django.apps import apps
from django.db import models
from django.urls import reverse
from scrobbles.dataclasses import BaseLogData, WithPeopleLogData
from scrobbles.mixins import ScrobblableConstants, ScrobblableMixin
BNULL = {"blank": True, "null": True}
class DiscGolfSingleScores(TypedDict, total=False):
person_id: int
total: int
class DiscGolfTeamScores(TypedDict, total=False):
person_ids: list[int]
total: int
@dataclass
class DiscGolfLogData(BaseLogData, WithPeopleLogData):
scores: Optional[dict[str, DiscGolfSingleScores | DiscGolfTeamScores]] = None
weather: Optional[str] = None
fun_factor: Optional[str] = None
course_name: Optional[str] = None
par: Optional[int] = None
round_type: Optional[str] = None
class DiscGolfCourse(ScrobblableMixin):
description = models.TextField(**BNULL)
layout_name = models.CharField(max_length=255, **BNULL)
number_of_holes = models.IntegerField(**BNULL)
par_total = models.IntegerField(**BNULL)
par_per_hole = models.JSONField(**BNULL)
trail = models.ForeignKey(
"trails.Trail", on_delete=models.DO_NOTHING, **BNULL
)
pdga_slug = models.CharField(max_length=255, **BNULL)
udisc_id = models.CharField(max_length=255, **BNULL)
@property
def pdga_link(self) -> str:
if self.pdga_slug:
return f"https://www.pdga.com/course-directory/course/{self.pdga_slug}/"
return ""
@property
def udisc_link(self) -> str:
if self.udisc_id:
return f"https://udisc.com/courses/{self.udisc_id}/"
return ""
def get_absolute_url(self) -> str:
return reverse("discgolf:course_detail", kwargs={"slug": self.uuid})
def __str__(self):
return f"{self.title} ({self.layout_name or 'Default'})"
@property
def logdata_cls(self):
return DiscGolfLogData
@property
def subtitle(self):
return self.layout_name or ""
@property
def strings(self) -> ScrobblableConstants:
return ScrobblableConstants(verb="Playing", tags="golf")
@property
def primary_image_url(self) -> str:
return ""
@classmethod
def find_or_create(cls, name: str, **defaults) -> "DiscGolfCourse":
course = cls.objects.filter(title=name).first()
if not course:
course = cls.objects.create(title=name, **defaults)
return course
def scrobbles(self, user_id):
Scrobble = apps.get_model("scrobbles", "Scrobble")
return Scrobble.objects.filter(user_id=user_id, disc_golf_course=self).order_by(
"-timestamp"
)