fix : added print , WSP and MJP logic (working)

This commit is contained in:
Sibin Sabu 2025-08-04 12:35:43 +05:30
parent e358205163
commit a8a64e064e
3 changed files with 362 additions and 27 deletions

View File

@ -165,18 +165,20 @@ export class SelectionService {
const legCount = this.getLegCount(label);
const legs = this.splitToLegs(numbers, legCount);
// Override for MJP to always start from race 1
const baseIdx = label === 'MJP' ? 0 : this.multiLegBaseRaceIdx - 1;
const legCounts = legs.map((leg, idx) => {
let count = 0;
for (const item of leg) {
if (item === 'F') {
count += this.getRunnerCountForLeg(this.multiLegBaseRaceIdx, idx);
count += this.getRunnerCountForLeg(baseIdx + 1, idx);
} else if (typeof item === 'number') {
count += 1;
}
}
return count;
});
const combinations = legCounts.reduce((acc, count) => acc * (count || 1), 1);
updated.total = combinations * value * 10;
break;
@ -259,4 +261,48 @@ export class SelectionService {
const race = raceCardData?.raceVenueRaces?.races?.[raceIdx] || [];
return Array.isArray(race) ? race.length : 12;
}
private calculateTotal(data: SelectionData): number {
const temp = new BehaviorSubject<SelectionData>(data);
const originalCurrent = this.currentRow;
this.currentRow = temp;
this.updatePartial(data);
const total = temp.value.total;
this.currentRow = originalCurrent; // Restore original
return total;
}
//-----------------ADDED THIS---------------------------------------------------//
createVirtualRowsFromWSP(): SelectionData[] {
const base = this.currentRow.value;
if (!base.numbers.length || base.value <= 0) return [];
return ['WIN', 'SHP', 'THP'].map(label => {
const newRow: SelectionData = {
...base,
label,
total: 0
};
newRow.total = this.calculateTotal(newRow);
return newRow;
});
}
setSelections(rows: SelectionData[]) {
this.selections.next(rows);
}
getSelections(): SelectionData[] {
return this.selections.getValue();
}
getCurrentRow(): SelectionData {
return this.currentRow.value;
}
}

View File

@ -93,7 +93,7 @@
<button class="btn btn-secondary w-100 number-button" [disabled]="!numericPadEnabled" (click)="onPadEnter()">Enter</button>
</div>
<div class="col-6">
<button class="btn btn-secondary w-100 number-button" [disabled]="!canPrint" (click)="print()">Print</button>
<button class="btn btn-secondary w-100 number-button" [disabled]="!canPrint" (click)="printTicket()">Print</button>
</div>
</div>
</div>

View File

@ -31,6 +31,8 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
labelRowsFlat: string[] = [];
numbersFlat: number[] = [];
wspTicketStage: number = 0; //added this
selectedLabel: string | null = null;
selectedNumbers: (number | string)[] = [];
padValue: string = '';
@ -228,6 +230,39 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
});
}
//----------------------------------ADDED THIS -----------------------------------------------------
if (label === 'WSP') {
const wspLabels = ['WIN', 'SHP', 'THP'];
this.wspTicketStage = 0; // Add this line
// Finalize any existing row before creating new ones
this.selectionService.finalizeCurrentRow();
// Immediately add 3 blank rows to the selection list
const currentSelections = this.selectionService['selections'].value;
const blankRows = wspLabels.map(lbl => ({
label: lbl,
numbers: [],
value: 0,
total: 0,
isBoxed: false
}));
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]);
}
// Clear the input area (so no editing conflicts)
this.selectionService.updatePartial({ label: '', numbers: [], value: 0, total: 0 });
return; // Skip default updatePartial below
}
//----------------------------------ended here----------------------------------------------------
// Reset TAN
this.tanGroupStage = 0;
this.tanGroups = [[], [], []];
@ -339,12 +374,33 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
return;
}
// Default single-number selection
// Default single-number selection (WIN, SHP, THP, etc.)
if (!this.selectedNumbers.includes(number)) {
this.selectedNumbers.push(number);
this.selectionService.updatePartial({ numbers: [...this.selectedNumbers] });
// ✅ Special logic: If WSP, mirror number to WIN, SHP, and THP
if (this.selectedLabel === 'WSP') {
const labelsToUpdate = ['WIN', 'SHP', 'THP'];
const selections = this.selectionService.getSelections();
const updated = selections.map(sel => {
if (labelsToUpdate.includes(sel.label)) {
const newNumbers = [...sel.numbers];
if (!newNumbers.includes(number)) {
newNumbers.push(number);
}
return { ...sel, numbers: newNumbers };
}
return sel;
});
this.selectionService.setSelections(updated);
}
}
}
private updateMultiLegSelection() {
const combined: (number | string)[] = [];
@ -361,11 +417,54 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
return horsesPerLeg.reduce((acc, v) => acc * v, 1) * units * unitBet;
}
//-------------------------ON PAD ENTER------------------------------------//
// onPadEnter() {
// if (this.canPrint) {
// this.print();
// }
// }
onPadEnter() {
if (this.canPrint) {
if (!this.canPrint) {
this.print();
}
const value = parseFloat(this.padValue) || 0;
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)) {
return {
...sel,
value,
total: value * (sel.numbers?.length || 0) * 10
};
}
return sel;
});
this.selectionService.setSelections(updatedSelections);
// Move to next stage
this.wspTicketStage = (this.wspTicketStage + 1) % 3;
this.padValue = '';
this.updateCanPrint();
return;
}
// ✅ Default path: finalize row and reset input
this.print();
}
//--------------------------------------------------------------------------//
onShashEnter() {
if (this.selectedLabel === 'TAN' && this.isBoxed) {
@ -404,12 +503,46 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
}
}
//-----------------------------ENTER PAD VALUE-------------------------------------
// enterPadVal(key: string) {
// if (!this.numericPadEnabled || this.totalAmountLimitReached) return;
// if (key === 'X') {
// this.padValue = '';
// } else if (/[0-9]/.test(key)) {
// const currentValue = parseInt(this.padValue + key) || 0;
// if (currentValue > 100) return;
// this.padValue += key;
// }
// this.updateCanPrint();
// const value = parseFloat(this.padValue) || 0;
// this.selectionService.updatePartial({
// value,
// isBoxed: this.isBoxed,
// label: this.selectedLabel || '',
// numbers: [...this.selectedNumbers]
// });
// }
enterPadVal(key: string) {
if (!this.numericPadEnabled || this.totalAmountLimitReached) return;
if (key === 'X') {
this.padValue = '';
} else if (/[0-9]/.test(key)) {
if (this.selectedLabel === 'WSP') {
this.wspTicketStage = 0; // Reset stage if WSP
}
else if (/[0-9]/.test(key)) {
const currentValue = parseInt(this.padValue + key) || 0;
if (currentValue > 100) return;
this.padValue += key;
}
}
if (/[0-9]/.test(key)) {
const currentValue = parseInt(this.padValue + key) || 0;
if (currentValue > 100) return;
this.padValue += key;
@ -418,6 +551,29 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
this.updateCanPrint();
const value = parseFloat(this.padValue) || 0;
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;
});
this.selectionService.setSelections(updatedSelections);
return;
}
// 🔵 Default path for non-WSP
this.selectionService.updatePartial({
value,
isBoxed: this.isBoxed,
@ -425,6 +581,7 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
numbers: [...this.selectedNumbers]
});
}
//---------------------------------------------------------------------------------------------
updateCanPrint() {
this.canPrint = this.padValue.trim().length > 0 && /^[0-9]+$/.test(this.padValue);
@ -472,6 +629,138 @@ export class TouchPadMenuComponent implements OnInit, OnDestroy {
this.resetSelections();
}
//-------------------PRINT LOGIC----------------------------------------
printTicket() {
const selectionsTotal = this.currentSelections.reduce((sum, sel) => sum + sel.total, 0);
if (selectionsTotal + this.currentTotal > 5000) {
this.showLimitPopup = true;
return;
}
//--------------------Added Print here
console.log("🖨️ Print ticket clicked");
const selections = this.selectionService['selections'].value;
const currentRow = this.selectionService['currentRow'].value;
let allRows = [...selections];
// ✅ Calculate total if currentRow is valid and not already finalized
if (currentRow.label && currentRow.numbers.length > 0 && currentRow.value > 0) {
if (!currentRow.total) {
let combinations = 1;
if (['TAN', 'FOR', 'QUI'].includes(currentRow.label)) {
combinations = currentRow.numbers.length * (currentRow.numbers.length - 1);
} else if (['TRE', 'JKP', 'MJP'].includes(currentRow.label)) {
combinations = 1; // or your specific logic
} else if (currentRow.label === 'BOX') {
const n = currentRow.numbers.length;
combinations = n > 1 ? (n * (n - 1)) / 2 : 0;
}
currentRow.total = combinations * currentRow.value * 10;
}
allRows.push(currentRow);
}
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 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');
// ✅ Print preview
const printData = {
ticketId,
barcodeId,
venue,
date: `${day}-${month}-${fullYear}`,
winLabels,
ticketCount,
totalAmount,
gstNumber: '29ABCDE1234F2Z5'
};
// 🧾 Simulated console ticket
console.log('--- Simulated Ticket Print ---');
console.log(`Ticket ID : ${printData.ticketId}`);
console.log(`Barcode ID : ${printData.barcodeId}`);
console.log(`|||||| ||| | ||||| |||| |`); // Dummy barcode
console.log(`WIN Labels :`);
printData.winLabels.split('\n').forEach(row => console.log(row));
console.log(`*${printData.ticketCount}${printData.totalAmount}`);
console.log(`GST Number : ${printData.gstNumber}`);
console.log(`Date/Time : ${now.toLocaleString()}`);
console.log('-----------------------------');
// 🖨️ Send to printer API
const payload = {
type: 'ticket',
ticketId: printData.ticketId,
barcodeId: printData.barcodeId,
winLabels: printData.winLabels,
ticketCount: printData.ticketCount,
totalAmount: printData.totalAmount,
gstNumber: printData.gstNumber,
dateTime: now.toLocaleString()
};
fetch('http://localhost:9100/print', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
})
.then(response => {
if (!response.ok) {
throw new Error(`Printer error: ${response.status}`);
}
return response.text();
})
.then(result => {
console.log("✅ Print successful:", result);
})
.catch(error => {
console.error("❌ Print failed:", error);
});
//--------------------Ended Print here -----------------------------
this.selectionService.finalizeCurrentRow();
this.resetSelections();
}
//----------------------------------PRINT ENDS HERE ------------------------------------------------------
erase() {
this.selectionService.clearSelections();
this.resetSelections();