import { Component, inject, OnInit, signal } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators, } from '@angular/forms'; import { DiceService } from './dice.service'; import { DiceDto, DiceResult } from './dice.model'; import { tap } from 'rxjs/operators'; import { UserService } from '@service/user.service'; type DiceFormGroup = FormGroup<{ betAmount: FormControl; rollOver: FormControl; targetValue: FormControl; }>; @Component({ selector: 'app-dice', standalone: true, imports: [CommonModule, ReactiveFormsModule], templateUrl: './dice.component.html', }) export class DiceComponent implements OnInit { private readonly formBuilder = inject(FormBuilder); private readonly diceService = inject(DiceService); private readonly userService = inject(UserService); rolledValue = signal(null); win = signal(null); payout = signal(null); winChance = signal(0); potentialWin = signal(0); readonly diceForm: DiceFormGroup = this.createDiceForm(); private readonly MAX_DICE_VALUE = 100; ngOnInit(): void { this.diceForm.valueChanges .pipe(tap(() => this.calculateWinChanceAndPotentialWin())) .subscribe(); this.calculateWinChanceAndPotentialWin(); } createDiceForm(): DiceFormGroup { return this.formBuilder.group({ betAmount: new FormControl(1.0, { validators: [Validators.required, Validators.min(0.01)], nonNullable: true, }), rollOver: new FormControl(true, { validators: [Validators.required], nonNullable: true, }), targetValue: new FormControl(50.5, { validators: [Validators.required, Validators.min(1), Validators.max(100)], nonNullable: true, }), }); } toggleRollMode(): void { const currentMode = this.diceForm.get('rollOver')?.value; this.diceForm.get('rollOver')?.setValue(!currentMode); } calculateWinChanceAndPotentialWin(): void { const formValues = this.diceForm.value; const target = formValues.targetValue ?? 0; const bet = formValues.betAmount ?? 0; const isOver = formValues.rollOver ?? true; const calculatedWinChance = isOver ? this.MAX_DICE_VALUE - target : target - 1; this.winChance.set(Math.max(0, calculatedWinChance)); let multiplier = 0; if (calculatedWinChance > 0) { multiplier = (this.MAX_DICE_VALUE - 1) / calculatedWinChance; } this.potentialWin.set(bet * multiplier); } roll(): void { if (this.diceForm.invalid) { this.diceForm.markAllAsTouched(); return; } const diceDto: DiceDto = this.diceForm.getRawValue() as DiceDto; this.rolledValue.set(null); this.win.set(null); this.payout.set(null); this.diceService.rollDice(diceDto).subscribe({ next: (result: DiceResult) => { this.rolledValue.set(result.rolledValue); this.win.set(result.win); this.payout.set(result.payout); this.userService.refreshCurrentUser(); }, error: (error) => { console.error('Dice roll failed:', error); }, }); } hasError(controlName: string, errorName: string): boolean { const control = this.diceForm.get(controlName); return control !== null && control.touched && control.hasError(errorName); } }