WECHESS

FRONTEND GUIDE FOR AI CODING AGENTS - PART 11 - Leaderboard Service

This document is a part of a REST API guide for the wechess project. It is designed for AI agents that will generate frontend code to consume the project’s backend.

This document provides extensive instruction for the usage of leaderboard

Service Access

Leaderboard service management is handled through service specific base urls.

Leaderboard service may be deployed to the preview server, staging server, or production server. Therefore,it has 3 access URLs. The frontend application must support all deployment environments during development, and the user should be able to select the target API server on the login page (already handled in first part.).

For the leaderboard service, the base URLs are:

Scope

Leaderboard Service Description

Handles ELO/stat computation and leaderboard management for registered players only. Excludes guest users entirely.

Leaderboard service provides apis and business logic for following data objects in wechess application. Each data object may be either a central domain of the application data structure or a related helper data object for a central concept. Note that data object concept is equal to table concept in the database, in the service database each data object is represented as a db table scheme and the object instances as table rows.

playerStats Data Object: Stores aggregate stats for a registered chess player: ELO, win/loss history, streak, last game, etc. Excludes guests. One per registered user.

leaderboardEntry Data Object: Holds global leaderboard standings for registered players. Rank, ELO, and season support. Excludes guests.

Leaderboard Service Frontend Description By The Backend Architect

Leaderboard Service Frontend Guide

API Structure

Object Structure of a Successful Response

When the service processes requests successfully, it wraps the requested resource(s) within a JSON envelope. This envelope includes the data and essential metadata such as configuration details and pagination information, providing context to the client.

HTTP Status Codes:

Success Response Format:

For successful operations, the response includes a "status": "OK" property, signaling that the request executed successfully. The structure of a successful response is outlined below:

{
  "status":"OK",
  "statusCode": 200,   
  "elapsedMs":126,
  "ssoTime":120,
  "source": "db",
  "cacheKey": "hexCode",
  "userId": "ID",
  "sessionId": "ID",
  "requestId": "ID",
  "dataName":"products",
  "method":"GET",
  "action":"list",
  "appVersion":"Version",
  "rowCount":3,
  "products":[{},{},{}],
  "paging": {
    "pageNumber":1, 
    "pageRowCount":25, 
    "totalRowCount":3,
    "pageCount":1
  },
  "filters": [],
  "uiPermissions": []
}

Additional Data

Each API may include additional data besides the main data object, depending on the business logic of the API. These will be provided in each API’s response signature.

Error Response

If a request encounters an issue—whether due to a logical fault or a technical problem—the service responds with a standardized JSON error structure. The HTTP status code indicates the nature of the error, using commonly recognized codes for clarity:

Each error response is structured to provide meaningful insight into the problem, assisting in efficient diagnosis and resolution.

{
  "result": "ERR",
  "status": 400,
  "message": "errMsg_organizationIdisNotAValidID",
  "errCode": 400,
  "date": "2024-03-19T12:13:54.124Z",
  "detail": "String"
}

PlayerStats Data Object

Stores aggregate stats for a registered chess player: ELO, win/loss history, streak, last game, etc. Excludes guests. One per registered user.

PlayerStats Data Object Frontend Description By The Backend Architect

Display these stats on the user’s profile and stats page. Guests never have a playerStats object. All stats are global (no season).

PlayerStats Data Object Properties

PlayerStats data object has got following properties that are represented as table fields in the database scheme. These properties don’t stand just for data storage, but each may have different settings to manage the business logic.

Property Type IsArray Required Secret Description
userId ID false Yes No The registered user this record belongs to (auth:user.id).
eloRating Integer false Yes No Current ELO rating for registered player.
totalGames Integer false Yes No Total completed games (wins + losses + draws) for this player.
wins Integer false Yes No Number of games won by the player.
losses Integer false Yes No Number of games lost by the player.
draws Integer false Yes No Number of drawn games by the player.
streak Integer false Yes No Current win or loss streak. Positive=win streak, negative=loss streak, 0=none/neutral.
lastGameAt Date false No No Timestamp of last completed game for user.
username String false No No Display name for the player, publicly visible.

Relation Properties

userId

Mindbricks supports relations between data objects, allowing you to define how objects are linked together. The relations may reference to a data object either in this service or in another service. Id the reference is remote, backend handles the relations through service communication or elastic search. These relations should be respected in the frontend so that instaead of showing the related objects id, the frontend should list human readable values from other data objects. If the relation points to another service, frontend should use the referenced service api in case it needs related data. The relation logic is montly handled in backend so the api responses feeds the frontend about the relational data. In mmost cases the api response will provide the relational data as well as the main one.

In frontend, please ensure that,

1- instaead of these relational ids you show the main human readable field of the related target data (like name), 2- if this data object needs a user input of these relational ids, you should provide a combobox with the list of possible records or (a searchbox) to select with the realted target data object main human readable field.

The target object is a parent object, meaning that the relation is a one-to-many relationship from target to this object.

Required: Yes

LeaderboardEntry Data Object

Holds global leaderboard standings for registered players. Rank, ELO, and season support. Excludes guests.

LeaderboardEntry Data Object Frontend Description By The Backend Architect

Use for leaderboard views and global player ranking displays. userId relates to registered player; can include fullname/avatar when needed for display. Season field may be used for future seasonal leaderboard resets.

LeaderboardEntry Data Object Properties

LeaderboardEntry data object has got following properties that are represented as table fields in the database scheme. These properties don’t stand just for data storage, but each may have different settings to manage the business logic.

Property Type IsArray Required Secret Description
userId ID false Yes No The registered user this leaderboard entry represents.
currentRank Integer false Yes No Current leaderboard rank (1=top). Lower is better.
eloRating Integer false Yes No Player’s current ELO rating (copy from playerStats).
season String false No No Leaderboard season identifier (null for all-time/global, can be set for seasonal leaderboards as needed).
lastRankChangeAt Date false No No Timestamp of last rank change/leaderboard update.
username String false No No Display name for the player, publicly visible on leaderboard.

Relation Properties

userId

Mindbricks supports relations between data objects, allowing you to define how objects are linked together. The relations may reference to a data object either in this service or in another service. Id the reference is remote, backend handles the relations through service communication or elastic search. These relations should be respected in the frontend so that instaead of showing the related objects id, the frontend should list human readable values from other data objects. If the relation points to another service, frontend should use the referenced service api in case it needs related data. The relation logic is montly handled in backend so the api responses feeds the frontend about the relational data. In mmost cases the api response will provide the relational data as well as the main one.

In frontend, please ensure that,

1- instaead of these relational ids you show the main human readable field of the related target data (like name), 2- if this data object needs a user input of these relational ids, you should provide a combobox with the list of possible records or (a searchbox) to select with the realted target data object main human readable field.

The target object is a parent object, meaning that the relation is a one-to-many relationship from target to this object.

Required: Yes

Default CRUD APIs

For each data object, the backend architect may designate default APIs for standard operations (create, update, delete, get, list). These are the APIs that frontend CRUD forms and AI agents should use for basic record management. If no default is explicitly set (isDefaultApi), the frontend generator auto-discovers the most general API for each operation.

PlayerStats Default APIs

Operation API Name Route Explicitly Set
Create createPlayerStats /v1/playerstatses Yes
Update updatePlayerStats /v1/playerstatses/:playerStatsId Yes
Delete none - Auto
Get getPlayerStats /v1/playerstatses/:userId Yes
List none - Auto

LeaderboardEntry Default APIs

Operation API Name Route Explicitly Set
Create createLeaderboardEntry /v1/leaderboardentries Auto
Update none - Auto
Delete none - Auto
Get getLeaderboardEntry /v1/leaderboardentries/:userId Yes
List listLeaderboardTopN /v1/leaderboardtopn Yes

When building CRUD forms for a data object, use the default create/update APIs listed above. The form fields should correspond to the API’s body parameters. For relation fields, render a dropdown loaded from the related object’s list API using the display label property.

Event Subscriptions

This service exposes 1 event subscription that allow clients to receive real-time Kafka events. Each subscription groups related topics with built-in authorization derived from the linked DataObject’s access configuration.

Subscription Overview

Subscription Transport Topics Auth
gameEvents websocket 1 Absolute: administrator

Subscription: gameEvents

Subscribes to gameplay events so the leaderboard can update ELO ratings, player stats, and rankings when games are completed.

Available Topics

Event Name DataObject Access Level Tenant Filter Owner Filter Description
gameCompleted playerStats accessPrivate No No Fires when a chess game is updated (status changes to completed/terminated). Used to trigger ELO recalculation and leaderboard rank updates for both players.

Connection & Subscription

import { io } from "socket.io-client";

const socket = io(`${baseUrl}/leaderboard-api/events/gameEvents`, {
  auth: {
    token: `Bearer ${accessToken}`,
  },
  transports: ["websocket"],
});

socket.on("connect", () => {
  // Subscribe to a subset (or all) of the available topics
  socket.emit("subscribe", {
    topics: ["gameCompleted"],
  });
});

// Server confirms which topics were allowed and which were rejected
socket.on("subscribed", ({ topics, rejected }) => {
  console.log("Subscribed to:", topics);
  if (rejected.length > 0) {
    // Some topics may be rejected based on authorization
    // Resubscribe with the allowed subset if needed
    console.warn("Rejected:", rejected);
  }
});

// Receive events
socket.on("event", ({ topic, name, data }) => {
  switch (name) {
    case "gameCompleted":
      // Handle gameCompleted — data from playerStats
      break;
  }
});

// Unsubscribe from topics you no longer need
socket.emit("unsubscribe", { topics: ["gameCompleted"] });

socket.on("unsubscribed", ({ topics }) => {
  console.log("Unsubscribed from:", topics);
});

socket.on("error", ({ message }) => {
  console.error("Subscription error:", message);
});

socket.on("connect_error", (err) => {
  console.error("Connection failed:", err.message);
});

Authorization Details

Each topic’s authorization is derived from its linked DataObject:

API Reference

Create Playerstats API

[Default create API] — This is the designated default create API for the playerStats data object. Frontend generators and AI agents should use this API for standard CRUD operations. Create a player stats record for a newly registered player. Only registered users (never guests) should have this object. Typically used at registration or conversion.

API Frontend Description By The Backend Architect

Called only at registration or on converting guest to registered. Prepares stats for profile display.

Rest Route

The createPlayerStats API REST controller can be triggered via the following route:

/v1/playerstatses

Rest Request Parameters

The createPlayerStats api has got 9 regular request parameters

Parameter Type Required Population
userId ID true request.body?.[“userId”]
eloRating Integer true request.body?.[“eloRating”]
totalGames Integer true request.body?.[“totalGames”]
wins Integer true request.body?.[“wins”]
losses Integer true request.body?.[“losses”]
draws Integer true request.body?.[“draws”]
streak Integer true request.body?.[“streak”]
lastGameAt Date false request.body?.[“lastGameAt”]
username String false request.body?.[“username”]
userId : The registered user this record belongs to (auth:user.id).
eloRating : Current ELO rating for registered player.
totalGames : Total completed games (wins + losses + draws) for this player.
wins : Number of games won by the player.
losses : Number of games lost by the player.
draws : Number of drawn games by the player.
streak : Current win or loss streak. Positive=win streak, negative=loss streak, 0=none/neutral.
lastGameAt : Timestamp of last completed game for user.
username : Display name for the player, publicly visible.

REST Request To access the api you can use the REST controller with the path POST /v1/playerstatses

  axios({
    method: 'POST',
    url: '/v1/playerstatses',
    data: {
            userId:"ID",  
            eloRating:"Integer",  
            totalGames:"Integer",  
            wins:"Integer",  
            losses:"Integer",  
            draws:"Integer",  
            streak:"Integer",  
            lastGameAt:"Date",  
            username:"String",  
    
    },
    params: {
    
        }
  });

REST Response

{
	"status": "OK",
	"statusCode": "201",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "playerStats",
	"method": "POST",
	"action": "create",
	"appVersion": "Version",
	"rowCount": 1,
	"playerStats": {
		"id": "ID",
		"userId": "ID",
		"eloRating": "Integer",
		"totalGames": "Integer",
		"wins": "Integer",
		"losses": "Integer",
		"draws": "Integer",
		"streak": "Integer",
		"lastGameAt": "Date",
		"username": "String",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}

Update Playerstats API

[Default update API] — This is the designated default update API for the playerStats data object. Frontend generators and AI agents should use this API for standard CRUD operations. Update player statistics when a game completes. Only called for registered users by gameplay service (M2M) or admin; guests not allowed.

API Frontend Description By The Backend Architect

System/gameplay triggers this to update stats at game end. Never called for guests.

Rest Route

The updatePlayerStats API REST controller can be triggered via the following route:

/v1/playerstatses/:playerStatsId

Rest Request Parameters

The updatePlayerStats api has got 9 regular request parameters

Parameter Type Required Population
playerStatsId ID true request.params?.[“playerStatsId”]
eloRating Integer true request.body?.[“eloRating”]
totalGames Integer true request.body?.[“totalGames”]
wins Integer true request.body?.[“wins”]
losses Integer true request.body?.[“losses”]
draws Integer true request.body?.[“draws”]
streak Integer true request.body?.[“streak”]
lastGameAt Date false request.body?.[“lastGameAt”]
username String false request.body?.[“username”]
playerStatsId : This id paremeter is used to select the required data object that will be updated
eloRating : Current ELO rating for registered player.
totalGames : Total completed games (wins + losses + draws) for this player.
wins : Number of games won by the player.
losses : Number of games lost by the player.
draws : Number of drawn games by the player.
streak : Current win or loss streak. Positive=win streak, negative=loss streak, 0=none/neutral.
lastGameAt : Timestamp of last completed game for user.
username : Display name for the player, publicly visible.

REST Request To access the api you can use the REST controller with the path PATCH /v1/playerstatses/:playerStatsId

  axios({
    method: 'PATCH',
    url: `/v1/playerstatses/${playerStatsId}`,
    data: {
            eloRating:"Integer",  
            totalGames:"Integer",  
            wins:"Integer",  
            losses:"Integer",  
            draws:"Integer",  
            streak:"Integer",  
            lastGameAt:"Date",  
            username:"String",  
    
    },
    params: {
    
        }
  });

REST Response

{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "playerStats",
	"method": "PATCH",
	"action": "update",
	"appVersion": "Version",
	"rowCount": 1,
	"playerStats": {
		"id": "ID",
		"userId": "ID",
		"eloRating": "Integer",
		"totalGames": "Integer",
		"wins": "Integer",
		"losses": "Integer",
		"draws": "Integer",
		"streak": "Integer",
		"lastGameAt": "Date",
		"username": "String",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}

Get Playerstats API

[Default get API] — This is the designated default get API for the playerStats data object. Frontend generators and AI agents should use this API for standard CRUD operations. Fetch a single registered user’s player stats (private to user or admin).

API Frontend Description By The Backend Architect

Used to display profile stats. User can only view own; admin can view any.

Rest Route

The getPlayerStats API REST controller can be triggered via the following route:

/v1/playerstatses/:userId

Rest Request Parameters

The getPlayerStats api has got 1 regular request parameter

Parameter Type Required Population
userId ID true request.params?.[“userId”]
userId : The registered user this record belongs to (auth:user.id)… The parameter is used to query data.

REST Request To access the api you can use the REST controller with the path GET /v1/playerstatses/:userId

  axios({
    method: 'GET',
    url: `/v1/playerstatses/${userId}`,
    data: {
    
    },
    params: {
    
        }
  });

REST Response

This route’s response is constrained to a select list of properties, and therefore does not encompass all attributes of the resource.

{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "playerStats",
	"method": "GET",
	"action": "get",
	"appVersion": "Version",
	"rowCount": 1,
	"playerStats": {
		"isActive": true
	}
}

Get Leaderboardentry API

[Default get API] — This is the designated default get API for the leaderboardEntry data object. Frontend generators and AI agents should use this API for standard CRUD operations. Fetch this player’s leaderboard rank entry (registered users only).

API Frontend Description By The Backend Architect

Allow user to view their own leaderboard position (or admin to view any user). Entry includes user info for display.

Rest Route

The getLeaderboardEntry API REST controller can be triggered via the following route:

/v1/leaderboardentries/:userId

Rest Request Parameters

The getLeaderboardEntry api has got 1 regular request parameter

Parameter Type Required Population
userId ID true request.params?.[“userId”]
userId : The registered user this leaderboard entry represents… The parameter is used to query data.

REST Request To access the api you can use the REST controller with the path GET /v1/leaderboardentries/:userId

  axios({
    method: 'GET',
    url: `/v1/leaderboardentries/${userId}`,
    data: {
    
    },
    params: {
    
        }
  });

REST Response

This route’s response is constrained to a select list of properties, and therefore does not encompass all attributes of the resource.

{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "leaderboardEntry",
	"method": "GET",
	"action": "get",
	"appVersion": "Version",
	"rowCount": 1,
	"leaderboardEntry": {
		"isActive": true
	}
}

List Leaderboardtopn API

[Default list API] — This is the designated default list API for the leaderboardEntry data object. Frontend generators and AI agents should use this API for standard CRUD operations. List top N players for leaderboard display (e.g., leaderboard page top 100). Sorted by currentRank ascending (best = 1).

API Frontend Description By The Backend Architect

Leaderboard screen populates using this API; accessible to all authenticated users (guests see empty/null result).

Rest Route

The listLeaderboardTopN API REST controller can be triggered via the following route:

/v1/leaderboardtopn

Rest Request Parameters

The listLeaderboardTopN api has got 1 regular request parameter

Parameter Type Required Population
topN Integer false request.query?.[“topN”]
topN : Number of top players to return (max 500)

REST Request To access the api you can use the REST controller with the path GET /v1/leaderboardtopn

  axios({
    method: 'GET',
    url: '/v1/leaderboardtopn',
    data: {
    
    },
    params: {
             topN:'"Integer"',  
    
        }
  });

REST Response

This route’s response is constrained to a select list of properties, and therefore does not encompass all attributes of the resource.

{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "leaderboardEntries",
	"method": "GET",
	"action": "list",
	"appVersion": "Version",
	"rowCount": "\"Number\"",
	"leaderboardEntries": [
		{
			"isActive": true
		},
		{},
		{}
	],
	"paging": {
		"pageNumber": "Number",
		"pageRowCount": "NUmber",
		"totalRowCount": "Number",
		"pageCount": "Number"
	},
	"filters": [],
	"uiPermissions": []
}

Create Leaderboardentry API

Create a leaderboard entry for a registered player. Called when PlayerStats exists but LeaderboardEntry is missing.

API Frontend Description By The Backend Architect

Called by ensureLeaderboardEntry when a user has PlayerStats but no LeaderboardEntry.

Rest Route

The createLeaderboardEntry API REST controller can be triggered via the following route:

/v1/leaderboardentries

Rest Request Parameters

The createLeaderboardEntry api has got 6 regular request parameters

Parameter Type Required Population
userId ID true request.body?.[“userId”]
currentRank Integer true request.body?.[“currentRank”]
eloRating Integer true request.body?.[“eloRating”]
season String false request.body?.[“season”]
lastRankChangeAt Date false request.body?.[“lastRankChangeAt”]
username String false request.body?.[“username”]
userId : The registered user this leaderboard entry represents.
currentRank : Current leaderboard rank (1=top). Lower is better.
eloRating : Player’s current ELO rating (copy from playerStats).
season : Leaderboard season identifier (null for all-time/global, can be set for seasonal leaderboards as needed).
lastRankChangeAt : Timestamp of last rank change/leaderboard update.
username : Display name for the player, publicly visible on leaderboard.

REST Request To access the api you can use the REST controller with the path POST /v1/leaderboardentries

  axios({
    method: 'POST',
    url: '/v1/leaderboardentries',
    data: {
            userId:"ID",  
            currentRank:"Integer",  
            eloRating:"Integer",  
            season:"String",  
            lastRankChangeAt:"Date",  
            username:"String",  
    
    },
    params: {
    
        }
  });

REST Response

{
	"status": "OK",
	"statusCode": "201",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "leaderboardEntry",
	"method": "POST",
	"action": "create",
	"appVersion": "Version",
	"rowCount": 1,
	"leaderboardEntry": {
		"id": "ID",
		"userId": "ID",
		"currentRank": "Integer",
		"eloRating": "Integer",
		"season": "String",
		"lastRankChangeAt": "Date",
		"username": "String",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}

After this prompt, the user may give you new instructions to update the output of this prompt or provide subsequent prompts about the project.