EnakGame: pay EnakCoin to play, earn EnakCoin from the result, exchange into EnakPoint, and redeem EnakPoint for vouchers only. - enakgame-prd.md: economy and business rules, including entry cost and automatic refund, monthly global budget with a separate budget per event (event = campaign), and EnakPoint being voucher-only. - rfc-enakgame.md: built on the existing wallet, ledger and lots. Game sessions with a state machine, versioned reward configs, Economy Guard counters, vouchers with internal codes and external providers, and realized cost attributed to budgets by tracing the lots spent. - tasks-enakgame.md: EG-001 to EG-1003 in eleven phases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
39 KiB
EnakGame — Economy & Business Rules v1
| Item | Value |
|---|---|
| Status | Draft v1 |
| Purpose | Source of truth untuk perencanaan dan implementasi EnakGame menggunakan Claude Code |
| Backend | Go |
| Database | PostgreSQL |
| Game Client | Phaser |
| Frontend/Backoffice | Next.js |
| Cache/Temporary Session | Redis (opsional, sesuai kebutuhan implementasi) |
1. Product Overview
EnakGame adalah game portal dalam ekosistem Enaklo/F&B.
- User membayar Coin untuk memainkan mini-game (entry cost), dan dapat memperoleh Coin sebagai virtual reward dari hasil permainan.
- Coin dapat dikonversi/digunakan sebagai Point, kemudian Point hanya dapat ditukar ke voucher yang disediakan Enaklo.
- Point tidak dapat digunakan sebagai alat pembayaran dan tidak dapat diuangkan.
- EnakGame bukan platform gambling dan tidak menggunakan uang tunai sebagai hadiah dari game.
Core Flow
User
↓
Game Lobby
↓
Start Game
↓
Pay Entry Cost (Coin) + Create Game Session
↓
Play Game
↓
Submit Result
↓
Result Validation
↓
Reward Engine
↓
Economy Guard
↓
Coin Wallet + Ledger
↓
Coin → Point
↓
Voucher Redemption
↓
Realized Voucher Cost
↓
Budget Controller
2. Core Business Principles
2.1 Server Is Authoritative
Client/game (Phaser) tidak boleh menentukan reward final.
Client hanya mengirim hasil permainan yang diperlukan, misalnya:
session_idscoreoutcome- game-specific result data
Backend menghitung reward berdasarkan configuration yang aktif.
❌ Tidak boleh
Phaser:
score = 800
reward = 1000 Coin
→ backend menerima 1000 Coin
✅ Yang benar
Phaser:
score = 800
Backend:
score 800
→ load active reward configuration
→ calculate reward
→ validate limits
→ issue approved Coin
3. Currency Model
EnakGame memiliki dua konsep utama: Coin dan Point.
3.1 Coin
Coin adalah virtual game/reward currency.
Sumber utama:
- Game reward
- Event reward
- Mission reward
- Bonus/promo yang diizinkan
Penggunaan:
- Membayar entry cost untuk memainkan game (lihat Section 10.1)
- Dikonversi ke Point
Coin dapat memiliki expiration (lihat Section 4).
3.2 Point
Point adalah redemption currency.
Current business rule:
1 Coin = 1 Point = Rp1
Penggunaan Point dibatasi:
- Point hanya dapat ditukar ke voucher (lihat Section 26).
- Point tidak dapat digunakan sebagai alat pembayaran (misalnya membayar order).
- Point tidak dapat diuangkan (cash out).
Nilai Rp1 di atas adalah nilai acuan untuk perhitungan voucher dan budget, bukan nilai tukar ke uang tunai.
Konversi dan expiration mengikuti sistem existing (prd-point-coin.md), tidak didesain ulang:
- Coin → Point menggunakan fitur exchange existing (K3, F4): dilakukan manual oleh customer, satu arah, kurs di-configure di level organisasi (default 1 : 1).
- Point expiration menggunakan sistem expiration existing per lot (F12).
Catatan perubahan dari sistem existing: Berdasarkan keputusan sebelumnya (prd-point-coin.md), backend saat ini masih mengizinkan EnakPoint dipakai untuk membayar order (point payment, ledger
PAYMENT/PAYMENT_REFUND). Aturan EnakGame di atas menggantikan keputusan tersebut, sehingga fitur point payment perlu di-update/dinonaktifkan sebelum EnakGame berjalan. Belum ada order yang dibayar dengan Point, jadi tidak ada data lama yang perlu dimigrasi. Saldo Point user tetap sebagai Point; yang berubah hanya penggunaannya (redeem voucher saja).
Namun Coin dan Point tetap diperlakukan sebagai konsep/domain yang berbeda agar sistem tidak terlalu tightly coupled.
Tujuannya agar business rule di masa depan dapat berubah tanpa membongkar Game/Reward Engine.
4. Coin Expiration
Sistem Coin sudah memiliki konsep expiration. Expiration harus tetap menjadi bagian dari economy.
Coin yang expired:
Wallet usable balance
↓
berkurang
Ledger
↓
mencatat expiration transaction
Penting: Expiration tidak boleh dianggap sebagai voucher redemption.
Kategori transaksi harus dapat dibedakan:
Wallet usable balance
↓
berkurang
Ledger
↓
mencatat expiration transaction
Implementasi detail expiration mengikuti sistem existing dan tidak perlu didesain ulang kecuali diperlukan.
5. Budget Model
5.1 Budget Is Shared
Semua game menggunakan budget pool yang sama. Tidak ada kewajiban setiap game memiliki budget terpisah.
Contoh:
EnakGame Global Budget
Rp100.000.000
│
├── Runner
├── Spin
├── Memory
└── Puzzle
Semua reward normal game berasal dari economy/budget pool yang sama.
Pengecualian: Event/Campaign memiliki budget sendiri (lihat Section 7).
5.2 Budget Period
- Global budget menggunakan periode bulanan secara default.
- Periode budget dapat di-configure.
- Setiap Event/Campaign memiliki budget sendiri, terpisah dari global budget bulanan.
6. Budget vs Realized Cost
6.1 Budget Is Based on Actual Voucher Redemption
Budget Controller menggunakan voucher yang benar-benar diredeem sebagai dasar actual cost.
Coin yang baru diterbitkan bukan otomatis dianggap sebagai biaya voucher.
Contoh:
| Metric | Jumlah |
|---|---|
| Coin Generated | 20.000.000 |
| Coin Outstanding | 12.000.000 |
| Coin Expired | 3.000.000 |
| Coin Used/Converted | 5.000.000 |
Actual Voucher Cost = Rp5.000.000
Karena 1 Point = Rp1 dan Point digunakan untuk redemption.
6.1.1 Hanya Point dari EnakGame yang Dihitung ke Budget
Satu voucher dapat dibayar dengan Point dari berbagai asal: reward game, belanja (earning order), transfer, atau adjustment.
Realized cost yang dihitung ke budget EnakGame (global maupun event) hanya bagian voucher yang dibayar dengan Point yang berasal dari reward EnakGame. Bagian yang dibayar dengan Point dari belanja tetap dicatat untuk reporting Finance, tetapi tidak mengurangi budget mana pun.
Voucher face value = Rp10.000, point cost = 8.000
Point dipakai = 6.000 (dari reward game) + 2.000 (dari belanja)
Dihitung ke budget = Rp7.500
Tidak ke budget = Rp2.500
6.2 Important Distinction
Sistem harus membedakan:
| Konsep | Definisi |
|---|---|
| Issuance | Berapa Coin yang dikeluarkan oleh Reward Engine |
| Outstanding | Berapa Coin masih berada di user/economy |
| Redemption | Berapa Point benar-benar digunakan untuk mendapatkan voucher |
| Realized Cost | Nilai voucher yang benar-benar menjadi cost bisnis |
Budget Controller terutama menggunakan realized redemption/cost, bukan sekadar total Coin issuance.
7. Budget Hierarchy
Secara konsep:
GLOBAL BUDGET (bulanan, configurable)
│
└── Regular Game Activity (reward normal semua game)
EVENT/CAMPAIGN BUDGET (per event, terpisah)
│
└── Tambahan reward dari event (multiplier + bonus)
Event dan Campaign adalah hal yang sama. Setiap event memiliki budget sendiri, terpisah dari global budget.
Pembagian biaya saat event berjalan:
| Komponen reward | Dibiayai oleh |
|---|---|
| Reward normal game (base reward) | Global budget |
| Tambahan dari event (multiplier/bonus) | Budget event |
Contoh:
Normal Reward 10 Coin → Global budget
Ramadan 2x +10 Coin → Budget event Ramadan
──────────────────────────
Final Reward 20 Coin
Realized cost dari Point yang berasal dari tambahan event dihitung ke budget event tersebut, kapan pun Point itu ditukar ke voucher, termasuk setelah event berakhir.
8. Budget Metrics
Minimum metric yang harus tersedia:
- Total Budget
- Allocated Budget
- Realized Cost
- Remaining Budget
- Budget Utilization
- Forecasted Cost
- Forecasted Remaining Budget
- Budget Status
Contoh status:
HEALTHYWARNINGCRITICALEXHAUSTED
Threshold harus configurable.
9. Game Management
Game Management mengelola semua game yang tersedia di EnakGame.
Minimum information:
idnameslugdescriptionthumbnail- game URL/path
versionstatusconfigurationcreated_atupdated_at
Game status minimal:
DRAFTACTIVEINACTIVEARCHIVED
Game harus dapat memiliki reward configuration.
10. Game Session
Setiap permainan yang dapat menghasilkan reward harus memiliki session.
Flow:
User
↓
Start Game
↓
Debit Entry Cost (Coin) + Create Game Session
↓
Phaser Game
↓
Submit Result
↓
Validate Session
↓
Calculate Reward
↓
Issue Reward
Session harus dapat mencegah:
- duplicate completion
- duplicate reward
- expired session
- invalid session
- user mismatch
- game mismatch
Recommended concept: game_session_id menjadi idempotency key untuk reward completion.
Penting: Satu session tidak boleh menghasilkan reward berkali-kali.
10.1 Game Entry Cost
Semua game wajib berbayar menggunakan Coin. Tidak ada game gratis.
- Entry cost di-configure per game sebagai bagian dari game configuration, dengan nilai minimal 1 Coin.
- Entry cost dibayar dengan Coin, bukan Point.
- Coin dipotong saat Start Game, yaitu saat session dibuat — bukan saat submit result.
- Debit Coin dan pembuatan session terjadi dalam satu database transaction. Jika salah satu gagal, tidak ada Coin yang terpotong dan tidak ada session yang terbuat.
- Jika usable balance Coin tidak cukup, session tidak dibuat dan user tidak dapat bermain.
- Entry cost yang berlaku dicatat di session (snapshot), sehingga perubahan configuration tidak mengubah session yang sudah berjalan.
- Debit dicatat di ledger sebagai
SPENTdengan referencegame_session_iddangame_id. - Satu session hanya boleh didebit satu kali (
game_session_idmenjadi idempotency key untuk debit).
Start Game
→ load game configuration (entry cost)
→ check Coin usable balance
→ [1 transaction] debit Coin (SPENT) + create session
→ return session_id ke Phaser
Entry Cost & Budget
Entry cost tidak mengurangi atau meng-offset perhitungan budget.
Budget Controller dan Budget Metrics hanya memperhitungkan reward (Coin yang diterbitkan) dan realized voucher cost. Coin yang dibayar untuk bermain tidak dianggap sebagai pemasukan yang menambah budget.
Reward issued = 1.000.000 Coin
Entry cost paid = 400.000 Coin
Budget memakai → 1.000.000 Coin (reward), bukan 600.000 (net)
10.2 Entry Cost Refund
Entry cost dapat dikembalikan (refund) ke user untuk session yang tidak dapat diselesaikan.
- Refund mengembalikan jumlah Coin yang sama dengan entry cost yang tercatat di session.
- Refund dicatat di ledger sebagai
REFUNDdengan referencegame_session_iddan reference ke transaksiSPENTasalnya. - Refund wajib idempotent: satu session maksimal satu kali refund.
- Session yang sudah di-refund tidak boleh menghasilkan reward, dan session yang sudah rewarded tidak boleh di-refund.
- Refund bukan reward: tidak melewati Reward Engine, tidak dihitung sebagai Coin issued, dan tidak dihitung di budget.
- Refund harus auditable (siapa/sistem apa yang memicu dan alasannya).
Kondisi refund:
| Kondisi | Refund |
|---|---|
| System error (session gagal diselesaikan karena sistem) | Ya, otomatis oleh sistem |
| Game di-nonaktifkan saat session sedang berjalan | Ya, otomatis oleh sistem |
| Session expired/abandoned oleh user | Tidak |
- Refund dijalankan otomatis oleh sistem, tanpa perlu request user atau approval admin.
- Session yang ditinggalkan user tidak di-refund, agar user tidak dapat memulai game lalu meninggalkannya saat hasilnya tidak menguntungkan.
11. Reward Engine
Reward Engine adalah komponen yang menentukan berapa reward yang secara teoritis berhak diterima user berdasarkan result dan configuration.
Reward Engine tidak bertanggung jawab sendirian untuk memutuskan apakah reward boleh diterbitkan.
Flow:
Game Result
↓
Reward Engine
↓
Base Reward
↓
Event Modifier / Bonus
↓
Final Calculated Reward
↓
Economy Guard
12. Supported Reward Types
Reward Engine dirancang agar extensible.
Jenis reward minimum yang dapat didukung:
FIXED
Play completed → 5 Coin
SCORE_BASED
| Score | Reward |
|---|---|
| 0–100 | 1 Coin |
| 101–500 | 5 Coin |
| 501–1000 | 10 Coin |
| 1001+ | 20 Coin |
OUTCOME_BASED
| Outcome | Reward |
|---|---|
PERFECT |
20 Coin |
GOOD |
10 Coin |
NORMAL |
5 Coin |
FAIL |
0 Coin |
PROBABILITY
Reward berdasarkan probability yang dihitung server.
Contoh:
| Probability | Reward |
|---|---|
| 0.1% | 1000 Coin |
| 1% | 100 Coin |
| 10% | 10 Coin |
| 88.9% | 0 Coin |
Probability harus tervalidasi.
MULTIPLIER
Base reward dikalikan modifier.
Base = 10 Coin
Multiplier = 2x
Final = 20 Coin
TIERED
Reward berdasarkan tier/user/game progression.
Jenis reward dapat ditambah di masa depan tanpa mengubah seluruh engine.
13. Reward Configuration
Reward configuration harus memiliki lifecycle/version.
Contoh:
| Config | Reward |
|---|---|
| Runner Reward Config v1 | 10 Coin |
| Runner Reward Config v2 | 8 Coin |
Penting: Jangan overwrite configuration lama jika configuration tersebut sudah pernah digunakan dalam transaksi.
Tujuan:
- audit
- debugging
- historical accuracy
- mengetahui rule yang berlaku saat user bermain
Setiap reward transaction idealnya dapat dilacak ke configuration/version yang digunakan.
14. Normal Reward + Event Reward
Normal reward dan event modifier boleh aktif bersamaan.
Contoh:
Normal Reward 10 Coin
Ramadan Event 2x multiplier
Mission Bonus +5 Coin
─────────────────────────
Final Reward 25 Coin
Event tidak boleh mengubah permanent/base configuration game. Event bekerja sebagai layer/override/modifier.
Setelah event selesai:
Normal Reward 10 Coin
15. Event Management
Event digunakan untuk seasonal/campaign activity.
Contoh:
- Ramadan
- Christmas
- Independence Day
- Anniversary
- F&B campaign
Minimum event data:
idnameslugdescriptionbannerstart_atend_attimezonestatuspriority- reward configuration/modifier
- budget sendiri (lihat Section 7)
- rules
Event dapat menentukan:
- participating games
- reward multiplier
- bonus reward
- mission
- daily limit
- user limit
- leaderboard
- event-specific campaign rules
16. Multiple Event Handling
Karena event dapat overlap, sistem harus memiliki priority/stacking rule.
Contoh:
Normal Reward
+ Event A
+ Event B
Sistem harus memiliki aturan jelas apakah:
- hanya event priority tertinggi yang berlaku
- modifier dapat ditumpuk
- bonus dapat ditumpuk
- ada maximum multiplier
Default recommendation:
| Komponen | Rule |
|---|---|
| Reward Modifier | Controlled stacking |
| Bonus | Independently tracked |
| Maximum Reward Cap | Always enforced |
Penting: Final stacking rules harus ditentukan sebelum production.
17. Economy Guard
Economy Guard menentukan apakah calculated reward benar-benar boleh diterbitkan.
Minimum checks:
- session valid
- session belum rewarded
- user valid
- game valid
- reward configuration active
- user daily limit
- game daily limit
- event limit
- global limit
- maximum reward
- budget/economy status
- fraud/risk checks
- idempotency
Contoh:
Reward Engine
→ 20 Coin
Economy Guard
→ daily limit OK
→ event limit OK
→ duplicate NO
→ budget status OK
Approved
→ issue 20 Coin
18. Coin Wallet
Wallet menyimpan current usable balance.
Namun wallet bukan satu-satunya source of truth. Source of truth untuk audit adalah ledger.
| Komponen | Digunakan untuk |
|---|---|
| Wallet | fast balance lookup, current balance |
| Ledger | transaction history, audit, reconciliation, debugging, reporting |
19. Coin Ledger
Setiap perubahan balance harus menghasilkan ledger transaction.
Minimum transaction concepts:
EARNEDBONUSSPENTEXPIREDADJUSTMENTREVERSALCONVERSIONREFUND
SPENT mencakup pembayaran entry cost game. REFUND adalah pengembalian entry cost (lihat Section 10.2).
Transaction harus dapat memiliki reference:
game_session_idgame_idevent_idvoucher_redemption_idmission_id- admin adjustment reference
Idealnya setiap transaction memiliki:
balance_beforeamountbalance_after
20. Idempotency
Reward transaction wajib idempotent.
Contoh:
POST /game-session/complete
session_id = ABC
Request pertama:
Reward = 10 Coin
Status = SUCCESS
Request kedua dengan session yang sama:
Tidak membuat reward baru.
Return existing reward/result.
Database harus memiliki unique constraint/strategy yang menjamin satu session tidak bisa menghasilkan duplicate reward.
Hal yang sama berlaku untuk entry cost: satu session maksimal satu debit SPENT dan satu REFUND.
21. Voucher Management
Voucher Management adalah core module tersendiri.
Voucher adalah benefit yang dapat ditukar menggunakan Point.
Minimum voucher data:
idnamedescriptionimage- provider/merchant
- voucher value
- point cost
- stock
- validity
- terms
- status
- redemption rules
Sumber voucher mendukung keduanya:
- Internal voucher codes — kode dikelola sendiri (lihat Section 25).
- External API — kode/voucher diterbitkan oleh provider eksternal saat redemption.
22. Voucher Value vs Point Cost
Jangan menganggap Voucher Value = Point Cost selamanya.
Current conversion:
1 Coin = 1 Point = Rp1
Tetapi sebuah voucher dapat memiliki:
| Voucher Value | Point Cost |
|---|---|
| Rp10.000 | 8.000 |
| Rp10.000 | 12.000 |
Hal ini memungkinkan Product/Finance mengatur subsidy, promotion, atau margin.
23. Voucher Types
Voucher Management harus extensible.
Contoh:
| Type | Contoh |
|---|---|
| Fixed Value | Rp5.000, Rp10.000, Rp20.000 |
| Percentage Discount | 10%, 20%, 50% |
| Free Item | Free Coffee, Free Food |
| Merchant Benefit | Benefit yang hanya berlaku pada merchant/location tertentu |
Jenis voucher dapat ditambah sesuai kebutuhan.
24. Voucher Inventory
Jika voucher menggunakan unique code, sistem harus memiliki inventory.
Status minimal:
AVAILABLERESERVEDREDEEMEDEXPIREDCANCELLED
Flow normal:
AVAILABLE → RESERVED → REDEEMED
Jika redemption gagal/timeout:
RESERVED → AVAILABLE
Jika voucher expired:
AVAILABLE → EXPIRED
25. Voucher Stock
Voucher dapat menggunakan salah satu dari:
Static Stock
Admin memasukkan jumlah stock.
Stock = 1.000
Code Pool
Admin/provider memasukkan unique voucher codes.
CODE-001
CODE-002
CODE-003
...
System harus mengetahui stock available secara reliable.
26. Redemption Flow
Recommended flow:
User
↓
Select Voucher
↓
Check Point Balance
↓
Check Voucher Availability
↓
Reserve Voucher
↓
Deduct Point
↓
Issue Voucher
↓
Mark Voucher Redeemed
↓
Create Redemption Record
↓
Record Realized Cost
Transaction harus atomic.
Penting: Jangan sampai Point sudah dikurangi + voucher gagal diberikan tanpa recovery/rollback.
27. Redemption Idempotency
Redemption juga harus idempotent.
Satu redemption request tidak boleh menghasilkan:
- dua voucher
- dua Point deduction
- dua cost records
Gunakan idempotency/reference key.
28. Realized Cost
Setiap successful voucher redemption menghasilkan realized cost.
Contoh:
Voucher Value = Rp10.000
Point Used = 10.000
Realized Cost = Rp10.000
Realized cost menggunakan voucher face value.
Sistem tetap menyimpan field berikut secara terpisah:
voucher_value— face value, menjadi dasar realized cost dan budgetpoint_cost— Point yang dibayar userbusiness_cost— opsional, untuk reporting Finance jika berbeda dari face value; tidak dipakai untuk budget
29. Budget Controller
Budget Controller bertugas mengontrol reward economy berdasarkan actual redemption dan forecast.
Input
Minimum input:
- global budget
- realized voucher cost
- remaining budget
- remaining days
- historical redemption
- coin issuance
- active users
- plays
- average reward
- event status
- redemption rate
- target utilization
Output
Budget Controller dapat menghasilkan:
- budget status
- forecast cost
- recommended reward multiplier
- recommended reward rate
- warning
- automatic adjustment
- stop reward recommendation
30. Redemption-Based Forecast
Contoh kondisi:
| Metric | Nilai |
|---|---|
| Global Budget | Rp100M |
| Realized Cost | Rp60M |
| Remaining | Rp40M |
| Remaining Days | 10 |
Jika current burn rate terlalu tinggi:
Forecast = Rp115M
System dapat menghitung adjustment.
Contoh:
| Item | Nilai |
|---|---|
| Current Reward | 10 Coin |
| Recommended Multiplier | 0.85x |
| New Effective Reward | 8.5 Coin |
Penting: Rounding rule harus ditentukan agar reward final tidak menghasilkan pecahan Coin jika Coin integer.
31. Dynamic Rate Safety
Reward rate tidak boleh berubah secara liar setiap request.
Gunakan:
- configuration version
effective_at- cooldown
- min/max multiplier
- adjustment step
- forecast window
- audit log
Contoh:
Current = 10 Coin
Allowed adjustment step = 10%
Next possible: 9 Coin atau 11 Coin
❌ Jangan:
10 → 7 → 12 → 5 → 14 (dalam waktu singkat)
Tujuannya menjaga predictability dan user trust.
32. Budget Status
Recommended:
| Status | Arti |
|---|---|
HEALTHY |
Budget aman |
WARNING |
Burn rate mulai tinggi |
CRITICAL |
Forecast berpotensi melewati budget |
EXHAUSTED |
Budget sudah mencapai limit |
Behavior setiap status harus configurable.
33. Automatic vs Approval
Sistem sebaiknya mendukung dua mode:
RECOMMENDATION MODE
System calculates recommendation
↓
Admin/Product/Finance approves
↓
Publish
AUTOMATIC MODE
System calculates
↓
Guardrails
↓
Auto publish
Automatic mode hanya boleh berjalan dengan:
- min reward
- max reward
- min multiplier
- max multiplier
- maximum daily adjustment
- budget safety threshold
- audit log
- rollback capability
Default recommendation untuk production awal:
RECOMMENDATION MODESetelah economy memiliki data historis yang cukup, automatic mode dapat diaktifkan untuk rule tertentu.
34. Budget Exhaustion
Jika budget exhausted, system harus memiliki policy.
Possible policy:
- Stop rewards
- Reduce rewards to minimum
- Allow non-budget rewards only
- Disable affected event
- Continue game but no reward
Policy harus configurable.
Game tetap dapat dimainkan meskipun reward sementara tidak tersedia, kecuali Product menentukan game harus ikut disabled.
35. Limits
Minimum limit concepts:
| Limit | Definisi |
|---|---|
| User Daily Limit | Jumlah Coin maksimal yang dapat diperoleh user per hari |
| Game Daily Limit | Total reward game per hari |
| Event Limit | Reward maksimal dari event |
| Global Limit | Global economy protection |
| Session Limit | Satu session hanya dapat rewarded sekali |
Semua limit harus dapat di-configure.
Jika reward melewati limit, reward dipotong ke sisa limit (bukan dibatalkan seluruhnya). Jika sisa limit 0, reward menjadi 0.
36. Reporting & Analytics
Dashboard minimal:
Game
- DAU
- total plays
- completed games
- average score
- total Coin issued
- average reward
- reward per play
- total Coin spent for entry cost
- total Coin refunded
Economy
- Coin generated
- Coin spent
- Coin expired
- Coin outstanding
- Point balance
- Point redeemed
Voucher
- redemption count
- voucher value
- point spent
- realized cost
- stock
- redemption rate
Budget
- total budget
- realized cost
- remaining budget
- utilization
- forecast
- burn rate
Event
- participants
- plays
- Coin issued
- redemption
- event cost
- event performance
37. Audit Log
Admin changes harus dapat diaudit.
Minimal audit:
- who
- what
- before
- after
- timestamp
- reason
- source
Contoh:
Who : Admin A
Change : Reward 10 Coin → 8 Coin
Reason : Budget optimization
Timestamp : 2027-03-10 10:00
Audit terutama wajib untuk:
- reward configuration
- event configuration
- budget
- voucher
- Point/Coin adjustment
- automatic controller changes
38. Security & Anti-Abuse
Minimum protection:
- server-side reward calculation
- session validation
- idempotency
- rate limiting
- duplicate detection
- suspicious score detection
- impossible score detection
- concurrent request protection
- atomic wallet update
- atomic redemption
- audit trail
Penting: Jangan mempercayai reward amount dari client.
39. Recommended System Architecture
┌──────────────────┐
│ Next.js Web │
│ Game Portal │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ Go API │
└────────┬─────────┘
│
┌────────────────────┼────────────────────┐
│ │ │
▼ ▼ ▼
Game Management Game Session User/Economy
│ │ │
└────────────────────┼────────────────────┘
▼
Result Validator
│
▼
Reward Engine
│
▼
Economy Guard
│
┌──────┴──────┐
▼ ▼
Budget Controller Event
│ │
└──────┬──────┘
▼
Coin Wallet
│
▼
Coin Ledger
│
▼
Point Layer
│
▼
Voucher Management
│
▼
Redemption Engine
│
▼
Realized Cost
│
▼
Budget Controller
40. Recommended Development Order
Jangan langsung membuat semua modul sekaligus.
Phase 1 — Business Rules
Lock:
- Coin
- Point
- Voucher
- Budget
- Redemption
- Reward
- Event
- Limits
- Expiration
Phase 2 — Domain & Database
Design:
gamesgame_sessionsreward_configseventsevent_reward_configswalletscoin_transactionsbudgetsbudget_transactionsvouchersvoucher_inventoryredemptionsaudit_logs
Exact schema harus ditentukan setelah business rules final.
Phase 3 — Game Management
Build:
- Game CRUD
- Game status
- Game configuration
- Game version
Phase 4 — Game Session
Build:
- create session
- entry cost debit (Coin) saat create session
- entry cost refund
- validate session
- complete session
- idempotency
Phase 5 — Reward Engine
Build:
- fixed reward
- score based
- outcome based
- probability
- multiplier
- tiered
- reward configuration versioning
Phase 6 — Coin Economy
Build:
- wallet
- ledger
- earning
- expiration integration
- adjustment
- transaction history
Phase 7 — Voucher Management
Build:
- voucher CRUD
- voucher type
- voucher value
- point cost
- stock
- code pool
- expiration
- status
Phase 8 — Redemption
Build:
- voucher reservation
- Point deduction
- voucher issue
- rollback
- idempotency
- realized cost
Phase 9 — Event Management
Build:
- event CRUD
- participating games
- reward modifiers
- missions
- event limits
- event leaderboard
Phase 10 — Budget Controller
Build:
- budget pool
- realized cost tracking
- burn rate
- forecast
- recommendation
- automatic mode
- guardrails
Phase 11 — Analytics
Build:
- game analytics
- economy analytics
- voucher analytics
- budget dashboard
- event analytics
Phase 12 — Phaser Integration
Integrate real games with:
- game session
- result submission
- reward result
- leaderboard
- missions
41. Important Implementation Rules for Claude Code
Claude Code must follow these principles:
- Do not invent business rules that are not defined.
- Do not let Phaser/client determine reward amount.
- Do not mutate historical reward configuration that has already been used in transactions.
- Every reward completion must be idempotent.
- Every wallet mutation must have a ledger record.
- Voucher redemption must be atomic/recoverable.
- Budget actual cost is based on successful voucher redemption, according to the current business rule.
- All games use the same global/shared budget pool.
- Normal reward and event reward can be active simultaneously.
- Event configuration must not permanently mutate normal game reward configuration.
- Automatic reward adjustment must have guardrails.
- All important admin/economy changes must be auditable.
- Use database transactions for wallet, redemption, and other financial/economic mutations.
- Avoid premature microservices. Start with a modular Go backend unless scale requires otherwise.
- Prefer clear domain boundaries inside the existing backend.
- Entry cost is debited in Coin when the session is created, in the same transaction as the session.
- Entry cost and its refund never offset the budget; budget only counts reward and realized voucher cost.
- Point can only be redeemed for vouchers. It must never be usable as payment or cashed out.
42. Current Decisions
These decisions are confirmed for v1:
| Decision | Rule |
|---|---|
| Backend | Go |
| Database | PostgreSQL |
| Game engine | Phaser |
| Temporary session | Redis optional |
| Coin | Virtual game currency |
| Point | Redemption currency |
| Coin : Point | 1 : 1 |
| Coin : Rupiah | 1 Coin = Rp1 (nilai acuan, bukan cash out) |
| Point usage | Voucher redemption only |
| Point as payment | Not allowed |
| Point cash out | Not allowed |
| Game entry cost | Paid in Coin |
| Entry cost debit | At session creation (Start Game) |
| Entry cost refund | Automatic, idempotent; only for system error / game deactivated mid-session |
| Abandoned/expired session | No refund |
| Entry cost vs budget | Not counted; budget = reward only |
| Coin expiration | Existing system |
| Point expiration | Existing system |
| Coin → Point | Existing exchange (manual, configurable rate) |
| Budget model | Shared/global pool |
| Budget period | Monthly (default), configurable |
| Event = Campaign | Same concept |
| Budget counts | Only Point originating from EnakGame rewards |
| Budget actual cost | Successful voucher redemption |
| Realized cost basis | Voucher face value |
| Voucher source | Internal codes + external API |
| Free game | Not allowed (entry cost ≥ 1 Coin) |
| Event budget | Own budget per event, separate from global; funds the event's extra reward |
| Over limit | Reward capped to remaining limit |
| Game reward Coin transfer | Allowed |
| Voucher redemption PIN | Required |
| Legacy games (spin, ferris wheel) | Removed; spin rebuilt as EnakGame game |
| Game budget | Shared pool, not isolated per game |
| Normal + Event reward | Can run together |
| Reward authority | Backend |
| Reward idempotency | Required |
| Wallet | Required |
| Ledger | Required |
| Voucher Management | Core module |
| Redemption | Atomic/idempotent |
| Budget Controller | Required |
| Dynamic reward | Supported |
| Auto adjustment | Supported with guardrails |
| Default adjustment mode | Recommendation/approval |
| Event | Layer over normal game reward |
| Historical configs | Must be versioned |
| Audit | Required |
43. Open Decisions Before Database Design
The following should remain explicitly unresolved until Product/Finance decides them:
- Reward rounding
- integer Coin only
- allow fractional internal calculation but round final reward
- Event stacking
- priority only
- controlled stacking
- maximum multiplier
- Budget exhaustion policy (global dan event)
- Automatic Budget Controller thresholds
- Voucher reservation timeout
Sudah diputuskan (lihat Section 42): budget period, event/campaign budget, budget attribution, redemption cost model, Coin → Point conversion, Point expiration, voucher provider, free game, entry cost refund conditions.
These decisions should be finalized before production schema/API is considered final.
44. Definition of Done for Economy v1
Economy v1 is considered technically ready when:
- Game session cannot be rewarded twice.
- Entry cost is debited exactly once per session, atomically with session creation.
- Session cannot start when Coin balance is insufficient.
- Entry cost refund is idempotent, and a session cannot be both refunded and rewarded.
- Sessions failed by system error or game deactivation are refunded automatically; abandoned/expired sessions are not.
- Entry cost does not affect budget calculation.
- Point cannot be used as payment or cashed out.
- Client cannot directly choose reward amount.
- Reward configuration is versioned.
- Reward Engine calculates reward correctly.
- Economy Guard enforces limits.
- Wallet balance is consistent with ledger.
- Coin expiration is correctly represented.
- Voucher stock cannot go negative.
- Redemption is atomic.
- Redemption is idempotent.
- Successful redemption records realized cost.
- Budget Controller can calculate current utilization.
- Budget Controller can forecast future cost.
- Reward adjustment has guardrails.
- Event reward does not corrupt normal reward configuration.
- Admin changes are auditable.
- Finance can reconcile voucher cost against redemption records.
45. Guiding Principle
| Component | Responsibility |
|---|---|
| Product/Finance | Defines the budget |
| Game Management | Defines the game |
| Reward Engine | Calculates the reward |
| Economy Guard | Protects the economy |
| Budget Controller | Protects the budget |
| Voucher Management | Defines what users can redeem |
| Redemption | Records the actual business cost |
| Ledger | Provides the audit trail |
The goal is not simply to build a collection of games.