EGP Leaderboard System
  1. Getting Started
EGP Leaderboard System
  • Getting Started
    • Overview
  • Authentication
    • Register a new user account
      POST
    • Login and get token
      POST
    • Login and get token
      POST
    • Validate token
      POST
    • Logout
      POST
    • Refresh token
      POST
  • Users
    • List all users
      GET
    • Create a new user
      POST
    • Update user leaderboard access
      PUT
    • Delete user
      DELETE
    • Get user details
      GET
    • Generate user token
      POST
    • Create a new user (admin)
      POST
  • Admin
    • Get user API keys
      GET
    • Create API key
      POST
    • Delete API key
      DELETE
    • List all roles
      GET
    • Create a new role
      POST
    • Get role by name
      GET
    • Update role
      PUT
    • Delete role
      DELETE
    • Get users with role
      GET
    • Assign role to user
      POST
    • Remove role from user
      DELETE
    • Search audit logs
      GET
    • Get user audit logs
      GET
    • Get failed login attempts
      GET
    • Get audit event types
      GET
    • Get all available roles
      GET
    • Trigger leaderboard sync
      POST
  • Leaderboards
    • Get my leaderboards
    • Create a leaderboard
    • Get my leaderboard
    • Delete my leaderboard
    • List all leaderboards
    • Create a new leaderboard
    • Get leaderboard by ID
    • Update leaderboard
    • Delete leaderboard
    • Update a leaderboard's score aggregation rule
    • Update leaderboard metadata
    • Get leaderboard by displayId and owner
    • Get leaderboard entries by displayId and owner
    • Add entry to leaderboard by display ID
    • Get leaderboards with history
    • Reset a leaderboard (clear entries)
    • Get user history in leaderboard
    • Get leaderboards with history
  • Entries
    • Get leaderboard entries
    • Add or update entry
    • Delete leaderboard entry
    • Get user entry in leaderboard
    • Get entries for a leaderboard
  • getApiMyApikeysByKeyIdPermissions
    GET
  • postApiMyApikeysByKeyIdPermissions
    POST
  • deleteApiMyApikeysByKeyIdPermissions
    DELETE
  • putApiMyApikeysByKeyIdPermissions
    PUT
  • putApiMyLeaderboardsById
    PUT
  • putApiMyLeaderboardsByIdScore-aggregation
    PUT
  • postApiMyLeaderboardsByIdEntries
    POST
  • getApiMyLeaderboardsByIdEntriesByUserId
    GET
  • postApiAdminUsers
    POST
  • postApiAdminLeaderboards
    POST
  • postApiAdminEntries
    POST
  • postApiAdminPermissions
    POST
  • getApiAdminStatus
    GET
  • postApiAdminCacheInvalidate
    POST
  • getIndex
    GET
  1. Getting Started

Overview

EGP Leaderboard Service v3.0#

A scalable, real-time leaderboard service for game applications. This service provides APIs for managing leaderboards, submitting scores, and retrieving leaderboard data with real-time updates via WebSockets.

Features#

Real-time Leaderboards: Get instant updates when scores change
Multiple Time Frames: Support for daily, weekly, monthly, and all-time leaderboards
Scalable Architecture: Built with Redis for real-time data and ScyllaDB for historical storage
WebSocket Support: Real-time notifications for leaderboard changes
Flexible Scoring: Support for different scoring strategies (highest, latest, cumulative)
Customizable Score Aggregation: Per-leaderboard mathematical formulas for score calculation
Advanced Math Operations: Integration with Math.js for complex statistical calculations
Custom Display IDs: Specify your own IDs when creating leaderboards, with per-owner uniqueness
Extensible Metadata System: Store custom configuration and UI settings with each leaderboard
Pagination: Efficient retrieval of large leaderboards
User History: Track a user's performance over time
Game-specific Leaderboards: Organize leaderboards by game
Comprehensive API: RESTful endpoints for all operations
User Management: Complete user management with authentication and authorization
Bulk Operations: Support for bulk creating leaderboards and adding entries
Robust Leaderboard Reset: Securely reset leaderboards with distributed locking to prevent race conditions
Historical Snapshots: Create snapshots before resetting leaderboards to preserve historical data
Role-Based Time Restrictions: Configurable time-based access controls based on user roles
Strategic Cache Invalidation: Sophisticated cache management to ensure data consistency

Implementation#

Score aggregation is implemented at the service layer, ensuring consistent application regardless of how scores are submitted:
1.
Each leaderboard's scoring rule is stored in its metadata in ScyllaDB
2.
When a score is submitted, the rule is loaded and applied automatically
3.
Calculations occur server-side, ensuring consistent application of rules
4.
Optional metadata can track score history and calculation details

API#

Leaderboard owners can manage scoring rules through the dedicated API endpoint:
PUT /api/leaderboards/:id/score-aggregation
This allows defining or updating the scoring formula for a specific leaderboard.

Examples#

Basic examples of score aggregation rules:
// Accumulate scores (add new scores to current total)
{
  "type": "expression",
  "expression": "${current} + ${new}"
}

// Keep highest score
{
  "type": "expression",
  "expression": "Math.max(${current}, ${new})"
}

// Calculate statistical weighted average with Math.js
{
  "type": "expression",
  "engine": "mathjs",
  "expression": "0.7 * ${new} + 0.3 * ${current}"
}
For a complete reference, see the Score Aggregation API documentation.

Custom Display IDs#

The Leaderboard Service allows clients to specify their own custom display IDs when creating leaderboards, making them easier to reference and integrate with external systems.

Key Features#

1.
Custom Identifiers: Specify your own IDs when creating leaderboards
2.
Per-Owner Uniqueness: Different owners can use the same display ID
3.
Public Access: Retrieve leaderboards by display ID without authentication
4.
No Schema Changes: Uses existing metadata field, avoiding migrations

Example Usage#

Benefits#

Meaningful Identifiers: Use IDs that make sense for your application
Easier Integration: Simplify integration with other systems
User-Friendly URLs: Create cleaner, more readable URLs
Predictable References: Reference leaderboards with known IDs in your code
For more details and implementation specifics, see the Custom Display ID documentation.

Extensible Metadata System#

The Leaderboard Service includes a powerful metadata system that allows storing custom configuration, UI settings, and game-specific information with each leaderboard and entry.

Key Features#

Custom JSON Storage: Store any valid JSON data as metadata with leaderboards and entries
Schema-Free Design: Add custom fields without requiring database schema changes
Intelligent Merging: New metadata merges with existing values, preserving critical data
Dual Redis/ScyllaDB Storage: Metadata is stored in both databases for performance and reliability
UI Customization: Store display preferences, color schemes, and formatting options
Game-Specific Data: Include game modes, seasons, levels, and other contextual information
Administrative Tags: Add searchable tags and categories for organization
Client Configuration: Store client-side rendering options and behavior settings

Implementation#

The metadata system is built into the core service layer:
1.
Storage: Metadata is stored as a JSON string in both Redis and ScyllaDB
2.
Validation: All metadata is validated to ensure it's proper JSON before storage
3.
Merging: New metadata is intelligently merged with existing data
4.
Preservation: Important data like score aggregation rules are preserved during updates
5.
Cache Invalidation: Updates automatically invalidate Redis cache to ensure consistency

Blackjack Leaderboard Aggregator: A Case Study#

This document provides a detailed explanation of the Blackjack Leaderboard Aggregator integration test, which demonstrates how score aggregation rules can be used to track complex game statistics.

Overview#

The blackjack leaderboard aggregator test demonstrates a real-world implementation of our centralized score aggregation system. It simulates a blackjack tournament where multiple players compete against a dealer, with the leaderboard automatically tracking wins, losses, pushes, blackjacks, and calculating win rates.

Game Rules#

Blackjack is played with the following rules in our implementation:
1.
Basic Play: Players try to get a higher card total than the dealer without exceeding 21
2.
Card Values:
Number cards (2-10) are worth their face value
Face cards (J, Q, K) are worth 10
Aces are worth 11 or 1, whichever creates the better hand
3.
Outcomes:
Win: Player's hand beats dealer's hand, or dealer busts
Loss: Dealer's hand beats player's hand, or player busts
Push: Player and dealer have equal hand values
Blackjack: A natural 21 with first two cards (Ace + 10/Face card)
4.
Betting:
Standard wins pay 1:1 ($50 in our test)
Blackjack pays 1.5:1 ($75 in our test)
Pushes return the original bet (no gain/loss)
Losses forfeit the bet

Implementation Flow#

The test demonstrates the full integration between client and server components:

1. Setup Phase#

1.
Register a dealer (admin) user
2.
Obtain JWT token
3.
Generate API key
4.
Create a leaderboard with score aggregation rules

2. Gameplay Phase#

1.
Deal cards to players and dealer
2.
Players make decisions (hit/stand) based on basic strategy
3.
Dealer plays according to house rules (hit until 17+)
4.
Calculate outcomes (win/loss/push)
5.
Update bankrolls
6.
Send results to leaderboard service

3. Verification Phase#

1.
Get leaderboard entries
2.
Verify statistics calculation
3.
Validate ranking order

Client vs. Server Responsibilities#

ComponentClient SideServer Side
Game Logic✓ (Hit/stand decisions, card values)✗
Outcome Determination✓ (Win/loss/push)✗
Bankroll Tracking✓ (Starting $1000, modified each round)✓ (Stored as score)
Raw Statistics✓ (Basic counting)✗
Score Aggregation✗✓ (Rules evaluation)
Statistical Calculations✗✓ (Hands, wins, losses, etc.)
Win Rate Calculation✗✓ (Wins / hands)
History Tracking✗✓ (Score changes over time)
Final Ranking✗✓ (Based on bankroll total)

Score Aggregation Rules#

The leaderboard uses these rules to process scores:

Request-Response Flow#

For each player's turn, the following data flow occurs:
1.
Client Side:
Determine outcome (win/loss/push)
Update local bankroll
Send score update to server with outcome metadata
2.
Server Side (LeaderboardService):
Receive score update
Load existing entry (if any)
Merge existing and new metadata
Pass to ExpressionService for calculation
3.
Server Side (ExpressionService):
Apply main score rule (use new score)
Calculate all custom fields
Return results to LeaderboardService
4.
Server Side (LeaderboardService):
Store updated score and metadata
Add to history if enabled
Return updated entry to client

Step-by-Step Example#

Let's follow Alice's first three rounds to see how the system works:

Round 1#

1.
Client: Alice beats dealer with 21 vs 17
Local bankroll updated: 1000→1050
Send score update with outcome: "win", hasBlackjack: false
2.
Server:
No previous entry exists, so initialize counters
Apply score rule: set score to $1050
Calculate fields:
hands = 1 (first hand)
wins = 1 (first win)
winRate = 1.0 (1 win ÷ 1 hand)

Round 2#

1.
Client: Alice wins again with 21 vs 17
Local bankroll updated: 1050→1100
Send score update with outcome: "win", hasBlackjack: false
2.
Server:
Get existing entry with current metadata
Apply score rule: set score to $1100
Calculate fields:
hands = 2 (1 + 1)
wins = 2 (1 + 1)
winRate = 1.0 (2 wins ÷ 2 hands)

Round 3#

1.
Client: Alice ties dealer with 19 vs 19
Local bankroll unchanged: $1100
Send score update with outcome: "push", hasBlackjack: false
2.
Server:
Get existing entry with current metadata
Apply score rule: score remains $1100
Calculate fields:
hands = 3 (2 + 1)
wins = 2 (unchanged from 2)
pushes = 1 (0 + 1)
winRate = 0.67 (2 wins ÷ 3 hands)

Formula Breakdown#

Each statistic is calculated using expressions that:
1.
Check if a previous value exists
2.
Process conditionally based on outcome
3.
Increment the appropriate counter
For example, the wins calculation:
context.mergedMetadata.outcome === 'win' ? 
  (context.mergedMetadata.wins ? context.mergedMetadata.wins + 1 : 1) : 
  (context.mergedMetadata.wins || 0)
This breaks down to:
IF outcome is 'win'
THEN IF we already have a wins count
THEN increment it
ELSE set it to 1
ELSE keep the existing wins count (or 0 if none)

Advantages of Server-Side Calculation#

This approach offers several benefits:
1.
Single Source of Truth: Statistics calculated in one place
2.
Consistency: Rules applied uniformly across all entries
3.
Reduced Client Complexity: Clients only need to send raw data
4.
Cheat Prevention: Clients can't manipulate statistics directly
5.
Extended Analytics: Complex metrics like winRate automatically calculated
6.
History Tracking: Score and statistic changes preserved over time
Modified at 2025-04-12 12:48:40
Next
Register a new user account
Built with