Compare commits
No commits in common. "70141b162f6715d47859401238e571c503158733" and "bf1793e56117324a354c376ff693d30f09f50c00" have entirely different histories.
70141b162f
...
bf1793e561
145
.gitignore
vendored
145
.gitignore
vendored
@ -11,148 +11,3 @@ htmlcov
|
|||||||
*.db
|
*.db
|
||||||
cache/
|
cache/
|
||||||
token
|
token
|
||||||
|
|
||||||
# Created by https://www.toptal.com/developers/gitignore/api/node
|
|
||||||
# Edit at https://www.toptal.com/developers/gitignore?templates=node
|
|
||||||
|
|
||||||
### Node ###
|
|
||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
.pnpm-debug.log*
|
|
||||||
|
|
||||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
||||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
||||||
|
|
||||||
# Runtime data
|
|
||||||
pids
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
*.pid.lock
|
|
||||||
|
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
||||||
lib-cov
|
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
|
||||||
coverage
|
|
||||||
*.lcov
|
|
||||||
|
|
||||||
# nyc test coverage
|
|
||||||
.nyc_output
|
|
||||||
|
|
||||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
||||||
.grunt
|
|
||||||
|
|
||||||
# Bower dependency directory (https://bower.io/)
|
|
||||||
bower_components
|
|
||||||
|
|
||||||
# node-waf configuration
|
|
||||||
.lock-wscript
|
|
||||||
|
|
||||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
||||||
build/Release
|
|
||||||
|
|
||||||
# Dependency directories
|
|
||||||
node_modules/
|
|
||||||
jspm_packages/
|
|
||||||
|
|
||||||
# Snowpack dependency directory (https://snowpack.dev/)
|
|
||||||
web_modules/
|
|
||||||
|
|
||||||
# TypeScript cache
|
|
||||||
*.tsbuildinfo
|
|
||||||
|
|
||||||
# Optional npm cache directory
|
|
||||||
.npm
|
|
||||||
|
|
||||||
# Optional eslint cache
|
|
||||||
.eslintcache
|
|
||||||
|
|
||||||
# Optional stylelint cache
|
|
||||||
.stylelintcache
|
|
||||||
|
|
||||||
# Microbundle cache
|
|
||||||
.rpt2_cache/
|
|
||||||
.rts2_cache_cjs/
|
|
||||||
.rts2_cache_es/
|
|
||||||
.rts2_cache_umd/
|
|
||||||
|
|
||||||
# Optional REPL history
|
|
||||||
.node_repl_history
|
|
||||||
|
|
||||||
# Output of 'npm pack'
|
|
||||||
*.tgz
|
|
||||||
|
|
||||||
# Yarn Integrity file
|
|
||||||
.yarn-integrity
|
|
||||||
|
|
||||||
# dotenv environment variable files
|
|
||||||
.env
|
|
||||||
.env.development.local
|
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
|
||||||
.env.local
|
|
||||||
|
|
||||||
# parcel-bundler cache (https://parceljs.org/)
|
|
||||||
.cache
|
|
||||||
.parcel-cache
|
|
||||||
|
|
||||||
# Next.js build output
|
|
||||||
.next
|
|
||||||
out
|
|
||||||
|
|
||||||
# Nuxt.js build / generate output
|
|
||||||
.nuxt
|
|
||||||
dist
|
|
||||||
|
|
||||||
# Gatsby files
|
|
||||||
.cache/
|
|
||||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
|
||||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
|
||||||
# public
|
|
||||||
|
|
||||||
# vuepress build output
|
|
||||||
.vuepress/dist
|
|
||||||
|
|
||||||
# vuepress v2.x temp and cache directory
|
|
||||||
.temp
|
|
||||||
|
|
||||||
# Docusaurus cache and generated files
|
|
||||||
.docusaurus
|
|
||||||
|
|
||||||
# Serverless directories
|
|
||||||
.serverless/
|
|
||||||
|
|
||||||
# FuseBox cache
|
|
||||||
.fusebox/
|
|
||||||
|
|
||||||
# DynamoDB Local files
|
|
||||||
.dynamodb/
|
|
||||||
|
|
||||||
# TernJS port file
|
|
||||||
.tern-port
|
|
||||||
|
|
||||||
# Stores VSCode versions used for testing VSCode extensions
|
|
||||||
.vscode-test
|
|
||||||
|
|
||||||
# yarn v2
|
|
||||||
.yarn/cache
|
|
||||||
.yarn/unplugged
|
|
||||||
.yarn/build-state.yml
|
|
||||||
.yarn/install-state.gz
|
|
||||||
.pnp.*
|
|
||||||
|
|
||||||
### Node Patch ###
|
|
||||||
# Serverless Webpack directories
|
|
||||||
.webpack/
|
|
||||||
|
|
||||||
# Optional stylelint cache
|
|
||||||
|
|
||||||
# SvelteKit build / generate output
|
|
||||||
.svelte-kit
|
|
||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/node
|
|
||||||
|
28
bot.py
28
bot.py
@ -61,37 +61,11 @@ class BotClient(discord.Client):
|
|||||||
|
|
||||||
async def on_message(self, message: discord.Message):
|
async def on_message(self, message: discord.Message):
|
||||||
content = message.content
|
content = message.content
|
||||||
if self.is_command(message):
|
if self.is_replay(message):
|
||||||
await self.on_command(message)
|
|
||||||
elif self.is_replay(message):
|
|
||||||
await self.on_replay(message)
|
await self.on_replay(message)
|
||||||
elif self.is_leaguefact(message):
|
elif self.is_leaguefact(message):
|
||||||
await self.on_leaguefact(message)
|
await self.on_leaguefact(message)
|
||||||
|
|
||||||
def is_command(self, message: discord.Message) -> bool:
|
|
||||||
return message.content.startswith("%")
|
|
||||||
|
|
||||||
async def on_command(self, message: discord.Message):
|
|
||||||
match message.content.split(" "):
|
|
||||||
case ["%calc", *args]:
|
|
||||||
try:
|
|
||||||
calc = await self._calculate(args)
|
|
||||||
await message.reply(content=calc.strip())
|
|
||||||
except Exception as e:
|
|
||||||
await message.reply(
|
|
||||||
content="```\n" + str(e) + "\n```", delete_after=30
|
|
||||||
)
|
|
||||||
case _:
|
|
||||||
_log.info(f"Unrecognised command {command}")
|
|
||||||
|
|
||||||
async def _calculate(self, args: list[str]) -> str:
|
|
||||||
proc = sp.run(
|
|
||||||
["node", "calc_main.js", "--"] + args, stdout=sp.PIPE, stderr=sp.PIPE
|
|
||||||
)
|
|
||||||
if proc.returncode != 0:
|
|
||||||
raise Exception(proc.stderr.decode())
|
|
||||||
return proc.stdout.decode()
|
|
||||||
|
|
||||||
def is_replay(self, message: discord.Message) -> bool:
|
def is_replay(self, message: discord.Message) -> bool:
|
||||||
if re.match("https://replay.pokemonshowdown.com/dl-.*", message.content):
|
if re.match("https://replay.pokemonshowdown.com/dl-.*", message.content):
|
||||||
return True
|
return True
|
||||||
|
304
calc.js
304
calc.js
@ -1,304 +0,0 @@
|
|||||||
import {
|
|
||||||
calculate,
|
|
||||||
Field,
|
|
||||||
Generations,
|
|
||||||
Move,
|
|
||||||
Pokemon,
|
|
||||||
Result,
|
|
||||||
} from "@ajhyndman/smogon-calc";
|
|
||||||
import assert from "assert";
|
|
||||||
import { createToken, Lexer } from "chevrotain";
|
|
||||||
|
|
||||||
const gen = Generations.get(9);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a lexer.
|
|
||||||
*
|
|
||||||
* @returns {Lexer}
|
|
||||||
*/
|
|
||||||
function buildLexer() {
|
|
||||||
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 = createToken({
|
|
||||||
name: "Item",
|
|
||||||
pattern: new RegExp([...gen.items].map((i) => i.name).join("|")),
|
|
||||||
});
|
|
||||||
const Ability = createToken({
|
|
||||||
name: "Ability",
|
|
||||||
pattern: new RegExp([...gen.abilities].map((a) => a.name).join("|")),
|
|
||||||
});
|
|
||||||
|
|
||||||
const Pokemon = createToken({
|
|
||||||
name: "Pokemon",
|
|
||||||
pattern: new RegExp([...gen.species].map((s) => s.name).join("|")),
|
|
||||||
});
|
|
||||||
const Move = createToken({
|
|
||||||
name: "Move",
|
|
||||||
pattern: new RegExp([...gen.moves].map((m) => m.name).join("|")),
|
|
||||||
});
|
|
||||||
|
|
||||||
const whitespace = createToken({
|
|
||||||
name: "Whitespace",
|
|
||||||
pattern: /\s+/,
|
|
||||||
group: Lexer.SKIPPED,
|
|
||||||
});
|
|
||||||
const div = createToken({
|
|
||||||
name: "div",
|
|
||||||
pattern: "/",
|
|
||||||
group: Lexer.SKIPPED,
|
|
||||||
});
|
|
||||||
const vs = createToken({
|
|
||||||
name: "vs",
|
|
||||||
pattern: /vs\.?/,
|
|
||||||
});
|
|
||||||
|
|
||||||
const terrainEnter = createToken({
|
|
||||||
name: "terrainEnter",
|
|
||||||
pattern: "in",
|
|
||||||
push_mode: "terrain_mode",
|
|
||||||
});
|
|
||||||
const Weather = createToken({
|
|
||||||
name: "Weather",
|
|
||||||
pattern: /Sun|Rain|Sand|Snow/,
|
|
||||||
});
|
|
||||||
const Terrain = createToken({
|
|
||||||
name: "Terrain",
|
|
||||||
pattern: /(Electric|Grassy|Misty|Psychic) Terrain/,
|
|
||||||
});
|
|
||||||
|
|
||||||
const screenEnter = createToken({
|
|
||||||
name: "screenEnter",
|
|
||||||
pattern: "through",
|
|
||||||
push_mode: "screen_mode",
|
|
||||||
});
|
|
||||||
|
|
||||||
return new Lexer({
|
|
||||||
modes: {
|
|
||||||
default_mode: [
|
|
||||||
whitespace,
|
|
||||||
div,
|
|
||||||
vs,
|
|
||||||
Boost,
|
|
||||||
EV,
|
|
||||||
Stat,
|
|
||||||
Item,
|
|
||||||
Ability,
|
|
||||||
Pokemon,
|
|
||||||
Move,
|
|
||||||
terrainEnter,
|
|
||||||
screenEnter,
|
|
||||||
],
|
|
||||||
terrain_mode: [whitespace, screenEnter, Weather, Terrain],
|
|
||||||
screen_mode: [whitespace, Move],
|
|
||||||
},
|
|
||||||
defaultMode: "default_mode",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @generator
|
|
||||||
* @template T item type
|
|
||||||
* @param {T[]} arr
|
|
||||||
* @yields {T} item
|
|
||||||
*/
|
|
||||||
function* iterate(arr) {
|
|
||||||
for (const a of arr) {
|
|
||||||
yield a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} type token type
|
|
||||||
* @param {import("chevrotain").IToken} token token
|
|
||||||
* @return {string} matched token
|
|
||||||
*/
|
|
||||||
function unwrapToken(type, token) {
|
|
||||||
assert(
|
|
||||||
token.tokenType.name == type,
|
|
||||||
"expected token %s, got %s",
|
|
||||||
type,
|
|
||||||
token.tokenType.name
|
|
||||||
);
|
|
||||||
return token.image;
|
|
||||||
}
|
|
||||||
|
|
||||||
const POS_NATURES = {
|
|
||||||
atk: "Adamant",
|
|
||||||
def: "Bold",
|
|
||||||
spa: "Modest",
|
|
||||||
spd: "Calm",
|
|
||||||
spe: "Jolly",
|
|
||||||
};
|
|
||||||
|
|
||||||
const NEG_NATURES = {
|
|
||||||
atk: "Modest",
|
|
||||||
def: "Lonely",
|
|
||||||
spa: "Adamant",
|
|
||||||
spd: "Rash",
|
|
||||||
spe: "Brave",
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a Smogon calculator output:
|
|
||||||
*
|
|
||||||
* -2 8 SpA Choice Specs Torkoal vs.
|
|
||||||
* 252 HP / 4+ SpD Assault Vest Abomasnow
|
|
||||||
* in Sun
|
|
||||||
* through Light Screen
|
|
||||||
*
|
|
||||||
* @param {string} line textual line
|
|
||||||
* @return {Result} calculation result
|
|
||||||
*/
|
|
||||||
function parseAndCalculate(line) {
|
|
||||||
const lexer = buildLexer();
|
|
||||||
const result = lexer.tokenize(line);
|
|
||||||
if (result.errors && result.errors.length > 0) {
|
|
||||||
console.error("Unparsed tokens: %o", result.errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @type {string} */
|
|
||||||
var attacker;
|
|
||||||
/** @type {string} */
|
|
||||||
var defender;
|
|
||||||
|
|
||||||
/** @type {import("@ajhyndman/smogon-calc").State.Pokemon} */
|
|
||||||
var attackerOpts = {};
|
|
||||||
/** @type {import("@ajhyndman/smogon-calc").State.Pokemon} */
|
|
||||||
var defenderOpts = {};
|
|
||||||
|
|
||||||
/** @type {string} */
|
|
||||||
var move;
|
|
||||||
/** @type {import("@ajhyndman/smogon-calc").State.Field} */
|
|
||||||
var field = {};
|
|
||||||
|
|
||||||
// Tokenising state.
|
|
||||||
var isAttacker = true;
|
|
||||||
var it = iterate(result.tokens);
|
|
||||||
|
|
||||||
const opts = () => (isAttacker ? attackerOpts : defenderOpts);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
let item = it.next().value;
|
|
||||||
if (!item) break;
|
|
||||||
switch (item.tokenType.name) {
|
|
||||||
case "Boost":
|
|
||||||
{
|
|
||||||
let boost = unwrapToken("Boost", item);
|
|
||||||
let ev = unwrapToken("EV", it.next().value);
|
|
||||||
let stat = unwrapToken("Stat", it.next().value).toLowerCase();
|
|
||||||
opts().boosts = { [stat]: parseInt(boost), ...opts().boosts };
|
|
||||||
opts().evs = { [stat]: parseInt(ev), ...opts().evs };
|
|
||||||
if (ev.endsWith("+")) {
|
|
||||||
opts().nature = POS_NATURES[stat];
|
|
||||||
} else if (ev.endsWith("-")) {
|
|
||||||
opts().nature = NEG_NATURES[stat];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "EV":
|
|
||||||
{
|
|
||||||
let ev = unwrapToken("EV", item);
|
|
||||||
let stat = unwrapToken("Stat", it.next().value).toLowerCase();
|
|
||||||
opts().evs = { [stat]: parseInt(ev), ...opts().evs };
|
|
||||||
if (ev.endsWith("+")) {
|
|
||||||
opts().nature = POS_NATURES[stat];
|
|
||||||
} else if (ev.endsWith("-")) {
|
|
||||||
opts().nature = NEG_NATURES[stat];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "Stat":
|
|
||||||
throw Error("Impossible state: bare Stat");
|
|
||||||
case "Item":
|
|
||||||
opts().item = unwrapToken("Item", item);
|
|
||||||
break;
|
|
||||||
case "Pokemon":
|
|
||||||
{
|
|
||||||
let name = unwrapToken("Pokemon", item);
|
|
||||||
if (isAttacker) attacker = name;
|
|
||||||
else defender = name;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "Move":
|
|
||||||
move = unwrapToken("Move", item);
|
|
||||||
break;
|
|
||||||
case "terrainEnter":
|
|
||||||
{
|
|
||||||
let next = it.next().value;
|
|
||||||
switch (next.tokenType.name) {
|
|
||||||
case "Weather":
|
|
||||||
field.weather = next.image;
|
|
||||||
break;
|
|
||||||
case "Terrain":
|
|
||||||
field.terrain = next.image;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw Error(
|
|
||||||
"Unhandled terrain %s: %s",
|
|
||||||
next.tokenType.name,
|
|
||||||
next.image
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "screenEnter":
|
|
||||||
{
|
|
||||||
let screen = unwrapToken("Move", it.next().value);
|
|
||||||
field.defenderSide = field.defenderSide || {};
|
|
||||||
field.defenderSide.isLightScreen = screen === "Light Screen";
|
|
||||||
field.defenderSide.isReflect = screen === "Reflect";
|
|
||||||
field.defenderSide.isAuroraVeil = screen === "Aurora Veil";
|
|
||||||
field.defenderSide.is;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "vs":
|
|
||||||
isAttacker = false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.error("unmatched token type: %s", item.tokenType.name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pre-checking before the calculator throws unreadable errors.
|
|
||||||
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,
|
|
||||||
new Pokemon(gen, attacker, attackerOpts),
|
|
||||||
new Pokemon(gen, defender, defenderOpts),
|
|
||||||
new Move(gen, move),
|
|
||||||
new Field(field)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test() {
|
|
||||||
const text =
|
|
||||||
"-2 8 SpA Choice Specs Torkoal Overheat vs. 252 HP / 4+ SpD Assault Vest Abomasnow in Sun through Light Screen";
|
|
||||||
const res = parseAndCalculate(text);
|
|
||||||
|
|
||||||
assert(res.attacker.boosts.spa === -2, "should have -2 SpA");
|
|
||||||
assert(res.attacker.evs.spa === 8, "should have 8 SpA EVs");
|
|
||||||
assert(res.attacker.item === "Choice Specs", "should have Choice Specs");
|
|
||||||
assert(res.attacker.name === "Torkoal", "should be Torkoal");
|
|
||||||
assert(res.move.name === "Overheat", "should be Overheat");
|
|
||||||
assert(res.defender.evs.hp === 252, "should have 252 HP EVs");
|
|
||||||
assert(res.defender.evs.spd === 4, "should have 4 SpD EVs");
|
|
||||||
assert(res.field.weather === "Sun", "should be in sun");
|
|
||||||
|
|
||||||
assert(
|
|
||||||
res.desc().replace(/:.*/, "") === text,
|
|
||||||
"non-damage text should be equivalent to input"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { parseAndCalculate, test };
|
|
@ -1,8 +0,0 @@
|
|||||||
import { parseAndCalculate } from "./calc.js";
|
|
||||||
|
|
||||||
// FIXME: issue with using execArgv.
|
|
||||||
let args = process.argv.slice(2);
|
|
||||||
if (args[0] === "--") args = args.slice(1);
|
|
||||||
const line = args.join(" ");
|
|
||||||
const res = parseAndCalculate(line);
|
|
||||||
console.log(res.fullDesc());
|
|
@ -17,11 +17,7 @@
|
|||||||
ps.requests
|
ps.requests
|
||||||
]);
|
]);
|
||||||
in
|
in
|
||||||
[
|
[ python pkgs.sqlite ];
|
||||||
pkgs.nodejs
|
|
||||||
python
|
|
||||||
pkgs.sqlite
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
82
package-lock.json
generated
82
package-lock.json
generated
@ -1,82 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "hhirls",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"lockfileVersion": 3,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"name": "hhirls",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"license": "WTFPL",
|
|
||||||
"dependencies": {
|
|
||||||
"@ajhyndman/smogon-calc": "^0.8.0",
|
|
||||||
"chevrotain": "^10.5.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@ajhyndman/smogon-calc": {
|
|
||||||
"version": "0.8.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@ajhyndman/smogon-calc/-/smogon-calc-0.8.0.tgz",
|
|
||||||
"integrity": "sha512-jx/gY1uSD70skzE0xE7+lUPp7KxKKqj3PcyRLMCejbd9A68PwnBKfbDP3pW5ILX9Dy+9R9m6OkiPCa9K4qi/pQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": "^18.14.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@chevrotain/cst-dts-gen": {
|
|
||||||
"version": "10.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.5.0.tgz",
|
|
||||||
"integrity": "sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==",
|
|
||||||
"dependencies": {
|
|
||||||
"@chevrotain/gast": "10.5.0",
|
|
||||||
"@chevrotain/types": "10.5.0",
|
|
||||||
"lodash": "4.17.21"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@chevrotain/gast": {
|
|
||||||
"version": "10.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-10.5.0.tgz",
|
|
||||||
"integrity": "sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==",
|
|
||||||
"dependencies": {
|
|
||||||
"@chevrotain/types": "10.5.0",
|
|
||||||
"lodash": "4.17.21"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@chevrotain/types": {
|
|
||||||
"version": "10.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-10.5.0.tgz",
|
|
||||||
"integrity": "sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A=="
|
|
||||||
},
|
|
||||||
"node_modules/@chevrotain/utils": {
|
|
||||||
"version": "10.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-10.5.0.tgz",
|
|
||||||
"integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ=="
|
|
||||||
},
|
|
||||||
"node_modules/@types/node": {
|
|
||||||
"version": "18.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.1.tgz",
|
|
||||||
"integrity": "sha512-DZxSZWXxFfOlx7k7Rv4LAyiMroaxa3Ly/7OOzZO8cBNho0YzAi4qlbrx8W27JGqG57IgR/6J7r+nOJWw6kcvZA=="
|
|
||||||
},
|
|
||||||
"node_modules/chevrotain": {
|
|
||||||
"version": "10.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-10.5.0.tgz",
|
|
||||||
"integrity": "sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==",
|
|
||||||
"dependencies": {
|
|
||||||
"@chevrotain/cst-dts-gen": "10.5.0",
|
|
||||||
"@chevrotain/gast": "10.5.0",
|
|
||||||
"@chevrotain/types": "10.5.0",
|
|
||||||
"@chevrotain/utils": "10.5.0",
|
|
||||||
"lodash": "4.17.21",
|
|
||||||
"regexp-to-ast": "0.5.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/lodash": {
|
|
||||||
"version": "4.17.21",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
|
||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
|
||||||
},
|
|
||||||
"node_modules/regexp-to-ast": {
|
|
||||||
"version": "0.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz",
|
|
||||||
"integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
17
package.json
17
package.json
@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "hhirls",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "Pokemon Showdown data processing, mostly for HHIRLLL's Pokemon league. Ugly as fuck.",
|
|
||||||
"main": "calc.js",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"calc": "node calc_main.js",
|
|
||||||
"test": "node -e 'import(\"./calc.js\").then(mod => mod.test())'"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "WTFPL",
|
|
||||||
"dependencies": {
|
|
||||||
"@ajhyndman/smogon-calc": "^0.8.0",
|
|
||||||
"chevrotain": "^10.5.0"
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user