@pixels-online/pixels-client-js-sdk 1.17.0 → 1.19.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/core/OfferStore.d.ts +20 -14
- package/dist/core/OfferwallClient.d.ts +6 -4
- package/dist/index.esm.js +265 -78
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +266 -77
- package/dist/index.js.map +1 -1
- package/dist/offerwall-sdk.umd.js +266 -77
- package/dist/offerwall-sdk.umd.js.map +1 -1
- package/dist/utils/conditions.d.ts +13 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -630,25 +630,33 @@ class SSEConnection {
|
|
|
630
630
|
}
|
|
631
631
|
|
|
632
632
|
class OfferStore {
|
|
633
|
-
constructor(config) {
|
|
633
|
+
constructor(config, client) {
|
|
634
|
+
this.client = client;
|
|
634
635
|
this.offers = new Map();
|
|
635
|
-
this.
|
|
636
|
+
this.players = new Map();
|
|
636
637
|
this.logger = createLogger(config, 'OfferStore');
|
|
637
638
|
}
|
|
638
|
-
getPlayer() {
|
|
639
|
-
|
|
639
|
+
getPlayer(targetId = this.client.getSelfId()) {
|
|
640
|
+
if (!targetId)
|
|
641
|
+
return null;
|
|
642
|
+
return this.players.get(targetId) || null;
|
|
640
643
|
}
|
|
641
644
|
setPlayer(player) {
|
|
642
|
-
this.player
|
|
645
|
+
this.players.set(player.snapshot.playerId, player);
|
|
643
646
|
this.logger.log('Updated player:', player);
|
|
644
647
|
}
|
|
645
648
|
/**
|
|
646
649
|
* Set all offers (replaces existing)
|
|
647
650
|
*/
|
|
648
|
-
setOffers(offers) {
|
|
649
|
-
this.
|
|
651
|
+
setOffers(offers, target) {
|
|
652
|
+
const targetPlayer = target || this.getPlayer();
|
|
653
|
+
if (!targetPlayer) {
|
|
654
|
+
this.logger.warn('No target player to set offers for');
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
this.offers.set(targetPlayer.snapshot.playerId, new Map());
|
|
650
658
|
offers.forEach((offer) => {
|
|
651
|
-
this.offers.set(offer.instanceId, offer);
|
|
659
|
+
this.offers.get(targetPlayer.snapshot.playerId).set(offer.instanceId, offer);
|
|
652
660
|
});
|
|
653
661
|
this.logger.log(`Set ${offers.length} offers`);
|
|
654
662
|
}
|
|
@@ -656,16 +664,23 @@ class OfferStore {
|
|
|
656
664
|
* Add or update a single offer
|
|
657
665
|
*/
|
|
658
666
|
upsertOffer(offer) {
|
|
659
|
-
|
|
660
|
-
|
|
667
|
+
let playerOffers = this.offers.get(offer.playerId);
|
|
668
|
+
if (!playerOffers) {
|
|
669
|
+
playerOffers = new Map();
|
|
670
|
+
this.offers.set(offer.playerId, playerOffers);
|
|
671
|
+
}
|
|
672
|
+
const previousOffer = playerOffers.get(offer.instanceId);
|
|
673
|
+
playerOffers.set(offer.instanceId, offer);
|
|
661
674
|
this.logger.log(`${previousOffer ? 'Updated' : 'Added'} offer:`, offer.instanceId);
|
|
662
675
|
return previousOffer;
|
|
663
676
|
}
|
|
664
677
|
/**
|
|
665
678
|
* Remove an offer
|
|
666
679
|
*/
|
|
667
|
-
removeOffer(offerId) {
|
|
668
|
-
|
|
680
|
+
removeOffer(offerId, targetId = this.client.getSelfId()) {
|
|
681
|
+
if (!targetId)
|
|
682
|
+
return false;
|
|
683
|
+
const removed = this.offers.get(targetId)?.delete(offerId) || false;
|
|
669
684
|
if (removed) {
|
|
670
685
|
this.logger.log(`Removed offer:`, offerId);
|
|
671
686
|
}
|
|
@@ -674,26 +689,30 @@ class OfferStore {
|
|
|
674
689
|
/**
|
|
675
690
|
* Get a single offer
|
|
676
691
|
*/
|
|
677
|
-
getOffer(offerId) {
|
|
678
|
-
|
|
692
|
+
getOffer(offerId, targetId = this.client.getSelfId()) {
|
|
693
|
+
if (!targetId)
|
|
694
|
+
return undefined;
|
|
695
|
+
return this.offers.get(targetId)?.get(offerId);
|
|
679
696
|
}
|
|
680
697
|
/**
|
|
681
698
|
* Get all offers
|
|
682
699
|
*/
|
|
683
|
-
getAllOffers() {
|
|
684
|
-
|
|
700
|
+
getAllOffers(targetId = this.client.getSelfId()) {
|
|
701
|
+
if (!targetId)
|
|
702
|
+
return [];
|
|
703
|
+
return Array.from(this.offers.get(targetId)?.values() || []);
|
|
685
704
|
}
|
|
686
705
|
/**
|
|
687
706
|
* Get offers filtered by status
|
|
688
707
|
*/
|
|
689
|
-
getOffersByStatus(status) {
|
|
690
|
-
return this.getAllOffers().filter((offer) => offer.status === status);
|
|
708
|
+
getOffersByStatus(status, targetId = this.client.getSelfId()) {
|
|
709
|
+
return this.getAllOffers(targetId).filter((offer) => offer.status === status);
|
|
691
710
|
}
|
|
692
711
|
/**
|
|
693
712
|
* Get active offers (not expired, not claimed)
|
|
694
713
|
*/
|
|
695
|
-
getActiveOffers() {
|
|
696
|
-
return this.getAllOffers().filter((offer) => {
|
|
714
|
+
getActiveOffers(targetId = this.client.getSelfId()) {
|
|
715
|
+
return this.getAllOffers(targetId).filter((offer) => {
|
|
697
716
|
if (!offer.status)
|
|
698
717
|
return false; // Must have a status
|
|
699
718
|
return (offer.status === 'surfaced' ||
|
|
@@ -704,14 +723,14 @@ class OfferStore {
|
|
|
704
723
|
/**
|
|
705
724
|
* Get claimable offers
|
|
706
725
|
*/
|
|
707
|
-
getClaimableOffers() {
|
|
708
|
-
return this.getOffersByStatus('claimable');
|
|
726
|
+
getClaimableOffers(targetId = this.client.getSelfId()) {
|
|
727
|
+
return this.getOffersByStatus('claimable', targetId);
|
|
709
728
|
}
|
|
710
729
|
/**
|
|
711
730
|
* Check if an offer has expired
|
|
712
731
|
*/
|
|
713
|
-
isOfferExpired(offerId) {
|
|
714
|
-
const offer = this.getOffer(offerId);
|
|
732
|
+
isOfferExpired(offerId, targetId = this.client.getSelfId()) {
|
|
733
|
+
const offer = this.getOffer(offerId, targetId);
|
|
715
734
|
if (!offer)
|
|
716
735
|
return true;
|
|
717
736
|
// Check status
|
|
@@ -724,17 +743,29 @@ class OfferStore {
|
|
|
724
743
|
return false;
|
|
725
744
|
}
|
|
726
745
|
/**
|
|
727
|
-
* Clear all offers
|
|
746
|
+
* Clear all offers for a specific player
|
|
728
747
|
*/
|
|
729
|
-
clear() {
|
|
748
|
+
clear(targetId = this.client.getSelfId()) {
|
|
749
|
+
if (!targetId)
|
|
750
|
+
return;
|
|
751
|
+
this.offers.set(targetId, new Map());
|
|
752
|
+
this.logger.log('Cleared all offers for player:', targetId);
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Clear all offers for all players
|
|
756
|
+
*/
|
|
757
|
+
clearAll() {
|
|
730
758
|
this.offers.clear();
|
|
731
|
-
this.logger.log('Cleared all offers');
|
|
759
|
+
this.logger.log('Cleared all offers for all players');
|
|
732
760
|
}
|
|
733
761
|
/**
|
|
734
|
-
* Get offer count
|
|
762
|
+
* Get offer count (for self player)
|
|
735
763
|
*/
|
|
736
764
|
get size() {
|
|
737
|
-
|
|
765
|
+
const selfId = this.client.getSelfId();
|
|
766
|
+
if (!selfId)
|
|
767
|
+
return 0;
|
|
768
|
+
return this.offers.get(selfId)?.size || 0;
|
|
738
769
|
}
|
|
739
770
|
}
|
|
740
771
|
|
|
@@ -837,7 +868,9 @@ class AssetHelper {
|
|
|
837
868
|
return null;
|
|
838
869
|
}
|
|
839
870
|
setCurrencyAssetContents(currencies) {
|
|
840
|
-
|
|
871
|
+
Object.keys(currencies).forEach((key) => {
|
|
872
|
+
this.currencies[key] = currencies[key];
|
|
873
|
+
});
|
|
841
874
|
}
|
|
842
875
|
resolveReward(reward) {
|
|
843
876
|
if (reward.kind === 'loyalty_currency' && reward.rewardId) {
|
|
@@ -893,6 +926,7 @@ class OfferwallClient {
|
|
|
893
926
|
constructor(config) {
|
|
894
927
|
this.isInitializing = false;
|
|
895
928
|
this.pendingStackedToken = null;
|
|
929
|
+
this.selfId = null;
|
|
896
930
|
this.config = {
|
|
897
931
|
autoConnect: config.autoConnect ?? false,
|
|
898
932
|
reconnect: config.reconnect ?? true,
|
|
@@ -905,7 +939,7 @@ class OfferwallClient {
|
|
|
905
939
|
this.hooks = this.config.hooks || {};
|
|
906
940
|
this.logger = createLogger(this.config, 'OfferwallClient');
|
|
907
941
|
this.eventEmitter = new EventEmitter(this.config);
|
|
908
|
-
this.offerStore = new OfferStore(this.config);
|
|
942
|
+
this.offerStore = new OfferStore(this.config, this);
|
|
909
943
|
this.tokenManager = new TokenManager(this.config);
|
|
910
944
|
this.assetHelper = new AssetHelper(this.config);
|
|
911
945
|
this.sseConnection = new SSEConnection(this.config, this.eventEmitter, this.tokenManager);
|
|
@@ -946,6 +980,9 @@ class OfferwallClient {
|
|
|
946
980
|
get assets() {
|
|
947
981
|
return this.assetHelper;
|
|
948
982
|
}
|
|
983
|
+
getSelfId() {
|
|
984
|
+
return this.selfId;
|
|
985
|
+
}
|
|
949
986
|
/**
|
|
950
987
|
* Initialize the offerwall client and connect
|
|
951
988
|
*/
|
|
@@ -1008,8 +1045,9 @@ class OfferwallClient {
|
|
|
1008
1045
|
if (this.sseConnection) {
|
|
1009
1046
|
this.sseConnection.disconnect();
|
|
1010
1047
|
}
|
|
1011
|
-
this.offerStore.
|
|
1048
|
+
this.offerStore.clearAll();
|
|
1012
1049
|
this.tokenManager.clearToken();
|
|
1050
|
+
this.selfId = null;
|
|
1013
1051
|
if (this.hooks.afterDisconnect) {
|
|
1014
1052
|
await this.hooks.afterDisconnect();
|
|
1015
1053
|
}
|
|
@@ -1017,8 +1055,8 @@ class OfferwallClient {
|
|
|
1017
1055
|
/**
|
|
1018
1056
|
* Claim rewards for an offer
|
|
1019
1057
|
*/
|
|
1020
|
-
async claimReward(instanceId) {
|
|
1021
|
-
const offer = this.offerStore.getOffer(instanceId);
|
|
1058
|
+
async claimReward(instanceId, targetId = this.getSelfId()) {
|
|
1059
|
+
const offer = this.offerStore.getOffer(instanceId, targetId);
|
|
1022
1060
|
if (!offer) {
|
|
1023
1061
|
throw new Error(`Offer ${instanceId} not found`);
|
|
1024
1062
|
}
|
|
@@ -1033,7 +1071,7 @@ class OfferwallClient {
|
|
|
1033
1071
|
}
|
|
1034
1072
|
}
|
|
1035
1073
|
try {
|
|
1036
|
-
const response = await this.claimOfferAPI(instanceId);
|
|
1074
|
+
const response = await this.claimOfferAPI(instanceId, targetId);
|
|
1037
1075
|
const updatedOffer = { ...offer, status: 'claimed' };
|
|
1038
1076
|
this.offerStore.upsertOffer(updatedOffer);
|
|
1039
1077
|
this.eventEmitter.emit(exports.OfferEvent.OFFER_CLAIMED, {
|
|
@@ -1089,7 +1127,7 @@ class OfferwallClient {
|
|
|
1089
1127
|
});
|
|
1090
1128
|
*/
|
|
1091
1129
|
this.eventEmitter.on(exports.OfferEvent.OFFER_SURFACED, ({ offer }) => {
|
|
1092
|
-
this.offerStore.upsertOffer(offer);
|
|
1130
|
+
this.offerStore.upsertOffer(offer); // should always be selfId
|
|
1093
1131
|
this.logger.log(`Surfaced offer: ${offer.instanceId}`);
|
|
1094
1132
|
});
|
|
1095
1133
|
}
|
|
@@ -1119,23 +1157,27 @@ class OfferwallClient {
|
|
|
1119
1157
|
}
|
|
1120
1158
|
return response.json();
|
|
1121
1159
|
}
|
|
1122
|
-
async claimOfferAPI(instanceId) {
|
|
1160
|
+
async claimOfferAPI(instanceId, targetId = null) {
|
|
1123
1161
|
return this.postWithAuth('/v1/client/reward/claim', {
|
|
1124
1162
|
instanceId,
|
|
1125
1163
|
kind: 'offer',
|
|
1164
|
+
targetId: targetId || undefined,
|
|
1126
1165
|
});
|
|
1127
1166
|
}
|
|
1128
|
-
getPlayer() {
|
|
1129
|
-
return this.offerStore.getPlayer();
|
|
1167
|
+
getPlayer(targetId = this.getSelfId()) {
|
|
1168
|
+
return this.offerStore.getPlayer(targetId);
|
|
1130
1169
|
}
|
|
1131
|
-
getOffers() {
|
|
1132
|
-
return this.offerStore.getAllOffers();
|
|
1170
|
+
getOffers(targetId = this.getSelfId()) {
|
|
1171
|
+
return this.offerStore.getAllOffers(targetId);
|
|
1133
1172
|
}
|
|
1134
|
-
async refreshOffersAndPlayer() {
|
|
1173
|
+
async refreshOffersAndPlayer(targetId = null) {
|
|
1135
1174
|
try {
|
|
1136
|
-
const { offers, player } = await this.getOffersAndPlayer();
|
|
1137
|
-
|
|
1175
|
+
const { offers, player } = await this.getOffersAndPlayer(targetId);
|
|
1176
|
+
if (targetId == null) {
|
|
1177
|
+
this.selfId = player.snapshot.playerId;
|
|
1178
|
+
}
|
|
1138
1179
|
this.offerStore.setPlayer(player);
|
|
1180
|
+
this.offerStore.setOffers(offers, player);
|
|
1139
1181
|
this.eventEmitter.emit(exports.OfferEvent.REFRESH, { offers, player: player });
|
|
1140
1182
|
this.logger.log('Refreshed offers and player snapshot');
|
|
1141
1183
|
}
|
|
@@ -1144,9 +1186,10 @@ class OfferwallClient {
|
|
|
1144
1186
|
throw error;
|
|
1145
1187
|
}
|
|
1146
1188
|
}
|
|
1147
|
-
async getOffersAndPlayer() {
|
|
1189
|
+
async getOffersAndPlayer(targetId = null) {
|
|
1148
1190
|
const data = await this.postWithAuth('/v1/client/player/campaigns', {
|
|
1149
1191
|
viewingCampaigns: true,
|
|
1192
|
+
targetId: targetId || undefined,
|
|
1150
1193
|
});
|
|
1151
1194
|
if (!data.offers || !Array.isArray(data.offers)) {
|
|
1152
1195
|
throw new Error('No offers returned from offers endpoint');
|
|
@@ -1921,6 +1964,8 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
1921
1964
|
const claimMultiplier = shouldScale ? (playerOffer.claimedCount || 0) + 1 : 1;
|
|
1922
1965
|
const conditionData = [];
|
|
1923
1966
|
let isValid = true;
|
|
1967
|
+
let maxTotalClaimsFromScaling = Infinity;
|
|
1968
|
+
const updateMax = (limit) => (maxTotalClaimsFromScaling = Math.min(maxTotalClaimsFromScaling, limit));
|
|
1924
1969
|
if (completionConditions?.context?.id) {
|
|
1925
1970
|
const hasTrackedContext = completionTrackers?.context &&
|
|
1926
1971
|
completionConditions.context.id === completionTrackers.context;
|
|
@@ -1937,17 +1982,22 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
1937
1982
|
}
|
|
1938
1983
|
else {
|
|
1939
1984
|
if (isDisqualify)
|
|
1940
|
-
return { isValid: false };
|
|
1985
|
+
return { isValid: false, availableClaimsNow: 0 };
|
|
1941
1986
|
}
|
|
1942
1987
|
}
|
|
1943
1988
|
if (conditions?.buyItem) {
|
|
1944
|
-
const
|
|
1945
|
-
const
|
|
1989
|
+
const baseAmount = conditions.buyItem.amount || 1;
|
|
1990
|
+
const scaledAmount = baseAmount * claimMultiplier;
|
|
1991
|
+
const trackerValue = completionTrackers?.buyItem || 0;
|
|
1992
|
+
const isDisqualify = trackerValue < scaledAmount;
|
|
1993
|
+
if (shouldScale && baseAmount > 0) {
|
|
1994
|
+
updateMax(Math.floor(trackerValue / baseAmount));
|
|
1995
|
+
}
|
|
1946
1996
|
if (addDetails) {
|
|
1947
1997
|
conditionData.push({
|
|
1948
1998
|
isMet: !isDisqualify,
|
|
1949
1999
|
kind: 'buyItem',
|
|
1950
|
-
trackerAmount:
|
|
2000
|
+
trackerAmount: trackerValue,
|
|
1951
2001
|
text: `Buy ${scaledAmount} ${conditions.buyItem.name}`,
|
|
1952
2002
|
});
|
|
1953
2003
|
if (isDisqualify)
|
|
@@ -1955,17 +2005,22 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
1955
2005
|
}
|
|
1956
2006
|
else {
|
|
1957
2007
|
if (isDisqualify)
|
|
1958
|
-
return { isValid: false };
|
|
2008
|
+
return { isValid: false, availableClaimsNow: 0 };
|
|
1959
2009
|
}
|
|
1960
2010
|
}
|
|
1961
2011
|
if (conditions?.spendCurrency) {
|
|
1962
|
-
const
|
|
1963
|
-
const
|
|
2012
|
+
const baseAmount = conditions.spendCurrency.amount || 1;
|
|
2013
|
+
const scaledAmount = baseAmount * claimMultiplier;
|
|
2014
|
+
const trackerValue = completionTrackers?.spendCurrency || 0;
|
|
2015
|
+
const isDisqualify = trackerValue < scaledAmount;
|
|
2016
|
+
if (shouldScale && baseAmount > 0) {
|
|
2017
|
+
updateMax(Math.floor(trackerValue / baseAmount));
|
|
2018
|
+
}
|
|
1964
2019
|
if (addDetails) {
|
|
1965
2020
|
conditionData.push({
|
|
1966
2021
|
isMet: !isDisqualify,
|
|
1967
2022
|
kind: 'spendCurrency',
|
|
1968
|
-
trackerAmount:
|
|
2023
|
+
trackerAmount: trackerValue,
|
|
1969
2024
|
text: `Spend ${scaledAmount} ${conditions.spendCurrency.name}`,
|
|
1970
2025
|
});
|
|
1971
2026
|
if (isDisqualify)
|
|
@@ -1973,17 +2028,22 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
1973
2028
|
}
|
|
1974
2029
|
else {
|
|
1975
2030
|
if (isDisqualify)
|
|
1976
|
-
return { isValid: false };
|
|
2031
|
+
return { isValid: false, availableClaimsNow: 0 };
|
|
1977
2032
|
}
|
|
1978
2033
|
}
|
|
1979
2034
|
if (conditions?.depositCurrency) {
|
|
1980
|
-
const
|
|
1981
|
-
const
|
|
2035
|
+
const baseAmount = conditions.depositCurrency.amount || 1;
|
|
2036
|
+
const scaledAmount = baseAmount * claimMultiplier;
|
|
2037
|
+
const trackerValue = completionTrackers?.depositCurrency || 0;
|
|
2038
|
+
const isDisqualify = trackerValue < scaledAmount;
|
|
2039
|
+
if (shouldScale && baseAmount > 0) {
|
|
2040
|
+
updateMax(Math.floor(trackerValue / baseAmount));
|
|
2041
|
+
}
|
|
1982
2042
|
if (addDetails) {
|
|
1983
2043
|
conditionData.push({
|
|
1984
2044
|
isMet: !isDisqualify,
|
|
1985
2045
|
kind: 'depositCurrency',
|
|
1986
|
-
trackerAmount:
|
|
2046
|
+
trackerAmount: trackerValue,
|
|
1987
2047
|
text: `Deposit ${scaledAmount} ${conditions.depositCurrency.name}`,
|
|
1988
2048
|
});
|
|
1989
2049
|
if (isDisqualify)
|
|
@@ -1991,7 +2051,7 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
1991
2051
|
}
|
|
1992
2052
|
else {
|
|
1993
2053
|
if (isDisqualify)
|
|
1994
|
-
return { isValid: false };
|
|
2054
|
+
return { isValid: false, availableClaimsNow: 0 };
|
|
1995
2055
|
}
|
|
1996
2056
|
}
|
|
1997
2057
|
if (conditions?.login) {
|
|
@@ -2008,7 +2068,7 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
2008
2068
|
}
|
|
2009
2069
|
else {
|
|
2010
2070
|
if (!isMet)
|
|
2011
|
-
return { isValid: false };
|
|
2071
|
+
return { isValid: false, availableClaimsNow: 0 };
|
|
2012
2072
|
}
|
|
2013
2073
|
}
|
|
2014
2074
|
if (conditions?.loginStreak) {
|
|
@@ -2028,7 +2088,7 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
2028
2088
|
}
|
|
2029
2089
|
else {
|
|
2030
2090
|
if (isDisqualify)
|
|
2031
|
-
return { isValid: false };
|
|
2091
|
+
return { isValid: false, availableClaimsNow: 0 };
|
|
2032
2092
|
}
|
|
2033
2093
|
}
|
|
2034
2094
|
if (conditions?.social) {
|
|
@@ -2050,6 +2110,17 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
2050
2110
|
if (likes < minLikes || views < minViews || comments < minComments) {
|
|
2051
2111
|
isDisqualify = true;
|
|
2052
2112
|
}
|
|
2113
|
+
if (shouldScale && mode === 'accumulate' && hasContent) {
|
|
2114
|
+
const baseLikes = cSocial?.minLikes || 0;
|
|
2115
|
+
const baseViews = cSocial?.minViews || 0;
|
|
2116
|
+
const baseComments = cSocial?.minComments || 0;
|
|
2117
|
+
if (baseLikes > 0)
|
|
2118
|
+
updateMax(Math.floor(likes / baseLikes));
|
|
2119
|
+
if (baseViews > 0)
|
|
2120
|
+
updateMax(Math.floor(views / baseViews));
|
|
2121
|
+
if (baseComments > 0)
|
|
2122
|
+
updateMax(Math.floor(comments / baseComments));
|
|
2123
|
+
}
|
|
2053
2124
|
if (addDetails) {
|
|
2054
2125
|
const platformMap = {
|
|
2055
2126
|
tiktok: 'TikTok',
|
|
@@ -2121,14 +2192,18 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
2121
2192
|
}
|
|
2122
2193
|
else {
|
|
2123
2194
|
if (isDisqualify)
|
|
2124
|
-
return { isValid: false };
|
|
2195
|
+
return { isValid: false, availableClaimsNow: 0 };
|
|
2125
2196
|
}
|
|
2126
2197
|
}
|
|
2127
2198
|
// Linked completions - wait for N linked entities to complete
|
|
2128
2199
|
if (conditions?.linkedCompletions?.min) {
|
|
2200
|
+
const baseMin = conditions.linkedCompletions.min;
|
|
2129
2201
|
const currentCount = completionTrackers?.linkedCompletions || 0;
|
|
2130
|
-
const scaledMin =
|
|
2202
|
+
const scaledMin = baseMin * claimMultiplier;
|
|
2131
2203
|
const isDisqualify = currentCount < scaledMin;
|
|
2204
|
+
if (shouldScale && baseMin > 0) {
|
|
2205
|
+
updateMax(Math.floor(currentCount / baseMin));
|
|
2206
|
+
}
|
|
2132
2207
|
if (addDetails) {
|
|
2133
2208
|
conditionData.push({
|
|
2134
2209
|
isMet: !isDisqualify,
|
|
@@ -2141,7 +2216,7 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
2141
2216
|
}
|
|
2142
2217
|
else {
|
|
2143
2218
|
if (isDisqualify)
|
|
2144
|
-
return { isValid: false };
|
|
2219
|
+
return { isValid: false, availableClaimsNow: 0 };
|
|
2145
2220
|
}
|
|
2146
2221
|
}
|
|
2147
2222
|
if (conditions?.dynamicTracker?.conditions?.length) {
|
|
@@ -2151,6 +2226,13 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
2151
2226
|
...conditions.dynamicTracker,
|
|
2152
2227
|
conditions: resolvedConditions,
|
|
2153
2228
|
}, claimMultiplier);
|
|
2229
|
+
if (shouldScale) {
|
|
2230
|
+
const dynamicMax = getMaxClaimsForDynamicGroup(completionTrackers?.dynamicTracker || {}, {
|
|
2231
|
+
...conditions.dynamicTracker,
|
|
2232
|
+
conditions: resolvedConditions,
|
|
2233
|
+
}, playerOffer.claimedCount || 0);
|
|
2234
|
+
updateMax(dynamicMax);
|
|
2235
|
+
}
|
|
2154
2236
|
if (addDetails) {
|
|
2155
2237
|
conditionData.push({
|
|
2156
2238
|
isMet: dynamicResult,
|
|
@@ -2162,7 +2244,7 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
2162
2244
|
}
|
|
2163
2245
|
else {
|
|
2164
2246
|
if (!dynamicResult)
|
|
2165
|
-
return { isValid: false };
|
|
2247
|
+
return { isValid: false, availableClaimsNow: 0 };
|
|
2166
2248
|
}
|
|
2167
2249
|
}
|
|
2168
2250
|
const r = meetsBaseConditions({
|
|
@@ -2173,9 +2255,18 @@ const meetsCompletionConditions = ({ completionConditions, completionTrackers, p
|
|
|
2173
2255
|
});
|
|
2174
2256
|
isValid = isValid && r.isValid;
|
|
2175
2257
|
conditionData.push(...(r.conditionData || []));
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2258
|
+
if (maxClaimCount && maxClaimCount > 0) {
|
|
2259
|
+
updateMax(maxClaimCount);
|
|
2260
|
+
}
|
|
2261
|
+
const claimedCount = playerOffer.claimedCount || 0;
|
|
2262
|
+
let availableClaimsNow = !isValid
|
|
2263
|
+
? 0
|
|
2264
|
+
: maxTotalClaimsFromScaling === Infinity
|
|
2265
|
+
? -1
|
|
2266
|
+
: Math.max(0, maxTotalClaimsFromScaling - claimedCount);
|
|
2267
|
+
return { isValid, conditionData, availableClaimsNow };
|
|
2268
|
+
}
|
|
2269
|
+
return { isValid: true, conditionData: [], availableClaimsNow: -1 };
|
|
2179
2270
|
};
|
|
2180
2271
|
/**
|
|
2181
2272
|
* Checks if completion conditions were met before a specific expiry time.
|
|
@@ -2340,26 +2431,30 @@ function evaluateDynamicCondition(dynamicObj, cond, claimMultiplier = 1) {
|
|
|
2340
2431
|
}
|
|
2341
2432
|
}
|
|
2342
2433
|
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
2434
|
if (isNumber && typeof compareTo === 'number') {
|
|
2435
|
+
const skipMultiplier = cond.operator === '==' || cond.operator === '!=';
|
|
2436
|
+
const scaledCompareTo = skipMultiplier ? compareTo : compareTo * claimMultiplier;
|
|
2350
2437
|
switch (cond.operator) {
|
|
2438
|
+
case '==':
|
|
2439
|
+
return val === scaledCompareTo;
|
|
2440
|
+
case '!=':
|
|
2441
|
+
return val !== scaledCompareTo;
|
|
2351
2442
|
case '>':
|
|
2352
|
-
return val >
|
|
2443
|
+
return val > scaledCompareTo;
|
|
2353
2444
|
case '>=':
|
|
2354
|
-
return val >=
|
|
2445
|
+
return val >= scaledCompareTo;
|
|
2355
2446
|
case '<':
|
|
2356
|
-
return val <
|
|
2447
|
+
return val < scaledCompareTo;
|
|
2357
2448
|
case '<=':
|
|
2358
|
-
return val <=
|
|
2449
|
+
return val <= scaledCompareTo;
|
|
2359
2450
|
}
|
|
2360
2451
|
}
|
|
2361
2452
|
else if (!isNumber && typeof compareTo === 'string') {
|
|
2362
2453
|
switch (cond.operator) {
|
|
2454
|
+
case '==':
|
|
2455
|
+
return val === compareTo;
|
|
2456
|
+
case '!=':
|
|
2457
|
+
return val !== compareTo;
|
|
2363
2458
|
case 'has':
|
|
2364
2459
|
return val.includes(compareTo);
|
|
2365
2460
|
case 'not_has':
|
|
@@ -2368,6 +2463,98 @@ function evaluateDynamicCondition(dynamicObj, cond, claimMultiplier = 1) {
|
|
|
2368
2463
|
}
|
|
2369
2464
|
return false;
|
|
2370
2465
|
}
|
|
2466
|
+
/**
|
|
2467
|
+
* Calculates the maximum number of claims supported by a single dynamic condition.
|
|
2468
|
+
*/
|
|
2469
|
+
function getMaxClaimsForDynamicCondition(dynamicObj, cond) {
|
|
2470
|
+
if (!dynamicObj)
|
|
2471
|
+
return 0;
|
|
2472
|
+
const val = dynamicObj[cond.key];
|
|
2473
|
+
if (val === undefined)
|
|
2474
|
+
return 0;
|
|
2475
|
+
if (typeof val === 'number') {
|
|
2476
|
+
const base = Number(cond.compareTo);
|
|
2477
|
+
if (isNaN(base)) {
|
|
2478
|
+
return evaluateDynamicCondition(dynamicObj, cond, 1) ? Infinity : 0;
|
|
2479
|
+
}
|
|
2480
|
+
switch (cond.operator) {
|
|
2481
|
+
case '>=':
|
|
2482
|
+
if (base === 0)
|
|
2483
|
+
return val >= 0 ? Infinity : 0;
|
|
2484
|
+
if (base < 0)
|
|
2485
|
+
return val >= base ? Infinity : 0;
|
|
2486
|
+
return Math.max(0, Math.floor(val / base));
|
|
2487
|
+
case '>':
|
|
2488
|
+
if (base === 0)
|
|
2489
|
+
return val > 0 ? Infinity : 0;
|
|
2490
|
+
if (base < 0)
|
|
2491
|
+
return val > base ? Infinity : 0;
|
|
2492
|
+
if (val <= 0)
|
|
2493
|
+
return 0;
|
|
2494
|
+
return Math.max(0, Math.ceil(val / base) - 1);
|
|
2495
|
+
case '==':
|
|
2496
|
+
return val === base ? Infinity : 0;
|
|
2497
|
+
case '!=':
|
|
2498
|
+
return val !== base ? Infinity : 0;
|
|
2499
|
+
case '<=':
|
|
2500
|
+
if (base === 0)
|
|
2501
|
+
return val <= 0 ? Infinity : 0;
|
|
2502
|
+
if (base > 0)
|
|
2503
|
+
return evaluateDynamicCondition(dynamicObj, cond, 1) ? Infinity : 0;
|
|
2504
|
+
if (val >= 0)
|
|
2505
|
+
return 0;
|
|
2506
|
+
return Math.max(0, Math.floor(val / base));
|
|
2507
|
+
case '<':
|
|
2508
|
+
if (base === 0)
|
|
2509
|
+
return val < 0 ? Infinity : 0;
|
|
2510
|
+
if (base > 0)
|
|
2511
|
+
return evaluateDynamicCondition(dynamicObj, cond, 1) ? Infinity : 0;
|
|
2512
|
+
if (val >= 0)
|
|
2513
|
+
return 0;
|
|
2514
|
+
return Math.max(0, Math.ceil(val / base) - 1);
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
// we don't scale the rest, they are always true or always false
|
|
2518
|
+
return evaluateDynamicCondition(dynamicObj, cond, 1) ? Infinity : 0;
|
|
2519
|
+
}
|
|
2520
|
+
/**
|
|
2521
|
+
* Calculates the maximum number of claims supported by a group of dynamic conditions.
|
|
2522
|
+
*/
|
|
2523
|
+
function getMaxClaimsForDynamicGroup(dynamicObj, dynamicGroup, currentClaimCount = 0) {
|
|
2524
|
+
const { conditions, links } = dynamicGroup;
|
|
2525
|
+
if (!conditions || conditions.length === 0)
|
|
2526
|
+
return Infinity;
|
|
2527
|
+
// AND only
|
|
2528
|
+
if (!links || links.length === 0 || links.every((l) => l === 'AND')) {
|
|
2529
|
+
let minClaims = Infinity;
|
|
2530
|
+
for (const cond of conditions) {
|
|
2531
|
+
const max = getMaxClaimsForDynamicCondition(dynamicObj, cond);
|
|
2532
|
+
if (max === 0)
|
|
2533
|
+
return 0;
|
|
2534
|
+
minClaims = Math.min(minClaims, max);
|
|
2535
|
+
}
|
|
2536
|
+
return minClaims;
|
|
2537
|
+
}
|
|
2538
|
+
// OR only
|
|
2539
|
+
if (links.every((l) => l === 'OR')) {
|
|
2540
|
+
let maxClaims = 0;
|
|
2541
|
+
for (const cond of conditions) {
|
|
2542
|
+
const max = getMaxClaimsForDynamicCondition(dynamicObj, cond);
|
|
2543
|
+
if (max === Infinity)
|
|
2544
|
+
return Infinity;
|
|
2545
|
+
maxClaims = Math.max(maxClaims, max);
|
|
2546
|
+
}
|
|
2547
|
+
return maxClaims;
|
|
2548
|
+
}
|
|
2549
|
+
// mixed:
|
|
2550
|
+
const maxIterations = 100;
|
|
2551
|
+
for (let n = currentClaimCount + 1; n <= currentClaimCount + maxIterations; n++) {
|
|
2552
|
+
if (!meetsDynamicConditions(dynamicObj, dynamicGroup, n)) {
|
|
2553
|
+
return n - 1;
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
return currentClaimCount + maxIterations;
|
|
2557
|
+
}
|
|
2371
2558
|
/**
|
|
2372
2559
|
* Evaluates a group of dynamic conditions with logical links (AND, OR, AND NOT).
|
|
2373
2560
|
* @param dynamicObj - The player's dynamic object with any key and string or number value.
|
|
@@ -2476,6 +2663,8 @@ exports.OfferStore = OfferStore;
|
|
|
2476
2663
|
exports.OfferwallClient = OfferwallClient;
|
|
2477
2664
|
exports.PlayerOfferStatuses = PlayerOfferStatuses;
|
|
2478
2665
|
exports.SSEConnection = SSEConnection;
|
|
2666
|
+
exports.getMaxClaimsForDynamicCondition = getMaxClaimsForDynamicCondition;
|
|
2667
|
+
exports.getMaxClaimsForDynamicGroup = getMaxClaimsForDynamicGroup;
|
|
2479
2668
|
exports.hasConditions = hasConditions;
|
|
2480
2669
|
exports.meetsBaseConditions = meetsBaseConditions;
|
|
2481
2670
|
exports.meetsClaimableConditions = meetsClaimableConditions;
|