Write patch to pull in weekly player data to database; start player/team stat models

This commit is contained in:
Garrett Mills 2020-11-07 12:10:19 -06:00
parent 9d3d614c20
commit 5cc3d31415
Signed by: garrettmills
GPG Key ID: D2BF5FBA8298F246
8 changed files with 166 additions and 6 deletions

View File

@ -4,7 +4,7 @@ const path = require('path')
class FrontendUnit extends Unit { class FrontendUnit extends Unit {
static get services() { static get services() {
return [...super.services, 'configs', 'express', 'canon', 'utility'] return [...super.services, 'configs', 'express', 'canon', 'utility', 'models']
} }
constructor(...args) { constructor(...args) {
@ -40,6 +40,14 @@ class FrontendUnit extends Unit {
}, },
Express.static(this.directory), Express.static(this.directory),
]) ])
// Set the default setting values
const Setting = this.models.get('models::setting') // a built-in helper
const default_settings = this.configs.get('settings.default_settings') || []
for ( const default_setting of default_settings ) {
await Setting.guarantee(default_setting.key, default_setting.value)
}
} }
} }

View File

@ -0,0 +1,67 @@
const { Injectable } = require('flitter-di')
/**
* A data patch which fetches all of the player stats for a range of
* weeks and creates WeeklyPlayerStat records for all players for all
* weeks.
*
* This builds the base of data we need to calculate the weekly team
* standings.
*
* @example
* P = require('./app/SeedWeeklyPlayerData.patch')
* p = _di.make(P)
* await p.run()
*
* @extends Injectable
*/
class SeedWeeklyPlayerDataPatch extends Injectable {
static get services() {
return [...super.services, 'models', 'sports_data', 'output']
}
/**
* Run the patch.
* @return {Promise<void>}
*/
async run() {
const Player = this.models.get('Player')
const WeeklyPlayerStat = this.models.get('WeeklyPlayerStat')
const start_week = 1
const end_week = 17
// Clear existing data
await WeeklyPlayerStat.deleteMany()
// Populate the weekly player stats for all weeks in the range
for ( let week = start_week; week <= end_week; week += 1 ) {
this.output.info(`Building weekly player stats for week ${week}...`)
const player_stats = await this.sports_data.get_week_player_stats(week)
this.output.info(` - processing ${player_stats.length} stats`)
for ( const stat of player_stats ) {
const player = await Player.findOne({
'patch_data.player_id': stat.PlayerID,
})
if ( player ) {
const weekly_stat = new WeeklyPlayerStat({
player_id: player.id,
patch_player_id: stat.PlayerID,
week_num: week,
fantasy_points: stat.FantasyPoints,
})
await weekly_stat.save()
} else {
this.output.warn(` - Player ID ${stat.PlayerID} does not exist.`)
}
}
this.output.success(` - complete`)
}
this.output.success('Complete!')
}
}
module.exports = exports = SeedWeeklyPlayerDataPatch

View File

@ -0,0 +1,18 @@
const { Model } = require('flitter-orm')
class Matchup extends Model {
static get services() {
return [...super.services, 'models']
}
static get schema() {
return {
home_team_id: String,
visitor_team_id: String,
week_num: Number,
complete: { type: Boolean, default: false },
}
}
}
module.exports = exports = Matchup

View File

@ -0,0 +1,18 @@
const { Model } = require('flitter-orm')
class WeeklyPlayerStat extends Model {
static get services() {
return [...super.services, 'models']
}
static get schema() {
return {
player_id: String,
week_num: Number,
patch_player_id: String,
fantasy_points: Number,
}
}
}
module.exports = exports = WeeklyPlayerStat

View File

@ -0,0 +1,19 @@
const { Model } = require('flitter-orm')
class WeeklyTeamStat extends Model {
static get services() {
return [...super.services, 'models']
}
static get schema() {
return {
team_id: String,
lineup_id: String,
week_num: Number,
player_ids: [String],
fantasy_points: Number,
}
}
}
module.exports = exports = WeeklyTeamStat

View File

@ -6,7 +6,17 @@ const axios = require('axios').default;
*/ */
class SportsDataService extends Service { class SportsDataService extends Service {
static get services() { static get services() {
return [...super.services, 'configs'] return [...super.services, 'configs', 'models', 'utility']
}
async is_draft_stage() {
const Setting = this.models.get('models::setting')
return !!this.utility.infer(await Setting.get('in_draft_stage'))
}
async current_play_week() {
const Setting = this.models.get('models::setting')
return !!this.utility.infer(await Setting.get('current_week'))
} }
async get_team_players(team_key) { async get_team_players(team_key) {
@ -17,14 +27,18 @@ class SportsDataService extends Service {
return this.get_request('Teams') return this.get_request('Teams')
} }
async get_request(path) { async get_request(path, base = 'scores') {
const response = await axios.get(this.url(path)) const response = await axios.get(this.url(path, base))
return response.data return response.data
} }
url(path) { async get_week_player_stats(week_num) {
return this.get_request(`PlayerGameProjectionStatsByWeek/${this.configs.get('server.sports_data.season')}/${week_num}`, 'projections')
}
url(path, base = 'scores') {
if ( path.startsWith('/') ) path = path.slice(1) if ( path.startsWith('/') ) path = path.slice(1)
return `https://api.sportsdata.io/v3/nfl/scores/json/${path}?key=${this.configs.get('server.sports_data.api_key')}` return `https://api.sportsdata.io/v3/nfl/${base}/json/${path}?key=${this.configs.get('server.sports_data.api_key')}`
} }
} }

View File

@ -22,6 +22,7 @@ const server_config = {
sports_data: { sports_data: {
api_key: env('SPORTSDATA_API_KEY'), api_key: env('SPORTSDATA_API_KEY'),
season: env('SPORTSDATA_SEASON', '2020REG'),
}, },
logging: { logging: {

15
config/settings.config.js Normal file
View File

@ -0,0 +1,15 @@
const settings_config = {
default_settings: [
{
key: 'in_draft_stage',
value: true,
},
{
key: 'current_week',
value: 1,
},
],
}
module.exports = exports = settings_config