Refactor: reimplement flowchart calculation
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
cb63919d40
commit
476cd0bd61
6 changed files with 329 additions and 241 deletions
|
@ -15,6 +15,7 @@ interface CompetitionList {
|
||||||
*/
|
*/
|
||||||
export class DigitalrockAPi {
|
export class DigitalrockAPi {
|
||||||
private BASE_URL = 'https://www.digitalrock.de/egroupware/ranking/json.php?';
|
private BASE_URL = 'https://www.digitalrock.de/egroupware/ranking/json.php?';
|
||||||
|
// private BASE_URL = '/test.json?';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* function to get competitions
|
* function to get competitions
|
||||||
|
|
|
@ -1,9 +1,22 @@
|
||||||
import { SpeedCompetitionCategoryResult } from '../models/Competition';
|
import {
|
||||||
import { Participant } from '../models/Participant';
|
RouteNames,
|
||||||
|
SpeedCompetitionCategoryResult,
|
||||||
|
} from '../models/Competition';
|
||||||
|
import {
|
||||||
|
Participant,
|
||||||
|
participantFromApiParticipant,
|
||||||
|
} from '../models/Participant';
|
||||||
|
|
||||||
|
export interface SpeedRoundParticipant {
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
hasWon: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface SpeedRoundPair {
|
export interface SpeedRoundPair {
|
||||||
laneA?: Participant;
|
laneA?: Participant;
|
||||||
laneB?: Participant;
|
laneB?: Participant;
|
||||||
|
winner?: 'A' | 'B';
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SpeedRound {
|
export interface SpeedRound {
|
||||||
|
@ -12,217 +25,217 @@ export interface SpeedRound {
|
||||||
roundName?: string;
|
roundName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export interface SpeedFlowchartResult {
|
||||||
* Class for use with speed flowcharts
|
rounds: SpeedRound[];
|
||||||
*/
|
|
||||||
export class SpeedFlowchart {
|
|
||||||
private _result: SpeedCompetitionCategoryResult;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {SpeedCompetitionCategoryResult} result
|
|
||||||
*/
|
|
||||||
constructor(result: SpeedCompetitionCategoryResult) {
|
|
||||||
this._result = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return {SpeedRound[]} list of speed rounds
|
* @param {number} roundNumber
|
||||||
|
* @param {RouteNames} routeNames
|
||||||
|
* @return {string | undefined}
|
||||||
*/
|
*/
|
||||||
public _convert() {
|
function getRoundName(
|
||||||
const allData: SpeedRound[] = [];
|
roundNumber: number,
|
||||||
|
routeNames: RouteNames,
|
||||||
|
): string | undefined {
|
||||||
|
if (roundNumber < 2 || roundNumber > 6) return undefined;
|
||||||
|
|
||||||
const rounds =
|
return routeNames[roundNumber];
|
||||||
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;
|
* @param {string} name
|
||||||
};
|
* @return {number}
|
||||||
// console.log(this._result.route_names);
|
*/
|
||||||
|
function getRoundRank(name: string): number {
|
||||||
|
const match = name.match(/1\/([842])/);
|
||||||
|
console.log(match);
|
||||||
|
if (match === undefined || match === null || match.length !== 2) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return parseInt(match[1]);
|
||||||
|
}
|
||||||
|
|
||||||
for (const round in this._result.route_names) {
|
/**
|
||||||
|
*
|
||||||
|
* @param {SpeedRoundPair} pair
|
||||||
|
* @param {number} roundIndex
|
||||||
|
*/
|
||||||
|
function computeWinnerOfPair(pair: SpeedRoundPair, roundIndex: number) {
|
||||||
if (
|
if (
|
||||||
Object.keys(this._result.route_names).indexOf(round) >= 0 &&
|
pair.laneA?.results[roundIndex]?.rank === undefined ||
|
||||||
parseInt(round) >= 0
|
pair.laneB?.results[roundIndex]?.rank === undefined
|
||||||
) {
|
)
|
||||||
// console.log(round);
|
return;
|
||||||
|
|
||||||
if (parseInt(round) === 0) {
|
if (pair.winner === undefined) {
|
||||||
// this is the first round
|
pair.winner =
|
||||||
|
pair.laneA.results[roundIndex].rank > pair.laneB.results[roundIndex].rank
|
||||||
// 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)
|
? 'B'
|
||||||
|
: 'A';
|
||||||
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 ?? '')
|
* @param {SpeedRoundPair} pair
|
||||||
|
* @param {number} roundNumber
|
||||||
|
* @return {Participant | undefined}
|
||||||
|
*/
|
||||||
|
function getWinnerOfPair(
|
||||||
|
pair: SpeedRoundPair,
|
||||||
|
roundNumber: number,
|
||||||
|
): Participant | undefined {
|
||||||
|
computeWinnerOfPair(pair, roundNumber);
|
||||||
|
return pair.winner === 'A' ? pair.laneA : pair.laneB;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {SpeedRoundPair} pair
|
||||||
|
* @param {number} roundNumber
|
||||||
|
* @return {Participant | undefined}
|
||||||
|
*/
|
||||||
|
function getLooserOfPair(
|
||||||
|
pair: SpeedRoundPair,
|
||||||
|
roundNumber: number,
|
||||||
|
): Participant | undefined {
|
||||||
|
computeWinnerOfPair(pair, roundNumber);
|
||||||
|
return pair.winner === 'A' ? pair.laneB : pair.laneA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {number} roundIndex index of the new round
|
||||||
|
* @param {string} roundName name of the new round
|
||||||
|
* @param {SpeedRound} previousRound
|
||||||
|
* @param {boolean} takeLooser
|
||||||
|
* @return {SpeedRound}
|
||||||
|
*/
|
||||||
|
function computeRoundFromPreviousRound(
|
||||||
|
roundIndex: number,
|
||||||
|
roundName: string,
|
||||||
|
previousRound: SpeedRound,
|
||||||
|
takeLooser = false,
|
||||||
|
): SpeedRound {
|
||||||
|
const getAdvancingParticipant = takeLooser
|
||||||
|
? getLooserOfPair
|
||||||
|
: getWinnerOfPair;
|
||||||
|
const nextRoundPairs = new Array(previousRound.pairs.length / 2)
|
||||||
|
.fill(0)
|
||||||
|
.map((_, i) => {
|
||||||
|
return {
|
||||||
|
laneA: getAdvancingParticipant(
|
||||||
|
previousRound.pairs[i * 2],
|
||||||
|
previousRound.roundIndex,
|
||||||
|
),
|
||||||
|
laneB: getAdvancingParticipant(
|
||||||
|
previousRound.pairs[i * 2 + 1],
|
||||||
|
previousRound.roundIndex,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
pairs: nextRoundPairs,
|
||||||
|
roundIndex: roundIndex,
|
||||||
|
roundName: roundName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {SpeedCompetitionCategoryResult} result The result to process
|
||||||
|
* @return {SpeedFlowchartResult}
|
||||||
|
*/
|
||||||
|
export function convertResultsToSpeedFlowchartResult(
|
||||||
|
result: SpeedCompetitionCategoryResult,
|
||||||
|
): SpeedFlowchartResult {
|
||||||
|
const rounds: SpeedRound[] = [];
|
||||||
|
const convertedParticipants = result.participants
|
||||||
|
.map(fromApi => participantFromApiParticipant(fromApi))
|
||||||
|
// sort by qualification result
|
||||||
|
.sort((a, b) => a.results[0].rank - b.results[0].rank);
|
||||||
|
|
||||||
|
const roundIndices = Object.keys(result.route_names)
|
||||||
|
.map(number => parseInt(number))
|
||||||
|
.filter(number => number > 0);
|
||||||
|
|
||||||
|
console.log(`Have final rounds:`, roundIndices);
|
||||||
|
|
||||||
|
// process first round
|
||||||
|
const firstRoundName = getRoundName(roundIndices[0], result.route_names);
|
||||||
|
const firstRoundNumber = getRoundRank(
|
||||||
|
getRoundName(roundIndices[0], result.route_names) ?? '',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getOpponent = (ofRank: number): Participant => {
|
||||||
|
return convertedParticipants[firstRoundNumber * 2 - 1 - ofRank];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Should be:
|
||||||
|
// 0, 1, 2, 3, 4, 5, 6, 7
|
||||||
|
// - 1,16, 8, 9, 4,13, 5,12, 2,15, 7,10, 3,14, 6,11
|
||||||
|
// - 1, 8, 4, 5, 2, 7, 3, 6 for firstRoundNumber=8
|
||||||
|
// - 1, 4, 2, 3 for firstRoundNumber=4
|
||||||
|
// - 1, 2 for firstRoundNumber=2
|
||||||
|
// TODO: come up with a proper alogorithm maybe
|
||||||
|
const ranksOfLaneAInOrder = [
|
||||||
|
[1, 2],
|
||||||
|
[1, 4, 2, 3],
|
||||||
|
[1, 8, 4, 5, 2, 7, 3, 6],
|
||||||
|
][firstRoundNumber / 4];
|
||||||
|
console.log(ranksOfLaneAInOrder);
|
||||||
|
|
||||||
|
const firstRoundPairs = ranksOfLaneAInOrder.map(rank => {
|
||||||
|
return {
|
||||||
|
laneA: convertedParticipants[rank - 1],
|
||||||
|
laneB: getOpponent(rank - 1),
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const nextRoundPairs: SpeedRoundPair[] = [];
|
const firstRound: SpeedRound = {
|
||||||
const totalMatches =
|
pairs: firstRoundPairs,
|
||||||
(Object.keys(this._result.route_names).length > 2
|
roundIndex: roundIndices[0],
|
||||||
? this._result.route_names['2']?.includes('8')
|
roundName: firstRoundName,
|
||||||
? 2
|
};
|
||||||
: 1
|
|
||||||
: 0) + 2;
|
|
||||||
const nextRoundMatches = Math.pow(2, totalMatches - 1);
|
|
||||||
|
|
||||||
for (let i = 0; i < nextRoundMatches; i++) {
|
rounds.push(firstRound);
|
||||||
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; ... ))
|
// compute following rounds
|
||||||
|
for (let i = 1; i < roundIndices.length - 2; i++) {
|
||||||
const sortedFirstRoundPairs: [SpeedRoundPair?, SpeedRoundPair?][] =
|
rounds.push(
|
||||||
[];
|
computeRoundFromPreviousRound(
|
||||||
|
roundIndices[i],
|
||||||
for (let i = 0; i < nextRoundMatches; i += 1) {
|
result.route_names[roundIndices[i]] ?? '',
|
||||||
sortedFirstRoundPairs.push([
|
rounds[i - 1],
|
||||||
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
|
// compute final and semi final
|
||||||
|
const semifinalRoundIndex = roundIndices[roundIndices.length - 2];
|
||||||
|
const semifinal = computeRoundFromPreviousRound(
|
||||||
|
semifinalRoundIndex,
|
||||||
|
result.route_names[semifinalRoundIndex] ?? '',
|
||||||
|
rounds[rounds.length - 1],
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
computeWinnerOfPair(semifinal.pairs[0], semifinalRoundIndex);
|
||||||
|
rounds.push(semifinal);
|
||||||
|
|
||||||
const finalFirstRoundPairs: SpeedRoundPair[] = [];
|
const finalRoundIndex = roundIndices[roundIndices.length - 1];
|
||||||
|
const final = computeRoundFromPreviousRound(
|
||||||
|
finalRoundIndex,
|
||||||
|
result.route_names[finalRoundIndex] ?? '',
|
||||||
|
rounds[rounds.length - 2],
|
||||||
|
);
|
||||||
|
computeWinnerOfPair(final.pairs[0], finalRoundIndex);
|
||||||
|
rounds.push(final);
|
||||||
|
|
||||||
for (let i = 0; i < finalSortedFirstRoundPairs.length; i++) {
|
return {
|
||||||
const [laneA, laneB] = finalSortedFirstRoundPairs[i];
|
rounds: rounds,
|
||||||
if (laneA !== undefined) finalFirstRoundPairs.push(laneA);
|
|
||||||
if (laneB !== undefined) finalFirstRoundPairs.push(laneB);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Category } from './Category';
|
import { Category } from './Category';
|
||||||
import { Participant } from './Participant';
|
import { ParticipantFromApi } from './Participant';
|
||||||
|
|
||||||
export interface Competiton {
|
export interface Competiton {
|
||||||
WetId: string;
|
WetId: string;
|
||||||
|
@ -10,8 +10,7 @@ export interface Competiton {
|
||||||
cats: Category[];
|
cats: Category[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SpeedCompetitionCategoryResult extends Competiton {
|
export interface RouteNames {
|
||||||
route_names: {
|
|
||||||
'0'?: string; // Qualification
|
'0'?: string; // Qualification
|
||||||
'1'?: string; // 1/16 - Final
|
'1'?: string; // 1/16 - Final
|
||||||
'2'?: string; // 1/8 - Final
|
'2'?: string; // 1/8 - Final
|
||||||
|
@ -21,6 +20,9 @@ export interface SpeedCompetitionCategoryResult extends Competiton {
|
||||||
'6'?: string; // Final
|
'6'?: string; // Final
|
||||||
'-1'?: string; // General result
|
'-1'?: string; // General result
|
||||||
[key: string]: string | undefined;
|
[key: string]: string | undefined;
|
||||||
};
|
}
|
||||||
participants: Participant[];
|
|
||||||
|
export interface SpeedCompetitionCategoryResult extends Competiton {
|
||||||
|
route_names: RouteNames;
|
||||||
|
participants: ParticipantFromApi[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* A pariticpant of a competition
|
* A pariticpant of a competition
|
||||||
*/
|
*/
|
||||||
export interface Participant {
|
export interface ParticipantFromApi {
|
||||||
PerId: string;
|
PerId: string;
|
||||||
firstname: string;
|
firstname: string;
|
||||||
lastname: string;
|
lastname: string;
|
||||||
|
@ -13,5 +13,65 @@ export interface Participant {
|
||||||
['result_rank4']?: string;
|
['result_rank4']?: string;
|
||||||
['result_rank5']?: string;
|
['result_rank5']?: string;
|
||||||
['result_rank6']?: string;
|
['result_rank6']?: string;
|
||||||
[key: string]: string | number | undefined;
|
[key: string]: string | number | boolean | undefined;
|
||||||
|
}
|
||||||
|
export interface Participant {
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
results: Result[];
|
||||||
|
overallRank?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Result {
|
||||||
|
rank: number;
|
||||||
|
result: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to extract results from PartiipantFromApi
|
||||||
|
* @param {ParticipantFromApi} fromApi
|
||||||
|
* @return {Result[]}
|
||||||
|
*/
|
||||||
|
function _extractResults(fromApi: ParticipantFromApi): Result[] {
|
||||||
|
const results: Result[] = Array(7);
|
||||||
|
|
||||||
|
const existingResults = Object.keys(fromApi).filter(key =>
|
||||||
|
key.match(/result[0-9]/),
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const result of existingResults) {
|
||||||
|
let roundNumber = 0;
|
||||||
|
const match = result.match(/result([0-9])/);
|
||||||
|
if (match !== undefined && match !== null) {
|
||||||
|
roundNumber = parseInt(match[1]);
|
||||||
|
}
|
||||||
|
if (roundNumber < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
results[roundNumber] = {
|
||||||
|
rank: parseInt(fromApi[`result_rank${roundNumber}`] as string),
|
||||||
|
result: fromApi[`result${roundNumber}`] as string,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to clean up participants from the api
|
||||||
|
* @param {ParticipantFromApi} fromApi
|
||||||
|
* @return {Participant}
|
||||||
|
*/
|
||||||
|
export function participantFromApiParticipant(
|
||||||
|
fromApi: ParticipantFromApi,
|
||||||
|
): Participant {
|
||||||
|
const results = _extractResults(fromApi);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: fromApi.PerId,
|
||||||
|
firstName: fromApi.firstname,
|
||||||
|
lastName: fromApi.lastname,
|
||||||
|
results: results,
|
||||||
|
overallRank: fromApi.result_rank,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import { Context } from '../data/Context';
|
import { Context } from '../data/Context';
|
||||||
import { useContext, useEffect, useState } from 'react';
|
import { useContext, useEffect, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { SpeedFlowchart, SpeedRound } from '../data/SpeedFlowchart';
|
import {
|
||||||
import { Card, CardContent, Grid } from '@mui/material';
|
convertResultsToSpeedFlowchartResult,
|
||||||
|
SpeedFlowchartResult,
|
||||||
|
} from '../data/SpeedFlowchart';
|
||||||
|
import { Card, CardContent, Grid, Typography } from '@mui/material';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -12,7 +15,8 @@ export default function SpeedFlowchartPage() {
|
||||||
const { competitionId, categoryId } = useParams();
|
const { competitionId, categoryId } = useParams();
|
||||||
const { api } = useContext(Context);
|
const { api } = useContext(Context);
|
||||||
|
|
||||||
const [rounds, setRounds] = useState<SpeedRound[]>([]);
|
const [flowchartResult, setFlowchartResult] =
|
||||||
|
useState<SpeedFlowchartResult>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (competitionId === undefined || categoryId === undefined) {
|
if (competitionId === undefined || categoryId === undefined) {
|
||||||
|
@ -20,12 +24,9 @@ export default function SpeedFlowchartPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
api.getCompetitionResults(competitionId, categoryId).then(r => {
|
api.getCompetitionResults(competitionId, categoryId).then(r => {
|
||||||
const flowchart = new SpeedFlowchart(r);
|
const flowchartResult = convertResultsToSpeedFlowchartResult(r);
|
||||||
const rounds = flowchart
|
console.log(flowchartResult);
|
||||||
._convert()
|
setFlowchartResult(flowchartResult);
|
||||||
.filter(round => round.roundName !== undefined && round.pairs.length);
|
|
||||||
console.log(rounds);
|
|
||||||
setRounds(rounds);
|
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ export default function SpeedFlowchartPage() {
|
||||||
<>
|
<>
|
||||||
<h1>RESULT:</h1>
|
<h1>RESULT:</h1>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
{rounds.map((round, roundKey) => (
|
{flowchartResult?.rounds.map((round, roundKey) => (
|
||||||
<Grid key={`flowchart-column-${roundKey}`} item xs={12 / 5}>
|
<Grid key={`flowchart-column-${roundKey}`} item xs={12 / 5}>
|
||||||
<h3>{round.roundName}</h3>
|
<h3>{round.roundName}</h3>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
|
@ -45,9 +46,20 @@ export default function SpeedFlowchartPage() {
|
||||||
>
|
>
|
||||||
<Card>
|
<Card>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
A: {pair.laneA?.firstname} {pair.laneA?.lastname}
|
<Typography
|
||||||
<br />
|
sx={{
|
||||||
B: {pair.laneB?.firstname} {pair.laneB?.lastname}
|
fontWeight: pair.winner === 'A' ? 'bold' : 'plain',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
A: {pair.laneA?.firstName} {pair.laneA?.lastName}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontWeight: pair.winner === 'B' ? 'bold' : 'plain',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
B: {pair.laneB?.firstName} {pair.laneB?.lastName}
|
||||||
|
</Typography>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
import { BrowserRouter, Routes, Route, HashRouter } from 'react-router-dom';
|
||||||
import CalendarPage from '../pages/CalendarPage';
|
import CalendarPage from '../pages/CalendarPage';
|
||||||
import SpeedFlowchartPage from '../pages/SpeedFlowchartPage';
|
import SpeedFlowchartPage from '../pages/SpeedFlowchartPage';
|
||||||
import PageTemplate from './PageTemplate';
|
import PageTemplate from './PageTemplate';
|
||||||
|
@ -9,16 +9,16 @@ import PageTemplate from './PageTemplate';
|
||||||
*/
|
*/
|
||||||
export default function Routing() {
|
export default function Routing() {
|
||||||
return (
|
return (
|
||||||
<BrowserRouter>
|
<HashRouter>
|
||||||
<PageTemplate>
|
<PageTemplate>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path='/' element={<CalendarPage />} />
|
<Route path='/' element={<CalendarPage />} />
|
||||||
<Route
|
<Route
|
||||||
path='/#/speed-flowchart/:competitionId/:categoryId'
|
path='/speed-flowchart/:competitionId/:categoryId'
|
||||||
element={<SpeedFlowchartPage />}
|
element={<SpeedFlowchartPage />}
|
||||||
></Route>
|
></Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
</PageTemplate>
|
</PageTemplate>
|
||||||
</BrowserRouter>
|
</HashRouter>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue