This commit is contained in:
126
vrobbler/apps/discgolf/utils.py
Normal file
126
vrobbler/apps/discgolf/utils.py
Normal file
@ -0,0 +1,126 @@
|
||||
import csv
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from dateutil.parser import parse as parse_datetime
|
||||
from django.utils import timezone
|
||||
from people.models import Person
|
||||
from scrobbles.models import Scrobble
|
||||
from scrobbles.notifications import ScrobbleNtfyNotification
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _parse_udisc_datetime(raw: str) -> datetime:
|
||||
return parse_datetime(raw)
|
||||
|
||||
|
||||
def _resolve_player(name: str) -> Person:
|
||||
person, _ = Person.objects.get_or_create(name=name.strip())
|
||||
return person
|
||||
|
||||
|
||||
def import_udisc_csv(
|
||||
file_path: str, user_id: int, record_error=None
|
||||
) -> list[Scrobble]:
|
||||
from discgolf.models import DiscGolfCourse
|
||||
|
||||
new_scrobbles = []
|
||||
|
||||
with open(file_path, newline="", encoding="utf-8-sig") as f:
|
||||
reader = csv.DictReader(f)
|
||||
rows = list(reader)
|
||||
|
||||
if not rows:
|
||||
return []
|
||||
|
||||
par_row = None
|
||||
player_rows = []
|
||||
for row in rows:
|
||||
name = row.get("PlayerName", "").strip()
|
||||
if name.lower() == "par":
|
||||
par_row = row
|
||||
else:
|
||||
player_rows.append(row)
|
||||
|
||||
if not par_row:
|
||||
return []
|
||||
|
||||
course_name = par_row.get("CourseName", "").strip()
|
||||
layout_name = par_row.get("LayoutName", "").strip()
|
||||
start_date_raw = par_row.get("StartDate", "").strip()
|
||||
start_dt = _parse_udisc_datetime(start_date_raw) if start_date_raw else timezone.now()
|
||||
|
||||
number_of_holes = sum(1 for k in par_row if k.startswith("Hole") and k[4:].isdigit())
|
||||
par_total_str = par_row.get("Total", "").strip()
|
||||
par_total = int(par_total_str) if par_total_str.isdigit() else None
|
||||
|
||||
par_per_hole = {}
|
||||
for k, v in par_row.items():
|
||||
if k.startswith("Hole") and k[4:].isdigit() and v:
|
||||
hole_num = int(k[4:])
|
||||
try:
|
||||
par_per_hole[f"hole_{hole_num}"] = int(v)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
course, _ = DiscGolfCourse.objects.get_or_create(
|
||||
title=course_name,
|
||||
defaults={
|
||||
"layout_name": layout_name,
|
||||
"number_of_holes": number_of_holes,
|
||||
"par_total": par_total,
|
||||
"par_per_hole": par_per_hole or None,
|
||||
},
|
||||
)
|
||||
|
||||
is_teams = "+" in player_rows[0].get("PlayerName", "") if player_rows else False
|
||||
round_type = "Teams" if is_teams else "Singles"
|
||||
|
||||
scores = {}
|
||||
for row in player_rows:
|
||||
player_name = row.get("PlayerName", "").strip()
|
||||
hole_scores = {}
|
||||
for k, v in row.items():
|
||||
if k.startswith("Hole") and k[4:].isdigit() and v:
|
||||
hole_num = int(k[4:])
|
||||
try:
|
||||
hole_scores[f"hole_{hole_num}"] = int(v)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
total_str = row.get("Total", "").strip()
|
||||
total = int(total_str) if total_str.isdigit() else None
|
||||
if total is not None:
|
||||
hole_scores["total"] = total
|
||||
|
||||
if is_teams:
|
||||
people = player_name.split("+")
|
||||
person_ids = [_resolve_player(p.strip()).id for p in people]
|
||||
hole_scores["person_ids"] = person_ids
|
||||
else:
|
||||
person = _resolve_player(player_name)
|
||||
hole_scores["person_id"] = person.id
|
||||
|
||||
scores[player_name] = hole_scores
|
||||
|
||||
log = {
|
||||
"scores": scores,
|
||||
"course_name": course_name,
|
||||
"par": par_total,
|
||||
"round_type": round_type,
|
||||
}
|
||||
|
||||
scrobble_dict = {
|
||||
"user_id": user_id,
|
||||
"timestamp": start_dt,
|
||||
"source": "uDisc",
|
||||
"playback_position_seconds": 0,
|
||||
"log": log,
|
||||
}
|
||||
|
||||
scrobble = Scrobble.create_or_update(course, user_id, scrobble_dict)
|
||||
if scrobble:
|
||||
new_scrobbles.append(scrobble)
|
||||
ScrobbleNtfyNotification(scrobble).send()
|
||||
|
||||
return new_scrobbles
|
||||
Reference in New Issue
Block a user