diff --git a/btc-UI/src/app/components/navbar/navbar.component.html b/btc-UI/src/app/components/navbar/navbar.component.html
index 0503fb2..46e392f 100755
--- a/btc-UI/src/app/components/navbar/navbar.component.html
+++ b/btc-UI/src/app/components/navbar/navbar.component.html
@@ -42,7 +42,7 @@
class="nav-dropdown w-50 text-start ps-3"
(click)="openRaceModal()"
>
- Race No. | {{ selectedRace }}
+ Race No. | {{ currentLegRaceDisplay ? currentLegRaceDisplay : 'Race ' + selectedRace }}
@@ -95,7 +95,7 @@
class="nav-dropdown w-100 text-end pe-3"
(click)="openRaceModal()"
>
- Race No. | {{ selectedRace }}
+ Race No. | {{ currentLegRaceDisplay ? currentLegRaceDisplay : 'Race ' + selectedRace }}
@@ -211,7 +211,6 @@
@@ -220,40 +219,26 @@
Select Venue
-
0"
- (click)="selectVenue(0)"
->
- {{ raceCardData?.Venue }}
-
-
+ class="modal-option"
+ *ngIf="raceCardData?.raceVenueRaces?.races?.length > 0"
+ (click)="selectVenue(0)"
+ >
+ {{ raceCardData?.Venue }}
+
-
-
-
Select Race
- Race {{ i + 1 }}
+ class="modal-option"
+ *ngFor="let races of raceCardData.raceVenueRaces.races; let i = index"
+ (click)="selectRace(i + 1)"
+ >
+ Race {{ i + 1 }}
+
-
-
-
-
-
+
\ No newline at end of file
diff --git a/btc-UI/src/app/components/navbar/navbar.component.ts b/btc-UI/src/app/components/navbar/navbar.component.ts
index 1c6c68e..a5e38fe 100755
--- a/btc-UI/src/app/components/navbar/navbar.component.ts
+++ b/btc-UI/src/app/components/navbar/navbar.component.ts
@@ -24,7 +24,7 @@ export class NavbarComponent implements OnInit, OnDestroy {
showRaceModal = false;
selectedVenue = 'Select Venue';
selectedRace: number = 1;
- currentLegRaceDisplay: string = ''; // Display current leg's race
+ currentLegRaceDisplay: string = ''; // Display current leg's race or pool start
showWalletModal = false;
showResultModal = false;
@@ -38,6 +38,7 @@ export class NavbarComponent implements OnInit, OnDestroy {
selectedRaceId: number = 0;
enabledHorseNumbers: number[] = [];
multiLegBaseRaceIdx: number = 0; // Track base race index for multi-leg pools
+ currentPool: string | null = null; // Track current multi-leg pool
wallet = {
withdraw: 0,
@@ -104,12 +105,97 @@ export class NavbarComponent implements OnInit, OnDestroy {
this.sharedStateService.sharedData$.subscribe(data => {
if (data.type === 'currentLegRace') {
this.selectedRace = data.value;
- this.currentLegRaceDisplay = `Race ${data.value}`;
+ if (this.currentPool) {
+ const leg = this.getLegIndexForRace(this.currentPool, data.value);
+ this.currentLegRaceDisplay = `Leg ${leg + 1} (Race ${data.value}) for ${this.currentPool}`;
+ this.updateEnabledHorseNumbersForMultiLeg(this.multiLegBaseRaceIdx);
+ } else {
+ this.currentLegRaceDisplay = '';
+ this.updateEnabledHorseNumbers();
+ }
+ }
+ if (data.type === 'multiLegPoolStart') {
+ const { label, baseRaceIdx } = data.value;
+ this.currentPool = label;
+ this.multiLegBaseRaceIdx = baseRaceIdx;
+ this.currentLegRaceDisplay = `Starting at Race ${baseRaceIdx} for ${label}`;
+ this.updateEnabledHorseNumbersForMultiLeg(baseRaceIdx);
+ console.log(`[Multi-leg Pool] Selected: ${label}, Base Race: ${baseRaceIdx}`);
+ }
+ if (data.type === 'multiLegPoolEnd') {
+ this.currentPool = null;
+ this.multiLegBaseRaceIdx = 0;
+ this.currentLegRaceDisplay = '';
+ this.updateEnabledHorseNumbers();
+ }
+ if (data.type === 'selectedRace') {
+ this.currentPool = null;
+ this.multiLegBaseRaceIdx = 0;
+ this.currentLegRaceDisplay = '';
+ this.selectedRace = data.value;
this.updateEnabledHorseNumbers();
}
});
}
+ private getLegIndexForRace(poolName: string, race: number): number {
+ const raceMap: { [key: string]: number[] } = {
+ 'mjp1': [1, 2, 3, 4],
+ 'jkp1': [3, 4, 5, 6, 7],
+ 'trb1': [2, 3, 4],
+ 'trb2': [5, 6, 7]
+ };
+ return raceMap[poolName]?.indexOf(race) ?? 0;
+ }
+
+ private updateEnabledHorseNumbersForMultiLeg(baseRaceIdx: number) {
+ const raceCardData = this.raceCardData?.raceVenueRaces?.races || [];
+ let combinedHorseNumbers: number[] = [];
+ const legCount = this.getLegCountForLabel();
+
+ for (let i = 0; i < legCount; i++) {
+ const raceIdx = this.getRaceForLeg(this.currentPool || '', i) - 1;
+ const race = raceCardData[raceIdx] || [];
+ if (Array.isArray(race)) {
+ const horses = race
+ .map((runner: any) => runner?.horseNumber)
+ .filter((n: number) => typeof n === 'number' && n >= 1 && n <= 30);
+ combinedHorseNumbers = combinedHorseNumbers.concat(horses);
+ }
+ }
+
+ combinedHorseNumbers = Array.from(new Set(combinedHorseNumbers));
+ this.enabledHorseNumbers = combinedHorseNumbers;
+
+ this.sharedStateService.updateSharedData({
+ type: 'enabledHorseNumbers',
+ value: this.enabledHorseNumbers,
+ });
+
+ console.log('[Multi-leg Pool] Updated enabled horse numbers:', this.enabledHorseNumbers);
+ }
+
+ private getLegCountForLabel(): number {
+ if (!this.currentPool) return 3;
+ switch (this.currentPool) {
+ case 'mjp1': return 4;
+ case 'jkp1': return 5;
+ case 'trb1':
+ case 'trb2': return 3;
+ default: return 3;
+ }
+ }
+
+ private getRaceForLeg(poolName: string, leg: number): number {
+ const raceMap: { [key: string]: number[] } = {
+ 'mjp1': [1, 2, 3, 4],
+ 'jkp1': [3, 4, 5, 6, 7],
+ 'trb1': [2, 3, 4],
+ 'trb2': [5, 6, 7]
+ };
+ return raceMap[poolName]?.[leg] || (this.multiLegBaseRaceIdx + leg);
+ }
+
updateDateTime() {
const now = new Date();
this.dateTime = now.toLocaleString();
@@ -139,6 +225,8 @@ export class NavbarComponent implements OnInit, OnDestroy {
const venueIndex = Object.keys(this.raceCardData?.raceVenueRaces?.races || [])
.findIndex((_, idx) => idx === this.selectedRaceId);
+
+
if (venueIndex !== -1) {
this.raceData = this.raceCardData.raceVenueRaces.races[venueIndex] || [];
}
@@ -172,7 +260,9 @@ export class NavbarComponent implements OnInit, OnDestroy {
selectRace(race: number) {
this.selectedRace = race;
- this.multiLegBaseRaceIdx = race;
+ this.currentPool = null;
+ this.multiLegBaseRaceIdx = 0;
+ this.currentLegRaceDisplay = '';
this.sharedStateService.updateSharedData({
type: 'selectedRace',
@@ -268,4 +358,4 @@ export class NavbarComponent implements OnInit, OnDestroy {
this.subscription.unsubscribe();
}
}
-}
+}
\ No newline at end of file
diff --git a/btc-UI/src/app/components/touch-pad-menu/touch-pad-menu.component.ts b/btc-UI/src/app/components/touch-pad-menu/touch-pad-menu.component.ts
index 83a8fc8..fbd4513 100755
--- a/btc-UI/src/app/components/touch-pad-menu/touch-pad-menu.component.ts
+++ b/btc-UI/src/app/components/touch-pad-menu/touch-pad-menu.component.ts
@@ -57,6 +57,7 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
multiLegGroups: (number | string)[][] = [[], [], [], [], []];
multiLegBaseRaceIdx: number = 0; // Track starting race index
currentLegRaceDisplay: string = ''; // Display current leg's race
+ currentPool: string | null = null; // Track current pool (mjp1, jkp1, trb1, trb2)
isBoxed: boolean = false;
@@ -87,7 +88,7 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
this.runnerCount = count || 12;
this.numbers = Array.from({ length: 30 }, (_, i) => i + 1);
this.numbersFlat = this.numberRows.flat();
- this.updateLegRaceDisplay(this.selectedLabel || '');
+ this.updateLegRaceDisplay(this.currentPool || '');
});
this.labelRowsFlat = this.labelRows.flat();
@@ -96,8 +97,8 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
this.maxRowsReached = selections.length >= 5;
const totalAmount = selections.reduce((sum, selection) => sum + selection.total, 0);
this.totalAmountLimitReached = totalAmount >= 5000;
- if (this.totalAmountLimitReached) {
- this.showLimitPopup = true;
+ if (!this.totalAmountLimitReached) {
+ this.showLimitPopup = false;
}
});
this.currentRowSubscription = this.selectionService.currentRow$.subscribe(row => {
@@ -139,8 +140,8 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
}
return this.tanGroupStage >= 2 || this.tanGroups[this.tanGroupStage].length === 0;
} else if (this.multiLegLabels.includes(this.selectedLabel || '')) {
- const maxLegs = this.getMaxLegs(this.selectedLabel || '');
- return this.multiLegStage >= maxLegs - 1 || this.multiLegGroups[this.multiLegStage].length === 0;
+ const maxLegs = this.getMaxLegs(this.currentPool || '');
+ return this.multiLegStage >= maxLegs || this.multiLegGroups[this.multiLegStage].length === 0;
} else if (this.twoGroupLabels.includes(this.selectedLabel || '')) {
return this.isFirstGroupComplete || this.firstGroup.length === 0;
}
@@ -206,10 +207,25 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
this.canPrint = false;
this.isBoxed = false;
- // Store base race index for multi-leg pools
+ // Store base race index and pool name for multi-leg pools
if (this.multiLegLabels.includes(label)) {
- this.multiLegBaseRaceIdx = this.sharedStateService.getSelectedRace();
- this.updateLegRaceDisplay(label);
+ const poolName = label === 'MJP' ? 'mjp1' : label === 'JKP' ? 'jkp1' : label === 'TRE' ? 'trb1' : label;
+ this.currentPool = poolName;
+ this.multiLegBaseRaceIdx = this.getBaseRaceIndexForPool(poolName);
+ // Broadcast race and pool info for navbar
+ this.sharedStateService.updateSharedData({
+ type: 'multiLegPoolStart',
+ value: { label: poolName, baseRaceIdx: this.multiLegBaseRaceIdx }
+ });
+ this.updateLegRaceDisplay(poolName);
+ } else {
+ this.currentPool = null;
+ this.multiLegBaseRaceIdx = 0;
+ this.currentLegRaceDisplay = '';
+ this.sharedStateService.updateSharedData({
+ type: 'multiLegPoolEnd',
+ value: null
+ });
}
// Reset TAN
@@ -228,6 +244,34 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
this.selectionService.updatePartial({ label });
}
+ private getBaseRaceIndexForPool(poolName: string): number {
+ const raceCardData = JSON.parse(localStorage.getItem('raceCardData') || '{}');
+ const totalRaces = raceCardData?.raceVenueRaces?.races?.length || 10;
+ const maxLegs = this.getMaxLegs(poolName);
+
+ // Try to get pool-to-race mapping from raceCardData
+ const poolRaces = raceCardData?.raceVenueRaces?.pools?.[poolName] || [];
+ let baseRaceIdx = poolRaces.length > 0 ? poolRaces[0] : this.getDefaultBaseRace(poolName);
+
+ // Ensure enough races remain for the pool
+ if (baseRaceIdx + maxLegs - 1 > totalRaces) {
+ baseRaceIdx = Math.max(1, totalRaces - maxLegs + 1);
+ }
+
+ return baseRaceIdx;
+ }
+
+ private getDefaultBaseRace(poolName: string): number {
+ // Fallback to hardcoded values if raceCardData.pools is unavailable
+ const poolRaceMap: { [key: string]: number } = {
+ 'mjp1': 1,
+ 'jkp1': 3,
+ 'trb1': 2,
+ 'trb2': 5
+ };
+ return poolRaceMap[poolName] || this.sharedStateService.getSelectedRace();
+ }
+
selectNumber(number: number) {
if (!this.selectedLabel || this.totalAmountLimitReached || number > this.runnerCount) return;
@@ -310,7 +354,11 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
}
this.selectedNumbers = combined;
this.selectionService.updatePartial({ numbers: [...this.selectedNumbers] });
- this.updateLegRaceDisplay(this.selectedLabel || '');
+ this.updateLegRaceDisplay(this.currentPool || '');
+ }
+
+ private calculateMultiLegAmount(poolType: 'TRE' | 'MJP' | 'JKP', horsesPerLeg: number[], units: number, unitBet: number = 10): number {
+ return horsesPerLeg.reduce((acc, v) => acc * v, 1) * units * unitBet;
}
onPadEnter() {
@@ -325,7 +373,7 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
}
if (this.selectedLabel === 'TAN') {
- if (this.tanGroupStage < 2) {
+ if (this.tanGroupStage < 2 && this.tanGroups[this.tanGroupStage].length > 0) {
this.tanGroupStage++;
const combined: (number | string)[] = [...this.tanGroups[0]];
if (this.tanGroupStage > 0) combined.push('-', ...this.tanGroups[1]);
@@ -337,11 +385,11 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
}
if (this.multiLegLabels.includes(this.selectedLabel || '')) {
- const maxLegs = this.getMaxLegs(this.selectedLabel || '');
- if (this.multiLegStage < maxLegs - 1) {
+ const maxLegs = this.getMaxLegs(this.currentPool || '');
+ if (this.multiLegStage < maxLegs - 1 && this.multiLegGroups[this.multiLegStage].length > 0) {
this.multiLegStage++;
this.updateMultiLegSelection();
- this.updateLegRaceDisplay(this.selectedLabel || '');
+ this.updateLegRaceDisplay(this.currentPool || '');
}
return;
}
@@ -380,13 +428,45 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
updateCanPrint() {
this.canPrint = this.padValue.trim().length > 0 && /^[0-9]+$/.test(this.padValue);
+ if (this.multiLegLabels.includes(this.selectedLabel || '')) {
+ const maxLegs = this.getMaxLegs(this.currentPool || '');
+ this.canPrint = this.canPrint && this.multiLegStage === maxLegs - 1 && this.multiLegGroups[this.multiLegStage].length > 0;
+ }
}
print() {
const selectionsTotal = this.currentSelections.reduce((sum, sel) => sum + sel.total, 0);
- if (selectionsTotal + this.currentTotal > 5000) {
- this.showLimitPopup = true;
- return;
+ let currentRowAmount = 0;
+ if (this.multiLegLabels.includes(this.selectedLabel || '')) {
+ const maxLegs = this.getMaxLegs(this.currentPool || '');
+ const horsesPerLeg = this.multiLegGroups.map((group, index) => {
+ if (group.includes('F')) {
+ return this.getRunnerCountForLeg(this.multiLegBaseRaceIdx, index);
+ }
+ return group.length;
+ }).slice(0, maxLegs);
+ const units = parseFloat(this.padValue) || 0;
+ currentRowAmount = this.calculateMultiLegAmount(
+ this.selectedLabel as 'TRE' | 'MJP' | 'JKP',
+ horsesPerLeg,
+ units
+ );
+ if (currentRowAmount > 5000 || selectionsTotal + currentRowAmount > 5000) {
+ this.totalAmountLimitReached = true;
+ this.showLimitPopup = true;
+ return;
+ }
+ // Ensure all legs have selections
+ if (horsesPerLeg.some(count => count === 0)) {
+ return;
+ }
+ } else {
+ currentRowAmount = this.currentTotal;
+ if (selectionsTotal + currentRowAmount > 5000) {
+ this.totalAmountLimitReached = true;
+ this.showLimitPopup = true;
+ return;
+ }
}
this.selectionService.finalizeCurrentRow();
this.resetSelections();
@@ -403,6 +483,8 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
this.padValue = '';
this.canPrint = false;
this.isBoxed = false;
+ this.totalAmountLimitReached = false;
+ this.showLimitPopup = false;
this.tanGroupStage = 0;
this.tanGroups = [[], [], []];
@@ -413,10 +495,17 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
this.multiLegGroups = [[], [], [], [], []];
this.multiLegBaseRaceIdx = 0;
this.currentLegRaceDisplay = '';
+ this.currentPool = null;
this.fieldModalOpen = false;
this.fieldInput = '';
this.fieldFEntered = false;
+
+ // Clear multi-leg display in Navbar
+ this.sharedStateService.updateSharedData({
+ type: 'multiLegPoolEnd',
+ value: null
+ });
}
toggleBoxMode() {
@@ -512,21 +601,44 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
this.selectionService.updatePartial({ numbers: [...this.selectedNumbers] });
}
- private getMaxLegs(label: string): number {
- switch (label) {
- case 'TRE': return 3;
- case 'MJP': return 4;
- case 'JKP': return 5;
- default: return 3;
+ private getMaxLegs(poolName: string): number {
+ switch (poolName) {
+ case 'mjp1':
+ return 4;
+ case 'jkp1':
+ return 5;
+ case 'trb1':
+ case 'trb2':
+ case 'TRE':
+ return 3;
+ default:
+ return 5; // Default to 5 for unspecified pools
}
}
- private updateLegRaceDisplay(label: string) {
- if (!this.multiLegLabels.includes(label)) {
+ private getRaceForLeg(poolName: string, leg: number): number {
+ const raceCardData = JSON.parse(localStorage.getItem('raceCardData') || '{}');
+ const poolRaces = raceCardData?.raceVenueRaces?.pools?.[poolName] || [];
+ if (poolRaces.length > leg) {
+ return poolRaces[leg];
+ }
+ // Fallback to default race mapping
+ const raceMap: { [key: string]: number[] } = {
+ 'mjp1': [1, 2, 3, 4],
+ 'jkp1': [3, 4, 5, 6, 7],
+ 'trb1': [2, 3, 4],
+ 'trb2': [5, 6, 7]
+ };
+ return raceMap[poolName]?.[leg] || (this.multiLegBaseRaceIdx + leg);
+ }
+
+ private updateLegRaceDisplay(poolName: string) {
+ if (!['mjp1', 'jkp1', 'trb1', 'trb2'].includes(poolName)) {
this.currentLegRaceDisplay = '';
+ this.currentPool = null;
return;
}
- const raceIdx = this.multiLegBaseRaceIdx + this.multiLegStage;
+ const raceIdx = this.getRaceForLeg(poolName, this.multiLegStage);
this.currentLegRaceDisplay = `Leg ${this.multiLegStage + 1} (Race ${raceIdx})`;
const runnerCount = this.getRunnerCountForLeg(this.multiLegBaseRaceIdx, this.multiLegStage);
this.sharedStateService.setRunnerCount(runnerCount);
@@ -538,7 +650,7 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
private getRunnerCountForLeg(baseIdx: number, leg: number): number {
const raceCardData = JSON.parse(localStorage.getItem('raceCardData') || '{}');
- const raceIdx = baseIdx - 1 + leg; // 0-based index
+ const raceIdx = this.getRaceForLeg(this.currentPool || '', leg) - 1;
const race = raceCardData?.raceVenueRaces?.races?.[raceIdx] || [];
return Array.isArray(race) ? race.length : 12;
}
@@ -729,10 +841,10 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
treButtonClick(btnNum: number) {
this.trePopupVisible = false;
- this._selectTreAfterPopup();
+ this._selectTreAfterPopup(btnNum);
}
- private _selectTreAfterPopup() {
+ private _selectTreAfterPopup(btnNum: number) {
this.selectedLabel = 'TRE';
this.selectedNumbers = [];
this.padValue = '';
@@ -746,9 +858,24 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
this.secondGroup = [];
this.multiLegStage = 0;
this.multiLegGroups = [[], [], [], [], []];
- this.multiLegBaseRaceIdx = this.sharedStateService.getSelectedRace();
- this.updateLegRaceDisplay('TRE');
+ // Map TRE button to specific pool name and base race dynamically
+ const raceCardData = JSON.parse(localStorage.getItem('raceCardData') || '{}');
+ const trePoolMap: { [key: number]: { name: string } } = {
+ 1: { name: 'trb1' },
+ 2: { name: 'trb2' }
+ };
+ const poolInfo = trePoolMap[btnNum] || { name: 'trb1' };
+ this.currentPool = poolInfo.name;
+ this.multiLegBaseRaceIdx = this.getBaseRaceIndexForPool(poolInfo.name);
+
+ // Broadcast TRE selection
+ this.sharedStateService.updateSharedData({
+ type: 'multiLegPoolStart',
+ value: { label: poolInfo.name, baseRaceIdx: this.multiLegBaseRaceIdx }
+ });
+
+ this.updateLegRaceDisplay(poolInfo.name);
this.selectionService.updatePartial({ label: 'TRE' });
}