@schedule1-tools/mixer 0.0.2 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,11 +17,29 @@ const result = mixSubstances('OG Kush', ['Cuke', 'Flu Medicine', 'Gasoline']);
17
17
 
18
18
  /*
19
19
  {
20
- effects: [ 'Be', 'Eu', 'Se', 'To' ],
20
+ effects: [ 'Be', 'Se', 'Eu', 'To' ],
21
21
  cost: 12,
22
22
  sellPrice: 64,
23
- profit: 17,
24
- profitMargin: 0.27
23
+ profit: 52,
24
+ profitMargin: 0.81,
25
+ addiction: 0.44
26
+ }
27
+ */
28
+ ```
29
+
30
+ ### Calculate a mix using a hash
31
+
32
+ ```typescript
33
+ const result = mixFromHash('T0cgS3VzaDpBQkM');
34
+
35
+ /*
36
+ {
37
+ effects: [ 'Be', 'Se', 'Eu', 'To' ],
38
+ cost: 12,
39
+ sellPrice: 64,
40
+ profit: 52,
41
+ profitMargin: 0.81,
42
+ addiction: 0.44
25
43
  }
26
44
  */
27
45
  ```
@@ -1,38 +1,38 @@
1
1
  import type { EffectCode } from '../types';
2
2
  export declare class EffectSet {
3
- private static readonly effectToIndex;
4
- private static readonly indexToEffect;
5
- private static initialized;
6
- private bits;
7
- /**
8
- * Initialize the static mapping between effect codes and bit positions
9
- */
10
- private static initialize;
3
+ private effects;
11
4
  constructor(initialEffects?: EffectCode[]);
12
5
  /**
13
6
  * Add an effect to the set
14
- * @returns true if the effect was added, false if it was already present
7
+ * @param effect - The effect to add
8
+ * @returns True if the effect was added, false if it already exists
15
9
  */
16
10
  add(effect: EffectCode): boolean;
17
11
  /**
18
12
  * Remove an effect from the set
19
- * @returns true if the effect was removed, false if it wasn't present
13
+ * @param effect - The effect to remove
14
+ * @returns True if the effect was removed, false if it didn't exist
20
15
  */
21
16
  remove(effect: EffectCode): boolean;
22
17
  /**
23
- * Check if an effect is in the set
18
+ * Check if the set contains an effect
19
+ * @param effect - The effect to check for
20
+ * @returns True if the effect is in the set, false otherwise
24
21
  */
25
22
  has(effect: EffectCode): boolean;
26
23
  /**
27
- * Convert the set to an array of effect codes
24
+ * Convert the set to an array
25
+ * @returns An array of effects
28
26
  */
29
27
  toArray(): EffectCode[];
30
28
  /**
31
- * Get the number of effects in the set
29
+ * Get the size of the set
30
+ * @returns The number of effects in the set
32
31
  */
33
32
  size(): number;
34
33
  /**
35
- * Create a copy of this effect set
34
+ * Clone the set
35
+ * @returns A new set with the same effects
36
36
  */
37
37
  clone(): EffectSet;
38
38
  }
@@ -2,132 +2,59 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EffectSet = void 0;
4
4
  class EffectSet {
5
- /**
6
- * Initialize the static mapping between effect codes and bit positions
7
- */
8
- static initialize() {
9
- if (this.initialized)
10
- return;
11
- const effects = [
12
- 'Ag',
13
- 'At',
14
- 'Ba',
15
- 'Be',
16
- 'Ca',
17
- 'Cd',
18
- 'Cy',
19
- 'Di',
20
- 'El',
21
- 'En',
22
- 'Eu',
23
- 'Ex',
24
- 'Fc',
25
- 'Fo',
26
- 'Gi',
27
- 'Gl',
28
- 'Je',
29
- 'La',
30
- 'Lf',
31
- 'Mu',
32
- 'Pa',
33
- 'Re',
34
- 'Sc',
35
- 'Se',
36
- 'Sh',
37
- 'Si',
38
- 'Sl',
39
- 'Sm',
40
- 'Sn',
41
- 'Sp',
42
- 'To',
43
- 'Tp',
44
- 'Tt',
45
- 'Zo',
46
- ];
47
- effects.forEach((effect, index) => {
48
- this.effectToIndex.set(effect, index);
49
- this.indexToEffect.set(index, effect);
50
- });
51
- this.initialized = true;
52
- }
53
5
  constructor(initialEffects = []) {
54
- this.bits = 0;
55
- EffectSet.initialize();
56
- for (const effect of initialEffects) {
57
- this.add(effect);
58
- }
6
+ this.effects = new Set(initialEffects);
59
7
  }
60
8
  /**
61
9
  * Add an effect to the set
62
- * @returns true if the effect was added, false if it was already present
10
+ * @param effect - The effect to add
11
+ * @returns True if the effect was added, false if it already exists
63
12
  */
64
13
  add(effect) {
65
- const index = EffectSet.effectToIndex.get(effect);
66
- if (index === undefined)
67
- return false;
68
- const mask = 1 << index;
69
- const alreadyExists = (this.bits & mask) !== 0;
70
- this.bits |= mask;
14
+ const alreadyExists = this.effects.has(effect);
15
+ this.effects.add(effect);
71
16
  return !alreadyExists;
72
17
  }
73
18
  /**
74
19
  * Remove an effect from the set
75
- * @returns true if the effect was removed, false if it wasn't present
20
+ * @param effect - The effect to remove
21
+ * @returns True if the effect was removed, false if it didn't exist
76
22
  */
77
23
  remove(effect) {
78
- const index = EffectSet.effectToIndex.get(effect);
79
- if (index === undefined)
80
- return false;
81
- const mask = 1 << index;
82
- const existed = (this.bits & mask) !== 0;
83
- this.bits &= ~mask;
24
+ const existed = this.effects.has(effect);
25
+ this.effects.delete(effect);
84
26
  return existed;
85
27
  }
86
28
  /**
87
- * Check if an effect is in the set
29
+ * Check if the set contains an effect
30
+ * @param effect - The effect to check for
31
+ * @returns True if the effect is in the set, false otherwise
88
32
  */
89
33
  has(effect) {
90
- const index = EffectSet.effectToIndex.get(effect);
91
- if (index === undefined)
92
- return false;
93
- return (this.bits & (1 << index)) !== 0;
34
+ return this.effects.has(effect);
94
35
  }
95
36
  /**
96
- * Convert the set to an array of effect codes
37
+ * Convert the set to an array
38
+ * @returns An array of effects
97
39
  */
98
40
  toArray() {
99
- const result = [];
100
- for (let i = 0; i < 34; i++) {
101
- if ((this.bits & (1 << i)) !== 0) {
102
- const effect = EffectSet.indexToEffect.get(i);
103
- if (effect)
104
- result.push(effect);
105
- }
106
- }
107
- return result;
41
+ return Array.from(this.effects);
108
42
  }
109
43
  /**
110
- * Get the number of effects in the set
44
+ * Get the size of the set
45
+ * @returns The number of effects in the set
111
46
  */
112
47
  size() {
113
- let count = 0;
114
- let n = this.bits;
115
- while (n) {
116
- n &= n - 1;
117
- count++;
118
- }
119
- return count;
48
+ return this.effects.size;
120
49
  }
121
50
  /**
122
- * Create a copy of this effect set
51
+ * Clone the set
52
+ * @returns A new set with the same effects
123
53
  */
124
54
  clone() {
125
55
  const clone = new EffectSet();
126
- clone.bits = this.bits;
56
+ clone.effects = new Set(this.effects);
127
57
  return clone;
128
58
  }
129
59
  }
130
60
  exports.EffectSet = EffectSet;
131
- EffectSet.effectToIndex = new Map();
132
- EffectSet.indexToEffect = new Map();
133
- EffectSet.initialized = false;
@@ -1,5 +1,14 @@
1
- import type { MixResult, ProductType, SubstanceCode } from '../types';
1
+ import type { MixResult, Product, Substance } from '../types';
2
2
  /**
3
3
  * Calculate the result of mixing substances with a product
4
+ * @param product - The product to mix
5
+ * @param substanceCodes - The substances to mix
6
+ * @returns The result of the mix
4
7
  */
5
- export declare function mixSubstances(product: ProductType, substanceCodes: SubstanceCode[]): MixResult;
8
+ export declare function mixSubstances(product: Product, substanceCodes: Substance[]): MixResult;
9
+ /**
10
+ * Mix substances from a hash
11
+ * @param hash - The hash to mix
12
+ * @returns The result of the mix
13
+ */
14
+ export declare function mixFromHash(hash: string): MixResult;
@@ -1,14 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.mixSubstances = mixSubstances;
4
+ exports.mixFromHash = mixFromHash;
4
5
  const effects_1 = require("../data/effects");
5
6
  const products_1 = require("../data/products");
6
7
  const rules_1 = require("../data/rules");
7
8
  const substances_1 = require("../data/substances");
9
+ const encoding_1 = require("../utils/encoding");
8
10
  const effectSet_1 = require("./effectSet");
9
11
  const MAX_EFFECTS = 8;
10
12
  /**
11
13
  * Calculate the result of mixing substances with a product
14
+ * @param product - The product to mix
15
+ * @param substanceCodes - The substances to mix
16
+ * @returns The result of the mix
12
17
  */
13
18
  function mixSubstances(product, substanceCodes) {
14
19
  if (!products_1.products[product]) {
@@ -16,16 +21,40 @@ function mixSubstances(product, substanceCodes) {
16
21
  }
17
22
  const productInfo = products_1.products[product];
18
23
  const effectsSet = new effectSet_1.EffectSet(productInfo.effects);
19
- const processedEffects = new effectSet_1.EffectSet();
20
- const removedEffects = new effectSet_1.EffectSet();
21
24
  let totalCost = 0;
22
25
  for (const code of substanceCodes) {
23
26
  const substance = substances_1.substances[code];
24
27
  if (!substance)
25
28
  continue;
26
29
  totalCost += substance.price;
27
- applySubstanceRules(code, effectsSet, processedEffects, removedEffects);
28
- if (effectsSet.size() < MAX_EFFECTS) {
30
+ const rules = rules_1.effectRulesBySubstance[code];
31
+ if (rules && rules.length > 0) {
32
+ const initialEffects = effectsSet.clone();
33
+ const processedEffects = new effectSet_1.EffectSet();
34
+ const removedEffects = new effectSet_1.EffectSet();
35
+ const appliedRules = new Set();
36
+ // Phase 1: Apply rules where conditions are met in the initial state
37
+ for (let i = 0; i < rules.length; i++) {
38
+ const rule = rules[i];
39
+ if (checkRulePreconditions(rule, initialEffects)) {
40
+ applyReplaceEffects(rule.replace, initialEffects, effectsSet, processedEffects, removedEffects);
41
+ appliedRules.add(i);
42
+ }
43
+ }
44
+ // Phase 2: Apply rules where conditions are met after phase 1
45
+ for (let i = 0; i < rules.length; i++) {
46
+ if (appliedRules.has(i))
47
+ continue;
48
+ const rule = rules[i];
49
+ if (meetsPhaseTwo(rule, initialEffects, effectsSet, removedEffects)) {
50
+ if (canApplyTransformation(rule.replace, effectsSet)) {
51
+ applyTransformations(rule.replace, effectsSet, processedEffects);
52
+ }
53
+ }
54
+ }
55
+ }
56
+ // Add substance effects AFTER applying rules
57
+ if (effectsSet.size() < MAX_EFFECTS && substance.effect) {
29
58
  for (const effect of substance.effect) {
30
59
  if (!effectsSet.has(effect)) {
31
60
  effectsSet.add(effect);
@@ -37,9 +66,10 @@ function mixSubstances(product, substanceCodes) {
37
66
  }
38
67
  const finalEffects = effectsSet.toArray().slice(0, MAX_EFFECTS);
39
68
  const effectValue = calculateEffectValue(finalEffects);
40
- const productPrice = productInfo.price;
41
- const sellPrice = Math.round(productPrice * (1 + effectValue));
42
- const profit = sellPrice - totalCost - productPrice;
69
+ const addictionValue = calculateAddiction(finalEffects);
70
+ const addiction = Math.round(addictionValue * 100) / 100;
71
+ const sellPrice = Math.round(productInfo.price * (1 + effectValue));
72
+ const profit = sellPrice - totalCost;
43
73
  const profitMargin = Math.round((profit / sellPrice) * 100) / 100;
44
74
  return {
45
75
  effects: finalEffects,
@@ -47,39 +77,26 @@ function mixSubstances(product, substanceCodes) {
47
77
  sellPrice,
48
78
  profit,
49
79
  profitMargin,
80
+ addiction,
50
81
  };
51
82
  }
52
83
  /**
53
- * Apply the rules for a substance to the current effect set
84
+ * Mix substances from a hash
85
+ * @param hash - The hash to mix
86
+ * @returns The result of the mix
54
87
  */
55
- function applySubstanceRules(substanceCode, effectsSet, processedEffects, removedEffects) {
56
- const rules = rules_1.effectRulesBySubstance[substanceCode];
57
- if (!rules || rules.length === 0)
58
- return;
59
- const initialEffects = effectsSet.clone();
60
- const appliedRules = new Set();
61
- // Phase 1: Apply rules where conditions are met in the initial state
62
- for (let i = 0; i < rules.length; i++) {
63
- const rule = rules[i];
64
- if (checkRulePreconditions(rule, initialEffects)) {
65
- applyReplaceEffects(rule.replace, initialEffects, effectsSet, processedEffects, removedEffects);
66
- appliedRules.add(i);
67
- }
68
- }
69
- // Phase 2: Apply rules where conditions are met after phase 1
70
- for (let i = 0; i < rules.length; i++) {
71
- if (appliedRules.has(i))
72
- continue;
73
- const rule = rules[i];
74
- if (meetsPhaseTwo(rule, initialEffects, effectsSet, removedEffects)) {
75
- if (canApplyTransformation(rule.replace, effectsSet)) {
76
- applyTransformations(rule.replace, effectsSet, processedEffects);
77
- }
78
- }
88
+ function mixFromHash(hash) {
89
+ const state = (0, encoding_1.decodeMixState)(hash);
90
+ if (!state) {
91
+ throw new Error(`Invalid hash: ${hash}`);
79
92
  }
93
+ return mixSubstances(state.product, state.substances);
80
94
  }
81
95
  /**
82
96
  * Check if a rule's preconditions are met
97
+ * @param rule - The rule to check
98
+ * @param initialEffects - The initial effects
99
+ * @returns True if the preconditions are met, false otherwise
83
100
  */
84
101
  function checkRulePreconditions(rule, initialEffects) {
85
102
  // Check if all required effects are present
@@ -101,6 +118,11 @@ function checkRulePreconditions(rule, initialEffects) {
101
118
  }
102
119
  /**
103
120
  * Check if a rule meets phase two conditions
121
+ * @param rule - The rule to check
122
+ * @param initialEffects - The initial effects
123
+ * @param currentEffects - The current effects
124
+ * @param removedEffects - The removed effects
125
+ * @returns True if the rule meets the conditions, false otherwise
104
126
  */
105
127
  function meetsPhaseTwo(rule, initialEffects, currentEffects, removedEffects) {
106
128
  // All required effects must have been initially present
@@ -125,18 +147,13 @@ function meetsPhaseTwo(rule, initialEffects, currentEffects, removedEffects) {
125
147
  }
126
148
  return true;
127
149
  }
128
- /**
129
- * Check if a transformation can be applied
130
- */
131
- function canApplyTransformation(replace, effectsSet) {
132
- for (const oldEffect of Object.keys(replace)) {
133
- if (effectsSet.has(oldEffect))
134
- return true;
135
- }
136
- return false;
137
- }
138
150
  /**
139
151
  * Apply effect replacements
152
+ * @param replace - The replacements to apply
153
+ * @param initialEffects - The initial effects
154
+ * @param effectsSet - The effects set
155
+ * @param processedEffects - The processed effects
156
+ * @param removedEffects - The removed effects
140
157
  */
141
158
  function applyReplaceEffects(replace, initialEffects, effectsSet, processedEffects, removedEffects) {
142
159
  for (const [oldEffect, newEffect] of Object.entries(replace)) {
@@ -148,8 +165,24 @@ function applyReplaceEffects(replace, initialEffects, effectsSet, processedEffec
148
165
  }
149
166
  }
150
167
  }
168
+ /**
169
+ * Check if a transformation can be applied
170
+ * @param replace - The replacements to apply
171
+ * @param effectsSet - The effects set
172
+ * @returns True if the transformation can be applied, false otherwise
173
+ */
174
+ function canApplyTransformation(replace, effectsSet) {
175
+ for (const oldEffect of Object.keys(replace)) {
176
+ if (effectsSet.has(oldEffect))
177
+ return true;
178
+ }
179
+ return false;
180
+ }
151
181
  /**
152
182
  * Apply transformations to effects
183
+ * @param replace - The replacements to apply
184
+ * @param effectsSet - The effects set
185
+ * @param processedEffects - The processed effects
153
186
  */
154
187
  function applyTransformations(replace, effectsSet, processedEffects) {
155
188
  for (const [oldEffect, newEffect] of Object.entries(replace)) {
@@ -162,6 +195,8 @@ function applyTransformations(replace, effectsSet, processedEffects) {
162
195
  }
163
196
  /**
164
197
  * Calculate the total value multiplier from effects
198
+ * @param effectCodes - The effects to calculate the value for
199
+ * @returns The total value multiplier
165
200
  */
166
201
  function calculateEffectValue(effectCodes) {
167
202
  var _a;
@@ -171,3 +206,16 @@ function calculateEffectValue(effectCodes) {
171
206
  }
172
207
  return value;
173
208
  }
209
+ /**
210
+ * Calculate the total addiction value from effects
211
+ * @param effectCodes - The effects to calculate the value for
212
+ * @returns The total addiction value
213
+ */
214
+ function calculateAddiction(effectCodes) {
215
+ var _a;
216
+ let value = 0;
217
+ for (const code of effectCodes) {
218
+ value += ((_a = effects_1.effects[code]) === null || _a === void 0 ? void 0 : _a.addiction) || 0;
219
+ }
220
+ return value;
221
+ }
@@ -4,172 +4,274 @@ exports.effects = void 0;
4
4
  exports.effects = {
5
5
  Ca: {
6
6
  name: 'Calming',
7
+ description: 'Induces a slight calmness in the user.',
8
+ tier: 1,
7
9
  price: 0.1,
8
10
  color: '#fdba74',
11
+ addiction: 0,
9
12
  },
10
13
  Re: {
11
14
  name: 'Refreshing',
15
+ description: 'Slightly energizes the user.',
16
+ tier: 1,
12
17
  price: 0.14,
13
18
  color: '#bef264',
19
+ addiction: 0.104,
14
20
  },
15
21
  En: {
16
22
  name: 'Energizing',
23
+ description: 'Increases the users energy.',
24
+ tier: 2,
17
25
  price: 0.22,
18
26
  color: '#a3e635',
27
+ addiction: 0.34,
19
28
  },
20
29
  Se: {
21
30
  name: 'Sedating',
31
+ description: 'Induces heavy sleepiness in the user.',
32
+ tier: 2,
22
33
  price: 0.26,
23
34
  color: '#818cf8',
35
+ addiction: 0,
24
36
  },
25
37
  Be: {
26
38
  name: 'Bright-Eyed',
39
+ description: "Causes the user's eyes to emit light.",
40
+ tier: 4,
27
41
  price: 0.4,
28
42
  color: '#67e8f9',
43
+ addiction: 0.2,
29
44
  },
30
45
  Cd: {
31
46
  name: 'Calorie-Dense',
47
+ description: 'Results in immediate weight gain.',
48
+ tier: 2,
32
49
  price: 0.28,
33
50
  color: '#e879f9',
51
+ addiction: 0.1,
34
52
  },
35
53
  Eu: {
36
54
  name: 'Euphoric',
55
+ description: 'Induces mild euphoria in the user.',
56
+ tier: 1,
37
57
  price: 0.18,
38
58
  color: '#fde68a',
59
+ addiction: 0.235,
39
60
  },
40
61
  To: {
41
62
  name: 'Toxic',
63
+ description: "Damages the user's liver and induces vomiting.",
64
+ tier: 2,
42
65
  price: 0,
43
66
  color: '#a3e635',
67
+ addiction: 0,
44
68
  },
45
69
  At: {
46
70
  name: 'Athletic',
71
+ description: 'After consumption, the user is only able to run.',
72
+ tier: 3,
47
73
  price: 0.32,
48
74
  color: '#7dd3fc',
75
+ addiction: 0.607,
49
76
  },
50
77
  Ba: {
51
78
  name: 'Balding',
79
+ description: 'Causes balding in the user.',
80
+ tier: 3,
52
81
  price: 0.3,
53
82
  color: '#c79232',
83
+ addiction: 0,
54
84
  },
55
85
  Ag: {
56
86
  name: 'Anti-Gravity',
87
+ description: 'Weakens the effects of gravity on the user.',
88
+ tier: 5,
57
89
  price: 0.54,
58
90
  color: '#3b82f6',
91
+ addiction: 0.611,
59
92
  },
60
93
  Mu: {
61
94
  name: 'Munchies',
95
+ description: 'Makes the user hungry.',
96
+ tier: 1,
62
97
  price: 0.12,
63
98
  color: '#C96E57',
99
+ addiction: 0.096,
64
100
  },
65
101
  Sl: {
66
102
  name: 'Slippery',
103
+ description: "Reduces the user's ability to maintain traction on the ground.",
104
+ tier: 3,
67
105
  price: 0.34,
68
106
  color: '#7dd3fc',
107
+ addiction: 0.309,
69
108
  },
70
109
  Gi: {
71
110
  name: 'Gingeritis',
111
+ description: 'After consumption, the user will become a ginger.',
112
+ tier: 2,
72
113
  price: 0.2,
73
114
  color: '#fb923c',
115
+ addiction: 0,
74
116
  },
75
117
  Sn: {
76
118
  name: 'Sneaky',
119
+ description: 'Silences the users foot steps.',
120
+ tier: 2,
77
121
  price: 0.24,
78
122
  color: '#a8a29e',
123
+ addiction: 0.327,
79
124
  },
80
125
  Tp: {
81
126
  name: 'Thought-Provoking',
127
+ description: "Increases the size of the user's head.",
128
+ tier: 4,
82
129
  price: 0.44,
83
130
  color: '#f9a8d4',
131
+ addiction: 0.37,
84
132
  },
85
133
  Sp: {
86
134
  name: 'Spicy',
135
+ description: "Consumption results in the user's eyes turning blue.",
136
+ tier: 3,
87
137
  price: 0.38,
88
138
  color: '#f87171',
139
+ addiction: 0.665,
89
140
  },
90
141
  Pa: {
91
142
  name: 'Paranoia',
143
+ description: 'Induces paranoia in the user.',
144
+ tier: 1,
92
145
  price: 0,
93
146
  color: '#f87171',
147
+ addiction: 0,
94
148
  },
95
149
  Tt: {
96
150
  name: 'Tropic Thunder',
151
+ description: "Inverts the user's skin color.",
152
+ tier: 4,
97
153
  price: 0.46,
98
154
  color: '#fdba74',
155
+ addiction: 0.803,
99
156
  },
100
157
  Gl: {
101
158
  name: 'Glowing',
159
+ description: 'Imbues a bioluminescence on the user.',
160
+ tier: 4,
102
161
  price: 0.48,
103
162
  color: '#85E459',
163
+ addiction: 0.472,
104
164
  },
105
165
  Cy: {
106
166
  name: 'Cyclopean',
167
+ description: 'Causes the user to see with a single eye in the center of their forehead.',
168
+ tier: 5,
107
169
  price: 0.56,
108
170
  color: '#FEC174',
171
+ addiction: 0.1,
109
172
  },
110
173
  Fo: {
111
174
  name: 'Foggy',
175
+ description: 'Causes a cloud of fog to form around the user.',
176
+ tier: 3,
112
177
  price: 0.36,
113
178
  color: '#94a3b8',
179
+ addiction: 0.1,
114
180
  },
115
181
  Ex: {
116
182
  name: 'Explosive',
183
+ description: 'Causes the user to explode shortly after consumption.',
184
+ tier: 5,
117
185
  price: 0,
118
186
  color: '#ef4444',
187
+ addiction: 0,
119
188
  },
120
189
  La: {
121
190
  name: 'Laxative',
191
+ description: 'Causes the user to fart and shit uncontrollably.',
192
+ tier: 3,
122
193
  price: 0,
123
194
  color: '#a16207',
195
+ addiction: 0.1,
124
196
  },
125
197
  Lf: {
126
198
  name: 'Long Faced',
199
+ description: "Considerably increases the size of the user's head and neck.",
200
+ tier: 5,
127
201
  price: 0.52,
128
202
  color: '#fde047',
203
+ addiction: 0.607,
129
204
  },
130
205
  Je: {
131
206
  name: 'Jennerising',
207
+ description: "Inverts the user's gender.",
208
+ tier: 4,
132
209
  price: 0.42,
133
210
  color: '#e879f9',
211
+ addiction: 0.343,
134
212
  },
135
213
  El: {
136
214
  name: 'Electrifying',
215
+ description: 'Electrifies the user, causing arcs of electricity to be emitted, zapping anyone nearby.',
216
+ tier: 5,
137
217
  price: 0.5,
138
218
  color: '#22d3ee',
219
+ addiction: 0.235,
139
220
  },
140
221
  Di: {
141
222
  name: 'Disorienting',
223
+ description: 'Causes unpredictable movement and slight visual impairment in the user.',
224
+ tier: 2,
142
225
  price: 0,
143
226
  color: '#FE7551',
227
+ addiction: 0,
144
228
  },
145
229
  Sc: {
146
230
  name: 'Schizophrenia',
231
+ description: 'Induces hallucinations and unpredictable behaviour in the user.',
232
+ tier: 4,
147
233
  price: 0,
148
234
  color: '#645AFD',
235
+ addiction: 0,
149
236
  },
150
237
  Si: {
151
238
  name: 'Seizure-Inducing',
239
+ description: 'Consumption results in an instant seizure.',
240
+ tier: 3,
152
241
  price: 0,
153
242
  color: '#FEE900',
243
+ addiction: 0,
154
244
  },
155
245
  Zo: {
156
246
  name: 'Zombifying',
247
+ description: 'Transforms the user into a zombie, causing them to walk with a limp and seek brains.',
248
+ tier: 5,
157
249
  price: 0.58,
158
250
  color: '#71AB5D',
251
+ addiction: 0.598,
159
252
  },
160
253
  Fc: {
161
254
  name: 'Focused',
255
+ description: "Focuses the user's mind.",
256
+ tier: 1,
162
257
  price: 0.16,
163
258
  color: '#75F1FD',
259
+ addiction: 0.104,
164
260
  },
165
261
  Sm: {
166
262
  name: 'Smelly',
263
+ description: 'Makes the user unbearably smelly.',
264
+ tier: 1,
167
265
  price: 0,
168
266
  color: '#84cc16',
267
+ addiction: 0,
169
268
  },
170
269
  Sh: {
171
270
  name: 'Shrinking',
271
+ description: 'Shrinks the user.',
272
+ tier: 5,
172
273
  price: 0.6,
173
274
  color: '#B6FEDA',
275
+ addiction: 0.336,
174
276
  },
175
277
  };
@@ -1,3 +1,3 @@
1
- import type { ProductData, ProductType } from '../types';
2
- export declare const products: Record<ProductType, ProductData>;
3
- export declare const productAbbreviations: Record<string, ProductType>;
1
+ import type { Product, ProductData } from '../types';
2
+ export declare const products: Record<Product, ProductData>;
3
+ export declare const productAbbreviations: Record<string, Product>;
@@ -22,16 +22,16 @@ exports.products = {
22
22
  effects: ['Se'],
23
23
  abbreviation: 'GE',
24
24
  },
25
- Cocaine: {
26
- price: 150,
27
- effects: [],
28
- abbreviation: 'CE',
29
- },
30
25
  Meth: {
31
26
  price: 70,
32
27
  effects: [],
33
28
  abbreviation: 'MH',
34
29
  },
30
+ Cocaine: {
31
+ price: 150,
32
+ effects: [],
33
+ abbreviation: 'CE',
34
+ },
35
35
  };
36
36
  exports.productAbbreviations = Object.entries(exports.products).reduce((acc, [product, data]) => {
37
37
  acc[data.abbreviation] = product;
@@ -1,2 +1,2 @@
1
- import type { EffectRule, SubstanceCode } from '../types';
2
- export declare const effectRulesBySubstance: Record<SubstanceCode, EffectRule[]>;
1
+ import type { EffectRule, Substance } from '../types';
2
+ export declare const effectRulesBySubstance: Record<Substance, EffectRule[]>;
@@ -1,3 +1,3 @@
1
- import type { SubstanceCode, SubstanceData } from '../types';
2
- export declare const substances: Record<SubstanceCode, SubstanceData>;
3
- export declare const substanceAbbreviations: Record<string, SubstanceCode>;
1
+ import type { Substance, SubstanceData } from '../types';
2
+ export declare const substances: Record<Substance, SubstanceData>;
3
+ export declare const substanceAbbreviations: Record<string, Substance>;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { mixSubstances } from './core/mixer';
1
+ export { mixSubstances, mixFromHash } from './core/mixer';
2
2
  export { encodeMixState, decodeMixState } from './utils/encoding';
3
3
  export { effects } from './data/effects';
4
4
  export { products, productAbbreviations } from './data/products';
5
5
  export { substances } from './data/substances';
6
6
  export { effectRulesBySubstance } from './data/rules';
7
- export type { EffectCode, SubstanceCode, ProductType, RankCode, EffectData, SubstanceData, ProductData, EffectRule, MixResult, MixState, } from './types';
7
+ export type { EffectCode, Substance, Product, RankCode, EffectData, SubstanceData, ProductData, EffectRule, MixResult, MixState, } from './types';
package/dist/index.js CHANGED
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.effectRulesBySubstance = exports.substances = exports.productAbbreviations = exports.products = exports.effects = exports.decodeMixState = exports.encodeMixState = exports.mixSubstances = void 0;
3
+ exports.effectRulesBySubstance = exports.substances = exports.productAbbreviations = exports.products = exports.effects = exports.decodeMixState = exports.encodeMixState = exports.mixFromHash = exports.mixSubstances = void 0;
4
4
  // Main exports
5
5
  var mixer_1 = require("./core/mixer");
6
6
  Object.defineProperty(exports, "mixSubstances", { enumerable: true, get: function () { return mixer_1.mixSubstances; } });
7
+ Object.defineProperty(exports, "mixFromHash", { enumerable: true, get: function () { return mixer_1.mixFromHash; } });
7
8
  var encoding_1 = require("./utils/encoding");
8
9
  Object.defineProperty(exports, "encodeMixState", { enumerable: true, get: function () { return encoding_1.encodeMixState; } });
9
10
  Object.defineProperty(exports, "decodeMixState", { enumerable: true, get: function () { return encoding_1.decodeMixState; } });
package/dist/types.d.ts CHANGED
@@ -1,11 +1,14 @@
1
1
  export type EffectCode = 'Ag' | 'At' | 'Ba' | 'Be' | 'Ca' | 'Cd' | 'Cy' | 'Di' | 'El' | 'En' | 'Eu' | 'Ex' | 'Fc' | 'Fo' | 'Gi' | 'Gl' | 'Je' | 'La' | 'Lf' | 'Mu' | 'Pa' | 'Re' | 'Sc' | 'Se' | 'Sh' | 'Si' | 'Sl' | 'Sm' | 'Sn' | 'Sp' | 'To' | 'Tp' | 'Tt' | 'Zo';
2
- export type SubstanceCode = 'Cuke' | 'Flu Medicine' | 'Gasoline' | 'Donut' | 'Energy Drink' | 'Mouth Wash' | 'Motor Oil' | 'Banana' | 'Chili' | 'Iodine' | 'Paracetamol' | 'Viagra' | 'Horse Semen' | 'Mega Bean' | 'Addy' | 'Battery';
3
- export type ProductType = 'OG Kush' | 'Sour Diesel' | 'Green Crack' | 'Grandaddy Purple' | 'Meth' | 'Cocaine';
2
+ export type Substance = 'Cuke' | 'Flu Medicine' | 'Gasoline' | 'Donut' | 'Energy Drink' | 'Mouth Wash' | 'Motor Oil' | 'Banana' | 'Chili' | 'Iodine' | 'Paracetamol' | 'Viagra' | 'Horse Semen' | 'Mega Bean' | 'Addy' | 'Battery';
3
+ export type Product = 'OG Kush' | 'Sour Diesel' | 'Green Crack' | 'Grandaddy Purple' | 'Meth' | 'Cocaine';
4
4
  export type RankCode = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | '13';
5
5
  export interface EffectData {
6
6
  name: string;
7
+ description: string;
8
+ tier: number;
7
9
  price: number;
8
10
  color: string;
11
+ addiction: number;
9
12
  }
10
13
  export interface SubstanceData {
11
14
  abbreviation: string;
@@ -29,8 +32,9 @@ export interface MixResult {
29
32
  sellPrice: number;
30
33
  profit: number;
31
34
  profitMargin: number;
35
+ addiction: number;
32
36
  }
33
37
  export interface MixState {
34
- product: ProductType;
35
- substances: SubstanceCode[];
38
+ product: Product;
39
+ substances: Substance[];
36
40
  }
@@ -1,11 +1,14 @@
1
1
  import type { MixState } from '../types';
2
2
  /**
3
3
  * Encode a mix state into a URL-safe string
4
+ * @param state - The mix state to encode
5
+ * @returns The URL-safe string
4
6
  * @throws Error if the product type or any substance code is invalid
5
7
  */
6
8
  export declare function encodeMixState(state: MixState): string;
7
9
  /**
8
10
  * Decode a mix state from a URL-safe string
11
+ * @param hash - The URL-safe string to decode
9
12
  * @returns The decoded MixState or null if invalid
10
13
  */
11
14
  export declare function decodeMixState(hash: string): MixState | null;
@@ -6,6 +6,8 @@ const products_1 = require("../data/products");
6
6
  const substances_1 = require("../data/substances");
7
7
  /**
8
8
  * Encode a mix state into a URL-safe string
9
+ * @param state - The mix state to encode
10
+ * @returns The URL-safe string
9
11
  * @throws Error if the product type or any substance code is invalid
10
12
  */
11
13
  function encodeMixState(state) {
@@ -29,6 +31,7 @@ function encodeMixState(state) {
29
31
  }
30
32
  /**
31
33
  * Decode a mix state from a URL-safe string
34
+ * @param hash - The URL-safe string to decode
32
35
  * @returns The decoded MixState or null if invalid
33
36
  */
34
37
  function decodeMixState(hash) {
@@ -45,7 +48,7 @@ function decodeMixState(hash) {
45
48
  if (!product || !products_1.products[product]) {
46
49
  return null;
47
50
  }
48
- const substanceCodes = [];
51
+ const subs = [];
49
52
  if (substancesStr) {
50
53
  for (let i = 0; i < substancesStr.length; i++) {
51
54
  const abbr = substancesStr[i];
@@ -53,12 +56,12 @@ function decodeMixState(hash) {
53
56
  if (!fullName || !substances_1.substances[fullName]) {
54
57
  return null;
55
58
  }
56
- substanceCodes.push(fullName);
59
+ subs.push(fullName);
57
60
  }
58
61
  }
59
62
  return {
60
63
  product: product,
61
- substances: substanceCodes,
64
+ substances: subs,
62
65
  };
63
66
  }
64
67
  catch (error) {
@@ -67,6 +70,8 @@ function decodeMixState(hash) {
67
70
  }
68
71
  /**
69
72
  * Convert a string to a URL-safe base64 string
73
+ * @param str - The string to convert
74
+ * @returns The URL-safe base64 string
70
75
  */
71
76
  function toBase64Url(str) {
72
77
  return Buffer.from(str, 'utf-8')
@@ -77,6 +82,8 @@ function toBase64Url(str) {
77
82
  }
78
83
  /**
79
84
  * Convert a URL-safe base64 string back to a regular string
85
+ * @param str - The URL-safe base64 string to convert
86
+ * @returns The regular string
80
87
  */
81
88
  function fromBase64Url(str) {
82
89
  if (typeof str !== 'string') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schedule1-tools/mixer",
3
- "version": "0.0.2",
3
+ "version": "0.2.2",
4
4
  "description": "A package for calculating substance mixes in Schedule 1",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",