@allemandi/gacha-engine 0.3.4 → 0.3.6
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/gacha-engine.d.ts +1 -0
- 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/dist/gacha-engine.d.ts
CHANGED
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
|
|
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.flatRateRateUpItems=[],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);var a=t;this.pools=a.pools;for(var n,i=e(a.pools);!(n=i()).done;)for(var o,s=e(n.value.items);!(o=s()).done;){var l=o.value;if(l.weight<0)throw new Error('FlatRate item "'+l.name+'" must have non-negative weight');this.flatRateMap.set(l.name,l.weight),l.rateUp&&this.flatRateRateUpItems.push(l.name)}var h=Array.from(this.flatRateMap.values()).reduce(function(t,e){return t+e},0);if(Math.abs(h-1)>1e-6)throw new Error("FlatRate item rates must sum to 1.0, but got "+h)}}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 h,u=e(l.items);!(h=u()).done;){var f=h.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],h=this.toScaled(o.weight),u=this.toScaled(s),f=Math.round(h*l/t.SCALE),c=Math.round(f*t.SCALE/u);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.flatMap(function(t){return t.items.filter(function(t){return t.rateUp}).map(function(t){return t.name})}):this.flatRateRateUpItems},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(),h=r.pools.find(function(t){return t.rarity===l}),u=r.selectItemFromPool(h);a.push(u.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),h=0,u=e(o);!(a=u()).done;){var f=a.value;if(l<(h+=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 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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"}
|
|
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 private flatRateRateUpItems: string[] = [];\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 this.pools = flatConfig.pools; // Keep pools for reference\n\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); // direct probability\n if (item.rateUp) {\n this.flatRateRateUpItems.push(item.name);\n }\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 return this.flatRateRateUpItems;\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","flatRateRateUpItems","weightedConfig","scaleRarityRates","rarityRates","validateConfig","Error","flatConfig","_iterator","_step","_createForOfIteratorHelperLoose","done","_step2","_iterator2","value","items","item","weight","name","set","rateUp","push","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","_step3","_iterator3","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","getAllItemDropRates","_this","_ref","dropRate","roll","count","_this2","results","_loop","_step6","rand","random","cumulative","_iterator6","_step6$value","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
|
|
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.flatRateRateUpItems=[],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);var a=t;this.pools=a.pools;for(var n,i=e(a.pools);!(n=i()).done;)for(var o,s=e(n.value.items);!(o=s()).done;){var l=o.value;if(l.weight<0)throw new Error('FlatRate item "'+l.name+'" must have non-negative weight');this.flatRateMap.set(l.name,l.weight),l.rateUp&&this.flatRateRateUpItems.push(l.name)}var u=Array.from(this.flatRateMap.values()).reduce(function(t,e){return t+e},0);if(Math.abs(u-1)>1e-6)throw new Error("FlatRate item rates must sum to 1.0, but got "+u)}}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.flatMap(function(t){return t.items.filter(function(t){return t.rateUp}).map(function(t){return t.name})}):this.flatRateRateUpItems},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 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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"}
|
|
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 private flatRateRateUpItems: string[] = [];\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 this.pools = flatConfig.pools; // Keep pools for reference\n\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); // direct probability\n if (item.rateUp) {\n this.flatRateRateUpItems.push(item.name);\n }\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 return this.flatRateRateUpItems;\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","flatRateRateUpItems","weightedConfig","scaleRarityRates","rarityRates","validateConfig","Error","flatConfig","_iterator","_step","_createForOfIteratorHelperLoose","done","_step2","_iterator2","value","items","item","weight","name","set","rateUp","push","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","_step3","_iterator3","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","getAllItemDropRates","_this","_ref","dropRate","roll","count","_this2","results","_loop","_step6","rand","random","cumulative","_iterator6","_step6$value","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
|
|
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.flatRateRateUpItems=[],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);var a=t;this.pools=a.pools;for(var n,i=r(a.pools);!(n=i()).done;)for(var o,s=r(n.value.items);!(o=s()).done;){var l=o.value;if(l.weight<0)throw new Error('FlatRate item "'+l.name+'" must have non-negative weight');this.flatRateMap.set(l.name,l.weight),l.rateUp&&this.flatRateRateUpItems.push(l.name)}var f=Array.from(this.flatRateMap.values()).reduce(function(t,e){return t+e},0);if(Math.abs(f-1)>1e-6)throw new Error("FlatRate item rates must sum to 1.0, but got "+f)}}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.flatMap(function(t){return t.items.filter(function(t){return t.rateUp}).map(function(t){return t.name})}):this.flatRateRateUpItems},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 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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"}
|
|
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 private flatRateRateUpItems: string[] = [];\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 this.pools = flatConfig.pools; // Keep pools for reference\n\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); // direct probability\n if (item.rateUp) {\n this.flatRateRateUpItems.push(item.name);\n }\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 return this.flatRateRateUpItems;\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","flatRateRateUpItems","weightedConfig","scaleRarityRates","rarityRates","validateConfig","Error","flatConfig","_iterator","_step","_createForOfIteratorHelperLoose","done","_step2","_iterator2","value","items","item","weight","name","set","rateUp","push","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","_step3","_iterator3","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","getAllItemDropRates","_this","_ref","dropRate","roll","count","_this2","results","_loop","_step6","rand","random","cumulative","_iterator6","_step6$value","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