fix typing and generation-based matching
This commit is contained in:
		
							
								
								
									
										67
									
								
								calc.js
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								calc.js
									
									
									
									
									
								
							| @@ -1,12 +1,13 @@ | ||||
| import calc, { | ||||
| import { | ||||
|   calculate, | ||||
|   Generations, | ||||
|   Field, | ||||
|   Generations, | ||||
|   Move, | ||||
|   Pokemon, | ||||
|   Result, | ||||
| } from "@ajhyndman/smogon-calc"; | ||||
| import assert from "assert"; | ||||
| import chev, { Lexer } from "chevrotain"; | ||||
| import { createToken, Lexer } from "chevrotain"; | ||||
|  | ||||
| const gen = Generations.get(9); | ||||
|  | ||||
| @@ -16,65 +17,61 @@ const gen = Generations.get(9); | ||||
|  * @returns {Lexer} | ||||
|  */ | ||||
| function buildLexer() { | ||||
|   const Boost = chev.createToken({ name: "Boost", pattern: /[+-]\d+/ }); | ||||
|   const EV = chev.createToken({ name: "EV", pattern: /\d+[+-]?/ }); | ||||
|   const Stat = chev.createToken({ | ||||
|   const Boost = createToken({ name: "Boost", pattern: /[+-]\d+/ }); | ||||
|   const EV = createToken({ name: "EV", pattern: /\d+[+-]?/ }); | ||||
|   const Stat = createToken({ | ||||
|     name: "Stat", | ||||
|     pattern: /HP|Atk|Def|SpA|SpD|Spe/, | ||||
|   }); | ||||
|  | ||||
|   const Item = chev.createToken({ | ||||
|   const Item = createToken({ | ||||
|     name: "Item", | ||||
|     pattern: new RegExp(calc.ITEMS.flatMap((gen) => gen).join("|")), | ||||
|     pattern: new RegExp([...gen.items].map((i) => i.name).join("|")), | ||||
|   }); | ||||
|   const Ability = chev.createToken({ | ||||
|   const Ability = createToken({ | ||||
|     name: "Ability", | ||||
|     pattern: new RegExp(calc.ABILITIES.flatMap((gen) => gen).join("|")), | ||||
|     pattern: new RegExp([...gen.abilities].map((a) => a.name).join("|")), | ||||
|   }); | ||||
|  | ||||
|   const Pokemon = chev.createToken({ | ||||
|   const Pokemon = createToken({ | ||||
|     name: "Pokemon", | ||||
|     pattern: new RegExp( | ||||
|       calc.SPECIES.flatMap((gen) => Object.keys(gen)).join("|") | ||||
|     ), | ||||
|     pattern: new RegExp([...gen.species].map((s) => s.name).join("|")), | ||||
|   }); | ||||
|   const Move = chev.createToken({ | ||||
|   const Move = createToken({ | ||||
|     name: "Move", | ||||
|     pattern: new RegExp( | ||||
|       calc.MOVES.flatMap((gen) => Object.keys(gen)).join("|") | ||||
|     ), | ||||
|     pattern: new RegExp([...gen.moves].map((m) => m.name).join("|")), | ||||
|   }); | ||||
|  | ||||
|   const whitespace = chev.createToken({ | ||||
|   const whitespace = createToken({ | ||||
|     name: "Whitespace", | ||||
|     pattern: /\s+/, | ||||
|     group: Lexer.SKIPPED, | ||||
|   }); | ||||
|   const div = chev.createToken({ | ||||
|   const div = createToken({ | ||||
|     name: "div", | ||||
|     pattern: "/", | ||||
|     group: Lexer.SKIPPED, | ||||
|   }); | ||||
|   const vs = chev.createToken({ | ||||
|   const vs = createToken({ | ||||
|     name: "vs", | ||||
|     pattern: /vs\.?/, | ||||
|   }); | ||||
|  | ||||
|   const terrainEnter = chev.createToken({ | ||||
|   const terrainEnter = createToken({ | ||||
|     name: "terrainEnter", | ||||
|     pattern: "in", | ||||
|     push_mode: "terrain_mode", | ||||
|   }); | ||||
|   const Weather = chev.createToken({ | ||||
|   const Weather = createToken({ | ||||
|     name: "Weather", | ||||
|     pattern: /Sun|Rain|Sand|Snow/, | ||||
|   }); | ||||
|   const Terrain = chev.createToken({ | ||||
|   const Terrain = createToken({ | ||||
|     name: "Terrain", | ||||
|     pattern: /(Electric|Grassy|Misty|Psychic) Terrain/, | ||||
|   }); | ||||
|  | ||||
|   const screenEnter = chev.createToken({ | ||||
|   const screenEnter = createToken({ | ||||
|     name: "screenEnter", | ||||
|     pattern: "through", | ||||
|     push_mode: "screen_mode", | ||||
| @@ -117,7 +114,7 @@ function* iterate(arr) { | ||||
|  | ||||
| /** | ||||
|  * @param {string} type token type | ||||
|  * @param {chev.IToken} token token | ||||
|  * @param {import("chevrotain").IToken} token token | ||||
|  * @return {string} matched token | ||||
|  */ | ||||
| function unwrapToken(type, token) { | ||||
| @@ -155,7 +152,7 @@ const NEG_NATURES = { | ||||
|  * through Light Screen | ||||
|  * | ||||
|  * @param {string} line textual line | ||||
|  * @return {calc.Result} calculation result | ||||
|  * @return {Result} calculation result | ||||
|  */ | ||||
| function parseAndCalculate(line) { | ||||
|   const lexer = buildLexer(); | ||||
| @@ -169,14 +166,14 @@ function parseAndCalculate(line) { | ||||
|   /** @type {string} */ | ||||
|   var defender; | ||||
|  | ||||
|   /** @type {calc.State.Pokemon} */ | ||||
|   /** @type {import("@ajhyndman/smogon-calc").State.Pokemon} */ | ||||
|   var attackerOpts = {}; | ||||
|   /** @type {calc.State.Pokemon} */ | ||||
|   /** @type {import("@ajhyndman/smogon-calc").State.Pokemon} */ | ||||
|   var defenderOpts = {}; | ||||
|  | ||||
|   /** @type {string} */ | ||||
|   var move; | ||||
|   /** @type {calc.State.Field} */ | ||||
|   /** @type {import("@ajhyndman/smogon-calc").State.Field} */ | ||||
|   var field = {}; | ||||
|  | ||||
|   // Tokenising state. | ||||
| @@ -216,7 +213,7 @@ function parseAndCalculate(line) { | ||||
|         } | ||||
|         break; | ||||
|       case "Stat": | ||||
|         throw Error("Impossibel state: bare Stat"); | ||||
|         throw Error("Impossible state: bare Stat"); | ||||
|       case "Item": | ||||
|         opts().item = unwrapToken("Item", item); | ||||
|         break; | ||||
| @@ -269,9 +266,11 @@ function parseAndCalculate(line) { | ||||
|   } | ||||
|  | ||||
|   // Pre-checking before the calculator throws unreadable errors. | ||||
|   if (!gen.species.get(attacker)) throw Error(`No species ${attacker}`); | ||||
|   if (!gen.species.get(defender)) throw Error(`No species ${attacker}`); | ||||
|   if (!gen.moves.get(move)) throw Error(`No move ${move}`); | ||||
|   if (!gen.species.get(attacker.toLowerCase())) | ||||
|     throw Error(`No species named ${attacker}`); | ||||
|   if (!gen.species.get(defender.toLowerCase())) | ||||
|     throw Error(`No species named ${defender}`); | ||||
|   if (!gen.moves.get(move.toLowerCase())) throw Error(`No move named ${move}`); | ||||
|  | ||||
|   return calculate( | ||||
|     gen, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user