Show per-player TTR totals from completed singles only
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 57s
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 57s
This commit is contained in:
@@ -2,14 +2,14 @@ import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import vm from 'node:vm';
|
||||
import { calculateTtrChange } from '../src/services/ttrCalculator.mjs';
|
||||
import { calculateTtrEvent } from '../src/services/ttrCalculator.mjs';
|
||||
|
||||
const source = readFileSync(new URL('../src/components/MatchReportApiDialog.vue', import.meta.url), 'utf8');
|
||||
const script = source.match(/<script>([\s\S]*?)<\/script>/)[1]
|
||||
.replace(/^import .*;\n/gm, '')
|
||||
.replace('export default', 'globalThis.component =');
|
||||
const requests = [];
|
||||
const context = vm.createContext({ console, calculateTtrChange, apiClient: {
|
||||
const context = vm.createContext({ console, calculateTtrEvent, apiClient: {
|
||||
async post(url, body) {
|
||||
requests.push({ url, body });
|
||||
return { data: { players: [] } };
|
||||
@@ -19,7 +19,7 @@ vm.runInContext(script, context);
|
||||
const { methods, computed } = context.component;
|
||||
|
||||
function dialog() {
|
||||
return Object.assign({}, methods, {
|
||||
const report = Object.assign({}, methods, {
|
||||
results: [
|
||||
{ label: 'D1-D1', homeName: 'Anton Schottdorf / Anna Wolf', guestName: 'Yumin Kim / Timo Engler' },
|
||||
{ label: '1. Einzel der Runde', homeName: 'Anton Schottdorf', guestName: 'Yumin Kim', completed: false },
|
||||
@@ -27,6 +27,8 @@ function dialog() {
|
||||
ttrSnapshots: {},
|
||||
ttrPlayers: [],
|
||||
});
|
||||
Object.defineProperty(report, 'ttrSingles', { get: () => computed.ttrSingles.call(report) });
|
||||
return report;
|
||||
}
|
||||
|
||||
test('singles with a D in their title are retained while double formation labels are excluded', () => {
|
||||
@@ -48,22 +50,59 @@ test('missing TTR values retain the single and are not treated as zero', () => {
|
||||
assert.equal(rows.length, 1);
|
||||
assert.equal(rows[0].homeTtr, 1300);
|
||||
assert.equal(rows[0].guestTtr, null);
|
||||
assert.equal(rows[0].preview, null);
|
||||
assert.equal(rows[0].winner, null);
|
||||
assert.equal(computed.ttrUnavailablePlayers.call(report)[0], 'Yumin Kim');
|
||||
});
|
||||
|
||||
test('available ratings produce the preview and a completed single uses the entered result', () => {
|
||||
test('ratings without results show no projection; a completed single shows new ratings for both players', () => {
|
||||
const report = dialog();
|
||||
report.applyTtrPreviewPlayers([
|
||||
{ side: 'home', name: 'Anton Schottdorf', ttr: 1300 },
|
||||
{ side: 'guest', name: 'Yumin Kim', ttr: 1300 },
|
||||
]);
|
||||
assert.equal(computed.ttrSingles.call(report)[0].preview.homeWin.displayChange, 8);
|
||||
assert.ok(computed.ttrPlayerResults.call(report).every(player => player.projectedTtr === null));
|
||||
report.results[1].completed = true;
|
||||
report.getPlayerSetWins = (_match, side) => side === 'home' ? 3 : 0;
|
||||
const row = computed.ttrSingles.call(report)[0];
|
||||
assert.equal(row.actual.home.displayChange, 8);
|
||||
assert.equal(row.actual.guest.displayChange, -8);
|
||||
const players = computed.ttrPlayerResults.call(report);
|
||||
assert.equal(players[0].projectedTtr, 1308);
|
||||
assert.equal(players[1].projectedTtr, 1292);
|
||||
assert.equal(players[0].completedCount, 1);
|
||||
});
|
||||
|
||||
test('player totals use the original snapshot and round once across completed singles only', () => {
|
||||
const report = dialog();
|
||||
report.results[0].completed = true; // A double must never enter the total.
|
||||
report.results[1].completed = true;
|
||||
report.results.push({ label: 'E1-E2', homeName: 'Anton Schottdorf', guestName: 'Timo Engler', completed: true });
|
||||
report.results.push({ label: 'E1-E3', homeName: 'Anton Schottdorf', guestName: 'Ramón Hirschfeld', completed: false });
|
||||
report.getPlayerSetWins = (_match, side) => side === 'home' ? 3 : 0;
|
||||
report.applyTtrPreviewPlayers([
|
||||
{ side: 'home', name: 'Anton Schottdorf', ttr: 1318 },
|
||||
{ side: 'guest', name: 'Yumin Kim', ttr: 1382 },
|
||||
{ side: 'guest', name: 'Timo Engler', ttr: 1429 },
|
||||
{ side: 'guest', name: 'Ramón Hirschfeld', ttr: 1500 },
|
||||
]);
|
||||
let players = computed.ttrPlayerResults.call(report);
|
||||
assert.equal(players[0].completedCount, 2);
|
||||
assert.equal(players[0].projectedTtr, 1343);
|
||||
assert.equal(players.find(player => player.name === 'Ramón Hirschfeld').projectedTtr, null);
|
||||
report.results[1].completed = false;
|
||||
report.results[2].completed = false;
|
||||
players = computed.ttrPlayerResults.call(report);
|
||||
assert.equal(players[0].completedCount, 0);
|
||||
assert.equal(players[0].projectedTtr, null);
|
||||
});
|
||||
|
||||
test('missing opponent ratings prevent misleading partial totals for completed results', () => {
|
||||
const report = dialog();
|
||||
report.results[1].completed = true;
|
||||
report.getPlayerSetWins = (_match, side) => side === 'home' ? 3 : 0;
|
||||
report.applyTtrPreviewPlayers([{ side: 'home', name: 'Anton Schottdorf', ttr: 1300 }]);
|
||||
const players = computed.ttrPlayerResults.call(report);
|
||||
assert.equal(players[0].completedCount, 1);
|
||||
assert.equal(players[0].missingOpponentTtr, true);
|
||||
assert.equal(players[0].projectedTtr, null);
|
||||
assert.equal(players[1].projectedTtr, null);
|
||||
});
|
||||
|
||||
test('standalone test mode calls the API and keeps real pairings without inventing ratings', async () => {
|
||||
@@ -82,7 +121,7 @@ test('standalone test mode calls the API and keeps real pairings without inventi
|
||||
const rows = computed.ttrSingles.call(report);
|
||||
assert.equal(rows.length, 1);
|
||||
assert.equal(rows[0].homeTtr, null);
|
||||
assert.equal(rows[0].preview, null);
|
||||
assert.equal(rows[0].winner, null);
|
||||
});
|
||||
|
||||
test('TTR requests include displayed singles even when legacy lineup metadata is missing', () => {
|
||||
|
||||
Reference in New Issue
Block a user