Skip to content

Commit

Permalink
Add command to set game option defaults
Browse files Browse the repository at this point in the history
  • Loading branch information
Brainicism committed Dec 21, 2021
1 parent ad7160c commit 624a0d5
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 30 deletions.
1 change: 1 addition & 0 deletions docs/GAMEPLAY.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,5 +255,6 @@ Use `,help [command_name]` for more details for any of the following commands:
- `,include`: Specify which artists to forcefully include, regardless of other game options

- `,reset`: Reset all options to the default settings
- `,setdefault`: Sets the current game options as the default settings
- `,add`: Add groups to `,groups`, `,exclude`, or `,include`
- `,remove`: Remove groups to `,groups`, `,exclude`, or `,include`
17 changes: 9 additions & 8 deletions src/commands/game_options/cutoff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,7 @@ export default class CutoffCommand implements BaseCommand {
call = async ({ message, parsedMessage }: CommandArgs): Promise<void> => {
const guildPreference = await getGuildPreference(message.guildID);
if (parsedMessage.components.length === 0) {
await guildPreference.setBeginningCutoffYear(
DEFAULT_BEGINNING_SEARCH_YEAR
);
await guildPreference.setEndCutoffYear(DEFAULT_ENDING_SEARCH_YEAR);
await guildPreference.reset(GameOption.CUTOFF);
await sendOptionsMessage(
MessageContext.fromMessage(message),
guildPreference,
Expand All @@ -82,8 +79,10 @@ export default class CutoffCommand implements BaseCommand {
const yearRange = parsedMessage.components;
const startYear = yearRange[0];
if (yearRange.length === 1) {
await guildPreference.setBeginningCutoffYear(parseInt(startYear));
await guildPreference.setEndCutoffYear(DEFAULT_ENDING_SEARCH_YEAR);
await guildPreference.setCutoff(
parseInt(startYear),
DEFAULT_ENDING_SEARCH_YEAR
);
} else if (yearRange.length === 2) {
const endYear = yearRange[1];
if (endYear < startYear) {
Expand All @@ -95,8 +94,10 @@ export default class CutoffCommand implements BaseCommand {
return;
}

await guildPreference.setBeginningCutoffYear(parseInt(startYear));
await guildPreference.setEndCutoffYear(parseInt(endYear));
await guildPreference.setCutoff(
parseInt(startYear),
parseInt(endYear)
);
}

await sendOptionsMessage(
Expand Down
48 changes: 48 additions & 0 deletions src/commands/game_options/default.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import BaseCommand, { CommandArgs } from "../interfaces/base_command";
import { IPCLogger } from "../../logger";
import { getGuildPreference } from "../../helpers/game_utils";
import {
getDebugLogHeader,
sendInfoMessage,
} from "../../helpers/discord_utils";
import MessageContext from "../../structures/message_context";
import CommandPrechecks from "../../command_prechecks";

const logger = new IPCLogger("default");

export default class DefaultCommand implements BaseCommand {
preRunChecks = [{ checkFn: CommandPrechecks.competitionPrecheck }];

validations = {
minArgCount: 0,
maxArgCount: 0,
arguments: [],
};

aliases = ["setdefault", "setdefaults", "defaults"];

help = {
name: "default",
description: `Sets the current game option as the defaults (for ${process.env.BOT_PREFIX}reset or per-option resets). This should only be used by experienced users!`,
usage: ",default",
examples: [
{
example: "`,default`",
explanation: "Sets the current game option as the defaults.",
},
],
priority: 130,
};

call = async ({ message }: CommandArgs): Promise<void> => {
const guildPreference = await getGuildPreference(message.guildID);
await guildPreference.setAsDefault();
logger.info(`${getDebugLogHeader(message)} | Set default game options`);

await sendInfoMessage(MessageContext.fromMessage(message), {
title: "Success!",
description:
"Default game options has been set to the current options!",
});
};
}
12 changes: 12 additions & 0 deletions src/migrations/20211221024206_game_option_defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
exports.up = function (knex) {
return knex.schema.createTable("game_option_defaults", (table) => {
table.string("guild_id").notNullable();
table.string("option_name").notNullable();
table.json("option_value");
table.unique(["guild_id", "option_name"]);
});
};

exports.down = function (knex) {
return knex.schema.dropTableIfExists("game_option_defaults");
};
107 changes: 91 additions & 16 deletions src/structures/guild_preference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,13 @@ export default class GuildPreference {
default: [0, DEFAULT_LIMIT],
setter: this.setLimit,
},
[GameOption.CUTOFF]: {
default: [
DEFAULT_BEGINNING_SEARCH_YEAR,
DEFAULT_ENDING_SEARCH_YEAR,
],
setter: this.setCutoff,
},
[GameOption.GROUPS]: { default: [null], setter: this.setGroups },
[GameOption.EXCLUDE]: { default: [null], setter: this.setExcludes },
[GameOption.INCLUDE]: { default: [null], setter: this.setIncludes },
Expand Down Expand Up @@ -470,32 +477,51 @@ export default class GuildPreference {
]);
}

/**
* Resets a specific game option to the default value
* @param gameOption - The game option to reset
*/
async reset(gameOption: GameOption): Promise<void> {
if (gameOption in this.resetArgs) {
const resetArg = this.resetArgs[gameOption];
resetArg.setter.bind(this)(...resetArg.default);
const defaultGameOptionOverride =
await this.getGameOptionDefaultOverrides();

if (!defaultGameOptionOverride) {
resetArg.setter.bind(this)(...resetArg.default);
return;
}

// get game optional internal keys to reset
const gameOptionsDefaultsToReset = Object.keys(
GameOptionInternalToGameOption
).filter(
(key) => GameOptionInternalToGameOption[key] === gameOption
);

// associated override values
const gameOptionDefaultResets = gameOptionsDefaultsToReset.map(
(key) => defaultGameOptionOverride[key]
);

resetArg.setter.bind(this)(
...(gameOptionDefaultResets || resetArg.default)
);
}
}

/**
* Sets the beginning cutoff year option value
* @param year - The beginning cutoff year
* Sets the cutoff option value
* @param beginningYear - The beginning cutoff year
* @param endingYear - The ending cutoff year
*/
async setBeginningCutoffYear(year: number): Promise<void> {
this.gameOptions.beginningYear = year;
await this.updateGuildPreferences([
{ name: GameOptionInternal.BEGINNING_YEAR, value: year },
]);
}
async setCutoff(beginningYear: number, endingYear?: number): Promise<void> {
this.gameOptions.beginningYear = beginningYear;
this.gameOptions.endYear = endingYear ?? DEFAULT_ENDING_SEARCH_YEAR;

/**
* Sets the end cutoff year option value
* @param year - The end cutoff year
*/
async setEndCutoffYear(year: number): Promise<void> {
this.gameOptions.endYear = year;
await this.updateGuildPreferences([
{ name: GameOptionInternal.END_YEAR, value: year },
{ name: GameOptionInternal.BEGINNING_YEAR, value: beginningYear },
{ name: GameOptionInternal.END_YEAR, value: endingYear },
]);
}

Expand Down Expand Up @@ -908,6 +934,17 @@ export default class GuildPreference {
async resetToDefault(): Promise<Array<GameOption>> {
const oldOptions = this.gameOptions;
this.gameOptions = { ...GuildPreference.DEFAULT_OPTIONS };

// apply per-server game option default overrides
const gameOptionOverrides = await this.getGameOptionDefaultOverrides();
if (gameOptionOverrides) {
for (const [option, value] of Object.entries(gameOptionOverrides)) {
if (value) {
this.gameOptions[option] = value;
}
}
}

const options = Object.entries(this.gameOptions).map((x) => {
const optionName = x[0];
const optionValue = x[1];
Expand All @@ -922,4 +959,42 @@ export default class GuildPreference {

return updatedOptions.map((x) => x[0] as GameOption);
}

/** Sets the current game options as the default */
async setAsDefault(): Promise<void> {
const options = Object.entries(this.gameOptions).map((x) => ({
guild_id: this.guildID,
option_name: x[0],
option_value: JSON.stringify(x[1]),
}));

await dbContext.kmq.transaction(async (trx) => {
await dbContext
.kmq("game_option_defaults")
.where("guild_id", "=", this.guildID)
.del()
.transacting(trx);

await dbContext
.kmq("game_option_defaults")
.insert(options)
.transacting(trx);
});
}

/* Gets the per-server game option default overrides */
async getGameOptionDefaultOverrides(): Promise<GameOptions> {
const defaultOverrides = await dbContext
.kmq("game_option_defaults")
.where("guild_id", "=", this.guildID);

if (defaultOverrides.length === 0) return null;

const gameOptions = defaultOverrides.reduce((prev, curr) => {
prev[curr["option_name"]] = JSON.parse(curr["option_value"]);
return prev;
}, {});

return gameOptions;
}
}
14 changes: 8 additions & 6 deletions src/test/ci/song_selector.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
LanguageType,
} from "../../commands/game_options/language";
import { ShuffleType } from "../../commands/game_options/shuffle";
import { DEFAULT_BEGINNING_SEARCH_YEAR } from "../../commands/game_options/cutoff";

async function getMockGuildPreference(): Promise<GuildPreference> {
const guildPreference = new GuildPreference("test");
Expand Down Expand Up @@ -244,7 +245,7 @@ describe("getFilteredSongList", () => {
(song) => song.publishedon >= new Date("2016-01-01")
).length;

await guildPreference.setBeginningCutoffYear(2016);
await guildPreference.setCutoff(2016);
const { songs } = await SongSelector.getFilteredSongList(
guildPreference
);
Expand All @@ -259,7 +260,10 @@ describe("getFilteredSongList", () => {
(song) => song.publishedon <= new Date("2015-12-31")
).length;

await guildPreference.setEndCutoffYear(2015);
await guildPreference.setCutoff(
DEFAULT_BEGINNING_SEARCH_YEAR,
2015
);
const { songs } = await SongSelector.getFilteredSongList(
guildPreference
);
Expand All @@ -276,8 +280,7 @@ describe("getFilteredSongList", () => {
song.publishedon <= new Date("2018-12-31")
).length;

await guildPreference.setBeginningCutoffYear(2008);
await guildPreference.setEndCutoffYear(2018);
await guildPreference.setCutoff(2008, 2018);
const { songs } = await SongSelector.getFilteredSongList(
guildPreference
);
Expand All @@ -294,8 +297,7 @@ describe("getFilteredSongList", () => {
song.publishedon <= new Date("2017-12-31")
).length;

await guildPreference.setBeginningCutoffYear(2017);
await guildPreference.setEndCutoffYear(2017);
await guildPreference.setCutoff(2017, 2017);
const { songs } = await SongSelector.getFilteredSongList(
guildPreference
);
Expand Down

0 comments on commit 624a0d5

Please sign in to comment.