Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Commands: Improve timer and showgif #80

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
24 changes: 10 additions & 14 deletions src/commands/user-hosted-game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -712,16 +712,9 @@ export const commands: BaseCommandDefinitions = {
time *= 60 * 1000;
}
} else {
time = parseFloat(targets[0] ? targets[0].trim() : "");
if (secondsArguments.includes(Tools.toId(targets[1]))) {
if (isNaN(time) || time > 60 || time < 3) return this.say("Please enter an amount of seconds between 3 and 60.");
time *= 1000;
} else {
if (isNaN(time) || time < 1) {
return this.say("Please enter a valid amount of minutes (add `` seconds`` to use seconds).");
}
time *= 60 * 1000;
}
time = Tools.fromTimeString(target);
if (!time) time = Tools.fromTimeString(target + (target.trim().length === 1 ? "min" : "sec"));
if (Number.isNaN(time) || time < 3000) this.say("Please enter an amount of seconds more than 3 seconds.");
}

if (now + time > gameRoom.userHostedGame.endTime) {
Expand Down Expand Up @@ -759,10 +752,13 @@ export const commands: BaseCommandDefinitions = {
return this.say("The game start timer has been turned off.");
}

const minutes = parseInt(target.trim());
if (isNaN(minutes) || minutes < 1 || minutes > 4) return this.say("You must specify a number of minutes between 1 and 4.");
room.userHostedGame.setStartTimer(minutes);
this.say("The game will start in " + minutes + " minutes.");
let time = Tools.fromTimeString(target);
if (!time) time = Tools.fromTimeString(id + (id.length === 1 ? "min" : "sec"));
if (isNaN(time) || time < 60 * 1000 || time > 60 * 4000) {
return this.say("You must specify time between 1 minute and 4 minutes.");
}
room.userHostedGame.setStartTimer(time);
this.say("The game will start in " + Tools.toDurationString(time) + ".");
},
chatOnly: true,
aliases: ['sgtimer'],
Expand Down
26 changes: 16 additions & 10 deletions src/commands/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { BaseCommandDefinitions } from "../types/command-parser";
import type { CharacterType, ModelGeneration, LocationType, RegionName } from "../types/dex";
import type { IPokemon } from "../types/pokemon-showdown";

const shinyOption = "shiny";
const RANDOM_GENERATOR_LIMIT = 6;

export const commands: BaseCommandDefinitions = {
Expand Down Expand Up @@ -66,14 +67,10 @@ export const commands: BaseCommandDefinitions = {
return this.say("Your timer has been turned off.");
}

let time: number;
if (id.length === 1) {
time = parseInt(id) * 60;
} else {
time = parseInt(id);
}
if (isNaN(time) || time > 1800 || time < 5) return this.say("Please enter an amount of time between 5 seconds and 30 minutes.");
time *= 1000;
let time = Tools.fromTimeString(target);
if (!time) time = Tools.fromTimeString(target + (target.trim().length === 1 ? "min" : "sec"));
if (isNaN(time) || time > 30 * 60 * 1000 || time < 5000)
return this.say("Please enter an amount of time between 5 seconds and 30 minutes.");

if (!room.timers) room.timers = {};
if (timerId in room.timers) clearTimeout(room.timers[timerId]);
Expand Down Expand Up @@ -199,14 +196,23 @@ export const commands: BaseCommandDefinitions = {
const gifsOrIcons: string[] = [];
const pokemonList: IPokemon[] = [];

for (const name of targets) {
for (let name of targets) {
name = name.trim();
let shiny: boolean = false;
const names = name.split(" ");
if (names[0] === shinyOption) {
shiny = true;
name = names.slice(1).join("");
}
if (showIcon && shiny) return this.say("You cannot specify the option shiny with icons.");
const pokemon = Dex.getPokemon(name);
if (!pokemon) return this.sayError(['invalidPokemon', name]);
if (!showIcon && !Dex.hasModelData(pokemon, generation)) {
return this.say(pokemon.name + " does not have a" + (isBW ? " BW" : "") + " gif.");
}
pokemonList.push(pokemon);
gifsOrIcons.push(showIcon ? Dex.getPSPokemonIcon(pokemon) + pokemon.name : Dex.getPokemonModel(pokemon, generation));
gifsOrIcons.push(showIcon ? Dex.getPSPokemonIcon(pokemon) + pokemon.name :
Dex.getPokemonModel(pokemon, generation, "front", shiny));
}

if (!gifsOrIcons.length) return this.say("You must specify at least 1 Pokemon.");
Expand Down
4 changes: 2 additions & 2 deletions src/room-game-user-hosted.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,9 @@ export class UserHostedGame extends Game {
this.parseCommand(this.subHostName || this.hostName, command, target);
}

setStartTimer(minutes: number): void {
setStartTimer(time: number): void {
if (this.startTimer) clearTimeout(this.startTimer);
this.startTimer = setTimeout(() => this.useHostCommand('startgame'), minutes * 60 * 1000);
this.startTimer = setTimeout(() => this.useHostCommand('startgame'), time);
}

// Players
Expand Down
17 changes: 17 additions & 0 deletions src/test/modules/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,23 @@ describe("Tools", () => {
assert(!Tools.isFloat('-'));
assert(!Tools.isFloat('@'));
});
it('should return proper values from fromTimeString()', () => {
assertStrictEqual(Tools.fromTimeString('1 sec'), 1 * second);
assertStrictEqual(Tools.fromTimeString('1+e7 seconds'), 0);
assertStrictEqual(Tools.fromTimeString('2.5sec'), 2.5 * second);
assertStrictEqual(Tools.fromTimeString('10seconds'), 10 * second);
assertStrictEqual(Tools.fromTimeString('1 min'), 1 * minute);
assertStrictEqual(Tools.fromTimeString('a sec'), 1 * second);
assertStrictEqual(Tools.fromTimeString('a min'), 1 * minute);
assertStrictEqual(Tools.fromTimeString('1min, 1sec'), 1 * minute + 1 * second);
assertStrictEqual(Tools.fromTimeString('5seconds, 5min'), 5 * minute + 5 * second);
assertStrictEqual(Tools.fromTimeString('5minand5min,5min'), 10 * minute);
assertStrictEqual(Tools.fromTimeString('10minute,1sec'), 10 * minute + 1 * second);
assertStrictEqual(Tools.fromTimeString('1hour,10sec'), 10 * second);
assertStrictEqual(Tools.fromTimeString('an hour'), 0);
assertStrictEqual(Tools.fromTimeString(''), 0);
});

it('should return proper values from toDurationString()', () => {
assertStrictEqual(Tools.toDurationString(second), '1 second');
assertStrictEqual(Tools.toDurationString(2 * second), '2 seconds');
Expand Down
24 changes: 24 additions & 0 deletions src/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,30 @@ export class Tools {
return parts.slice(0, 3).join("-") + " " + parts.slice(3, human ? 5 : 6).join(":") + (human ? "" + parts[6] : "");
}

fromTimeString(input: string): number {
const targets: string[] = input.split(input.includes("and") ? "and" : ",")
.map((str) => str.toLowerCase().replaceAll(/[^a-z0-9.]/g, ""));
let time: number = 0;
for (const t of targets) {
if (t.includes("sec")) {
const possibleAmount = t.split("sec")[0]!;
if (!possibleAmount.includes("e")) {
const amount = possibleAmount === "a" ? 1 : parseFloat(possibleAmount);
if (!Number.isNaN(amount)) time += amount * 1000;
}
}
if (t.includes("min")) {
const possibleAmount = t.split("min")[0]!;
if (!possibleAmount.includes("e")) {
const amount = possibleAmount === "a" ? 1 : parseFloat(possibleAmount);
if (!Number.isNaN(amount)) time += amount * 60 * 1000;
}
}
}
if (time < 0) return 0;
return time;
}

/**Converts `input` in milliseconds to a duration string */
toDurationString(input: number, options?: {precision?: number; hhmmss?: boolean, milliseconds?: boolean}): string {
const date = new Date(input);
Expand Down