Skip to content

Commit

Permalink
Merge pull request #37 from AlecM33/wildcard
Browse files Browse the repository at this point in the history
wildcard command
  • Loading branch information
AlecM33 authored Aug 10, 2024
2 parents 0934df5 + ee65954 commit 6d47683
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 21 deletions.
20 changes: 20 additions & 0 deletions commands/wildcard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const interactionHandlers = require('../modules/interaction-handlers.js');
const { SlashCommandBuilder } = require('@discordjs/builders');

module.exports = {
data: new SlashCommandBuilder()
.setName('wildcard')
.setDescription('View the current wildcard standings.'),
async execute (interaction) {
try {
await interactionHandlers.wildcardHandler(interaction);
} catch (e) {
console.error(e);
if (interaction.deferred && !interaction.replied) {
await interaction.followUp('There was an error processing this command. If it persists, please reach out to the developer.');
} else if (!interaction.replied) {
await interaction.reply('There was an error processing this command. If it persists, please reach out to the developer.');
}
}
}
};
8 changes: 8 additions & 0 deletions modules/MLB-API-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ const endpoints = {
},
players: () => {
return 'https://statsapi.mlb.com/api/v1/sports/1/players?fields=people,fullName,lastName,id,currentTeam,primaryPosition,name,code,abbreviation';
},
wildcard: () => {
return 'https://bdfed.stitch.mlbinfra.com/bdfed/transform-mlb-standings?&splitPcts=false&numberPcts=false&standingsView=division&sortTemplate=3&season=' +
(new Date().getFullYear()) + '&leagueIds=103,104&standingsTypes=wildCard&contextTeamId=&date=' +
((new Date()).toISOString().split('T')[0]) + '&hydrateAlias=noSchedule&sortDivisions=201,202,200,204,205,203&sortLeagues=103,104,115,114&sortSports=1';
}
};

Expand Down Expand Up @@ -254,5 +259,8 @@ module.exports = {
},
players: async () => {
return (await fetch(endpoints.players())).json();
},
wildcard: async () => {
return (await fetch(endpoints.wildcard())).json();
}
};
94 changes: 73 additions & 21 deletions modules/command-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,27 +223,7 @@ module.exports = {
},

buildStandingsTable: async (standings, divisionName) => {
const centralMap = standings.teamRecords.map(teamRecord => {
return {
name: teamRecord.team.name,
wins: teamRecord.leagueRecord.wins,
losses: teamRecord.leagueRecord.losses,
pct: teamRecord.leagueRecord.pct,
gamesBack: teamRecord.gamesBack,
homeRecord: (() => {
const home = teamRecord.records.splitRecords.find(record => record.type === 'home');
return home.wins + '-' + home.losses;
})(),
awayRecord: (() => {
const away = teamRecord.records.splitRecords.find(record => record.type === 'away');
return away.wins + '-' + away.losses;
})(),
lastTen: (() => {
const l10 = teamRecord.records.splitRecords.find(record => record.type === 'lastTen');
return l10.wins + '-' + l10.losses;
})()
};
});
const centralMap = mapStandings(standings);
const table = new AsciiTable(divisionName + '\n');
table.setHeading('Team', 'W-L', 'GB', 'L10');
centralMap.forEach((entry) => table.addRow(
Expand All @@ -256,6 +236,37 @@ module.exports = {
return (await getScreenshotOfHTMLTables([table]));
},

buildWildcardTable: async (divisionLeaders, wildcard, leagueName) => {
const divisionLeadersMap = mapStandings(divisionLeaders);
const wildcardMap = mapStandings(wildcard, true);
const table = new AsciiTable(leagueName + ' Wild Card \n');
table.setHeading('Team', 'W-L', 'WCGB', 'L10', 'STRK');
divisionLeadersMap.forEach((entry) => table.addRow(
entry.name,
entry.wins + '-' + entry.losses,
'-',
entry.lastTen,
entry.streak
));
let wildCardDivided = false;
table.addRow('', '', '', '', '');
wildcardMap.forEach((entry) => {
if (!wildCardDivided && entry.gamesBack !== '-' && !entry.gamesBack.includes('+')) {
wildCardDivided = true;
table.addRow('', '', '', '', '');
}
table.addRow(
entry.name,
entry.wins + '-' + entry.losses,
entry.gamesBack,
entry.lastTen,
entry.streak
);
});
table.removeBorder();
return (await getScreenshotOfHTMLTables([table]));
},

getStatcastData: (savantText) => {
const statcast = /statcast: \[(?<statcast>.+)],/.exec(savantText)?.groups.statcast;
const metricSummaries = /metricSummaryStats: {(?<metricSummaries>.+)},/.exec(savantText)?.groups.metricSummaries;
Expand Down Expand Up @@ -858,6 +869,37 @@ module.exports = {
}
};

function mapStandings (standings, wildcard = false) {
return standings.teamRecords.map(teamRecord => {
return {
name: teamRecord.team.name + (standings.standingsType === 'divisionLeaders' ? ' - ' + getDivisionAbbreviation(teamRecord.team.division.name) : ''),
wins: (teamRecord.leagueRecord?.wins === undefined ? teamRecord.wins : teamRecord.leagueRecord.wins),
losses: (teamRecord.leagueRecord?.losses === undefined ? teamRecord.losses : teamRecord.leagueRecord.losses),
pct: (teamRecord.leagueRecord?.pct === undefined ? teamRecord.pct : teamRecord.leagueRecord.pct),
gamesBack: (wildcard ? teamRecord.wildCardGamesBack : teamRecord.gamesBack),
homeRecord: (teamRecord.record_home
? teamRecord.record_home
: (() => {
const home = teamRecord.records.splitRecords.find(record => record.type === 'home');
return home.wins + '-' + home.losses;
})()),
awayRecord: (teamRecord.record_away
? teamRecord.record_away
: (() => {
const away = teamRecord.records.splitRecords.find(record => record.type === 'away');
return away.wins + '-' + away.losses;
})()),
lastTen: (teamRecord.record_lastTen
? teamRecord.record_lastTen
: (() => {
const l10 = teamRecord.records.splitRecords.find(record => record.type === 'lastTen');
return l10.wins + '-' + l10.losses;
})()),
streak: teamRecord.streak
};
});
}

function getPitchCollections (dom) {
const pitches = [];
const percentages = [];
Expand Down Expand Up @@ -1119,3 +1161,13 @@ function calculateRoundedPercentileFromNormalDistribution (metric, value, mean,
(shouldInvert ? (1.00 - ztable((value - mean) / standardDeviation)) : ztable((value - mean) / standardDeviation)) * 100
);
}

function getDivisionAbbreviation (division) {
if (division.toLowerCase().includes('east')) {
return 'E';
} else if (division.toLowerCase().includes('west')) {
return 'W';
} else {
return 'C';
}
}
18 changes: 18 additions & 0 deletions modules/interaction-handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,22 @@ module.exports = {
});
},

wildcardHandler: async (interaction) => {
await interaction.deferReply();
console.info(`WILDCARD command invoked by guild: ${interaction.guildId}`);
const team = await mlbAPIUtil.team(process.env.TEAM_ID);
const leagueId = team.teams[0].league.id;
const leagueName = team.teams[0].league.name;
const wildcard = (await mlbAPIUtil.wildcard()).records
.find(record => record.standingsType === 'wildCard' && record.league === leagueId);
const divisionLeaders = (await mlbAPIUtil.wildcard()).records
.find(record => record.standingsType === 'divisionLeaders' && record.league === leagueId);
await interaction.followUp({
ephemeral: false,
files: [new AttachmentBuilder((await commandUtil.buildWildcardTable(divisionLeaders, wildcard, leagueName)), { name: 'wildcard.png' })]
});
},

subscribeGamedayHandler: async (interaction) => {
console.info(`SUBSCRIBE GAMEDAY command invoked by guild: ${interaction.guildId}`);
if (!interaction.member.roles.cache.some(role => globals.ADMIN_ROLES.includes(role.name))) {
Expand Down Expand Up @@ -442,6 +458,7 @@ module.exports = {
},

batterSavantHandler: async (interaction) => {
console.info(`BATTER SAVANT command invoked by guild: ${interaction.guildId}`);
await interaction.deferReply();
const playerName = interaction.options.getString('player')?.trim();
const playerResult = await commandUtil.getPlayerFromUserInputOrLiveFeed(playerName, interaction, 'Batter');
Expand Down Expand Up @@ -474,6 +491,7 @@ module.exports = {
},

pitcherSavantHandler: async (interaction) => {
console.info(`PITCHER SAVANT command invoked by guild: ${interaction.guildId}`);
await interaction.deferReply();
const playerName = interaction.options.getString('player')?.trim();
const playerResult = await commandUtil.getPlayerFromUserInputOrLiveFeed(playerName, interaction, 'Pitcher');
Expand Down

0 comments on commit 6d47683

Please sign in to comment.