fix typing and generation-based matching

This commit is contained in:
xeals 2023-04-27 10:38:19 +10:00
parent 6d92cb4deb
commit 70141b162f
Signed by: xeals
GPG Key ID: A498C7AF27EC6B5C

67
calc.js
View File

@ -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,