@smartico/public-api 0.0.387 → 0.0.389
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/CustomSections/AchCustomSection.d.ts +2 -1
- package/dist/SmarticoAPI.d.ts +4 -3
- package/dist/WSAPI/WSAPIAvatars.d.ts +1 -4
- package/dist/WSAPI/WSAPILeaderBoard.d.ts +76 -10
- package/dist/WSAPI/WSAPITypes.d.ts +16 -3
- package/dist/index.js +268 -159
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +116 -28
- package/dist/index.modern.mjs.map +1 -1
- package/docs/api/classes/WSAPILeaderBoard.md +86 -10
- package/docs/api/interfaces/LeaderBoardDetailsT.md +19 -0
- package/docs/api/interfaces/LeaderBoardUserT.md +14 -2
- package/docs/native/PROTOCOL.md +34 -6
- package/docs/ui/leaderboard/UIGuide_getLeaderBoard.md +15 -0
- package/package.json +1 -1
- package/src/CustomSections/AchCustomSection.ts +1 -0
- package/src/Leaderboard/LeaderBoards.ts +9 -12
- package/src/SmarticoAPI.ts +33 -5
- package/src/WSAPI/WSAPIAvatars.ts +2 -5
- package/src/WSAPI/WSAPILeaderBoard.ts +91 -14
- package/src/WSAPI/WSAPITypes.ts +16 -3
|
@@ -13,7 +13,9 @@ monthly tabs.
|
|
|
13
13
|
|
|
14
14
|
The leaderboard for each period type is configured separately by
|
|
15
15
|
the operator. A label may have any combination of DAILY, WEEKLY,
|
|
16
|
-
and MONTHLY boards configured (or none).
|
|
16
|
+
and MONTHLY boards configured (or none). To discover which boards
|
|
17
|
+
exist before loading any standings, call [getLeaderBoards](#getleaderboards)
|
|
18
|
+
(metadata only) and drive the tab selector from its `period_type_id`s.
|
|
17
19
|
|
|
18
20
|
#### Parameters
|
|
19
21
|
|
|
@@ -29,12 +31,13 @@ The board's period type
|
|
|
29
31
|
|
|
30
32
|
##### getPreviousPeriod?
|
|
31
33
|
|
|
32
|
-
`boolean`
|
|
34
|
+
`number` \| `boolean`
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
`
|
|
36
|
+
Which period to fetch. `false` (default)
|
|
37
|
+
= current in-progress period; `true` =
|
|
38
|
+
the most recent finalized snapshot; a
|
|
39
|
+
number `n` = the n-th previous snapshot
|
|
40
|
+
(`1` = previous, `2` = the one before, …).
|
|
38
41
|
|
|
39
42
|
#### Returns
|
|
40
43
|
|
|
@@ -56,10 +59,13 @@ against that case in consumer code.
|
|
|
56
59
|
Pass a `periodType` from [LeaderBoardPeriodType](../enumerations/LeaderBoardPeriodType.md)
|
|
57
60
|
(`DAILY = 1`, `WEEKLY = 2`, `MONTHLY = 3`). Pass
|
|
58
61
|
`getPreviousPeriod: true` to fetch the most-recently-ended
|
|
59
|
-
period's snapshot (yesterday's
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
period's snapshot (yesterday's / last week's / last month's
|
|
63
|
+
results) instead of the current live period. To reach older
|
|
64
|
+
snapshots, pass a number instead of a boolean: `1` = previous
|
|
65
|
+
period, `2` = the one before that, and so on (`0` / `false` =
|
|
66
|
+
current). Use the snapshot's `create_date` / `version_id` to label
|
|
67
|
+
which historical run a previous-period board is. How far back
|
|
68
|
+
snapshots are retained is operator-configured.
|
|
63
69
|
|
|
64
70
|
**Top-20 cap**
|
|
65
71
|
The server hard-caps `users[]` at 20 entries, ordered by
|
|
@@ -147,3 +153,73 @@ console.log('[smartico] previous-week standings — render with greyed-out "ende
|
|
|
147
153
|
```
|
|
148
154
|
|
|
149
155
|
***
|
|
156
|
+
|
|
157
|
+
### getLeaderBoards()
|
|
158
|
+
|
|
159
|
+
> **getLeaderBoards**(): `Promise`\<[`LeaderBoardDetailsT`](../interfaces/LeaderBoardDetailsT.md)[]\>
|
|
160
|
+
|
|
161
|
+
Returns the list of leaderboards the operator has configured for this
|
|
162
|
+
label — **metadata only, without participants**. Use it to discover
|
|
163
|
+
which boards exist (and their period types) so you can render the
|
|
164
|
+
board/tab selector, then load a specific board's standings on demand
|
|
165
|
+
with [getLeaderBoard](#getleaderboard).
|
|
166
|
+
|
|
167
|
+
This is the lightweight discovery counterpart to [getLeaderBoard](#getleaderboard):
|
|
168
|
+
it issues one round-trip that returns every board's identity, name,
|
|
169
|
+
description, rules, `period_type_id`, and prize table, but **not** the
|
|
170
|
+
ranked players. Fetching the full standings for one board (the top-20
|
|
171
|
+
`users[]` and the caller's own `me` entry) is what [getLeaderBoard](#getleaderboard)
|
|
172
|
+
does per period.
|
|
173
|
+
|
|
174
|
+
#### Returns
|
|
175
|
+
|
|
176
|
+
`Promise`\<[`LeaderBoardDetailsT`](../interfaces/LeaderBoardDetailsT.md)[]\>
|
|
177
|
+
|
|
178
|
+
Promise resolving to the array of configured boards
|
|
179
|
+
(metadata only). Empty array when none are configured.
|
|
180
|
+
|
|
181
|
+
#### Remarks
|
|
182
|
+
|
|
183
|
+
**Returned shape**
|
|
184
|
+
An array of `LeaderBoardDetailsT`, one per configured board, ordered by
|
|
185
|
+
`period_type_id` ascending (DAILY, WEEKLY, MONTHLY, …). On every entry
|
|
186
|
+
`users` is an empty array and `me` is `undefined` — this call never
|
|
187
|
+
carries participant data. Read `period_type_id` from each entry and pass
|
|
188
|
+
it to [getLeaderBoard](#getleaderboard) to load that board's standings.
|
|
189
|
+
|
|
190
|
+
**Empty result**
|
|
191
|
+
Resolves to an empty array when the label has no leaderboards configured
|
|
192
|
+
— treat that as "hide the leaderboard surface".
|
|
193
|
+
|
|
194
|
+
**Cache TTL**
|
|
195
|
+
Cached for 30 seconds under a dedicated key (independent of
|
|
196
|
+
[getLeaderBoard](#getleaderboard)'s per-period cache). Repeated calls within the
|
|
197
|
+
window return the cached list without a round-trip.
|
|
198
|
+
|
|
199
|
+
**Refresh model**: one-shot fetch — no subscription, no push. Board
|
|
200
|
+
configuration changes surface on the next cache miss.
|
|
201
|
+
|
|
202
|
+
**Idempotency / Side effects**: safe. Read-only.
|
|
203
|
+
|
|
204
|
+
**Visitor mode**: supported. Returns the brand's public board list.
|
|
205
|
+
|
|
206
|
+
#### Example
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
const boards = await window._smartico.api.getLeaderBoards();
|
|
210
|
+
|
|
211
|
+
if (boards.length === 0) {
|
|
212
|
+
console.log('[smartico] no leaderboards configured — hide the leaderboard surface');
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Render one tab per board from the lightweight list (no players yet).
|
|
217
|
+
console.log('[smartico] render leaderboard tabs:', boards.map(b => b.name));
|
|
218
|
+
|
|
219
|
+
// When the user opens a tab, load that board's standings on demand.
|
|
220
|
+
const first = boards[0];
|
|
221
|
+
const full = await window._smartico.api.getLeaderBoard(first.period_type_id);
|
|
222
|
+
console.log('[smartico] loaded standings for', first.name, '—', full?.users.length ?? 0, 'players');
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
***
|
|
@@ -46,6 +46,24 @@ Period type this board is bound to ([LeaderBoardPeriodType](../enumerations/Lead
|
|
|
46
46
|
|
|
47
47
|
***
|
|
48
48
|
|
|
49
|
+
### version\_id
|
|
50
|
+
|
|
51
|
+
> **version\_id**: `number`
|
|
52
|
+
|
|
53
|
+
Snapshot version. `0` for the live current period; a positive value
|
|
54
|
+
identifies a finalized previous-period snapshot (see `getPreviousPeriod`).
|
|
55
|
+
|
|
56
|
+
***
|
|
57
|
+
|
|
58
|
+
### create\_date
|
|
59
|
+
|
|
60
|
+
> **create\_date**: `number`
|
|
61
|
+
|
|
62
|
+
Snapshot creation timestamp (Unix ms). `0` for the live current period;
|
|
63
|
+
the finalization time for a previous-period snapshot.
|
|
64
|
+
|
|
65
|
+
***
|
|
66
|
+
|
|
49
67
|
### rewards
|
|
50
68
|
|
|
51
69
|
> **rewards**: [`LeaderBoardsRewardsT`](LeaderBoardsRewardsT.md)[]
|
|
@@ -59,6 +77,7 @@ Per-place prize table; the array length is the number of paid places.
|
|
|
59
77
|
> **users**: [`LeaderBoardUserT`](LeaderBoardUserT.md)[]
|
|
60
78
|
|
|
61
79
|
Top-20 ranked entries (server-capped), sorted by `position` ASC.
|
|
80
|
+
Empty when fetched via `getLeaderBoards()` (metadata-only list).
|
|
62
81
|
|
|
63
82
|
***
|
|
64
83
|
|
|
@@ -16,7 +16,18 @@ Display username (operator-defined alias).
|
|
|
16
16
|
|
|
17
17
|
> **avatar\_url**: `string`
|
|
18
18
|
|
|
19
|
-
Resolved CDN URL for the participant's avatar.
|
|
19
|
+
Resolved CDN URL for the participant's avatar. May be empty when the
|
|
20
|
+
participant has no custom avatar — fall back to a level-based default
|
|
21
|
+
using `level_id`.
|
|
22
|
+
|
|
23
|
+
***
|
|
24
|
+
|
|
25
|
+
### level\_id
|
|
26
|
+
|
|
27
|
+
> **level\_id**: `number`
|
|
28
|
+
|
|
29
|
+
The participant's level id — use it to resolve a level-based default
|
|
30
|
+
avatar when `avatar_url` is empty.
|
|
20
31
|
|
|
21
32
|
***
|
|
22
33
|
|
|
@@ -41,4 +52,5 @@ Participant's points for this period.
|
|
|
41
52
|
|
|
42
53
|
> **is\_me**: `boolean`
|
|
43
54
|
|
|
44
|
-
`true` when this row is the current authenticated user.
|
|
55
|
+
`true` when this row is the current authenticated user. Always `true`
|
|
56
|
+
on the `me` entry.
|
package/docs/native/PROTOCOL.md
CHANGED
|
@@ -1872,7 +1872,8 @@ No method-specific fields. Send only the common fields (see [Common Message Fiel
|
|
|
1872
1872
|
|
|
1873
1873
|
### getLeaderBoard
|
|
1874
1874
|
|
|
1875
|
-
Get leaderboard
|
|
1875
|
+
Get one period's leaderboard with its ranked players, or the list of all
|
|
1876
|
+
configured boards without players.
|
|
1876
1877
|
|
|
1877
1878
|
#### Request
|
|
1878
1879
|
|
|
@@ -1880,9 +1881,14 @@ Get leaderboard for a specific period type.
|
|
|
1880
1881
|
|
|
1881
1882
|
| Field | Type | Description |
|
|
1882
1883
|
|-------|------|-------------|
|
|
1883
|
-
| `period_type_id` | `number` | Period type: `1` = Daily, `2` = Weekly, `3` = Monthly
|
|
1884
|
+
| `period_type_id` | `number` | Period type: `1` = Daily, `2` = Weekly, `3` = Monthly. Optional — if omitted, the response `map` contains **every** configured board. |
|
|
1884
1885
|
| `snapshot_offset` | `number` | `0` = current period, `1` = previous period, `2` = period before previous, etc. |
|
|
1885
|
-
| `include_users` | `boolean` |
|
|
1886
|
+
| `include_users` | `boolean` | `true` → each board includes its `positions` (and `userPosition`). `false` (or omitted) → board metadata only, no players — the lightweight "list available boards" mode. |
|
|
1887
|
+
|
|
1888
|
+
> **Two modes from one request.** Send `period_type_id` + `include_users: true`
|
|
1889
|
+
> to load a single board's standings. Omit `period_type_id` and send
|
|
1890
|
+
> `include_users: false` to enumerate all configured boards (metadata only) —
|
|
1891
|
+
> useful to build the board/tab selector before loading any standings.
|
|
1886
1892
|
|
|
1887
1893
|
#### Response
|
|
1888
1894
|
|
|
@@ -1890,9 +1896,31 @@ Get leaderboard for a specific period type.
|
|
|
1890
1896
|
|
|
1891
1897
|
| Field | Type | Description |
|
|
1892
1898
|
|-------|------|-------------|
|
|
1893
|
-
| `
|
|
1894
|
-
|
|
1895
|
-
|
|
1899
|
+
| `map` | `object` | Keyed by `period_type_id` (as a string: `"1"` / `"2"` / `"3"`), one entry per board. With `period_type_id` set in the request only that key is present; omitted → every configured board. |
|
|
1900
|
+
|
|
1901
|
+
Each value of `map` is a leaderboard object:
|
|
1902
|
+
|
|
1903
|
+
| Field | Type | Description |
|
|
1904
|
+
|-------|------|-------------|
|
|
1905
|
+
| `board_id` | `number` | Stable board id |
|
|
1906
|
+
| `period_type_id` | `number` | `1` = Daily, `2` = Weekly, `3` = Monthly |
|
|
1907
|
+
| `create_date` | `number` | `0` for the current period; the snapshot timestamp for a previous period |
|
|
1908
|
+
| `versiod_id` | `number` | Snapshot version; `0` for the current period (the field is spelled `versiod_id` on the wire) |
|
|
1909
|
+
| `reward_points` | `number[]` | Per-place prize points; index `0` = place 1 |
|
|
1910
|
+
| `board_public_meta` | `object` | `{ name, description, rules }` display strings (HTML allowed in `description` / `rules`) |
|
|
1911
|
+
| `positions` | `LeaderBoardPosition[]` | Ranked entries, top 20, ordered by rank. **Absent when `include_users` is `false`.** |
|
|
1912
|
+
| `userPosition` | `LeaderBoardPosition` | The requesting user's own entry. Absent when `include_users` is `false`, or when the user is unranked. |
|
|
1913
|
+
|
|
1914
|
+
Each `LeaderBoardPosition`:
|
|
1915
|
+
|
|
1916
|
+
| Field | Type | Description |
|
|
1917
|
+
|-------|------|-------------|
|
|
1918
|
+
| `position_in_board` | `number` | Rank (DENSE_RANK); `-1` on `userPosition` = unranked / outside the window |
|
|
1919
|
+
| `points_accumulated` | `number` | Participant's points for the period |
|
|
1920
|
+
| `public_username` | `string` | Display name (falls back to `user_alt_name`) |
|
|
1921
|
+
| `is_me` | `boolean` | `true` for the requesting user's row inside `positions` |
|
|
1922
|
+
| `avatar_id` | `string` | Raw avatar id — build the image URL client-side |
|
|
1923
|
+
| `level_id` | `number` | The participant's level (factor it into avatar resolution to match the default Smartico UI) |
|
|
1896
1924
|
|
|
1897
1925
|
---
|
|
1898
1926
|
|
|
@@ -9,6 +9,15 @@
|
|
|
9
9
|
- No subscription, no push refresh. Poll manually if the consumer
|
|
10
10
|
needs live updates during an in-progress period.
|
|
11
11
|
|
|
12
|
+
## Discovering boards (`getLeaderBoards`)
|
|
13
|
+
Before loading any standings, call `getLeaderBoards()` to discover which
|
|
14
|
+
boards the operator configured (DAILY / WEEKLY / MONTHLY, or none). It
|
|
15
|
+
returns the board list as **metadata only** — `name`, `period_type_id`,
|
|
16
|
+
`rewards`, etc., with `users` empty and `me` undefined — in one lightweight
|
|
17
|
+
round-trip. Build the board/tab selector from that list, then call
|
|
18
|
+
`getLeaderBoard(period_type_id)` to load a tab's standings on demand. If it
|
|
19
|
+
returns an empty array, hide the leaderboard surface entirely.
|
|
20
|
+
|
|
12
21
|
## List view organization
|
|
13
22
|
|
|
14
23
|
The default Smartico UI renders the leaderboard with three top-level
|
|
@@ -113,6 +122,12 @@ a fresh fetch within the TTL (e.g. a manual refresh button), call
|
|
|
113
122
|
`clearCaches()` first — it clears the whole SDK cache, not just this
|
|
114
123
|
board.
|
|
115
124
|
|
|
125
|
+
To page back through **older** snapshots (not just the immediately
|
|
126
|
+
previous one), pass a number instead of a boolean: `getLeaderBoard(periodType, 2)`
|
|
127
|
+
fetches the period before last, `3` the one before that, etc. Label each
|
|
128
|
+
historical board with its `create_date` / `version_id` so the user knows
|
|
129
|
+
which run they're viewing.
|
|
130
|
+
|
|
116
131
|
## Status-specific visual treatments
|
|
117
132
|
|
|
118
133
|
- **Current period**: full-color rendering; live point counts.
|
package/package.json
CHANGED
|
@@ -13,19 +13,16 @@ const pointsRewardTransform = (reward_points: number[]): LeaderBoardsRewardsT[]
|
|
|
13
13
|
|
|
14
14
|
const getLeaderBoardPlayerTransformed = (user: LeaderBoardPosition, isMe?: boolean): LeaderBoardUserT => {
|
|
15
15
|
if (user) {
|
|
16
|
-
|
|
16
|
+
return {
|
|
17
17
|
public_username: user?.public_username || user.user_alt_name,
|
|
18
18
|
avatar_url: user.avatar_url,
|
|
19
|
+
level_id: user.level_id,
|
|
19
20
|
position: user.position_in_board,
|
|
20
21
|
points: user.points_accumulated,
|
|
21
|
-
|
|
22
|
+
// The `me` entry is the current user by definition, so force `true`
|
|
23
|
+
// there; list rows carry the server-provided flag.
|
|
24
|
+
is_me: isMe ? true : user.is_me,
|
|
22
25
|
};
|
|
23
|
-
|
|
24
|
-
if (isMe) {
|
|
25
|
-
delete x.is_me;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return x;
|
|
29
26
|
}
|
|
30
27
|
|
|
31
28
|
return null;
|
|
@@ -33,18 +30,18 @@ const getLeaderBoardPlayerTransformed = (user: LeaderBoardPosition, isMe?: boole
|
|
|
33
30
|
|
|
34
31
|
export const getLeaderBoardTransform = (board: LeaderBoardDetails): LeaderBoardDetailsT => {
|
|
35
32
|
if (board) {
|
|
36
|
-
|
|
33
|
+
return {
|
|
37
34
|
board_id: board.board_id,
|
|
38
35
|
name: board.board_public_meta.name,
|
|
39
36
|
description: board.board_public_meta.description,
|
|
40
37
|
rules: board.board_public_meta.rules,
|
|
41
38
|
period_type_id: board.period_type_id,
|
|
39
|
+
version_id: board.versiod_id,
|
|
40
|
+
create_date: board.create_date,
|
|
42
41
|
rewards: pointsRewardTransform(board.reward_points),
|
|
43
|
-
users: board.positions.map((p) => getLeaderBoardPlayerTransformed(p)),
|
|
42
|
+
users: (board.positions || []).map((p) => getLeaderBoardPlayerTransformed(p)),
|
|
44
43
|
me: getLeaderBoardPlayerTransformed(board.userPosition, true),
|
|
45
44
|
};
|
|
46
|
-
|
|
47
|
-
return x;
|
|
48
45
|
}
|
|
49
46
|
|
|
50
47
|
return null;
|
package/src/SmarticoAPI.ts
CHANGED
|
@@ -1144,15 +1144,18 @@ class SmarticoAPI {
|
|
|
1144
1144
|
public async leaderboardGet(
|
|
1145
1145
|
user_ext_id: string,
|
|
1146
1146
|
period_type_id?: LeaderBoardPeriodType,
|
|
1147
|
-
prevPeriod: boolean = false,
|
|
1147
|
+
prevPeriod: boolean | number = false,
|
|
1148
1148
|
force_language?: string,
|
|
1149
1149
|
): Promise<LeaderBoardDetails> {
|
|
1150
|
+
// boolean keeps back-compat (false → current, true → previous);
|
|
1151
|
+
// a number selects an arbitrary snapshot offset (1 = previous, 2 = the one before, …).
|
|
1152
|
+
const snapshot_offset = typeof prevPeriod === 'number' ? prevPeriod : prevPeriod ? 1 : 0;
|
|
1150
1153
|
const message = this.buildMessage<GetLeaderBoardsRequest, GetLeaderBoardsResponse>(
|
|
1151
1154
|
user_ext_id,
|
|
1152
1155
|
ClassId.GET_LEADERS_BOARD_REQUEST,
|
|
1153
1156
|
{
|
|
1154
1157
|
period_type_id,
|
|
1155
|
-
snapshot_offset
|
|
1158
|
+
snapshot_offset,
|
|
1156
1159
|
include_users: true,
|
|
1157
1160
|
},
|
|
1158
1161
|
);
|
|
@@ -1184,11 +1187,36 @@ class SmarticoAPI {
|
|
|
1184
1187
|
public async leaderboardsGetT(
|
|
1185
1188
|
user_ext_id: string,
|
|
1186
1189
|
period_type_id: LeaderBoardPeriodType = LeaderBoardPeriodType.DAILY,
|
|
1187
|
-
prevPeriod: boolean = false,
|
|
1190
|
+
prevPeriod: boolean | number = false,
|
|
1188
1191
|
): Promise<LeaderBoardDetailsT> {
|
|
1189
1192
|
return getLeaderBoardTransform(await this.leaderboardGet(user_ext_id, period_type_id, prevPeriod));
|
|
1190
1193
|
}
|
|
1191
1194
|
|
|
1195
|
+
public async leaderboardsGetList(
|
|
1196
|
+
user_ext_id: string,
|
|
1197
|
+
force_language?: string,
|
|
1198
|
+
): Promise<LeaderBoardDetails[]> {
|
|
1199
|
+
const message = this.buildMessage<GetLeaderBoardsRequest, GetLeaderBoardsResponse>(
|
|
1200
|
+
user_ext_id,
|
|
1201
|
+
ClassId.GET_LEADERS_BOARD_REQUEST,
|
|
1202
|
+
{
|
|
1203
|
+
// No period_type_id → the server returns every configured board.
|
|
1204
|
+
// include_users: false → board metadata only (no positions / userPosition).
|
|
1205
|
+
snapshot_offset: 0,
|
|
1206
|
+
include_users: false,
|
|
1207
|
+
},
|
|
1208
|
+
);
|
|
1209
|
+
|
|
1210
|
+
const response = await this.send<GetLeaderBoardsResponse>(message, ClassId.GET_LEADERS_BOARD_RESPONSE, force_language);
|
|
1211
|
+
|
|
1212
|
+
// map is keyed by period_type_id; integer-like keys iterate in ascending order.
|
|
1213
|
+
return Object.values(response.map || {});
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
public async leaderboardsGetListT(user_ext_id: string): Promise<LeaderBoardDetailsT[]> {
|
|
1217
|
+
return (await this.leaderboardsGetList(user_ext_id)).map(getLeaderBoardTransform);
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1192
1220
|
public async levelsGet(user_ext_id: string, force_language?: string): Promise<GetLevelMapResponse> {
|
|
1193
1221
|
const message = this.buildMessage<any, GetLevelMapResponse>(user_ext_id, ClassId.GET_LEVEL_MAP_REQUEST);
|
|
1194
1222
|
return await this.send<GetLevelMapResponse>(message, ClassId.GET_LEVEL_MAP_RESPONSE, force_language);
|
|
@@ -1572,7 +1600,6 @@ class SmarticoAPI {
|
|
|
1572
1600
|
}
|
|
1573
1601
|
|
|
1574
1602
|
public async avatarsCustomize(params: {
|
|
1575
|
-
label_id: number;
|
|
1576
1603
|
user_id: number;
|
|
1577
1604
|
prompt_id: number;
|
|
1578
1605
|
avatar_url: string;
|
|
@@ -1581,7 +1608,8 @@ class SmarticoAPI {
|
|
|
1581
1608
|
return this.sendAvatarApi<AvatarCustomizeResponse>({
|
|
1582
1609
|
method: 'avatar-customize',
|
|
1583
1610
|
body: {
|
|
1584
|
-
label_id
|
|
1611
|
+
// The server resolves label_id from label_api_key.
|
|
1612
|
+
label_api_key: this.label_api_key,
|
|
1585
1613
|
user_id: params.user_id,
|
|
1586
1614
|
user_ext_id: this.tracker?.getExtUserId(),
|
|
1587
1615
|
brand_key: this.brand_api_key || this.tracker?.params?.brand_key,
|
|
@@ -404,7 +404,6 @@ export class WSAPIAvatars extends WSAPIMiniGames {
|
|
|
404
404
|
*
|
|
405
405
|
* **Visitor mode**: not supported (throws).
|
|
406
406
|
*
|
|
407
|
-
* @param props.label_id Numeric Smartico label (brand) ID the user belongs to.
|
|
408
407
|
* @param props.user_id Numeric Smartico user ID.
|
|
409
408
|
* @param props.prompt_id Style-prompt ID (`prompt_id`) from {@link getAvatarPrompts}.
|
|
410
409
|
* @param props.avatar_url CDN URL of the base avatar to customize.
|
|
@@ -414,13 +413,12 @@ export class WSAPIAvatars extends WSAPIMiniGames {
|
|
|
414
413
|
*
|
|
415
414
|
* @example
|
|
416
415
|
* ```ts
|
|
417
|
-
* //
|
|
416
|
+
* // user_id identifies the Smartico user being customized.
|
|
418
417
|
* const prompts = await window._smartico.api.getAvatarPrompts();
|
|
419
418
|
* const prompt = prompts[0];
|
|
420
419
|
*
|
|
421
420
|
* console.log('[smartico] generating avatar — show a spinner for ~5-20s and disable the Generate button');
|
|
422
421
|
* const result = await window._smartico.api.avatarsCustomize({
|
|
423
|
-
* label_id,
|
|
424
422
|
* user_id,
|
|
425
423
|
* prompt_id: prompt.prompt_id,
|
|
426
424
|
* avatar_url: baseAvatar.avatar_url,
|
|
@@ -440,13 +438,12 @@ export class WSAPIAvatars extends WSAPIMiniGames {
|
|
|
440
438
|
* ```
|
|
441
439
|
*/
|
|
442
440
|
public async avatarsCustomize(props: {
|
|
443
|
-
label_id: number;
|
|
444
441
|
user_id: number;
|
|
445
442
|
prompt_id: number;
|
|
446
443
|
avatar_url: string;
|
|
447
444
|
avatar_real_id: number;
|
|
448
445
|
}): Promise<AvatarCustomizeResponse> {
|
|
449
|
-
const required: (keyof typeof props)[] = ['
|
|
446
|
+
const required: (keyof typeof props)[] = ['user_id', 'prompt_id', 'avatar_url', 'avatar_real_id'];
|
|
450
447
|
for (const field of required) {
|
|
451
448
|
if (!props[field]) {
|
|
452
449
|
throw new Error(`${field} is required`);
|
|
@@ -20,7 +20,9 @@ export class WSAPILeaderBoard extends WSAPIGamePick {
|
|
|
20
20
|
*
|
|
21
21
|
* The leaderboard for each period type is configured separately by
|
|
22
22
|
* the operator. A label may have any combination of DAILY, WEEKLY,
|
|
23
|
-
* and MONTHLY boards configured (or none).
|
|
23
|
+
* and MONTHLY boards configured (or none). To discover which boards
|
|
24
|
+
* exist before loading any standings, call {@link getLeaderBoards}
|
|
25
|
+
* (metadata only) and drive the tab selector from its `period_type_id`s.
|
|
24
26
|
*
|
|
25
27
|
* @remarks
|
|
26
28
|
* **Return value note** — the runtime may return `undefined` if no
|
|
@@ -32,10 +34,13 @@ export class WSAPILeaderBoard extends WSAPIGamePick {
|
|
|
32
34
|
* Pass a `periodType` from {@link LeaderBoardPeriodType}
|
|
33
35
|
* (`DAILY = 1`, `WEEKLY = 2`, `MONTHLY = 3`). Pass
|
|
34
36
|
* `getPreviousPeriod: true` to fetch the most-recently-ended
|
|
35
|
-
* period's snapshot (yesterday's
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
37
|
+
* period's snapshot (yesterday's / last week's / last month's
|
|
38
|
+
* results) instead of the current live period. To reach older
|
|
39
|
+
* snapshots, pass a number instead of a boolean: `1` = previous
|
|
40
|
+
* period, `2` = the one before that, and so on (`0` / `false` =
|
|
41
|
+
* current). Use the snapshot's `create_date` / `version_id` to label
|
|
42
|
+
* which historical run a previous-period board is. How far back
|
|
43
|
+
* snapshots are retained is operator-configured.
|
|
39
44
|
*
|
|
40
45
|
* **Top-20 cap**
|
|
41
46
|
* The server hard-caps `users[]` at 20 entries, ordered by
|
|
@@ -89,10 +94,11 @@ export class WSAPILeaderBoard extends WSAPIGamePick {
|
|
|
89
94
|
* Selects which pre-configured board to
|
|
90
95
|
* fetch; the board itself is bound to one
|
|
91
96
|
* period by the operator.
|
|
92
|
-
* @param getPreviousPeriod
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* `
|
|
97
|
+
* @param getPreviousPeriod Which period to fetch. `false` (default)
|
|
98
|
+
* = current in-progress period; `true` =
|
|
99
|
+
* the most recent finalized snapshot; a
|
|
100
|
+
* number `n` = the n-th previous snapshot
|
|
101
|
+
* (`1` = previous, `2` = the one before, …).
|
|
96
102
|
* @returns Promise resolving to `LeaderBoardDetailsT`.
|
|
97
103
|
* **At runtime, may resolve to `undefined`**
|
|
98
104
|
* when no board is configured for the
|
|
@@ -135,14 +141,85 @@ export class WSAPILeaderBoard extends WSAPIGamePick {
|
|
|
135
141
|
* // const visitorBoard = await window._smartico.vapi('EN').getLeaderBoard(LeaderBoardPeriodType.DAILY);
|
|
136
142
|
* ```
|
|
137
143
|
*/
|
|
138
|
-
public async getLeaderBoard(periodType: LeaderBoardPeriodType, getPreviousPeriod?: boolean): Promise<LeaderBoardDetailsT> {
|
|
139
|
-
//
|
|
140
|
-
//
|
|
141
|
-
const
|
|
144
|
+
public async getLeaderBoard(periodType: LeaderBoardPeriodType, getPreviousPeriod?: boolean | number): Promise<LeaderBoardDetailsT> {
|
|
145
|
+
// Resolve the snapshot offset: false/omitted → 0 (current), true → 1
|
|
146
|
+
// (previous), or an explicit number for older snapshots.
|
|
147
|
+
const offset = typeof getPreviousPeriod === 'number' ? getPreviousPeriod : getPreviousPeriod ? 1 : 0;
|
|
148
|
+
// Cache per (periodType, offset) so switching tabs or period within the
|
|
149
|
+
// TTL doesn't return a colliding board.
|
|
150
|
+
const cacheKey = `${onUpdateContextKey.LeaderBoards}:${periodType}:${offset}`;
|
|
142
151
|
return OCache.use(
|
|
143
152
|
cacheKey,
|
|
144
153
|
ECacheContext.WSAPI,
|
|
145
|
-
() => this.api.leaderboardsGetT(this.userExtId, periodType,
|
|
154
|
+
() => this.api.leaderboardsGetT(this.userExtId, periodType, offset),
|
|
155
|
+
CACHE_DATA_SEC,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Returns the list of leaderboards the operator has configured for this
|
|
161
|
+
* label — **metadata only, without participants**. Use it to discover
|
|
162
|
+
* which boards exist (and their period types) so you can render the
|
|
163
|
+
* board/tab selector, then load a specific board's standings on demand
|
|
164
|
+
* with {@link getLeaderBoard}.
|
|
165
|
+
*
|
|
166
|
+
* This is the lightweight discovery counterpart to {@link getLeaderBoard}:
|
|
167
|
+
* it issues one round-trip that returns every board's identity, name,
|
|
168
|
+
* description, rules, `period_type_id`, and prize table, but **not** the
|
|
169
|
+
* ranked players. Fetching the full standings for one board (the top-20
|
|
170
|
+
* `users[]` and the caller's own `me` entry) is what {@link getLeaderBoard}
|
|
171
|
+
* does per period.
|
|
172
|
+
*
|
|
173
|
+
* @remarks
|
|
174
|
+
* **Returned shape**
|
|
175
|
+
* An array of `LeaderBoardDetailsT`, one per configured board, ordered by
|
|
176
|
+
* `period_type_id` ascending (DAILY, WEEKLY, MONTHLY, …). On every entry
|
|
177
|
+
* `users` is an empty array and `me` is `undefined` — this call never
|
|
178
|
+
* carries participant data. Read `period_type_id` from each entry and pass
|
|
179
|
+
* it to {@link getLeaderBoard} to load that board's standings.
|
|
180
|
+
*
|
|
181
|
+
* **Empty result**
|
|
182
|
+
* Resolves to an empty array when the label has no leaderboards configured
|
|
183
|
+
* — treat that as "hide the leaderboard surface".
|
|
184
|
+
*
|
|
185
|
+
* **Cache TTL**
|
|
186
|
+
* Cached for 30 seconds under a dedicated key (independent of
|
|
187
|
+
* {@link getLeaderBoard}'s per-period cache). Repeated calls within the
|
|
188
|
+
* window return the cached list without a round-trip.
|
|
189
|
+
*
|
|
190
|
+
* **Refresh model**: one-shot fetch — no subscription, no push. Board
|
|
191
|
+
* configuration changes surface on the next cache miss.
|
|
192
|
+
*
|
|
193
|
+
* **Idempotency / Side effects**: safe. Read-only.
|
|
194
|
+
*
|
|
195
|
+
* **Visitor mode**: supported. Returns the brand's public board list.
|
|
196
|
+
*
|
|
197
|
+
* @returns Promise resolving to the array of configured boards
|
|
198
|
+
* (metadata only). Empty array when none are configured.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```ts
|
|
202
|
+
* const boards = await window._smartico.api.getLeaderBoards();
|
|
203
|
+
*
|
|
204
|
+
* if (boards.length === 0) {
|
|
205
|
+
* console.log('[smartico] no leaderboards configured — hide the leaderboard surface');
|
|
206
|
+
* return;
|
|
207
|
+
* }
|
|
208
|
+
*
|
|
209
|
+
* // Render one tab per board from the lightweight list (no players yet).
|
|
210
|
+
* console.log('[smartico] render leaderboard tabs:', boards.map(b => b.name));
|
|
211
|
+
*
|
|
212
|
+
* // When the user opens a tab, load that board's standings on demand.
|
|
213
|
+
* const first = boards[0];
|
|
214
|
+
* const full = await window._smartico.api.getLeaderBoard(first.period_type_id);
|
|
215
|
+
* console.log('[smartico] loaded standings for', first.name, '—', full?.users.length ?? 0, 'players');
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
public async getLeaderBoards(): Promise<LeaderBoardDetailsT[]> {
|
|
219
|
+
return OCache.use(
|
|
220
|
+
`${onUpdateContextKey.LeaderBoards}:list`,
|
|
221
|
+
ECacheContext.WSAPI,
|
|
222
|
+
() => this.api.leaderboardsGetListT(this.userExtId),
|
|
146
223
|
CACHE_DATA_SEC,
|
|
147
224
|
);
|
|
148
225
|
}
|
package/src/WSAPI/WSAPITypes.ts
CHANGED
|
@@ -1105,9 +1105,16 @@ export interface LeaderBoardDetailsT {
|
|
|
1105
1105
|
rules: string;
|
|
1106
1106
|
/** Period type this board is bound to ({@link LeaderBoardPeriodType}). */
|
|
1107
1107
|
period_type_id: LeaderBoardPeriodType;
|
|
1108
|
+
/** Snapshot version. `0` for the live current period; a positive value
|
|
1109
|
+
* identifies a finalized previous-period snapshot (see `getPreviousPeriod`). */
|
|
1110
|
+
version_id: number;
|
|
1111
|
+
/** Snapshot creation timestamp (Unix ms). `0` for the live current period;
|
|
1112
|
+
* the finalization time for a previous-period snapshot. */
|
|
1113
|
+
create_date: number;
|
|
1108
1114
|
/** Per-place prize table; the array length is the number of paid places. */
|
|
1109
1115
|
rewards: LeaderBoardsRewardsT[];
|
|
1110
|
-
/** Top-20 ranked entries (server-capped), sorted by `position` ASC.
|
|
1116
|
+
/** Top-20 ranked entries (server-capped), sorted by `position` ASC.
|
|
1117
|
+
* Empty when fetched via `getLeaderBoards()` (metadata-only list). */
|
|
1111
1118
|
users: LeaderBoardUserT[];
|
|
1112
1119
|
/** Current user's own entry. `undefined` for visitor sessions.
|
|
1113
1120
|
* For authenticated users, `position === -1` means the user is
|
|
@@ -1132,14 +1139,20 @@ export interface LeaderBoardsRewardsT {
|
|
|
1132
1139
|
export interface LeaderBoardUserT {
|
|
1133
1140
|
/** Display username (operator-defined alias). */
|
|
1134
1141
|
public_username: string;
|
|
1135
|
-
/** Resolved CDN URL for the participant's avatar.
|
|
1142
|
+
/** Resolved CDN URL for the participant's avatar. May be empty when the
|
|
1143
|
+
* participant has no custom avatar — fall back to a level-based default
|
|
1144
|
+
* using `level_id`. */
|
|
1136
1145
|
avatar_url: string;
|
|
1146
|
+
/** The participant's level id — use it to resolve a level-based default
|
|
1147
|
+
* avatar when `avatar_url` is empty. */
|
|
1148
|
+
level_id: number;
|
|
1137
1149
|
/** Rank in the leaderboard (DENSE_RANK over all participants).
|
|
1138
1150
|
* `-1` on the `me` entry signals "unranked / outside the window". */
|
|
1139
1151
|
position: number;
|
|
1140
1152
|
/** Participant's points for this period. */
|
|
1141
1153
|
points: number;
|
|
1142
|
-
/** `true` when this row is the current authenticated user.
|
|
1154
|
+
/** `true` when this row is the current authenticated user. Always `true`
|
|
1155
|
+
* on the `me` entry. */
|
|
1143
1156
|
is_me: boolean;
|
|
1144
1157
|
}
|
|
1145
1158
|
|