@pixels-online/pixels-client-js-sdk 1.17.0 → 1.18.0

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/index.js CHANGED
@@ -1921,6 +1921,8 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
1921
1921
  const claimMultiplier = shouldScale ? (playerOffer.claimedCount || 0) + 1 : 1;
1922
1922
  const conditionData = [];
1923
1923
  let isValid = true;
1924
+ let maxTotalClaimsFromScaling = Infinity;
1925
+ const updateMax = (limit) => (maxTotalClaimsFromScaling = Math.min(maxTotalClaimsFromScaling, limit));
1924
1926
  if (completionConditions?.context?.id) {
1925
1927
  const hasTrackedContext = completionTrackers?.context &&
1926
1928
  completionConditions.context.id === completionTrackers.context;
@@ -1937,17 +1939,22 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
1937
1939
  }
1938
1940
  else {
1939
1941
  if (isDisqualify)
1940
- return { isValid: false };
1942
+ return { isValid: false, availableClaimsNow: 0 };
1941
1943
  }
1942
1944
  }
1943
1945
  if (conditions?.buyItem) {
1944
- const scaledAmount = (conditions.buyItem.amount || 1) * claimMultiplier;
1945
- const isDisqualify = (completionTrackers?.buyItem || 0) < scaledAmount;
1946
+ const baseAmount = conditions.buyItem.amount || 1;
1947
+ const scaledAmount = baseAmount * claimMultiplier;
1948
+ const trackerValue = completionTrackers?.buyItem || 0;
1949
+ const isDisqualify = trackerValue < scaledAmount;
1950
+ if (shouldScale && baseAmount > 0) {
1951
+ updateMax(Math.floor(trackerValue / baseAmount));
1952
+ }
1946
1953
  if (addDetails) {
1947
1954
  conditionData.push({
1948
1955
  isMet: !isDisqualify,
1949
1956
  kind: 'buyItem',
1950
- trackerAmount: completionTrackers?.buyItem || 0,
1957
+ trackerAmount: trackerValue,
1951
1958
  text: `Buy ${scaledAmount} ${conditions.buyItem.name}`,
1952
1959
  });
1953
1960
  if (isDisqualify)
@@ -1955,17 +1962,22 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
1955
1962
  }
1956
1963
  else {
1957
1964
  if (isDisqualify)
1958
- return { isValid: false };
1965
+ return { isValid: false, availableClaimsNow: 0 };
1959
1966
  }
1960
1967
  }
1961
1968
  if (conditions?.spendCurrency) {
1962
- const scaledAmount = (conditions.spendCurrency.amount || 1) * claimMultiplier;
1963
- const isDisqualify = (completionTrackers?.spendCurrency || 0) < scaledAmount;
1969
+ const baseAmount = conditions.spendCurrency.amount || 1;
1970
+ const scaledAmount = baseAmount * claimMultiplier;
1971
+ const trackerValue = completionTrackers?.spendCurrency || 0;
1972
+ const isDisqualify = trackerValue < scaledAmount;
1973
+ if (shouldScale && baseAmount > 0) {
1974
+ updateMax(Math.floor(trackerValue / baseAmount));
1975
+ }
1964
1976
  if (addDetails) {
1965
1977
  conditionData.push({
1966
1978
  isMet: !isDisqualify,
1967
1979
  kind: 'spendCurrency',
1968
- trackerAmount: completionTrackers?.spendCurrency || 0,
1980
+ trackerAmount: trackerValue,
1969
1981
  text: `Spend ${scaledAmount} ${conditions.spendCurrency.name}`,
1970
1982
  });
1971
1983
  if (isDisqualify)
@@ -1973,17 +1985,22 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
1973
1985
  }
1974
1986
  else {
1975
1987
  if (isDisqualify)
1976
- return { isValid: false };
1988
+ return { isValid: false, availableClaimsNow: 0 };
1977
1989
  }
1978
1990
  }
1979
1991
  if (conditions?.depositCurrency) {
1980
- const scaledAmount = (conditions.depositCurrency.amount || 1) * claimMultiplier;
1981
- const isDisqualify = (completionTrackers?.depositCurrency || 0) < scaledAmount;
1992
+ const baseAmount = conditions.depositCurrency.amount || 1;
1993
+ const scaledAmount = baseAmount * claimMultiplier;
1994
+ const trackerValue = completionTrackers?.depositCurrency || 0;
1995
+ const isDisqualify = trackerValue < scaledAmount;
1996
+ if (shouldScale && baseAmount > 0) {
1997
+ updateMax(Math.floor(trackerValue / baseAmount));
1998
+ }
1982
1999
  if (addDetails) {
1983
2000
  conditionData.push({
1984
2001
  isMet: !isDisqualify,
1985
2002
  kind: 'depositCurrency',
1986
- trackerAmount: completionTrackers?.depositCurrency || 0,
2003
+ trackerAmount: trackerValue,
1987
2004
  text: `Deposit ${scaledAmount} ${conditions.depositCurrency.name}`,
1988
2005
  });
1989
2006
  if (isDisqualify)
@@ -1991,7 +2008,7 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
1991
2008
  }
1992
2009
  else {
1993
2010
  if (isDisqualify)
1994
- return { isValid: false };
2011
+ return { isValid: false, availableClaimsNow: 0 };
1995
2012
  }
1996
2013
  }
1997
2014
  if (conditions?.login) {
@@ -2008,7 +2025,7 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
2008
2025
  }
2009
2026
  else {
2010
2027
  if (!isMet)
2011
- return { isValid: false };
2028
+ return { isValid: false, availableClaimsNow: 0 };
2012
2029
  }
2013
2030
  }
2014
2031
  if (conditions?.loginStreak) {
@@ -2028,7 +2045,7 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
2028
2045
  }
2029
2046
  else {
2030
2047
  if (isDisqualify)
2031
- return { isValid: false };
2048
+ return { isValid: false, availableClaimsNow: 0 };
2032
2049
  }
2033
2050
  }
2034
2051
  if (conditions?.social) {
@@ -2050,6 +2067,17 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
2050
2067
  if (likes < minLikes || views < minViews || comments < minComments) {
2051
2068
  isDisqualify = true;
2052
2069
  }
2070
+ if (shouldScale && mode === 'accumulate' && hasContent) {
2071
+ const baseLikes = cSocial?.minLikes || 0;
2072
+ const baseViews = cSocial?.minViews || 0;
2073
+ const baseComments = cSocial?.minComments || 0;
2074
+ if (baseLikes > 0)
2075
+ updateMax(Math.floor(likes / baseLikes));
2076
+ if (baseViews > 0)
2077
+ updateMax(Math.floor(views / baseViews));
2078
+ if (baseComments > 0)
2079
+ updateMax(Math.floor(comments / baseComments));
2080
+ }
2053
2081
  if (addDetails) {
2054
2082
  const platformMap = {
2055
2083
  tiktok: 'TikTok',
@@ -2121,14 +2149,18 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
2121
2149
  }
2122
2150
  else {
2123
2151
  if (isDisqualify)
2124
- return { isValid: false };
2152
+ return { isValid: false, availableClaimsNow: 0 };
2125
2153
  }
2126
2154
  }
2127
2155
  // Linked completions - wait for N linked entities to complete
2128
2156
  if (conditions?.linkedCompletions?.min) {
2157
+ const baseMin = conditions.linkedCompletions.min;
2129
2158
  const currentCount = completionTrackers?.linkedCompletions || 0;
2130
- const scaledMin = conditions.linkedCompletions.min * claimMultiplier;
2159
+ const scaledMin = baseMin * claimMultiplier;
2131
2160
  const isDisqualify = currentCount < scaledMin;
2161
+ if (shouldScale && baseMin > 0) {
2162
+ updateMax(Math.floor(currentCount / baseMin));
2163
+ }
2132
2164
  if (addDetails) {
2133
2165
  conditionData.push({
2134
2166
  isMet: !isDisqualify,
@@ -2141,7 +2173,7 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
2141
2173
  }
2142
2174
  else {
2143
2175
  if (isDisqualify)
2144
- return { isValid: false };
2176
+ return { isValid: false, availableClaimsNow: 0 };
2145
2177
  }
2146
2178
  }
2147
2179
  if (conditions?.dynamicTracker?.conditions?.length) {
@@ -2151,6 +2183,13 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
2151
2183
  ...conditions.dynamicTracker,
2152
2184
  conditions: resolvedConditions,
2153
2185
  }, claimMultiplier);
2186
+ if (shouldScale) {
2187
+ const dynamicMax = getMaxClaimsForDynamicGroup(completionTrackers?.dynamicTracker || {}, {
2188
+ ...conditions.dynamicTracker,
2189
+ conditions: resolvedConditions,
2190
+ }, playerOffer.claimedCount || 0);
2191
+ updateMax(dynamicMax);
2192
+ }
2154
2193
  if (addDetails) {
2155
2194
  conditionData.push({
2156
2195
  isMet: dynamicResult,
@@ -2162,7 +2201,7 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
2162
2201
  }
2163
2202
  else {
2164
2203
  if (!dynamicResult)
2165
- return { isValid: false };
2204
+ return { isValid: false, availableClaimsNow: 0 };
2166
2205
  }
2167
2206
  }
2168
2207
  const r = meetsBaseConditions({
@@ -2173,9 +2212,18 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
2173
2212
  });
2174
2213
  isValid = isValid && r.isValid;
2175
2214
  conditionData.push(...(r.conditionData || []));
2176
- return { isValid, conditionData };
2177
- }
2178
- return { isValid: true, conditionData: [] };
2215
+ if (maxClaimCount && maxClaimCount > 0) {
2216
+ updateMax(maxClaimCount);
2217
+ }
2218
+ const claimedCount = playerOffer.claimedCount || 0;
2219
+ let availableClaimsNow = !isValid
2220
+ ? 0
2221
+ : maxTotalClaimsFromScaling === Infinity
2222
+ ? -1
2223
+ : Math.max(0, maxTotalClaimsFromScaling - claimedCount);
2224
+ return { isValid, conditionData, availableClaimsNow };
2225
+ }
2226
+ return { isValid: true, conditionData: [], availableClaimsNow: -1 };
2179
2227
  };
2180
2228
  /**
2181
2229
  * Checks if completion conditions were met before a specific expiry time.
@@ -2340,26 +2388,30 @@ function evaluateDynamicCondition(dynamicObj, cond, claimMultiplier = 1) {
2340
2388
  }
2341
2389
  }
2342
2390
  const compareTo = isNumber ? Number(cond.compareTo) : String(cond.compareTo);
2343
- switch (cond.operator) {
2344
- case '==':
2345
- return val === compareTo;
2346
- case '!=':
2347
- return val !== compareTo;
2348
- }
2349
2391
  if (isNumber && typeof compareTo === 'number') {
2392
+ const skipMultiplier = cond.operator === '==' || cond.operator === '!=';
2393
+ const scaledCompareTo = skipMultiplier ? compareTo : compareTo * claimMultiplier;
2350
2394
  switch (cond.operator) {
2395
+ case '==':
2396
+ return val === scaledCompareTo;
2397
+ case '!=':
2398
+ return val !== scaledCompareTo;
2351
2399
  case '>':
2352
- return val > compareTo * claimMultiplier;
2400
+ return val > scaledCompareTo;
2353
2401
  case '>=':
2354
- return val >= compareTo * claimMultiplier;
2402
+ return val >= scaledCompareTo;
2355
2403
  case '<':
2356
- return val < compareTo * claimMultiplier;
2404
+ return val < scaledCompareTo;
2357
2405
  case '<=':
2358
- return val <= compareTo * claimMultiplier;
2406
+ return val <= scaledCompareTo;
2359
2407
  }
2360
2408
  }
2361
2409
  else if (!isNumber && typeof compareTo === 'string') {
2362
2410
  switch (cond.operator) {
2411
+ case '==':
2412
+ return val === compareTo;
2413
+ case '!=':
2414
+ return val !== compareTo;
2363
2415
  case 'has':
2364
2416
  return val.includes(compareTo);
2365
2417
  case 'not_has':
@@ -2368,6 +2420,98 @@ function evaluateDynamicCondition(dynamicObj, cond, claimMultiplier = 1) {
2368
2420
  }
2369
2421
  return false;
2370
2422
  }
2423
+ /**
2424
+ * Calculates the maximum number of claims supported by a single dynamic condition.
2425
+ */
2426
+ function getMaxClaimsForDynamicCondition(dynamicObj, cond) {
2427
+ if (!dynamicObj)
2428
+ return 0;
2429
+ const val = dynamicObj[cond.key];
2430
+ if (val === undefined)
2431
+ return 0;
2432
+ if (typeof val === 'number') {
2433
+ const base = Number(cond.compareTo);
2434
+ if (isNaN(base)) {
2435
+ return evaluateDynamicCondition(dynamicObj, cond, 1) ? Infinity : 0;
2436
+ }
2437
+ switch (cond.operator) {
2438
+ case '>=':
2439
+ if (base === 0)
2440
+ return val >= 0 ? Infinity : 0;
2441
+ if (base < 0)
2442
+ return val >= base ? Infinity : 0;
2443
+ return Math.max(0, Math.floor(val / base));
2444
+ case '>':
2445
+ if (base === 0)
2446
+ return val > 0 ? Infinity : 0;
2447
+ if (base < 0)
2448
+ return val > base ? Infinity : 0;
2449
+ if (val <= 0)
2450
+ return 0;
2451
+ return Math.max(0, Math.ceil(val / base) - 1);
2452
+ case '==':
2453
+ return val === base ? Infinity : 0;
2454
+ case '!=':
2455
+ return val !== base ? Infinity : 0;
2456
+ case '<=':
2457
+ if (base === 0)
2458
+ return val <= 0 ? Infinity : 0;
2459
+ if (base > 0)
2460
+ return evaluateDynamicCondition(dynamicObj, cond, 1) ? Infinity : 0;
2461
+ if (val >= 0)
2462
+ return 0;
2463
+ return Math.max(0, Math.floor(val / base));
2464
+ case '<':
2465
+ if (base === 0)
2466
+ return val < 0 ? Infinity : 0;
2467
+ if (base > 0)
2468
+ return evaluateDynamicCondition(dynamicObj, cond, 1) ? Infinity : 0;
2469
+ if (val >= 0)
2470
+ return 0;
2471
+ return Math.max(0, Math.ceil(val / base) - 1);
2472
+ }
2473
+ }
2474
+ // we don't scale the rest, they are always true or always false
2475
+ return evaluateDynamicCondition(dynamicObj, cond, 1) ? Infinity : 0;
2476
+ }
2477
+ /**
2478
+ * Calculates the maximum number of claims supported by a group of dynamic conditions.
2479
+ */
2480
+ function getMaxClaimsForDynamicGroup(dynamicObj, dynamicGroup, currentClaimCount = 0) {
2481
+ const { conditions, links } = dynamicGroup;
2482
+ if (!conditions || conditions.length === 0)
2483
+ return Infinity;
2484
+ // AND only
2485
+ if (!links || links.length === 0 || links.every((l) => l === 'AND')) {
2486
+ let minClaims = Infinity;
2487
+ for (const cond of conditions) {
2488
+ const max = getMaxClaimsForDynamicCondition(dynamicObj, cond);
2489
+ if (max === 0)
2490
+ return 0;
2491
+ minClaims = Math.min(minClaims, max);
2492
+ }
2493
+ return minClaims;
2494
+ }
2495
+ // OR only
2496
+ if (links.every((l) => l === 'OR')) {
2497
+ let maxClaims = 0;
2498
+ for (const cond of conditions) {
2499
+ const max = getMaxClaimsForDynamicCondition(dynamicObj, cond);
2500
+ if (max === Infinity)
2501
+ return Infinity;
2502
+ maxClaims = Math.max(maxClaims, max);
2503
+ }
2504
+ return maxClaims;
2505
+ }
2506
+ // mixed:
2507
+ const maxIterations = 100;
2508
+ for (let n = currentClaimCount + 1; n <= currentClaimCount + maxIterations; n++) {
2509
+ if (!meetsDynamicConditions(dynamicObj, dynamicGroup, n)) {
2510
+ return n - 1;
2511
+ }
2512
+ }
2513
+ return currentClaimCount + maxIterations;
2514
+ }
2371
2515
  /**
2372
2516
  * Evaluates a group of dynamic conditions with logical links (AND, OR, AND NOT).
2373
2517
  * @param dynamicObj - The player's dynamic object with any key and string or number value.
@@ -2476,6 +2620,8 @@ exports.OfferStore = OfferStore;
2476
2620
  exports.OfferwallClient = OfferwallClient;
2477
2621
  exports.PlayerOfferStatuses = PlayerOfferStatuses;
2478
2622
  exports.SSEConnection = SSEConnection;
2623
+ exports.getMaxClaimsForDynamicCondition = getMaxClaimsForDynamicCondition;
2624
+ exports.getMaxClaimsForDynamicGroup = getMaxClaimsForDynamicGroup;
2479
2625
  exports.hasConditions = hasConditions;
2480
2626
  exports.meetsBaseConditions = meetsBaseConditions;
2481
2627
  exports.meetsClaimableConditions = meetsClaimableConditions;