From 38e62ae16388cf2326f3c2bd53a6fe4d3c7fb753 Mon Sep 17 00:00:00 2001 From: FinnIckler Date: Fri, 16 Feb 2024 21:08:15 +0100 Subject: [PATCH 1/4] show minutes --- Frontend/src/pages/events/index.jsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Frontend/src/pages/events/index.jsx b/Frontend/src/pages/events/index.jsx index 09c3a3c2..da188ffd 100644 --- a/Frontend/src/pages/events/index.jsx +++ b/Frontend/src/pages/events/index.jsx @@ -16,6 +16,15 @@ import { CompetitionContext } from '../../api/helper/context/competition_context import { setMessage } from '../../ui/events/messages' import LoadingMessage from '../../ui/messages/loadingMessage' +function centiSecondsToHumanReadable(centiSeconds) { + const seconds = centiSeconds / 100 + if (seconds < 60) { + return `${seconds} seconds` + } + const minutes = Math.floor(seconds / 60) + return `${minutes}:${(seconds % 60).toString().padStart(2, '0')}` +} + export default function Events() { const { competitionInfo } = useContext(CompetitionContext) @@ -73,12 +82,14 @@ export default function Events() { {getFormatName(round.format)} {round.timeLimit && - `${round.timeLimit.centiseconds / 100} seconds`} + centiSecondsToHumanReadable(round.timeLimit.centiseconds)} {competitionInfo['uses_cutoff?'] && ( {round.cutoff && - `${round.cutoff?.attemptResult / 100} seconds`} + centiSecondsToHumanReadable( + round.timeLimit.centiseconds + )} )} From f5d2f575f995522ab66609141211a9342c04e3f6 Mon Sep 17 00:00:00 2001 From: FinnIckler Date: Sat, 17 Feb 2024 15:09:50 +0100 Subject: [PATCH 2/4] add monolith function to lib --- Frontend/src/lib/solveTime.ts | 67 +++++++++++++++++++++++++++++ Frontend/src/pages/events/index.jsx | 20 +++------ 2 files changed, 74 insertions(+), 13 deletions(-) create mode 100644 Frontend/src/lib/solveTime.ts diff --git a/Frontend/src/lib/solveTime.ts b/Frontend/src/lib/solveTime.ts new file mode 100644 index 00000000..aa06ea95 --- /dev/null +++ b/Frontend/src/lib/solveTime.ts @@ -0,0 +1,67 @@ +export const SECOND_IN_CS = 100 +export const MINUTE_IN_CS = 60 * SECOND_IN_CS +export const HOUR_IN_CS = 60 * MINUTE_IN_CS + +interface PluralizeParams { + count: number + word: string + options?: { + fixed?: number + abbreviate?: boolean + } +} + +export function pluralize({ count, word, options = {} }: PluralizeParams) { + const countStr = + options.fixed && count % 1 > 0 ? count.toFixed(options.fixed) : count + const countDesc = options.abbreviate + ? word[0] + : ` ${count === 1 ? word : `${word}s`}` + return countStr + countDesc +} + +interface CentiSecondsToHumanReadableParams { + c: number + options?: { + short?: boolean + } +} + +export function centiSecondsToHumanReadable({ + c, + options = {}, +}: CentiSecondsToHumanReadableParams) { + let centiseconds = c + let str = '' + + const hours = centiseconds / HOUR_IN_CS + centiseconds %= HOUR_IN_CS + if (hours >= 1) { + str += `${pluralize({ + count: Math.floor(hours), + word: 'hour', + options: { abbreviate: options.short }, + })} ` + } + + const minutes = centiseconds / MINUTE_IN_CS + centiseconds %= MINUTE_IN_CS + if (minutes >= 1) { + str += `${pluralize({ + count: Math.floor(minutes), + word: 'minute', + options: { abbreviate: options.short }, + })} ` + } + + const seconds = centiseconds / SECOND_IN_CS + if (seconds > 0 || str.length === 0) { + str += `${pluralize({ + count: seconds, + word: 'second', + options: { fixed: 2, abbreviate: options.short }, + })} ` + } + + return str.trim() +} diff --git a/Frontend/src/pages/events/index.jsx b/Frontend/src/pages/events/index.jsx index da188ffd..2140e80f 100644 --- a/Frontend/src/pages/events/index.jsx +++ b/Frontend/src/pages/events/index.jsx @@ -15,15 +15,7 @@ import getCompetitionWcif from '../../api/competition/get/get_competition_wcif' import { CompetitionContext } from '../../api/helper/context/competition_context' import { setMessage } from '../../ui/events/messages' import LoadingMessage from '../../ui/messages/loadingMessage' - -function centiSecondsToHumanReadable(centiSeconds) { - const seconds = centiSeconds / 100 - if (seconds < 60) { - return `${seconds} seconds` - } - const minutes = Math.floor(seconds / 60) - return `${minutes}:${(seconds % 60).toString().padStart(2, '0')}` -} +import { centiSecondsToHumanReadable } from '../../lib/solveTime' export default function Events() { const { competitionInfo } = useContext(CompetitionContext) @@ -82,14 +74,16 @@ export default function Events() { {getFormatName(round.format)} {round.timeLimit && - centiSecondsToHumanReadable(round.timeLimit.centiseconds)} + centiSecondsToHumanReadable({ + c: round.timeLimit.centiseconds, + })} {competitionInfo['uses_cutoff?'] && ( {round.cutoff && - centiSecondsToHumanReadable( - round.timeLimit.centiseconds - )} + centiSecondsToHumanReadable({ + c: round.timeLimit.centiseconds, + })} )} From bb26be0e77217c05036b102882516f95eb822406 Mon Sep 17 00:00:00 2001 From: FinnIckler Date: Sat, 17 Feb 2024 15:18:57 +0100 Subject: [PATCH 3/4] lint --- Frontend/src/pages/events/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Frontend/src/pages/events/index.jsx b/Frontend/src/pages/events/index.jsx index 2140e80f..f396ba24 100644 --- a/Frontend/src/pages/events/index.jsx +++ b/Frontend/src/pages/events/index.jsx @@ -13,9 +13,9 @@ import { } from 'semantic-ui-react' import getCompetitionWcif from '../../api/competition/get/get_competition_wcif' import { CompetitionContext } from '../../api/helper/context/competition_context' +import { centiSecondsToHumanReadable } from '../../lib/solveTime' import { setMessage } from '../../ui/events/messages' import LoadingMessage from '../../ui/messages/loadingMessage' -import { centiSecondsToHumanReadable } from '../../lib/solveTime' export default function Events() { const { competitionInfo } = useContext(CompetitionContext) From 205e146986f89d70517c02ac1b1e3978414b0b78 Mon Sep 17 00:00:00 2001 From: Finn Ickler Date: Sun, 18 Feb 2024 09:19:19 +0100 Subject: [PATCH 4/4] support FMC and MBLD for cutoffs --- Frontend/src/lib/solveTime.ts | 55 ++++++++++++++++++++++++++++- Frontend/src/pages/events/index.jsx | 10 ++++-- 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/Frontend/src/lib/solveTime.ts b/Frontend/src/lib/solveTime.ts index aa06ea95..9c78c472 100644 --- a/Frontend/src/lib/solveTime.ts +++ b/Frontend/src/lib/solveTime.ts @@ -1,3 +1,5 @@ +import { EventId, getEventResultType } from '@wca/helpers' + export const SECOND_IN_CS = 100 export const MINUTE_IN_CS = 60 * SECOND_IN_CS export const HOUR_IN_CS = 60 * MINUTE_IN_CS @@ -20,13 +22,64 @@ export function pluralize({ count, word, options = {} }: PluralizeParams) { return countStr + countDesc } +interface AttemptResultToStringParams { + attemptResult: number + eventId: EventId +} + +export function attemptResultToString({ + attemptResult, + eventId, +}: AttemptResultToStringParams) { + const type = getEventResultType(eventId) + if (type === 'time') { + return centiSecondsToHumanReadable({ c: attemptResult }) + } + if (type === 'number') { + return `${attemptResult} moves` + } + return `${attemptResultToMbPoints(attemptResult)} points` +} + +function parseMbValue(val: number) { + let mbValue = val + const old = Math.floor(mbValue / 1000000000) !== 0 + let timeSeconds + let attempted + let solved + if (old) { + timeSeconds = mbValue % 100000 + mbValue = Math.floor(mbValue / 100000) + attempted = mbValue % 100 + mbValue = Math.floor(mbValue / 100) + solved = 99 - (mbValue % 100) + } else { + const missed = mbValue % 100 + mbValue = Math.floor(mbValue / 100) + timeSeconds = mbValue % 100000 + mbValue = Math.floor(mbValue / 100000) + const difference = 99 - (mbValue % 100) + + solved = difference + missed + attempted = solved + missed + } + + const timeCentiseconds = timeSeconds === 99999 ? null : timeSeconds * 100 + return { solved, attempted, timeCentiseconds } +} + +function attemptResultToMbPoints(mbValue: number) { + const { solved, attempted } = parseMbValue(mbValue) + const missed = attempted - solved + return solved - missed +} + interface CentiSecondsToHumanReadableParams { c: number options?: { short?: boolean } } - export function centiSecondsToHumanReadable({ c, options = {}, diff --git a/Frontend/src/pages/events/index.jsx b/Frontend/src/pages/events/index.jsx index f396ba24..a485558c 100644 --- a/Frontend/src/pages/events/index.jsx +++ b/Frontend/src/pages/events/index.jsx @@ -13,7 +13,10 @@ import { } from 'semantic-ui-react' import getCompetitionWcif from '../../api/competition/get/get_competition_wcif' import { CompetitionContext } from '../../api/helper/context/competition_context' -import { centiSecondsToHumanReadable } from '../../lib/solveTime' +import { + attemptResultToString, + centiSecondsToHumanReadable, +} from '../../lib/solveTime' import { setMessage } from '../../ui/events/messages' import LoadingMessage from '../../ui/messages/loadingMessage' @@ -81,8 +84,9 @@ export default function Events() { {competitionInfo['uses_cutoff?'] && ( {round.cutoff && - centiSecondsToHumanReadable({ - c: round.timeLimit.centiseconds, + attemptResultToString({ + attemptResult: round.cutoff.attemptResult, + eventId: event.id, })} )}