// ListTeamsForSeason is a http handler that returns a brief summary // of all of the NBA games for the given season. func (s *Server) ListGamesForSeason(ctx context.Context, rw http.ResponseWriter, req *http.Request, ps parameterSet) (interface{}, error) { var season data.Season err := season.UnmarshalText([]byte(ps["season"])) if err != nil { return nil, ErrBadRequest("Invalid season identifier") } const q = ` SELECT games.id, home_team_id, visitor_team_id, status, time, length_minutes FROM games WHERE season = ? ORDER BY time DESC, status ASC, length_minutes ASC ` var games []*gameSummary err = s.db.DB.Select(&games, q, season.String()) if err != nil { return nil, err } for _, g := range games { g.HomeTeam = teamSummaryFromData(s.teams.ByID(g.HomeTeamID)) g.VisitorTeam = teamSummaryFromData(s.teams.ByID(g.VisitorTeamID)) } return games, nil }
// ListPlayersForSeason is a http handler that returns a list of all the // players active during the given season. func (s *Server) RetrievePlayerForSeason(ctx context.Context, rw http.ResponseWriter, req *http.Request, ps parameterSet) (interface{}, error) { var ( season data.Season playerID int ) err := season.UnmarshalText([]byte(ps["season"])) if err != nil { return nil, ErrBadRequest("Invalid season identifier") } playerID, err = ps.Int("playerID") if err != nil { return nil, ErrBadRequest("Bad player identifier") } var player data.PlayerDetails err = s.db.DB.Get(&player, playerID) if err == sql.ErrNoRows { return nil, ErrNotFound("Player not found") } if err != nil { return nil, err } resp := struct { Player data.PlayerDetails `json:"player"` GamesPlayed []*playerStatLine `json:"games_played"` }{ Player: player, GamesPlayed: []*playerStatLine{}, } // Pull in their games too. const q = ` SELECT player_game_stats.team_id, player_game_stats.game_id, stats.*, games.home_team_id, games.visitor_team_id, games.time FROM player_game_stats INNER JOIN stats ON player_game_stats.stats_id = stats.id INNER JOIN games ON player_game_stats.game_id = games.id WHERE games.season = ? AND player_game_stats.player_id = ? ORDER BY games.time DESC ` err = s.db.DB.Select(&resp.GamesPlayed, q, season.String(), playerID) if err != nil { return nil, err } for _, gp := range resp.GamesPlayed { if gp.TeamID == gp.HomeTeamID { gp.HomeOrAway = data.Home } else { gp.HomeOrAway = data.Away } // Calculate percentages, and other derived statistics that aren't // actually stored in the nbagame db because they're redundant. gp.Stats.Calculate() } return resp, nil }
// ListPlayersForSeason is a http handler that returns a list of all the // players active during the given season. // TODO(jackson): This endpoint isn't strictly correct, because if players // take a year off, we'll incorrectly include them in that year. func (s *Server) ListPlayersForSeason(ctx context.Context, rw http.ResponseWriter, req *http.Request, ps parameterSet) (interface{}, error) { var season data.Season err := season.UnmarshalText([]byte(ps["season"])) if err != nil { return nil, ErrBadRequest("Invalid season identifier") } const q = ` SELECT * FROM players WHERE NOT dleague AND career_start <= ? AND career_end >= ? ORDER BY last_name, first_name ASC ` var players []*data.PlayerDetails err = s.db.DB.Select(&players, q, season.SpringYear(), season.FallYear()) if err != nil { return nil, err } return players, nil }
// RetrieveGameForSeason is a http handler that returns a full synopsis // of a particular game. func (s *Server) RetrieveGameForSeason(ctx context.Context, rw http.ResponseWriter, req *http.Request, ps parameterSet) (interface{}, error) { var season data.Season err := season.UnmarshalText([]byte(ps["season"])) if err != nil { return nil, ErrBadRequest("Invalid season identifier") } var details data.GameDetails err = s.db.DB.Get(&details, ps.String("gameID")) if err == sql.ErrNoRows { return nil, ErrNotFound("No such game exists") } if err != nil { return nil, err } g := &game{ ID: details.ID.String(), Date: details.Date, Status: details.Status, HomeTeam: teamGamePerformance{ teamSummary: *teamSummaryFromData(s.teams.ByID(details.HomeTeamID)), }, VisitorTeam: teamGamePerformance{ teamSummary: *teamSummaryFromData(s.teams.ByID(details.VisitorTeamID)), }, Minutes: details.LengthMinutes, Attendance: details.Attendance, LeadChanges: details.LeadChanges, TimesTied: details.TimesTied, } // Pull in data about the refs that officiated the game. const officialsQ = ` SELECT o.id, o.first_name, o.last_name, o.jersey_number FROM officiated INNER JOIN officials o ON officiated.official_id = o.id WHERE officiated.game_id = ? ORDER BY o.last_name, o.first_name ASC ` err = s.db.DB.Select(&g.Officials, officialsQ, g.ID) if err != nil { return nil, err } // Pull in aggregated stat lines for each team. const teamStatsQ = ` SELECT team_game_stats.team_id, stats.* FROM team_game_stats INNER JOIN stats ON team_game_stats.stats_id = stats.id WHERE team_game_stats.game_id = ? ` var teamStats []*struct { data.Stats TeamID int `db:"team_id"` } err = s.db.DB.Select(&teamStats, teamStatsQ, g.ID) if err != nil { return nil, err } for _, ts := range teamStats { ts.Stats.Calculate() if ts.TeamID == g.HomeTeam.ID { g.HomeTeam.Stats = &ts.Stats } if ts.TeamID == g.VisitorTeam.ID { g.VisitorTeam.Stats = &ts.Stats } } // Pull in aggregated stat lines for each player. const playerStatsQ = ` SELECT stats.*, player_game_stats.team_id, player_game_stats.player_id, players.first_name, players.last_name FROM player_game_stats INNER JOIN stats ON player_game_stats.stats_id = stats.id INNER JOIN players ON players.id = player_game_stats.player_id WHERE player_game_stats.game_id = ? ORDER BY stats.points DESC ` var playerStats []*struct { TeamID int `db:"team_id"` PlayerID string `db:"player_id"` FirstName string `db:"first_name"` LastName string `db:"last_name"` data.Stats } err = s.db.DB.Select(&playerStats, playerStatsQ, g.ID) if err != nil { return nil, err } for _, ps := range playerStats { pgp := playerGamePerformance{ PlayerID: ps.PlayerID, FirstName: ps.FirstName, LastName: ps.LastName, Stats: ps.Stats, } if ps.TeamID == g.HomeTeam.ID { g.HomeTeam.Players = append(g.HomeTeam.Players, pgp) } if ps.TeamID == g.VisitorTeam.ID { g.VisitorTeam.Players = append(g.VisitorTeam.Players, pgp) } } return g, nil }