diff --git a/frontend/src/components/ProblemSubmissionList.vue b/frontend/src/components/ProblemSubmissionList.vue new file mode 100644 index 0000000..f8f675a --- /dev/null +++ b/frontend/src/components/ProblemSubmissionList.vue @@ -0,0 +1,132 @@ + + + diff --git a/frontend/src/components/SubmissionInspector.vue b/frontend/src/components/SubmissionInspector.vue new file mode 100644 index 0000000..2c682bd --- /dev/null +++ b/frontend/src/components/SubmissionInspector.vue @@ -0,0 +1,232 @@ + + diff --git a/frontend/src/components/SubmissionPerformance.vue b/frontend/src/components/SubmissionPerformance.vue new file mode 100644 index 0000000..7f4a224 --- /dev/null +++ b/frontend/src/components/SubmissionPerformance.vue @@ -0,0 +1,213 @@ + + + diff --git a/frontend/src/lib/performance.ts b/frontend/src/lib/performance.ts new file mode 100644 index 0000000..2de885f --- /dev/null +++ b/frontend/src/lib/performance.ts @@ -0,0 +1,16 @@ +// Integers stay exact. Number conversion is confined to chart coordinates/count ratios. +export function formatMeasurement(value: string | null, unit: 'cpu_microseconds' | 'bytes') { + if (value === null) return '—' + const raw = BigInt(value) + const scale = unit === 'bytes' ? 1048576n : 1000n + const places = unit === 'bytes' ? 6 : 3 + const fraction = ((raw % scale) * 10n ** BigInt(places)) / scale + if (raw > 0n && raw < scale && fraction === 0n) return '<0.' + '0'.repeat(places - 1) + '1' + return `${raw / scale}.${String(fraction).padStart(places, '0')}`.replace(/\.?0+$/, '') || '0' +} + +export function chartPosition(value: string, end: string) { + const ceiling = BigInt(end) + if (ceiling <= 0n) return 0 + return Number((BigInt(value) * 1000000n) / ceiling) / 1000000 +} diff --git a/frontend/src/views/ProblemDetailView.vue b/frontend/src/views/ProblemDetailView.vue index ee43698..f3c1db4 100644 --- a/frontend/src/views/ProblemDetailView.vue +++ b/frontend/src/views/ProblemDetailView.vue @@ -1,5 +1,5 @@ - + diff --git a/frontend/tests/performance.test.ts b/frontend/tests/performance.test.ts new file mode 100644 index 0000000..868546a --- /dev/null +++ b/frontend/tests/performance.test.ts @@ -0,0 +1,14 @@ +import assert from 'node:assert/strict' +import test from 'node:test' +import { chartPosition, formatMeasurement } from '../src/lib/performance.ts' + +test('measurements preserve raw integer precision and distinguish missing from zero', () => { + assert.equal(formatMeasurement(null, 'bytes'), '—') + assert.equal(formatMeasurement('0', 'cpu_microseconds'), '0') + assert.equal(formatMeasurement('10000', 'cpu_microseconds'), '10') + assert.equal(formatMeasurement('9007199254740993', 'cpu_microseconds'), '9007199254740.993') + assert.equal(formatMeasurement('9007199254740992', 'cpu_microseconds'), '9007199254740.992') + assert.equal(formatMeasurement('1', 'bytes'), '<0.000001') + assert.equal(chartPosition('0', '1'), 0) + assert.equal(chartPosition('9223372036854775807', '9223372036854775807'), 1) +})