diff --git a/.hintrc b/.hintrc new file mode 100644 index 0000000..5b02c11 --- /dev/null +++ b/.hintrc @@ -0,0 +1,13 @@ +{ + "extends": [ + "development" + ], + "hints": { + "axe/forms": [ + "default", + { + "label": "off" + } + ] + } +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..1bdcfb1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "workbench.iconTheme": "symbols" +} \ No newline at end of file diff --git a/README.md b/README.md index 3e25fef..dbeca32 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +# Table Tennis Counter + The code is running, well, good! 凑活凑活用用吧 diff --git a/assets/css/styles.css b/assets/css/styles.css new file mode 100644 index 0000000..73e26b3 --- /dev/null +++ b/assets/css/styles.css @@ -0,0 +1,139 @@ +:root { + --reset-button-bg-color: #e74c3c; + --reset-button-hover-bg-color: #c0392b; +} +* { + max-width: none; + scrollbar-width: 0; + scrollbar-color: none; + scroll-behavior: smooth; +} +*::-webkit-scrollbar { + display: none; +} + +body { + margin: 0; + padding: 0; + margin-block: 0; + margin-inline: 0; + padding-block: 0; + padding-inline: 0; +} +s-page { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + display: flex; + flex-direction: column; +} +main { + font-family: Arial, sans-serif; + display: flex; + flex-direction: column; + align-content: center; + justify-content: center; + align-items: center; + margin: 0; + flex: 1; +} + +#top-loading { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 100%; +} +#top-bar, #main { + visibility: hidden; +} + +h1 { + margin: 20px 0; +} + +.form-group { + margin: 5px; +} +#setup { + min-width: 40%; + padding: 10px; + display: block; +} +s-text-field { + display: block; +} + +.player-list ul, #playerScoreList, #matchOrderList, #historyList { + list-style: none; + padding: 0; +} + +.player-list li, #playerScoreList li, #matchOrderList li, #historyList li { + margin: 5px 0; +} + +.score-button { + padding: 20px 30px; + font-size: 24px; +} + +.reset-button { + width: 100%; + background-color: var(--reset-button-bg-color); + color: var(--primary-text-color); +} + +.reset-button:hover { + background-color: var(--reset-button-hover-bg-color); +} + +label { + font-size: 18px; + margin-bottom: 10px; +} + +.game-board { + display: flex; + flex-direction: row; + max-width: 90%; + min-width: 50%; + max-height: 80%; + min-height: 40%; + padding: 20px; + box-sizing: border-box; + justify-content: center; + align-items: stretch; +} +.game-board:not(.active) { + display: none; +} +.game-board>div { + flex: 1; + display: flex; + flex-direction: column; +} +.game-board>div>s-card { + flex: 1; + margin: 5px; +} + +.player-scores, .current-match, .match-order, .history { + padding: 20px; + border-radius: 12px; + overflow-y: auto; +} +h2 { + margin-top: 0; +} + +.current-match .player { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; +} diff --git a/script.js b/assets/js/script.js similarity index 82% rename from script.js rename to assets/js/script.js index e52b5f0..397cb37 100644 --- a/script.js +++ b/assets/js/script.js @@ -1,166 +1,170 @@ -let players = []; -let totalScores = {}; -let currentMatchScores = {}; -let currentMatch = [0, 1]; // Indexes of the players in the current match -let winBalls = 5; -let matchHistory = []; - -document.addEventListener('DOMContentLoaded', () => { - document.getElementById('addPlayerButton').addEventListener('click', addPlayer); - document.getElementById('startGameButton').addEventListener('click', startGame); -}); - -function addPlayer() { - const playerName = document.getElementById('playerName').value.trim(); - if (playerName === '' || players.includes(playerName)) { - alert('Please enter a unique valid player name'); - return; - } - players.push(playerName); - totalScores[playerName] = 0; - updatePlayerList(); - document.getElementById('playerName').value = ''; -} - -function updatePlayerList() { - const playerList = document.getElementById('playerList'); - playerList.innerHTML = ''; - players.forEach(player => { - const li = document.createElement('li'); - li.textContent = player; - playerList.appendChild(li); - }); -} - -function startGame() { - if (players.length < 2) { - alert('Please add at least two players'); - return; - } - winBalls = parseInt(document.getElementById('winBalls').value); - if (isNaN(winBalls) || winBalls <= 0) { - alert('Please enter a valid number of winning balls'); - return; - } - document.getElementById('initialSetup').style.display = 'none'; - document.getElementById('playerInputGroup').style.display = 'none'; - document.getElementById('playerListGroup').style.display = 'none'; - document.getElementById('initialButtons').style.display = 'none'; - document.getElementById('gameBoard').style.display = 'grid'; - updatePlayerScoreList(); - updateMatchOrderList(); - startNewMatch(); -} - -function startNewMatch() { - currentMatchScores = {}; - players.forEach(player => { - currentMatchScores[player] = 0; - }); - updateCurrentMatch(); -} - -function incrementCurrentMatchScore(playerName) { - currentMatchScores[playerName]++; - updateCurrentMatch(); - if (currentMatchScores[playerName] >= winBalls) { - totalScores[playerName]++; - document.getElementById('result').innerText = `${playerName} Wins this round!`; - matchHistory.push(`${players[currentMatch[0]]} vs ${players[currentMatch[1]]}: ${playerName} won`); - disableScoreButtons(); - setTimeout(() => { - document.getElementById('result').innerText = ''; - updatePlayerScoreList(); - updateMatchOrder(); - updateMatchOrderList(); - updateHistoryList(); - enableScoreButtons(); - startNewMatch(); - }, 2000); - } -} - -function disableScoreButtons() { - document.querySelectorAll('.score-button').forEach(button => { - button.disabled = true; - }); -} - -function enableScoreButtons() { - document.querySelectorAll('.score-button').forEach(button => { - button.disabled = false; - }); -} - -function updateCurrentMatch() { - const match = document.getElementById('currentMatch'); - const player1 = players[currentMatch[0]]; - const player2 = players[currentMatch[1]]; - match.innerHTML = ` -
- - -
-
- - -
- `; -} - -function updatePlayerScoreList() { - const playerScoreList = document.getElementById('playerScoreList'); - playerScoreList.innerHTML = ''; - players.forEach(player => { - const li = document.createElement('li'); - li.textContent = `${player}: ${totalScores[player]}`; - playerScoreList.appendChild(li); - }); -} - -function updateMatchOrderList() { - const matchOrderList = document.getElementById('matchOrderList'); - matchOrderList.innerHTML = ''; - for (let i = 0; i < players.length; i++) { - const player1 = players[i]; - const player2 = players[(i + 1) % players.length]; - const li = document.createElement('li'); - li.textContent = `${player1} vs ${player2}`; - matchOrderList.appendChild(li); - } -} - -function updateHistoryList() { - const historyList = document.getElementById('historyList'); - historyList.innerHTML = ''; - matchHistory.forEach(match => { - const li = document.createElement('li'); - li.textContent = match; - historyList.appendChild(li); - }); -} - -function updateMatchOrder() { - currentMatch[0] = (currentMatch[0] + 1) % players.length; - currentMatch[1] = (currentMatch[1] + 1) % players.length; - if (currentMatch[0] === currentMatch[1]) { - currentMatch[1] = (currentMatch[1] + 1) % players.length; - } -} - -function resetScores() { - players = []; - totalScores = {}; - currentMatchScores = {}; - currentMatch = [0, 1]; - matchHistory = []; - document.getElementById('playerList').innerHTML = ''; - document.getElementById('gameBoard').style.display = 'none'; - document.getElementById('initialSetup').style.display = 'block'; - document.getElementById('playerInputGroup').style.display = 'block'; - document.getElementById('playerListGroup').style.display = 'block'; - document.getElementById('initialButtons').style.display = 'block'; - document.getElementById('historyList').innerHTML = ''; -} - -window.incrementCurrentMatchScore = incrementCurrentMatchScore; +let players = []; +let totalScores = {}; +let currentMatchScores = {}; +let currentMatch = [0, 1]; // Indexes of the players in the current match +let winBalls = 5; +let matchHistory = []; + +document.addEventListener('DOMContentLoaded', () => { + // 虽然但是,onclick:? +}); + +function addPlayer() { + const playerName = document.getElementById('playerName').value.trim(); + if (playerName === '' || players.includes(playerName)) { + showSnackBar('Please enter a unique valid player name', 'PlayerNameError'); + return; + } + players.push(playerName); + totalScores[playerName] = 0; + updatePlayerList(); + document.getElementById('playerName').value = ''; +} + +function updatePlayerList() { + showLoading(); + const playerList = document.getElementById('playerList'); + playerList.innerHTML = ''; + players.forEach(player => { + const li = document.createElement('li'); + li.textContent = player; + playerList.appendChild(li); + }); + hideLoading(); +} + +function startGame() { + showLoading(); + if (players.length < 2) { + showSnackBar('Please add at least two players', 'PlayerAmountError'); + hideLoading(); + return; + } + winBalls = parseInt(document.getElementById('winBalls').value); + if (isNaN(winBalls) || winBalls <= 0) { + showSnackBar('Please enter a valid number of winning balls', 'WinningBallsError'); + hideLoading(); + return; + } + document.getElementById('setup').style.display = 'none'; + document.getElementById('gameBoard').classList.add('active'); + updatePlayerScoreList(); + updateMatchOrderList(); + startNewMatch(); + hideLoading(); +} + +function startNewMatch() { + showLoading(); + currentMatchScores = {}; + players.forEach(player => { + currentMatchScores[player] = 0; + }); + updateCurrentMatch(); + hideLoading(); +} + +function incrementCurrentMatchScore(playerName) { + currentMatchScores[playerName]++; + updateCurrentMatch(); + if (currentMatchScores[playerName] >= winBalls) { + totalScores[playerName]++; + document.getElementById('result').innerText = `${playerName} Wins this round!`; + matchHistory.push(`${players[currentMatch[0]]} vs ${players[currentMatch[1]]}: ${playerName} won`); + disableScoreButtons(); + setTimeout(() => { + document.getElementById('result').innerText = ''; + updatePlayerScoreList(); + updateMatchOrder(); + updateMatchOrderList(); + updateHistoryList(); + enableScoreButtons(); + startNewMatch(); + }, 2000); + } +} + +function disableScoreButtons() { + document.querySelectorAll('.score-button').forEach(button => { + button.disabled = true; + }); +} + +function enableScoreButtons() { + document.querySelectorAll('.score-button').forEach(button => { + button.disabled = false; + }); +} + +function updateCurrentMatch() { + const match = document.getElementById('currentMatch'); + const player1 = players[currentMatch[0]]; + const player2 = players[currentMatch[1]]; + match.innerHTML = ` +
+ + Score +
+
+ + Score +
+ `; +} + +function updatePlayerScoreList() { + const playerScoreList = document.getElementById('playerScoreList'); + playerScoreList.innerHTML = ''; + players.forEach(player => { + const li = document.createElement('li'); + li.textContent = `${player}: ${totalScores[player]}`; + playerScoreList.appendChild(li); + }); +} + +function updateMatchOrderList() { + const matchOrderList = document.getElementById('matchOrderList'); + matchOrderList.innerHTML = ''; + for (let i = 0; i < players.length; i++) { + const player1 = players[i]; + const player2 = players[(i + 1) % players.length]; + const li = document.createElement('li'); + li.textContent = `${player1} vs ${player2}`; + matchOrderList.appendChild(li); + } +} + +function updateHistoryList() { + const historyList = document.getElementById('historyList'); + historyList.innerHTML = ''; + matchHistory.forEach(match => { + const li = document.createElement('li'); + li.textContent = match; + historyList.appendChild(li); + }); +} + +function updateMatchOrder() { + currentMatch[0] = (currentMatch[0] + 1) % players.length; + currentMatch[1] = (currentMatch[1] + 1) % players.length; + if (currentMatch[0] === currentMatch[1]) { + currentMatch[1] = (currentMatch[1] + 1) % players.length; + } +} + +function resetScores() { + players = []; + totalScores = {}; + currentMatchScores = {}; + currentMatch = [0, 1]; + matchHistory = []; + document.getElementById('playerList').innerHTML = ''; + document.getElementById('gameBoard').style.display = 'none'; + document.getElementById('initialSetup').style.display = 'block'; + document.getElementById('playerInputGroup').style.display = 'block'; + document.getElementById('playerListGroup').style.display = 'block'; + document.getElementById('initialButtons').style.display = 'block'; + document.getElementById('historyList').innerHTML = ''; +} + +window.incrementCurrentMatchScore = incrementCurrentMatchScore; diff --git a/assets/js/ui.js b/assets/js/ui.js new file mode 100644 index 0000000..b663da5 --- /dev/null +++ b/assets/js/ui.js @@ -0,0 +1,81 @@ + +document.addEventListener('DOMContentLoaded', () => { // 虽然但是,onclick:? + let pageEl = document.getElementById('page'); + + document.getElementById('sober').addEventListener('load', function () { + e_toggleTheme('auto') + setTimeout(function () { // 等Sober执行完 + document.getElementById('main').style.visibility = 'visible'; + document.getElementById('top-bar').style.visibility = 'visible'; + hideLoading(); + }, 500); + }); +}); + +function showSnackBar(message, id = 'snackbar') { + let snackBarEl = document.getElementById('snackbar-' + id); + if (snackBarEl === null) { + snackBarEl = document.createElement('s-snackbar'); + snackBarEl.id ='snackbar-' + id; + document.getElementById('tooltips').appendChild(snackBarEl); + } + snackBarEl.innerText = message; + snackBarEl.show(); +} +function showLoading() { + document.getElementById('top-loading').style.visibility = 'visible'; +} +function hideLoading() { + document.getElementById('top-loading').style.visibility = 'hidden'; +} + +function e_toggleTheme(theme) { + let pageEl = document.getElementById('page'); + let themeIconEl = document.getElementById('theme-icon'); + if (!theme) { + switch (pageEl.theme) { + case 'auto': + theme = 'light'; + break; + case 'light': + theme = 'dark'; + break; + case 'dark': + theme = 'auto'; + break; + default: + theme = 'light'; + break; + } + } + switch (theme) { + case 'auto': + pageEl.theme = 'auto'; + themeIconEl.type = ''; + themeIconEl.innerHTML = ` + + +`; + showSnackBar('Theme set to auto', 'Theme'); + break; + case 'light': + pageEl.theme = 'light'; + themeIconEl.type = 'light_mode'; + themeIconEl.innerHTML = ''; + showSnackBar('Theme set to light', 'Theme'); + break; + case 'dark': + pageEl.theme = 'dark'; + themeIconEl.type = 'dark_mode'; + themeIconEl.innerHTML = ''; + showSnackBar('Theme set to dark', 'Theme'); + break; + } +} +function e_gotoGitHub() { + showSnackBar('Issues and PRs are welcome!!!', 'RepoTips'); + window.open('https://github.com/Minemetero/Table-Tennis-Counter', '_blank'); +} \ No newline at end of file diff --git a/index.html b/index.html index e2f7788..dff57ae 100644 --- a/index.html +++ b/index.html @@ -1,51 +1,106 @@ - - + + Table Tennis Counter - + -

Table Tennis Counter

-
- - -
-
- - -
-
-

Players:

- -
-
- -
- -