mana-scribe 1.1.0 → 2.0.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/README.md CHANGED
@@ -1,21 +1,21 @@
1
1
  # mana-scribe
2
2
  [![Tests](https://github.com/matortheeternal/mana-scribe/actions/workflows/tests.yml/badge.svg)](https://github.com/matortheeternal/mana-scribe/actions/workflows/tests.yml) [![codecov](https://codecov.io/github/matortheeternal/mana-scribe/graph/badge.svg?token=Z81O4KMEOH)](https://codecov.io/github/matortheeternal/mana-scribe)
3
3
 
4
- Mana Scribe is a utility for working with Magic: The Gathering mana costs and activation costs.
4
+ Mana Scribe is a utility for working with Magic: The Gathering mana costs and activation costs.
5
5
 
6
6
  Supports both brace `{3}{R/U}` and shortform `3R/U` notation.
7
7
 
8
8
  ## Features
9
9
 
10
10
  - Parse MTG mana costs into structured objects
11
- - Supports all major symbols: generic, colored, hybrid, phyrexian, snow, energy, tap/untap, variable
11
+ - Supports all major symbols: generic, colored, 2-5 color hybrid, phyrexian, generic hybrid, phyrexian hybrid, snow, energy, tap/untap, variable
12
12
  - Works with both Scryfall braces and shortform notation
13
13
  - Compute:
14
14
  - Converted mana cost
15
15
  - Color identity
16
16
  - Devotion
17
- - Compare mana costs to evaluate if they are equal, greater than, or less than each other.
18
- - Extensible design — add new symbol types by subclassing
17
+ - Compare mana costs (equality, greater than, less than)
18
+ - Easily add custom colors, types of mana, or other extra symbols
19
19
 
20
20
  Note: When the parser encounters an unrecognized symbol it stops parsing and returns the symbols it parsed so far. You can access the unparsed string component through the property `remainingStr`.
21
21
 
@@ -61,36 +61,60 @@ console.log(a.greaterThan(b)); // true
61
61
  console.log(b.lessThan(a)); // true
62
62
  ```
63
63
 
64
- ## Activation costs
64
+
65
+ ### Activation costs
65
66
  `ActivationCost` offers the same functionality as the `ManaCost` class, but supports additional symbols such as Tap, Untap, and Energy. It does not have comparison functions.
66
67
 
67
68
  ```js
68
69
  import { ActivationCost } from 'mana-scribe';
69
70
 
70
71
  const cost = ActivationCost.parse('{1}{G}{T}');
71
- console.log(cost.symbols.map(s => s.type)); // ["generic", "colored", "tap"]
72
+ console.log(cost.symbols.map(s => s.type)); // ["genericMana", "coloredMana", "tap"]
72
73
  console.log(cost.toString(true)); // "{1}{G}{T}"
73
74
  ```
74
75
 
75
76
  ## Extending
76
77
 
77
- The library is class-based. Each symbol type is a subclass of a base Symbol class and implements:
78
+ ### Custom colors
79
+
80
+ You can add custom colors of mana with `symbolRegistry.addColor`.
81
+
82
+ ```js
83
+ import { symbolRegistry, ManaCost } from 'mana-scribe';
84
+
85
+ symbolRegistry.addColor({ id: 'P', name: 'Purple' });
86
+ const cost = ManaCost.parse('{3}{R/P}{P}');
87
+ console.log(cost.symbols.map(s => s.type)); // ["genericMana", "twoColorHybridMana", "coloredMana"]
88
+ console.log(cost.cmc); // 5
89
+ console.log(cost.colors); // ['R','P']
90
+ console.log(cost.getDevotionTo('P')); // 2
91
+ ```
92
+
93
+ ### Custom mana types
78
94
 
79
- - `static match(str)` returns a regex match object if it applies
80
- - `get colors()` → returns an array of the colors associated with the symbol
81
- - `cmcValue()` → returns an integer corresponding to how much this symbol contributes to a card's overall converted mana cost.
95
+ You can add custom types of mana with `symbolRegistry.addManaType`. This is for mana produced by specific sources, like snow mana.
82
96
 
83
- This makes it easy to add custom symbols or patch existing ones in your own project.
97
+ ```js
98
+ import { symbolRegistry, ActivationCost } from 'mana-scribe';
99
+
100
+ symbolRegistry.addManaType({ id: 'A', name: 'Artificial' }); // mana produced by an artifact
101
+ const cost = ActivationCost.parse('{A}{A}{T}');
102
+ console.log(cost.symbols.map(s => s.type)); // ["typedMana", "typedMana", "tap"]
103
+ console.log(cost.colors); // []
104
+ ```
84
105
 
85
- ## Project Status
106
+ ### Extra symbols
86
107
 
87
- This is an early but complete implementation.
108
+ You can add additional symbols for use in activation costs with `symbolRegistry.addExtraSym`. This is used for things like the energy symbol.
88
109
 
89
- Current priorities:
90
- - [x] Support core MTG symbols
91
- - [x] Add test coverage
92
- - [x] Add cost comparison
93
- - [ ] Other improvements? TBD
110
+ ```js
111
+ import { symbolRegistry, ActivationCost } from 'mana-scribe';
112
+
113
+ symbolRegistry.addManaType({ id: '\\@', name: 'Chaos' });
114
+ const cost = ActivationCost.parse('{@}');
115
+ console.log(cost.symbols.map(s => s.type)); // ["extra"]
116
+ console.log(cost.colors); // []
117
+ ```
94
118
 
95
119
  ## License
96
120
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mana-scribe",
3
- "version": "1.1.0",
3
+ "version": "2.0.0",
4
4
  "description": "Library for parsing and querying Magic: The Gathering mana costs — with support for CMC, devotion, and color identity.",
5
5
  "keywords": [
6
6
  "mtg",
@@ -29,6 +29,7 @@
29
29
  },
30
30
  "scripts": {
31
31
  "test": "jasmine --config=jasmine.json",
32
+ "debug:test": "node --inspect-brk node_modules/jasmine/bin/jasmine.js --config=jasmine.json",
32
33
  "coverage": "c8 npm test"
33
34
  },
34
35
  "files": [
@@ -3,14 +3,15 @@ import ColoredManaSymbol from '../symbols/ColoredManaSymbol.js';
3
3
  import ColoredPhyrexianManaSymbol from '../symbols/ColoredPhyrexianManaSymbol.js';
4
4
  import ColorlessManaSymbol from '../symbols/ColorlessManaSymbol.js';
5
5
  import ColorlessPhyrexianManaSymbol from '../symbols/ColorlessPhyrexianManaSymbol.js';
6
- import EnergySymbol from '../symbols/EnergySymbol.js';
6
+ import ExtraSymbol from '../symbols/ExtraSymbol.js';
7
7
  import FiveColorHybridManaSymbol from '../symbols/FiveColorHybridManaSymbol.js';
8
8
  import FourColorHybridManaSymbol from '../symbols/FourColorHybridManaSymbol.js';
9
9
  import GenericHybridManaSymbol from '../symbols/GenericHybridManaSymbol.js';
10
10
  import GenericManaSymbol from '../symbols/GenericManaSymbol.js';
11
- import HalfColoredManaSymbol from '../symbols/HalfColoredManaSymbol.js';
11
+ import HalfManaSymbol from '../symbols/HalfManaSymbol.js';
12
+ import HybridPhyrexianManaSymbol from '../symbols/HybridPhyrexianManaSymbol.js';
12
13
  import InfiniteManaSymbol from '../symbols/InfiniteManaSymbol.js';
13
- import SnowManaSymbol from '../symbols/SnowManaSymbol.js';
14
+ import TypedManaSymbol from '../symbols/TypedManaSymbol.js';
14
15
  import TapSymbol from '../symbols/TapSymbol.js';
15
16
  import ThreeColorHybridManaSymbol from '../symbols/ThreeColorHybridManaSymbol.js';
16
17
  import TwoColorHybridManaSymbol from '../symbols/TwoColorHybridManaSymbol.js';
@@ -20,13 +21,13 @@ import VariableManaSymbol from '../symbols/VariableManaSymbol.js';
20
21
  export default class ActivationCost extends Cost {
21
22
  static get allowedSymbols() {
22
23
  return [
23
- ColoredPhyrexianManaSymbol, GenericHybridManaSymbol, FiveColorHybridManaSymbol,
24
- FourColorHybridManaSymbol, ThreeColorHybridManaSymbol, TwoColorHybridManaSymbol,
25
- ColorlessPhyrexianManaSymbol, HalfColoredManaSymbol,
26
- GenericManaSymbol, VariableManaSymbol,
27
- InfiniteManaSymbol, SnowManaSymbol,
28
- ColoredManaSymbol, ColorlessManaSymbol,
29
- EnergySymbol, TapSymbol, UntapSymbol,
24
+ HybridPhyrexianManaSymbol, ColoredPhyrexianManaSymbol,
25
+ GenericHybridManaSymbol, FiveColorHybridManaSymbol,
26
+ FourColorHybridManaSymbol, ThreeColorHybridManaSymbol,
27
+ TwoColorHybridManaSymbol, HalfManaSymbol, ColorlessPhyrexianManaSymbol,
28
+ GenericManaSymbol, VariableManaSymbol, InfiniteManaSymbol,
29
+ TypedManaSymbol, ColoredManaSymbol, ColorlessManaSymbol,
30
+ ExtraSymbol, TapSymbol, UntapSymbol,
30
31
  ];
31
32
  }
32
33
  }
@@ -7,23 +7,25 @@ import FiveColorHybridManaSymbol from '../symbols/FiveColorHybridManaSymbol.js';
7
7
  import FourColorHybridManaSymbol from '../symbols/FourColorHybridManaSymbol.js';
8
8
  import GenericHybridManaSymbol from '../symbols/GenericHybridManaSymbol.js';
9
9
  import GenericManaSymbol from '../symbols/GenericManaSymbol.js';
10
- import HalfColoredManaSymbol from '../symbols/HalfColoredManaSymbol.js';
10
+ import HalfManaSymbol from '../symbols/HalfManaSymbol.js';
11
11
  import InfiniteManaSymbol from '../symbols/InfiniteManaSymbol.js';
12
- import SnowManaSymbol from '../symbols/SnowManaSymbol.js';
12
+ import TypedManaSymbol from '../symbols/TypedManaSymbol.js';
13
13
  import ThreeColorHybridManaSymbol from '../symbols/ThreeColorHybridManaSymbol.js';
14
14
  import TwoColorHybridManaSymbol from '../symbols/TwoColorHybridManaSymbol.js';
15
+ import HybridPhyrexianManaSymbol from '../symbols/HybridPhyrexianManaSymbol.js';
15
16
  import VariableManaSymbol from '../symbols/VariableManaSymbol.js';
16
- import {arrayEquals, arrayGreaterThan, arrayLessThan} from '../arrayComparison.js';
17
+ import { arrayEquals, arrayGreaterThan, arrayLessThan } from '../arrayComparison.js';
17
18
 
18
19
  export default class ManaCost extends Cost {
19
20
  static get allowedSymbols() {
20
21
  return [
21
- ColoredPhyrexianManaSymbol, GenericHybridManaSymbol, FiveColorHybridManaSymbol,
22
- FourColorHybridManaSymbol, ThreeColorHybridManaSymbol, TwoColorHybridManaSymbol,
23
- ColorlessPhyrexianManaSymbol, HalfColoredManaSymbol,
24
- GenericManaSymbol, VariableManaSymbol,
25
- InfiniteManaSymbol, SnowManaSymbol,
26
- ColoredManaSymbol, ColorlessManaSymbol
22
+ HybridPhyrexianManaSymbol, ColoredPhyrexianManaSymbol,
23
+ GenericHybridManaSymbol, FiveColorHybridManaSymbol,
24
+ FourColorHybridManaSymbol, ThreeColorHybridManaSymbol,
25
+ TwoColorHybridManaSymbol, HalfManaSymbol,
26
+ ColorlessPhyrexianManaSymbol,
27
+ GenericManaSymbol, VariableManaSymbol, InfiniteManaSymbol,
28
+ TypedManaSymbol, ColoredManaSymbol, ColorlessManaSymbol
27
29
  ];
28
30
  }
29
31
 
@@ -4,3 +4,17 @@ export class NotImplementedError extends Error {
4
4
  this.name = 'NotImplementedError';
5
5
  }
6
6
  }
7
+
8
+ export class SchemaError extends Error {
9
+ constructor(message) {
10
+ super(message);
11
+ this.name = 'SchemaError';
12
+ }
13
+ }
14
+
15
+ export class AlreadyRegisteredError extends Error {
16
+ constructor(label, id) {
17
+ super(`${label} with id "${id}" already registered`);
18
+ this.name = 'AlreadyRegisteredError';
19
+ }
20
+ }
package/src/index.js CHANGED
@@ -1,4 +1,26 @@
1
1
  import ActivationCost from './costs/ActivationCost.js';
2
2
  import ManaCost from './costs/ManaCost.js';
3
+ import symbolRegistry from './services/SymbolRegistry.js';
3
4
 
4
- export { ActivationCost, ManaCost };
5
+ const baseColors = [
6
+ { id: 'W', name: 'White' },
7
+ { id: 'U', name: 'Blue' },
8
+ { id: 'B', name: 'Black' },
9
+ { id: 'R', name: 'Red' },
10
+ { id: 'G', name: 'Green' },
11
+ ];
12
+
13
+ const baseTypes = [
14
+ { id: 'S', name: 'Snow', },
15
+ { id: 'L', name: 'Legendary' },
16
+ ];
17
+
18
+ const extraSymbols = [
19
+ { id: 'E', name: 'Energy' }
20
+ ];
21
+
22
+ baseColors.forEach(color => symbolRegistry.addColor(color));
23
+ baseTypes.forEach(type => symbolRegistry.addManaType(type));
24
+ extraSymbols.forEach(type => symbolRegistry.addExtraSym(type));
25
+
26
+ export { ActivationCost, ManaCost, symbolRegistry };
@@ -0,0 +1,80 @@
1
+ import { AlreadyRegisteredError, SchemaError } from '../customErrors.js';
2
+
3
+ const ReservedIds = {
4
+ H: 'Phyrexian',
5
+ I: 'Infinite Mana',
6
+ Q: 'Untap',
7
+ T: 'Tap',
8
+ X: 'Variable Mana',
9
+ Y: 'Variable Mana',
10
+ Z: 'Variable Mana',
11
+ };
12
+
13
+ function isEscapedChar(str) {
14
+ return str.length === 2 && str[0] === '\\';
15
+ }
16
+
17
+ function validateSchema(item, label) {
18
+ if (!item.id || item.id.constructor !== String)
19
+ throw new SchemaError(`${label} must have a string property "id"`);
20
+ if (item.id.length !== 1 && !isEscapedChar(item.id))
21
+ throw new SchemaError(`${label} property "id" length must be 1`);
22
+ if (ReservedIds.hasOwnProperty(item.id))
23
+ throw new SchemaError(
24
+ `${label} id "${item.id}" is not allowed (used for ${ReservedIds[item.id]})`
25
+ );
26
+ if (!item.name || item.name.constructor !== String)
27
+ throw new SchemaError(`${label} must have a string property "name"`);
28
+ }
29
+
30
+ class SymbolRegistry {
31
+ constructor() {
32
+ this.colors = new Map();
33
+ this.manaTypes = new Map();
34
+ this.extraSymbols = new Map();
35
+ }
36
+
37
+ checkIfRegistered(key) {
38
+ if (this.colors.has(key))
39
+ throw new AlreadyRegisteredError('Color', key);
40
+ if (this.manaTypes.has(key))
41
+ throw new AlreadyRegisteredError('ManaType', key);
42
+ if (this.extraSymbols.has(key))
43
+ throw new AlreadyRegisteredError('ExtraSym', key);
44
+ }
45
+
46
+ addColor(item) {
47
+ validateSchema(item, 'Color');
48
+ const key = item.id;
49
+ this.checkIfRegistered(key);
50
+ this.colors.set(key, item);
51
+ }
52
+
53
+ addManaType(item) {
54
+ validateSchema(item, 'ManaType');
55
+ const key = item.id;
56
+ this.checkIfRegistered(key);
57
+ this.manaTypes.set(key, item);
58
+ }
59
+
60
+ addExtraSym(item) {
61
+ validateSchema(item, 'ExtraSym');
62
+ const key = item.id;
63
+ this.checkIfRegistered(key);
64
+ this.extraSymbols.set(key, item);
65
+ }
66
+
67
+ get colorKeys() {
68
+ return [...this.colors.keys()];
69
+ }
70
+
71
+ get manaTypeKeys() {
72
+ return [...this.manaTypes.keys()];
73
+ }
74
+
75
+ get extraSymKeys() {
76
+ return [...this.extraSymbols.keys()];
77
+ }
78
+ }
79
+
80
+ export default new SymbolRegistry();
@@ -0,0 +1,12 @@
1
+ import symbolRegistry from './SymbolRegistry.js';
2
+
3
+ export function msr(str) {
4
+ const colorKeys = symbolRegistry.colorKeys.join('');
5
+ const mTypeKeys = symbolRegistry.manaTypeKeys.join('');
6
+ const extraKeys = symbolRegistry.extraSymKeys.join('');
7
+ const pstr = str.raw[0]
8
+ .replaceAll('\\c', '[' + colorKeys + ']')
9
+ .replaceAll('\\T', '[' + mTypeKeys + ']')
10
+ .replaceAll('\\#', '[' + extraKeys + ']');
11
+ return new RegExp(`^({${pstr}}|${pstr})`, 'i');
12
+ }
@@ -1,9 +1,9 @@
1
1
  import Symbol from './Symbol.js';
2
+ import { msr } from '../services/regExpService.js';
2
3
 
3
4
  export default class ColoredManaSymbol extends Symbol {
4
5
  static match(str) {
5
- return str.match(/^{[WUBRG]}/i)
6
- || str.match(/^[WUBRG]/i);
6
+ return str.match(msr`\c`)
7
7
  }
8
8
 
9
9
  get colors() {
@@ -1,9 +1,9 @@
1
1
  import Symbol from './Symbol.js';
2
+ import { msr } from '../services/regExpService.js';
2
3
 
3
4
  export default class ColoredPhyrexianManaSymbol extends Symbol {
4
5
  static match(str) {
5
- return str.match(/^{(h\/[wubrg]|[wubrg]\/h)}/i)
6
- || str.match(/^(h\/[wubrg]|[wubrg]\/h)/i);
6
+ return str.match(msr`(H\/\c|\c\/H)`);
7
7
  }
8
8
 
9
9
  get colors() {
@@ -1,9 +1,9 @@
1
1
  import Symbol from './Symbol.js';
2
+ import { msr } from '../services/regExpService.js';
2
3
 
3
4
  export default class ColorlessManaSymbol extends Symbol {
4
5
  static match(str) {
5
- return str.match(/^{C}/i)
6
- || str.match(/^C/i);
6
+ return str.match(msr`C`);
7
7
  }
8
8
 
9
9
  get colors() {
@@ -1,9 +1,9 @@
1
1
  import ColorlessManaSymbol from './ColorlessManaSymbol.js';
2
+ import { msr } from '../services/regExpService.js';
2
3
 
3
4
  export default class ColorlessPhyrexianManaSymbol extends ColorlessManaSymbol {
4
5
  static match(str) {
5
- return str.match(/^{(h\/c|c\/h|h)}/i)
6
- || str.match(/^(h\/c|c\/h|h)/i);
6
+ return str.match(msr`(H\/c|c\/H|H)`);
7
7
  }
8
8
 
9
9
  get type() {
@@ -0,0 +1,12 @@
1
+ import NonManaSymbol from './NonManaSymbol.js';
2
+ import { msr } from '../services/regExpService.js';
3
+
4
+ export default class ExtraSymbol extends NonManaSymbol {
5
+ static match(str) {
6
+ return str.match(msr`\#`);
7
+ }
8
+
9
+ get type() {
10
+ return 'extra';
11
+ }
12
+ }
@@ -1,9 +1,9 @@
1
1
  import HybridManaSymbol from './HybridManaSymbol.js';
2
+ import { msr } from '../services/regExpService.js';
2
3
 
3
4
  export default class FiveColorHybridManaSymbol extends HybridManaSymbol {
4
5
  static match(str) {
5
- return super.match(str, 5, /^{[WUBRG](\/[WUBRG]){4}}/i)
6
- || super.match(str, 5, /^[WUBRG](\/[WUBRG]){4}/i);
6
+ return super.match(str, 5, msr`\c(\/\c){4}`);
7
7
  }
8
8
 
9
9
  get type() {
@@ -1,9 +1,9 @@
1
1
  import HybridManaSymbol from './HybridManaSymbol.js';
2
+ import { msr } from '../services/regExpService.js';
2
3
 
3
4
  export default class FourColorHybridManaSymbol extends HybridManaSymbol {
4
5
  static match(str) {
5
- return super.match(str, 4, /^{[WUBRG](\/[WUBRG]){3}}/i)
6
- || super.match(str, 4, /^[WUBRG](\/[WUBRG]){3}/i);
6
+ return super.match(str, 4, msr`\c(\/\c){3}`);
7
7
  }
8
8
 
9
9
  get type() {
@@ -1,9 +1,9 @@
1
1
  import Symbol from './Symbol.js';
2
+ import { msr } from '../services/regExpService.js';
2
3
 
3
4
  export default class GenericHybridManaSymbol extends Symbol {
4
5
  static match(str) {
5
- return str.match(/^{\d\/([WUBRGC])}/i)
6
- || str.match(/^\d\/([WUBRGC])/i)
6
+ return str.match(msr`\d\/(\c|c)`);
7
7
  }
8
8
 
9
9
  get colors() {
@@ -1,9 +1,9 @@
1
1
  import Symbol from './Symbol.js';
2
+ import { msr } from '../services/regExpService.js';
2
3
 
3
4
  export default class GenericManaSymbol extends Symbol {
4
5
  static match(str) {
5
- return str.match(/^{[0-9][0-9]?}/)
6
- || str.match(/^[0-9][0-9]?/);
6
+ return str.match(msr`[0-9][0-9]?`);
7
7
  }
8
8
 
9
9
  get type() {
@@ -0,0 +1,23 @@
1
+ import Symbol from './Symbol.js';
2
+ import { msr } from '../services/regExpService.js';
3
+ import { symbolRegistry } from '../index.js';
4
+
5
+ export default class HalfManaSymbol extends Symbol {
6
+ static match(str) {
7
+ return str.match(msr`\|(\c|\T)`);
8
+ }
9
+
10
+ get colors() {
11
+ const c = this.raw[1];
12
+ const colorIds = symbolRegistry.colorKeys;
13
+ return colorIds.includes(c) ? [c] : [];
14
+ }
15
+
16
+ get type() {
17
+ return 'halfMana';
18
+ }
19
+
20
+ cmcValue() {
21
+ return 0.5;
22
+ }
23
+ }
@@ -0,0 +1,16 @@
1
+ import HybridManaSymbol from './HybridManaSymbol.js';
2
+ import { msr } from '../services/regExpService.js';
3
+
4
+ export default class HybridPhyrexianManaSymbol extends HybridManaSymbol {
5
+ static match(str) {
6
+ return super.match(str, 3, msr`(H\/\c\/\c|\c\/H\/\c|\c\/\c\/H)`);
7
+ }
8
+
9
+ get colors() {
10
+ return this.raw.split('/').filter(c => c !== 'H');
11
+ }
12
+
13
+ get type() {
14
+ return 'hybridPhyrexianMana';
15
+ }
16
+ }
@@ -1,9 +1,9 @@
1
1
  import Symbol from './Symbol.js';
2
+ import { msr } from '../services/regExpService.js';
2
3
 
3
4
  export default class InfiniteManaSymbol extends Symbol {
4
5
  static match(str) {
5
- return str.match(/^{I}/i)
6
- || str.match(/^I/i)
6
+ return str.match(msr`I`);
7
7
  }
8
8
 
9
9
  get type() {
@@ -1,9 +1,9 @@
1
1
  import NonManaSymbol from './NonManaSymbol.js';
2
+ import { msr } from '../services/regExpService.js';
2
3
 
3
4
  export default class TapSymbol extends NonManaSymbol {
4
5
  static match(str) {
5
- return str.match(/^{T}/i)
6
- || str.match(/^T/i);
6
+ return str.match(msr`T`);
7
7
  }
8
8
 
9
9
  get type() {
@@ -1,9 +1,9 @@
1
1
  import HybridManaSymbol from './HybridManaSymbol.js';
2
+ import { msr } from '../services/regExpService.js';
2
3
 
3
4
  export default class ThreeColorHybridManaSymbol extends HybridManaSymbol {
4
5
  static match(str) {
5
- return super.match(str, 3, /^{[WUBRG](\/[WUBRG]){2}}/i)
6
- || super.match(str, 3, /^[WUBRG](\/[WUBRG]){2}/i);
6
+ return super.match(str, 3, msr`\c(\/\c){2}`);
7
7
  }
8
8
 
9
9
  get type() {
@@ -1,9 +1,9 @@
1
1
  import HybridManaSymbol from './HybridManaSymbol.js';
2
+ import { msr } from '../services/regExpService.js';
2
3
 
3
4
  export default class TwoColorHybridManaSymbol extends HybridManaSymbol {
4
5
  static match(str) {
5
- return super.match(str, 2, /^{[WUBRG]\/[WUBRG]}/i)
6
- || super.match(str, 2, /^[WUBRG]\/[WUBRG]/i);
6
+ return super.match(str, 2, msr`\c\/\c`);
7
7
  }
8
8
 
9
9
  get type() {
@@ -0,0 +1,21 @@
1
+ import Symbol from './Symbol.js';
2
+ import { msr } from '../services/regExpService.js';
3
+
4
+ // used for typed mana, like snow or legendary
5
+ export default class TypedManaSymbol extends Symbol {
6
+ static match(str) {
7
+ return str.match(msr`\T`);
8
+ }
9
+
10
+ get colors() {
11
+ return [];
12
+ }
13
+
14
+ get type() {
15
+ return 'typedMana';
16
+ }
17
+
18
+ cmcValue() {
19
+ return 1;
20
+ }
21
+ }
@@ -1,9 +1,9 @@
1
1
  import NonManaSymbol from './NonManaSymbol.js';
2
+ import { msr } from '../services/regExpService.js';
2
3
 
3
4
  export default class UntapSymbol extends NonManaSymbol {
4
5
  static match(str) {
5
- return str.match(/^{Q}/i)
6
- || str.match(/^Q/i);
6
+ return str.match(msr`Q`);
7
7
  }
8
8
 
9
9
  get type() {
@@ -1,9 +1,9 @@
1
1
  import Symbol from './Symbol.js';
2
+ import { msr } from '../services/regExpService.js';
2
3
 
3
4
  export default class VariableManaSymbol extends Symbol {
4
5
  static match(str) {
5
- return str.match(/^{[XYZ]}/i)
6
- || str.match(/^[XYZ]/i);
6
+ return str.match(msr`[XYZ]`);
7
7
  }
8
8
 
9
9
  get type() {
@@ -1,12 +0,0 @@
1
- import NonManaSymbol from './NonManaSymbol.js';
2
-
3
- export default class EnergySymbol extends NonManaSymbol {
4
- static match(str) {
5
- return str.match(/^{E}/i)
6
- || str.match(/^E/i);
7
- }
8
-
9
- get type() {
10
- return 'energy';
11
- }
12
- }
@@ -1,21 +0,0 @@
1
- import Symbol from './Symbol.js';
2
-
3
- export default class HalfColoredManaSymbol extends Symbol {
4
- static match(str) {
5
- return str.match(/^{\|[WUBRGS]}/i)
6
- || str.match(/^\|[WUBRGS]/i);
7
- }
8
-
9
- get colors() {
10
- const c = this.raw[1];
11
- return c === 'S' ? [] : [c];
12
- }
13
-
14
- get type() {
15
- return 'halfColoredMana';
16
- }
17
-
18
- cmcValue() {
19
- return 0.5;
20
- }
21
- }
@@ -1,20 +0,0 @@
1
- import Symbol from './Symbol.js';
2
-
3
- export default class SnowManaSymbol extends Symbol {
4
- static match(str) {
5
- return str.match(/^{S}/i)
6
- || str.match(/^S/i);
7
- }
8
-
9
- get colors() {
10
- return [];
11
- }
12
-
13
- get type() {
14
- return 'snowMana';
15
- }
16
-
17
- cmcValue() {
18
- return 1;
19
- }
20
- }