Merge pull request #3638 from AleixDev/score

Score: bug fixes and some usability and performance improvements
pull/3613/head
Rob Pilling 2024-11-12 08:30:40 +00:00 committed by GitHub
commit 9b3b7e1856
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 112 additions and 46 deletions

View File

@ -1,2 +1,3 @@
0.01: New App! 0.01: New App!
0.02: Minor code improvements 0.02: Minor code improvements
0.03: Bug fixes and some usability and performance improvements

View File

@ -1,13 +1,14 @@
{ {
"id": "score", "id": "score",
"name": "Score Tracker", "name": "Score Tracker",
"version": "0.02", "version": "0.03",
"description": "Score Tracker for sports that use plain numbers (e.g. Badminton, Volleyball, Soccer, Table Tennis, ...). Also supports tennis scoring.", "description": "Score Tracker for sports that use plain numbers (e.g. Badminton, Volleyball, Soccer, Table Tennis, ...). Also supports tennis scoring.",
"icon": "score.app.png", "icon": "score.app.png",
"screenshots": [{"url":"screenshot_score.png"}], "screenshots": [{"url":"screenshot_score.png"}],
"type": "app", "type": "app",
"tags": "", "tags": "",
"supports": ["BANGLEJS","BANGLEJS2"], "supports": ["BANGLEJS","BANGLEJS2"],
"allow_emulator": true,
"readme": "README.md", "readme": "README.md",
"storage": [ "storage": [
{"name":"score.app.js","url":"score.app.js"}, {"name":"score.app.js","url":"score.app.js"},

View File

@ -10,6 +10,7 @@ let tennisScores = ['00','15','30','40','DC','AD'];
let scores = null; let scores = null;
let tScores = null; let tScores = null;
let cSet = null; let cSet = null;
let matchEnd = null;
let firstShownSet = null; let firstShownSet = null;
@ -19,10 +20,10 @@ let correctionMode = false;
let w = g.getWidth(); let w = g.getWidth();
let h = g.getHeight(); let h = g.getHeight();
let isBangle1 = process.env.BOARD === 'BANGLEJS'; let isBangle1 = process.env.BOARD === 'BANGLEJS' || process.env.BOARD === 'EMSCRIPTEN';
function getXCoord(func) { function getXCoord(func) {
let offset = 40; let offset = 20;
return func(w-offset)+offset; return func(w-offset)+offset;
} }
@ -54,7 +55,9 @@ function setupInputWatchers(init) {
} }
}); });
if (init) { if (init) {
setWatch(() => handleInput(2), isBangle1 ? BTN2 : BTN, { repeat: true }); if (isBangle1) {
setWatch(() => handleInput(2), BTN2, { repeat: true });
}
Bangle.on('touch', (b, e) => { Bangle.on('touch', (b, e) => {
if (isBangle1) { if (isBangle1) {
if (b === 1) { if (b === 1) {
@ -63,10 +66,36 @@ function setupInputWatchers(init) {
handleInput(4); handleInput(4);
} }
} else { } else {
if (e.x < getXCoord(w => w/2)) { if (e.y > 18) {
handleInput(0); if (e.x < getXCoord(w => w/2)) {
handleInput(0);
} else {
handleInput(1);
}
} else { } else {
handleInput(1); // long press except if we have the menu opened or we are in the emulator (that doesn't
// seem to support long press events)
if (e.type === 2 || settingsMenuOpened || process.env.BOARD === 'EMSCRIPTEN2') {
handleInput(2);
} else {
let p = null;
if (matchWon(0)) p = 0;
else if (matchWon(1)) p = 1;
// display full instructions if there is space available, or brief ones otherwise
if (p === null) {
drawInitialMsg();
} else {
g.setFontAlign(0,0);
g.setFont('Teletext5x9Ascii',1);
g.drawString(
"-Long press-",
getXCoord(w => p === 0 ? w/4*3: (w/4) + 20),
15
);
}
}
} }
} }
}); });
@ -74,6 +103,7 @@ function setupInputWatchers(init) {
} }
function setupMatch() { function setupMatch() {
matchEnd = null;
scores = []; scores = [];
for (let s = 0; s < sets(); s++) { for (let s = 0; s < sets(); s++) {
scores.push([0,0,null,0,0]); scores.push([0,0,null,0,0]);
@ -96,28 +126,33 @@ function setupMatch() {
function showSettingsMenu() { function showSettingsMenu() {
settingsMenuOpened = getSecondsTime(); settingsMenuOpened = getSecondsTime();
settingsMenu(function (s, reset) { settingsMenu(function (s, reset, back) {
E.showMenu(); // console.log('reset:', reset, 'back:', back);
if (isBangle1) {
E.showMenu();
}
settings = s; settings = s;
if (reset) { if (reset) {
setupMatch(); setupMatch();
} else if (getSecondsTime() - settingsMenuOpened < 500 || correctionMode) {
correctionMode = !correctionMode;
} }
if (isBangle1 || (!isBangle1 && back)) {
settingsMenuOpened = null;
settingsMenuOpened = null; draw();
draw(); setupDisplay();
setupInputWatchers();
setupDisplay(); }
setupInputWatchers();
}, function (msg) { }, function (msg) {
switch (msg) { switch (msg) {
case 'end_set': case 'end_set':
updateCurrentSet(1); updateCurrentSet(1);
break; break;
case 'correct_mode':
correctionMode = !correctionMode;
break;
} }
}); });
} }
@ -144,6 +179,7 @@ function currentSet() {
function shouldTiebreak() { function shouldTiebreak() {
return settings.enableMaxScoreTiebreak && return settings.enableMaxScoreTiebreak &&
scores[cSet][0] === scores[cSet][1] &&
scores[cSet][0] + scores[cSet][1] === (maxScore() - 1) * 2; scores[cSet][0] + scores[cSet][1] === (maxScore() - 1) * 2;
} }
@ -176,27 +212,21 @@ function tiebreakWon(set, player) {
let pScore = scores[set][3+player]; let pScore = scores[set][3+player];
let p2Score = scores[set][3+~~!player]; let p2Score = scores[set][3+~~!player];
let winScoreReached = pScore >= settings.maxScoreTiebreakWinScore; // reachedMaxScore || (winScoreReached && isTwoAhead);
let isTwoAhead = !settings.maxScoreTiebreakEnableTwoAhead || pScore - p2Score >= 2; return (settings.maxScoreTiebreakEnableMaxScore && pScore >= tiebreakMaxScore()) ||
let reachedMaxScore = settings.maxScoreTiebreakEnableMaxScore && pScore >= tiebreakMaxScore(); ((pScore >= settings.maxScoreTiebreakWinScore) &&
(!settings.maxScoreTiebreakEnableTwoAhead || pScore - p2Score >= 2));
return reachedMaxScore || (winScoreReached && isTwoAhead);
} }
function setWon(set, player) { function setWon(set, player) {
let pScore = scores[set][player]; let pScore = scores[set][player];
let p2Score = scores[set][~~!player]; let p2Score = scores[set][~~!player];
let winScoreReached = pScore >= settings.winScore; // (tiebreak won / max score) || (winScoreReached && isTwoAhead) || manuallyEndedWon
let isTwoAhead = !settings.enableTwoAhead || pScore - p2Score >= 2;
let tiebreakW = tiebreakWon(set, player);
let reachedMaxScore = settings.enableMaxScore && pScore >= maxScore();
let manuallyEndedWon = cSet > set ? pScore > p2Score : false;
return ( return (
(settings.enableMaxScoreTiebreak ? tiebreakW : reachedMaxScore) || (settings.enableMaxScoreTiebreak ? tiebreakWon(set, player) : settings.enableMaxScore && pScore >= maxScore()) ||
(winScoreReached && isTwoAhead) || (pScore >= settings.winScore && (!settings.enableTwoAhead || pScore - p2Score >= 2)) ||
manuallyEndedWon (cSet > set ? pScore > p2Score : false)
); );
} }
@ -205,7 +235,7 @@ function setEnded(set) {
} }
function setsWon(player) { function setsWon(player) {
return Array(sets()).fill(0).map((_, s) => ~~setWon(s, player)).reduce((a,v) => a+v, 0); return Uint16Array(sets()).fill(0).map((_, s) => ~~setWon(s, player)).reduce((a,v) => a+v, 0);
} }
function matchWon(player) { function matchWon(player) {
@ -213,7 +243,14 @@ function matchWon(player) {
} }
function matchEnded() { function matchEnded() {
return (matchWon(0) || matchWon(1)) && cSet > (setsWon(0) + setsWon(1) - 1); // query if the match is ended only if: the value is not already saved or the set changed
if (matchEnd == null || matchEnd.set != cSet) {
matchEnd = {
ended: (matchWon(0) || matchWon(1)) && cSet > (setsWon(0) + setsWon(1) - 1),
set: cSet,
}
}
return matchEnd.ended
} }
function matchScore(player) { function matchScore(player) {
@ -304,7 +341,20 @@ function score(player) {
} }
function handleInput(button) { function handleInput(button) {
// console.log('button:', button);
if (settingsMenuOpened) { if (settingsMenuOpened) {
if (!isBangle1 && button == 2) {
E.showMenu();
settingsMenuOpened = null;
draw();
setupDisplay();
setupInputWatchers();
}
return; return;
} }
@ -340,8 +390,8 @@ function draw() {
g.setFontAlign(0,0); g.setFontAlign(0,0);
g.setFont('Teletext5x9Ascii',2); g.setFont('Teletext5x9Ascii',2);
g.drawString( g.drawString(
"WINNER", "WINS",
getXCoord(w => p === 0 ? w/4 : w/4*3), getXCoord(w => p === 0 ? w/4 + 7 : w/4*3 + 7),
15 15
); );
} else if (matchEnded()) { } else if (matchEnded()) {
@ -376,7 +426,7 @@ function draw() {
g.setFont('7x11Numeric7Seg',2); g.setFont('7x11Numeric7Seg',2);
g.drawString( g.drawString(
formatNumber(matchScore(p), 3), formatNumber(matchScore(p), 3),
getXCoord(w => p === 0 ? w/2 - 3 : w/2 + 6), getXCoord(w => p === 0 ? w/2 - 6 : w/2 + 9),
h-5 h-5
); );
} }
@ -387,7 +437,7 @@ function draw() {
g.setFont('Teletext5x9Ascii',2); g.setFont('Teletext5x9Ascii',2);
g.drawString( g.drawString(
"R", "R",
getXCoord(w => w/2), getXCoord(w => w/2) + 1,
h-10 h-10
); );
} }
@ -411,13 +461,13 @@ function draw() {
g.drawString(set+1, 5, y-10); g.drawString(set+1, 5, y-10);
if (scores[set+1][2] != null) { if (scores[set+1][2] != null) {
let dur2 = formatDuration(scores[set+1][2] - scores[set][2]); let dur2 = formatDuration(scores[set+1][2] - scores[set][2]);
g.drawString(dur2, 5, y+10); g.drawString(dur2, 2, y+10);
} }
for (let p = 0; p < 2; p++) { for (let p = 0; p < 2; p++) {
if (!setWon(set, p === 0 ? 1 : 0) || matchEnded()) { if (!setWon(set, p === 0 ? 1 : 0) || matchEnded()) {
let bigNumX = getXCoord(w => p === 0 ? w/4-12 : w/4*3+15); let bigNumX = getXCoord(w => p === 0 ? w/4-2 : w/4*3+5);
let smallNumX = getXCoord(w => p === 0 ? w/2-2 : w/2+3); let smallNumX = getXCoord(w => p === 0 ? w/2-1 : w/2+2);
if (settings.enableTennisScoring && set === cSet && !shouldTiebreak()) { if (settings.enableTennisScoring && set === cSet && !shouldTiebreak()) {
g.setFontAlign(0,0); g.setFontAlign(0,0);
@ -427,12 +477,12 @@ function draw() {
bigNumX, bigNumX,
y y
); );
} else if (shouldTiebreak() && set === cSet) { } else if (set === cSet && shouldTiebreak()) {
g.setFontAlign(0,0); g.setFontAlign(0,0);
g.setFont('7x11Numeric7Seg',3); g.setFont('7x11Numeric7Seg',3);
g.drawString( g.drawString(
formatNumber(scores[set][3+p], 3), formatNumber(scores[set][3+p], 3),
bigNumX, bigNumX + (p === 0 ? -5 : 5),
y y
); );
} else { } else {
@ -445,7 +495,7 @@ function draw() {
); );
} }
if ((shouldTiebreak() || settings.enableTennisScoring) && set === cSet) { if (set === cSet && (shouldTiebreak() || settings.enableTennisScoring)) {
g.setFontAlign(p === 0 ? 1 : -1,0); g.setFontAlign(p === 0 ? 1 : -1,0);
g.setFont('7x11Numeric7Seg',1); g.setFont('7x11Numeric7Seg',1);
g.drawString( g.drawString(
@ -472,7 +522,20 @@ function draw() {
g.flip(); g.flip();
} }
function drawInitialMsg() {
if (!isBangle1) {
g.setFontAlign(0,0);
g.setFont('Teletext5x9Ascii',1);
g.drawString(
"-Long press here for menu-",
90,
15
);
}
}
setupDisplay(); setupDisplay();
setupInputWatchers(true); setupInputWatchers(true);
setupMatch(); setupMatch();
draw(); draw();
drawInitialMsg();

View File

@ -116,7 +116,7 @@
if (selected != null) { if (selected != null) {
m[''].selected = selected; m[''].selected = selected;
} }
m['< Back'] = function () { back(settings, changed); }; m['< Back'] = function () { back(settings, changed, true); };
m['Presets'] = function () { E.showMenu(presetMenu(back)); }; m['Presets'] = function () { E.showMenu(presetMenu(back)); };
if (isBangle1) { if (isBangle1) {
m['Mirror Buttons'] = { m['Mirror Buttons'] = {
@ -198,9 +198,10 @@
const inAppMenu = function () { const inAppMenu = function () {
let m = { let m = {
'': {'title': 'Score Menu'}, '': {'title': 'Score Menu'},
'< Back': function () { back(settings, changed); }, '< Back': function () { back(settings, changed, false); },
'Reset match': function () { back(settings, true); }, 'Correct mode': function () { inApp('correct_mode'); back(settings, false, true); },
'End current set': function () { inApp('end_set'); back(settings, changed); }, 'Reset match': function () { back(settings, true, true); },
'End current set': function () { inApp('end_set'); back(settings, changed, true); },
'Configuration': function () { E.showMenu(appMenu(function () { 'Configuration': function () { E.showMenu(appMenu(function () {
E.showMenu(inAppMenu()); E.showMenu(inAppMenu());
})); }, })); },