> ## Documentation Index
> Fetch the complete documentation index at: https://hedgeem-api.qeetoto.com/llms.txt
> Use this file to discover all available pages before exploring further.

# F049 — Win Level System (Scaled Sound & Title)

> The win screen sound duration and title label scale with the win/total-bet multiplier — YOU WON for small wins, up to EPIC WIN for 250× and above

# F049 — Win Level System

| Field  | Value               |
| ------ | ------------------- |
| ID     | F049                |
| Phase  | 3 — UI              |
| Jira   | HEDGE-227           |
| Status | TS ✅ · JS ⬜ · UMA ✅ |

## Business Rule

When a player wins, the duration of the win-screen sound (`ramp_loop`) and the title label shown on the win panel are determined by the **win-to-total-bet multiplier**. Small wins play a short sound and show "YOU WON". Large wins play progressively longer sounds and escalate through "BIG WIN", "SUPER WIN", "GIGANTIC WIN", and "EPIC WIN".

The win label and sound duration are determined at river resolution and cannot be changed once set.

## Win Level Table

| Win / Total Bet | Sound duration | Label            |
| --------------- | -------------- | ---------------- |
| 0 – 1×          | 1 s            | YOU WON          |
| 1 – 3×          | 1 s            | YOU WON          |
| 3 – 5×          | 1.5 s          | YOU WON          |
| 5 – 7×          | 2 s            | YOU WON          |
| 7 – 12×         | 2.5 s          | YOU WON          |
| 12 – 20×        | 3 s            | YOU WON          |
| 20 – 50×        | **4 s**        | **BIG WIN**      |
| 50 – 100×       | **6 s**        | **SUPER WIN**    |
| 100 – 250×      | **8 s**        | **GIGANTIC WIN** |
| 250×+           | **10 s**       | **EPIC WIN**     |

Coin emission and auto-hide timer both scale to the same `collectTime` — the win screen stays visible for `soundMs + 3 000 ms` after the sound ends.

## V5 Source References

| File                                                                      | Lines                                   | Purpose                                                                                      |
| ------------------------------------------------------------------------- | --------------------------------------- | -------------------------------------------------------------------------------------------- |
| `source/client_source/src/js/GameConfig/fugaGaming/game/collectRule.json` | 1–42                                    | Win level table (identical in leander/ and gameIOM/)                                         |
| `source/client_source/src/js/Engine/modules/wins/totalWinManager.js`      | 245–266                                 | `getWinLevel()` — lookup by win/totalBet multiplier                                          |
| `source/client_source/src/js/Engine/modules/framework/UGame.js`           | 57–59                                   | `U.Game.getWinSummary()` — public wrapper                                                    |
| `source/client_source/src/js/Game/gameTypes/collectPlate.js`              | 1–11                                    | Uses `collectTime * 1000` as duration; level label via locale key                            |
| `source/client_source/src/js/Game/gameTypes/baseGameScene.js`             | 560–590                                 | `_collectWin()` starts `ramp_loop`; `_onWinCollectEnd()` stops it then plays `ramp_loop_end` |
| `source/client_source/src/locale/en_GB/locale.json`                       | `g_you_won`, `g_bigwin_header_level1–4` | Labels: Big Win / Super Win / Gigantic Win / Epic Win                                        |

## V6 Implementation

### Files

| File           | Location                                    | Purpose                                                       |
| -------------- | ------------------------------------------- | ------------------------------------------------------------- |
| `GameScene.ts` | `hedgeem-v6-client/src/scenes/GameScene.ts` | COLLECT\_RULES table, `_getWinLevel()`, `_showWinnerScreen()` |

### Key Locations in GameScene.ts

| Symbol                                             | \~Line | Description                                                                     |
| -------------------------------------------------- | ------ | ------------------------------------------------------------------------------- |
| `COLLECT_RULES` static array                       | \~1593 | 10-entry table mirroring `collectRule.json`                                     |
| `_getWinLevel(winPence, totalBetPence)`            | \~1609 | Iterates table top-down; returns matching rule + `levelIndex` (0–9)             |
| `_winLevelTimers` property                         | \~240  | `Phaser.Time.TimerEvent[]` — holds in-flight progressive label timers           |
| `_showWinnerScreen(winAmountPence, totalBetPence)` | \~1618 | Starts "YOU WON"; schedules `maxCollectLevel` label-step timers + bounce tweens |
| `_hideWinnerScreen()`                              | \~1672 | Destroys all `_winLevelTimers` on early dismiss                                 |
| `rampLoopSound` class property                     | \~239  | Stores `sound.add('ramp_loop')` ref so it can be `.stop()`-ped explicitly       |
| Call site                                          | \~942  | `_showWinnerScreen(snap.winAmount, snap.totalBet)`                              |

### Progressive Label Animation

Mirrors v5 `collectPlate._onShowEnd()` / `_updatePlate()` / `_bonuce()`. The win screen always opens with **"YOU WON"**, then escalates through the label tiers at evenly-spaced intervals.

**Formula** (matches v5 exactly):

```
maxCollectLevel = levelIndex - 5   (levels 0–5 stay "YOU WON", no timers)
delay(i) = (i + 1) × soundMs / (maxCollectLevel + 1)
```

**Label step-up sequence per level:**

| Win level                   | Labels in order                                             | Transition times                       |
| --------------------------- | ----------------------------------------------------------- | -------------------------------------- |
| YOU WON (levels 0–5)        | YOU WON only                                                | —                                      |
| BIG WIN (level 6, 4 s)      | YOU WON → **BIG WIN**                                       | 2 000 ms                               |
| SUPER WIN (level 7, 6 s)    | YOU WON → BIG WIN → **SUPER WIN**                           | 2 000 ms, 4 000 ms                     |
| GIGANTIC WIN (level 8, 8 s) | YOU WON → BIG WIN → SUPER WIN → **GIGANTIC WIN**            | 2 000 ms, 4 000 ms, 6 000 ms           |
| EPIC WIN (level 9, 10 s)    | YOU WON → BIG WIN → SUPER WIN → GIGANTIC WIN → **EPIC WIN** | 2 000 ms, 4 000 ms, 6 000 ms, 8 000 ms |

Each step-up fires a **bounce tween** on the label text: scale 1.0 → 1.3 → 1.0, 150 ms, `Back.easeOut` — mirrors v5 `_bonuce()`.

### Sound Fix (also in this commit)

Prior to this feature, `ramp_loop` was started via `this.sound.play()` which returns `boolean` and discards the sound reference. This meant `ramp_loop` kept playing after `ramp_loop_end` fired. Fixed by storing the reference via `this.sound.add('ramp_loop').play()` and calling `.stop()` in the delayed callback.

| Old behaviour                             | Fixed behaviour                                                               |
| ----------------------------------------- | ----------------------------------------------------------------------------- |
| `_sfx('ramp_loop')` — reference discarded | `this.rampLoopSound = this.sound.add('ramp_loop'); this.rampLoopSound.play()` |
| `ramp_loop` never stopped                 | `this.rampLoopSound?.stop()` called before `ramp_loop_end`                    |

### Timing (example: 25× win → BIG WIN)

| Time     | Event                                                          |
| -------- | -------------------------------------------------------------- |
| 0 ms     | `ramp_loop` starts, coin emitter starts, label = "YOU WON"     |
| 2 000 ms | Label → "BIG WIN" + bounce tween                               |
| 4 000 ms | `ramp_loop` stopped; `ramp_loop_end` plays; coin emitter stops |
| 7 000 ms | `_hideWinnerScreen()` — panel hidden                           |

## Acceptance Criteria

| ID         | Criterion                                                                                                                               |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| AC-F049-01 | A win of 5× total bet plays `ramp_loop` for 2 s and shows "YOU WON" throughout                                                          |
| AC-F049-02 | A win of 25× total bet plays `ramp_loop` for 4 s; starts "YOU WON", transitions to "BIG WIN" at 2 s                                     |
| AC-F049-03 | A win of 60× total bet plays `ramp_loop` for 6 s; YOU WON → BIG WIN at 2 s → SUPER WIN at 4 s                                           |
| AC-F049-04 | A win of 150× total bet plays `ramp_loop` for 8 s; YOU WON → BIG WIN at 2 s → SUPER WIN at 4 s → GIGANTIC WIN at 6 s                    |
| AC-F049-05 | A win of 300× total bet plays `ramp_loop` for 10 s; YOU WON → BIG WIN at 2 s → SUPER WIN at 4 s → GIGANTIC WIN at 6 s → EPIC WIN at 8 s |
| AC-F049-06 | Each label transition fires a bounce scale tween (1.0 → 1.3 → 1.0, 150 ms)                                                              |
| AC-F049-07 | `ramp_loop` always stops cleanly before `ramp_loop_end` plays                                                                           |
| AC-F049-08 | Auto-hide fires at `soundMs + 3 000 ms` after deal resolution                                                                           |
| AC-F049-09 | Dismissing the win screen early (next deal) cancels all pending label timers                                                            |

## Version Parity

| Version         | Status            | Notes                                                |
| --------------- | ----------------- | ---------------------------------------------------- |
| JS (v4)         | ⬜ Not yet audited | `ShowWinner()` pattern — likely fixed 2 s            |
| TypeScript (v6) | ✅ Implemented     | `COLLECT_RULES` table + `_getWinLevel()`, HEDGE-227  |
| UMA (v5)        | ✅ Implemented     | `collectRule.json` + `TotalWinManager.getWinLevel()` |
