speed-flowchart-web/src/data/SpeedFlowchart.tsx

231 lines
7.2 KiB
TypeScript

import { FILE } from 'dns';
import { SpeedCompetitionCategoryResult } from '../models/Competition';
import { Participant } from '../models/Participant';
export interface SpeedRoundPair {
laneA?: Participant;
laneB?: Participant;
}
export interface SpeedRound {
pairs: SpeedRoundPair[];
roundIndex: number;
roundName?: string;
}
/**
* Class for use with speed flowcharts
*/
export class SpeedFlowchart {
private _result: SpeedCompetitionCategoryResult;
/**
*
* @param {SpeedCompetitionCategoryResult} result
*/
constructor(result: SpeedCompetitionCategoryResult) {
this._result = result;
}
/**
*
* @return {SpeedRound[]} list of speed rounds
*/
public _convert() {
const allData: SpeedRound[] = [];
const rounds =
Object.keys(this._result.route_names).length > 2
? this._result.route_names['2']?.includes('8')
? 2
: 1
: 0;
const setAorB = (pair: SpeedRoundPair, participant: Participant) => {
if (pair.laneA === undefined) pair.laneA = participant;
else pair.laneB = participant;
};
// console.log(this._result.route_names);
for (const round in this._result.route_names) {
if (
Object.keys(this._result.route_names).indexOf(round) >= 0 &&
parseInt(round) >= 0
) {
// console.log(round);
if (parseInt(round) === 0) {
// this is the first round
// find pairs (always worse vs. best (1-16; 1-15; ...)) (they are sorted by the rank of the better athlete (1-2-3-4-5-6-7-8)
const qualificationResults: Participant[] = [];
for (let x = 0; x < this._result.participants.length; x++) {
qualificationResults.push(this._result.participants[x]);
}
qualificationResults.sort(function (a, b) {
return (
parseInt(a.result_rank0 ?? '') - parseInt(b.result_rank0 ?? '')
);
});
const nextRoundPairs: SpeedRoundPair[] = [];
const totalMatches =
(Object.keys(this._result.route_names).length > 2
? this._result.route_names['2']?.includes('8')
? 2
: 1
: 0) + 2;
const nextRoundMatches = Math.pow(2, totalMatches - 1);
for (let i = 0; i < nextRoundMatches; i++) {
nextRoundPairs.push({
laneA: qualificationResults[i],
laneB: qualificationResults[nextRoundMatches * 2 - i - 1],
});
}
// build second round pairs (sorted by the rank of the better athlete and worst vs. best (1-8; 2-7; ... ))
const sortedFirstRoundPairs: [SpeedRoundPair?, SpeedRoundPair?][] =
[];
for (let i = 0; i < nextRoundMatches; i += 1) {
sortedFirstRoundPairs.push([
nextRoundPairs.shift(),
nextRoundPairs.pop(),
]);
}
// sort these pairs (containing two pairs of athletes) by the rank of the better athlete (1-4;2-3)
const finalSortedFirstRoundPairs = [];
for (let i = 0; i < nextRoundMatches / 4; i++) {
finalSortedFirstRoundPairs.push(sortedFirstRoundPairs[i]);
finalSortedFirstRoundPairs.push(
sortedFirstRoundPairs[nextRoundMatches / 2 - i - 1],
);
}
// convert the list of pairs of pairs of athletes back to a single list of pairs of athletes
const finalFirstRoundPairs: SpeedRoundPair[] = [];
for (let i = 0; i < finalSortedFirstRoundPairs.length; i++) {
if (finalSortedFirstRoundPairs[i][0] !== undefined)
finalFirstRoundPairs.push(finalSortedFirstRoundPairs[i][0]!);
if (finalSortedFirstRoundPairs[i][1] !== undefined)
finalFirstRoundPairs.push(finalSortedFirstRoundPairs[i][1]!);
}
// push the first round to all data
allData.push({
pairs: finalFirstRoundPairs,
roundIndex: 2,
roundName: this._result.route_names[2] ?? '',
});
// console.log(allData);
} else if (parseInt(round) > 0) {
// this is not the first round
const nextRound: SpeedRound = {
pairs: [],
roundIndex: -1,
roundName: '',
};
// only used when the current round is the 1/2 final
const smallFinal: SpeedRoundPair = {};
const Final: SpeedRoundPair = {};
for (
let i = 0;
i < allData[allData.length - 1].pairs.length;
i += 1
) {
const thisPair: SpeedRoundPair =
allData[allData.length - 1].pairs[i];
let thisWinner;
let thisLooser;
const thisWinnerIsFirstOfNewPair = i % 2 === 0;
if (thisPair.laneA === undefined || thisPair.laneB === undefined) {
continue;
}
if (thisWinnerIsFirstOfNewPair) {
nextRound.pairs.push({});
}
if (
Object.keys(thisPair.laneA).indexOf('result_rank' + round) < 0 ||
Object.keys(thisPair.laneB).indexOf('result_rank' + round) < 0
) {
continue;
}
if (
parseInt(thisPair.laneA['result_rank' + round] as string) <
parseInt(thisPair.laneB['result_rank' + round] as string)
) {
thisWinner = thisPair.laneA;
thisLooser = thisPair.laneB;
} else if (
parseInt(thisPair.laneA['result_rank' + round] as string) >
parseInt(thisPair.laneB['result_rank' + round] as string)
) {
thisWinner = thisPair.laneB;
thisLooser = thisPair.laneA;
} else {
// no result yet!!
/* console.log(
'got no winner yet, rank 0: ' +
thisPair.laneA['result_rank' + round] +
' rank 1: ' +
thisPair.laneB['result_rank' + round],
);*/
continue;
}
// console.log(thisWinner['firstname'] + ' has won in round ' + round);
if (parseInt(round) - rounds === 2) {
// if we are in the 1/2 final
setAorB(Final, thisWinner);
setAorB(smallFinal, thisLooser);
} else {
setAorB(nextRound.pairs[nextRound.pairs.length - 1], thisWinner);
}
}
if (smallFinal.laneA !== undefined && Final.laneA !== undefined) {
// Final
allData.push({
pairs: [Final],
roundIndex: parseInt(round) + 2,
roundName:
this._result.route_names[String(parseInt(round) + 2)] +
' / ' +
this._result.route_names[String(parseInt(round) + 1)],
});
// small Final
allData.push({
pairs: [smallFinal],
roundIndex: parseInt(round) + 1,
});
} else {
nextRound.roundIndex = parseInt(round) + 1;
nextRound.roundName = this._result.route_names[parseInt(round) + 1];
allData.push(nextRound);
}
}
}
}
return allData;
}
}