diff --git a/backend/routes/achievements.py b/backend/routes/achievements.py index 1c0c1e8..00b8748 100644 --- a/backend/routes/achievements.py +++ b/backend/routes/achievements.py @@ -92,6 +92,45 @@ CATEGORIES = [ ("gold", 10, "Wiki-Fotograf"), ], }, + { + "id": "wetter_tapfer", + "name": "Wetter-Tapferkeit", + "emoji": "⛈️", + "metrik": "wetter_tapfer_score", + "einheit": " Eintrag/Einträge", + "stufen": [ + ("bronze", 1, "Regentrotzdem"), + ("silber", 5, "Wettertrotzer"), + ("gold", 15, "Allwetter-Held"), + ("platin", 30, "Hunde-Wetterheld"), + ], + }, + { + "id": "jahreszeiten", + "name": "Jahreszeiten-Erkunder", + "emoji": "🍃", + "metrik": "jahreszeiten_score", + "einheit": " Jahreszeit(en)", + "stufen": [ + ("bronze", 1, "Frühlings-Erkunder"), + ("silber", 2, "Sommer-Genießer"), + ("gold", 3, "Herbst-Schnüffler"), + ("platin", 4, "Alle-Jahreszeiten"), + ], + }, + { + "id": "schnee_held", + "name": "Schneeheld", + "emoji": "❄️", + "metrik": "schnee_eintraege", + "einheit": " Eintrag/Einträge", + "stufen": [ + ("bronze", 1, "Erster Schnee"), + ("silber", 5, "Schneehund"), + ("gold", 15, "Schneeheld"), + ("platin", 30, "Schneewolf"), + ], + }, ] # Flat-Liste aller Badge-IDs für DB-Kompatibilität @@ -150,12 +189,47 @@ def check_and_award(user_id: int, conn): "SELECT current_streak FROM users WHERE id=?", (user_id,) ).fetchone() + # Wetter-Tapferkeit: Diary-Einträge bei schlechtem Wetter + wetter_row = conn.execute(""" + SELECT COUNT(*) AS cnt FROM diary d + LEFT JOIN diary_dogs dd ON dd.diary_id = d.id + WHERE d.user_id = ? + AND d.weather_json IS NOT NULL + AND ( + CAST(json_extract(d.weather_json, '$.precip_prob') AS INTEGER) > 60 + OR CAST(json_extract(d.weather_json, '$.temp_c') AS REAL) < 2 + OR CAST(json_extract(d.weather_json, '$.wind_kmh') AS REAL) > 50 + ) + """, (user_id,)).fetchone() + + # Jahreszeiten: Anzahl Jahreszeiten mit mind. 5 Diary-Einträgen + jahreszeiten_row = conn.execute(""" + SELECT + (CASE WHEN (SELECT COUNT(*) FROM diary WHERE user_id=? AND CAST(strftime('%m', datum) AS INTEGER) IN (3,4,5)) >= 5 THEN 1 ELSE 0 END) + + (CASE WHEN (SELECT COUNT(*) FROM diary WHERE user_id=? AND CAST(strftime('%m', datum) AS INTEGER) IN (6,7,8)) >= 5 THEN 1 ELSE 0 END) + + (CASE WHEN (SELECT COUNT(*) FROM diary WHERE user_id=? AND CAST(strftime('%m', datum) AS INTEGER) IN (9,10,11)) >= 5 THEN 1 ELSE 0 END) + + (CASE WHEN (SELECT COUNT(*) FROM diary WHERE user_id=? AND CAST(strftime('%m', datum) AS INTEGER) IN (12,1,2)) >= 5 THEN 1 ELSE 0 END) + AS jahreszeiten_score + FROM (SELECT 1) + """, (user_id, user_id, user_id, user_id)).fetchone() + + # Schnee: Diary-Einträge bei Schnee (weathercode 71-77) + schnee_row = conn.execute(""" + SELECT COUNT(*) AS cnt FROM diary + WHERE user_id = ? + AND weather_json IS NOT NULL + AND CAST(json_extract(weather_json, '$.weathercode') AS INTEGER) BETWEEN 71 AND 77 + """, (user_id,)).fetchone() + metrics = { - "total_km": stats["total_km"] if stats else 0, - "routen": stats["routen"] if stats else 0, - "pois": stats["pois"] if stats else 0, - "streak": (streak_row["current_streak"] if streak_row else 0), - "wiki_fotos": stats["wiki_fotos"] if stats else 0, + "total_km": stats["total_km"] if stats else 0, + "routen": stats["routen"] if stats else 0, + "pois": stats["pois"] if stats else 0, + "streak": (streak_row["current_streak"] if streak_row else 0), + "wiki_fotos": stats["wiki_fotos"] if stats else 0, + "wetter_tapfer_score": wetter_row["cnt"] if wetter_row else 0, + "jahreszeiten_score": (jahreszeiten_row["jahreszeiten_score"] if jahreszeiten_row else 0), + "schnee_eintraege": schnee_row["cnt"] if schnee_row else 0, } earned = {r["badge_id"] for r in @@ -211,6 +285,38 @@ async def my_achievements(user=Depends(get_current_user)): "SELECT current_streak, max_streak FROM users WHERE id=?", (uid,) ).fetchone() + # Wetter-Tapferkeit + wetter_row = conn.execute(""" + SELECT COUNT(*) AS cnt FROM diary d + LEFT JOIN diary_dogs dd ON dd.diary_id = d.id + WHERE d.user_id = ? + AND d.weather_json IS NOT NULL + AND ( + CAST(json_extract(d.weather_json, '$.precip_prob') AS INTEGER) > 60 + OR CAST(json_extract(d.weather_json, '$.temp_c') AS REAL) < 2 + OR CAST(json_extract(d.weather_json, '$.wind_kmh') AS REAL) > 50 + ) + """, (uid,)).fetchone() + + # Jahreszeiten + jahreszeiten_row = conn.execute(""" + SELECT + (CASE WHEN (SELECT COUNT(*) FROM diary WHERE user_id=? AND CAST(strftime('%m', datum) AS INTEGER) IN (3,4,5)) >= 5 THEN 1 ELSE 0 END) + + (CASE WHEN (SELECT COUNT(*) FROM diary WHERE user_id=? AND CAST(strftime('%m', datum) AS INTEGER) IN (6,7,8)) >= 5 THEN 1 ELSE 0 END) + + (CASE WHEN (SELECT COUNT(*) FROM diary WHERE user_id=? AND CAST(strftime('%m', datum) AS INTEGER) IN (9,10,11)) >= 5 THEN 1 ELSE 0 END) + + (CASE WHEN (SELECT COUNT(*) FROM diary WHERE user_id=? AND CAST(strftime('%m', datum) AS INTEGER) IN (12,1,2)) >= 5 THEN 1 ELSE 0 END) + AS jahreszeiten_score + FROM (SELECT 1) + """, (uid, uid, uid, uid)).fetchone() + + # Schnee-Einträge + schnee_row = conn.execute(""" + SELECT COUNT(*) AS cnt FROM diary + WHERE user_id = ? + AND weather_json IS NOT NULL + AND CAST(json_extract(weather_json, '$.weathercode') AS INTEGER) BETWEEN 71 AND 77 + """, (uid,)).fetchone() + earned_rows = conn.execute( "SELECT badge_id FROM user_badges WHERE user_id=?", (uid,) ).fetchall() @@ -230,11 +336,14 @@ async def my_achievements(user=Depends(get_current_user)): """, (stats["punkte"] if stats else 0,)).fetchone() metrics = { - "total_km": stats["total_km"] if stats else 0, - "routen": stats["routen"] if stats else 0, - "pois": stats["pois"] if stats else 0, - "streak": (streak_row["current_streak"] if streak_row else 0), - "wiki_fotos": stats["wiki_fotos"] if stats else 0, + "total_km": stats["total_km"] if stats else 0, + "routen": stats["routen"] if stats else 0, + "pois": stats["pois"] if stats else 0, + "streak": (streak_row["current_streak"] if streak_row else 0), + "wiki_fotos": stats["wiki_fotos"] if stats else 0, + "wetter_tapfer_score": wetter_row["cnt"] if wetter_row else 0, + "jahreszeiten_score": (jahreszeiten_row["jahreszeiten_score"] if jahreszeiten_row else 0), + "schnee_eintraege": schnee_row["cnt"] if schnee_row else 0, } # Kategorien mit aktuellem Tier + Fortschritt aufbauen