refactor(clickTtTournamentRegistrationService): optimize tournament search and link retrieval logic
- Streamlined the tournament search process by caching the results page URL to avoid redundant searches. - Enhanced the link retrieval mechanism to focus on table rows, improving accuracy in finding relevant tournament links. - Updated scoring criteria for link selection to better prioritize relevant entries based on tournament and competition context.
This commit is contained in:
@@ -152,11 +152,20 @@ class ClickTtTournamentRegistrationService {
|
||||
trace
|
||||
});
|
||||
await clickTtPlayerRegistrationService._selectClubContext(page, associationMemberNumber, trace);
|
||||
await this._openTournamentSearch(page, trace);
|
||||
await this._filterTournamentSearch(page, tournament, trace);
|
||||
const resultsPageUrl = page.url();
|
||||
|
||||
const processedCompetitions = [];
|
||||
for (const group of competitionGroups) {
|
||||
await this._openTournamentSearch(page, trace);
|
||||
await this._filterTournamentSearch(page, tournament, trace);
|
||||
if (page.url() !== resultsPageUrl) {
|
||||
clickTtPlayerRegistrationService._trace(trace, 'step', {
|
||||
name: 'open-search-results',
|
||||
url: resultsPageUrl
|
||||
});
|
||||
await page.goto(resultsPageUrl, { waitUntil: 'domcontentloaded' });
|
||||
await clickTtPlayerRegistrationService._dismissConsentOverlays(page, trace);
|
||||
}
|
||||
await this._openCompetitionRegistration(page, tournament, group.competition, trace);
|
||||
await this._selectCompetitionMembers(page, group.entries, trace);
|
||||
await this._openControlStep(page, trace);
|
||||
@@ -244,79 +253,8 @@ class ClickTtTournamentRegistrationService {
|
||||
}
|
||||
|
||||
const titleProfile = getTitleSearchProfile(tournament.title || '');
|
||||
const contentRoot = page.locator('#content-row1, #content, #container').first();
|
||||
|
||||
const tournamentHref = await contentRoot.locator('a').evaluateAll((anchors, criteria) => {
|
||||
const normalize = (value) => String(value || '')
|
||||
.normalize('NFKC')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
const tokenize = (value) => normalize(value)
|
||||
.split(/[^a-z0-9äöüß]+/i)
|
||||
.map((token) => token.trim())
|
||||
.filter((token) => token.length >= 3)
|
||||
.filter((token) => !new Set([
|
||||
'und', 'der', 'die', 'das', 'des', 'den', 'dem', 'von', 'für', 'mit',
|
||||
'ein', 'eine', 'einer', 'eines', 'zum', 'zur', 'im', 'am', 'an'
|
||||
]).has(token));
|
||||
|
||||
const wantedTitle = normalize(criteria.tournamentTitle);
|
||||
const wantedTokens = Array.isArray(criteria.tournamentTokens) ? criteria.tournamentTokens : [];
|
||||
const wantedTailTokens = Array.isArray(criteria.tournamentTailTokens) ? criteria.tournamentTailTokens : [];
|
||||
|
||||
let bestHref = null;
|
||||
let bestScore = -1;
|
||||
|
||||
for (const anchor of anchors) {
|
||||
const href = anchor.getAttribute('href');
|
||||
if (!href) continue;
|
||||
if (/dataProtection|legalNotice|logout|contact/i.test(href)) continue;
|
||||
|
||||
const text = normalize(anchor.textContent || '');
|
||||
const contextText = normalize(anchor.closest('tr, li, div, td')?.textContent || '');
|
||||
const combinedText = `${text} ${contextText}`.trim();
|
||||
const combinedTokens = new Set(tokenize(combinedText));
|
||||
|
||||
let score = 0;
|
||||
if (wantedTitle && combinedText.includes(wantedTitle)) score += 100;
|
||||
if (text && wantedTitle && text.includes(wantedTitle)) score += 30;
|
||||
|
||||
for (const token of wantedTokens) {
|
||||
if (combinedTokens.has(token)) score += 3;
|
||||
}
|
||||
|
||||
for (const token of wantedTailTokens) {
|
||||
if (combinedTokens.has(token)) score += 8;
|
||||
}
|
||||
|
||||
if (/turnier|meisterschaft|rangliste|pokal/i.test(combinedText)) score += 10;
|
||||
if (/anmelden|meldung|teilnehmer/i.test(combinedText)) score += 5;
|
||||
|
||||
if (score > bestScore) {
|
||||
bestScore = score;
|
||||
bestHref = href;
|
||||
}
|
||||
}
|
||||
|
||||
return bestHref;
|
||||
}, {
|
||||
tournamentTitle: tournament.title || '',
|
||||
tournamentTokens: titleProfile.tokens,
|
||||
tournamentTailTokens: titleProfile.tailTokens
|
||||
});
|
||||
|
||||
if (tournamentHref) {
|
||||
clickTtPlayerRegistrationService._trace(trace, 'step', {
|
||||
name: 'click',
|
||||
label: tournament.title || 'Turnier',
|
||||
selector: `a[href="${tournamentHref}"]`
|
||||
});
|
||||
await contentRoot.locator(`a[href="${tournamentHref}"]`).first().click();
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
}
|
||||
|
||||
const href = await page.locator('#content-row1 a, #content a, #container a').evaluateAll((anchors, criteria) => {
|
||||
const href = await page.locator('#content-row1 tr, #content tr, #container tr').evaluateAll((rows, criteria) => {
|
||||
const normalize = (value) => String(value || '')
|
||||
.normalize('NFKC')
|
||||
.replace(/\s+/g, ' ')
|
||||
@@ -339,19 +277,26 @@ class ClickTtTournamentRegistrationService {
|
||||
let bestHref = null;
|
||||
let bestScore = -1;
|
||||
|
||||
for (const anchor of anchors) {
|
||||
for (const row of rows) {
|
||||
const rowText = normalize(row.textContent || '');
|
||||
if (!rowText.includes(wantedCompetition)) continue;
|
||||
if (wantedTournament && !rowText.includes(wantedTournament)) continue;
|
||||
|
||||
const anchor = Array.from(row.querySelectorAll('a[href]')).find((candidate) =>
|
||||
/anmeldung|anmelden|melden/i.test(normalize(candidate.textContent || ''))
|
||||
);
|
||||
if (!anchor) continue;
|
||||
const href = anchor.getAttribute('href');
|
||||
if (!href) continue;
|
||||
if (/dataProtection|legalNotice|logout|contact/i.test(href)) continue;
|
||||
const text = normalize(anchor.textContent || '');
|
||||
if (!text.includes(wantedCompetition)) continue;
|
||||
|
||||
const contextText = normalize(anchor.closest('tr, li, div, td')?.textContent || '');
|
||||
const combinedText = `${text} ${contextText}`.trim();
|
||||
const linkText = normalize(anchor.textContent || '');
|
||||
const combinedText = `${rowText} ${linkText}`.trim();
|
||||
const combinedTokens = new Set(tokenize(combinedText));
|
||||
|
||||
let score = 0;
|
||||
if (wantedTournament && combinedText.includes(wantedTournament)) score += 100;
|
||||
if (/anmeldung|anmelden|melden/.test(linkText)) score += 20;
|
||||
|
||||
for (const token of wantedTournamentTokens) {
|
||||
if (combinedTokens.has(token)) score += 3;
|
||||
|
||||
Reference in New Issue
Block a user