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

Add Mafia search capability #10467

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
39d76be
Mafia: Prevent incorrect alignment.
Lucas-Meijer Jan 28, 2023
6509702
Mafia: Update readability.
Lucas-Meijer Jan 28, 2023
a345222
Merge pull request #1 from smogon/master
Lucas-Meijer Nov 7, 2023
f45a045
Merge branch 'master' of https://github.com/Lucas-Meijer/pokemon-show…
May 27, 2024
da8c7a2
Merge branch 'master' of https://github.com/Lucas-Meijer/pokemon-show…
Jun 1, 2024
b352d5e
Implement mafia search, mafia randomdata
Jun 3, 2024
6f2c746
Add Mafia Autohost
Jun 25, 2024
79933c5
setup autohost
Jul 2, 2024
e100d21
Test commit
Jul 7, 2024
2c32677
Scav and Mafia changes
Jul 10, 2024
e0ea6f1
Scavengers fix image scroll
Jul 11, 2024
7e7285d
Merge pull request #2 from Lucas-Meijer/scav-images
Lucas-Meijer Jul 11, 2024
57f4a67
Merge branch 'smogon:master' into master
Lucas-Meijer Jul 11, 2024
c947220
Remove tags
Jul 29, 2024
18ba599
Improve theme searching
Jul 30, 2024
6bbdca0
Improve for npm test
Aug 2, 2024
79253ba
Merge branch 'smogon:master' into mafia-search
Lucas-Meijer Aug 2, 2024
b88b3ce
Remove unwanted changes
Aug 2, 2024
65baee0
Merge branch 'mafia-search' of https://github.com/Lucas-Meijer/pokemo…
Aug 2, 2024
1a773d2
Remove scavengers tab added
Aug 2, 2024
3f68014
Fix TypeScript type errors
Aug 4, 2024
78bdeac
Add StartsWith instead of indexing
Aug 4, 2024
e4426c8
Fix TypeScript errors, idea searching
Aug 13, 2024
c7d8258
Remove more autohost
Aug 13, 2024
0cdc93c
Start fixing types Mafia
Aug 21, 2024
63a0379
Edit Mafia
Aug 30, 2024
a4d45b4
Merge branch 'master' into mafia-search
KrisXV Oct 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
242 changes: 231 additions & 11 deletions server/chat-plugins/mafia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,16 @@
MafiaData = readFile(DATA_FILE) || {alignments: {}, roles: {}, themes: {}, IDEAs: {}, terms: {}, aliases: {}};
if (!MafiaData.alignments.town) {
MafiaData.alignments.town = {
name: 'town', plural: 'town', memo: [`This alignment is required for the script to function properly.`],
name: 'Town',
plural: 'Town',
memo: [`This alignment is required for the script to function properly.`],
};
}
if (!MafiaData.alignments.solo) {
MafiaData.alignments.solo = {
name: 'solo', plural: 'solo', memo: [`This alignment is required for the script to function properly.`],
name: 'Solo',
plural: 'Solo',
memo: [`This alignment is required for the script to function properly.`],
};
}

Expand Down Expand Up @@ -323,6 +327,7 @@
dlAt: number;

IDEA: MafiaIDEAModule;

constructor(room: ChatRoom, host: User) {
super(room);

Expand All @@ -335,6 +340,7 @@

this.hostid = host.id;
this.host = Utils.escapeHTML(host.name);

this.cohostids = [];
this.cohosts = [];

Expand Down Expand Up @@ -2192,7 +2198,6 @@
}
return this.parse('/help mafia');
},

forcehost: 'host',
nexthost: 'host',
host(target, room, user, connection, cmd) {
Expand Down Expand Up @@ -4049,23 +4054,222 @@
this.sendReply(`The entry ${entry} was deleted from the ${source} database.`);
},
deletedatahelp: [`/mafia deletedata source,entry - Removes an entry from the database. Requires % @ # ~`],
listdata(target, room, user) {
if (!(target in MafiaData)) {
return this.errorReply(`Invalid source. Valid sources are ${Object.keys(MafiaData).join(', ')}`);

randtheme: 'listdata',
randrole: 'listdata',
randalignment: 'listdata',
randidea: 'listdata',
randterm: 'listdata',
randroles: 'listdata',
randalignments: 'listdata',
randideas: 'listdata',
randterms: 'listdata',
randdata: 'listdata',
randomtheme: 'listdata',
randomrole: 'listdata',
randomalignment: 'listdata',
randomidea: 'listdata',
randomterm: 'listdata',
randomdata: 'listdata',
randomthemes: 'listdata',
randomroles: 'listdata',
randomalignments: 'listdata',
randomideas: 'listdata',
randomterms: 'listdata',
randthemes: 'listdata',
listthemes: 'listdata',
listroles: 'listdata',
listalignments: 'listdata',
listideas: 'listdata',
listterms: 'listdata',
themes: 'listdata',
roles: 'listdata',
alignments: 'listdata',
ideas: 'listdata',
terms: 'listdata',
ds: 'listdata',
search: 'listdata',
random: 'listdata',
list: 'listdata',
listdata(target, room, user, connection, cmd, message) {
if (!this.runBroadcast()) return false;

// Determine non-search targets first, afterward searching is done with the remainder
const targets = target.split(',').map(x => x.trim().toLowerCase());

// Determine search type
let searchType: keyof MafiaData = 'aliases';
if (cmd.includes('theme') || targets.includes(`themes`)) {
searchType = `themes`;
if (targets.includes(`themes`)) targets.splice(targets.indexOf(`themes`), 1);
} else if (cmd.includes('role') || targets.includes(`roles`)) {
searchType = `roles`;
if (targets.includes(`roles`)) targets.splice(targets.indexOf(`roles`), 1);
} else if (cmd.includes('alignment') || targets.includes(`alignments`)) {
searchType = `alignments`;
if (targets.includes(`alignments`)) targets.splice(targets.indexOf(`alignments`), 1);
} else if (cmd.includes('idea') || targets.includes(`ideas`)) {
searchType = `IDEAs`;
if (targets.includes(`ideas`)) targets.splice(targets.indexOf(`ideas`), 1);
} else if (cmd.includes('term') || targets.includes(`terms`)) {
searchType = `terms`;
if (targets.includes(`terms`)) targets.splice(targets.indexOf(`terms`), 1);
} else if (targets.includes(`aliases`)) {
searchType = `aliases`;
} else if (cmd === 'random' || cmd === 'randomdata' || cmd === 'randdata') {
searchType = ([`themes`, `roles`, `alignments`, `IDEAs`, `terms`] as (keyof MafiaData)[])[Math.floor(Math.random() * 5)];

Check warning on line 4120 in server/chat-plugins/mafia.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

This line has a length of 121. Maximum allowed is 120
} else {
return this.errorReply(`Invalid source. Valid sources are ${Object.keys(MafiaData).filter(key => key !== `aliases`).join(', ')}.`);
}
const dataSource = MafiaData[target as keyof MafiaData];
if (dataSource === MafiaData.aliases) {

const dataSource = MafiaData[searchType as keyof MafiaData];

Check failure on line 4125 in server/chat-plugins/mafia.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

This assertion is unnecessary since it does not change the type of the expression

const random = (cmd.includes('rand') || targets.includes(`random`));

if (targets.includes(`random`)) targets.splice(targets.indexOf(`random`), 1);

const hidden = (targets.includes(`hidden`));
if (hidden) targets.splice(targets.indexOf(`hidden`), 1);

const shuffle = function (array: any[]) { // replace by utils thing
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[j], array[i]] = [array[i], array[j]];
}
return array;
};

// Number of results
let number = random ? 1 : 0;
for (let i = 0; i < targets.length; i++) {
if (((targets[i] !== null) &&
(targets[i] !== '') &&
!isNaN(Number(targets[i].toString())))) {
number = Number(targets[i]);
targets.splice(i, 1);
break;
}
}

// Convert to rows
const themeRow = function (theme: MafiaDataTheme, players = 0) {
return `<tr><td style="text-align:left;width:30%" ><button class="button" name = "send" value = "/mafia theme ${theme.name}" > ${theme.name} </button> </td><td style="text-align:left;width:70%">${players > 0 ? theme[players] : theme.desc} </td></tr >`;
};
const ideaRow = function (idea: MafiaDataIDEA) {
return `<tr><td style="text-align:left;width:100%" ><button class="button" name = "send" value = "/mafia dt ${idea.name}" > ${idea.name} </button> </td></tr >`;
};
const row = function (role: MafiaDataRole | MafiaDataTerm | MafiaDataAlignment) {
return `<tr><td style="text-align:left;width:30%" ><button class="button" name = "send" value = "/mafia role ${role.name}" > ${role.name} </button> </td><td style="text-align:left;width:70%">${role.memo.join(' ')} </td></tr >`;
};

if (searchType === `aliases`) { // Can I use dataSource > searchType
room = this.requireRoom();
this.checkCan('mute', null, room);
const aliases = Object.entries(MafiaData.aliases)
.map(([from, to]) => `${from}: ${to}`)
.join('<br/>');
return this.sendReplyBox(`Mafia aliases:<br/>${aliases}`);
} else {
const entries = Object.entries(dataSource)
.map(([key, data]) => `<button class="button" name="send" value="/mafia dt ${key}">${data.name}</button>`)
let table = `<div style="max-height:300px;overflow:auto;"><table border="1" style="border: 1px solid black;width: 100%">`;
let entries : [string, MafiaDataAlignment | MafiaDataRole | MafiaDataTheme | MafiaDataIDEA | MafiaDataTerm][] = Object.entries(dataSource).sort();

Check warning on line 4174 in server/chat-plugins/mafia.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

This line has a length of 146. Maximum allowed is 120

Check failure on line 4174 in server/chat-plugins/mafia.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

Unexpected space before the ':'

for (const targetString of targets) {
entries = targetString.split('|').map(x => x.trim())
.map(searchTerm => search(entries.slice(), searchTerm, searchType))
.reduce((aggregate, result) => [...new Set([...aggregate, ...result])]);
}

if (typeof (entries) === 'undefined') return;

if (random) entries = shuffle(entries);
if (number > 0) entries = entries.slice(0, number);

if (entries.length === 0) {
return this.errorReply(`No ${searchType} found.`);
}

if (entries.length === 1) {
this.target = entries[0][0];
return this.run((Chat.commands.mafia as Chat.ChatCommands).data as Chat.AnnotatedChatHandler);
}

table += entries
.map(([key, data]) => searchType === `themes` ?
themeRow(MafiaData[searchType][key]) : searchType === `IDEAs` ?
ideaRow(MafiaData[searchType][key]) : row(MafiaData[searchType][key]))
.join('');
return this.sendReplyBox(`Mafia ${target}:<br/>${entries}`);
table += `</table></div>`;
return this.sendReplyBox(table);
}
},
listdatahelp: [
`/mafia roles [parameter, paramater, ...] - Views all Mafia roles. Parameters: theme that must include role, text included in role data.`,
`/mafia themes [parameter, paramater, ...] - Views all Mafia themes. Parameters: roles in theme, players(< | <= | = | => | >)[x] for playercounts, text included in theme data.`,
`/mafia alignments [parameter, paramater, ...] - Views all Mafia alignments. Parameters: text included in alignment data.`,
`/mafia ideas [parameter, paramater, ...] - Views all Mafia IDEAs. Parameters: roles in IDEA, text included in IDEA data.`,
`/mafia terms [parameter, paramater, ...] - Views all Mafia terms. Parameters: text included in term data.`,
`/mafia randomrole [parameter, paramater, ...] - View a random Mafia role. Parameters: number of roles to be randomly generated, theme that must include role, text included in role data.`,
`/mafia randomtheme [parameter, paramater, ...] - View a random Mafia theme. Parameters: number of themes to be randomly generated, roles in theme, players(< | <= | = | => | >)[x] for playercounts, text included in theme data.`,
`/mafia randomalignment [parameter, paramater, ...] - View a random Mafia alignment. Parameters: number of alignments to be randomly generated, text included in alignment data.`,
`/mafia randomidea [parameter, paramater, ...] - View a random Mafia IDEA. Parameters: number of IDEAs to be randomly generated, roles in IDEA, text included in IDEA data.`,
`/mafia randomterm [parameter, paramater, ...] - View a random Mafia term. Parameters: number of terms to be randomly generated, text included in term data.`,
],

search (entries: [string, MafiaDataAlignment | MafiaDataRole | MafiaDataTheme | MafiaDataIDEA | MafiaDataTerm][], searchTarget: string, searchType: keyof MafiaData) {

Check warning on line 4218 in server/chat-plugins/mafia.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

This line has a length of 166. Maximum allowed is 120

Check failure on line 4218 in server/chat-plugins/mafia.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

Unexpected space before function parentheses
if (typeof (entries) === 'undefined') return entries;
if (searchType === `aliases`) return entries;

if (searchTarget.length === 0) return entries;
const negation = searchTarget.startsWith('!');

if (negation) searchTarget = searchTarget.substring(1).trim();
const entriesCopy = entries.slice();

const alias = toID((toID(searchTarget) in MafiaData[`aliases`]) ?
MafiaData[`aliases`][toID(searchTarget)] : searchTarget);

if (searchType === `themes` && searchTarget.includes(`players`)) {
const inequalities = ['<=', '>=', '=', '<', '>'];
const inequality = inequalities.find(x => searchTarget.includes(x));
if (!inequality) return entries; // this.errorReply(`Please provide a valid inequality for the players.`);

const players = searchTarget.split(inequality)[1].trim();
if (((players !== null) &&
(players !== '') &&
!isNaN(Number(players)))) {
if (inequality === '=') {
entries = entries.filter(([key, data]) => players in MafiaData[`themes`][key]);
} else if (inequality === '<' || inequality === '<=') {
entries = entries.filter(([key, data]) => ([...Array(+players + (inequality === '<=' ? +1 : +0)).keys()])
.some(playerCount => playerCount in (MafiaData[`themes`][key])));
} else if (inequality === '>' || inequality === '>=') {
entries = entries.filter(([key, data]) => ([...Array(50 - Number(players)).keys()]
.map(num => +num + +players + (inequality === '>=' ? +0 : +1)))
.some(playerCount => playerCount in (MafiaData[`themes`][key])));
}
} else {
return entries;
}
} else if (searchType === `themes` && alias in MafiaData[`roles`]) {
entries = entries.filter(([key, data]) => ([...Array(50).keys()])
.some(playerCount => playerCount in (MafiaData[`themes`][key]) &&
(MafiaData[`themes`][key])[playerCount].toString().toLowerCase().includes(alias)));
} else if (searchType === `IDEAs` && alias in MafiaData[`roles`]) {
entries = entries.filter(([key, data]) => MafiaData[`IDEAs`][key].roles.map(role =>
toID((toID(role) in MafiaData[`aliases`]) ? MafiaData[`aliases`][toID(role)] : role)).includes(alias));
} else if (searchType === `roles` && alias in MafiaData[`themes`]) {
entries = entries.filter(([key, data]) => Object.keys(MafiaData[`themes`][alias])
.filter((newKey: any) => toID((MafiaData[`themes`][alias])[newKey].toString()).includes(key)).length > 0);
} else if (searchType === `roles` && alias in MafiaData[`IDEAs`]) {
entries = entries.filter(([key, data]) => MafiaData[`IDEAs`][alias].roles.map(role =>
toID((toID(role) in MafiaData[`aliases`]) ? MafiaData[`aliases`][toID(role)] : role)).includes(key));
} else {
entries = entries.filter(([key, data]) => Object.keys((MafiaData[searchType][key]))
.filter((newKey: any) => (MafiaData[searchType][key])[newKey]
.toString().toLowerCase().includes(searchTarget)).length > 0);
}
return negation ? entriesCopy.filter(element => !entries.includes(element)) : entries;
},

disable(target, room, user) {
room = this.requireRoom();
Expand Down Expand Up @@ -4198,6 +4402,22 @@
`/mafia (un)gameban [user], [duration] - Ban a user from playing games for [duration] days. Requires % @ # ~`,
].join('<br/>');
buf += `</details>`;
buf += `</details><details><summary class="button">Mafia Dexsearch Commands</summary>`;
buf += [
`<br/><strong>Commands to search Mafia data</strong>:<br/>`,
`/mafia dt [data] - Views Mafia data.`,
`/mafia roles [parameter, paramater, ...] - Views all Mafia roles. Parameters: theme that must include role, text included in role data.`,
`/mafia themes [parameter, paramater, ...] - Views all Mafia themes. Parameters: roles in theme, players(< | <= | = | => | >)[x] for playercounts, text included in theme data.`,
`/mafia alignments [parameter, paramater, ...] - Views all Mafia alignments. Parameters: text included in alignment data.`,
`/mafia ideas [parameter, paramater, ...] - Views all Mafia IDEAs. Parameters: roles in IDEA, text included in IDEA data.`,
`/mafia terms [parameter, paramater, ...] - Views all Mafia terms. Parameters: text included in term data.`,
`/mafia randomrole [parameter, paramater, ...] - View a random Mafia role. Parameters: number of roles to be randomly generated, theme that must include role, text included in role data.`,
`/mafia randomtheme [parameter, paramater, ...] - View a random Mafia theme. Parameters: number of themes to be randomly generated, roles in theme, players(< | <= | = | => | >)[x] for playercounts, text included in theme data.`,
`/mafia randomalignment [parameter, paramater, ...] - View a random Mafia alignment. Parameters: number of alignments to be randomly generated, text included in alignment data.`,
`/mafia randomidea [parameter, paramater, ...] - View a random Mafia IDEA. Parameters: number of IDEAs to be randomly generated, roles in IDEA, text included in IDEA data.`,
`/mafia randomterm [parameter, paramater, ...] - View a random Mafia term. Parameters: number of terms to be randomly generated, text included in term data.`,
].join('<br/>');
buf += `</details>`;

return this.sendReplyBox(buf);
},
Expand Down
Loading