Merge remote-tracking branch 'origin/main'

main
Benjamin Kraft 3 months ago
commit 5733606f03
  1. 266
      public/elotracker/chart-integration.js
  2. 82
      public/elotracker/index.php
  3. 57
      public/elotracker/leaderboard_list.php
  4. 49
      public/elotracker/styles.css
  5. 1
      public/img/material-symbols/sync_24dp_FILL1_wght300_GRAD0_opsz24.svg
  6. 19
      public/index.php
  7. 1
      public/util/mysql_connect.php

@ -1,9 +1,99 @@
window.onload = async function(){
let all_dates = []; // Alle Daten für die für min. einen Spieler ein Rang gespeichert ist
let all_rank_yDatasets = []; // Datasets, also die einzelnen Linien im Graphen, beinhaltet player_points
let all_progress_yDatasets = []; // Datasets, also die einzelnen Linien im Graphen, beinhaltet die Differenz der aktuellen player_points und der start player_points
let player_points = {}; // puuid zeigt auf eine Liste von Punkten, welche die y-Koordinaten im Graphen darstellen
let player_pointprogress = {}; // puuid zeigt auf eine Liste von Punkten, welche die y-Koordinaten im Graphen darstellen
let combined_charts = [];
let player_charts = [];
const x_scale = {
display: true,
type: "timeseries",
time: {
parser: "dd.MM.yy HH:mm",
tooltipFormat: "dd.MM.yy HH:mm",
unit: "day",
unitStepSize: 1,
displayFormats: {
"day": "dd.MM.yy",
}
},
ticks: {
callback: (value, index, ticks) => {
let tickdate = new Date(value);
if (index === 0) return `${tickdate.getDate()}.${month_names[tickdate.getMonth()]}`;
let prev_tickdate = new Date(ticks[index-1].value);
if (prev_tickdate.getDate() === tickdate.getDate()) {
return null;
}
return `${tickdate.getDate()}.${month_names[tickdate.getMonth()]}`;
}
}
}
const zoom_plugin = {
zoom: {
wheel: {
enabled: true,
},
pinch: {
enabled: true,
},
mode: "x",
},
pan: {
enabled: true,
mode: "x",
},
}
const trigger_legend_hover = function (e, legendItem, legend) {
if (legendItem.hidden) {
return;
}
legend.chart.data.datasets.forEach((dataset, i) => {
dataset.backgroundColor = (legendItem.datasetIndex === i || dataset.backgroundColor.length === 9) ? dataset.backgroundColor : dataset.backgroundColor + '3D';
dataset.borderColor = (legendItem.datasetIndex === i || dataset.borderColor.length === 9) ? dataset.borderColor : dataset.borderColor + '3D';
dataset.borderWidth = legendItem.datasetIndex === i ? 4 : 3;
dataset.pointRadius = 2;
});
legend.chart.update();
}
const trigger_legend_leave = function (e, legendItem, legend) {
legend.chart.data.datasets.forEach((dataset, i) => {
dataset.backgroundColor = dataset.backgroundColor.length === 9 ? dataset.backgroundColor.slice(0, -2) : dataset.backgroundColor;
dataset.borderColor = dataset.borderColor.length === 9 ? dataset.borderColor.slice(0, -2) : dataset.borderColor;
dataset.borderWidth = 3;
});
legend.chart.update();
}
const legend_plugin = {
position: "bottom",
labels: {
padding: 10,
useBorderRadius: true,
borderRadius: 2,
boxWidth: 20,
},
onHover: trigger_legend_hover,
onLeave: trigger_legend_leave,
onClick: function (e, legendItem, legend) {
if (legend.chart.isDatasetVisible(legendItem.datasetIndex)) {
trigger_legend_leave(e, legendItem, legend);
legend.chart.hide(legendItem.datasetIndex);
legendItem.hidden = true;
} else {
legend.chart.show(legendItem.datasetIndex);
legendItem.hidden = false;
trigger_legend_hover(e, legendItem, legend);
}
}
}
window.onload = create_charts;
async function create_charts() {
combined_charts.forEach(chart => chart.destroy());
combined_charts = [];
player_charts.forEach(chart => chart.destroy());
player_charts = [];
let player_rank_values = {};
let player_progress_values = {};
let player_entries = {}; // puuid zeigt auf player entries
let player_entries_byName = {}; // playername zeigt auf entries (damit im kombinierten Graphen die Tooltips korrekt gerendert werden können)
let player_accounts = {}; // puuid zeigt auf player account
@ -15,39 +105,28 @@ window.onload = async function(){
.then(result => {
player_entries = result["entries"];
player_accounts = result["accounts"];
for (const puuid in player_entries) {
// Alle Daten für die Spieler Einträge haben sollen in all_dates
for (const entry_date in player_entries[puuid]) {
all_dates.push(entry_date)
}
// Hier schonmal puuids/namen auf leere Arrays setzen, damit später einfach .push verwendet werden kann
player_points[puuid] = [];
player_pointprogress[puuid] = [];
player_entries_byName[`${player_accounts[puuid]["gameName"]}#${player_accounts[puuid]["tagLine"]}`] = [];
}
// Daten sortieren und Duplicates entfernen
all_dates.sort();
all_dates = [...new Set(all_dates)];
let all_rank_yDatasets = []; // Datasets, also die einzelnen Linien im Graphen, beinhaltet player_rank_values
let all_progress_yDatasets = []; // Datasets, also die einzelnen Linien im Graphen, beinhaltet player_progress_values
let color_counter = 0;
for (const puuid in player_entries) {
player_rank_values[puuid] = [];
player_progress_values[puuid] = [];
player_entries_byName[`${player_accounts[puuid]["gameName"]}#${player_accounts[puuid]["tagLine"]}`] = [];
let player_start_points = -1;
for (const date_string of all_dates) {
// Für alle Player Entries Punktzahl berechnen und in player_points eintragen
for (const timestamp in player_entries[puuid]) {
// Für alle Player Entries Punktzahl und Punktedifferenz berechnen
// Bei der Gelegenheit auch Entries in player_entries_byName eintragen
if (date_string in player_entries[puuid]) {
const current_points = rank_to_points(player_entries[puuid][date_string]["tier"],player_entries[puuid][date_string]["rank"],player_entries[puuid][date_string]["points"]);
player_points[puuid].push(current_points);
player_entries_byName[`${player_accounts[puuid]["gameName"]}#${player_accounts[puuid]["tagLine"]}`][date_string] = player_entries[puuid][date_string];
const current_points = rank_to_points(player_entries[puuid][timestamp]["tier"], player_entries[puuid][timestamp]["rank"], player_entries[puuid][timestamp]["points"]);
player_rank_values[puuid].push({x: parseInt(timestamp) * 1000, y: current_points});
player_entries_byName[`${player_accounts[puuid]["gameName"]}#${player_accounts[puuid]["tagLine"]}`][timestamp] = player_entries[puuid][timestamp];
if (player_start_points === -1) {
player_start_points = current_points;
player_pointprogress[puuid].push(0);
player_progress_values[puuid].push({x: parseInt(timestamp) * 1000, y: 0});
} else {
player_pointprogress[puuid].push(current_points - player_start_points);
}
} else {
player_points[puuid].push(null);
player_pointprogress[puuid].push(null);
player_progress_values[puuid].push({x: parseInt(timestamp) * 1000, y: current_points - player_start_points});
}
}
// Linie für den Spieler zu Datasets des Graphen hinzufügen
@ -56,24 +135,25 @@ window.onload = async function(){
fill: false,
borderColor: getColor(color_counter),
backgroundColor: getColor(color_counter),
data: player_points[puuid],
data: player_rank_values[puuid],
spanGaps: true,
pointHitRadius: 16,
})
all_progress_yDatasets.push({
label: `${player_accounts[puuid]["gameName"]}#${player_accounts[puuid]["tagLine"]}`,
fill: false,
borderColor: getColor(color_counter),
backgroundColor: getColor(color_counter),
data: player_pointprogress[puuid],
data: player_progress_values[puuid],
spanGaps: true,
pointHitRadius: 16,
})
color_counter++;
}
// Graphen erstellen
new Chart(`progress-chart-combined`, {
combined_charts.push(new Chart(`progress-chart-combined`, {
type: "line",
data: {
labels: all_dates,
datasets: all_rank_yDatasets,
},
options: {
@ -81,15 +161,18 @@ window.onload = async function(){
tooltip: {
callbacks: {
label: function(context) {
return format_rank(player_entries_byName[context.dataset.label][context.label]["tier"],player_entries_byName[context.dataset.label][context.label]["rank"],player_entries_byName[context.dataset.label][context.label]["points"])
return format_rank(player_entries_byName[context.dataset.label][context.parsed.x/1000]["tier"],player_entries_byName[context.dataset.label][context.parsed.x/1000]["rank"],player_entries_byName[context.dataset.label][context.parsed.x/1000]["points"])
},
beforeTitle: function (context) {
return context[0].dataset.label;
},
}
}
},
zoom: zoom_plugin,
legend: legend_plugin,
},
scales: {
x: x_scale,
y: {
display: true,
stepSize: 100,
@ -103,11 +186,10 @@ window.onload = async function(){
responsive: true,
maintainAspectRatio: false,
}
});
new Chart(`progress-chart-combined-progress`, {
}));
combined_charts.push(new Chart(`progress-chart-combined-progress`, {
type: "line",
data: {
labels: all_dates,
datasets: all_progress_yDatasets,
},
options: {
@ -115,15 +197,18 @@ window.onload = async function(){
tooltip: {
callbacks: {
label: function(context) {
return format_rank(player_entries_byName[context.dataset.label][context.label]["tier"],player_entries_byName[context.dataset.label][context.label]["rank"],player_entries_byName[context.dataset.label][context.label]["points"])
return format_rank(player_entries_byName[context.dataset.label][context.parsed.x/1000]["tier"],player_entries_byName[context.dataset.label][context.parsed.x/1000]["rank"],player_entries_byName[context.dataset.label][context.parsed.x/1000]["points"])
},
beforeTitle: function (context) {
return context[0].dataset.label;
},
}
}
},
zoom: zoom_plugin,
legend: legend_plugin,
},
scales: {
x: x_scale,
y: {
display: true,
},
@ -131,7 +216,7 @@ window.onload = async function(){
responsive: true,
maintainAspectRatio: false,
}
});
}));
})
.catch(e => console.error(e))
@ -140,23 +225,21 @@ window.onload = async function(){
let puuid = chart.id.split("-");
puuid.splice(0,2);
puuid = puuid.join("-");
let xValues = [];
let yValues = [];
let values = [];
for (const entriesKey in player_entries[puuid]) {
let points = rank_to_points(player_entries[puuid][entriesKey]["tier"], player_entries[puuid][entriesKey]["rank"], player_entries[puuid][entriesKey]["points"]);
xValues.push(entriesKey);
yValues.push(points);
values.push({x: parseInt(entriesKey)*1000, y: points});
}
new Chart(`progress-chart-${puuid}`, {
player_charts.push(new Chart(`progress-chart-${puuid}`, {
type: "line",
data: {
labels: xValues,
datasets: [{
label: `${player_accounts[puuid]["gameName"]}#${player_accounts[puuid]["tagLine"]}`,
fill: false,
borderColor: "rgba(150,150,175)",
backgroundColor: "rgba(150,150,175)",
data: yValues
data: values,
pointHitRadius: 16,
}]
},
options: {
@ -165,15 +248,17 @@ window.onload = async function(){
tooltip: {
callbacks: {
label: function(context) {
return format_rank(player_entries[puuid][context.label]["tier"],player_entries[puuid][context.label]["rank"],player_entries[puuid][context.label]["points"])
return format_rank(player_entries[puuid][context.parsed.x/1000]["tier"],player_entries[puuid][context.parsed.x/1000]["rank"],player_entries[puuid][context.parsed.x/1000]["points"])
},
beforeTitle: function (context) {
return context[0].dataset.label;
},
}
}
},
zoom: zoom_plugin,
},
scales: {
x: x_scale,
y: {
display: true,
stepSize: 100,
@ -187,10 +272,9 @@ window.onload = async function(){
responsive: true,
maintainAspectRatio: false,
}
});
}));
}
};
}
function rank_to_points(tier,rank,lp) {
const apex_tiers = (tier === "MASTER" || tier === "GRANDMASTER" || tier === "CHALLENGER");
@ -267,12 +351,80 @@ function toggle_combined_chart() {
chart.classList.add("closed");
}
}
function toggle_leaderboard_chart() {
function toggle_leaderboard_chart(event) {
if (this.classList.contains("closed")) {
this.classList.remove("closed");
} else {
if (event.target.nodeName === "CANVAS") return;
this.classList.add("closed");
}
}
document.querySelectorAll("button.open-general-graph").forEach(element => element.addEventListener("click", toggle_combined_chart));
document.querySelectorAll("button.leaderboard-element").forEach(element => element.addEventListener("click", toggle_leaderboard_chart));
document.querySelectorAll("button.leaderboard-element").forEach(element => element.addEventListener("mousedown", toggle_leaderboard_chart));
async function update_leaderboard_entries() {
this.disabled = true;
this.classList.add("button-updating")
let eventSource = new EventSource("./update.php");
eventSource.addEventListener("progress", e => {
this.style.setProperty("--button-loading-bar-width", `${e.data*100}%`);
})
eventSource.addEventListener("forbidden", e => {
const currenttime = new Date();
const updatetime = new Date(e.data);
let timediff = new Date(currenttime - updatetime);
let resttime = new Date(600000 - (currenttime - updatetime));
window.alert(`Das letzte Update wurde vor ${format_time_minsec(timediff)} durchgeführt. Versuche es in ${format_time_minsec(resttime)} noch einmal`);
reset_button(this);
eventSource.close();
})
eventSource.onerror = e => {
window.alert(`Beim Update ist ein Fehler aufgetreten. Versuche es später noch einmal`)
reset_button(this);
eventSource.close();
}
eventSource.addEventListener("done", e => {
reset_button(this);
eventSource.close();
update_leaderboard_elements();
})
function reset_button(button) {
button.disabled = false;
button.style.setProperty("--button-loading-bar-width", `0`);
button.classList.remove("button-updating");
}
}
document.querySelector("button.update-leaderboard").addEventListener("click", update_leaderboard_entries);
function format_time_minsec(date) {
let format, trenner = "", min = "", nullausgleich = "";
if (date.getMinutes() === 0) {
format = " Sekunden";
} else {
min = date.getMinutes();
format = " Minuten";
trenner = ":";
if (date.getSeconds() < 10) {
nullausgleich = "0";
}
}
return min + trenner + nullausgleich + date.getSeconds() + format;
}
const month_names = ["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"];
async function update_leaderboard_elements() {
fetch(`./leaderboard_list.php`, {
method: "GET",
})
.then(res => res.text())
.then(leaderboard_list => {
// replace updated Leaderboard
document.querySelector(".leaderboard-list").outerHTML = leaderboard_list;
// reapply EventListeners
document.querySelectorAll("button.leaderboard-element").forEach(element => element.addEventListener("click", toggle_leaderboard_chart));
// recreate charts
create_charts();
})
.catch(e => console.error(e));
}

@ -4,81 +4,25 @@
<meta charset="utf-8">
<link href="styles.css" rel="stylesheet">
<title>UEM Elo Tracker</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4/dist/chart.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@3.0/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/hammerjs@2.0/hammer.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom@2.0/dist/chartjs-plugin-zoom.min.js"></script>
</head>
<body>
<?php
require_once __DIR__."/Tracker.php";
$tracker = new Tracker();
$latest_patch = json_decode(file_get_contents("https://ddragon.leagueoflegends.com/api/versions.json"))[0];
echo "<h1>UEM LoL Elo-Challenge</h1>";
echo "<div class='uem-logo-header'><img class='uem-logo' src='./../img/uem-logo.png' alt=''></div>";
echo "<div class='leaderboard'>";
echo "<div class='combined-charts-buttons'>
<h1>UEM LoL Elo-Challenge</h1>
<div class='uem-logo-header'><img class='uem-logo' src='./../img/uem-logo.png' alt=''></div>
<div class='leaderboard'>
<button type='button' class='update-leaderboard progress-button'>Ränge aktualisieren <?php echo file_get_contents(__DIR__."/../img/material-symbols/sync_24dp_FILL1_wght300_GRAD0_opsz24.svg")?></button>
<div class='combined-charts-buttons'>
<button type='button' id='rank-graph' class='open-general-graph'>Rang-Vergleich</button>
<button type='button' id='progress-graph' class='open-general-graph'>Fortschritt-Vergleich</button>
</div>";
echo "<div class='graph-wrapper rank-graph closed'><canvas id=\"progress-chart-combined\" style=\"width:100%;max-width:700px\"></canvas></div>";
echo "<div class='graph-wrapper progress-graph closed'><canvas id=\"progress-chart-combined-progress\" style=\"width:100%;max-width:700px\"></canvas></div>";
echo "<div class='leaderboard-list'>";
$placement_counter = 1;
foreach ($tracker->getProgressions() as $puuid => $progress){
$entries = $tracker->entries[$puuid];
$account = $tracker->accounts[$puuid];
$start_elo = reset($entries);
$start_tier = ($start_elo) ? $start_elo->tier : "UNRANKED";
if ($start_tier == "MASTER" || $start_tier == "GRANDMASTER" || $start_tier == "CHALLENGER") $start_elo->rank = "";
$current_elo = end($entries);
$current_tier = ($current_elo) ? $current_elo->tier : "UNRANKED";
if ($current_tier == "MASTER" || $current_tier == "GRANDMASTER" || $current_tier == "CHALLENGER") $current_elo->rank = "";
$progress = ($progress>=0) ? "+$progress" : $progress;
$tier_lowercase = strtolower($current_tier);
$start_tier_lowercase = strtolower($start_tier);
$tier_ucfirst = ucfirst($tier_lowercase);
$start_tier_ucfirst = ucfirst($start_tier_lowercase);
$gained_lp_sign = ($progress > 0) ? " plus-lp" : (($progress < 0) ? " minus-lp" : "no-lp");
if ($start_elo) {
echo "<button type='button' class='leaderboard-element place-$placement_counter closed'>";
} else {
echo "<button type='button' class='leaderboard-element place-$placement_counter closed' disabled>";
}
echo "<span class='placement'>$placement_counter.</span>";
echo "<div class='player-info'>
<img src='https://ddragon.leagueoflegends.com/cdn/$latest_patch/img/profileicon/$account->profileIconId.png' alt='' style='height: 64px; aspect-ratio: 1 / 1;'>
<h2 class='playername'>$account->gameName<span class='riot-tag'>#$account->tagLine</span></h2>
<h3 class='lp-gained $gained_lp_sign'>$progress LP</h3>
</div>";
echo "<div class='ranked-emblem'><img class='current-rank' src='https://raw.communitydragon.org/latest/plugins/rcp-fe-lol-shared-components/global/default/$tier_lowercase.png' alt=''></div>";
if ($start_elo) {
echo "<div class='elo-gained'>
<div class='rank rank-start'>
<img class='ranked-mini-crest' src='https://raw.communitydragon.org/latest/plugins/rcp-fe-lol-static-assets/global/default/ranked-mini-crests/$start_tier_lowercase.svg' alt=''>
<span class='rank-desc'><span class='rank-tier'>{$start_tier_ucfirst} {$start_elo->rank}</span> <br> <span class='rank-LP'>{$start_elo->points} LP</span></span>
</div>
&rarr;
<div class='rank rank-start'>
<img class='ranked-mini-crest' src='https://raw.communitydragon.org/latest/plugins/rcp-fe-lol-static-assets/global/default/ranked-mini-crests/$tier_lowercase.svg' alt=''>
<span class='rank-desc'><span class='rank-tier'>{$tier_ucfirst} {$current_elo->rank}</span> <br> <span class='rank-LP'>{$current_elo->points} LP</span></span>
<div class='graph-wrapper rank-graph closed'><canvas id="progress-chart-combined" style="width:100%;max-width:700px"></canvas></div>
<div class='graph-wrapper progress-graph closed'><canvas id="progress-chart-combined-progress" style="width:100%;max-width:700px"></canvas></div>
<?php include "leaderboard_list.php"; ?>
</div>
</div>";
echo "<div class='graph-wrapper'><canvas id=\"progress-chart-$puuid\" class='progress-chart' style=\"width:100%;max-width:700px\"></canvas></div>";
}
echo "</button>";
$placement_counter++;
}
echo "</div>";
echo "</div>";
?>
<script src="chart-integration.js"></script>
<script src="chart-integration.js"></script>
</body>
</html>

@ -0,0 +1,57 @@
<?php
require_once __DIR__ . "/Tracker.php";
$tracker = new Tracker();
$latest_patch = json_decode(file_get_contents("https://ddragon.leagueoflegends.com/api/versions.json"))[0];
echo "<div class='leaderboard-list'>";
$placement_counter = 1;
foreach ($tracker->getProgressions() as $puuid => $progress) {
$entries = $tracker->entries[$puuid];
$account = $tracker->accounts[$puuid];
$start_elo = reset($entries);
$start_tier = ($start_elo) ? $start_elo->tier : "UNRANKED";
if ($start_tier == "MASTER" || $start_tier == "GRANDMASTER" || $start_tier == "CHALLENGER") $start_elo->rank = "";
$current_elo = end($entries);
$current_tier = ($current_elo) ? $current_elo->tier : "UNRANKED";
if ($current_tier == "MASTER" || $current_tier == "GRANDMASTER" || $current_tier == "CHALLENGER") $current_elo->rank = "";
$progress = ($progress >= 0) ? "+$progress" : $progress;
$tier_lowercase = strtolower($current_tier);
$start_tier_lowercase = strtolower($start_tier);
$tier_ucfirst = ucfirst($tier_lowercase);
$start_tier_ucfirst = ucfirst($start_tier_lowercase);
$gained_lp_sign = ($progress > 0) ? " plus-lp" : (($progress < 0) ? " minus-lp" : "no-lp");
if ($start_elo) {
echo "<button type='button' class='leaderboard-element place-$placement_counter closed'>";
} else {
echo "<button type='button' class='leaderboard-element place-$placement_counter closed' disabled>";
}
echo "<span class='placement'>$placement_counter.</span>";
echo "<div class='player-info'>
<img src='https://ddragon.leagueoflegends.com/cdn/$latest_patch/img/profileicon/$account->profileIconId.png' alt='' style='height: 64px; aspect-ratio: 1 / 1;'>
<h2 class='playername'>$account->gameName<span class='riot-tag'>#$account->tagLine</span></h2>
<h3 class='lp-gained $gained_lp_sign'>$progress LP</h3>
</div>";
echo "<div class='ranked-emblem'><img class='current-rank' src='https://raw.communitydragon.org/latest/plugins/rcp-fe-lol-shared-components/global/default/$tier_lowercase.png' alt=''></div>";
if ($start_elo) {
echo "<div class='elo-gained'>
<div class='rank rank-start'>
<img class='ranked-mini-crest' src='https://raw.communitydragon.org/latest/plugins/rcp-fe-lol-static-assets/global/default/ranked-mini-crests/$start_tier_lowercase.svg' alt=''>
<span class='rank-desc'><span class='rank-tier'>{$start_tier_ucfirst} {$start_elo->rank}</span> <br> <span class='rank-LP'>{$start_elo->points} LP</span></span>
</div>
&rarr;
<div class='rank rank-start'>
<img class='ranked-mini-crest' src='https://raw.communitydragon.org/latest/plugins/rcp-fe-lol-static-assets/global/default/ranked-mini-crests/$tier_lowercase.svg' alt=''>
<span class='rank-desc'><span class='rank-tier'>{$tier_ucfirst} {$current_elo->rank}</span> <br> <span class='rank-LP'>{$current_elo->points} LP</span></span>
</div>
</div>";
echo "<div class='graph-wrapper'><canvas id=\"progress-chart-$puuid\" class='progress-chart' style=\"width:100%;max-width:700px\"></canvas></div>";
}
echo "</button>";
$placement_counter++;
}
echo "</div>";

@ -20,12 +20,17 @@ h1 {
button {
background: none;
color: inherit;
border: none;
padding: 0;
border: solid 2px #68a8cc;
border-radius: 12px;
padding: 16px 24px;
font: inherit;
cursor: pointer;
outline: inherit;
text-align: unset;
transition: background-color 200ms ease-out;
}
button:hover {
background-color: #1f2931;
}
button[disabled] {
cursor: initial;
@ -44,14 +49,34 @@ img.uem-logo {
height: 120px;
}
button.open-general-graph {
border: solid 2px #68a8cc;
border-radius: 12px;
padding: 16px 24px;
transition: background-color 200ms ease-out;
button.update-leaderboard {
display: flex;
flex-direction: row;
gap: 4px;
align-items: center;
margin-bottom: 8px;
}
button.open-general-graph:hover {
background-color: #1f2931;
button.progress-button {
position: relative;
overflow: hidden;
--button-loading-bar-width: 0;
}
button.progress-button::before {
content: '';
position: absolute;
width: var(--button-loading-bar-width);
height: 100%;
left: 0;
background-color: #294c87;
border-radius: 10px;
transition: width 400ms ease-out;
z-index: -1;
}
button.button-updating svg {
animation: ease_rotating 2s infinite;
}
@keyframes ease_rotating {
to { transform: rotate(-360deg)}
}
.leaderboard {
@ -76,11 +101,15 @@ button.open-general-graph:hover {
border: solid 4px #6a818f;
border-radius: 20px;
padding: 16px 16px 16px 36px;
transition: background-color 200ms ease-out;
transition: background-color 200ms ease;
}
.leaderboard-element:hover {
background-color: #1f2931;
}
.leaderboard-element:has(canvas:hover) {
background-color: transparent;
cursor: initial;
}
.leaderboard-element.place-1 {
border: solid 4px var(--gold-1);
}

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M173.08-173.08v-60H290l-29.08-27.84q-47.46-47.47-69.19-103.04Q170-419.54 170-477.23q0-103.69 60.73-185.96Q291.46-745.46 390-776.15v63.23q-72.39 28.3-116.19 92.73Q230-555.77 230-477.23q0 46.92 17.77 91.15 17.77 44.23 55.31 81.77l25.38 25.39v-109.54h60v215.38H173.08ZM570-183.85v-63.23q72.39-28.3 116.19-92.73Q730-404.23 730-482.77q0-46.92-17.77-91.15-17.77-44.23-55.31-81.77l-25.38-25.39v109.54h-60v-215.38h215.38v60H670l29.08 27.84q47.46 47.47 69.19 103.04Q790-540.46 790-482.77q0 103.69-60.73 185.96Q668.54-214.54 570-183.85Z"/></svg>

After

Width:  |  Height:  |  Size: 651 B

@ -4,25 +4,6 @@
<meta charset="utf-8">
<link href="styles.css" rel="stylesheet">
<title>University eSports Mainz</title>
<script>
let eventSource = new EventSource("elotracker/update.php");
eventSource.onopen = evt => console.log("Open: ", evt);
eventSource.addEventListener("progress", evt => {
console.log("Progress: ", evt.data);
})
eventSource.addEventListener("forbidden", evt => {
console.log("Forbidden: ", evt.data);
eventSource.close();
})
eventSource.onerror = evt => {
console.log("Error: ", evt);
eventSource.close();
}
eventSource.addEventListener("done", evt => {
console.log("done: ", evt);
eventSource.close();
})
</script>
</head>
<body>
<a href="elotracker">Zum Elo Tracker</a>

@ -22,6 +22,7 @@ class MySQLConnection {
private function createConn(): void {
$this->mysqli = new mysqli($this->host . ":" . $this->port, $this->user, $this->pass, $this->dbName);
$this->mysqli->set_charset("utf8");
}
public function query($sql): mysqli_result|bool {

Loading…
Cancel
Save