feat(tournament): enhance tournament repair logic and normalize competition names
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 55s
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 55s
This commit is contained in:
@@ -35,6 +35,14 @@ class OfficialTournamentService {
|
||||
return [];
|
||||
}
|
||||
|
||||
normalizeCompetitionName(value) {
|
||||
return String(value || '')
|
||||
.toLocaleLowerCase('de')
|
||||
.replace(/mädchen\s*(\d{1,2})/g, 'm$1')
|
||||
.replace(/jungen\s*(\d{1,2})/g, 'j$1')
|
||||
.replace(/[^a-z0-9]/g, '');
|
||||
}
|
||||
|
||||
async repairTournamentFromSource(clubId, tournament) {
|
||||
let sourceUrl = tournament.sourceUrl;
|
||||
if (!sourceUrl) {
|
||||
@@ -47,19 +55,35 @@ class OfficialTournamentService {
|
||||
const source = new URL(sourceUrl);
|
||||
if (!['www.mytischtennis.de', 'mytischtennis.de'].includes(source.hostname)) return 0;
|
||||
const response = await axios.get(sourceUrl, { timeout: 30000, headers: { 'User-Agent': 'Trainingstagebuch/1.0 (+turnierdetails)' } });
|
||||
const competitions = this.extractJsonArray(response.data, 'competitions')
|
||||
.filter((competition) => competition?.name)
|
||||
const competitions = this.extractJsonArray(response.data, 'competition_infos')
|
||||
.filter((competition) => competition?.competition_name)
|
||||
.map((competition) => ({
|
||||
ageClassCompetition: String(competition.name).slice(0, 255),
|
||||
cutoffDate: competition.fed_rank_remarks ? String(competition.fed_rank_remarks).slice(0, 255) : null,
|
||||
ageClassCompetition: String(competition.competition_name).slice(0, 255),
|
||||
startTime: [competition.formattedStartDate, String(competition.formattedStartTime || '').replace(/\s*Uhr$/i, '')].filter(Boolean).join(', ') || null,
|
||||
registrationDeadlineDate: competition.formattedRegistrationEnd || null,
|
||||
registrationDeadlineOnline: competition.formattedRegistrationEnd || null,
|
||||
cutoffDate: competition.competition_fed_rank_remarks ? String(competition.competition_fed_rank_remarks).slice(0, 255) : null,
|
||||
ttrRelevant: competition.ttr_relevant ? 'Ja' : 'Nein',
|
||||
openTo: Array.isArray(competition.open_for) ? competition.open_for.join(', ') : null,
|
||||
preliminaryRound: competition.competition_playmode || null,
|
||||
maxParticipants: competition.competition_player_capacity_total == null ? null : String(competition.competition_player_capacity_total),
|
||||
entryFee: competition.competition_fee == null ? null : `${competition.competition_fee}${competition.competition_fee_currency === 'euro' ? '€' : ''}`,
|
||||
}));
|
||||
if (!competitions.length) return 0;
|
||||
|
||||
const existing = await OfficialCompetition.findAll({ where: { tournamentId: tournament.id }, attributes: ['ageClassCompetition'] });
|
||||
const existingNames = new Set(existing.map((competition) => competition.ageClassCompetition));
|
||||
const missing = competitions.filter((competition) => !existingNames.has(competition.ageClassCompetition));
|
||||
if (missing.length) await OfficialCompetition.bulkCreate(missing.map((competition) => ({ tournamentId: tournament.id, ...competition })));
|
||||
return missing.length;
|
||||
const existing = await OfficialCompetition.findAll({ where: { tournamentId: tournament.id } });
|
||||
const byName = new Map(existing.map((competition) => [this.normalizeCompetitionName(competition.ageClassCompetition), competition]));
|
||||
let repaired = 0;
|
||||
for (const competition of competitions) {
|
||||
const existingCompetition = byName.get(this.normalizeCompetitionName(competition.ageClassCompetition));
|
||||
if (existingCompetition) {
|
||||
await existingCompetition.update(competition);
|
||||
} else {
|
||||
await OfficialCompetition.create({ tournamentId: tournament.id, ...competition });
|
||||
}
|
||||
repaired += 1;
|
||||
}
|
||||
return repaired;
|
||||
}
|
||||
|
||||
async saveTournamentSuggestion(clubId, suggestionId) {
|
||||
@@ -173,7 +197,8 @@ class OfficialTournamentService {
|
||||
if (!t) return null;
|
||||
|
||||
let comps = await OfficialCompetition.findAll({ where: { tournamentId: id } });
|
||||
if (!comps.length) {
|
||||
const needsRepair = !comps.length || comps.some((competition) => !competition.startTime || competition.entryFee == null);
|
||||
if (needsRepair) {
|
||||
try {
|
||||
await this.repairTournamentFromSource(clubId, t);
|
||||
comps = await OfficialCompetition.findAll({ where: { tournamentId: id } });
|
||||
|
||||
Reference in New Issue
Block a user