@allemandi/gacha-engine 0.3.3 → 0.3.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/README.md +13 -16
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.module.js +1 -1
- package/dist/index.module.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -85,24 +85,21 @@ const engine = new GachaEngine({ mode: 'weighted', pools, rarityRates });
|
|
|
85
85
|
console.log('10 rolls:', engine.roll(10).join(', '));
|
|
86
86
|
|
|
87
87
|
const rate = engine.getItemDropRate('Super Hobo');
|
|
88
|
-
console.log('Drop rate for Super Hobo:', (rate * 100)
|
|
88
|
+
console.log('Drop rate for Super Hobo:', (rate * 100) + '%');
|
|
89
89
|
// ~0.4% → (0.8 / 1.6) * 0.01 = 0.005 → 0.5%
|
|
90
90
|
|
|
91
91
|
const cumulative = engine.getCumulativeProbabilityForItem('Super Hobo', 300);
|
|
92
|
-
console.log('Probability in 300 rolls:', (cumulative * 100)
|
|
92
|
+
console.log('Probability in 300 rolls:', (cumulative * 100) + '%');
|
|
93
93
|
// ~77.7%
|
|
94
94
|
|
|
95
95
|
console.log('Rolls for 50% chance:', engine.getRollsForTargetProbability('Super Hobo', 0.5));
|
|
96
|
-
//
|
|
96
|
+
// 139
|
|
97
97
|
|
|
98
98
|
console.log('Rate-up items:', engine.getRateUpItems().join(', '));
|
|
99
99
|
// Super Hobo, Cold Salaryman
|
|
100
|
-
|
|
101
|
-
console.log('All items:', engine.getAllItems().join(', '));
|
|
102
|
-
// Super Hobo, Broke King, Cardboard Hero, Cold Salaryman, Numb Artist, Crying Cook, Regular Joe, Normal Person
|
|
103
100
|
```
|
|
104
101
|
|
|
105
|
-
**CommonJS (Flat Mode)**
|
|
102
|
+
**CommonJS (Flat Rate Mode)**
|
|
106
103
|
```js
|
|
107
104
|
const { GachaEngine } = require('@allemandi/gacha-engine');
|
|
108
105
|
|
|
@@ -110,30 +107,30 @@ const pools = [
|
|
|
110
107
|
{
|
|
111
108
|
rarity: 'SSR',
|
|
112
109
|
items: [
|
|
113
|
-
{ name: 'God-Tier Rat',
|
|
114
|
-
{ name: 'Dumpster King',
|
|
110
|
+
{ name: 'God-Tier Rat', weight: 0.003, rateUp: true },
|
|
111
|
+
{ name: 'Dumpster King', weight: 0.002 }
|
|
115
112
|
]
|
|
116
113
|
},
|
|
117
114
|
{
|
|
118
115
|
rarity: 'SR',
|
|
119
116
|
items: [
|
|
120
|
-
{ name: 'Sleepy Chef',
|
|
117
|
+
{ name: 'Sleepy Chef', weight: 0.015 }
|
|
121
118
|
]
|
|
122
119
|
},
|
|
123
120
|
{
|
|
124
121
|
rarity: 'R',
|
|
125
122
|
items: [
|
|
126
|
-
{ name: 'Unknown Student',
|
|
123
|
+
{ name: 'Unknown Student', weight: 0.1 }
|
|
127
124
|
]
|
|
128
125
|
}
|
|
129
126
|
];
|
|
130
127
|
|
|
131
|
-
const engine = new GachaEngine({ mode: '
|
|
128
|
+
const engine = new GachaEngine({ mode: 'flatRate', pools });
|
|
132
129
|
|
|
133
130
|
console.log('Roll x5:', engine.roll(5).join(', '));
|
|
134
131
|
|
|
135
132
|
const dropRate = engine.getItemDropRate('God-Tier Rat');
|
|
136
|
-
console.log('Drop rate for God-Tier Rat:', (dropRate * 100)
|
|
133
|
+
console.log('Drop rate for God-Tier Rat:', (dropRate * 100) + '%');
|
|
137
134
|
// 0.3%
|
|
138
135
|
|
|
139
136
|
const cumulative = engine.getCumulativeProbabilityForItem('God-Tier Rat', 500);
|
|
@@ -200,13 +197,13 @@ console.log('All items:', engine.getAllItems().join(', '));
|
|
|
200
197
|
// ~86.6%
|
|
201
198
|
|
|
202
199
|
console.log('Rolls for 75% chance:', rolls);
|
|
203
|
-
// ~
|
|
200
|
+
// ~138
|
|
204
201
|
|
|
205
202
|
console.log('Rate-up items:', engine.getRateUpItems().join(', '));
|
|
206
203
|
// Park Master
|
|
207
204
|
|
|
208
|
-
console.log('All items:', engine.
|
|
209
|
-
// Trash Wizard, Park Master, Street Sweeper, Bench Philosopher, Bus Stop Ghost
|
|
205
|
+
console.log('All items:', engine.getAllItemDropRates().map(i => i.name));
|
|
206
|
+
// ["Trash Wizard", "Park Master", "Street Sweeper", "Bench Philosopher", "Bus Stop Ghost"]
|
|
210
207
|
</script>
|
|
211
208
|
```
|
|
212
209
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function t(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,a=Array(e);r<e;r++)a[r]=t[r];return a}function e(e,r){var a="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(a)return(a=a.call(e)).next.bind(a);if(Array.isArray(e)||(a=function(e,r){if(e){if("string"==typeof e)return t(e,r);var a={}.toString.call(e).slice(8,-1);return"Object"===a&&e.constructor&&(a=e.constructor.name),"Map"===a||"Set"===a?Array.from(e):"Arguments"===a||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(a)?t(e,r):void 0}}(e))||r&&e&&"number"==typeof e.length){a&&(e=a);var n=0;return function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function r(){return r=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var a in r)({}).hasOwnProperty.call(r,a)&&(t[a]=r[a])}return t},r.apply(null,arguments)}var a,n=/*#__PURE__*/function(){function t(t){if(this.mode=void 0,this.pools=[],this.rarityRatesScaled={},this.flatRateMap=new Map,this.dropRateCacheScaled=new Map,this.mode=t.mode,"weighted"===t.mode){var r=t;this.pools=r.pools,this.rarityRatesScaled=this.scaleRarityRates(r.rarityRates),this.validateConfig(r.rarityRates)}else{if("flatRate"!==t.mode)throw new Error("Unknown gacha mode: "+this.mode);for(var a,n=e(t.pools);!(a=n()).done;)for(var i,o=e(a.value.items);!(i=o()).done;){var s=i.value;if(s.weight<0)throw new Error('FlatRate item "'+s.name+'" must have non-negative weight');this.flatRateMap.set(s.name,s.weight)}var
|
|
1
|
+
function t(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,a=Array(e);r<e;r++)a[r]=t[r];return a}function e(e,r){var a="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(a)return(a=a.call(e)).next.bind(a);if(Array.isArray(e)||(a=function(e,r){if(e){if("string"==typeof e)return t(e,r);var a={}.toString.call(e).slice(8,-1);return"Object"===a&&e.constructor&&(a=e.constructor.name),"Map"===a||"Set"===a?Array.from(e):"Arguments"===a||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(a)?t(e,r):void 0}}(e))||r&&e&&"number"==typeof e.length){a&&(e=a);var n=0;return function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function r(){return r=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var a in r)({}).hasOwnProperty.call(r,a)&&(t[a]=r[a])}return t},r.apply(null,arguments)}var a,n=/*#__PURE__*/function(){function t(t){if(this.mode=void 0,this.pools=[],this.rarityRatesScaled={},this.flatRateMap=new Map,this.dropRateCacheScaled=new Map,this.mode=t.mode,"weighted"===t.mode){var r=t;this.pools=r.pools,this.rarityRatesScaled=this.scaleRarityRates(r.rarityRates),this.validateConfig(r.rarityRates)}else{if("flatRate"!==t.mode)throw new Error("Unknown gacha mode: "+this.mode);for(var a,n=e(t.pools);!(a=n()).done;)for(var i,o=e(a.value.items);!(i=o()).done;){var s=i.value;if(s.weight<0)throw new Error('FlatRate item "'+s.name+'" must have non-negative weight');this.flatRateMap.set(s.name,s.weight)}var l=Array.from(this.flatRateMap.values()).reduce(function(t,e){return t+e},0);if(Math.abs(l-1)>1e-6)throw new Error("FlatRate item rates must sum to 1.0, but got "+l)}}var a=t.prototype;return a.scaleRarityRates=function(t){for(var e={},r=0,a=Object.entries(t);r<a.length;r++){var n=a[r],i=n[0],o=n[1];if(o<0||o>1)throw new Error('Rarity rate for "'+i+'" must be between 0 and 1, got '+o);e[i]=this.toScaled(o)}return e},a.toScaled=function(e){if(e>t.MAX_SAFE_SCALE/t.SCALE)throw new Error("Probability "+e+" too large for safe integer arithmetic");return Math.round(e*t.SCALE)},a.fromScaled=function(e){return e/t.SCALE},a.validateConfig=function(t){var r=new Set(Object.keys(this.rarityRatesScaled)),a=new Set(this.pools.map(function(t){return t.rarity})),n=Array.from(a).filter(function(t){return!r.has(t)});if(n.length>0)throw new Error("Missing rarity rates for: "+n.join(", "));var i=Object.values(t).reduce(function(t,e){return t+e},0);if(Math.abs(i-1)>1e-10)throw new Error("Rarity rates must sum to 1.0, got "+i);for(var o,s=e(this.pools);!(o=s()).done;){var l=o.value;if(0===l.items.length)throw new Error('Rarity "'+l.rarity+'" has no items');if(l.items.reduce(function(t,e){return t+e.weight},0)<=0)throw new Error('Rarity "'+l.rarity+'" has zero total weight');for(var u,h=e(l.items);!(u=h()).done;){var f=u.value;if(f.weight<0)throw new Error('Item "'+f.name+'" weight must be non-negative, got '+f.weight)}if(!l.items.some(function(t){return t.weight>0}))throw new Error('Rarity "'+l.rarity+'" must have at least one item with positive weight')}},a.getItemDropRate=function(r){if("flatRate"===this.mode)return this.flatRateMap.get(r)||0;if(this.dropRateCacheScaled.has(r))return this.fromScaled(this.dropRateCacheScaled.get(r));for(var a,n=e(this.pools);!(a=n()).done;){var i=a.value,o=i.items.find(function(t){return t.name===r});if(o){if(0===o.weight)return this.dropRateCacheScaled.set(r,0),0;var s=i.items.reduce(function(t,e){return t+e.weight},0),l=this.rarityRatesScaled[i.rarity],u=this.toScaled(o.weight),h=this.toScaled(s),f=Math.round(u*l/t.SCALE),c=Math.round(f*t.SCALE/h);return this.dropRateCacheScaled.set(r,c),this.fromScaled(c)}}throw new Error('Item "'+r+'" not found')},a.getCumulativeProbabilityForItem=function(t,e){var r=this.getItemDropRate(t);return 0===r?0:r>=1?1:1-Math.pow(1-r,e)},a.getRollsForTargetProbability=function(t,e){if(e<=0)return 0;if(e>=1)return 1;var r=this.getItemDropRate(t);return r<=0?Infinity:Math.ceil(Math.log(1-e)/Math.log(1-r))},a.getRateUpItems=function(){return"weighted"===this.mode||this.pools.length>0?this.pools.flatMap(function(t){return t.items.filter(function(t){return t.rateUp}).map(function(t){return t.name})}):[]},a.getAllItemDropRates=function(){var t=this;return"flatRate"===this.mode?Array.from(this.flatRateMap.entries()).map(function(t){return{name:t[0],dropRate:t[1],rarity:"flatRate"}}):this.pools.flatMap(function(e){return e.items.map(function(r){return{name:r.name,dropRate:t.getItemDropRate(r.name),rarity:e.rarity}})})},a.roll=function(t){var r=this;void 0===t&&(t=1);for(var a=[],n=function(){if("flatRate"===r.mode)for(var t,n=Math.random(),i=0,o=e(r.flatRateMap.entries());!(t=o()).done;){var s=t.value;if(n<(i+=s[1])){a.push(s[0]);break}}else{var l=r.selectRarity(),u=r.pools.find(function(t){return t.rarity===l}),h=r.selectItemFromPool(u);a.push(h.name)}},i=0;i<t;i++)n();return a},a.selectRarity=function(){for(var e=Math.floor(Math.random()*t.SCALE),r=0,a=0,n=Object.entries(this.rarityRatesScaled);a<n.length;a++){var i=n[a];if(e<(r+=i[1]))return i[0]}return Object.keys(this.rarityRatesScaled)[0]},a.selectItemFromPool=function(t){for(var a,n=this,i=t.items.filter(function(t){return t.weight>0}),o=i.map(function(t){return r({},t,{scaledWeight:n.toScaled(t.weight)})}),s=o.reduce(function(t,e){return t+e.scaledWeight},0),l=Math.floor(Math.random()*s),u=0,h=e(o);!(a=h()).done;){var f=a.value;if(l<(u+=f.scaledWeight))return{name:f.name,weight:f.weight}}return i[0]},a.getDebugInfo=function(){for(var e={},a=0,n=Object.entries(this.rarityRatesScaled);a<n.length;a++){var i=n[a];e[i[0]]=this.fromScaled(i[1])}return{scale:t.SCALE,rarityRatesScaled:r({},this.rarityRatesScaled),rarityRatesFloat:e}},t}();a=n,n.SCALE=1e6,n.MAX_SAFE_SCALE=Math.floor(Number.MAX_SAFE_INTEGER/a.SCALE),exports.GachaEngine=n;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/gacha-engine.ts"],"sourcesContent":["import {\n RarityInput,\n GachaEngineConfig,\n WeightedGachaEngineConfig,\n FlatRateGachaEngineConfig,\n} from './types';\n\nexport class GachaEngine {\n private static readonly SCALE = 1_000_000;\n private static readonly MAX_SAFE_SCALE = Math.floor(Number.MAX_SAFE_INTEGER / GachaEngine.SCALE);\n\n private mode: 'weighted' | 'flatRate';\n private pools: RarityInput[] = [];\n private rarityRatesScaled: Record<string, number> = {};\n private flatRateMap: Map<string, number> = new Map();\n private dropRateCacheScaled = new Map<string, number>();\n\n constructor(config: GachaEngineConfig) {\n this.mode = config.mode;\n\n if (config.mode === 'weighted') {\n const weightedConfig = config as WeightedGachaEngineConfig;\n this.pools = weightedConfig.pools;\n this.rarityRatesScaled = this.scaleRarityRates(weightedConfig.rarityRates);\n this.validateConfig(weightedConfig.rarityRates);\n } else if (config.mode === 'flatRate') {\n const flatConfig = config as FlatRateGachaEngineConfig;\n for (const pool of flatConfig.pools) {\n for (const item of pool.items) {\n if (item.weight < 0) {\n throw new Error(`FlatRate item \"${item.name}\" must have non-negative weight`);\n }\n this.flatRateMap.set(item.name, item.weight); // Here, interpreted as direct probability\n }\n }\n const total = Array.from(this.flatRateMap.values()).reduce((sum, v) => sum + v, 0);\n if (Math.abs(total - 1.0) > 1e-6) {\n throw new Error(`FlatRate item rates must sum to 1.0, but got ${total}`);\n }\n } else {\n throw new Error(`Unknown gacha mode: ${this.mode}`);\n }\n }\n\n private scaleRarityRates(rarityRates: Record<string, number>): Record<string, number> {\n const scaled: Record<string, number> = {};\n for (const [rarity, rate] of Object.entries(rarityRates)) {\n if (rate < 0 || rate > 1) {\n throw new Error(`Rarity rate for \"${rarity}\" must be between 0 and 1, got ${rate}`);\n }\n scaled[rarity] = this.toScaled(rate);\n }\n return scaled;\n }\n\n private toScaled(probability: number): number {\n if (probability > GachaEngine.MAX_SAFE_SCALE / GachaEngine.SCALE) {\n throw new Error(`Probability ${probability} too large for safe integer arithmetic`);\n }\n return Math.round(probability * GachaEngine.SCALE);\n }\n\n private fromScaled(scaledInt: number): number {\n return scaledInt / GachaEngine.SCALE;\n }\n\n private validateConfig(originalRates: Record<string, number>): void {\n const configuredRarities = new Set(Object.keys(this.rarityRatesScaled));\n const usedRarities = new Set(this.pools.map(p => p.rarity));\n const missing = Array.from(usedRarities).filter(r => !configuredRarities.has(r));\n\n if (missing.length > 0) {\n throw new Error(`Missing rarity rates for: ${missing.join(', ')}`);\n }\n\n const totalRate = Object.values(originalRates).reduce((sum, rate) => sum + rate, 0);\n if (Math.abs(totalRate - 1.0) > 1e-10) {\n throw new Error(`Rarity rates must sum to 1.0, got ${totalRate}`);\n }\n\n for (const pool of this.pools) {\n if (pool.items.length === 0) {\n throw new Error(`Rarity \"${pool.rarity}\" has no items`);\n }\n\n const totalWeight = pool.items.reduce((sum, i) => sum + i.weight, 0);\n if (totalWeight <= 0) {\n throw new Error(`Rarity \"${pool.rarity}\" has zero total weight`);\n }\n\n for (const item of pool.items) {\n if (item.weight < 0) {\n throw new Error(`Item \"${item.name}\" weight must be non-negative, got ${item.weight}`);\n }\n }\n\n if (!pool.items.some(i => i.weight > 0)) {\n throw new Error(`Rarity \"${pool.rarity}\" must have at least one item with positive weight`);\n }\n }\n }\n\n getItemDropRate(name: string): number {\n if (this.mode === 'flatRate') {\n return this.flatRateMap.get(name) || 0;\n }\n\n if (this.dropRateCacheScaled.has(name)) {\n return this.fromScaled(this.dropRateCacheScaled.get(name)!);\n }\n\n for (const pool of this.pools) {\n const item = pool.items.find(i => i.name === name);\n if (item) {\n if (item.weight === 0) {\n this.dropRateCacheScaled.set(name, 0);\n return 0;\n }\n\n const totalPoolWeight = pool.items.reduce((sum, i) => sum + i.weight, 0);\n const baseRarityRateScaled = this.rarityRatesScaled[pool.rarity];\n const itemWeightScaled = this.toScaled(item.weight);\n const totalWeightScaled = this.toScaled(totalPoolWeight);\n const numeratorScaled = Math.round((itemWeightScaled * baseRarityRateScaled) / GachaEngine.SCALE);\n const rateScaled = Math.round((numeratorScaled * GachaEngine.SCALE) / totalWeightScaled);\n\n this.dropRateCacheScaled.set(name, rateScaled);\n return this.fromScaled(rateScaled);\n }\n }\n\n throw new Error(`Item \"${name}\" not found`);\n }\n\n getCumulativeProbabilityForItem(name: string, rolls: number): number {\n const rate = this.getItemDropRate(name);\n if (rate === 0) return 0;\n if (rate >= 1) return 1;\n\n const cumulativeFailProbability = Math.pow(1 - rate, rolls);\n return 1 - cumulativeFailProbability;\n }\n\n getRollsForTargetProbability(name: string, targetProbability: number): number {\n if (targetProbability <= 0) return 0;\n if (targetProbability >= 1) return 1;\n\n const rate = this.getItemDropRate(name);\n if (rate <= 0) return Infinity;\n return Math.ceil(Math.log(1 - targetProbability) / Math.log(1 - rate));\n }\n\n getRateUpItems(): string[] {\n return this.pools.flatMap(p => p.items.filter(i => i.rateUp).map(i => i.name));\n }\n\n getAllItemDropRates(): { name: string; dropRate: number; rarity: string }[] {\n if (this.mode === 'flatRate') {\n return Array.from(this.flatRateMap.entries()).map(([name, dropRate]) => ({\n name,\n dropRate,\n rarity: 'flatRate',\n }));\n }\n\n return this.pools.flatMap(p =>\n p.items.map(i => ({\n name: i.name,\n dropRate: this.getItemDropRate(i.name),\n rarity: p.rarity,\n }))\n );\n }\n\n roll(count: number = 1): string[] {\n const results: string[] = [];\n for (let i = 0; i < count; i++) {\n if (this.mode === 'flatRate') {\n const rand = Math.random();\n let cumulative = 0;\n for (const [name, rate] of this.flatRateMap.entries()) {\n cumulative += rate;\n if (rand < cumulative) {\n results.push(name);\n break;\n }\n }\n } else {\n const rarity = this.selectRarity();\n const pool = this.pools.find(p => p.rarity === rarity)!;\n const item = this.selectItemFromPool(pool);\n results.push(item.name);\n }\n }\n return results;\n }\n\n private selectRarity(): string {\n const rand = Math.floor(Math.random() * GachaEngine.SCALE);\n let cumulative = 0;\n\n for (const [rarity, scaledRate] of Object.entries(this.rarityRatesScaled)) {\n cumulative += scaledRate;\n if (rand < cumulative) return rarity;\n }\n\n return Object.keys(this.rarityRatesScaled)[0];\n }\n\n private selectItemFromPool(pool: RarityInput): { name: string; weight: number } {\n const items = pool.items.filter(i => i.weight > 0);\n const scaledItems = items.map(i => ({\n ...i,\n scaledWeight: this.toScaled(i.weight),\n }));\n\n const totalScaledWeight = scaledItems.reduce((sum, i) => sum + i.scaledWeight, 0);\n const rand = Math.floor(Math.random() * totalScaledWeight);\n let cumulative = 0;\n\n for (const item of scaledItems) {\n cumulative += item.scaledWeight;\n if (rand < cumulative) {\n return { name: item.name, weight: item.weight };\n }\n }\n\n return items[0]; // Fallback\n }\n\n getDebugInfo(): {\n scale: number;\n rarityRatesScaled: Record<string, number>;\n rarityRatesFloat: Record<string, number>;\n } {\n const rarityRatesFloat: Record<string, number> = {};\n for (const [rarity, scaledRate] of Object.entries(this.rarityRatesScaled)) {\n rarityRatesFloat[rarity] = this.fromScaled(scaledRate);\n }\n\n return {\n scale: GachaEngine.SCALE,\n rarityRatesScaled: { ...this.rarityRatesScaled },\n rarityRatesFloat,\n };\n }\n}\n"],"names":["GachaEngine","config","this","mode","pools","rarityRatesScaled","flatRateMap","Map","dropRateCacheScaled","weightedConfig","scaleRarityRates","rarityRates","validateConfig","Error","_step","_iterator","_createForOfIteratorHelperLoose","done","_step2","_iterator2","value","items","item","weight","name","set","total","Array","from","values","reduce","sum","v","Math","abs","_proto","prototype","scaled","_i","_Object$entries","Object","entries","length","_Object$entries$_i","rarity","rate","toScaled","probability","MAX_SAFE_SCALE","SCALE","round","fromScaled","scaledInt","originalRates","configuredRarities","Set","keys","usedRarities","map","p","missing","filter","r","has","join","totalRate","_iterator3","_step3","pool","i","_step4","_iterator4","some","getItemDropRate","get","_iterator5","_step5","find","totalPoolWeight","baseRarityRateScaled","itemWeightScaled","totalWeightScaled","numeratorScaled","rateScaled","getCumulativeProbabilityForItem","rolls","pow","getRollsForTargetProbability","targetProbability","Infinity","ceil","log","getRateUpItems","flatMap","rateUp","getAllItemDropRates","_this","_ref","dropRate","roll","count","_this2","results","_loop","_step6","rand","random","cumulative","_iterator6","_step6$value","push","selectRarity","selectItemFromPool","floor","_i2","_Object$entries2","_Object$entries2$_i","scaledRate","_step7","_this3","scaledItems","_extends","scaledWeight","totalScaledWeight","_iterator7","getDebugInfo","rarityRatesFloat","_i3","_Object$entries3","_Object$entries3$_i","scale","Number","MAX_SAFE_INTEGER"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/gacha-engine.ts"],"sourcesContent":["import {\n RarityInput,\n GachaEngineConfig,\n WeightedGachaEngineConfig,\n FlatRateGachaEngineConfig,\n} from './types';\n\nexport class GachaEngine {\n private static readonly SCALE = 1_000_000;\n private static readonly MAX_SAFE_SCALE = Math.floor(Number.MAX_SAFE_INTEGER / GachaEngine.SCALE);\n\n private mode: 'weighted' | 'flatRate';\n private pools: RarityInput[] = [];\n private rarityRatesScaled: Record<string, number> = {};\n private flatRateMap: Map<string, number> = new Map();\n private dropRateCacheScaled = new Map<string, number>();\n\n constructor(config: GachaEngineConfig) {\n this.mode = config.mode;\n\n if (config.mode === 'weighted') {\n const weightedConfig = config as WeightedGachaEngineConfig;\n this.pools = weightedConfig.pools;\n this.rarityRatesScaled = this.scaleRarityRates(weightedConfig.rarityRates);\n this.validateConfig(weightedConfig.rarityRates);\n } else if (config.mode === 'flatRate') {\n const flatConfig = config as FlatRateGachaEngineConfig;\n for (const pool of flatConfig.pools) {\n for (const item of pool.items) {\n if (item.weight < 0) {\n throw new Error(`FlatRate item \"${item.name}\" must have non-negative weight`);\n }\n this.flatRateMap.set(item.name, item.weight); // Here, interpreted as direct probability\n }\n }\n const total = Array.from(this.flatRateMap.values()).reduce((sum, v) => sum + v, 0);\n if (Math.abs(total - 1.0) > 1e-6) {\n throw new Error(`FlatRate item rates must sum to 1.0, but got ${total}`);\n }\n } else {\n throw new Error(`Unknown gacha mode: ${this.mode}`);\n }\n }\n\n private scaleRarityRates(rarityRates: Record<string, number>): Record<string, number> {\n const scaled: Record<string, number> = {};\n for (const [rarity, rate] of Object.entries(rarityRates)) {\n if (rate < 0 || rate > 1) {\n throw new Error(`Rarity rate for \"${rarity}\" must be between 0 and 1, got ${rate}`);\n }\n scaled[rarity] = this.toScaled(rate);\n }\n return scaled;\n }\n\n private toScaled(probability: number): number {\n if (probability > GachaEngine.MAX_SAFE_SCALE / GachaEngine.SCALE) {\n throw new Error(`Probability ${probability} too large for safe integer arithmetic`);\n }\n return Math.round(probability * GachaEngine.SCALE);\n }\n\n private fromScaled(scaledInt: number): number {\n return scaledInt / GachaEngine.SCALE;\n }\n\n private validateConfig(originalRates: Record<string, number>): void {\n const configuredRarities = new Set(Object.keys(this.rarityRatesScaled));\n const usedRarities = new Set(this.pools.map(p => p.rarity));\n const missing = Array.from(usedRarities).filter(r => !configuredRarities.has(r));\n\n if (missing.length > 0) {\n throw new Error(`Missing rarity rates for: ${missing.join(', ')}`);\n }\n\n const totalRate = Object.values(originalRates).reduce((sum, rate) => sum + rate, 0);\n if (Math.abs(totalRate - 1.0) > 1e-10) {\n throw new Error(`Rarity rates must sum to 1.0, got ${totalRate}`);\n }\n\n for (const pool of this.pools) {\n if (pool.items.length === 0) {\n throw new Error(`Rarity \"${pool.rarity}\" has no items`);\n }\n\n const totalWeight = pool.items.reduce((sum, i) => sum + i.weight, 0);\n if (totalWeight <= 0) {\n throw new Error(`Rarity \"${pool.rarity}\" has zero total weight`);\n }\n\n for (const item of pool.items) {\n if (item.weight < 0) {\n throw new Error(`Item \"${item.name}\" weight must be non-negative, got ${item.weight}`);\n }\n }\n\n if (!pool.items.some(i => i.weight > 0)) {\n throw new Error(`Rarity \"${pool.rarity}\" must have at least one item with positive weight`);\n }\n }\n }\n\n getItemDropRate(name: string): number {\n if (this.mode === 'flatRate') {\n return this.flatRateMap.get(name) || 0;\n }\n\n if (this.dropRateCacheScaled.has(name)) {\n return this.fromScaled(this.dropRateCacheScaled.get(name)!);\n }\n\n for (const pool of this.pools) {\n const item = pool.items.find(i => i.name === name);\n if (item) {\n if (item.weight === 0) {\n this.dropRateCacheScaled.set(name, 0);\n return 0;\n }\n\n const totalPoolWeight = pool.items.reduce((sum, i) => sum + i.weight, 0);\n const baseRarityRateScaled = this.rarityRatesScaled[pool.rarity];\n const itemWeightScaled = this.toScaled(item.weight);\n const totalWeightScaled = this.toScaled(totalPoolWeight);\n const numeratorScaled = Math.round((itemWeightScaled * baseRarityRateScaled) / GachaEngine.SCALE);\n const rateScaled = Math.round((numeratorScaled * GachaEngine.SCALE) / totalWeightScaled);\n\n this.dropRateCacheScaled.set(name, rateScaled);\n return this.fromScaled(rateScaled);\n }\n }\n\n throw new Error(`Item \"${name}\" not found`);\n }\n\n getCumulativeProbabilityForItem(name: string, rolls: number): number {\n const rate = this.getItemDropRate(name);\n if (rate === 0) return 0;\n if (rate >= 1) return 1;\n\n const cumulativeFailProbability = Math.pow(1 - rate, rolls);\n return 1 - cumulativeFailProbability;\n }\n\n getRollsForTargetProbability(name: string, targetProbability: number): number {\n if (targetProbability <= 0) return 0;\n if (targetProbability >= 1) return 1;\n\n const rate = this.getItemDropRate(name);\n if (rate <= 0) return Infinity;\n return Math.ceil(Math.log(1 - targetProbability) / Math.log(1 - rate));\n }\n\n getRateUpItems(): string[] {\n if (this.mode === 'weighted') {\n return this.pools.flatMap(p => p.items.filter(i => i.rateUp).map(i => i.name));\n } else {\n if (this.pools.length > 0) {\n return this.pools.flatMap(p => p.items.filter(i => i.rateUp).map(i => i.name));\n }\n return [];\n }\n}\n\n\n getAllItemDropRates(): { name: string; dropRate: number; rarity: string }[] {\n if (this.mode === 'flatRate') {\n return Array.from(this.flatRateMap.entries()).map(([name, dropRate]) => ({\n name,\n dropRate,\n rarity: 'flatRate',\n }));\n }\n\n return this.pools.flatMap(p =>\n p.items.map(i => ({\n name: i.name,\n dropRate: this.getItemDropRate(i.name),\n rarity: p.rarity,\n }))\n );\n }\n\n roll(count: number = 1): string[] {\n const results: string[] = [];\n for (let i = 0; i < count; i++) {\n if (this.mode === 'flatRate') {\n const rand = Math.random();\n let cumulative = 0;\n for (const [name, rate] of this.flatRateMap.entries()) {\n cumulative += rate;\n if (rand < cumulative) {\n results.push(name);\n break;\n }\n }\n } else {\n const rarity = this.selectRarity();\n const pool = this.pools.find(p => p.rarity === rarity)!;\n const item = this.selectItemFromPool(pool);\n results.push(item.name);\n }\n }\n return results;\n }\n\n private selectRarity(): string {\n const rand = Math.floor(Math.random() * GachaEngine.SCALE);\n let cumulative = 0;\n\n for (const [rarity, scaledRate] of Object.entries(this.rarityRatesScaled)) {\n cumulative += scaledRate;\n if (rand < cumulative) return rarity;\n }\n\n return Object.keys(this.rarityRatesScaled)[0];\n }\n\n private selectItemFromPool(pool: RarityInput): { name: string; weight: number } {\n const items = pool.items.filter(i => i.weight > 0);\n const scaledItems = items.map(i => ({\n ...i,\n scaledWeight: this.toScaled(i.weight),\n }));\n\n const totalScaledWeight = scaledItems.reduce((sum, i) => sum + i.scaledWeight, 0);\n const rand = Math.floor(Math.random() * totalScaledWeight);\n let cumulative = 0;\n\n for (const item of scaledItems) {\n cumulative += item.scaledWeight;\n if (rand < cumulative) {\n return { name: item.name, weight: item.weight };\n }\n }\n\n return items[0]; // Fallback\n }\n\n getDebugInfo(): {\n scale: number;\n rarityRatesScaled: Record<string, number>;\n rarityRatesFloat: Record<string, number>;\n } {\n const rarityRatesFloat: Record<string, number> = {};\n for (const [rarity, scaledRate] of Object.entries(this.rarityRatesScaled)) {\n rarityRatesFloat[rarity] = this.fromScaled(scaledRate);\n }\n\n return {\n scale: GachaEngine.SCALE,\n rarityRatesScaled: { ...this.rarityRatesScaled },\n rarityRatesFloat,\n };\n }\n}\n"],"names":["GachaEngine","config","this","mode","pools","rarityRatesScaled","flatRateMap","Map","dropRateCacheScaled","weightedConfig","scaleRarityRates","rarityRates","validateConfig","Error","_step","_iterator","_createForOfIteratorHelperLoose","done","_step2","_iterator2","value","items","item","weight","name","set","total","Array","from","values","reduce","sum","v","Math","abs","_proto","prototype","scaled","_i","_Object$entries","Object","entries","length","_Object$entries$_i","rarity","rate","toScaled","probability","MAX_SAFE_SCALE","SCALE","round","fromScaled","scaledInt","originalRates","configuredRarities","Set","keys","usedRarities","map","p","missing","filter","r","has","join","totalRate","_iterator3","_step3","pool","i","_iterator4","_step4","some","getItemDropRate","get","_iterator5","_step5","find","totalPoolWeight","baseRarityRateScaled","itemWeightScaled","totalWeightScaled","numeratorScaled","rateScaled","getCumulativeProbabilityForItem","rolls","pow","getRollsForTargetProbability","targetProbability","Infinity","ceil","log","getRateUpItems","flatMap","rateUp","getAllItemDropRates","_this","_ref","dropRate","roll","count","_this2","results","_loop","_step6","rand","random","cumulative","_iterator6","_step6$value","push","selectRarity","selectItemFromPool","floor","_i2","_Object$entries2","_Object$entries2$_i","_this3","_step7","scaledItems","_extends","scaledWeight","totalScaledWeight","_iterator7","getDebugInfo","rarityRatesFloat","_i3","_Object$entries3","_Object$entries3$_i","scale","Number","MAX_SAFE_INTEGER"],"mappings":"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"}
|
package/dist/index.module.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function t(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,a=Array(e);r<e;r++)a[r]=t[r];return a}function e(e,r){var a="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(a)return(a=a.call(e)).next.bind(a);if(Array.isArray(e)||(a=function(e,r){if(e){if("string"==typeof e)return t(e,r);var a={}.toString.call(e).slice(8,-1);return"Object"===a&&e.constructor&&(a=e.constructor.name),"Map"===a||"Set"===a?Array.from(e):"Arguments"===a||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(a)?t(e,r):void 0}}(e))||r&&e&&"number"==typeof e.length){a&&(e=a);var n=0;return function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function r(){return r=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var a in r)({}).hasOwnProperty.call(r,a)&&(t[a]=r[a])}return t},r.apply(null,arguments)}var a,n=/*#__PURE__*/function(){function t(t){if(this.mode=void 0,this.pools=[],this.rarityRatesScaled={},this.flatRateMap=new Map,this.dropRateCacheScaled=new Map,this.mode=t.mode,"weighted"===t.mode){var r=t;this.pools=r.pools,this.rarityRatesScaled=this.scaleRarityRates(r.rarityRates),this.validateConfig(r.rarityRates)}else{if("flatRate"!==t.mode)throw new Error("Unknown gacha mode: "+this.mode);for(var a,n=e(t.pools);!(a=n()).done;)for(var i,o=e(a.value.items);!(i=o()).done;){var s=i.value;if(s.weight<0)throw new Error('FlatRate item "'+s.name+'" must have non-negative weight');this.flatRateMap.set(s.name,s.weight)}var
|
|
1
|
+
function t(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,a=Array(e);r<e;r++)a[r]=t[r];return a}function e(e,r){var a="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(a)return(a=a.call(e)).next.bind(a);if(Array.isArray(e)||(a=function(e,r){if(e){if("string"==typeof e)return t(e,r);var a={}.toString.call(e).slice(8,-1);return"Object"===a&&e.constructor&&(a=e.constructor.name),"Map"===a||"Set"===a?Array.from(e):"Arguments"===a||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(a)?t(e,r):void 0}}(e))||r&&e&&"number"==typeof e.length){a&&(e=a);var n=0;return function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function r(){return r=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var a in r)({}).hasOwnProperty.call(r,a)&&(t[a]=r[a])}return t},r.apply(null,arguments)}var a,n=/*#__PURE__*/function(){function t(t){if(this.mode=void 0,this.pools=[],this.rarityRatesScaled={},this.flatRateMap=new Map,this.dropRateCacheScaled=new Map,this.mode=t.mode,"weighted"===t.mode){var r=t;this.pools=r.pools,this.rarityRatesScaled=this.scaleRarityRates(r.rarityRates),this.validateConfig(r.rarityRates)}else{if("flatRate"!==t.mode)throw new Error("Unknown gacha mode: "+this.mode);for(var a,n=e(t.pools);!(a=n()).done;)for(var i,o=e(a.value.items);!(i=o()).done;){var s=i.value;if(s.weight<0)throw new Error('FlatRate item "'+s.name+'" must have non-negative weight');this.flatRateMap.set(s.name,s.weight)}var l=Array.from(this.flatRateMap.values()).reduce(function(t,e){return t+e},0);if(Math.abs(l-1)>1e-6)throw new Error("FlatRate item rates must sum to 1.0, but got "+l)}}var a=t.prototype;return a.scaleRarityRates=function(t){for(var e={},r=0,a=Object.entries(t);r<a.length;r++){var n=a[r],i=n[0],o=n[1];if(o<0||o>1)throw new Error('Rarity rate for "'+i+'" must be between 0 and 1, got '+o);e[i]=this.toScaled(o)}return e},a.toScaled=function(e){if(e>t.MAX_SAFE_SCALE/t.SCALE)throw new Error("Probability "+e+" too large for safe integer arithmetic");return Math.round(e*t.SCALE)},a.fromScaled=function(e){return e/t.SCALE},a.validateConfig=function(t){var r=new Set(Object.keys(this.rarityRatesScaled)),a=new Set(this.pools.map(function(t){return t.rarity})),n=Array.from(a).filter(function(t){return!r.has(t)});if(n.length>0)throw new Error("Missing rarity rates for: "+n.join(", "));var i=Object.values(t).reduce(function(t,e){return t+e},0);if(Math.abs(i-1)>1e-10)throw new Error("Rarity rates must sum to 1.0, got "+i);for(var o,s=e(this.pools);!(o=s()).done;){var l=o.value;if(0===l.items.length)throw new Error('Rarity "'+l.rarity+'" has no items');if(l.items.reduce(function(t,e){return t+e.weight},0)<=0)throw new Error('Rarity "'+l.rarity+'" has zero total weight');for(var u,h=e(l.items);!(u=h()).done;){var f=u.value;if(f.weight<0)throw new Error('Item "'+f.name+'" weight must be non-negative, got '+f.weight)}if(!l.items.some(function(t){return t.weight>0}))throw new Error('Rarity "'+l.rarity+'" must have at least one item with positive weight')}},a.getItemDropRate=function(r){if("flatRate"===this.mode)return this.flatRateMap.get(r)||0;if(this.dropRateCacheScaled.has(r))return this.fromScaled(this.dropRateCacheScaled.get(r));for(var a,n=e(this.pools);!(a=n()).done;){var i=a.value,o=i.items.find(function(t){return t.name===r});if(o){if(0===o.weight)return this.dropRateCacheScaled.set(r,0),0;var s=i.items.reduce(function(t,e){return t+e.weight},0),l=this.rarityRatesScaled[i.rarity],u=this.toScaled(o.weight),h=this.toScaled(s),f=Math.round(u*l/t.SCALE),c=Math.round(f*t.SCALE/h);return this.dropRateCacheScaled.set(r,c),this.fromScaled(c)}}throw new Error('Item "'+r+'" not found')},a.getCumulativeProbabilityForItem=function(t,e){var r=this.getItemDropRate(t);return 0===r?0:r>=1?1:1-Math.pow(1-r,e)},a.getRollsForTargetProbability=function(t,e){if(e<=0)return 0;if(e>=1)return 1;var r=this.getItemDropRate(t);return r<=0?Infinity:Math.ceil(Math.log(1-e)/Math.log(1-r))},a.getRateUpItems=function(){return"weighted"===this.mode||this.pools.length>0?this.pools.flatMap(function(t){return t.items.filter(function(t){return t.rateUp}).map(function(t){return t.name})}):[]},a.getAllItemDropRates=function(){var t=this;return"flatRate"===this.mode?Array.from(this.flatRateMap.entries()).map(function(t){return{name:t[0],dropRate:t[1],rarity:"flatRate"}}):this.pools.flatMap(function(e){return e.items.map(function(r){return{name:r.name,dropRate:t.getItemDropRate(r.name),rarity:e.rarity}})})},a.roll=function(t){var r=this;void 0===t&&(t=1);for(var a=[],n=function(){if("flatRate"===r.mode)for(var t,n=Math.random(),i=0,o=e(r.flatRateMap.entries());!(t=o()).done;){var s=t.value;if(n<(i+=s[1])){a.push(s[0]);break}}else{var l=r.selectRarity(),u=r.pools.find(function(t){return t.rarity===l}),h=r.selectItemFromPool(u);a.push(h.name)}},i=0;i<t;i++)n();return a},a.selectRarity=function(){for(var e=Math.floor(Math.random()*t.SCALE),r=0,a=0,n=Object.entries(this.rarityRatesScaled);a<n.length;a++){var i=n[a];if(e<(r+=i[1]))return i[0]}return Object.keys(this.rarityRatesScaled)[0]},a.selectItemFromPool=function(t){for(var a,n=this,i=t.items.filter(function(t){return t.weight>0}),o=i.map(function(t){return r({},t,{scaledWeight:n.toScaled(t.weight)})}),s=o.reduce(function(t,e){return t+e.scaledWeight},0),l=Math.floor(Math.random()*s),u=0,h=e(o);!(a=h()).done;){var f=a.value;if(l<(u+=f.scaledWeight))return{name:f.name,weight:f.weight}}return i[0]},a.getDebugInfo=function(){for(var e={},a=0,n=Object.entries(this.rarityRatesScaled);a<n.length;a++){var i=n[a];e[i[0]]=this.fromScaled(i[1])}return{scale:t.SCALE,rarityRatesScaled:r({},this.rarityRatesScaled),rarityRatesFloat:e}},t}();a=n,n.SCALE=1e6,n.MAX_SAFE_SCALE=Math.floor(Number.MAX_SAFE_INTEGER/a.SCALE);export{n as GachaEngine};
|
|
2
2
|
//# sourceMappingURL=index.module.js.map
|
package/dist/index.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.module.js","sources":["../src/gacha-engine.ts"],"sourcesContent":["import {\n RarityInput,\n GachaEngineConfig,\n WeightedGachaEngineConfig,\n FlatRateGachaEngineConfig,\n} from './types';\n\nexport class GachaEngine {\n private static readonly SCALE = 1_000_000;\n private static readonly MAX_SAFE_SCALE = Math.floor(Number.MAX_SAFE_INTEGER / GachaEngine.SCALE);\n\n private mode: 'weighted' | 'flatRate';\n private pools: RarityInput[] = [];\n private rarityRatesScaled: Record<string, number> = {};\n private flatRateMap: Map<string, number> = new Map();\n private dropRateCacheScaled = new Map<string, number>();\n\n constructor(config: GachaEngineConfig) {\n this.mode = config.mode;\n\n if (config.mode === 'weighted') {\n const weightedConfig = config as WeightedGachaEngineConfig;\n this.pools = weightedConfig.pools;\n this.rarityRatesScaled = this.scaleRarityRates(weightedConfig.rarityRates);\n this.validateConfig(weightedConfig.rarityRates);\n } else if (config.mode === 'flatRate') {\n const flatConfig = config as FlatRateGachaEngineConfig;\n for (const pool of flatConfig.pools) {\n for (const item of pool.items) {\n if (item.weight < 0) {\n throw new Error(`FlatRate item \"${item.name}\" must have non-negative weight`);\n }\n this.flatRateMap.set(item.name, item.weight); // Here, interpreted as direct probability\n }\n }\n const total = Array.from(this.flatRateMap.values()).reduce((sum, v) => sum + v, 0);\n if (Math.abs(total - 1.0) > 1e-6) {\n throw new Error(`FlatRate item rates must sum to 1.0, but got ${total}`);\n }\n } else {\n throw new Error(`Unknown gacha mode: ${this.mode}`);\n }\n }\n\n private scaleRarityRates(rarityRates: Record<string, number>): Record<string, number> {\n const scaled: Record<string, number> = {};\n for (const [rarity, rate] of Object.entries(rarityRates)) {\n if (rate < 0 || rate > 1) {\n throw new Error(`Rarity rate for \"${rarity}\" must be between 0 and 1, got ${rate}`);\n }\n scaled[rarity] = this.toScaled(rate);\n }\n return scaled;\n }\n\n private toScaled(probability: number): number {\n if (probability > GachaEngine.MAX_SAFE_SCALE / GachaEngine.SCALE) {\n throw new Error(`Probability ${probability} too large for safe integer arithmetic`);\n }\n return Math.round(probability * GachaEngine.SCALE);\n }\n\n private fromScaled(scaledInt: number): number {\n return scaledInt / GachaEngine.SCALE;\n }\n\n private validateConfig(originalRates: Record<string, number>): void {\n const configuredRarities = new Set(Object.keys(this.rarityRatesScaled));\n const usedRarities = new Set(this.pools.map(p => p.rarity));\n const missing = Array.from(usedRarities).filter(r => !configuredRarities.has(r));\n\n if (missing.length > 0) {\n throw new Error(`Missing rarity rates for: ${missing.join(', ')}`);\n }\n\n const totalRate = Object.values(originalRates).reduce((sum, rate) => sum + rate, 0);\n if (Math.abs(totalRate - 1.0) > 1e-10) {\n throw new Error(`Rarity rates must sum to 1.0, got ${totalRate}`);\n }\n\n for (const pool of this.pools) {\n if (pool.items.length === 0) {\n throw new Error(`Rarity \"${pool.rarity}\" has no items`);\n }\n\n const totalWeight = pool.items.reduce((sum, i) => sum + i.weight, 0);\n if (totalWeight <= 0) {\n throw new Error(`Rarity \"${pool.rarity}\" has zero total weight`);\n }\n\n for (const item of pool.items) {\n if (item.weight < 0) {\n throw new Error(`Item \"${item.name}\" weight must be non-negative, got ${item.weight}`);\n }\n }\n\n if (!pool.items.some(i => i.weight > 0)) {\n throw new Error(`Rarity \"${pool.rarity}\" must have at least one item with positive weight`);\n }\n }\n }\n\n getItemDropRate(name: string): number {\n if (this.mode === 'flatRate') {\n return this.flatRateMap.get(name) || 0;\n }\n\n if (this.dropRateCacheScaled.has(name)) {\n return this.fromScaled(this.dropRateCacheScaled.get(name)!);\n }\n\n for (const pool of this.pools) {\n const item = pool.items.find(i => i.name === name);\n if (item) {\n if (item.weight === 0) {\n this.dropRateCacheScaled.set(name, 0);\n return 0;\n }\n\n const totalPoolWeight = pool.items.reduce((sum, i) => sum + i.weight, 0);\n const baseRarityRateScaled = this.rarityRatesScaled[pool.rarity];\n const itemWeightScaled = this.toScaled(item.weight);\n const totalWeightScaled = this.toScaled(totalPoolWeight);\n const numeratorScaled = Math.round((itemWeightScaled * baseRarityRateScaled) / GachaEngine.SCALE);\n const rateScaled = Math.round((numeratorScaled * GachaEngine.SCALE) / totalWeightScaled);\n\n this.dropRateCacheScaled.set(name, rateScaled);\n return this.fromScaled(rateScaled);\n }\n }\n\n throw new Error(`Item \"${name}\" not found`);\n }\n\n getCumulativeProbabilityForItem(name: string, rolls: number): number {\n const rate = this.getItemDropRate(name);\n if (rate === 0) return 0;\n if (rate >= 1) return 1;\n\n const cumulativeFailProbability = Math.pow(1 - rate, rolls);\n return 1 - cumulativeFailProbability;\n }\n\n getRollsForTargetProbability(name: string, targetProbability: number): number {\n if (targetProbability <= 0) return 0;\n if (targetProbability >= 1) return 1;\n\n const rate = this.getItemDropRate(name);\n if (rate <= 0) return Infinity;\n return Math.ceil(Math.log(1 - targetProbability) / Math.log(1 - rate));\n }\n\n getRateUpItems(): string[] {\n return this.pools.flatMap(p => p.items.filter(i => i.rateUp).map(i => i.name));\n }\n\n getAllItemDropRates(): { name: string; dropRate: number; rarity: string }[] {\n if (this.mode === 'flatRate') {\n return Array.from(this.flatRateMap.entries()).map(([name, dropRate]) => ({\n name,\n dropRate,\n rarity: 'flatRate',\n }));\n }\n\n return this.pools.flatMap(p =>\n p.items.map(i => ({\n name: i.name,\n dropRate: this.getItemDropRate(i.name),\n rarity: p.rarity,\n }))\n );\n }\n\n roll(count: number = 1): string[] {\n const results: string[] = [];\n for (let i = 0; i < count; i++) {\n if (this.mode === 'flatRate') {\n const rand = Math.random();\n let cumulative = 0;\n for (const [name, rate] of this.flatRateMap.entries()) {\n cumulative += rate;\n if (rand < cumulative) {\n results.push(name);\n break;\n }\n }\n } else {\n const rarity = this.selectRarity();\n const pool = this.pools.find(p => p.rarity === rarity)!;\n const item = this.selectItemFromPool(pool);\n results.push(item.name);\n }\n }\n return results;\n }\n\n private selectRarity(): string {\n const rand = Math.floor(Math.random() * GachaEngine.SCALE);\n let cumulative = 0;\n\n for (const [rarity, scaledRate] of Object.entries(this.rarityRatesScaled)) {\n cumulative += scaledRate;\n if (rand < cumulative) return rarity;\n }\n\n return Object.keys(this.rarityRatesScaled)[0];\n }\n\n private selectItemFromPool(pool: RarityInput): { name: string; weight: number } {\n const items = pool.items.filter(i => i.weight > 0);\n const scaledItems = items.map(i => ({\n ...i,\n scaledWeight: this.toScaled(i.weight),\n }));\n\n const totalScaledWeight = scaledItems.reduce((sum, i) => sum + i.scaledWeight, 0);\n const rand = Math.floor(Math.random() * totalScaledWeight);\n let cumulative = 0;\n\n for (const item of scaledItems) {\n cumulative += item.scaledWeight;\n if (rand < cumulative) {\n return { name: item.name, weight: item.weight };\n }\n }\n\n return items[0]; // Fallback\n }\n\n getDebugInfo(): {\n scale: number;\n rarityRatesScaled: Record<string, number>;\n rarityRatesFloat: Record<string, number>;\n } {\n const rarityRatesFloat: Record<string, number> = {};\n for (const [rarity, scaledRate] of Object.entries(this.rarityRatesScaled)) {\n rarityRatesFloat[rarity] = this.fromScaled(scaledRate);\n }\n\n return {\n scale: GachaEngine.SCALE,\n rarityRatesScaled: { ...this.rarityRatesScaled },\n rarityRatesFloat,\n };\n }\n}\n"],"names":["GachaEngine","config","this","mode","pools","rarityRatesScaled","flatRateMap","Map","dropRateCacheScaled","weightedConfig","scaleRarityRates","rarityRates","validateConfig","Error","_step","_iterator","_createForOfIteratorHelperLoose","done","_step2","_iterator2","value","items","item","weight","name","set","total","Array","from","values","reduce","sum","v","Math","abs","_proto","prototype","scaled","_i","_Object$entries","Object","entries","length","_Object$entries$_i","rarity","rate","toScaled","probability","MAX_SAFE_SCALE","SCALE","round","fromScaled","scaledInt","originalRates","configuredRarities","Set","keys","usedRarities","map","p","missing","filter","r","has","join","totalRate","_iterator3","_step3","pool","i","_step4","_iterator4","some","getItemDropRate","get","_iterator5","_step5","find","totalPoolWeight","baseRarityRateScaled","itemWeightScaled","totalWeightScaled","numeratorScaled","rateScaled","getCumulativeProbabilityForItem","rolls","pow","getRollsForTargetProbability","targetProbability","Infinity","ceil","log","getRateUpItems","flatMap","rateUp","getAllItemDropRates","_this","_ref","dropRate","roll","count","_this2","results","_loop","_step6","rand","random","cumulative","_iterator6","_step6$value","push","selectRarity","selectItemFromPool","floor","_i2","_Object$entries2","_Object$entries2$_i","scaledRate","_step7","_this3","scaledItems","_extends","scaledWeight","totalScaledWeight","_iterator7","getDebugInfo","rarityRatesFloat","_i3","_Object$entries3","_Object$entries3$_i","scale","Number","MAX_SAFE_INTEGER"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.module.js","sources":["../src/gacha-engine.ts"],"sourcesContent":["import {\n RarityInput,\n GachaEngineConfig,\n WeightedGachaEngineConfig,\n FlatRateGachaEngineConfig,\n} from './types';\n\nexport class GachaEngine {\n private static readonly SCALE = 1_000_000;\n private static readonly MAX_SAFE_SCALE = Math.floor(Number.MAX_SAFE_INTEGER / GachaEngine.SCALE);\n\n private mode: 'weighted' | 'flatRate';\n private pools: RarityInput[] = [];\n private rarityRatesScaled: Record<string, number> = {};\n private flatRateMap: Map<string, number> = new Map();\n private dropRateCacheScaled = new Map<string, number>();\n\n constructor(config: GachaEngineConfig) {\n this.mode = config.mode;\n\n if (config.mode === 'weighted') {\n const weightedConfig = config as WeightedGachaEngineConfig;\n this.pools = weightedConfig.pools;\n this.rarityRatesScaled = this.scaleRarityRates(weightedConfig.rarityRates);\n this.validateConfig(weightedConfig.rarityRates);\n } else if (config.mode === 'flatRate') {\n const flatConfig = config as FlatRateGachaEngineConfig;\n for (const pool of flatConfig.pools) {\n for (const item of pool.items) {\n if (item.weight < 0) {\n throw new Error(`FlatRate item \"${item.name}\" must have non-negative weight`);\n }\n this.flatRateMap.set(item.name, item.weight); // Here, interpreted as direct probability\n }\n }\n const total = Array.from(this.flatRateMap.values()).reduce((sum, v) => sum + v, 0);\n if (Math.abs(total - 1.0) > 1e-6) {\n throw new Error(`FlatRate item rates must sum to 1.0, but got ${total}`);\n }\n } else {\n throw new Error(`Unknown gacha mode: ${this.mode}`);\n }\n }\n\n private scaleRarityRates(rarityRates: Record<string, number>): Record<string, number> {\n const scaled: Record<string, number> = {};\n for (const [rarity, rate] of Object.entries(rarityRates)) {\n if (rate < 0 || rate > 1) {\n throw new Error(`Rarity rate for \"${rarity}\" must be between 0 and 1, got ${rate}`);\n }\n scaled[rarity] = this.toScaled(rate);\n }\n return scaled;\n }\n\n private toScaled(probability: number): number {\n if (probability > GachaEngine.MAX_SAFE_SCALE / GachaEngine.SCALE) {\n throw new Error(`Probability ${probability} too large for safe integer arithmetic`);\n }\n return Math.round(probability * GachaEngine.SCALE);\n }\n\n private fromScaled(scaledInt: number): number {\n return scaledInt / GachaEngine.SCALE;\n }\n\n private validateConfig(originalRates: Record<string, number>): void {\n const configuredRarities = new Set(Object.keys(this.rarityRatesScaled));\n const usedRarities = new Set(this.pools.map(p => p.rarity));\n const missing = Array.from(usedRarities).filter(r => !configuredRarities.has(r));\n\n if (missing.length > 0) {\n throw new Error(`Missing rarity rates for: ${missing.join(', ')}`);\n }\n\n const totalRate = Object.values(originalRates).reduce((sum, rate) => sum + rate, 0);\n if (Math.abs(totalRate - 1.0) > 1e-10) {\n throw new Error(`Rarity rates must sum to 1.0, got ${totalRate}`);\n }\n\n for (const pool of this.pools) {\n if (pool.items.length === 0) {\n throw new Error(`Rarity \"${pool.rarity}\" has no items`);\n }\n\n const totalWeight = pool.items.reduce((sum, i) => sum + i.weight, 0);\n if (totalWeight <= 0) {\n throw new Error(`Rarity \"${pool.rarity}\" has zero total weight`);\n }\n\n for (const item of pool.items) {\n if (item.weight < 0) {\n throw new Error(`Item \"${item.name}\" weight must be non-negative, got ${item.weight}`);\n }\n }\n\n if (!pool.items.some(i => i.weight > 0)) {\n throw new Error(`Rarity \"${pool.rarity}\" must have at least one item with positive weight`);\n }\n }\n }\n\n getItemDropRate(name: string): number {\n if (this.mode === 'flatRate') {\n return this.flatRateMap.get(name) || 0;\n }\n\n if (this.dropRateCacheScaled.has(name)) {\n return this.fromScaled(this.dropRateCacheScaled.get(name)!);\n }\n\n for (const pool of this.pools) {\n const item = pool.items.find(i => i.name === name);\n if (item) {\n if (item.weight === 0) {\n this.dropRateCacheScaled.set(name, 0);\n return 0;\n }\n\n const totalPoolWeight = pool.items.reduce((sum, i) => sum + i.weight, 0);\n const baseRarityRateScaled = this.rarityRatesScaled[pool.rarity];\n const itemWeightScaled = this.toScaled(item.weight);\n const totalWeightScaled = this.toScaled(totalPoolWeight);\n const numeratorScaled = Math.round((itemWeightScaled * baseRarityRateScaled) / GachaEngine.SCALE);\n const rateScaled = Math.round((numeratorScaled * GachaEngine.SCALE) / totalWeightScaled);\n\n this.dropRateCacheScaled.set(name, rateScaled);\n return this.fromScaled(rateScaled);\n }\n }\n\n throw new Error(`Item \"${name}\" not found`);\n }\n\n getCumulativeProbabilityForItem(name: string, rolls: number): number {\n const rate = this.getItemDropRate(name);\n if (rate === 0) return 0;\n if (rate >= 1) return 1;\n\n const cumulativeFailProbability = Math.pow(1 - rate, rolls);\n return 1 - cumulativeFailProbability;\n }\n\n getRollsForTargetProbability(name: string, targetProbability: number): number {\n if (targetProbability <= 0) return 0;\n if (targetProbability >= 1) return 1;\n\n const rate = this.getItemDropRate(name);\n if (rate <= 0) return Infinity;\n return Math.ceil(Math.log(1 - targetProbability) / Math.log(1 - rate));\n }\n\n getRateUpItems(): string[] {\n if (this.mode === 'weighted') {\n return this.pools.flatMap(p => p.items.filter(i => i.rateUp).map(i => i.name));\n } else {\n if (this.pools.length > 0) {\n return this.pools.flatMap(p => p.items.filter(i => i.rateUp).map(i => i.name));\n }\n return [];\n }\n}\n\n\n getAllItemDropRates(): { name: string; dropRate: number; rarity: string }[] {\n if (this.mode === 'flatRate') {\n return Array.from(this.flatRateMap.entries()).map(([name, dropRate]) => ({\n name,\n dropRate,\n rarity: 'flatRate',\n }));\n }\n\n return this.pools.flatMap(p =>\n p.items.map(i => ({\n name: i.name,\n dropRate: this.getItemDropRate(i.name),\n rarity: p.rarity,\n }))\n );\n }\n\n roll(count: number = 1): string[] {\n const results: string[] = [];\n for (let i = 0; i < count; i++) {\n if (this.mode === 'flatRate') {\n const rand = Math.random();\n let cumulative = 0;\n for (const [name, rate] of this.flatRateMap.entries()) {\n cumulative += rate;\n if (rand < cumulative) {\n results.push(name);\n break;\n }\n }\n } else {\n const rarity = this.selectRarity();\n const pool = this.pools.find(p => p.rarity === rarity)!;\n const item = this.selectItemFromPool(pool);\n results.push(item.name);\n }\n }\n return results;\n }\n\n private selectRarity(): string {\n const rand = Math.floor(Math.random() * GachaEngine.SCALE);\n let cumulative = 0;\n\n for (const [rarity, scaledRate] of Object.entries(this.rarityRatesScaled)) {\n cumulative += scaledRate;\n if (rand < cumulative) return rarity;\n }\n\n return Object.keys(this.rarityRatesScaled)[0];\n }\n\n private selectItemFromPool(pool: RarityInput): { name: string; weight: number } {\n const items = pool.items.filter(i => i.weight > 0);\n const scaledItems = items.map(i => ({\n ...i,\n scaledWeight: this.toScaled(i.weight),\n }));\n\n const totalScaledWeight = scaledItems.reduce((sum, i) => sum + i.scaledWeight, 0);\n const rand = Math.floor(Math.random() * totalScaledWeight);\n let cumulative = 0;\n\n for (const item of scaledItems) {\n cumulative += item.scaledWeight;\n if (rand < cumulative) {\n return { name: item.name, weight: item.weight };\n }\n }\n\n return items[0]; // Fallback\n }\n\n getDebugInfo(): {\n scale: number;\n rarityRatesScaled: Record<string, number>;\n rarityRatesFloat: Record<string, number>;\n } {\n const rarityRatesFloat: Record<string, number> = {};\n for (const [rarity, scaledRate] of Object.entries(this.rarityRatesScaled)) {\n rarityRatesFloat[rarity] = this.fromScaled(scaledRate);\n }\n\n return {\n scale: GachaEngine.SCALE,\n rarityRatesScaled: { ...this.rarityRatesScaled },\n rarityRatesFloat,\n };\n }\n}\n"],"names":["GachaEngine","config","this","mode","pools","rarityRatesScaled","flatRateMap","Map","dropRateCacheScaled","weightedConfig","scaleRarityRates","rarityRates","validateConfig","Error","_step","_iterator","_createForOfIteratorHelperLoose","done","_step2","_iterator2","value","items","item","weight","name","set","total","Array","from","values","reduce","sum","v","Math","abs","_proto","prototype","scaled","_i","_Object$entries","Object","entries","length","_Object$entries$_i","rarity","rate","toScaled","probability","MAX_SAFE_SCALE","SCALE","round","fromScaled","scaledInt","originalRates","configuredRarities","Set","keys","usedRarities","map","p","missing","filter","r","has","join","totalRate","_iterator3","_step3","pool","i","_iterator4","_step4","some","getItemDropRate","get","_iterator5","_step5","find","totalPoolWeight","baseRarityRateScaled","itemWeightScaled","totalWeightScaled","numeratorScaled","rateScaled","getCumulativeProbabilityForItem","rolls","pow","getRollsForTargetProbability","targetProbability","Infinity","ceil","log","getRateUpItems","flatMap","rateUp","getAllItemDropRates","_this","_ref","dropRate","roll","count","_this2","results","_loop","_step6","rand","random","cumulative","_iterator6","_step6$value","push","selectRarity","selectItemFromPool","floor","_i2","_Object$entries2","_Object$entries2$_i","_this3","_step7","scaledItems","_extends","scaledWeight","totalScaledWeight","_iterator7","getDebugInfo","rarityRatesFloat","_i3","_Object$entries3","_Object$entries3$_i","scale","Number","MAX_SAFE_INTEGER"],"mappings":"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"}
|
package/dist/index.umd.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t||self).AllemandiGachaEngine={})}(this,function(t){function e(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,a=Array(e);r<e;r++)a[r]=t[r];return a}function r(t,r){var a="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(a)return(a=a.call(t)).next.bind(a);if(Array.isArray(t)||(a=function(t,r){if(t){if("string"==typeof t)return e(t,r);var a={}.toString.call(t).slice(8,-1);return"Object"===a&&t.constructor&&(a=t.constructor.name),"Map"===a||"Set"===a?Array.from(t):"Arguments"===a||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(a)?e(t,r):void 0}}(t))||r&&t&&"number"==typeof t.length){a&&(t=a);var n=0;return function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function a(){return a=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var a in r)({}).hasOwnProperty.call(r,a)&&(t[a]=r[a])}return t},a.apply(null,arguments)}var n,i=/*#__PURE__*/function(){function t(t){if(this.mode=void 0,this.pools=[],this.rarityRatesScaled={},this.flatRateMap=new Map,this.dropRateCacheScaled=new Map,this.mode=t.mode,"weighted"===t.mode){var e=t;this.pools=e.pools,this.rarityRatesScaled=this.scaleRarityRates(e.rarityRates),this.validateConfig(e.rarityRates)}else{if("flatRate"!==t.mode)throw new Error("Unknown gacha mode: "+this.mode);for(var a,n=r(t.pools);!(a=n()).done;)for(var i,o=r(a.value.items);!(i=o()).done;){var s=i.value;if(s.weight<0)throw new Error('FlatRate item "'+s.name+'" must have non-negative weight');this.flatRateMap.set(s.name,s.weight)}var
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t||self).AllemandiGachaEngine={})}(this,function(t){function e(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,a=Array(e);r<e;r++)a[r]=t[r];return a}function r(t,r){var a="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(a)return(a=a.call(t)).next.bind(a);if(Array.isArray(t)||(a=function(t,r){if(t){if("string"==typeof t)return e(t,r);var a={}.toString.call(t).slice(8,-1);return"Object"===a&&t.constructor&&(a=t.constructor.name),"Map"===a||"Set"===a?Array.from(t):"Arguments"===a||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(a)?e(t,r):void 0}}(t))||r&&t&&"number"==typeof t.length){a&&(t=a);var n=0;return function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function a(){return a=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var a in r)({}).hasOwnProperty.call(r,a)&&(t[a]=r[a])}return t},a.apply(null,arguments)}var n,i=/*#__PURE__*/function(){function t(t){if(this.mode=void 0,this.pools=[],this.rarityRatesScaled={},this.flatRateMap=new Map,this.dropRateCacheScaled=new Map,this.mode=t.mode,"weighted"===t.mode){var e=t;this.pools=e.pools,this.rarityRatesScaled=this.scaleRarityRates(e.rarityRates),this.validateConfig(e.rarityRates)}else{if("flatRate"!==t.mode)throw new Error("Unknown gacha mode: "+this.mode);for(var a,n=r(t.pools);!(a=n()).done;)for(var i,o=r(a.value.items);!(i=o()).done;){var s=i.value;if(s.weight<0)throw new Error('FlatRate item "'+s.name+'" must have non-negative weight');this.flatRateMap.set(s.name,s.weight)}var l=Array.from(this.flatRateMap.values()).reduce(function(t,e){return t+e},0);if(Math.abs(l-1)>1e-6)throw new Error("FlatRate item rates must sum to 1.0, but got "+l)}}var e=t.prototype;return e.scaleRarityRates=function(t){for(var e={},r=0,a=Object.entries(t);r<a.length;r++){var n=a[r],i=n[0],o=n[1];if(o<0||o>1)throw new Error('Rarity rate for "'+i+'" must be between 0 and 1, got '+o);e[i]=this.toScaled(o)}return e},e.toScaled=function(e){if(e>t.MAX_SAFE_SCALE/t.SCALE)throw new Error("Probability "+e+" too large for safe integer arithmetic");return Math.round(e*t.SCALE)},e.fromScaled=function(e){return e/t.SCALE},e.validateConfig=function(t){var e=new Set(Object.keys(this.rarityRatesScaled)),a=new Set(this.pools.map(function(t){return t.rarity})),n=Array.from(a).filter(function(t){return!e.has(t)});if(n.length>0)throw new Error("Missing rarity rates for: "+n.join(", "));var i=Object.values(t).reduce(function(t,e){return t+e},0);if(Math.abs(i-1)>1e-10)throw new Error("Rarity rates must sum to 1.0, got "+i);for(var o,s=r(this.pools);!(o=s()).done;){var l=o.value;if(0===l.items.length)throw new Error('Rarity "'+l.rarity+'" has no items');if(l.items.reduce(function(t,e){return t+e.weight},0)<=0)throw new Error('Rarity "'+l.rarity+'" has zero total weight');for(var f,u=r(l.items);!(f=u()).done;){var h=f.value;if(h.weight<0)throw new Error('Item "'+h.name+'" weight must be non-negative, got '+h.weight)}if(!l.items.some(function(t){return t.weight>0}))throw new Error('Rarity "'+l.rarity+'" must have at least one item with positive weight')}},e.getItemDropRate=function(e){if("flatRate"===this.mode)return this.flatRateMap.get(e)||0;if(this.dropRateCacheScaled.has(e))return this.fromScaled(this.dropRateCacheScaled.get(e));for(var a,n=r(this.pools);!(a=n()).done;){var i=a.value,o=i.items.find(function(t){return t.name===e});if(o){if(0===o.weight)return this.dropRateCacheScaled.set(e,0),0;var s=i.items.reduce(function(t,e){return t+e.weight},0),l=this.rarityRatesScaled[i.rarity],f=this.toScaled(o.weight),u=this.toScaled(s),h=Math.round(f*l/t.SCALE),c=Math.round(h*t.SCALE/u);return this.dropRateCacheScaled.set(e,c),this.fromScaled(c)}}throw new Error('Item "'+e+'" not found')},e.getCumulativeProbabilityForItem=function(t,e){var r=this.getItemDropRate(t);return 0===r?0:r>=1?1:1-Math.pow(1-r,e)},e.getRollsForTargetProbability=function(t,e){if(e<=0)return 0;if(e>=1)return 1;var r=this.getItemDropRate(t);return r<=0?Infinity:Math.ceil(Math.log(1-e)/Math.log(1-r))},e.getRateUpItems=function(){return"weighted"===this.mode||this.pools.length>0?this.pools.flatMap(function(t){return t.items.filter(function(t){return t.rateUp}).map(function(t){return t.name})}):[]},e.getAllItemDropRates=function(){var t=this;return"flatRate"===this.mode?Array.from(this.flatRateMap.entries()).map(function(t){return{name:t[0],dropRate:t[1],rarity:"flatRate"}}):this.pools.flatMap(function(e){return e.items.map(function(r){return{name:r.name,dropRate:t.getItemDropRate(r.name),rarity:e.rarity}})})},e.roll=function(t){var e=this;void 0===t&&(t=1);for(var a=[],n=function(){if("flatRate"===e.mode)for(var t,n=Math.random(),i=0,o=r(e.flatRateMap.entries());!(t=o()).done;){var s=t.value;if(n<(i+=s[1])){a.push(s[0]);break}}else{var l=e.selectRarity(),f=e.pools.find(function(t){return t.rarity===l}),u=e.selectItemFromPool(f);a.push(u.name)}},i=0;i<t;i++)n();return a},e.selectRarity=function(){for(var e=Math.floor(Math.random()*t.SCALE),r=0,a=0,n=Object.entries(this.rarityRatesScaled);a<n.length;a++){var i=n[a];if(e<(r+=i[1]))return i[0]}return Object.keys(this.rarityRatesScaled)[0]},e.selectItemFromPool=function(t){for(var e,n=this,i=t.items.filter(function(t){return t.weight>0}),o=i.map(function(t){return a({},t,{scaledWeight:n.toScaled(t.weight)})}),s=o.reduce(function(t,e){return t+e.scaledWeight},0),l=Math.floor(Math.random()*s),f=0,u=r(o);!(e=u()).done;){var h=e.value;if(l<(f+=h.scaledWeight))return{name:h.name,weight:h.weight}}return i[0]},e.getDebugInfo=function(){for(var e={},r=0,n=Object.entries(this.rarityRatesScaled);r<n.length;r++){var i=n[r];e[i[0]]=this.fromScaled(i[1])}return{scale:t.SCALE,rarityRatesScaled:a({},this.rarityRatesScaled),rarityRatesFloat:e}},t}();n=i,i.SCALE=1e6,i.MAX_SAFE_SCALE=Math.floor(Number.MAX_SAFE_INTEGER/n.SCALE),t.GachaEngine=i});
|
|
2
2
|
//# sourceMappingURL=index.umd.js.map
|
package/dist/index.umd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.umd.js","sources":["../src/gacha-engine.ts"],"sourcesContent":["import {\n RarityInput,\n GachaEngineConfig,\n WeightedGachaEngineConfig,\n FlatRateGachaEngineConfig,\n} from './types';\n\nexport class GachaEngine {\n private static readonly SCALE = 1_000_000;\n private static readonly MAX_SAFE_SCALE = Math.floor(Number.MAX_SAFE_INTEGER / GachaEngine.SCALE);\n\n private mode: 'weighted' | 'flatRate';\n private pools: RarityInput[] = [];\n private rarityRatesScaled: Record<string, number> = {};\n private flatRateMap: Map<string, number> = new Map();\n private dropRateCacheScaled = new Map<string, number>();\n\n constructor(config: GachaEngineConfig) {\n this.mode = config.mode;\n\n if (config.mode === 'weighted') {\n const weightedConfig = config as WeightedGachaEngineConfig;\n this.pools = weightedConfig.pools;\n this.rarityRatesScaled = this.scaleRarityRates(weightedConfig.rarityRates);\n this.validateConfig(weightedConfig.rarityRates);\n } else if (config.mode === 'flatRate') {\n const flatConfig = config as FlatRateGachaEngineConfig;\n for (const pool of flatConfig.pools) {\n for (const item of pool.items) {\n if (item.weight < 0) {\n throw new Error(`FlatRate item \"${item.name}\" must have non-negative weight`);\n }\n this.flatRateMap.set(item.name, item.weight); // Here, interpreted as direct probability\n }\n }\n const total = Array.from(this.flatRateMap.values()).reduce((sum, v) => sum + v, 0);\n if (Math.abs(total - 1.0) > 1e-6) {\n throw new Error(`FlatRate item rates must sum to 1.0, but got ${total}`);\n }\n } else {\n throw new Error(`Unknown gacha mode: ${this.mode}`);\n }\n }\n\n private scaleRarityRates(rarityRates: Record<string, number>): Record<string, number> {\n const scaled: Record<string, number> = {};\n for (const [rarity, rate] of Object.entries(rarityRates)) {\n if (rate < 0 || rate > 1) {\n throw new Error(`Rarity rate for \"${rarity}\" must be between 0 and 1, got ${rate}`);\n }\n scaled[rarity] = this.toScaled(rate);\n }\n return scaled;\n }\n\n private toScaled(probability: number): number {\n if (probability > GachaEngine.MAX_SAFE_SCALE / GachaEngine.SCALE) {\n throw new Error(`Probability ${probability} too large for safe integer arithmetic`);\n }\n return Math.round(probability * GachaEngine.SCALE);\n }\n\n private fromScaled(scaledInt: number): number {\n return scaledInt / GachaEngine.SCALE;\n }\n\n private validateConfig(originalRates: Record<string, number>): void {\n const configuredRarities = new Set(Object.keys(this.rarityRatesScaled));\n const usedRarities = new Set(this.pools.map(p => p.rarity));\n const missing = Array.from(usedRarities).filter(r => !configuredRarities.has(r));\n\n if (missing.length > 0) {\n throw new Error(`Missing rarity rates for: ${missing.join(', ')}`);\n }\n\n const totalRate = Object.values(originalRates).reduce((sum, rate) => sum + rate, 0);\n if (Math.abs(totalRate - 1.0) > 1e-10) {\n throw new Error(`Rarity rates must sum to 1.0, got ${totalRate}`);\n }\n\n for (const pool of this.pools) {\n if (pool.items.length === 0) {\n throw new Error(`Rarity \"${pool.rarity}\" has no items`);\n }\n\n const totalWeight = pool.items.reduce((sum, i) => sum + i.weight, 0);\n if (totalWeight <= 0) {\n throw new Error(`Rarity \"${pool.rarity}\" has zero total weight`);\n }\n\n for (const item of pool.items) {\n if (item.weight < 0) {\n throw new Error(`Item \"${item.name}\" weight must be non-negative, got ${item.weight}`);\n }\n }\n\n if (!pool.items.some(i => i.weight > 0)) {\n throw new Error(`Rarity \"${pool.rarity}\" must have at least one item with positive weight`);\n }\n }\n }\n\n getItemDropRate(name: string): number {\n if (this.mode === 'flatRate') {\n return this.flatRateMap.get(name) || 0;\n }\n\n if (this.dropRateCacheScaled.has(name)) {\n return this.fromScaled(this.dropRateCacheScaled.get(name)!);\n }\n\n for (const pool of this.pools) {\n const item = pool.items.find(i => i.name === name);\n if (item) {\n if (item.weight === 0) {\n this.dropRateCacheScaled.set(name, 0);\n return 0;\n }\n\n const totalPoolWeight = pool.items.reduce((sum, i) => sum + i.weight, 0);\n const baseRarityRateScaled = this.rarityRatesScaled[pool.rarity];\n const itemWeightScaled = this.toScaled(item.weight);\n const totalWeightScaled = this.toScaled(totalPoolWeight);\n const numeratorScaled = Math.round((itemWeightScaled * baseRarityRateScaled) / GachaEngine.SCALE);\n const rateScaled = Math.round((numeratorScaled * GachaEngine.SCALE) / totalWeightScaled);\n\n this.dropRateCacheScaled.set(name, rateScaled);\n return this.fromScaled(rateScaled);\n }\n }\n\n throw new Error(`Item \"${name}\" not found`);\n }\n\n getCumulativeProbabilityForItem(name: string, rolls: number): number {\n const rate = this.getItemDropRate(name);\n if (rate === 0) return 0;\n if (rate >= 1) return 1;\n\n const cumulativeFailProbability = Math.pow(1 - rate, rolls);\n return 1 - cumulativeFailProbability;\n }\n\n getRollsForTargetProbability(name: string, targetProbability: number): number {\n if (targetProbability <= 0) return 0;\n if (targetProbability >= 1) return 1;\n\n const rate = this.getItemDropRate(name);\n if (rate <= 0) return Infinity;\n return Math.ceil(Math.log(1 - targetProbability) / Math.log(1 - rate));\n }\n\n getRateUpItems(): string[] {\n return this.pools.flatMap(p => p.items.filter(i => i.rateUp).map(i => i.name));\n }\n\n getAllItemDropRates(): { name: string; dropRate: number; rarity: string }[] {\n if (this.mode === 'flatRate') {\n return Array.from(this.flatRateMap.entries()).map(([name, dropRate]) => ({\n name,\n dropRate,\n rarity: 'flatRate',\n }));\n }\n\n return this.pools.flatMap(p =>\n p.items.map(i => ({\n name: i.name,\n dropRate: this.getItemDropRate(i.name),\n rarity: p.rarity,\n }))\n );\n }\n\n roll(count: number = 1): string[] {\n const results: string[] = [];\n for (let i = 0; i < count; i++) {\n if (this.mode === 'flatRate') {\n const rand = Math.random();\n let cumulative = 0;\n for (const [name, rate] of this.flatRateMap.entries()) {\n cumulative += rate;\n if (rand < cumulative) {\n results.push(name);\n break;\n }\n }\n } else {\n const rarity = this.selectRarity();\n const pool = this.pools.find(p => p.rarity === rarity)!;\n const item = this.selectItemFromPool(pool);\n results.push(item.name);\n }\n }\n return results;\n }\n\n private selectRarity(): string {\n const rand = Math.floor(Math.random() * GachaEngine.SCALE);\n let cumulative = 0;\n\n for (const [rarity, scaledRate] of Object.entries(this.rarityRatesScaled)) {\n cumulative += scaledRate;\n if (rand < cumulative) return rarity;\n }\n\n return Object.keys(this.rarityRatesScaled)[0];\n }\n\n private selectItemFromPool(pool: RarityInput): { name: string; weight: number } {\n const items = pool.items.filter(i => i.weight > 0);\n const scaledItems = items.map(i => ({\n ...i,\n scaledWeight: this.toScaled(i.weight),\n }));\n\n const totalScaledWeight = scaledItems.reduce((sum, i) => sum + i.scaledWeight, 0);\n const rand = Math.floor(Math.random() * totalScaledWeight);\n let cumulative = 0;\n\n for (const item of scaledItems) {\n cumulative += item.scaledWeight;\n if (rand < cumulative) {\n return { name: item.name, weight: item.weight };\n }\n }\n\n return items[0]; // Fallback\n }\n\n getDebugInfo(): {\n scale: number;\n rarityRatesScaled: Record<string, number>;\n rarityRatesFloat: Record<string, number>;\n } {\n const rarityRatesFloat: Record<string, number> = {};\n for (const [rarity, scaledRate] of Object.entries(this.rarityRatesScaled)) {\n rarityRatesFloat[rarity] = this.fromScaled(scaledRate);\n }\n\n return {\n scale: GachaEngine.SCALE,\n rarityRatesScaled: { ...this.rarityRatesScaled },\n rarityRatesFloat,\n };\n }\n}\n"],"names":["GachaEngine","config","this","mode","pools","rarityRatesScaled","flatRateMap","Map","dropRateCacheScaled","weightedConfig","scaleRarityRates","rarityRates","validateConfig","Error","_step","_iterator","_createForOfIteratorHelperLoose","done","_step2","_iterator2","value","items","item","weight","name","set","total","Array","from","values","reduce","sum","v","Math","abs","_proto","prototype","scaled","_i","_Object$entries","Object","entries","length","_Object$entries$_i","rarity","rate","toScaled","probability","MAX_SAFE_SCALE","SCALE","round","fromScaled","scaledInt","originalRates","configuredRarities","Set","keys","usedRarities","map","p","missing","filter","r","has","join","totalRate","_iterator3","_step3","pool","i","_step4","_iterator4","some","getItemDropRate","get","_iterator5","_step5","find","totalPoolWeight","baseRarityRateScaled","itemWeightScaled","totalWeightScaled","numeratorScaled","rateScaled","getCumulativeProbabilityForItem","rolls","pow","getRollsForTargetProbability","targetProbability","Infinity","ceil","log","getRateUpItems","flatMap","rateUp","getAllItemDropRates","_this","_ref","dropRate","roll","count","_this2","results","_loop","_step6","rand","random","cumulative","_iterator6","_step6$value","push","selectRarity","selectItemFromPool","floor","_i2","_Object$entries2","_Object$entries2$_i","scaledRate","_step7","_this3","scaledItems","_extends","scaledWeight","totalScaledWeight","_iterator7","getDebugInfo","rarityRatesFloat","_i3","_Object$entries3","_Object$entries3$_i","scale","Number","MAX_SAFE_INTEGER"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/gacha-engine.ts"],"sourcesContent":["import {\n RarityInput,\n GachaEngineConfig,\n WeightedGachaEngineConfig,\n FlatRateGachaEngineConfig,\n} from './types';\n\nexport class GachaEngine {\n private static readonly SCALE = 1_000_000;\n private static readonly MAX_SAFE_SCALE = Math.floor(Number.MAX_SAFE_INTEGER / GachaEngine.SCALE);\n\n private mode: 'weighted' | 'flatRate';\n private pools: RarityInput[] = [];\n private rarityRatesScaled: Record<string, number> = {};\n private flatRateMap: Map<string, number> = new Map();\n private dropRateCacheScaled = new Map<string, number>();\n\n constructor(config: GachaEngineConfig) {\n this.mode = config.mode;\n\n if (config.mode === 'weighted') {\n const weightedConfig = config as WeightedGachaEngineConfig;\n this.pools = weightedConfig.pools;\n this.rarityRatesScaled = this.scaleRarityRates(weightedConfig.rarityRates);\n this.validateConfig(weightedConfig.rarityRates);\n } else if (config.mode === 'flatRate') {\n const flatConfig = config as FlatRateGachaEngineConfig;\n for (const pool of flatConfig.pools) {\n for (const item of pool.items) {\n if (item.weight < 0) {\n throw new Error(`FlatRate item \"${item.name}\" must have non-negative weight`);\n }\n this.flatRateMap.set(item.name, item.weight); // Here, interpreted as direct probability\n }\n }\n const total = Array.from(this.flatRateMap.values()).reduce((sum, v) => sum + v, 0);\n if (Math.abs(total - 1.0) > 1e-6) {\n throw new Error(`FlatRate item rates must sum to 1.0, but got ${total}`);\n }\n } else {\n throw new Error(`Unknown gacha mode: ${this.mode}`);\n }\n }\n\n private scaleRarityRates(rarityRates: Record<string, number>): Record<string, number> {\n const scaled: Record<string, number> = {};\n for (const [rarity, rate] of Object.entries(rarityRates)) {\n if (rate < 0 || rate > 1) {\n throw new Error(`Rarity rate for \"${rarity}\" must be between 0 and 1, got ${rate}`);\n }\n scaled[rarity] = this.toScaled(rate);\n }\n return scaled;\n }\n\n private toScaled(probability: number): number {\n if (probability > GachaEngine.MAX_SAFE_SCALE / GachaEngine.SCALE) {\n throw new Error(`Probability ${probability} too large for safe integer arithmetic`);\n }\n return Math.round(probability * GachaEngine.SCALE);\n }\n\n private fromScaled(scaledInt: number): number {\n return scaledInt / GachaEngine.SCALE;\n }\n\n private validateConfig(originalRates: Record<string, number>): void {\n const configuredRarities = new Set(Object.keys(this.rarityRatesScaled));\n const usedRarities = new Set(this.pools.map(p => p.rarity));\n const missing = Array.from(usedRarities).filter(r => !configuredRarities.has(r));\n\n if (missing.length > 0) {\n throw new Error(`Missing rarity rates for: ${missing.join(', ')}`);\n }\n\n const totalRate = Object.values(originalRates).reduce((sum, rate) => sum + rate, 0);\n if (Math.abs(totalRate - 1.0) > 1e-10) {\n throw new Error(`Rarity rates must sum to 1.0, got ${totalRate}`);\n }\n\n for (const pool of this.pools) {\n if (pool.items.length === 0) {\n throw new Error(`Rarity \"${pool.rarity}\" has no items`);\n }\n\n const totalWeight = pool.items.reduce((sum, i) => sum + i.weight, 0);\n if (totalWeight <= 0) {\n throw new Error(`Rarity \"${pool.rarity}\" has zero total weight`);\n }\n\n for (const item of pool.items) {\n if (item.weight < 0) {\n throw new Error(`Item \"${item.name}\" weight must be non-negative, got ${item.weight}`);\n }\n }\n\n if (!pool.items.some(i => i.weight > 0)) {\n throw new Error(`Rarity \"${pool.rarity}\" must have at least one item with positive weight`);\n }\n }\n }\n\n getItemDropRate(name: string): number {\n if (this.mode === 'flatRate') {\n return this.flatRateMap.get(name) || 0;\n }\n\n if (this.dropRateCacheScaled.has(name)) {\n return this.fromScaled(this.dropRateCacheScaled.get(name)!);\n }\n\n for (const pool of this.pools) {\n const item = pool.items.find(i => i.name === name);\n if (item) {\n if (item.weight === 0) {\n this.dropRateCacheScaled.set(name, 0);\n return 0;\n }\n\n const totalPoolWeight = pool.items.reduce((sum, i) => sum + i.weight, 0);\n const baseRarityRateScaled = this.rarityRatesScaled[pool.rarity];\n const itemWeightScaled = this.toScaled(item.weight);\n const totalWeightScaled = this.toScaled(totalPoolWeight);\n const numeratorScaled = Math.round((itemWeightScaled * baseRarityRateScaled) / GachaEngine.SCALE);\n const rateScaled = Math.round((numeratorScaled * GachaEngine.SCALE) / totalWeightScaled);\n\n this.dropRateCacheScaled.set(name, rateScaled);\n return this.fromScaled(rateScaled);\n }\n }\n\n throw new Error(`Item \"${name}\" not found`);\n }\n\n getCumulativeProbabilityForItem(name: string, rolls: number): number {\n const rate = this.getItemDropRate(name);\n if (rate === 0) return 0;\n if (rate >= 1) return 1;\n\n const cumulativeFailProbability = Math.pow(1 - rate, rolls);\n return 1 - cumulativeFailProbability;\n }\n\n getRollsForTargetProbability(name: string, targetProbability: number): number {\n if (targetProbability <= 0) return 0;\n if (targetProbability >= 1) return 1;\n\n const rate = this.getItemDropRate(name);\n if (rate <= 0) return Infinity;\n return Math.ceil(Math.log(1 - targetProbability) / Math.log(1 - rate));\n }\n\n getRateUpItems(): string[] {\n if (this.mode === 'weighted') {\n return this.pools.flatMap(p => p.items.filter(i => i.rateUp).map(i => i.name));\n } else {\n if (this.pools.length > 0) {\n return this.pools.flatMap(p => p.items.filter(i => i.rateUp).map(i => i.name));\n }\n return [];\n }\n}\n\n\n getAllItemDropRates(): { name: string; dropRate: number; rarity: string }[] {\n if (this.mode === 'flatRate') {\n return Array.from(this.flatRateMap.entries()).map(([name, dropRate]) => ({\n name,\n dropRate,\n rarity: 'flatRate',\n }));\n }\n\n return this.pools.flatMap(p =>\n p.items.map(i => ({\n name: i.name,\n dropRate: this.getItemDropRate(i.name),\n rarity: p.rarity,\n }))\n );\n }\n\n roll(count: number = 1): string[] {\n const results: string[] = [];\n for (let i = 0; i < count; i++) {\n if (this.mode === 'flatRate') {\n const rand = Math.random();\n let cumulative = 0;\n for (const [name, rate] of this.flatRateMap.entries()) {\n cumulative += rate;\n if (rand < cumulative) {\n results.push(name);\n break;\n }\n }\n } else {\n const rarity = this.selectRarity();\n const pool = this.pools.find(p => p.rarity === rarity)!;\n const item = this.selectItemFromPool(pool);\n results.push(item.name);\n }\n }\n return results;\n }\n\n private selectRarity(): string {\n const rand = Math.floor(Math.random() * GachaEngine.SCALE);\n let cumulative = 0;\n\n for (const [rarity, scaledRate] of Object.entries(this.rarityRatesScaled)) {\n cumulative += scaledRate;\n if (rand < cumulative) return rarity;\n }\n\n return Object.keys(this.rarityRatesScaled)[0];\n }\n\n private selectItemFromPool(pool: RarityInput): { name: string; weight: number } {\n const items = pool.items.filter(i => i.weight > 0);\n const scaledItems = items.map(i => ({\n ...i,\n scaledWeight: this.toScaled(i.weight),\n }));\n\n const totalScaledWeight = scaledItems.reduce((sum, i) => sum + i.scaledWeight, 0);\n const rand = Math.floor(Math.random() * totalScaledWeight);\n let cumulative = 0;\n\n for (const item of scaledItems) {\n cumulative += item.scaledWeight;\n if (rand < cumulative) {\n return { name: item.name, weight: item.weight };\n }\n }\n\n return items[0]; // Fallback\n }\n\n getDebugInfo(): {\n scale: number;\n rarityRatesScaled: Record<string, number>;\n rarityRatesFloat: Record<string, number>;\n } {\n const rarityRatesFloat: Record<string, number> = {};\n for (const [rarity, scaledRate] of Object.entries(this.rarityRatesScaled)) {\n rarityRatesFloat[rarity] = this.fromScaled(scaledRate);\n }\n\n return {\n scale: GachaEngine.SCALE,\n rarityRatesScaled: { ...this.rarityRatesScaled },\n rarityRatesFloat,\n };\n }\n}\n"],"names":["GachaEngine","config","this","mode","pools","rarityRatesScaled","flatRateMap","Map","dropRateCacheScaled","weightedConfig","scaleRarityRates","rarityRates","validateConfig","Error","_step","_iterator","_createForOfIteratorHelperLoose","done","_step2","_iterator2","value","items","item","weight","name","set","total","Array","from","values","reduce","sum","v","Math","abs","_proto","prototype","scaled","_i","_Object$entries","Object","entries","length","_Object$entries$_i","rarity","rate","toScaled","probability","MAX_SAFE_SCALE","SCALE","round","fromScaled","scaledInt","originalRates","configuredRarities","Set","keys","usedRarities","map","p","missing","filter","r","has","join","totalRate","_iterator3","_step3","pool","i","_iterator4","_step4","some","getItemDropRate","get","_iterator5","_step5","find","totalPoolWeight","baseRarityRateScaled","itemWeightScaled","totalWeightScaled","numeratorScaled","rateScaled","getCumulativeProbabilityForItem","rolls","pow","getRollsForTargetProbability","targetProbability","Infinity","ceil","log","getRateUpItems","flatMap","rateUp","getAllItemDropRates","_this","_ref","dropRate","roll","count","_this2","results","_loop","_step6","rand","random","cumulative","_iterator6","_step6$value","push","selectRarity","selectItemFromPool","floor","_i2","_Object$entries2","_Object$entries2$_i","_this3","_step7","scaledItems","_extends","scaledWeight","totalScaledWeight","_iterator7","getDebugInfo","rarityRatesFloat","_i3","_Object$entries3","_Object$entries3$_i","scale","Number","MAX_SAFE_INTEGER"],"mappings":"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"}
|
package/package.json
CHANGED