@smartico/public-api 0.0.434 → 0.0.436
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/dist/WSAPI/WSAPITypes.d.ts +2 -2
- package/dist/index.js +55 -49
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +46 -44
- package/dist/index.modern.mjs.map +1 -1
- package/docs/ui/minigames/UIGuide_getMiniGamesHistory.md +1 -1
- package/package.json +1 -1
- package/src/MiniGames/SAWGetTemplatesResponse.ts +20 -2
- package/src/Missions/MissionsUtils.ts +37 -47
- package/src/Missions/UserAchievement.ts +3 -3
- package/src/WSAPI/WSAPITypes.ts +2 -2
|
@@ -25,7 +25,7 @@ Fields rendered per row:
|
|
|
25
25
|
|---|---|---|
|
|
26
26
|
| Template icon | `template.thumbnail` (or similar) | 1:1 |
|
|
27
27
|
| Prize name | Look up `template.prizes[i]` by `saw_prize_id` | Display the prize's `name`. A spin finalised as lost (`miniGameWinAcknowledgeRequest` with `lose: true`) has no prize attached — render it as a loss. |
|
|
28
|
-
| Prize amount | `template.prizes[i].prize_value` or `prize_amount` | E.g. "100 points" |
|
|
28
|
+
| Prize amount | `template.prizes[i].prize_value` or `prize_amount`; for gems/diamonds prizes `prize_details_json.gems` / `.diamonds`, for raffle-ticket prizes `prize_details_json.tickets_count` | E.g. "100 points", "50 Diamonds". The history row carries the template as sent by the server, where `prize_value` of a gems/diamonds or raffle-ticket prize is only a default — `getMiniGames()` already resolves it into `prize_value` |
|
|
29
29
|
| Spin date | `create_date_ts` | Format as user-local relative time ("2h ago") or short date |
|
|
30
30
|
| Claim status | `is_claimed` | Show check-mark when true; "Pending claim" CTA when false |
|
|
31
31
|
| Acknowledge date | `acknowledge_date_ts` | Only when `is_claimed === true` |
|
package/package.json
CHANGED
|
@@ -6,13 +6,31 @@ import { SAWBuyInType, SAWBuyInTypeNamed } from './SAWBuyInType';
|
|
|
6
6
|
import { SAWExposeUserSpinIdNamed } from './SAWExposeUserSpinId';
|
|
7
7
|
import { SAWGameLayoutNamed } from './SAWGameLayout';
|
|
8
8
|
import { SAWGameType, SAWGameTypeNamed } from './SAWGameType';
|
|
9
|
-
import {
|
|
9
|
+
import { SAWPrize } from './SAWPrize';
|
|
10
|
+
import { MiniGamePrizeTypeNamed, SAWPrizeType } from './SAWPrizeType';
|
|
10
11
|
import { SAWTemplate } from './SAWTemplate';
|
|
11
12
|
|
|
12
13
|
export interface SAWGetTemplatesResponse extends ProtocolResponse {
|
|
13
14
|
templates: SAWTemplate[];
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
/**
|
|
18
|
+
* The amount a prize gives. Gems/diamonds and raffle-ticket prizes carry it in
|
|
19
|
+
* `prize_details_json` (their `prize_value` is only a default), the same way the
|
|
20
|
+
* default Smartico UI reads it; every other type keeps `prize_value`.
|
|
21
|
+
*/
|
|
22
|
+
const sawPrizeValue = (p: SAWPrize): number => {
|
|
23
|
+
const d = p.prize_details_json;
|
|
24
|
+
let n = 0;
|
|
25
|
+
if (p.prize_type_id === SAWPrizeType.GEMS_AND_DIAMONDS && d) {
|
|
26
|
+
// _gems_diamonds_type: 0 gems, 1 diamonds, 2 both
|
|
27
|
+
n = (d._gems_diamonds_type === 1 ? 0 : d.gems || 0) + (d._gems_diamonds_type === 0 ? 0 : d.diamonds || 0);
|
|
28
|
+
} else if (p.prize_type_id === SAWPrizeType.RAFFLE_TICKET && d) {
|
|
29
|
+
n = d.tickets_count || 0;
|
|
30
|
+
}
|
|
31
|
+
return n > 0 ? n : p.prize_value;
|
|
32
|
+
};
|
|
33
|
+
|
|
16
34
|
export const SAWTemplatesTransform = (items: SAWTemplate[]): TMiniGameTemplate[] => {
|
|
17
35
|
return items.map((r) => {
|
|
18
36
|
const x: TMiniGameTemplate = {
|
|
@@ -66,7 +84,7 @@ export const SAWTemplatesTransform = (items: SAWTemplate[]): TMiniGameTemplate[]
|
|
|
66
84
|
id: p.saw_prize_id,
|
|
67
85
|
name: p.saw_prize_ui_definition.name,
|
|
68
86
|
prize_type: MiniGamePrizeTypeNamed(p.prize_type_id),
|
|
69
|
-
prize_value: p
|
|
87
|
+
prize_value: sawPrizeValue(p),
|
|
70
88
|
font_size: p.saw_prize_ui_definition.font_size,
|
|
71
89
|
font_size_mobile: p.saw_prize_ui_definition.font_size_mobile,
|
|
72
90
|
icon: p.saw_prize_ui_definition.icon,
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
import { IntUtils } from "../IntUtils";
|
|
2
1
|
import { AchievementAvailabilityStatus } from "./AchievementAvailabilityStatus";
|
|
3
2
|
import { AchievementStatus } from "./AchievementStatus";
|
|
4
3
|
import { UserAchievement } from "./UserAchievement";
|
|
5
4
|
import { UserAchievementTask } from "./UserAchievementTask";
|
|
6
5
|
import { BadgesTimeLimitStates } from "./BadgesTimeLimitStates";
|
|
7
6
|
|
|
8
|
-
type UserStateParamsKeys =
|
|
9
|
-
|
|
7
|
+
type UserStateParamsKeys =
|
|
8
|
+
| 'core_fav_game_top3' | 'core_fav_game_type_top3' | 'core_fav_game_provider_top3'
|
|
9
|
+
| 'core_fav_sport_type_top3' | 'core_fav_sport_league_top3'
|
|
10
|
+
| 'core_recommended_deposit_amount' | 'core_recommended_casino_bet_amount' | 'core_recommended_sport_bet_amount';
|
|
11
|
+
|
|
12
|
+
// tag -> favorites (top 3 arrays) that fill it; a task has at most one condition per tag (enforced in the BO)
|
|
13
|
+
const FAV_TAGS: [string, UserStateParamsKeys[]][] = [
|
|
14
|
+
['{{suggested_games}}', ['core_fav_game_top3', 'core_fav_game_type_top3', 'core_fav_game_provider_top3']],
|
|
15
|
+
['{{suggested_sport}}', ['core_fav_sport_type_top3', 'core_fav_sport_league_top3']],
|
|
16
|
+
];
|
|
10
17
|
const USER_STATE_PARAMS_KEYS_BET_AMOUNT: UserStateParamsKeys[] = [
|
|
11
18
|
'core_recommended_deposit_amount',
|
|
12
19
|
'core_recommended_casino_bet_amount',
|
|
@@ -212,64 +219,47 @@ export class MissionUtils {
|
|
|
212
219
|
|
|
213
220
|
const userStateParams = (task.user_state_params || {});
|
|
214
221
|
const userStateOperator = task.task_public_meta?.user_state_operations;
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if (userStateParamsKeys.length === 0 || !userStateOperator) {
|
|
222
|
+
if (Object.keys(userStateParams).length === 0 || !userStateOperator) {
|
|
218
223
|
return result;
|
|
219
224
|
}
|
|
220
225
|
|
|
221
|
-
const
|
|
222
|
-
const operatorsPos = ['pos1', 'pos2', 'pos3'];
|
|
223
|
-
|
|
224
|
-
let suggestedGames: string = '';
|
|
225
|
-
let suggestedValue: string = '';
|
|
226
|
-
|
|
227
|
-
userStateParamsKeys.forEach((k: UserStateParamsKeys) => {
|
|
228
|
-
const operator = userStateOperator[k]?.op;
|
|
229
|
-
|
|
230
|
-
if (USER_STATE_PARAMS_KEYS_GAMES.includes(k)) {
|
|
231
|
-
if (operatorsMulti.includes(operator)) {
|
|
232
|
-
const value = userStateParams[k]?.filter(v => Boolean(v));
|
|
233
|
-
if (value && value.length > 0) {
|
|
234
|
-
suggestedGames = value.map((v: string) => {
|
|
235
|
-
const cleaned = v.replace(/_/g, ' ');
|
|
236
|
-
return toGameTitleCase(cleaned);
|
|
237
|
-
}).join(', ');
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (operatorsPos.includes(operator)) {
|
|
242
|
-
const value = userStateParams[k];
|
|
243
|
-
const pos = Number(operator.replace('pos', '')) - 1;
|
|
226
|
+
const formatFav = (v: string): string => toGameTitleCase(v.replace(/_/g, ' '));
|
|
244
227
|
|
|
245
|
-
|
|
246
|
-
|
|
228
|
+
// 'has' / '!has' -> all favorites, 'posN' -> the N-th one
|
|
229
|
+
const favValue = (k: UserStateParamsKeys): string => {
|
|
230
|
+
const values = userStateParams[k];
|
|
231
|
+
const operator: string = userStateOperator[k]?.op;
|
|
247
232
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
233
|
+
if (!Array.isArray(values)) {
|
|
234
|
+
return '';
|
|
235
|
+
}
|
|
251
236
|
|
|
252
|
-
|
|
253
|
-
|
|
237
|
+
if (operator === 'has' || operator === '!has') {
|
|
238
|
+
return values.filter(Boolean).map(formatFav).join(', ');
|
|
254
239
|
}
|
|
255
240
|
|
|
256
|
-
|
|
257
|
-
suggestedValue = userStateParams[k];
|
|
241
|
+
const pos = /^pos[1-3]$/.test(operator) ? values[Number(operator.substring(3)) - 1] : null;
|
|
258
242
|
|
|
259
|
-
|
|
260
|
-
|
|
243
|
+
return pos ? formatFav(pos) : '';
|
|
244
|
+
};
|
|
261
245
|
|
|
262
|
-
|
|
263
|
-
|
|
246
|
+
// split/join replaces every occurrence of the tag, not only the first one
|
|
247
|
+
const replaceTag = (tag: string, value: string) => {
|
|
248
|
+
if (value && result) {
|
|
249
|
+
result = result.split(tag).join(value);
|
|
264
250
|
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
FAV_TAGS.forEach(([tag, keys]) => {
|
|
254
|
+
replaceTag(tag, keys.map(favValue).find(Boolean));
|
|
265
255
|
});
|
|
266
256
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
257
|
+
const amountKey = USER_STATE_PARAMS_KEYS_BET_AMOUNT.find((k) => userStateParams[k]);
|
|
258
|
+
|
|
259
|
+
if (amountKey) {
|
|
260
|
+
const currencyFromTheTask = userStateParams.core_wallet_currency;
|
|
270
261
|
|
|
271
|
-
|
|
272
|
-
result = result.replace('{{suggested_value}}', suggestedValue);
|
|
262
|
+
replaceTag('{{suggested_value}}', `${userStateParams[amountKey]} ${currencySymbol || currencyFromTheTask || ''}`);
|
|
273
263
|
}
|
|
274
264
|
|
|
275
265
|
return result;
|
|
@@ -76,13 +76,13 @@ export const UserAchievementTransform = (items: UserAchievement[]): TMissionOrBa
|
|
|
76
76
|
if (missionName?.includes('{{suggested_') || missionSubHeader?.includes('{{suggested_') || missionDescription?.includes('{{suggested_')) {
|
|
77
77
|
r.achievementTasks.forEach(t => {
|
|
78
78
|
if (r.ach_public_meta.name?.includes('{{suggested_')) {
|
|
79
|
-
missionName = MissionUtils.replaceTagsFavMissionTask({ task: t, valueToReplace:
|
|
79
|
+
missionName = MissionUtils.replaceTagsFavMissionTask({ task: t, valueToReplace: missionName });
|
|
80
80
|
}
|
|
81
81
|
if (r.ach_public_meta.sub_header?.includes('{{suggested_')) {
|
|
82
|
-
missionSubHeader = MissionUtils.replaceTagsFavMissionTask({ task: t, valueToReplace:
|
|
82
|
+
missionSubHeader = MissionUtils.replaceTagsFavMissionTask({ task: t, valueToReplace: missionSubHeader });
|
|
83
83
|
}
|
|
84
84
|
if (r.ach_public_meta.description?.includes('{{suggested_')) {
|
|
85
|
-
missionDescription = MissionUtils.replaceTagsFavMissionTask({ task: t, valueToReplace:
|
|
85
|
+
missionDescription = MissionUtils.replaceTagsFavMissionTask({ task: t, valueToReplace: missionDescription });
|
|
86
86
|
}
|
|
87
87
|
});
|
|
88
88
|
}
|
package/src/WSAPI/WSAPITypes.ts
CHANGED
|
@@ -29,8 +29,8 @@ export interface TMiniGamePrize {
|
|
|
29
29
|
name: string;
|
|
30
30
|
/** The type of the prize — see {@link MiniGamePrizeTypeName} ('no-prize', 'points', 'gems-and-diamonds', 'spin', 'bonus', 'jackpot', 'raffle-ticket', 'mission', 'change-level', 'manual') */
|
|
31
31
|
prize_type: MiniGamePrizeTypeName;
|
|
32
|
-
/**
|
|
33
|
-
* For example for prize
|
|
32
|
+
/** Amount of the prize: points for 'points', attempts for 'spin', gems or diamonds for 'gems-and-diamonds' (their sum when the prize gives both), tickets for 'raffle-ticket'. Not relevant for other types.
|
|
33
|
+
* For example for prize '100 points' the prize_value will be 100, for '100 free spins' 100, for '50 Diamonds' 50.
|
|
34
34
|
*/
|
|
35
35
|
prize_value?: number;
|
|
36
36
|
/** Custom font size in px for rendering the prize name on the game surface (e.g. a wheel sector), desktop */
|