gambling-bot-shared 0.1.40 → 0.1.42
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/constants/defaultConfig.d.ts +1 -1
- package/dist/constants/defaultConfig.js +9 -9
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.js +1 -0
- package/dist/constants/plinkoConfig.d.ts +13 -0
- package/dist/constants/plinkoConfig.js +73 -0
- package/dist/mongoose/guildConfiguration.schema.d.ts +1 -1
- package/dist/schemas/forms.d.ts +1 -1
- package/dist/schemas/forms.js +4 -1
- package/dist/utils/calculateBonusReward.js +22 -21
- package/dist/utils/calculateRTP.js +3 -7
- package/package.json +1 -1
|
@@ -82,7 +82,6 @@ export declare const defaultCasinoSettings: {
|
|
|
82
82
|
};
|
|
83
83
|
plinko: {
|
|
84
84
|
binMultipliers: {
|
|
85
|
-
0: number;
|
|
86
85
|
1: number;
|
|
87
86
|
2: number;
|
|
88
87
|
3: number;
|
|
@@ -91,6 +90,7 @@ export declare const defaultCasinoSettings: {
|
|
|
91
90
|
6: number;
|
|
92
91
|
7: number;
|
|
93
92
|
8: number;
|
|
93
|
+
9: number;
|
|
94
94
|
};
|
|
95
95
|
maxBet: number;
|
|
96
96
|
minBet: number;
|
|
@@ -99,15 +99,15 @@ exports.defaultCasinoSettings = {
|
|
|
99
99
|
},
|
|
100
100
|
plinko: {
|
|
101
101
|
binMultipliers: {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
102
|
+
1: 8,
|
|
103
|
+
2: 6,
|
|
104
|
+
3: 1.5,
|
|
105
|
+
4: 0.75,
|
|
106
|
+
5: 0.5,
|
|
107
|
+
6: 0.75,
|
|
108
|
+
7: 1.5,
|
|
109
|
+
8: 6,
|
|
110
|
+
9: 8
|
|
111
111
|
},
|
|
112
112
|
maxBet: 0,
|
|
113
113
|
minBet: 0
|
package/dist/constants/index.js
CHANGED
|
@@ -19,4 +19,5 @@ __exportStar(require("./maxSimulations"), exports);
|
|
|
19
19
|
__exportStar(require("./lotteryConfig"), exports);
|
|
20
20
|
__exportStar(require("./rouletteConfig"), exports);
|
|
21
21
|
__exportStar(require("./gameRecordFields"), exports);
|
|
22
|
+
__exportStar(require("./plinkoConfig"), exports);
|
|
22
23
|
__exportStar(require("./transaction"), exports);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const PLINKO_BIN_COUNT = 9;
|
|
2
|
+
export declare const PLINKO_ROW_COUNT: number;
|
|
3
|
+
export declare const PLINKO_CENTER_BIN = 5;
|
|
4
|
+
export declare const PLINKO_EDITABLE_BINS: readonly [1, 2, 3, 4, 5];
|
|
5
|
+
export type PlinkoEditableBin = (typeof PLINKO_EDITABLE_BINS)[number];
|
|
6
|
+
export declare const getPlinkoMirrorBin: (bin: number) => number;
|
|
7
|
+
export declare const pathIndexToPlinkoBin: (pathIndex: number) => number;
|
|
8
|
+
export declare const plinkoBinToPathIndex: (bin: number) => number;
|
|
9
|
+
export declare const expandPlinkoBinMultipliers: (editable: Record<string | number, number | string>) => Record<string, number>;
|
|
10
|
+
/** Migrate legacy 0-indexed bins and enforce symmetric 1–9 layout. */
|
|
11
|
+
export declare const normalizePlinkoBinMultipliers: (input: Record<string | number, number | string> | null | undefined) => Record<string, number>;
|
|
12
|
+
export declare const getPlinkoMultiplierAtPathIndex: (binMultipliers: Record<string | number, number | string>, pathIndex: number) => number;
|
|
13
|
+
export declare const formatPlinkoBinMultipliersForDisplay: (binMultipliers: Record<string | number, number | string>) => Record<string, number>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatPlinkoBinMultipliersForDisplay = exports.getPlinkoMultiplierAtPathIndex = exports.normalizePlinkoBinMultipliers = exports.expandPlinkoBinMultipliers = exports.plinkoBinToPathIndex = exports.pathIndexToPlinkoBin = exports.getPlinkoMirrorBin = exports.PLINKO_EDITABLE_BINS = exports.PLINKO_CENTER_BIN = exports.PLINKO_ROW_COUNT = exports.PLINKO_BIN_COUNT = void 0;
|
|
4
|
+
const defaultConfig_1 = require("./defaultConfig");
|
|
5
|
+
exports.PLINKO_BIN_COUNT = 9;
|
|
6
|
+
exports.PLINKO_ROW_COUNT = exports.PLINKO_BIN_COUNT - 1;
|
|
7
|
+
exports.PLINKO_CENTER_BIN = 5;
|
|
8
|
+
exports.PLINKO_EDITABLE_BINS = [1, 2, 3, 4, 5];
|
|
9
|
+
const getPlinkoMirrorBin = (bin) => exports.PLINKO_BIN_COUNT + 1 - bin;
|
|
10
|
+
exports.getPlinkoMirrorBin = getPlinkoMirrorBin;
|
|
11
|
+
const pathIndexToPlinkoBin = (pathIndex) => pathIndex + 1;
|
|
12
|
+
exports.pathIndexToPlinkoBin = pathIndexToPlinkoBin;
|
|
13
|
+
const plinkoBinToPathIndex = (bin) => bin - 1;
|
|
14
|
+
exports.plinkoBinToPathIndex = plinkoBinToPathIndex;
|
|
15
|
+
const toNumber = (val) => {
|
|
16
|
+
if (typeof val === 'string')
|
|
17
|
+
return parseFloat(val) || 0;
|
|
18
|
+
if (typeof val === 'number')
|
|
19
|
+
return val;
|
|
20
|
+
return 0;
|
|
21
|
+
};
|
|
22
|
+
const defaultBinMultipliers = () => defaultConfig_1.defaultCasinoSettings.plinko.binMultipliers;
|
|
23
|
+
const expandPlinkoBinMultipliers = (editable) => {
|
|
24
|
+
const defaults = defaultBinMultipliers();
|
|
25
|
+
const result = {};
|
|
26
|
+
for (const bin of exports.PLINKO_EDITABLE_BINS) {
|
|
27
|
+
result[String(bin)] = toNumber(editable[bin] ?? editable[String(bin)] ?? defaults[String(bin)] ?? 0);
|
|
28
|
+
}
|
|
29
|
+
for (let bin = exports.PLINKO_CENTER_BIN + 1; bin <= exports.PLINKO_BIN_COUNT; bin++) {
|
|
30
|
+
const mirror = (0, exports.getPlinkoMirrorBin)(bin);
|
|
31
|
+
result[String(bin)] = result[String(mirror)];
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
exports.expandPlinkoBinMultipliers = expandPlinkoBinMultipliers;
|
|
36
|
+
/** Migrate legacy 0-indexed bins and enforce symmetric 1–9 layout. */
|
|
37
|
+
const normalizePlinkoBinMultipliers = (input) => {
|
|
38
|
+
if (!input || Object.keys(input).length === 0) {
|
|
39
|
+
return (0, exports.expandPlinkoBinMultipliers)(defaultBinMultipliers());
|
|
40
|
+
}
|
|
41
|
+
const raw = {};
|
|
42
|
+
for (const [key, value] of Object.entries(input)) {
|
|
43
|
+
const numKey = Number(key);
|
|
44
|
+
if (!Number.isFinite(numKey))
|
|
45
|
+
continue;
|
|
46
|
+
raw[numKey] = toNumber(value);
|
|
47
|
+
}
|
|
48
|
+
const usesZeroIndex = Object.prototype.hasOwnProperty.call(input, '0');
|
|
49
|
+
const editable = {};
|
|
50
|
+
const defaults = defaultBinMultipliers();
|
|
51
|
+
if (usesZeroIndex) {
|
|
52
|
+
for (let bin = 1; bin <= exports.PLINKO_CENTER_BIN; bin++) {
|
|
53
|
+
editable[bin] = raw[bin - 1] ?? toNumber(defaults[String(bin)]);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
for (const bin of exports.PLINKO_EDITABLE_BINS) {
|
|
58
|
+
editable[bin] = raw[bin] ?? toNumber(defaults[String(bin)]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return (0, exports.expandPlinkoBinMultipliers)(editable);
|
|
62
|
+
};
|
|
63
|
+
exports.normalizePlinkoBinMultipliers = normalizePlinkoBinMultipliers;
|
|
64
|
+
const getPlinkoMultiplierAtPathIndex = (binMultipliers, pathIndex) => {
|
|
65
|
+
const normalized = (0, exports.normalizePlinkoBinMultipliers)(binMultipliers);
|
|
66
|
+
return normalized[String((0, exports.pathIndexToPlinkoBin)(pathIndex))] ?? 0;
|
|
67
|
+
};
|
|
68
|
+
exports.getPlinkoMultiplierAtPathIndex = getPlinkoMultiplierAtPathIndex;
|
|
69
|
+
const formatPlinkoBinMultipliersForDisplay = (binMultipliers) => {
|
|
70
|
+
const normalized = (0, exports.normalizePlinkoBinMultipliers)(binMultipliers);
|
|
71
|
+
return Object.fromEntries(exports.PLINKO_EDITABLE_BINS.map((bin) => [String(bin), normalized[String(bin)]]));
|
|
72
|
+
};
|
|
73
|
+
exports.formatPlinkoBinMultipliersForDisplay = formatPlinkoBinMultipliersForDisplay;
|
|
@@ -158,7 +158,6 @@ export declare const GuildConfigurationSchema: Schema<TGuildConfiguration, impor
|
|
|
158
158
|
};
|
|
159
159
|
plinko: {
|
|
160
160
|
binMultipliers: {
|
|
161
|
-
0: number;
|
|
162
161
|
1: number;
|
|
163
162
|
2: number;
|
|
164
163
|
3: number;
|
|
@@ -167,6 +166,7 @@ export declare const GuildConfigurationSchema: Schema<TGuildConfiguration, impor
|
|
|
167
166
|
6: number;
|
|
168
167
|
7: number;
|
|
169
168
|
8: number;
|
|
169
|
+
9: number;
|
|
170
170
|
};
|
|
171
171
|
maxBet: number;
|
|
172
172
|
minBet: number;
|
package/dist/schemas/forms.d.ts
CHANGED
|
@@ -81,7 +81,7 @@ export declare const casinoSettingsSchema: z.ZodObject<{
|
|
|
81
81
|
casinoCut: z.ZodNumber;
|
|
82
82
|
}, z.core.$strip>;
|
|
83
83
|
plinko: z.ZodObject<{
|
|
84
|
-
binMultipliers: z.ZodRecord<z.ZodString, z.ZodNumber
|
|
84
|
+
binMultipliers: z.ZodPipe<z.ZodRecord<z.ZodString, z.ZodNumber>, z.ZodTransform<Record<string, number>, Record<string, number>>>;
|
|
85
85
|
minBet: z.ZodNumber;
|
|
86
86
|
maxBet: z.ZodNumber;
|
|
87
87
|
}, z.core.$strip>;
|
package/dist/schemas/forms.js
CHANGED
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.bonusFormSchema = exports.managerRoleFormSchema = exports.vipSettingsFormSchema = exports.casinoSettingsSchema = exports.channelsFormSchema = exports.raffleChannelsFormSchema = exports.predictionChannelsFormSchema = exports.casinoChannelsFormSchema = exports.atmChannelsFormSchema = void 0;
|
|
7
7
|
const zod_1 = __importDefault(require("zod"));
|
|
8
|
+
const plinkoConfig_1 = require("../constants/plinkoConfig");
|
|
8
9
|
const NO_CHANNEL = 'At least one channel must be selected.';
|
|
9
10
|
exports.atmChannelsFormSchema = zod_1.default.object({
|
|
10
11
|
actions: zod_1.default.string().min(1, { message: NO_CHANNEL }),
|
|
@@ -80,7 +81,9 @@ exports.casinoSettingsSchema = zod_1.default.object({
|
|
|
80
81
|
casinoCut: num
|
|
81
82
|
}),
|
|
82
83
|
plinko: zod_1.default.object({
|
|
83
|
-
binMultipliers: zod_1.default
|
|
84
|
+
binMultipliers: zod_1.default
|
|
85
|
+
.record(zod_1.default.string(), num)
|
|
86
|
+
.transform(plinkoConfig_1.normalizePlinkoBinMultipliers),
|
|
84
87
|
minBet: num,
|
|
85
88
|
maxBet: num
|
|
86
89
|
})
|
|
@@ -1,33 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.calculateBonusReward = void 0;
|
|
4
|
+
const getCycleLength = (rewardMode, baseReward, maxReward, streakIncrement, streakMultiplier) => {
|
|
5
|
+
if (rewardMode === 'linear') {
|
|
6
|
+
return streakIncrement > 0
|
|
7
|
+
? Math.floor((maxReward - baseReward) / streakIncrement) + 1
|
|
8
|
+
: 1;
|
|
9
|
+
}
|
|
10
|
+
return streakMultiplier > 1
|
|
11
|
+
? Math.floor(Math.log(maxReward / baseReward) / Math.log(streakMultiplier)) +
|
|
12
|
+
1
|
|
13
|
+
: 1;
|
|
14
|
+
};
|
|
4
15
|
const calculateBonusReward = ({ streak, settings }) => {
|
|
5
16
|
const { rewardMode, baseReward, streakIncrement = 0, streakMultiplier = 1, maxReward, resetOnMax, milestoneBonus } = settings;
|
|
6
17
|
let base = rewardMode === 'linear'
|
|
7
18
|
? baseReward + (streak - 1) * streakIncrement
|
|
8
19
|
: baseReward * Math.pow(streakMultiplier, streak - 1);
|
|
9
20
|
let isReset = false;
|
|
10
|
-
if (maxReward > 0 && base > maxReward) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const cycle = streakMultiplier > 1
|
|
22
|
-
? Math.floor(Math.log(maxReward / baseReward) / Math.log(streakMultiplier)) + 1
|
|
23
|
-
: 1;
|
|
24
|
-
const newStreak = ((streak - 1) % cycle) + 1;
|
|
25
|
-
base = baseReward * Math.pow(streakMultiplier, newStreak - 1);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
base = maxReward;
|
|
30
|
-
}
|
|
21
|
+
if (maxReward > 0 && resetOnMax && base > maxReward) {
|
|
22
|
+
const cycle = getCycleLength(rewardMode, baseReward, maxReward, streakIncrement, streakMultiplier);
|
|
23
|
+
const cycleStreak = ((streak - 1) % cycle) + 1;
|
|
24
|
+
isReset = streak > cycle && cycleStreak === 1;
|
|
25
|
+
base =
|
|
26
|
+
rewardMode === 'linear'
|
|
27
|
+
? baseReward + (cycleStreak - 1) * streakIncrement
|
|
28
|
+
: baseReward * Math.pow(streakMultiplier, cycleStreak - 1);
|
|
29
|
+
}
|
|
30
|
+
else if (maxReward > 0 && base > maxReward) {
|
|
31
|
+
base = maxReward;
|
|
31
32
|
}
|
|
32
33
|
const weekly = streak % 7 === 0 ? milestoneBonus.weekly : 0;
|
|
33
34
|
const monthly = streak % 28 === 0 ? milestoneBonus.monthly : 0;
|
|
@@ -103,17 +103,13 @@ const calculateRTP = (game, settings) => {
|
|
|
103
103
|
return 0;
|
|
104
104
|
case 'plinko': {
|
|
105
105
|
const { binMultipliers } = settings;
|
|
106
|
-
const multipliers = binMultipliers;
|
|
107
|
-
const
|
|
108
|
-
.map(Number)
|
|
109
|
-
.sort((a, b) => a - b);
|
|
110
|
-
const N = bins.length - 1; // rows
|
|
106
|
+
const multipliers = (0, constants_1.normalizePlinkoBinMultipliers)(binMultipliers);
|
|
107
|
+
const N = constants_1.PLINKO_ROW_COUNT;
|
|
111
108
|
const p = 0.5;
|
|
112
109
|
let rtp = 0;
|
|
113
110
|
for (let k = 0; k <= N; k++) {
|
|
114
111
|
const probability = combination(N, k) * Math.pow(p, k) * Math.pow(1 - p, N - k);
|
|
115
|
-
|
|
116
|
-
rtp += probability * multiplier;
|
|
112
|
+
rtp += probability * (0, constants_1.getPlinkoMultiplierAtPathIndex)(multipliers, k);
|
|
117
113
|
}
|
|
118
114
|
return rtp * 100;
|
|
119
115
|
}
|