405 lines
13 KiB
JavaScript
405 lines
13 KiB
JavaScript
document.getElementById("open-fin-modal").addEventListener("click", function() {
|
|
document.getElementById("fin-modal").style.visibility = "visible";
|
|
if (window.lockBodyScroll) window.lockBodyScroll();
|
|
});
|
|
|
|
document.querySelectorAll(".close-fin-modal").forEach(function(button) {
|
|
button.addEventListener("click", function() {
|
|
document.getElementById("fin-modal").style.visibility = "hidden";
|
|
if (window.unlockBodyScroll) window.unlockBodyScroll();
|
|
});
|
|
});
|
|
|
|
document.getElementById("open-game-modal").addEventListener("click", function() {
|
|
document.getElementById("game-modal").style.visibility = "visible";
|
|
if (window.lockBodyScroll) window.lockBodyScroll();
|
|
});
|
|
|
|
document.querySelectorAll(".close-game-modal").forEach(function(button) {
|
|
button.addEventListener("click", function() {
|
|
document.getElementById("game-modal").style.visibility = "hidden";
|
|
if (window.unlockBodyScroll) window.unlockBodyScroll();
|
|
});
|
|
});
|
|
|
|
document.getElementById("toggle-collapse").addEventListener("click", function() {
|
|
const collapseDiv = document.getElementById("page-collapse");
|
|
if (collapseDiv.style.visibility === "visible") {
|
|
collapseDiv.style.visibility = "hidden";
|
|
} else {
|
|
collapseDiv.style.visibility = "visible";
|
|
}
|
|
});
|
|
|
|
// Igra
|
|
|
|
const gameState = {
|
|
active: false,
|
|
loading: false,
|
|
currentEntry: null,
|
|
normalizedAnswer: "",
|
|
attemptsLeft: 3,
|
|
roundPoints: 100,
|
|
score: 0,
|
|
correct: 0,
|
|
failed: 0,
|
|
guesses: 0,
|
|
currentWordGuessed: false
|
|
};
|
|
|
|
const gameElements = {};
|
|
|
|
function stripHtmlTags(html) {
|
|
return String(html || "")
|
|
.replace(/<\s*br\s*\/?>/gi, "\n")
|
|
.replace(/<\s*\/p\s*>/gi, "\n")
|
|
.replace(/<\s*p[^>]*>/gi, "")
|
|
.replace(/<[^>]+>/g, "")
|
|
.replace(/ /g, " ")
|
|
.replace(/&/g, "&")
|
|
.replace(/</g, "<")
|
|
.replace(/>/g, ">")
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, "'")
|
|
.replace(/\n{3,}/g, "\n\n")
|
|
.trim();
|
|
}
|
|
|
|
function normalizeGuess(value) {
|
|
return String(value || "")
|
|
.toLowerCase()
|
|
.normalize("NFD")
|
|
.replace(/[\u0300-\u036f]/g, "")
|
|
.replace(/\s+/g, "")
|
|
.trim();
|
|
}
|
|
|
|
function parseDefinitions(html) {
|
|
const plain = stripHtmlTags(html);
|
|
return plain
|
|
.split(/\n+/)
|
|
.map(line => line.trim())
|
|
.filter(Boolean);
|
|
}
|
|
|
|
function setGameMessage(message, type) {
|
|
if (!gameElements.feedback) {
|
|
return;
|
|
}
|
|
|
|
gameElements.feedback.textContent = message;
|
|
gameElements.feedback.classList.remove("is-success", "is-error", "is-neutral");
|
|
gameElements.feedback.classList.add(type || "is-neutral");
|
|
}
|
|
|
|
function updateGameStats() {
|
|
if (gameElements.attemptsLeft) {
|
|
gameElements.attemptsLeft.textContent = String(gameState.attemptsLeft);
|
|
}
|
|
|
|
if (gameElements.roundPoints) {
|
|
gameElements.roundPoints.textContent = String(gameState.roundPoints);
|
|
}
|
|
|
|
if (gameElements.score) {
|
|
gameElements.score.textContent = String(gameState.score);
|
|
}
|
|
|
|
if (gameElements.correct) {
|
|
gameElements.correct.textContent = String(gameState.correct);
|
|
}
|
|
|
|
if (gameElements.failed) {
|
|
gameElements.failed.textContent = String(gameState.failed);
|
|
}
|
|
|
|
if (gameElements.guesses) {
|
|
gameElements.guesses.textContent = String(gameState.guesses);
|
|
}
|
|
}
|
|
|
|
function setGameScreen(screen) {
|
|
const screens = ["start", "play", "stats"];
|
|
screens.forEach(name => {
|
|
const element = gameElements[`${name}Screen`];
|
|
if (element) {
|
|
element.hidden = name !== screen;
|
|
}
|
|
});
|
|
}
|
|
|
|
function resetRoundState() {
|
|
gameState.loading = false;
|
|
gameState.attemptsLeft = 3;
|
|
gameState.roundPoints = 100;
|
|
gameState.currentWordGuessed = false;
|
|
updateGameStats();
|
|
setGameMessage("", "is-neutral");
|
|
if (gameElements.guessInput) {
|
|
gameElements.guessInput.value = "";
|
|
gameElements.guessInput.disabled = false;
|
|
gameElements.guessInput.focus();
|
|
}
|
|
if (gameElements.submitGuessButton) {
|
|
gameElements.submitGuessButton.disabled = false;
|
|
}
|
|
}
|
|
|
|
function renderCurrentEntry(entry) {
|
|
const definitions = parseDefinitions(entry?.Vsebina);
|
|
const typeText = entry?.Tip || "-";
|
|
|
|
if (gameElements.wordType) {
|
|
gameElements.wordType.textContent = typeText;
|
|
}
|
|
|
|
if (gameElements.definitions) {
|
|
if (!definitions.length) {
|
|
gameElements.definitions.innerHTML = '<p class="game-empty-state">Opis za ta vnos ni na voljo.</p>';
|
|
} else {
|
|
gameElements.definitions.innerHTML = definitions
|
|
.map(definition => `<div class="game-definition-line">${definition}</div>`)
|
|
.join("");
|
|
}
|
|
}
|
|
|
|
gameState.currentEntry = entry;
|
|
gameState.normalizedAnswer = normalizeGuess(entry?.Kljuc);
|
|
resetRoundState();
|
|
}
|
|
|
|
function showGameStats() {
|
|
if (gameElements.statScore) {
|
|
gameElements.statScore.textContent = String(gameState.score);
|
|
}
|
|
if (gameElements.statCorrect) {
|
|
gameElements.statCorrect.textContent = String(gameState.correct);
|
|
}
|
|
if (gameElements.statFailed) {
|
|
gameElements.statFailed.textContent = String(gameState.failed);
|
|
}
|
|
if (gameElements.statGuesses) {
|
|
gameElements.statGuesses.textContent = String(gameState.guesses);
|
|
}
|
|
setGameScreen("stats");
|
|
}
|
|
|
|
function nextWord() {
|
|
if (!gameState.active) {
|
|
return;
|
|
}
|
|
|
|
gameState.loading = true;
|
|
setGameMessage("Nalagam nov vnos ...", "is-neutral");
|
|
|
|
fetch("https://ssnj.dcrubro.com/api/random-vnos", { method: "GET" })
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP ${response.status}`);
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(data => {
|
|
if (!data || !data.success || !data.data) {
|
|
throw new Error("Neveljaven odgovor strežnika");
|
|
}
|
|
|
|
renderCurrentEntry(data.data);
|
|
setGameScreen("play");
|
|
setGameMessage("Ugibajte besedo glede na definicijo.", "is-neutral");
|
|
})
|
|
.catch(error => {
|
|
console.error("random-vnos error", error);
|
|
setGameMessage("Napaka pri nalaganju novega vnosa. Poskusite znova.", "is-error");
|
|
gameState.loading = false;
|
|
})
|
|
.finally(() => {
|
|
gameState.loading = false;
|
|
});
|
|
}
|
|
|
|
function finishCurrentWord(correctlyGuessed) {
|
|
if (correctlyGuessed) {
|
|
gameState.correct += 1;
|
|
} else {
|
|
gameState.failed += 1;
|
|
gameState.score = Math.max(0, gameState.score - 30);
|
|
}
|
|
|
|
updateGameStats();
|
|
if (gameElements.guessInput) {
|
|
gameElements.guessInput.value = "";
|
|
}
|
|
|
|
setTimeout(() => {
|
|
if (gameState.active) {
|
|
nextWord();
|
|
}
|
|
}, 700);
|
|
}
|
|
|
|
function submitGuess() {
|
|
if (!gameState.active || gameState.loading || !gameState.currentEntry) {
|
|
return;
|
|
}
|
|
|
|
const guess = normalizeGuess(gameElements.guessInput ? gameElements.guessInput.value : "");
|
|
if (!guess) {
|
|
setGameMessage("Vnesite svoj ugib.", "is-error");
|
|
return;
|
|
}
|
|
|
|
gameState.guesses += 1;
|
|
updateGameStats();
|
|
|
|
if (guess === gameState.normalizedAnswer) {
|
|
gameState.currentWordGuessed = true;
|
|
gameState.score += gameState.roundPoints;
|
|
setGameMessage(`Pravilno. Rešitev je ${gameState.currentEntry.Kljuc}.`, "is-success");
|
|
updateGameStats();
|
|
finishCurrentWord(true);
|
|
return;
|
|
}
|
|
|
|
gameState.attemptsLeft -= 1;
|
|
gameState.roundPoints = gameState.attemptsLeft === 2 ? 50 : gameState.attemptsLeft === 1 ? 25 : 0;
|
|
updateGameStats();
|
|
|
|
if (gameState.attemptsLeft > 0) {
|
|
setGameMessage(`Napačno. Preostali poskusi: ${gameState.attemptsLeft}.`, "is-error");
|
|
if (gameElements.guessInput) {
|
|
gameElements.guessInput.value = "";
|
|
gameElements.guessInput.focus();
|
|
}
|
|
return;
|
|
}
|
|
|
|
setGameMessage(`Tudi tretji poskus ni uspel. Rešitev je ${gameState.currentEntry.Kljuc}.`, "is-error");
|
|
finishCurrentWord(false);
|
|
}
|
|
|
|
function startGame() {
|
|
gameState.active = true;
|
|
gameState.score = 0;
|
|
gameState.correct = 0;
|
|
gameState.failed = 0;
|
|
gameState.guesses = 0;
|
|
updateGameStats();
|
|
setGameScreen("play");
|
|
nextWord();
|
|
}
|
|
|
|
function bindGameElements() {
|
|
gameElements.startScreen = document.getElementById("game-start-screen");
|
|
gameElements.playScreen = document.getElementById("game-play-screen");
|
|
gameElements.statsScreen = document.getElementById("game-stats-screen");
|
|
gameElements.wordType = document.getElementById("game-word-type");
|
|
gameElements.definitions = document.getElementById("game-definitions");
|
|
gameElements.guessInput = document.getElementById("game-guess-input");
|
|
gameElements.submitGuessButton = document.getElementById("submit-guess-button");
|
|
gameElements.restartGameButton = document.getElementById("restart-game-button");
|
|
gameElements.feedback = document.getElementById("game-feedback");
|
|
gameElements.attemptsLeft = document.getElementById("game-attempts-left");
|
|
gameElements.roundPoints = document.getElementById("game-round-points");
|
|
gameElements.score = document.getElementById("game-stat-score");
|
|
gameElements.correct = document.getElementById("game-stat-correct");
|
|
gameElements.failed = document.getElementById("game-stat-failed");
|
|
gameElements.guesses = document.getElementById("game-stat-guesses");
|
|
gameElements.statScore = document.getElementById("game-stat-score");
|
|
gameElements.statCorrect = document.getElementById("game-stat-correct");
|
|
gameElements.statFailed = document.getElementById("game-stat-failed");
|
|
gameElements.statGuesses = document.getElementById("game-stat-guesses");
|
|
}
|
|
|
|
bindGameElements();
|
|
|
|
document.getElementById("start-game-button").addEventListener("click", startGame);
|
|
document.getElementById("submit-guess-button").addEventListener("click", submitGuess);
|
|
document.getElementById("restart-game-button").addEventListener("click", startGame);
|
|
document.getElementById("game-guess-input").addEventListener("keydown", function(event) {
|
|
if (event.key === "Enter") {
|
|
event.preventDefault();
|
|
submitGuess();
|
|
}
|
|
});
|
|
// Konec igre
|
|
|
|
// Davčne stopnje in razredi za leto 2025
|
|
const taxBrackets = [
|
|
{ razred: 1, min: 0, max: 9210.26, rate: 16 },
|
|
{ razred: 2, min: 9210.26, max: 27089.00, rate: 26 },
|
|
{ razred: 3, min: 27089.00, max: 54178.00, rate: 33 },
|
|
{ razred: 4, min: 54178.00, max: 78016.32, rate: 39 },
|
|
{ razred: 5, min: 78016.32, max: Infinity, rate: 50 }
|
|
];
|
|
|
|
const STANDARD_DEDUCTION = 5551.93;
|
|
|
|
function parseEurAmount(input) {
|
|
if (!input) return null;
|
|
// Remove spaces, replace . with empty (thousands separator) and , with . (decimal)
|
|
let normalized = input.trim().replace(/\s/g, "").replace(/\./g, "").replace(",", ".");
|
|
let num = parseFloat(normalized);
|
|
return isNaN(num) ? null : num;
|
|
}
|
|
|
|
function formatEurAmount(num) {
|
|
// Format with thousands separator (.) and decimal separator (,)
|
|
return num.toFixed(2).replace(".", ",").replace(/\B(?=(\d{3})+(?!\d))/g, ".");
|
|
}
|
|
|
|
function calculateTaxBracket(amount) {
|
|
for (let bracket of taxBrackets) {
|
|
if (amount >= bracket.min && amount < bracket.max) {
|
|
return bracket;
|
|
}
|
|
}
|
|
return taxBrackets[taxBrackets.length - 1]; // Return highest bracket
|
|
}
|
|
|
|
function calculateProgressiveTax(amount) {
|
|
let totalTax = 0;
|
|
|
|
for (let bracket of taxBrackets) {
|
|
if (amount <= bracket.min) {
|
|
break;
|
|
}
|
|
|
|
let upperLimit = Math.min(amount, bracket.max);
|
|
let taxableInBracket = upperLimit - bracket.min;
|
|
totalTax += taxableInBracket * (bracket.rate / 100);
|
|
}
|
|
|
|
return totalTax;
|
|
}
|
|
|
|
function updateCalculator() {
|
|
const amountInput = document.getElementById("amount-input").value;
|
|
const useDeduction = document.getElementById("deduction-checkbox").checked;
|
|
const resultDiv = document.getElementById("calculator-result");
|
|
|
|
let amount = parseEurAmount(amountInput);
|
|
|
|
if (amount === null || amount < 0) {
|
|
resultDiv.style.display = "none";
|
|
return;
|
|
}
|
|
|
|
let taxBasis = amount;
|
|
if (useDeduction && amount > STANDARD_DEDUCTION) {
|
|
taxBasis = amount - STANDARD_DEDUCTION;
|
|
}
|
|
|
|
const bracket = calculateTaxBracket(taxBasis);
|
|
const taxAmount = calculateProgressiveTax(taxBasis);
|
|
|
|
document.getElementById("result-razred").textContent = bracket.razred;
|
|
document.getElementById("result-rate").textContent = bracket.rate + " %";
|
|
document.getElementById("result-basis").textContent = formatEurAmount(taxBasis) + " EUR";
|
|
document.getElementById("result-tax").textContent = formatEurAmount(taxAmount) + " EUR";
|
|
|
|
resultDiv.style.display = "block";
|
|
}
|
|
|
|
document.getElementById("amount-input").addEventListener("input", updateCalculator);
|
|
document.getElementById("deduction-checkbox").addEventListener("change", updateCalculator); |