+
+
+
+
+
+
-
${match.agent}
-
${match.map} • ${match.mode}
+
+ ${match.agent}
+
+
+
${match.map} • ${match.mode}
-
-
${statusText} (${match.score})
-
KDA: ${match.kills} / ${match.deaths} / ${match.assists}
+
+
+
+ KDA: ${match.kills} / ${match.deaths} / ${match.assists}
+ Ergebnis: ${match.score}
+
+
+ ${rrDisplay}
+
+
`);
});
@@ -183,10 +195,10 @@
document.getElementById('searchSection').classList.add('hidden');
document.getElementById('profileSection').classList.remove('hidden');
} else {
- alert("Fehler: " + (data.message || "Spieler nicht gefunden. Überprüfe Name, TAG und Spielmodus."));
+ alert("Fehler: " + (data.message || "Spieler konnte nicht geladen werden. Checke Name, Tag und Modus."));
}
} catch (error) {
- alert("Verbindungsfehler oder API antwortet nicht.");
+ alert("Verbindungsabbruch oder API temporär offline.");
} finally {
btn.innerText = "Analyse starten";
btn.disabled = false;
diff --git a/AstraOS/astra_os.py b/AstraOS/astra_os.py
index f4b3cc1..fe761c9 100644
--- a/AstraOS/astra_os.py
+++ b/AstraOS/astra_os.py
@@ -1540,12 +1540,11 @@ def get_valorant_stats(name, tag):
if not VALORANT_API_KEY:
return jsonify({"status": "error", "message": "API-Key Konfiguration fehlt in der .env-Datei."}), 500
- # Filter/Match-Typ aus den Query-Parametern auslesen (Standard: competitive)
match_mode = request.args.get('mode', 'competitive')
headers = {"Authorization": VALORANT_API_KEY}
try:
- # 1. Account Basis-Daten abrufen
+ # 1. Account Basis-Daten
acc_res = requests.get(f"{VALORANT_API_BASE}/v1/account/{name}/{tag}?force=true", headers=headers, timeout=10)
if acc_res.status_code != 200:
return jsonify(
@@ -1559,13 +1558,22 @@ def get_valorant_stats(name, tag):
mmr_data = mmr_res.json().get('data', {}) if mmr_res.status_code == 200 else {}
if not mmr_data: mmr_data = {}
- # 3. Match Historie abrufen (Größe auf 15 erhöht, dynamischer Modus)
+ # 3. RR-Verlauf (MMR History) für Plus/Minus Erkennung abrufen
+ rr_history = {}
+ if match_mode == 'competitive':
+ history_res = requests.get(f"{VALORANT_API_BASE}/v1/mmr-history/{region}/{name}/{tag}", headers=headers,
+ timeout=10)
+ if history_res.status_code == 200:
+ for h_item in history_res.json().get('data', []):
+ m_id = h_item.get('match_id')
+ if m_id:
+ rr_history[m_id] = h_item.get('mmr_change_to_last_game', 0)
+
+ # 4. Match Historie (Größe 15)
matches_res = requests.get(f"{VALORANT_API_BASE}/v3/matches/{region}/{name}/{tag}?size=15&mode={match_mode}",
headers=headers, timeout=10)
matches_list = matches_res.json().get('data', []) if matches_res.status_code == 200 else []
- if not matches_list: matches_list = []
- # Statistiken und Match-Details vorbereiten
match_count = 0
wins = 0
total_kills = 0
@@ -1578,9 +1586,9 @@ def get_valorant_stats(name, tag):
for match in matches_list:
metadata = match.get('metadata', {})
+ match_id = metadata.get('matchid')
players = match.get('players', {}).get('all_players', [])
- # Eigenen Spieler im Match suchen
me = next((p for p in players if
p.get('name', '').lower() == name.lower() and p.get('tag', '').lower() == tag.lower()), None)
if not me:
@@ -1590,7 +1598,6 @@ def get_valorant_stats(name, tag):
agent_name = me.get('character', 'Unknown')
agent_counts[agent_name] = agent_counts.get(agent_name, 0) + 1
- # Stats sammeln
stats = me.get('stats', {})
m_kills = stats.get('kills', 0)
m_deaths = stats.get('deaths', 0)
@@ -1600,7 +1607,6 @@ def get_valorant_stats(name, tag):
total_deaths += m_deaths
total_assists += m_assists
- # Rundenauswertung für Win/Loss & Schaden
teams = match.get('teams', {})
my_team_color = me.get('team', '').lower()
my_team_data = teams.get(my_team_color, {})
@@ -1609,43 +1615,43 @@ def get_valorant_stats(name, tag):
if has_won:
wins += 1
- # Runden-Zähler extrahieren
red_rounds = teams.get('red', {}).get('rounds_won', 0) or 0
blue_rounds = teams.get('blue', {}).get('rounds_won', 0) or 0
rounds_played = red_rounds + blue_rounds
total_rounds += rounds_played
- # Score-Anzeige formatieren (z.B. "13 - 5")
if my_team_color == 'red':
score_str = f"{red_rounds} : {blue_rounds}"
else:
score_str = f"{blue_rounds} : {red_rounds}"
- # Schaden aus Runden summieren
match_damage = 0
round_data = match.get('rounds', [])
for r in round_data:
- player_stats = r.get('player_stats', [])
- p_round_stat = next((ps for ps in player_stats if ps.get('player_name', '').lower() == name.lower()),
- None)
+ p_round_stat = next(
+ (ps for ps in r.get('player_stats', []) if ps.get('player_name', '').lower() == name.lower()), None)
if p_round_stat:
match_damage += p_round_stat.get('damage', 0)
total_damage += match_damage
- # Einzelnes Match für die Liste aufbereiten
+ # Bestimme den RR Change aus unserer History-Map
+ mmr_change = rr_history.get(match_id, 0) if match_mode == 'competitive' else None
+
processed_matches.append({
"map": metadata.get('map', 'Unknown'),
"mode": metadata.get('mode', 'Unknown'),
"agent": agent_name,
"agent_img": me.get('assets', {}).get('agent', {}).get('small', ''),
+ # Map-Hintergrundbild aus den Match-Metadaten ziehen
+ "map_img": metadata.get('images', {}).get('wide', ''),
"kills": m_kills,
"deaths": m_deaths,
"assists": m_assists,
"score": score_str,
- "has_won": has_won
+ "has_won": has_won,
+ "mmr_change": mmr_change
})
- # Globale Schnitte berechnen
kd_calculated = round(total_kills / total_deaths, 2) if total_deaths > 0 else total_kills
winrate_calculated = round((wins / match_count) * 100, 1) if match_count > 0 else 0
adr_calculated = round(total_damage / total_rounds, 1) if total_rounds > 0 else 0