This commit is contained in:
2026-04-16 17:21:48 +03:00
parent c8fa4c442d
commit c8e7e4e927
116 changed files with 3720 additions and 4197 deletions
@@ -3,8 +3,8 @@
* Transforms raw API data into database-ready formats
*/
import { Injectable, Logger } from '@nestjs/common';
import * as cheerio from 'cheerio';
import { Injectable, Logger } from "@nestjs/common";
import * as cheerio from "cheerio";
import {
RawKeyEvent,
TransformedEvent,
@@ -18,7 +18,7 @@ import {
GameStatsResponse,
DbEventPayload,
DbMarketPayload,
} from './feeder.types';
} from "./feeder.types";
@Injectable()
export class FeederTransformerService {
@@ -28,7 +28,7 @@ export class FeederTransformerService {
// HELPER FUNCTIONS
// ============================================
private safeString(value: any): string | null {
return value === null || value === undefined || value === ''
return value === null || value === undefined || value === ""
? null
: String(value);
}
@@ -45,7 +45,7 @@ export class FeederTransformerService {
private extractPlayerIdFromUrl(url: string | undefined): string | null {
if (!url) return null;
const parts = url.split('/');
const parts = url.split("/");
return parts[parts.length - 1] || null;
}
@@ -59,7 +59,7 @@ export class FeederTransformerService {
matchId: string,
): TransformedEvent[] {
return rawEvents.map((e) => {
const playerId = this.extractPlayerIdFromUrl(e.playerUrl) || '';
const playerId = this.extractPlayerIdFromUrl(e.playerUrl) || "";
const assistPlayerId = e.assistPlayerUrl
? this.extractPlayerIdFromUrl(e.assistPlayerUrl)
: null;
@@ -68,16 +68,16 @@ export class FeederTransformerService {
: null;
// Determine event type
let eventType: 'goal' | 'card' | 'substitute' | 'other' = 'other';
if (e.type === 'goal') eventType = 'goal';
else if (e.type === 'card') eventType = 'card';
else if (e.type === 'substitute') eventType = 'substitute';
let eventType: "goal" | "card" | "substitute" | "other" = "other";
if (e.type === "goal") eventType = "goal";
else if (e.type === "card") eventType = "card";
else if (e.type === "substitute") eventType = "substitute";
return {
matchId,
playerId,
playerName: e.playerName,
teamId: e.position === 'home' ? homeTeamId : awayTeamId,
teamId: e.position === "home" ? homeTeamId : awayTeamId,
eventType,
eventSubtype: e.subType || null,
timeMinute: e.timeMin,
@@ -136,7 +136,7 @@ export class FeederTransformerService {
// GAME STATS TRANSFORMER
// ============================================
transformGameStats(
data: GameStatsResponse['data'] | null,
data: GameStatsResponse["data"] | null,
): TransformedMatchStats | null {
if (!data || !data.home) return null;
@@ -173,20 +173,20 @@ export class FeederTransformerService {
// MATCH STATE TO STATUS MAPPER
// ============================================
mapMatchStateToStatus(state: MatchState | undefined): string {
if (!state) return 'NS';
if (!state) return "NS";
switch (state) {
case 'postGame':
case 'post':
return 'FT';
case 'preGame':
case 'pre':
return 'NS';
case 'live':
case 'liveGame':
return 'LIVE';
case "postGame":
case "post":
return "FT";
case "preGame":
case "pre":
return "NS";
case "live":
case "liveGame":
return "LIVE";
default:
return 'NS';
return "NS";
}
}
@@ -200,28 +200,28 @@ export class FeederTransformerService {
const officials: MatchOfficial[] = [];
// Try standard officials component
$('.p0c-match-officials__official-list-item').each((_, elem) => {
$(".p0c-match-officials__official-list-item").each((_, elem) => {
const name = $(elem)
.find('.p0c-match-officials__official-name')
.find(".p0c-match-officials__official-name")
.text()
.trim();
const role = $(elem)
.find('.p0c-match-officials__official-group-title')
.find(".p0c-match-officials__official-group-title")
.text()
.trim();
if (name) {
officials.push({ name, role: role || 'Referee' });
officials.push({ name, role: role || "Referee" });
}
});
// Fallback: look for referee info in match info section
if (officials.length === 0) {
// Try alternative selectors
$('.widget-match-info__referee-name, .referee-name').each((_, elem) => {
$(".widget-match-info__referee-name, .referee-name").each((_, elem) => {
const name = $(elem).text().trim();
if (name) {
officials.push({ name, role: 'Referee' });
officials.push({ name, role: "Referee" });
}
});
}
@@ -331,8 +331,8 @@ export class FeederTransformerService {
(
e,
): e is TransformedEvent & {
eventType: 'goal' | 'card' | 'substitute';
} => e.eventType !== 'other' && !!e.playerId,
eventType: "goal" | "card" | "substitute";
} => e.eventType !== "other" && !!e.playerId,
)
.map((e) => ({
match_id: e.matchId,
@@ -354,6 +354,6 @@ export class FeederTransformerService {
// BASKETBALL PLAYER ID GENERATOR
// ============================================
generateBasketballPlayerId(teamId: string, playerName: string): string {
return `${teamId}-${playerName.replace(/[^a-zA-Z0-9]/g, '-').toLowerCase()}`;
return `${teamId}-${playerName.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase()}`;
}
}