AstraOS Ver. 1.30:
All checks were successful
Deploy AstraOS Panel / deploy (push) Successful in 12s
All checks were successful
Deploy AstraOS Panel / deploy (push) Successful in 12s
- AyranTracker bearbeitet
This commit is contained in:
parent
7aaff575d7
commit
19370f1030
|
|
@ -3,7 +3,7 @@
|
||||||
{% block title %}AstraOS — AyranTracker{% endblock %}
|
{% block title %}AstraOS — AyranTracker{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="max-w-5xl mx-auto px-4 py-6">
|
<div class="max-w-4xl mx-auto px-4 py-6">
|
||||||
<header class="mb-10 text-center">
|
<header class="mb-10 text-center">
|
||||||
<h2 class="text-4xl font-black tracking-widest text-transparent bg-clip-text bg-gradient-to-r from-purple-400 via-violet-200 to-white">
|
<h2 class="text-4xl font-black tracking-widest text-transparent bg-clip-text bg-gradient-to-r from-purple-400 via-violet-200 to-white">
|
||||||
AYRAN<span class="text-purple-400">TRACKER</span>
|
AYRAN<span class="text-purple-400">TRACKER</span>
|
||||||
|
|
@ -33,58 +33,54 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="profileSection" class="hidden space-y-6">
|
<div id="profileSection" class="hidden space-y-8 max-w-3xl mx-auto">
|
||||||
<button onclick="location.reload()" class="text-xs font-bold text-slate-400 hover:text-white transition flex items-center gap-1">
|
<button onclick="location.reload()" class="text-xs font-bold text-slate-400 hover:text-white transition flex items-center gap-1">
|
||||||
← Neue Suche
|
← Neue Suche
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
<div class="bg-black/40 border border-purple-500/10 p-6 rounded-2xl flex flex-col items-center text-center backdrop-blur-md h-fit">
|
<div class="bg-black/40 border border-purple-500/10 p-6 rounded-2xl flex flex-col items-center text-center backdrop-blur-md">
|
||||||
<img id="playerCard" src="" alt="Player Card" class="w-24 h-24 rounded-xl object-cover mb-4 border border-purple-500/30 shadow-md">
|
<img id="playerCard" src="" alt="Player Card" class="w-20 h-20 rounded-xl object-cover mb-3 border border-purple-500/30 shadow-md">
|
||||||
<h4 id="playerNameTag" class="text-xl font-black text-white">Loading...</h4>
|
<h4 id="playerNameTag" class="text-lg font-black text-white truncate max-w-full">Loading...</h4>
|
||||||
<p id="playerLevel" class="text-xs text-slate-400 mt-1 bg-slate-950 px-2 py-0.5 rounded-full">Level: --</p>
|
<p id="playerLevel" class="text-[11px] text-slate-400 mt-1 bg-slate-950 px-2 py-0.5 rounded-full">Level: --</p>
|
||||||
|
|
||||||
<div class="mt-6 w-full border-t border-slate-800/60 pt-4">
|
<div class="mt-4 w-full border-t border-slate-800/60 pt-3">
|
||||||
<p class="text-xs text-slate-400 font-semibold">Aktueller Rang</p>
|
<p class="text-xs text-slate-400 font-semibold">Aktueller Rang</p>
|
||||||
<p id="playerRank" class="text-lg font-bold text-purple-300 mt-1">Unranked</p>
|
<p id="playerRank" class="text-base font-bold text-purple-300 mt-0.5">Unranked</p>
|
||||||
<p id="playerRR" class="text-xs text-slate-500">0 RR</p>
|
<p id="playerRR" class="text-xs text-slate-500">0 RR</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md:col-span-2 space-y-6">
|
<div class="md:col-span-2 bg-black/40 border border-purple-500/10 p-6 rounded-2xl backdrop-blur-md flex flex-col justify-between">
|
||||||
<div class="bg-black/40 border border-purple-500/10 p-6 rounded-2xl backdrop-blur-md space-y-6">
|
|
||||||
<h4 class="text-sm font-bold text-slate-400 tracking-wider uppercase">Berechnete Performance</h4>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-2 gap-4">
|
<div class="grid grid-cols-2 gap-4">
|
||||||
<div class="bg-slate-950/50 border border-slate-900 p-4 rounded-xl">
|
<div class="bg-slate-950/50 border border-slate-900 p-3 rounded-xl">
|
||||||
<span class="block text-xs text-slate-500 font-medium">Winrate</span>
|
<span class="block text-[11px] text-slate-500 font-medium">Winrate</span>
|
||||||
<span id="statWinrate" class="text-2xl font-black text-emerald-400">0%</span>
|
<span id="statWinrate" class="text-xl font-black text-emerald-400">0%</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-slate-950/50 border border-slate-900 p-4 rounded-xl">
|
<div class="bg-slate-950/50 border border-slate-900 p-3 rounded-xl">
|
||||||
<span class="block text-xs text-slate-500 font-medium">K/D Ratio</span>
|
<span class="block text-[11px] text-slate-500 font-medium">K/D Ratio</span>
|
||||||
<span id="statKD" class="text-2xl font-black text-purple-400">0.0</span>
|
<span id="statKD" class="text-xl font-black text-purple-400">0.0</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-slate-950/50 border border-slate-900 p-4 rounded-xl">
|
<div class="bg-slate-950/50 border border-slate-900 p-3 rounded-xl">
|
||||||
<span class="block text-xs text-slate-500 font-medium">Ø Schaden / Runde (ADR)</span>
|
<span class="block text-[11px] text-slate-500 font-medium">Ø Schaden / Rnd.</span>
|
||||||
<span id="statADR" class="text-2xl font-black text-blue-400">0.0</span>
|
<span id="statADR" class="text-xl font-black text-blue-400">0.0</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-slate-950/50 border border-slate-900 p-4 rounded-xl">
|
<div class="bg-slate-950/50 border border-slate-900 p-3 rounded-xl">
|
||||||
<span class="block text-xs text-slate-500 font-medium">Analysierte Matches</span>
|
<span class="block text-[11px] text-slate-500 font-medium">Matches Analysiert</span>
|
||||||
<span id="statMatches" class="text-2xl font-black text-slate-300">0</span>
|
<span id="statMatches" class="text-xl font-black text-slate-300">0</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="mt-4">
|
||||||
<h5 class="text-xs font-bold text-slate-400 uppercase tracking-wider mb-3">Top Agenten</h5>
|
<h5 class="text-[11px] font-bold text-slate-500 uppercase tracking-wider mb-2">Top Agenten</h5>
|
||||||
<div id="agentContainer" class="grid grid-cols-1 sm:grid-cols-2 gap-3"></div>
|
<div id="agentContainer" class="grid grid-cols-2 gap-2"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-black/40 border border-purple-500/10 p-6 rounded-2xl backdrop-blur-md space-y-4">
|
<div class="space-y-4">
|
||||||
<h4 class="text-sm font-bold text-slate-400 tracking-wider uppercase">Match Historie (Letzte 15 Matches)</h4>
|
<h4 class="text-sm font-bold text-slate-400 tracking-wider uppercase text-center md:text-left">Match Historie (Letzte 15 Matches)</h4>
|
||||||
<div id="matchHistoryContainer" class="space-y-2 max-h-[500px] overflow-y-auto pr-1">
|
<div id="matchHistoryContainer" class="space-y-3">
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -96,9 +92,8 @@
|
||||||
const mode = document.getElementById('matchModeSelect').value;
|
const mode = document.getElementById('matchModeSelect').value;
|
||||||
const btn = document.getElementById('searchBtn');
|
const btn = document.getElementById('searchBtn');
|
||||||
|
|
||||||
// Splitte Name und Tag anhand des '#'
|
|
||||||
if (!riotId.includes('#')) {
|
if (!riotId.includes('#')) {
|
||||||
alert("Bitte gib die Riot ID im Format Name#TAG an (z.B. TenZ#NA1)!");
|
alert("Format ungültig! Bitte nutze Name#TAG (z.B. TenZ#NA1)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,11 +101,6 @@
|
||||||
const name = parts[0].trim();
|
const name = parts[0].trim();
|
||||||
const tag = parts[1].trim();
|
const tag = parts[1].trim();
|
||||||
|
|
||||||
if (!name || !tag) {
|
|
||||||
alert("Name oder Tag darf nicht leer sein!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
btn.innerText = "Analysiere...";
|
btn.innerText = "Analysiere...";
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
|
|
||||||
|
|
@ -119,7 +109,7 @@
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (response.ok && data.status === "success") {
|
if (response.ok && data.status === "success") {
|
||||||
// Basisdaten füllen
|
// Dashboard füllen
|
||||||
document.getElementById('playerNameTag').innerText = `${data.account.name}#${data.account.tag}`;
|
document.getElementById('playerNameTag').innerText = `${data.account.name}#${data.account.tag}`;
|
||||||
document.getElementById('playerLevel').innerText = `Level: ${data.account.level}`;
|
document.getElementById('playerLevel').innerText = `Level: ${data.account.level}`;
|
||||||
document.getElementById('playerCard').src = data.account.card_url || 'https://media.valorant-api.com/playercards/9fb348bc-41a4-91ad-d131-1ca1efdc3535/smallart.png';
|
document.getElementById('playerCard').src = data.account.card_url || 'https://media.valorant-api.com/playercards/9fb348bc-41a4-91ad-d131-1ca1efdc3535/smallart.png';
|
||||||
|
|
@ -127,53 +117,75 @@
|
||||||
document.getElementById('playerRank').innerText = data.rank.current_tier_name;
|
document.getElementById('playerRank').innerText = data.rank.current_tier_name;
|
||||||
document.getElementById('playerRR').innerText = `${data.rank.ranking_in_tier} RR`;
|
document.getElementById('playerRR').innerText = `${data.rank.ranking_in_tier} RR`;
|
||||||
|
|
||||||
// Statistiken füllen
|
|
||||||
document.getElementById('statWinrate').innerText = data.calculated_stats.win_rate;
|
document.getElementById('statWinrate').innerText = data.calculated_stats.win_rate;
|
||||||
document.getElementById('statKD').innerText = data.calculated_stats.kd_ratio;
|
document.getElementById('statKD').innerText = data.calculated_stats.kd_ratio;
|
||||||
document.getElementById('statADR').innerText = data.calculated_stats.avg_damage_round;
|
document.getElementById('statADR').innerText = data.calculated_stats.avg_damage_round;
|
||||||
document.getElementById('statMatches').innerText = data.calculated_stats.matches_analyzed;
|
document.getElementById('statMatches').innerText = data.calculated_stats.matches_analyzed;
|
||||||
|
|
||||||
// Agenten füllen
|
// Agenten Boxen
|
||||||
const agentContainer = document.getElementById('agentContainer');
|
const agentContainer = document.getElementById('agentContainer');
|
||||||
agentContainer.innerHTML = '';
|
agentContainer.innerHTML = '';
|
||||||
if (data.top_agents.length === 0) {
|
|
||||||
agentContainer.innerHTML = '<p class="text-xs text-slate-500 py-2">Keine Daten verfügbar.</p>';
|
|
||||||
} else {
|
|
||||||
data.top_agents.forEach(agent => {
|
data.top_agents.forEach(agent => {
|
||||||
agentContainer.insertAdjacentHTML('beforeend', `
|
agentContainer.insertAdjacentHTML('beforeend', `
|
||||||
<div class="flex justify-between items-center bg-slate-900/50 p-3 rounded-lg border border-purple-950/40">
|
<div class="flex justify-between items-center bg-slate-950/40 p-2 rounded-lg border border-slate-900 text-xs">
|
||||||
<span class="text-xs font-bold text-purple-300">${agent.name}</span>
|
<span class="font-bold text-purple-300">${agent.name}</span>
|
||||||
<span class="text-xs font-semibold text-slate-400 bg-slate-950 px-2 py-0.5 rounded">${agent.count}x gespielt</span>
|
<span class="text-slate-400 bg-slate-950 px-1.5 py-0.5 rounded">${agent.count}x</span>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// Match Historie aufbauen
|
// Match History sauber rendern (Wie dein Altes liebgewonnenes Layout!)
|
||||||
const historyContainer = document.getElementById('matchHistoryContainer');
|
const historyContainer = document.getElementById('matchHistoryContainer');
|
||||||
historyContainer.innerHTML = '';
|
historyContainer.innerHTML = '';
|
||||||
|
|
||||||
if (!data.matches || data.matches.length === 0) {
|
if (!data.matches || data.matches.length === 0) {
|
||||||
historyContainer.innerHTML = '<p class="text-xs text-slate-500 text-center py-4">Keine Matches in diesem Spielmodus gefunden.</p>';
|
historyContainer.innerHTML = '<p class="text-xs text-slate-500 text-center py-6">Keine Matches gefunden.</p>';
|
||||||
} else {
|
} else {
|
||||||
data.matches.forEach(match => {
|
data.matches.forEach(match => {
|
||||||
const borderClass = match.has_won ? 'border-emerald-500/30 bg-emerald-950/10' : 'border-rose-500/30 bg-rose-950/10';
|
// Dynamisches Styling je nach Win/Loss
|
||||||
const textClass = match.has_won ? 'text-emerald-400' : 'text-rose-400';
|
const borderClass = match.has_won ? 'border-emerald-500/30' : 'border-rose-500/30';
|
||||||
const statusText = match.has_won ? 'SIEG' : 'NIEDERLAGE';
|
const badgeBg = match.has_won ? 'bg-emerald-500/20 text-emerald-300' : 'bg-rose-500/20 text-rose-300';
|
||||||
|
const statusLabel = match.has_won ? 'WIN' : 'LOSS';
|
||||||
|
|
||||||
|
// RR String bauen (+ / - oder verstecken wenn Modus != Comp)
|
||||||
|
let rrDisplay = '';
|
||||||
|
if (match.mmr_change !== null && mode === 'competitive') {
|
||||||
|
if (match.mmr_change > 0) {
|
||||||
|
rrDisplay = `<span class="text-emerald-400 font-black text-xs bg-emerald-950/80 px-2 py-1 rounded border border-emerald-500/20">+${match.mmr_change} RR</span>`;
|
||||||
|
} else if (match.mmr_change < 0) {
|
||||||
|
rrDisplay = `<span class="text-rose-400 font-black text-xs bg-rose-950/80 px-2 py-1 rounded border border-rose-500/20">${match.mmr_change} RR</span>`;
|
||||||
|
} else {
|
||||||
|
rrDisplay = `<span class="text-slate-400 font-black text-xs bg-slate-950 px-2 py-1 rounded">0 RR</span>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
historyContainer.insertAdjacentHTML('beforeend', `
|
historyContainer.insertAdjacentHTML('beforeend', `
|
||||||
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center border p-4 rounded-xl backdrop-blur-sm gap-4 ${borderClass}">
|
<div class="relative overflow-hidden border rounded-xl p-4 flex flex-col sm:flex-row justify-between items-center transition hover:scale-[1.01] duration-200 ${borderClass}" style="min-height: 85px;">
|
||||||
<div class="flex items-center gap-3">
|
|
||||||
<img src="${match.agent_img}" alt="${match.agent}" class="w-10 h-10 rounded-lg border border-slate-700 bg-slate-900 object-cover" onerror="this.style.display='none'">
|
<div class="absolute inset-0 bg-cover bg-center pointer-events-none opacity-[0.12] mix-blend-luminosity" style="background-image: url('${match.map_img}');"></div>
|
||||||
|
<div class="absolute inset-0 bg-gradient-to-r from-slate-950 via-transparent to-slate-950/40 pointer-events-none"></div>
|
||||||
|
|
||||||
|
<div class="relative z-10 flex items-center gap-4 w-full sm:w-auto">
|
||||||
|
<img src="${match.agent_img}" alt="${match.agent}" class="w-12 h-12 rounded-lg border border-slate-800 bg-slate-950 object-cover shadow-inner">
|
||||||
<div>
|
<div>
|
||||||
<span class="block text-sm font-black text-white">${match.agent}</span>
|
<div class="flex items-center gap-2">
|
||||||
<span class="block text-xs text-slate-400">${match.map} • ${match.mode}</span>
|
<span class="text-sm font-black text-white">${match.agent}</span>
|
||||||
|
<span class="text-[10px] px-1.5 py-0.5 rounded font-extrabold tracking-wider ${badgeBg}">${statusLabel}</span>
|
||||||
|
</div>
|
||||||
|
<span class="block text-xs text-slate-400 font-medium mt-0.5">${match.map} • <span class="capitalize text-purple-300 text-[11px]">${match.mode}</span></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row sm:flex-col justify-between sm:justify-center w-full sm:w-auto items-center sm:items-end gap-1">
|
|
||||||
<span class="text-xs font-bold ${textClass}">${statusText} (${match.score})</span>
|
<div class="relative z-10 flex justify-between sm:justify-end items-center w-full sm:w-auto mt-3 sm:mt-0 gap-6 border-t sm:border-t-0 border-slate-900 pt-2 sm:pt-0">
|
||||||
<span class="text-sm font-semibold text-slate-300">KDA: ${match.kills} / ${match.deaths} / ${match.assists}</span>
|
<div class="text-left sm:text-right">
|
||||||
|
<span class="block text-xs font-mono font-bold text-slate-200 tracking-wide">KDA: ${match.kills} / ${match.deaths} / ${match.assists}</span>
|
||||||
|
<span class="block text-[11px] text-slate-500 mt-0.5">Ergebnis: <span class="font-bold text-slate-300">${match.score}</span></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex items-center min-w-[75px] justify-end">
|
||||||
|
${rrDisplay}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
@ -183,10 +195,10 @@
|
||||||
document.getElementById('searchSection').classList.add('hidden');
|
document.getElementById('searchSection').classList.add('hidden');
|
||||||
document.getElementById('profileSection').classList.remove('hidden');
|
document.getElementById('profileSection').classList.remove('hidden');
|
||||||
} else {
|
} 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) {
|
} catch (error) {
|
||||||
alert("Verbindungsfehler oder API antwortet nicht.");
|
alert("Verbindungsabbruch oder API temporär offline.");
|
||||||
} finally {
|
} finally {
|
||||||
btn.innerText = "Analyse starten";
|
btn.innerText = "Analyse starten";
|
||||||
btn.disabled = false;
|
btn.disabled = false;
|
||||||
|
|
|
||||||
|
|
@ -1540,12 +1540,11 @@ def get_valorant_stats(name, tag):
|
||||||
if not VALORANT_API_KEY:
|
if not VALORANT_API_KEY:
|
||||||
return jsonify({"status": "error", "message": "API-Key Konfiguration fehlt in der .env-Datei."}), 500
|
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')
|
match_mode = request.args.get('mode', 'competitive')
|
||||||
headers = {"Authorization": VALORANT_API_KEY}
|
headers = {"Authorization": VALORANT_API_KEY}
|
||||||
|
|
||||||
try:
|
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)
|
acc_res = requests.get(f"{VALORANT_API_BASE}/v1/account/{name}/{tag}?force=true", headers=headers, timeout=10)
|
||||||
if acc_res.status_code != 200:
|
if acc_res.status_code != 200:
|
||||||
return jsonify(
|
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 {}
|
mmr_data = mmr_res.json().get('data', {}) if mmr_res.status_code == 200 else {}
|
||||||
if not mmr_data: mmr_data = {}
|
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}",
|
matches_res = requests.get(f"{VALORANT_API_BASE}/v3/matches/{region}/{name}/{tag}?size=15&mode={match_mode}",
|
||||||
headers=headers, timeout=10)
|
headers=headers, timeout=10)
|
||||||
matches_list = matches_res.json().get('data', []) if matches_res.status_code == 200 else []
|
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
|
match_count = 0
|
||||||
wins = 0
|
wins = 0
|
||||||
total_kills = 0
|
total_kills = 0
|
||||||
|
|
@ -1578,9 +1586,9 @@ def get_valorant_stats(name, tag):
|
||||||
|
|
||||||
for match in matches_list:
|
for match in matches_list:
|
||||||
metadata = match.get('metadata', {})
|
metadata = match.get('metadata', {})
|
||||||
|
match_id = metadata.get('matchid')
|
||||||
players = match.get('players', {}).get('all_players', [])
|
players = match.get('players', {}).get('all_players', [])
|
||||||
|
|
||||||
# Eigenen Spieler im Match suchen
|
|
||||||
me = next((p for p in players if
|
me = next((p for p in players if
|
||||||
p.get('name', '').lower() == name.lower() and p.get('tag', '').lower() == tag.lower()), None)
|
p.get('name', '').lower() == name.lower() and p.get('tag', '').lower() == tag.lower()), None)
|
||||||
if not me:
|
if not me:
|
||||||
|
|
@ -1590,7 +1598,6 @@ def get_valorant_stats(name, tag):
|
||||||
agent_name = me.get('character', 'Unknown')
|
agent_name = me.get('character', 'Unknown')
|
||||||
agent_counts[agent_name] = agent_counts.get(agent_name, 0) + 1
|
agent_counts[agent_name] = agent_counts.get(agent_name, 0) + 1
|
||||||
|
|
||||||
# Stats sammeln
|
|
||||||
stats = me.get('stats', {})
|
stats = me.get('stats', {})
|
||||||
m_kills = stats.get('kills', 0)
|
m_kills = stats.get('kills', 0)
|
||||||
m_deaths = stats.get('deaths', 0)
|
m_deaths = stats.get('deaths', 0)
|
||||||
|
|
@ -1600,7 +1607,6 @@ def get_valorant_stats(name, tag):
|
||||||
total_deaths += m_deaths
|
total_deaths += m_deaths
|
||||||
total_assists += m_assists
|
total_assists += m_assists
|
||||||
|
|
||||||
# Rundenauswertung für Win/Loss & Schaden
|
|
||||||
teams = match.get('teams', {})
|
teams = match.get('teams', {})
|
||||||
my_team_color = me.get('team', '').lower()
|
my_team_color = me.get('team', '').lower()
|
||||||
my_team_data = teams.get(my_team_color, {})
|
my_team_data = teams.get(my_team_color, {})
|
||||||
|
|
@ -1609,43 +1615,43 @@ def get_valorant_stats(name, tag):
|
||||||
if has_won:
|
if has_won:
|
||||||
wins += 1
|
wins += 1
|
||||||
|
|
||||||
# Runden-Zähler extrahieren
|
|
||||||
red_rounds = teams.get('red', {}).get('rounds_won', 0) or 0
|
red_rounds = teams.get('red', {}).get('rounds_won', 0) or 0
|
||||||
blue_rounds = teams.get('blue', {}).get('rounds_won', 0) or 0
|
blue_rounds = teams.get('blue', {}).get('rounds_won', 0) or 0
|
||||||
rounds_played = red_rounds + blue_rounds
|
rounds_played = red_rounds + blue_rounds
|
||||||
total_rounds += rounds_played
|
total_rounds += rounds_played
|
||||||
|
|
||||||
# Score-Anzeige formatieren (z.B. "13 - 5")
|
|
||||||
if my_team_color == 'red':
|
if my_team_color == 'red':
|
||||||
score_str = f"{red_rounds} : {blue_rounds}"
|
score_str = f"{red_rounds} : {blue_rounds}"
|
||||||
else:
|
else:
|
||||||
score_str = f"{blue_rounds} : {red_rounds}"
|
score_str = f"{blue_rounds} : {red_rounds}"
|
||||||
|
|
||||||
# Schaden aus Runden summieren
|
|
||||||
match_damage = 0
|
match_damage = 0
|
||||||
round_data = match.get('rounds', [])
|
round_data = match.get('rounds', [])
|
||||||
for r in round_data:
|
for r in round_data:
|
||||||
player_stats = r.get('player_stats', [])
|
p_round_stat = next(
|
||||||
p_round_stat = next((ps for ps in player_stats if ps.get('player_name', '').lower() == name.lower()),
|
(ps for ps in r.get('player_stats', []) if ps.get('player_name', '').lower() == name.lower()), None)
|
||||||
None)
|
|
||||||
if p_round_stat:
|
if p_round_stat:
|
||||||
match_damage += p_round_stat.get('damage', 0)
|
match_damage += p_round_stat.get('damage', 0)
|
||||||
total_damage += match_damage
|
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({
|
processed_matches.append({
|
||||||
"map": metadata.get('map', 'Unknown'),
|
"map": metadata.get('map', 'Unknown'),
|
||||||
"mode": metadata.get('mode', 'Unknown'),
|
"mode": metadata.get('mode', 'Unknown'),
|
||||||
"agent": agent_name,
|
"agent": agent_name,
|
||||||
"agent_img": me.get('assets', {}).get('agent', {}).get('small', ''),
|
"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,
|
"kills": m_kills,
|
||||||
"deaths": m_deaths,
|
"deaths": m_deaths,
|
||||||
"assists": m_assists,
|
"assists": m_assists,
|
||||||
"score": score_str,
|
"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
|
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
|
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
|
adr_calculated = round(total_damage / total_rounds, 1) if total_rounds > 0 else 0
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue