diff --git a/config/globals.js b/config/globals.js index 1662672..4dd70d3 100644 --- a/config/globals.js +++ b/config/globals.js @@ -63,6 +63,8 @@ module.exports = { 'other_out' ], SAVANT_POLLING_INTERVAL: 15000, + SAVANT_POLLING_ATTEMPTS: 15, + HOME_RUN_BALLPARKS_MIN_DISTANCE: 300, SLOW_POLL_INTERVAL: 300000, GAMEDAY_PING_INTERVAL: 10000, HIGHLIGHTS_PER_MESSAGE: 8, @@ -70,8 +72,8 @@ module.exports = { DATE: null, ADMIN_ROLES: [ "Mod" ], TEAM_COLOR_CONTRAST_RATIO: 1.5, - HOME_RUN_PARKS_MIN: 4, - HOME_RUN_PARKS_MAX: 26, + HOME_RUN_PARKS_MIN: 5, + HOME_RUN_PARKS_MAX: 25, EVENTS: [ "Double", "Double Play", diff --git a/modules/current-play-processor.js b/modules/current-play-processor.js index 6bc1c9a..6a49b45 100644 --- a/modules/current-play-processor.js +++ b/modules/current-play-processor.js @@ -77,13 +77,14 @@ function addScore (reply, currentPlayJSON) { function addMetrics (lastEvent, reply) { if (lastEvent.hitData.launchSpeed) { // this data can be randomly unavailable - reply += '\n\n**Statcast Metrics:**\n'; + reply += '\n\n'; reply += 'Exit Velo: ' + lastEvent.hitData.launchSpeed + ' mph' + getFireEmojis(lastEvent.hitData.launchSpeed) + '\n'; reply += 'Launch Angle: ' + lastEvent.hitData.launchAngle + '° \n'; reply += 'Distance: ' + lastEvent.hitData.totalDistance + ' ft.\n'; - reply += 'xBA: Pending...'; - reply += lastEvent.hitData.totalDistance && lastEvent.hitData.totalDistance >= 300 ? '\nHR/Park: Pending...' : ''; + reply += 'xBA: Pending...\n'; + reply += 'Bat Speed: Pending...'; + reply += lastEvent.hitData.totalDistance && lastEvent.hitData.totalDistance >= globals.HOME_RUN_BALLPARKS_MIN_DISTANCE ? '\nHR/Park: Pending...' : ''; } else { reply += '\n\n**Statcast Metrics:**\n'; reply += 'Data was not available.'; diff --git a/modules/gameday-util.js b/modules/gameday-util.js index 5668e3f..125ef50 100644 --- a/modules/gameday-util.js +++ b/modules/gameday-util.js @@ -43,8 +43,14 @@ module.exports = { getDueUp: () => { const feed = liveFeed.init(globalCache.values.game.currentLiveFeed); const linescore = feed.linescore(); + const upIndex = linescore.offense.battingOrder > 9 ? linescore.offense.battingOrder % 9 : linescore.offense.battingOrder; + const onDeckIndex = linescore.offense.battingOrder >= 9 ? (linescore.offense.battingOrder + 1) % 9 : linescore.offense.battingOrder + 1; + const inHoleIndex = linescore.offense.battingOrder >= 8 ? (linescore.offense.battingOrder + 2) % 9 : linescore.offense.battingOrder + 2; - return '\n\n**Due up**: ' + linescore.offense?.batter?.fullName + ', ' + linescore.offense?.onDeck?.fullName + ', ' + linescore.offense?.inHole?.fullName; + return '\n\n**Due up**: ' + + upIndex + '. ' + linescore.offense?.batter?.fullName + ', ' + + onDeckIndex + '. ' + linescore.offense?.onDeck?.fullName + ', ' + + inHoleIndex + '. ' + linescore.offense?.inHole?.fullName; }, getXParks: async (gamePk, playId, numberOfParks) => { diff --git a/modules/gameday.js b/modules/gameday.js index 53c1ecd..1ea319d 100644 --- a/modules/gameday.js +++ b/modules/gameday.js @@ -252,18 +252,25 @@ function notifySavantDataUnavailable (messages) { async function pollForSavantData (gamePk, playId, messages, hitDistance) { let attempts = 1; const messageTrackers = messages.map(message => { return { id: message.id, done: false }; }); + console.time('xBA: ' + playId); + console.time('Bat Speed: ' + playId); + if (hitDistance >= globals.HOME_RUN_BALLPARKS_MIN_DISTANCE) { + console.time('HR/Park: ' + playId); + } const pollingFunction = async () => { if (messageTrackers.every(messageTracker => messageTracker.done)) { LOGGER.debug('Savant: all messages done.'); return; } - if (attempts < 10) { + if (attempts < globals.SAVANT_POLLING_ATTEMPTS) { LOGGER.trace('Savant: polling for ' + playId + '...'); const gameFeed = await mlbAPIUtil.savantGameFeed(gamePk); const matchingPlay = gameFeed?.team_away?.find(play => play?.play_id === playId) || gameFeed?.team_home?.find(play => play?.play_id === playId); - if (matchingPlay && (matchingPlay.xba || matchingPlay.contextMetrics?.homeRunBallparks !== undefined)) { - module.exports.processMatchingPlay(matchingPlay, messages, messageTrackers, playId, hitDistance); + if (matchingPlay && (matchingPlay.xba + || matchingPlay.contextMetrics?.homeRunBallparks !== undefined + || matchingPlay.batSpeed !== undefined)) { + await module.exports.processMatchingPlay(matchingPlay, messages, messageTrackers, playId, hitDistance); } attempts ++; setTimeout(async () => { await pollingFunction(); }, globals.SAVANT_POLLING_INTERVAL); @@ -282,21 +289,34 @@ async function processMatchingPlay (matchingPlay, messages, messageTrackers, pla let description = messages[i].embeds[0].description; if (matchingPlay.xba && description.includes('xBA: Pending...')) { LOGGER.debug('Editing with xba: ' + playId); + console.timeEnd('xBA: ' + playId); description = description.replaceAll('xBA: Pending...', 'xBA: ' + matchingPlay.xba + (matchingPlay.is_barrel === 1 ? ' \uD83D\uDFE2 (Barreled)' : '')); receivedEmbed.setDescription(description); messages[i].edit({ embeds: [receivedEmbed] }).then((m) => LOGGER.trace('Edited: ' + m.id)).catch((e) => console.error(e)); - if (hitDistance && hitDistance < 300) { - LOGGER.debug('Found xba, done polling for: ' + playId); + } + if (matchingPlay.batSpeed && description.includes('Bat Speed: Pending...')) { + LOGGER.debug('Editing with Bat Speed: ' + playId); + console.timeEnd('Bat Speed: ' + playId); + description = description.replaceAll('Bat Speed: Pending...', 'Bat Speed: ' + matchingPlay.batSpeed + ' mph' + + (matchingPlay.isSword ? ' \u2694\uFE0F (Sword)' : '') + + (matchingPlay.batSpeed >= 75.0 ? ' \u26A1' : '')); + receivedEmbed.setDescription(description); + messages[i].edit({ + embeds: [receivedEmbed] + }).then((m) => LOGGER.trace('Edited: ' + m.id)).catch((e) => console.error(e)); + if (hitDistance && hitDistance < globals.HOME_RUN_BALLPARKS_MIN_DISTANCE && matchingPlay.xba) { + LOGGER.debug('Found xba and bat speed, done polling for: ' + playId); messageTrackers.find(tracker => tracker.id === messages[i].id).done = true; } } - if (hitDistance && hitDistance >= 300 + if (hitDistance && hitDistance >= globals.HOME_RUN_BALLPARKS_MIN_DISTANCE && matchingPlay.contextMetrics.homeRunBallparks !== undefined && description.includes('HR/Park: Pending...')) { LOGGER.debug('Editing with HR/Park: ' + playId); + console.timeEnd('HR/Park: ' + playId); const homeRunBallParksDescription = 'HR/Park: ' + matchingPlay.contextMetrics.homeRunBallparks + '/30' + (matchingPlay.contextMetrics.homeRunBallparks === 30 ? '\u203C\uFE0F' : '') + (await gamedayUtil.getXParks(feed.gamePk(), playId, matchingPlay.contextMetrics.homeRunBallparks)); @@ -305,7 +325,7 @@ async function processMatchingPlay (matchingPlay, messages, messageTrackers, pla messages[i].edit({ embeds: [receivedEmbed] }).then((m) => LOGGER.trace('Edited: ' + m.id)).catch((e) => console.error(e)); - if (matchingPlay.xba) { + if (matchingPlay.xba && matchingPlay.batSpeed !== undefined) { LOGGER.debug('Found all metrics: done polling for: ' + playId); messageTrackers.find(tracker => tracker.id === messages[i].id).done = true; }