probability-picker 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 qgave
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # Probability Picker
2
+ A lightweight library for selecting random values based on weighted probabilities.
3
+
4
+ ## Installation
5
+
6
+ ```bash
7
+ npm i probability-picker
8
+ ```
9
+
10
+ ## Usage
11
+
12
+ The `probabilityPicker` function will return `a`, `b`, or `c`. The probability of each one is defined as a value in the object.
13
+
14
+ ```javascript
15
+ import picker from 'probability-picker';
16
+
17
+ const value = picker({
18
+ a: 10,
19
+ b: 70,
20
+ c: 20,
21
+ });
22
+ ```
23
+
24
+ ## License
25
+
26
+ [MIT](LICENSE)
package/dist/index.cjs ADDED
@@ -0,0 +1,51 @@
1
+ 'use strict';
2
+
3
+ // src/index.ts
4
+ function filterNumbers(entries) {
5
+ return entries.filter((e) => typeof e[1] === "number" && !Number.isNaN(e[1]));
6
+ }
7
+ function sortEntries(entries) {
8
+ return entries.sort((a, b) => a[1] - b[1]);
9
+ }
10
+ function sumProbabilities(entries) {
11
+ return entries.reduce((acc, e) => acc + e[1], 0);
12
+ }
13
+ function normalizeProbabilities(entries, total) {
14
+ return entries.map(([k, v]) => [k, Math.round(v / total * 100)]);
15
+ }
16
+ function prepareEntries(entries) {
17
+ const filtered = filterNumbers(entries);
18
+ if (filtered.length === 0) return;
19
+ const sorted = sortEntries(filtered);
20
+ const sum = sumProbabilities(sorted);
21
+ if (sum === 0) return;
22
+ if (sum === 100) return sorted;
23
+ return normalizeProbabilities(sorted, sum);
24
+ }
25
+ function random(min, max) {
26
+ return Math.random() * (max - min) + min;
27
+ }
28
+ function chooseOne(entries) {
29
+ const num = random(1, 100);
30
+ let count = 0;
31
+ for (const entry of entries) {
32
+ count += entry[1];
33
+ if (num <= count) return entry[0];
34
+ }
35
+ return entries[entries.length - 1][0];
36
+ }
37
+ function probabilityPicker(map) {
38
+ if (!(map instanceof Object)) return null;
39
+ const entries = Object.entries(map);
40
+ if (entries.length === 0) return void 0;
41
+ const first = entries[0];
42
+ if (first && entries.length === 1) return first[0];
43
+ const prepared = prepareEntries(entries);
44
+ if (!prepared) return void 0;
45
+ return chooseOne(prepared);
46
+ }
47
+ var index_default = probabilityPicker;
48
+
49
+ module.exports = index_default;
50
+ //# sourceMappingURL=index.cjs.map
51
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;AAGA,SAAS,cAAc,OAAA,EAAkB;AACrC,EAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,CAAA,CAAA,KAAK,OAAO,EAAE,CAAC,CAAA,KAAM,QAAA,IAAY,CAAC,MAAA,CAAO,KAAA,CAAM,CAAA,CAAE,CAAC,CAAC,CAAC,CAAA;AAC9E;AAEA,SAAS,YAAY,OAAA,EAAkB;AACnC,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,CAAC,CAAA;AAC7C;AAEA,SAAS,iBAAiB,OAAA,EAAkB;AACxC,EAAA,OAAO,OAAA,CAAQ,OAAO,CAAC,GAAA,EAAK,MAAM,GAAA,GAAM,CAAA,CAAE,CAAC,CAAA,EAAG,CAAC,CAAA;AACnD;AAEA,SAAS,sBAAA,CAAuB,SAAkB,KAAA,EAAe;AAC7D,EAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAC,GAAG,CAAC,CAAA,KAAM,CAAC,CAAA,EAAG,KAAK,KAAA,CAAO,CAAA,GAAI,KAAA,GAAS,GAAG,CAAC,CAAU,CAAA;AAC9E;AAEA,SAAS,eAAe,OAAA,EAAkB;AACtC,EAAA,MAAM,QAAA,GAAW,cAAc,OAAO,CAAA;AACtC,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC3B,EAAA,MAAM,MAAA,GAAS,YAAY,QAAQ,CAAA;AACnC,EAAA,MAAM,GAAA,GAAM,iBAAiB,MAAM,CAAA;AACnC,EAAA,IAAI,QAAQ,CAAA,EAAG;AACf,EAAA,IAAI,GAAA,KAAQ,KAAK,OAAO,MAAA;AACxB,EAAA,OAAO,sBAAA,CAAuB,QAAQ,GAAG,CAAA;AAC7C;AAEA,SAAS,MAAA,CAAO,KAAa,GAAA,EAAa;AACtC,EAAA,OAAO,IAAA,CAAK,MAAA,EAAO,IAAK,GAAA,GAAM,GAAA,CAAA,GAAO,GAAA;AACzC;AAEA,SAAS,UAAU,OAAA,EAAkB;AACjC,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,CAAA,EAAG,GAAG,CAAA;AACzB,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AACzB,IAAA,KAAA,IAAS,MAAM,CAAC,CAAA;AAChB,IAAA,IAAI,GAAA,IAAO,KAAA,EAAO,OAAO,KAAA,CAAM,CAAC,CAAA;AAAA,EACpC;AACA,EAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,MAAA,GAAS,CAAC,EAAG,CAAC,CAAA;AACzC;AAEA,SAAS,kBAAkB,GAAA,EAAgD;AACvE,EAAA,IAAI,EAAE,GAAA,YAAe,MAAA,CAAA,EAAS,OAAO,IAAA;AACrC,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA;AAClC,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AACjC,EAAA,MAAM,KAAA,GAAQ,QAAQ,CAAC,CAAA;AACvB,EAAA,IAAI,SAAS,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,MAAM,CAAC,CAAA;AACjD,EAAA,MAAM,QAAA,GAAW,eAAe,OAAO,CAAA;AACvC,EAAA,IAAI,CAAC,UAAU,OAAO,MAAA;AACtB,EAAA,OAAO,UAAU,QAAQ,CAAA;AAC7B;AAEA,IAAO,aAAA,GAAQ","file":"index.cjs","sourcesContent":["type ProbabilityMap = Record<string, number>\r\ntype Entry = [string, number]\r\n\r\nfunction filterNumbers(entries: Entry[]) {\r\n return entries.filter(e => typeof e[1] === 'number' && !Number.isNaN(e[1]))\r\n}\r\n\r\nfunction sortEntries(entries: Entry[]) {\r\n return entries.sort((a, b) => a[1] - b[1])\r\n}\r\n\r\nfunction sumProbabilities(entries: Entry[]) {\r\n return entries.reduce((acc, e) => acc + e[1], 0)\r\n}\r\n\r\nfunction normalizeProbabilities(entries: Entry[], total: number) {\r\n return entries.map(([k, v]) => [k, Math.round((v / total) * 100)] as Entry)\r\n}\r\n\r\nfunction prepareEntries(entries: Entry[]) {\r\n const filtered = filterNumbers(entries)\r\n if (filtered.length === 0) return\r\n const sorted = sortEntries(filtered)\r\n const sum = sumProbabilities(sorted)\r\n if (sum === 0) return\r\n if (sum === 100) return sorted\r\n return normalizeProbabilities(sorted, sum)\r\n}\r\n\r\nfunction random(min: number, max: number) {\r\n return Math.random() * (max - min) + min\r\n}\r\n\r\nfunction chooseOne(entries: Entry[]) {\r\n const num = random(1, 100)\r\n let count = 0\r\n for (const entry of entries) {\r\n count += entry[1]\r\n if (num <= count) return entry[0]\r\n }\r\n return entries[entries.length - 1]![0]\r\n}\r\n\r\nfunction probabilityPicker(map: ProbabilityMap): string | null | undefined {\r\n if (!(map instanceof Object)) return null\r\n const entries = Object.entries(map) as Entry[]\r\n if (entries.length === 0) return undefined\r\n const first = entries[0]\r\n if (first && entries.length === 1) return first[0]\r\n const prepared = prepareEntries(entries)\r\n if (!prepared) return undefined\r\n return chooseOne(prepared)\r\n}\r\n\r\nexport default probabilityPicker;"]}
@@ -0,0 +1,4 @@
1
+ type ProbabilityMap = Record<string, number>;
2
+ declare function probabilityPicker(map: ProbabilityMap): string | null | undefined;
3
+
4
+ export { probabilityPicker as default };
@@ -0,0 +1,4 @@
1
+ type ProbabilityMap = Record<string, number>;
2
+ declare function probabilityPicker(map: ProbabilityMap): string | null | undefined;
3
+
4
+ export { probabilityPicker as default };
package/dist/index.js ADDED
@@ -0,0 +1,49 @@
1
+ // src/index.ts
2
+ function filterNumbers(entries) {
3
+ return entries.filter((e) => typeof e[1] === "number" && !Number.isNaN(e[1]));
4
+ }
5
+ function sortEntries(entries) {
6
+ return entries.sort((a, b) => a[1] - b[1]);
7
+ }
8
+ function sumProbabilities(entries) {
9
+ return entries.reduce((acc, e) => acc + e[1], 0);
10
+ }
11
+ function normalizeProbabilities(entries, total) {
12
+ return entries.map(([k, v]) => [k, Math.round(v / total * 100)]);
13
+ }
14
+ function prepareEntries(entries) {
15
+ const filtered = filterNumbers(entries);
16
+ if (filtered.length === 0) return;
17
+ const sorted = sortEntries(filtered);
18
+ const sum = sumProbabilities(sorted);
19
+ if (sum === 0) return;
20
+ if (sum === 100) return sorted;
21
+ return normalizeProbabilities(sorted, sum);
22
+ }
23
+ function random(min, max) {
24
+ return Math.random() * (max - min) + min;
25
+ }
26
+ function chooseOne(entries) {
27
+ const num = random(1, 100);
28
+ let count = 0;
29
+ for (const entry of entries) {
30
+ count += entry[1];
31
+ if (num <= count) return entry[0];
32
+ }
33
+ return entries[entries.length - 1][0];
34
+ }
35
+ function probabilityPicker(map) {
36
+ if (!(map instanceof Object)) return null;
37
+ const entries = Object.entries(map);
38
+ if (entries.length === 0) return void 0;
39
+ const first = entries[0];
40
+ if (first && entries.length === 1) return first[0];
41
+ const prepared = prepareEntries(entries);
42
+ if (!prepared) return void 0;
43
+ return chooseOne(prepared);
44
+ }
45
+ var index_default = probabilityPicker;
46
+
47
+ export { index_default as default };
48
+ //# sourceMappingURL=index.js.map
49
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";AAGA,SAAS,cAAc,OAAA,EAAkB;AACrC,EAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,CAAA,CAAA,KAAK,OAAO,EAAE,CAAC,CAAA,KAAM,QAAA,IAAY,CAAC,MAAA,CAAO,KAAA,CAAM,CAAA,CAAE,CAAC,CAAC,CAAC,CAAA;AAC9E;AAEA,SAAS,YAAY,OAAA,EAAkB;AACnC,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,CAAC,CAAA;AAC7C;AAEA,SAAS,iBAAiB,OAAA,EAAkB;AACxC,EAAA,OAAO,OAAA,CAAQ,OAAO,CAAC,GAAA,EAAK,MAAM,GAAA,GAAM,CAAA,CAAE,CAAC,CAAA,EAAG,CAAC,CAAA;AACnD;AAEA,SAAS,sBAAA,CAAuB,SAAkB,KAAA,EAAe;AAC7D,EAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAC,GAAG,CAAC,CAAA,KAAM,CAAC,CAAA,EAAG,KAAK,KAAA,CAAO,CAAA,GAAI,KAAA,GAAS,GAAG,CAAC,CAAU,CAAA;AAC9E;AAEA,SAAS,eAAe,OAAA,EAAkB;AACtC,EAAA,MAAM,QAAA,GAAW,cAAc,OAAO,CAAA;AACtC,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC3B,EAAA,MAAM,MAAA,GAAS,YAAY,QAAQ,CAAA;AACnC,EAAA,MAAM,GAAA,GAAM,iBAAiB,MAAM,CAAA;AACnC,EAAA,IAAI,QAAQ,CAAA,EAAG;AACf,EAAA,IAAI,GAAA,KAAQ,KAAK,OAAO,MAAA;AACxB,EAAA,OAAO,sBAAA,CAAuB,QAAQ,GAAG,CAAA;AAC7C;AAEA,SAAS,MAAA,CAAO,KAAa,GAAA,EAAa;AACtC,EAAA,OAAO,IAAA,CAAK,MAAA,EAAO,IAAK,GAAA,GAAM,GAAA,CAAA,GAAO,GAAA;AACzC;AAEA,SAAS,UAAU,OAAA,EAAkB;AACjC,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,CAAA,EAAG,GAAG,CAAA;AACzB,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AACzB,IAAA,KAAA,IAAS,MAAM,CAAC,CAAA;AAChB,IAAA,IAAI,GAAA,IAAO,KAAA,EAAO,OAAO,KAAA,CAAM,CAAC,CAAA;AAAA,EACpC;AACA,EAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,MAAA,GAAS,CAAC,EAAG,CAAC,CAAA;AACzC;AAEA,SAAS,kBAAkB,GAAA,EAAgD;AACvE,EAAA,IAAI,EAAE,GAAA,YAAe,MAAA,CAAA,EAAS,OAAO,IAAA;AACrC,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA;AAClC,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AACjC,EAAA,MAAM,KAAA,GAAQ,QAAQ,CAAC,CAAA;AACvB,EAAA,IAAI,SAAS,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,MAAM,CAAC,CAAA;AACjD,EAAA,MAAM,QAAA,GAAW,eAAe,OAAO,CAAA;AACvC,EAAA,IAAI,CAAC,UAAU,OAAO,MAAA;AACtB,EAAA,OAAO,UAAU,QAAQ,CAAA;AAC7B;AAEA,IAAO,aAAA,GAAQ","file":"index.js","sourcesContent":["type ProbabilityMap = Record<string, number>\r\ntype Entry = [string, number]\r\n\r\nfunction filterNumbers(entries: Entry[]) {\r\n return entries.filter(e => typeof e[1] === 'number' && !Number.isNaN(e[1]))\r\n}\r\n\r\nfunction sortEntries(entries: Entry[]) {\r\n return entries.sort((a, b) => a[1] - b[1])\r\n}\r\n\r\nfunction sumProbabilities(entries: Entry[]) {\r\n return entries.reduce((acc, e) => acc + e[1], 0)\r\n}\r\n\r\nfunction normalizeProbabilities(entries: Entry[], total: number) {\r\n return entries.map(([k, v]) => [k, Math.round((v / total) * 100)] as Entry)\r\n}\r\n\r\nfunction prepareEntries(entries: Entry[]) {\r\n const filtered = filterNumbers(entries)\r\n if (filtered.length === 0) return\r\n const sorted = sortEntries(filtered)\r\n const sum = sumProbabilities(sorted)\r\n if (sum === 0) return\r\n if (sum === 100) return sorted\r\n return normalizeProbabilities(sorted, sum)\r\n}\r\n\r\nfunction random(min: number, max: number) {\r\n return Math.random() * (max - min) + min\r\n}\r\n\r\nfunction chooseOne(entries: Entry[]) {\r\n const num = random(1, 100)\r\n let count = 0\r\n for (const entry of entries) {\r\n count += entry[1]\r\n if (num <= count) return entry[0]\r\n }\r\n return entries[entries.length - 1]![0]\r\n}\r\n\r\nfunction probabilityPicker(map: ProbabilityMap): string | null | undefined {\r\n if (!(map instanceof Object)) return null\r\n const entries = Object.entries(map) as Entry[]\r\n if (entries.length === 0) return undefined\r\n const first = entries[0]\r\n if (first && entries.length === 1) return first[0]\r\n const prepared = prepareEntries(entries)\r\n if (!prepared) return undefined\r\n return chooseOne(prepared)\r\n}\r\n\r\nexport default probabilityPicker;"]}
package/package.json CHANGED
@@ -1,10 +1,42 @@
1
1
  {
2
2
  "name": "probability-picker",
3
- "version": "1.0.0",
4
- "main": "probability-picker.js",
5
- "license": "MIT",
3
+ "version": "1.1.0",
4
+ "description": "A lightweight library for selecting random values based on weighted probabilities.",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup",
22
+ "dev": "tsup --watch",
23
+ "lint": "tsc --noEmit"
24
+ },
6
25
  "keywords": [
7
- "javascript",
8
- "probability"
9
- ]
26
+ "probability",
27
+ "weighted",
28
+ "random"
29
+ ],
30
+ "author": "qgave (https://github.com/qgave)",
31
+ "license": "MIT",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/qgave/probability-picker"
35
+ },
36
+ "type": "module",
37
+ "sideEffects": false,
38
+ "devDependencies": {
39
+ "tsup": "^8.5.1",
40
+ "typescript": "^5.9.3"
41
+ }
10
42
  }
@@ -1,68 +0,0 @@
1
- function probabilityPicker(e) {
2
- if (e instanceof Object === false) return null;
3
- let values = Object.entries(e);
4
- if (values.length === 0) return undefined;
5
- if (values.length === 1) return values[0][0];
6
- values = prepareValues(values);
7
- if (values === undefined) return;
8
- return chooseOne(values);
9
- }
10
-
11
- function prepareValues(values) {
12
- values = filterNumbers(values);
13
- if (values.length === 0) return;
14
- values = sortValues(values);
15
- return prepareProbability(values);
16
- }
17
-
18
- function filterNumbers(values) {
19
- const result = [];
20
- for (let i = 0; i < values.length; i++) {
21
- if (typeof values[i][1] === 'number' && !Number.isNaN(values[i][1])) {
22
- result.push(values[i]);
23
- }
24
- }
25
- return result;
26
- }
27
-
28
- function sortValues(values) {
29
- return values.sort((a, b) => a[1] - b[1]);
30
- }
31
-
32
- function prepareProbability(values) {
33
- const sum = sumProbabilities(values);
34
- if (sum === 0) return;
35
- if (sum === 100) return values;
36
- return changeProbability(values, sum);
37
- }
38
-
39
- function changeProbability(values, totalProbability) {
40
- for (let i = 0; i < values.length; i++) {
41
- values[i][1] = Math.round((values[i][1] / totalProbability) * 100);
42
- }
43
- return values;
44
- }
45
-
46
- function sumProbabilities(values) {
47
- let s = 0;
48
- for (let i = 0; i < values.length; i++) {
49
- s += values[i][1];
50
- }
51
- return s;
52
- }
53
-
54
- function chooseOne(values) {
55
- const num = random(1, 100);
56
- let count = 0;
57
- for (let i = 0; i < values.length; i++) {
58
- count += values[i][1];
59
- if (num <= count) return values[i][0];
60
- }
61
- return values;
62
- }
63
-
64
- function random(min, max) {
65
- return Math.random() * (max - min) + min;
66
- }
67
-
68
- export default probabilityPicker;