Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
CourtHive committed Apr 22, 2024
2 parents b377696 + 515a373 commit f814c6e
Show file tree
Hide file tree
Showing 17 changed files with 353 additions and 103 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { checkRequiredParameters } from '@Helpers/parameters/checkRequiredParameters';
import { addDays, extractDate } from '@Tools/dateTime';
import { UUID } from '@Tools/UUID';

// Constants
import { SUCCESS } from '@Constants/resultConstants';
import { Tournament } from '@Types/tournamentTypes';

type CopyTournamentRecordArgs = {
tournamentRecord: Tournament;
copyParticipants?: boolean;
tournamentName: string;
startDate: string;
endDate?: string;
};

export function copyTournamentRecord(params: CopyTournamentRecordArgs) {
const paramsCheck = checkRequiredParameters(params, [
{ tournamentRecord: true, startDate: true, endDate: false, tournamentName: true },
]);
if (paramsCheck.error) return paramsCheck;

const { startDate, endDate } = params.tournamentRecord;
const dayMilliseconds = 24 * 60 * 60 * 1000;
const tournamentDayMilliseconds =
startDate && endDate ? new Date(extractDate(endDate)).getTime() - new Date(extractDate(startDate)).getTime() : 0;
const tournamentDays = tournamentDayMilliseconds / dayMilliseconds;
const newEndDate = params.endDate || addDays(params.startDate, tournamentDays);

const copyParticipant = (participant) => {
const { timeItems, ...rest } = participant;
return { ...rest };
};

const copyEvent = (event) => {
const { drawDefinitions, ...rest } = event;
return { ...rest };
};

const tournamentRecord = {
participants: params.copyParticipants ? params.tournamentRecord.participants?.map(copyParticipant) ?? [] : [],
parentOrganisation: { ...params.tournamentRecord.parentOrganisation },
events: params.tournamentRecord.events?.map(copyEvent) ?? [],
weekdays: { ...params.tournamentRecord.weekdays },
venues: { ...params.tournamentRecord.venues },
tournamentName: params.tournamentName,
startDate: params.startDate,
tournamentId: UUID(),
endDate: newEndDate,
};

return { ...SUCCESS, tournamentRecord };
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { UUID } from '@Tools/UUID';
import { INVALID_DATE } from '@Constants/errorConditionConstants';

export function createTournamentRecord(params): any {
const attributes = params || {};
const { tournamentRecord, tournamentRecords, activeTournamentId, ...attributes } = params || {};
if (!attributes.tournamentId) attributes.tournamentId = UUID();
if (attributes.startDate && !isISODateString(attributes.startDate) && !validDateString.test(attributes.startDate)) {
return { error: INVALID_DATE };
Expand Down
1 change: 1 addition & 0 deletions src/assemblies/governors/tournamentGovernor/generate.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { createTournamentRecord } from '@Generators/tournamentRecords/createTournamentRecord';
export { copyTournamentRecord } from '@Generators/tournamentRecords/copyTournamentRecord';
2 changes: 2 additions & 0 deletions src/assemblies/governors/tournamentGovernor/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ export { getCompetitionPenalties } from '@Query/participants/getCompetitionPenal
export { getCompetitionDateRange } from '@Query/tournaments/getCompetitionDateRange';
export { getTournamentPenalties } from '@Query/participants/getTournamentPenalties';
export { getTournamentPersons } from '@Query/tournaments/getTournamentPersons';
export { getAggregateTeamResults } from '@Query/scales/getAggregateTeamResults';
export { getTournamentStructures } from '@Query/structure/structureGetter';
export { analyzeTournament } from '@Query/tournaments/analyzeTournament';
export { getTournamentInfo } from '@Query/tournaments/getTournamentInfo';
export { getTournamentPoints } from '@Query/scales/getTournamentPoints';
export { analyzeDraws } from '@Query/tournaments/analyzeDraws';
export { getTournamentTimeItem } from '@Query/base/timeItems';
7 changes: 4 additions & 3 deletions src/helpers/keyValueScore/keyValueScore.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { getMatchUpWinner, removeFromScore, getHighTiebreakValue } from './keyValueUtilities';
import { getLeadingSide } from '@Query/matchUp/checkSetIsComplete';
import { processIncompleteSetScore } from './processIncompleteSetScore';
import { getLeadingSide } from '@Query/matchUp/checkSetIsComplete';
import { keyValueTimedSetScore } from './keyValueTimedSetScore';
import { processTiebreakSet } from './processTiebreakSet';
import { arrayIndices } from '@Tools/arrays';
import { ensureInt } from '@Tools/ensureInt';
import { keyValueSetScore } from './keyValueSetScore';
import { getScoreAnalysis } from './scoreAnalysis';
import { processOutcome } from './processOutcome';
import { getWinningSide } from './winningSide';
import { arrayIndices } from '@Tools/arrays';
import { ensureInt } from '@Tools/ensureInt';

// Constants
import { INCOMPLETE, TO_BE_PLAYED } from '@Constants/matchUpStatusConstants';
import {
SET_TIEBREAK_BRACKETS,
Expand Down
4 changes: 3 additions & 1 deletion src/helpers/matchUpFormatCode/parse.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { definedAttributes } from '@Tools/definedAttributes';
import { isConvertableInteger } from '@Tools/math';
import { isString } from '@Tools/objects';

// Constants
import { SET, NOAD, TIMED, setTypes } from '@Constants/matchUpFormatConstants';

type TiebreakFormat = {
Expand Down Expand Up @@ -32,7 +34,7 @@ export type ParsedFormat = {
};

export function parse(matchUpFormatCode: string): ParsedFormat | undefined {
if (typeof matchUpFormatCode === 'string') {
if (isString(matchUpFormatCode)) {
const type = (matchUpFormatCode.startsWith('T') && TIMED) || (matchUpFormatCode.startsWith(SET) && SET) || '';

if (type === TIMED) {
Expand Down
3 changes: 3 additions & 0 deletions src/mutate/drawDefinitions/resetDrawDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getMatchUpsMap } from '@Query/matchUps/getMatchUpsMap';
import { MISSING_DRAW_DEFINITION } from '@Constants/errorConditionConstants';
import { MAIN, QUALIFYING } from '@Constants/drawDefinitionConstants';
import { toBePlayed } from '@Fixtures/scoring/outcomes/toBePlayed';
import { POSITION_ACTIONS } from '@Constants/extensionConstants';
import { BYE } from '@Constants/matchUpStatusConstants';
import { SUCCESS } from '@Constants/resultConstants';
import { TimeItem } from '@Types/tournamentTypes';
Expand Down Expand Up @@ -95,6 +96,8 @@ export function resetDrawDefinition({ tournamentRecord, removeScheduling, drawDe
}
}

drawDefinition.extensions = drawDefinition.extensions.filter((extension) => extension.name !== POSITION_ACTIONS);

const structureIds = (drawDefinition.structures || []).map(({ structureId }) => structureId);

modifyDrawNotice({ drawDefinition, structureIds });
Expand Down
3 changes: 2 additions & 1 deletion src/mutate/matchUps/score/modifyMatchUpScore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
DEFAULTED,
WALKOVER,
IN_PROGRESS,
INCOMPLETE,
} from '@Constants/matchUpStatusConstants';

/**
Expand Down Expand Up @@ -138,7 +139,7 @@ export function modifyMatchUpScore(params: ModifyMatchUpScoreArgs) {
!matchUp.winningSide &&
checkScoreHasValue(matchUp) &&
!completedMatchUpStatuses.includes(matchUpStatus) &&
![AWAITING_RESULT, SUSPENDED].includes(matchUpStatus)
![AWAITING_RESULT, SUSPENDED, INCOMPLETE].includes(matchUpStatus)
) {
matchUp.matchUpStatus = IN_PROGRESS;
}
Expand Down
52 changes: 52 additions & 0 deletions src/query/scales/getAggregateTeamResults.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { checkRequiredParameters } from '@Helpers/parameters/checkRequiredParameters';
import { allTournamentMatchUps } from '@Query/matchUps/getAllTournamentMatchUps';
import { parse } from '@Helpers/matchUpFormatCode/parse';

// Constants
import { TOURNAMENT_RECORD } from '@Constants/attributeConstants';
import { SUCCESS } from '@Constants/resultConstants';

export function getAggregateTeamResults(params) {
const paramsCheck = checkRequiredParameters(params, [{ [TOURNAMENT_RECORD]: true }]);
if (paramsCheck.error) return paramsCheck;

const teamResults = {};
for (const matchUp of allTournamentMatchUps(params)?.matchUps ?? []) {
const { sides, matchUpFormat } = matchUp;
const parsedMatchUpFormat: any = matchUpFormat && parse(matchUpFormat);

// both sides must be present and must be a timed format
if (
sides?.length === 2 &&
parsedMatchUpFormat.setFormat?.timed &&
(!parsedMatchUpFormat.finalSetFormat || parsedMatchUpFormat.finalSetFormat?.timed)
) {
for (const side of sides) {
const individualTeams = side?.participant?.individualParticipants?.map(
(i) => i.teams?.length === 1 && i.teams[0],
);
const teamParticipant =
(side?.participant?.teams?.length === 1 && side?.participant?.teams?.[0]) ||
(individualTeams?.[0].participantId === individualTeams?.[1].participantId && individualTeams?.[0]);
const teamParticipantId = teamParticipant?.participantId;
const sideNumber = side.sideNumber;

if (teamParticipantId && sideNumber) {
if (!teamResults[teamParticipantId]) {
teamResults[teamParticipantId] = { score: 0, diff: 0, teamName: teamParticipant.participantName };
}
for (const set of matchUp.score?.sets ?? []) {
const opponentPoints = set?.[`side${3 - sideNumber}Score`] || 0;
const points = set?.[`side${sideNumber}Score`] || 0;
const diff = points - opponentPoints;

teamResults[teamParticipantId].score += points;
teamResults[teamParticipantId].diff += diff;
}
}
}
}
}

return { ...SUCCESS, teamResults };
}
2 changes: 1 addition & 1 deletion src/query/scales/getAwardPoints.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { isConvertableInteger } from '@Tools/math';
import { getTargetElement } from './getTargetElement';
import { isConvertableInteger } from '@Tools/math';

type GetAwardPointsArgs = {
participantWon?: boolean;
Expand Down
3 changes: 2 additions & 1 deletion src/tests/generators/mocks/generateOutcome.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import mocksEngine from '@Assemblies/engines/mock';
import { generateRange } from '@Tools/arrays';
import { it, test, expect } from 'vitest';

// Constants
import { INVALID_MATCHUP_FORMAT, INVALID_VALUES } from '@Constants/errorConditionConstants';
import {
COMPLETED,
DEFAULTED,
Expand All @@ -11,7 +13,6 @@ import {
SUSPENDED,
WALKOVER,
} from '@Constants/matchUpStatusConstants';
import { INVALID_MATCHUP_FORMAT, INVALID_VALUES } from '@Constants/errorConditionConstants';

const SET1T20 = 'SET1-S:T20';
const iterations = 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { getContextMatchUp, getOrderedDrawPositionPairs } from '../../drawDefinitions/testingUtilities';
import mocksEngine from '@Assemblies/engines/mock';
import tournamentEngine from '@Engines/syncEngine';
import { expect, it } from 'vitest';
import { getContextMatchUp, getOrderedDrawPositionPairs } from '../../drawDefinitions/testingUtilities';

// Constants
import { INCOMPATIBLE_MATCHUP_STATUS } from '@Constants/errorConditionConstants';
import { INCOMPLETE } from '@Constants/matchUpStatusConstants';

it('DISALLOWS entry of incomplete result if active downsream', () => {
it('DISALLOWS entry of incomplete result if active downstream', () => {
const drawProfiles = [
{
drawSize: 8,
Expand Down Expand Up @@ -38,21 +39,21 @@ it('DISALLOWS entry of incomplete result if active downsream', () => {

const { matchUps } = tournamentEngine.setState(tournamentRecord).allTournamentMatchUps();
const { matchUp } = getContextMatchUp({
matchUps,
roundNumber: 1,
roundPosition: 1,
roundNumber: 1,
matchUps,
});
const { drawId, matchUpId, structureId } = matchUp;

const values = {
scoreString: '6-1',
matchUpStatus: INCOMPLETE,
scoreString: '6-1',
};
const { outcome } = mocksEngine.generateOutcomeFromScoreString(values);
const result = tournamentEngine.setMatchUpStatus({
drawId,
matchUpId,
outcome,
drawId,
});
expect(result.error).toEqual(INCOMPATIBLE_MATCHUP_STATUS);

Expand All @@ -66,15 +67,15 @@ it('removes advanced participant when completed score changes to incomplete resu
drawSize: 8,
outcomes: [
{
roundNumber: 1,
roundPosition: 1,
scoreString: '6-1 6-1',
roundPosition: 1,
roundNumber: 1,
winningSide: 1,
},
{
roundNumber: 1,
roundPosition: 2,
scoreString: '6-1 6-2',
roundPosition: 2,
roundNumber: 1,
winningSide: 1,
},
],
Expand All @@ -86,21 +87,21 @@ it('removes advanced participant when completed score changes to incomplete resu

let { matchUps } = tournamentEngine.setState(tournamentRecord).allTournamentMatchUps();
let { matchUp } = getContextMatchUp({
matchUps,
roundNumber: 1,
roundPosition: 1,
roundNumber: 1,
matchUps,
});
const { drawId, matchUpId, structureId } = matchUp;

const values = {
scoreString: '6-1',
matchUpStatus: INCOMPLETE,
scoreString: '6-1',
};
const { outcome } = mocksEngine.generateOutcomeFromScoreString(values);
const result = tournamentEngine.setMatchUpStatus({
drawId,
matchUpId,
outcome,
drawId,
});
expect(result.success).toEqual(true);

Expand All @@ -109,9 +110,9 @@ it('removes advanced participant when completed score changes to incomplete resu

({ matchUps } = tournamentEngine.allTournamentMatchUps());
({ matchUp } = getContextMatchUp({
matchUps,
roundNumber: 1,
roundPosition: 1,
roundNumber: 1,
matchUps,
}));
expect(matchUp.score.scoreStringSide1).toEqual('6-1');
});
Expand All @@ -122,9 +123,9 @@ it('removes advanced participant in FINAL when completed score changes to incomp
drawSize: 2,
outcomes: [
{
roundNumber: 1,
roundPosition: 1,
scoreString: '6-1 6-1',
roundPosition: 1,
roundNumber: 1,
winningSide: 1,
},
],
Expand All @@ -136,30 +137,31 @@ it('removes advanced participant in FINAL when completed score changes to incomp

let { matchUps } = tournamentEngine.setState(tournamentRecord).allTournamentMatchUps();
let { matchUp } = getContextMatchUp({
matchUps,
roundNumber: 1,
roundPosition: 1,
roundNumber: 1,
matchUps,
});
const { drawId, matchUpId } = matchUp;

const values = {
scoreString: '6-1',
matchUpStatus: INCOMPLETE,
scoreString: '6-1',
};
const { outcome } = mocksEngine.generateOutcomeFromScoreString(values);
const result = tournamentEngine.setMatchUpStatus({
drawId,
matchUpId,
outcome,
drawId,
});
expect(result.success).toEqual(true);

({ matchUps } = tournamentEngine.allTournamentMatchUps());
({ matchUp } = getContextMatchUp({
matchUps,
roundNumber: 1,
roundPosition: 1,
roundNumber: 1,
matchUps,
}));
expect(matchUp.score.scoreStringSide1).toEqual('6-1');
expect(matchUp.matchUpStatus).toEqual(INCOMPLETE);
expect(matchUp.winningSide).toBeUndefined();
});
Loading

0 comments on commit f814c6e

Please sign in to comment.