324 lines
15 KiB
HTML
324 lines
15 KiB
HTML
{{ define "full_calc" }}
|
|
|
|
<div class="modal modal-lg fade" data-bs-backdrop="static" data-bs-keyboard="false" id="fullCalcModal" tabindex="-1">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h1 class="modal-title fs-3 text-secondary-emphasis fw-bold" id="fullCalcModalLabel">Infantryskill-Ergebnis</h1>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body px-0">
|
|
<div class="row px-2">
|
|
<div class="col-6 d-flex flex-column border-end border-secondary px-1 pb-2" id="home-clan-results">
|
|
<h3 class="pb-3 text-center text-primary border-bottom border-primary-subtle fw-bold" id="home-clan-name">a</h3>
|
|
<!-- Dynamically added -->
|
|
</div>
|
|
<div class="col-6 d-flex flex-column px-1 mb-2" id="opponent-clan-results">
|
|
<h3 class="pb-3 text-center text-danger border-bottom border-danger-subtle fw-bold" id="opp-clan-name">b</h3>
|
|
<!-- Dynamically added -->
|
|
</div>
|
|
</div>
|
|
<div class="text-light-emphasis">
|
|
<hr class="mt-0">
|
|
</div>
|
|
<div class="row justify-content-center">
|
|
<div class="col-3 text-center fs-5 me-4 ps-0">
|
|
Avg. Score: <span id="home-avg-score"><i class="spinner-grow spinner-grow-sm text-secondary align-baseline mx-2" role="status"></i></span>
|
|
</div>
|
|
<div class="col-2 text-center fs-5">
|
|
Diff: <span id="diff-score"><i class="spinner-grow spinner-grow-sm text-secondary align-baseline mx-2" role="status"></i></span>
|
|
</div>
|
|
<div class="col-3 text-center fs-5 ms-4 pe-0">
|
|
Avg. Score: <span id="opp-avg-score"><i class="spinner-grow spinner-grow-sm text-secondary align-baseline mx-2" role="status"></i></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer justify-content-between">
|
|
<div class="text-center text-secondary ms-3" id="fullCalcInfo" hidden></div>
|
|
<div class="progress w-100" style="height: 30px;" id="fullCalcProgressbar" role="progressbar">
|
|
<div class="progress-bar progress-bar-striped progress-bar-animated" style="width: 0">Lade...</div>
|
|
</div>
|
|
<button type="submit" name="submit" class="btn btn-lg btn-outline-primary" onclick="downloadScreenshot()" hidden>
|
|
<i class="bi bi-download"></i>
|
|
</button>
|
|
<!--<button type="button" class="btn btn-lg btn-secondary" data-bs-dismiss="modal">Schließen</button>-->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<ul class="list-group list-group-horizontal fs-5 px-2 visually-hidden" id="result-item">
|
|
<li class="list-group-item border-0 rounded-0 border-bottom border-secondary-subtle w-75 text-light">
|
|
<i class="bi bi-question-square text-secondary me-2"></i>
|
|
<span id="username"></span>
|
|
</li>
|
|
<li class="list-group-item border-0 rounded-0 border-bottom border-secondary-subtle text-end w-25 ps-1 pe-3 text-warning">
|
|
<i class="bi bi-trophy text-warning me-2" hidden></i>
|
|
<span id="score"></span>
|
|
</li>
|
|
</ul>
|
|
|
|
<script lang="javascript">
|
|
function getSelectedPlayers(listId) {
|
|
const list = document.getElementById(listId);
|
|
const selectedPlayerNodes = list.querySelectorAll('input[type="checkbox"]:checked');
|
|
const selectedPlayers = [];
|
|
selectedPlayerNodes.forEach(p => {
|
|
p = p.parentElement.parentElement.parentElement.querySelector('span');
|
|
selectedPlayers.push([p.parentElement.getAttribute("data-id"), p.innerText]);
|
|
});
|
|
return selectedPlayers;
|
|
}
|
|
|
|
function getAndInsertScore(playerID, resultList) {
|
|
return fetch('/score/' + playerID)
|
|
.then(response => response.text())
|
|
.then(text => {
|
|
const score = resultList.querySelector('ul[data-id="' + playerID + '"] #score');
|
|
score.innerHTML = text;
|
|
if (!isNaN(parseFloat(text)))
|
|
score.previousElementSibling.hidden = false;
|
|
return text;
|
|
});
|
|
}
|
|
|
|
function downloadScreenshot() {
|
|
const submitBtn = document.querySelector('#fullCalcModal button[name="submit"]');
|
|
submitBtn.hidden = true;
|
|
html2canvas(document.querySelector('#fullCalcModal .modal-content'), {
|
|
backgroundColor: null,
|
|
scale: 1
|
|
}).then(canvas => {
|
|
let link = document.createElement('a');
|
|
let date = new Date().toLocaleString('de-DE', { dateStyle: 'short', timeStyle: 'short' }).replace(', ', '_').replace(':', '-');
|
|
link.download = 'InfantrySkill_' + date + '.png';
|
|
link.href = canvas.toDataURL();
|
|
link.click();
|
|
submitBtn.hidden = false;
|
|
});
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const fullCalcModal = document.getElementById('fullCalcModal');
|
|
const downloadBtn = fullCalcModal.querySelector('button[name="submit"]');
|
|
const progressbar = document.getElementById('fullCalcProgressbar');
|
|
const resultItem = document.getElementById('result-item');
|
|
const homeClanResults = document.getElementById('home-clan-results');
|
|
const oppClanResults = document.getElementById('opponent-clan-results');
|
|
const homeClanList = document.getElementById('home-clan');
|
|
const oppClanList = document.getElementById('opponent-clan');
|
|
const spinnerBorder = '<i class="spinner-border spinner-border-sm text-warning align-baseline me-2" style="margin-left: 0.91rem;" role="status"></i>';
|
|
const spinnerGrow = '<i class="spinner-grow spinner-grow-sm text-secondary align-baseline mx-2" role="status"></i>';
|
|
const dash = '<i class="bi bi-dash mx-2"></i>';
|
|
|
|
const homeAvgScore = document.getElementById('home-avg-score');
|
|
const diffScore = document.getElementById('diff-score');
|
|
const oppAvgScore = document.getElementById('opp-avg-score');
|
|
const fullCalcInfo = document.getElementById('fullCalcInfo');
|
|
|
|
let calcMutex = false;
|
|
let sortMutex = false;
|
|
|
|
function addResultItem(resultList, playerID, playerName) {
|
|
let item = resultList.appendChild(resultItem.cloneNode(true));
|
|
item.querySelector('#username').innerText = playerName;
|
|
item.querySelector('#score').innerHTML = spinnerBorder;
|
|
item.setAttribute('data-id', playerID);
|
|
item.classList.remove('visually-hidden');
|
|
}
|
|
|
|
function calcStatistics() {
|
|
if (calcMutex) {
|
|
setTimeout(calcStatistics, 100);
|
|
return;
|
|
}
|
|
calcMutex = true;
|
|
|
|
let homeScores = [];
|
|
let oppScores = [];
|
|
homeClanResults.querySelectorAll('ul').forEach(e => {
|
|
let score = parseFloat(e.querySelector('#score').innerText);
|
|
if (!isNaN(score)) {
|
|
homeScores.push(score);
|
|
}
|
|
});
|
|
oppClanResults.querySelectorAll('ul').forEach(e => {
|
|
let score = parseFloat(e.querySelector('#score').innerText);
|
|
if (!isNaN(score)) {
|
|
oppScores.push(score);
|
|
}
|
|
});
|
|
|
|
homeScores.sort((a, b) => a - b);
|
|
oppScores.sort((a, b) => a - b);
|
|
let homeAvg = homeScores.reduce((a, b) => a + b, 0) / homeScores.length;
|
|
let oppAvg = oppScores.reduce((a, b) => a + b, 0) / oppScores.length;
|
|
|
|
if (!isNaN(homeAvg))
|
|
homeAvgScore.innerText = homeAvg.toFixed(2);
|
|
if (!isNaN(oppAvg))
|
|
oppAvgScore.innerText = oppAvg.toFixed(2);
|
|
if (!isNaN(homeAvg) && !isNaN(oppAvg))
|
|
diffScore.innerText = (homeAvg - oppAvg).toFixed(2);
|
|
|
|
calcMutex = false;
|
|
}
|
|
|
|
function sortPlayers() {
|
|
if (sortMutex) {
|
|
setTimeout(sortPlayers, 100);
|
|
return;
|
|
}
|
|
sortMutex = true;
|
|
|
|
let homePlayers = Array.from(homeClanResults.querySelectorAll('ul'));
|
|
let oppPlayers = Array.from(oppClanResults.querySelectorAll('ul'));
|
|
homePlayers.sort((a, b) => {
|
|
let aScore = parseFloat(a.querySelector('#score').innerText);
|
|
let bScore = parseFloat(b.querySelector('#score').innerText);
|
|
if (isNaN(aScore)) {
|
|
return 1;
|
|
} else if (isNaN(bScore)) {
|
|
return -1;
|
|
} else {
|
|
return bScore - aScore;
|
|
}
|
|
});
|
|
oppPlayers.sort((a, b) => {
|
|
let aScore = parseFloat(a.querySelector('#score').innerText);
|
|
let bScore = parseFloat(b.querySelector('#score').innerText);
|
|
if (isNaN(aScore)) {
|
|
return 1;
|
|
} else if (isNaN(bScore)) {
|
|
return -1;
|
|
} else {
|
|
return bScore - aScore;
|
|
}
|
|
});
|
|
homePlayers.forEach(p => homeClanResults.appendChild(p));
|
|
oppPlayers.forEach(p => oppClanResults.appendChild(p));
|
|
|
|
sortMutex = false;
|
|
}
|
|
|
|
function setSquadNumbers() {
|
|
let homePlayers = Array.from(homeClanResults.querySelectorAll('ul'));
|
|
let oppPlayers = Array.from(oppClanResults.querySelectorAll('ul'));
|
|
let playerCounter = 0;
|
|
|
|
function setSquadNumber(player, squadNum) {
|
|
player.querySelector('#username').previousElementSibling.classList.replace('bi-question-square', 'bi-' + squadNum + '-square');
|
|
}
|
|
|
|
homePlayers.forEach((p, _) => {
|
|
if (p.querySelector('#score').innerText === '' && p.querySelector('#score').innerHTML !== spinnerBorder) {
|
|
setSquadNumber(p, 'x');
|
|
} else {
|
|
let squadNum = Math.floor(playerCounter / 4) + 1;
|
|
setSquadNumber(p, squadNum);
|
|
playerCounter++;
|
|
}
|
|
});
|
|
playerCounter = 0;
|
|
oppPlayers.forEach((p, _) => {
|
|
if (p.querySelector('#score').innerText === '' && p.querySelector('#score').innerHTML !== spinnerBorder) {
|
|
setSquadNumber(p, 'x');
|
|
} else {
|
|
let squadNum = Math.floor(playerCounter / 4) + 1;
|
|
setSquadNumber(p, squadNum);
|
|
playerCounter++;
|
|
}
|
|
});
|
|
}
|
|
|
|
function cleanupStatistic(statisticField) {
|
|
if (statisticField.innerHTML === spinnerGrow)
|
|
statisticField.innerHTML = dash;
|
|
}
|
|
|
|
function updateScoreInClanList(clanListId, playerID, score) {
|
|
let clanPlayers = document.getElementById(clanListId).querySelectorAll('div[data-id]');
|
|
clanPlayers.forEach(p => {
|
|
if (p.getAttribute('data-id') === playerID) {
|
|
p.querySelector('#quickScore').innerHTML = score;
|
|
}
|
|
});
|
|
}
|
|
|
|
function getClanName(clanList) {
|
|
let clanName = clanList.options[clanList.selectedIndex].innerText;
|
|
return clanList.selectedIndex <= 0 ? dash : clanName.replace(/\[.*]/, '').trim();
|
|
}
|
|
|
|
function updateProgress(progress) {
|
|
progressbar.firstElementChild.style.width = progress + '%';
|
|
}
|
|
|
|
if (fullCalcModal) {
|
|
fullCalcModal.addEventListener('show.bs.modal', _ => {
|
|
let homePlayers = getSelectedPlayers('home-player-list');
|
|
let oppPlayers = getSelectedPlayers('opponent-player-list');
|
|
let promises = [];
|
|
let doneCounter = 0;
|
|
|
|
homeClanResults.querySelector('#home-clan-name').innerHTML = getClanName(homeClanList);
|
|
oppClanResults.querySelector('#opp-clan-name').innerHTML = getClanName(oppClanList);
|
|
|
|
homePlayers.forEach(p => {
|
|
addResultItem(homeClanResults, p[0], p[1]);
|
|
promises.push(
|
|
getAndInsertScore(p[0], homeClanResults)
|
|
.then(score => {
|
|
calcStatistics();
|
|
sortPlayers();
|
|
updateScoreInClanList('home-player-list', p[0], score);
|
|
updateProgress(100 * (++doneCounter / (homePlayers.length + oppPlayers.length)));
|
|
})
|
|
);
|
|
});
|
|
|
|
oppPlayers.forEach(p => {
|
|
addResultItem(oppClanResults, p[0], p[1]);
|
|
promises.push(
|
|
getAndInsertScore(p[0], oppClanResults)
|
|
.then(score => {
|
|
calcStatistics();
|
|
sortPlayers();
|
|
updateScoreInClanList('opponent-player-list', p[0], score);
|
|
updateProgress(100 * (++doneCounter / (homePlayers.length + oppPlayers.length)));
|
|
})
|
|
);
|
|
});
|
|
|
|
Promise.all(promises).then(_ => {
|
|
setSquadNumbers();
|
|
|
|
cleanupStatistic(homeAvgScore);
|
|
cleanupStatistic(diffScore);
|
|
cleanupStatistic(oppAvgScore);
|
|
|
|
progressbar.hidden = true;
|
|
downloadBtn.hidden = false;
|
|
fullCalcInfo.hidden = false;
|
|
fullCalcInfo.innerHTML = 'Erstellt von <b>{{ .Username }}</b> am ' +
|
|
new Date().toLocaleString('de-DE', { dateStyle: 'short', timeStyle: 'short' }) + ' Uhr';
|
|
});
|
|
});
|
|
|
|
fullCalcModal.addEventListener('hidden.bs.modal', _ => {
|
|
homeClanResults.querySelectorAll('ul').forEach(e => e.remove());
|
|
oppClanResults.querySelectorAll('ul').forEach(e => e.remove());
|
|
homeAvgScore.innerHTML = spinnerGrow;
|
|
diffScore.innerHTML = spinnerGrow;
|
|
oppAvgScore.innerHTML = spinnerGrow;
|
|
downloadBtn.hidden = true;
|
|
fullCalcInfo.hidden = true;
|
|
progressbar.hidden = false;
|
|
progressbar.firstElementChild.style.width = '0';
|
|
});
|
|
}
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
{{ end }} |