@stackedapp/utils 1.17.2 → 1.17.4
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/conditions.js +109 -16
- package/package.json +3 -3
package/dist/conditions.js
CHANGED
|
@@ -16,6 +16,7 @@ const calculatePercent = (amount, goal, isMet) => {
|
|
|
16
16
|
}
|
|
17
17
|
return isMet ? 100 : 0;
|
|
18
18
|
};
|
|
19
|
+
const formatList = (items) => items.length === 2 ? items.join(' and ') : `${items.slice(0, -1).join(', ')}, and ${items.at(-1)}`;
|
|
19
20
|
const calculateDynamicConditionPercent = (dynamicObj, cond) => {
|
|
20
21
|
if (!dynamicObj)
|
|
21
22
|
return 0;
|
|
@@ -451,7 +452,7 @@ additionalData, }) => {
|
|
|
451
452
|
}
|
|
452
453
|
}
|
|
453
454
|
// Validate link count conditions
|
|
454
|
-
if (conditions?.links
|
|
455
|
+
if (conditions?.links) {
|
|
455
456
|
for (const [linkType, constraint] of Object.entries(conditions.links)) {
|
|
456
457
|
// linkType should always exist. and be default is none was specified
|
|
457
458
|
const linkCount = playerSnap.entityLinks?.filter((link) => (link.kind || exports.DEFAULT_ENTITY_KIND) === linkType).length || 0;
|
|
@@ -553,19 +554,30 @@ additionalData, }) => {
|
|
|
553
554
|
return { isValid: false, isComplete: false, percentCompleted: 0 };
|
|
554
555
|
}
|
|
555
556
|
}
|
|
556
|
-
if (conditions?.identifiers?.platforms?.length
|
|
557
|
+
if (conditions?.identifiers?.platforms?.length) {
|
|
557
558
|
const playerPlatforms = new Set(playerSnap.identifiers?.map((i) => i.platform.toLowerCase()) || []);
|
|
558
559
|
const isAndBehaviour = conditions.identifiers.behaviour === 'AND';
|
|
559
560
|
const platformsToCheck = conditions.identifiers.platforms;
|
|
560
561
|
let isMet;
|
|
561
562
|
let displayText;
|
|
563
|
+
const platformsMap = {
|
|
564
|
+
sms: 'SMS',
|
|
565
|
+
email: 'Email',
|
|
566
|
+
apple: 'Apple',
|
|
567
|
+
google: 'Google',
|
|
568
|
+
tiktok: 'TikTok',
|
|
569
|
+
};
|
|
570
|
+
const metAndPlatforms = platformsToCheck.filter((platform) => playerPlatforms.has(platform.toLowerCase()));
|
|
562
571
|
if (isAndBehaviour) {
|
|
563
|
-
isMet =
|
|
564
|
-
displayText =
|
|
572
|
+
isMet = metAndPlatforms.length === platformsToCheck.length;
|
|
573
|
+
displayText =
|
|
574
|
+
platformsToCheck.length > 1
|
|
575
|
+
? `Link your ${formatList(platformsToCheck.map((p) => platformsMap[p.toLowerCase()] ?? p))} accounts`
|
|
576
|
+
: `Link your ${platformsMap[platformsToCheck[0].toLowerCase()] ?? platformsToCheck[0]} account`;
|
|
565
577
|
}
|
|
566
578
|
else {
|
|
567
579
|
isMet = platformsToCheck.some((platform) => playerPlatforms.has(platform.toLowerCase()));
|
|
568
|
-
displayText = `Link any
|
|
580
|
+
displayText = `Link any of your ${formatList(platformsToCheck.map((p) => platformsMap[p.toLowerCase()] ?? p))} accounts`;
|
|
569
581
|
}
|
|
570
582
|
if (addDetails) {
|
|
571
583
|
conditionData.push({
|
|
@@ -573,7 +585,11 @@ additionalData, }) => {
|
|
|
573
585
|
kind: 'identifiers',
|
|
574
586
|
trackerAmount: isMet ? 1 : 0,
|
|
575
587
|
trackerGoal: 1,
|
|
576
|
-
percentCompleted:
|
|
588
|
+
percentCompleted: isAndBehaviour
|
|
589
|
+
? calculatePercent(metAndPlatforms.length, platformsToCheck.length, isMet)
|
|
590
|
+
: isMet
|
|
591
|
+
? 100
|
|
592
|
+
: 0,
|
|
577
593
|
text: displayText,
|
|
578
594
|
});
|
|
579
595
|
if (!isMet)
|
|
@@ -1155,24 +1171,101 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
1155
1171
|
// Evaluate contractInteractions completion trackers
|
|
1156
1172
|
if (conditions?.contractInteractions) {
|
|
1157
1173
|
for (const [conditionId, condition] of Object.entries(conditions.contractInteractions)) {
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
const
|
|
1161
|
-
const
|
|
1162
|
-
|
|
1163
|
-
|
|
1174
|
+
// Tracker now stores { amount: number, count: number }
|
|
1175
|
+
// Default to { amount: 0, count: 0 } if missing
|
|
1176
|
+
const rawTracker = completionTrackers?.contractInteractions?.[conditionId];
|
|
1177
|
+
const trackerData = rawTracker || { amount: 0, count: 0 };
|
|
1178
|
+
const trackerAmount = trackerData.amount || 0;
|
|
1179
|
+
const trackerCount = trackerData.count || 0;
|
|
1180
|
+
// Goals
|
|
1181
|
+
const minAmount = condition.minAmount ? condition.minAmount * claimMultiplier : 0;
|
|
1182
|
+
const maxAmount = condition.maxAmount ? condition.maxAmount * claimMultiplier : undefined;
|
|
1183
|
+
const minCount = condition.minCount ? condition.minCount * claimMultiplier : 0;
|
|
1184
|
+
const maxCount = condition.maxCount ? condition.maxCount * claimMultiplier : undefined;
|
|
1185
|
+
let isDisqualify = false;
|
|
1186
|
+
// Check Amounts
|
|
1187
|
+
if (shouldScale) {
|
|
1188
|
+
// If we have scaling (claimMultiplier), we handle max claims calculation differently
|
|
1189
|
+
// For now, assume standard validation
|
|
1190
|
+
}
|
|
1191
|
+
if (minAmount > 0 && trackerAmount < minAmount)
|
|
1192
|
+
isDisqualify = true;
|
|
1193
|
+
if (maxAmount !== undefined && trackerAmount > maxAmount)
|
|
1194
|
+
isDisqualify = true;
|
|
1195
|
+
// Check Counts
|
|
1196
|
+
if (minCount > 0 && trackerCount < minCount)
|
|
1197
|
+
isDisqualify = true;
|
|
1198
|
+
if (maxCount !== undefined && trackerCount > maxCount)
|
|
1199
|
+
isDisqualify = true;
|
|
1200
|
+
if (shouldScale) {
|
|
1201
|
+
// Update max claims based on whatever allows the FEWEST claims
|
|
1202
|
+
// e.g. if I have enough Amount for 3 claims but enough Count for 1 claim, I can only make 1 claim.
|
|
1203
|
+
const possibleClaimsByAmount = condition.minAmount
|
|
1204
|
+
? Math.floor(trackerAmount / condition.minAmount)
|
|
1205
|
+
: Number.MAX_SAFE_INTEGER;
|
|
1206
|
+
const possibleClaimsByCount = condition.minCount
|
|
1207
|
+
? Math.floor(trackerCount / condition.minCount)
|
|
1208
|
+
: Number.MAX_SAFE_INTEGER;
|
|
1209
|
+
const possibleClaims = Math.min(possibleClaimsByAmount, possibleClaimsByCount);
|
|
1210
|
+
// Only update if we have at least ANY requirement (Amount or Count)
|
|
1211
|
+
// If both minAmount and minCount are 0/undefined, this logic might be weird, but usually one is set.
|
|
1212
|
+
if (condition.minAmount || condition.minCount) {
|
|
1213
|
+
updateMax(possibleClaims);
|
|
1214
|
+
}
|
|
1164
1215
|
}
|
|
1165
1216
|
if (addDetails) {
|
|
1217
|
+
// Determine primary metric for progress display
|
|
1218
|
+
// If minAmount is set, use amount. Else use count.
|
|
1219
|
+
let current = trackerAmount;
|
|
1220
|
+
let goal = minAmount;
|
|
1221
|
+
let percent = 0;
|
|
1222
|
+
// If both are set, display percent based on the average of the two
|
|
1223
|
+
const hasMin = minAmount > 0 || minCount > 0;
|
|
1224
|
+
const hasMax = (maxAmount !== undefined && maxAmount > 0) || (maxCount !== undefined && maxCount > 0);
|
|
1225
|
+
if (!hasMin && hasMax) {
|
|
1226
|
+
// If only max is set: > 0 progress = 100%, else 0%
|
|
1227
|
+
const maxAmountSet = maxAmount !== undefined && maxAmount > 0;
|
|
1228
|
+
const maxCountSet = maxCount !== undefined && maxCount > 0;
|
|
1229
|
+
let pcts = [];
|
|
1230
|
+
if (maxAmountSet) {
|
|
1231
|
+
pcts.push(trackerAmount > 0 ? 100 : 0);
|
|
1232
|
+
}
|
|
1233
|
+
if (maxCountSet) {
|
|
1234
|
+
pcts.push(trackerCount > 0 ? 100 : 0);
|
|
1235
|
+
}
|
|
1236
|
+
if (pcts.length > 0) {
|
|
1237
|
+
percent = pcts.reduce((a, b) => a + b, 0) / pcts.length;
|
|
1238
|
+
}
|
|
1239
|
+
else {
|
|
1240
|
+
percent = 0;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
else if (minAmount > 0 && minCount > 0) {
|
|
1244
|
+
const pctAmount = calculatePercent(trackerAmount, minAmount, true); // clamp to 100
|
|
1245
|
+
const pctCount = calculatePercent(trackerCount, minCount, true);
|
|
1246
|
+
percent = (pctAmount + pctCount) / 2;
|
|
1247
|
+
}
|
|
1248
|
+
else if (minCount > 0) {
|
|
1249
|
+
current = trackerCount;
|
|
1250
|
+
goal = minCount;
|
|
1251
|
+
percent = calculatePercent(current, goal, !isDisqualify);
|
|
1252
|
+
}
|
|
1253
|
+
else {
|
|
1254
|
+
percent = calculatePercent(trackerAmount, minAmount || 0, !isDisqualify);
|
|
1255
|
+
}
|
|
1166
1256
|
const displayText = (0, template_1.renderTemplate)(condition.template, {
|
|
1167
|
-
|
|
1168
|
-
|
|
1257
|
+
currentAmount: trackerAmount || 0,
|
|
1258
|
+
currentCount: trackerCount || 0,
|
|
1259
|
+
minAmount: minAmount || 0,
|
|
1260
|
+
maxAmount: maxAmount || 0,
|
|
1261
|
+
minCount: minCount || 0,
|
|
1262
|
+
maxCount: maxCount || 0,
|
|
1169
1263
|
});
|
|
1170
1264
|
conditionData.push({
|
|
1171
1265
|
isMet: !isDisqualify,
|
|
1172
1266
|
kind: 'contractInteractions',
|
|
1173
1267
|
trackerAmount,
|
|
1174
|
-
|
|
1175
|
-
percentCompleted: calculatePercent(trackerAmount, trackerGoal, !isDisqualify),
|
|
1268
|
+
percentCompleted: percent,
|
|
1176
1269
|
text: displayText,
|
|
1177
1270
|
});
|
|
1178
1271
|
if (isDisqualify)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackedapp/utils",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.4",
|
|
4
4
|
"description": "Public utilities for Stacked platform SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"license": "ISC",
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
26
|
-
"@semantic-release/gitlab": "^13.
|
|
27
|
-
"@semantic-release/npm": "^13.1.
|
|
26
|
+
"@semantic-release/gitlab": "^13.3.0",
|
|
27
|
+
"@semantic-release/npm": "^13.1.4",
|
|
28
28
|
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
29
29
|
"conventional-changelog-conventionalcommits": "^9.1.0"
|
|
30
30
|
}
|