Feature: Wetter-Tapferkeits-, Jahreszeiten- und Schnee-Badges (SW by-v693)
Drei neue Badge-Kategorien in achievements.py: - wetter_tapfer: Diary-Einträge bei Regen/Kälte/Wind (precip>60, temp<2, wind>50) - jahreszeiten: Anzahl Jahreszeiten mit mind. 5 Diary-Einträgen (max 4) - schnee_held: Diary-Einträge bei Schnee (weathercode 71-77) Beide Funktionen check_and_award und my_achievements erweitert.
This commit is contained in:
parent
6bf088df56
commit
d081029618
1 changed files with 119 additions and 10 deletions
|
|
@ -92,6 +92,45 @@ CATEGORIES = [
|
||||||
("gold", 10, "Wiki-Fotograf"),
|
("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
|
# 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,)
|
"SELECT current_streak FROM users WHERE id=?", (user_id,)
|
||||||
).fetchone()
|
).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 = {
|
metrics = {
|
||||||
"total_km": stats["total_km"] if stats else 0,
|
"total_km": stats["total_km"] if stats else 0,
|
||||||
"routen": stats["routen"] if stats else 0,
|
"routen": stats["routen"] if stats else 0,
|
||||||
"pois": stats["pois"] if stats else 0,
|
"pois": stats["pois"] if stats else 0,
|
||||||
"streak": (streak_row["current_streak"] if streak_row else 0),
|
"streak": (streak_row["current_streak"] if streak_row else 0),
|
||||||
"wiki_fotos": stats["wiki_fotos"] if stats 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
|
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,)
|
"SELECT current_streak, max_streak FROM users WHERE id=?", (uid,)
|
||||||
).fetchone()
|
).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(
|
earned_rows = conn.execute(
|
||||||
"SELECT badge_id FROM user_badges WHERE user_id=?", (uid,)
|
"SELECT badge_id FROM user_badges WHERE user_id=?", (uid,)
|
||||||
).fetchall()
|
).fetchall()
|
||||||
|
|
@ -235,6 +341,9 @@ async def my_achievements(user=Depends(get_current_user)):
|
||||||
"pois": stats["pois"] if stats else 0,
|
"pois": stats["pois"] if stats else 0,
|
||||||
"streak": (streak_row["current_streak"] if streak_row else 0),
|
"streak": (streak_row["current_streak"] if streak_row else 0),
|
||||||
"wiki_fotos": stats["wiki_fotos"] if stats 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
|
# Kategorien mit aktuellem Tier + Fortschritt aufbauen
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue