From 0779cb38ec58d027248cb0d15c5b2c629662120d Mon Sep 17 00:00:00 2001 From: karthik Date: Tue, 5 Aug 2025 13:50:30 +0530 Subject: [PATCH] fix : made group for labels --- .../middle-section.component.ts | 2 +- .../label-restriction.service.ts | 51 +++++++ .../touch-pad-menu.component.ts | 137 +++++++++--------- 3 files changed, 118 insertions(+), 72 deletions(-) create mode 100644 btc-UI/src/app/components/selection.service/label-restriction.service.ts diff --git a/btc-UI/src/app/components/middle-section/middle-section.component.ts b/btc-UI/src/app/components/middle-section/middle-section.component.ts index 9f768de..df8d8e0 100755 --- a/btc-UI/src/app/components/middle-section/middle-section.component.ts +++ b/btc-UI/src/app/components/middle-section/middle-section.component.ts @@ -60,4 +60,4 @@ export class MiddleSectionComponent implements OnInit, OnDestroy { this.sub1.unsubscribe(); this.sub2.unsubscribe(); } -} +} \ No newline at end of file diff --git a/btc-UI/src/app/components/selection.service/label-restriction.service.ts b/btc-UI/src/app/components/selection.service/label-restriction.service.ts new file mode 100644 index 0000000..3a6105d --- /dev/null +++ b/btc-UI/src/app/components/selection.service/label-restriction.service.ts @@ -0,0 +1,51 @@ +import { Injectable } from '@angular/core'; +import { SelectionData } from '../selection.service/selection.service'; + +// Define mutually exclusive label groups +export const LABEL_GROUPS: { [key: string]: string[] } = { + groupA: ['WIN', 'SHP', 'THP', 'PLC', 'SHW'], + groupB: ['FOR', 'QUI', 'TAN', 'EXA'], + groupWSP: ['WSP'], + groupTRE: ['TRE'], + groupMJP: ['MJP'], + groupJKP: ['JKP'], +}; + +// Reverse index to map labels to their groups +export const LABEL_TO_GROUP: { [label: string]: string } = {}; +Object.entries(LABEL_GROUPS).forEach(([group, labels]) => { + labels.forEach(label => (LABEL_TO_GROUP[label] = group)); +}); + +@Injectable({ providedIn: 'root' }) +export class LabelRestrictionService { + getBlockedLabels(selections: SelectionData[]): Set { + const selectedGroups = new Set(); + for (const row of selections) { + if (row.label && LABEL_TO_GROUP[row.label]) { + selectedGroups.add(LABEL_TO_GROUP[row.label]); + } + } + + const blockLabels = new Set(); + if (selectedGroups.size > 0) { + // Block all labels from groups not already selected + Object.entries(LABEL_GROUPS).forEach(([group, labels]) => { + if (!selectedGroups.has(group)) { + labels.forEach(label => blockLabels.add(label)); + } + }); + + // Special rule for WSP: if WSP is selected, only allow WIN, SHP, THP in the three rows + if (selectedGroups.has('groupWSP')) { + Object.keys(LABEL_TO_GROUP).forEach(label => { + if (!['WIN', 'SHP', 'THP'].includes(label)) { + blockLabels.add(label); + } + }); + } + } + + return blockLabels; + } +} \ 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 a931d29..42a62d1 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 @@ -1,10 +1,9 @@ import { Component, Input, OnInit, OnDestroy } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Subscription } from 'rxjs'; -import { SelectionService } from '../selection.service/selection.service'; -import { SelectionData } from '../selection.service/selection.service'; +import { SelectionService, SelectionData } from '../selection.service/selection.service'; import { SharedStateService } from '../../service/shared-state.service'; - +import { LabelRestrictionService } from '../selection.service/label-restriction.service'; @Component({ selector: 'app-touch-pad-menu', standalone: true, @@ -27,15 +26,12 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { ]; numbers: number[] = Array.from({ length: 30 }, (_, i) => i + 1); - runnerCount: number = 12; // Fallback + runnerCount: number = 12; labelRowsFlat: string[] = []; numbersFlat: number[] = []; - - // --- NEW PROPERTY --- - public actualRunners: Set = new Set(); - - wspTicketStage: number = 0; //added this - + blockedLabels = new Set(); + actualRunners: Set = new Set(); + wspTicketStage: number = 0; selectedLabel: string | null = null; selectedNumbers: (number | string)[] = []; padValue: string = ''; @@ -45,7 +41,6 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { maxRowsReached: boolean = false; totalAmountLimitReached: boolean = false; showLimitPopup: boolean = false; - disabledLabels: string[] = ['SHW', 'SJP', '.']; // TAN logic @@ -85,7 +80,8 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { constructor( private selectionService: SelectionService, - private sharedStateService: SharedStateService + private sharedStateService: SharedStateService, + private labelRestrictionService: LabelRestrictionService ) {} ngOnInit() { @@ -104,6 +100,7 @@ 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; + this.blockedLabels = this.labelRestrictionService.getBlockedLabels(selections); if (!this.totalAmountLimitReached) { this.showLimitPopup = false; } @@ -208,7 +205,9 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { } isLabelDisabled(label: string): boolean { - return this.disabledLabels.includes(label) || this.totalAmountLimitReached; + return this.disabledLabels.includes(label) || + this.totalAmountLimitReached || + this.blockedLabels.has(label); } // --- MODIFIED METHOD --- @@ -234,7 +233,7 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { } selectLabel(label: string) { - if (this.totalAmountLimitReached) { + if (this.totalAmountLimitReached || this.blockedLabels.has(label)) { this.showLimitPopup = true; return; } @@ -277,12 +276,10 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { if (label === 'WSP') { const wspLabels = ['WIN', 'SHP', 'THP']; - this.wspTicketStage = 0; // Add this line - // Finalize any existing row before creating new ones + this.wspTicketStage = 0; this.selectionService.finalizeCurrentRow(); - // Immediately add 3 blank rows to the selection list - const currentSelections = this.selectionService['selections'].value; + const currentSelections = this.selectionService.getSelections(); const blankRows = wspLabels.map(lbl => ({ label: lbl, numbers: [], @@ -294,7 +291,7 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { const totalNew = 0; // Each row is empty initially const totalExisting = currentSelections.reduce((sum, r) => sum + r.total, 0); if (totalExisting + totalNew <= 5000) { - this.selectionService['selections'].next([...currentSelections, ...blankRows]); + this.selectionService.setSelections([...currentSelections, ...blankRows]); } // Clear the input area (so no editing conflicts) @@ -584,30 +581,29 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy { this.padValue += key; } - this.updateCanPrint(); + this.updateCanPrint(); - const value = parseFloat(this.padValue) || 0; + const value = parseFloat(this.padValue) || 0; - if (this.selectedLabel === 'WSP') { - const labels = ['WIN', 'SHP', 'THP']; - const targetLabel = labels[this.wspTicketStage]; + if (this.selectedLabel === 'WSP') { + const labels = ['WIN', 'SHP', 'THP']; + const targetLabel = labels[this.wspTicketStage]; - const updatedSelections = this.selectionService.getSelections().map(sel => { - if (sel.label === targetLabel && JSON.stringify(sel.numbers) === JSON.stringify(this.selectedNumbers)) { - const total = value * (sel.numbers?.length || 0) * 10; - return { - ...sel, - value, - total - }; - } - return sel; - }); + const updatedSelections = this.selectionService.getSelections().map(sel => { + if (sel.label === targetLabel && JSON.stringify(sel.numbers) === JSON.stringify(this.selectedNumbers)) { + const total = value * (sel.numbers?.length || 0) * 10; + return { + ...sel, + value, + total + }; + } + return sel; + }); - this.selectionService.setSelections(updatedSelections); - - return; - } + this.selectionService.setSelections(updatedSelections); + return; + } // 🔵 Default path for non-WSP this.selectionService.updatePartial({ @@ -677,10 +673,10 @@ printTicket() { console.log("🖨️ Print ticket clicked"); - const selections = this.selectionService['selections'].value; - const currentRow = this.selectionService['currentRow'].value; + const selections = this.selectionService.getSelections(); + const currentRow = this.selectionService.getCurrentRow(); - let allRows = [...selections]; + let allRows = [...selections]; // ✅ Calculate total if currentRow is valid and not already finalized if (currentRow.label && currentRow.numbers.length > 0 && currentRow.value > 0) { @@ -696,38 +692,38 @@ printTicket() { combinations = n > 1 ? (n * (n - 1)) / 2 : 0; } - currentRow.total = combinations * currentRow.value * 10; + currentRow.total = combinations * currentRow.value * 10; + } + + allRows.push(currentRow); } - allRows.push(currentRow); - } + if (allRows.length === 0) { + console.warn("No valid rows to print."); + return; + } - if (allRows.length === 0) { - console.warn("No valid rows to print."); - return; - } + const ticketCount = allRows.reduce((sum, row) => sum + (row.value || 0), 0); + const totalAmount = allRows.reduce((sum, row) => sum + (row.total || 0), 0); - const ticketCount = allRows.reduce((sum, row) => sum + (row.value || 0), 0); - const totalAmount = allRows.reduce((sum, row) => sum + (row.total || 0), 0); + const now = new Date(); + const venue = 'MYS'; + const day = String(now.getDate()).padStart(2, '0'); + const month = String(now.getMonth() + 1).padStart(2, '0'); + const year = String(now.getFullYear()).slice(-2); + const fullYear = now.getFullYear(); + const timeStr = now.toTimeString().slice(0, 8).replace(/:/g, ''); + const millis = now.getMilliseconds().toString().padStart(3, '0'); + const ticketId = `${venue}/${fullYear}${month}${day}/1`; + const barcodeId = `1111${day}${month}${year}${timeStr}${millis}`; - const now = new Date(); - const venue = 'MYS'; - const day = String(now.getDate()).padStart(2, '0'); - const month = String(now.getMonth() + 1).padStart(2, '0'); - const year = String(now.getFullYear()).slice(-2); - const fullYear = now.getFullYear(); - const timeStr = now.toTimeString().slice(0, 8).replace(/:/g, ''); - const millis = now.getMilliseconds().toString().padStart(3, '0'); - const ticketId = `${venue}/${fullYear}${month}${day}/1`; - const barcodeId = `1111${day}${month}${year}${timeStr}${millis}`; - -const winLabels = allRows.map(row => { - const label = row.label.padEnd(10); // WIN (or SHP) - const numbers = row.numbers.join(',').padEnd(15); // 1,2,3 - const value = (`*${row.value || 0}`).padEnd(8); // *4 - const total = `Rs ${row.total || 0}`.padStart(8); // Rs 80 - return `${label}${numbers}${value}${total}`; -}).join('\n'); + const winLabels = allRows.map(row => { + const label = row.label.padEnd(10); + const numbers = row.numbers.join(',').padEnd(15); + const value = (`*${row.value || 0}`).padEnd(8); + const total = `Rs ${row.total || 0}`.padStart(8); + return `${label}${numbers}${value}${total}`; + }).join('\n'); // ✅ Print preview const printData = { @@ -808,7 +804,6 @@ const winLabels = allRows.map(row => { this.isBoxed = false; this.totalAmountLimitReached = false; this.showLimitPopup = false; - this.tanGroupStage = 0; this.tanGroups = [[], [], []]; this.isFirstGroupComplete = false; @@ -819,10 +814,10 @@ const winLabels = allRows.map(row => { this.multiLegBaseRaceIdx = 0; this.currentLegRaceDisplay = ''; this.currentPool = null; - this.fieldModalOpen = false; this.fieldInput = ''; this.fieldFEntered = false; + this.wspTicketStage = 0; // Clear multi-leg display in Navbar this.sharedStateService.updateSharedData({