feat : race number changes automatically according to the stopbet✅
This commit is contained in:
parent
ff263099c7
commit
3486b342d7
@ -22,10 +22,9 @@ export class NavbarComponent implements OnInit, OnDestroy {
|
||||
btid: string | null = null;
|
||||
|
||||
// component properties - add these at top-level in the component class
|
||||
consecTimeouts = 0;
|
||||
maxConsecTimeouts = 2;
|
||||
liveStatusOk = true;
|
||||
|
||||
consecTimeouts = 0;
|
||||
maxConsecTimeouts = 2;
|
||||
liveStatusOk = true;
|
||||
|
||||
showVenueModal = false;
|
||||
showRaceModal = false;
|
||||
@ -77,6 +76,12 @@ liveStatusOk = true;
|
||||
private http: HttpClient
|
||||
) {}
|
||||
|
||||
// Stopbet-related properties
|
||||
private stopbetStatuses: Map<number, string> = new Map(); // raceNum => 'Y'|'N'|'S'
|
||||
private currentVenue: string = '';
|
||||
private currentDate: string = '';
|
||||
private eventSource?: EventSource;
|
||||
|
||||
ngOnInit() {
|
||||
this.userName = localStorage.getItem('userName') || '';
|
||||
this.btid = localStorage.getItem('btid');
|
||||
@ -117,6 +122,16 @@ liveStatusOk = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Set current venue and date
|
||||
this.currentVenue = (this.raceCardData?.venue ?? '').toUpperCase();
|
||||
this.currentDate = this.getTodayDate();
|
||||
|
||||
// Setup stopbet if venue is available
|
||||
if (this.currentVenue) {
|
||||
this.fetchInitialStopbets();
|
||||
this.setupSSE();
|
||||
}
|
||||
|
||||
// Periodic ABS/latest polling
|
||||
this.subscription = interval(5000)
|
||||
.pipe(
|
||||
@ -185,6 +200,97 @@ liveStatusOk = true;
|
||||
});
|
||||
}
|
||||
|
||||
private getTodayDate(): string {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
return `${year}/${month}/${day}`;
|
||||
}
|
||||
|
||||
private fetchInitialStopbets() {
|
||||
this.http.get(`http://localhost:8080/stopbet/raw?venue=${this.currentVenue}&date=${this.currentDate}`).subscribe({
|
||||
next: (res: any) => {
|
||||
if (res.ok && res.data) {
|
||||
const key = `${this.currentVenue}:${this.currentDate}`;
|
||||
const meeting = res.data[key] || {};
|
||||
for (const race in meeting) {
|
||||
const raceNum = parseInt(race, 10);
|
||||
this.stopbetStatuses.set(raceNum, meeting[race]);
|
||||
}
|
||||
// Check and switch if current race is stopped
|
||||
this.checkAndSwitchIfStopped();
|
||||
}
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('[STOPBET] Failed to fetch initial statuses:', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private setupSSE() {
|
||||
if (this.eventSource) {
|
||||
this.eventSource.close();
|
||||
}
|
||||
this.eventSource = new EventSource('http://localhost:8080/stopbet/stream');
|
||||
this.eventSource.onmessage = (event) => {
|
||||
this.zone.run(() => {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data.type === 'stopbet' && data.venue === this.currentVenue && data.date === this.currentDate) {
|
||||
const raceNum = parseInt(data.race, 10);
|
||||
this.stopbetStatuses.set(raceNum, data.status);
|
||||
// If current selected race is affected and now stopped, switch
|
||||
if (this.selectedRace === raceNum && !this.isOpen(raceNum)) {
|
||||
this.checkAndSwitchIfStopped();
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[STOPBET] SSE parse error:', err);
|
||||
}
|
||||
});
|
||||
};
|
||||
this.eventSource.onerror = (err) => {
|
||||
console.error('[STOPBET] SSE error:', err);
|
||||
};
|
||||
}
|
||||
|
||||
private isOpen(race: number): boolean {
|
||||
const status = this.stopbetStatuses.get(race);
|
||||
return status === 'N' || status === undefined; // Assume open if unknown
|
||||
}
|
||||
|
||||
private getMaxRaces(): number {
|
||||
return this.raceCardData?.raceVenueRaces?.races?.length || 10;
|
||||
}
|
||||
|
||||
private getOpenRaceStartingFrom(start: number): number {
|
||||
const max = this.getMaxRaces();
|
||||
// Try from start to max
|
||||
for (let r = start; r <= max; r++) {
|
||||
if (this.isOpen(r)) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
// If none after, try from 1 to start-1
|
||||
for (let r = 1; r < start; r++) {
|
||||
if (this.isOpen(r)) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
// All stopped, return original start
|
||||
return start;
|
||||
}
|
||||
|
||||
private checkAndSwitchIfStopped() {
|
||||
if (!this.isOpen(this.selectedRace)) {
|
||||
const nextOpen = this.getOpenRaceStartingFrom(this.selectedRace + 1);
|
||||
if (nextOpen !== this.selectedRace) {
|
||||
this.selectRace(nextOpen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private getLegIndexForRace(poolName: string, race: number): number {
|
||||
const raceMap: { [key: string]: number[] } = {
|
||||
mjp1: [1, 2, 3, 4],
|
||||
@ -335,12 +441,26 @@ liveStatusOk = true;
|
||||
value: this.selectedVenue,
|
||||
});
|
||||
|
||||
// Update currentVenue if changed
|
||||
const newVenue = venue.toUpperCase();
|
||||
if (newVenue !== this.currentVenue) {
|
||||
this.currentVenue = newVenue;
|
||||
this.stopbetStatuses.clear();
|
||||
if (this.currentVenue) {
|
||||
this.fetchInitialStopbets();
|
||||
this.setupSSE();
|
||||
}
|
||||
}
|
||||
|
||||
// console.log('[VENUE] Venue resolved to (structured):', this.selectedVenue, '| index:', index);
|
||||
this.closeModals();
|
||||
}
|
||||
|
||||
selectRace(race: number) {
|
||||
this.selectedRace = race;
|
||||
// Adjust race if the attempted one is stopped
|
||||
const adjustedRace = this.isOpen(race) ? race : this.getOpenRaceStartingFrom(race);
|
||||
|
||||
this.selectedRace = adjustedRace;
|
||||
this.currentPool = null;
|
||||
this.multiLegBaseRaceIdx = 0;
|
||||
this.currentLegRaceDisplay = '';
|
||||
@ -352,7 +472,7 @@ liveStatusOk = true;
|
||||
|
||||
// Use this.raceCardData (structured) rather than re-parsing localStorage
|
||||
const raceList = this.raceCardData?.raceVenueRaces?.races ?? [];
|
||||
const selectedRaceEntry = raceList[race - 1] ?? [];
|
||||
const selectedRaceEntry = raceList[this.selectedRace - 1] ?? [];
|
||||
|
||||
// Determine runnerCount defensively based on possible shapes
|
||||
let runnerCount = 12;
|
||||
@ -554,6 +674,9 @@ liveStatusOk = true;
|
||||
if (this.subscription) {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
if (this.eventSource) {
|
||||
this.eventSource.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Add trackByHorse for use in *ngFor
|
||||
@ -561,4 +684,3 @@ liveStatusOk = true;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user