Routen-Validierung: >15 km/h Ø zählt nicht für Stats/Trophäen, SW by-v331

This commit is contained in:
rene 2026-04-24 09:46:15 +02:00
parent b5e4eab84d
commit 7ac421fcf9
7 changed files with 40 additions and 16 deletions

View file

@ -125,10 +125,10 @@ def update_streak(user_id: int, conn):
def check_and_award(user_id: int, conn):
stats = conn.execute("""
SELECT ROUND(
COALESCE((SELECT SUM(r.distanz_km) FROM routes r WHERE r.user_id=? ), 0) +
COALESCE((SELECT SUM(r.distanz_km) FROM routes r WHERE r.user_id=? AND r.is_valid=1), 0) +
COALESCE((SELECT SUM(w.walked_km) FROM route_walks w WHERE w.user_id=?), 0),
1) AS total_km,
(SELECT COUNT(*) FROM routes r WHERE r.user_id=? ) AS routen,
(SELECT COUNT(*) FROM routes r WHERE r.user_id=? AND r.is_valid=1) AS routen,
(SELECT COUNT(*) FROM user_map_pois p WHERE p.user_id=?) AS pois
FROM (SELECT 1)
""", (user_id, user_id, user_id, user_id)).fetchone()
@ -178,17 +178,17 @@ async def my_achievements(user=Depends(get_current_user)):
stats = conn.execute("""
SELECT ROUND(
COALESCE((SELECT SUM(r.distanz_km) FROM routes r WHERE r.user_id=? ), 0) +
COALESCE((SELECT SUM(r.distanz_km) FROM routes r WHERE r.user_id=? AND r.is_valid=1), 0) +
COALESCE((SELECT SUM(w.walked_km) FROM route_walks w WHERE w.user_id=?), 0),
1) AS total_km,
(SELECT COUNT(*) FROM routes r WHERE r.user_id=? ) AS routen,
(SELECT COUNT(*) FROM routes r WHERE r.user_id=? AND r.is_valid=1) AS routen,
(SELECT COUNT(*) FROM user_map_pois p WHERE p.user_id=?) AS pois,
ROUND(
COALESCE((SELECT SUM(r.distanz_km) FROM routes r WHERE r.user_id=? ), 0) +
COALESCE((SELECT SUM(r.distanz_km) FROM routes r WHERE r.user_id=? AND r.is_valid=1), 0) +
COALESCE((SELECT SUM(w.walked_km) FROM route_walks w WHERE w.user_id=?), 0),
1)*1
+ (SELECT COUNT(*) FROM user_map_pois p WHERE p.user_id=?)*5
+ (SELECT COUNT(*) FROM routes r WHERE r.user_id=? )*10 AS punkte
+ (SELECT COUNT(*) FROM routes r WHERE r.user_id=? AND r.is_valid=1)*10 AS punkte
FROM (SELECT 1)
""", (uid, uid, uid, uid, uid, uid, uid, uid)).fetchone()
@ -208,7 +208,8 @@ async def my_achievements(user=Depends(get_current_user)):
+COUNT(DISTINCT p.id)*5
+COUNT(DISTINCT r.id)*10 AS punkte
FROM users u
LEFT JOIN routes r ON r.user_id=u.id LEFT JOIN user_map_pois p ON p.user_id=u.id
LEFT JOIN routes r ON r.user_id=u.id AND r.is_valid=1
LEFT JOIN user_map_pois p ON p.user_id=u.id
GROUP BY u.id
) WHERE punkte > ?
""", (stats["punkte"] if stats else 0,)).fetchone()

View file

@ -13,6 +13,14 @@ from routes.push import send_push_to_user
router = APIRouter()
_MAX_AVG_KMH = 15.0 # Über diesem Wert wird die Route nicht für Stats/Trophäen gewertet
def _check_speed(distanz_km, dauer_min) -> bool:
"""True = gültig, False = zu schnell (wahrscheinlich motorisiert)."""
if not distanz_km or not dauer_min or dauer_min <= 0:
return True
return (distanz_km / (dauer_min / 60)) <= _MAX_AVG_KMH
def _haversine(lat1: float, lon1: float, lat2: float, lon2: float) -> float:
R = 6_371_000
@ -135,26 +143,30 @@ async def create_route(data: RouteCreate, user=Depends(get_current_user)):
if len(data.gps_track) < 2:
raise HTTPException(400, "GPS-Track braucht mindestens 2 Punkte.")
gps_json = json.dumps([p.model_dump() for p in data.gps_track])
gps_json = json.dumps([p.model_dump() for p in data.gps_track])
is_valid = int(_check_speed(data.distanz_km, data.dauer_min))
with db() as conn:
cur = conn.execute("""
INSERT INTO routes
(user_id, name, beschreibung, gps_track, distanz_km, dauer_min,
schwierigkeit, untergrund, schatten, leine_empfohlen, is_public, hunde_tauglichkeit)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
schwierigkeit, untergrund, schatten, leine_empfohlen, is_public,
hunde_tauglichkeit, is_valid)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (
user['id'], data.name, data.beschreibung, gps_json,
data.distanz_km, data.dauer_min, data.schwierigkeit, data.untergrund,
int(data.schatten) if data.schatten is not None else None,
int(data.leine_empfohlen) if data.leine_empfohlen is not None else None,
int(data.is_public) if data.is_public is not None else 1,
data.hunde_tauglichkeit,
data.hunde_tauglichkeit, is_valid,
))
row = conn.execute("SELECT * FROM routes WHERE id = ?", (cur.lastrowid,)).fetchone()
update_streak(user['id'], conn)
check_and_award(user['id'], conn)
return _parse(row)
result = _parse(row)
result['is_valid'] = bool(is_valid)
return result
# ------------------------------------------------------------------

View file

@ -13,7 +13,7 @@ _STATS_SQL = """
+ COUNT(DISTINCT p.id) * 5
+ COUNT(DISTINCT r.id) * 10 AS punkte
FROM users u
LEFT JOIN routes r ON r.user_id = u.id
LEFT JOIN routes r ON r.user_id = u.id AND r.is_valid = 1
LEFT JOIN user_map_pois p ON p.user_id = u.id
GROUP BY u.id
"""