127 lines
3.7 KiB
Python
127 lines
3.7 KiB
Python
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
|