Skip to content

Commit

Permalink
Replace mlb odds with a single !odds which reports on all teams
Browse files Browse the repository at this point in the history
  • Loading branch information
rcy committed Sep 10, 2023
1 parent 338ac40 commit 276e012
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 27 deletions.
39 changes: 39 additions & 0 deletions fetch/fetch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package fetch

import (
"io"
"log"
"net/http"
"time"
)

type record struct {
StatusCode int
Body []byte
Time time.Time
}

var cache = make(map[string]record)

// Fetch url returning cached data if it exists and is not older than maxAge
func Get(url string, maxAge time.Duration) (int, []byte, error) {
rec, ok := cache[url]
if ok && time.Since(rec.Time) < maxAge {
log.Printf("cache hit")
return rec.StatusCode, rec.Body, nil
}

resp, err := http.Get(url)
if err != nil {
return 0, nil, err
}

body, err := io.ReadAll(resp.Body)
if err != nil {
return 0, nil, err
}

cache[url] = record{resp.StatusCode, body, time.Now()}

return resp.StatusCode, body, nil
}
87 changes: 62 additions & 25 deletions handlers/mlb/mlb.go
Original file line number Diff line number Diff line change
@@ -1,55 +1,92 @@
package mlb

import (
"encoding/json"
"fmt"
"goirc/bot"
"goirc/shell"
"goirc/fetch"
"sort"
"strconv"
"strings"
"time"
)

func SingleTeamOdds(params bot.HandlerParams) error {
team := strings.ToUpper(params.Matches[1])
type TeamEndData struct {
PoffTitle float64
}

type Team struct {
TeamID int `json:"teamId"`
AbbName string
League string
Division string
EndData TeamEndData
}

type TeamList []Team

func (tl TeamList) String() string {
arr := []string{}
for i, team := range tl {
arr = append(arr, fmt.Sprintf("%s:%.0f%%", team.AbbName, 100*team.EndData.PoffTitle))
if i == 5 { // top 6 teams make the playoffs in each league
arr = append(arr, "|")
}
}
return strings.Join(arr, " ")
}

func fetchTeams() (TeamList, error) {
date := time.Now().Format(time.DateOnly)

r, err := shell.Command(fmt.Sprintf(`
curl -s 'https://www.fangraphs.com/api/playoff-odds/odds?dateEnd=%s&dateDelta=&projectionMode=2&standingsType=div' |\
jq .[] |\
jq 'select(.abbName == "%s")'.endData.poffTitle
`, date, team))
url := fmt.Sprintf("https://www.fangraphs.com/api/playoff-odds/odds?dateEnd=%s&dateDelta=&projectionMode=2&standingsType=lg", date)

_, bytes, err := fetch.Get(url, time.Minute)
if err != nil {
return err
return nil, err
}

f, err := strconv.ParseFloat(strings.TrimSpace(r), 32)
var teams TeamList
err = json.Unmarshal(bytes, &teams)
if err != nil {
return err
return nil, err
}

params.Privmsgf(params.Target, "FanGraphs projects %s to have a %.3f%% chance of making the playoffs", team, f*100)
sort.Slice(teams, func(i, j int) bool {
return teams[i].EndData.PoffTitle > teams[j].EndData.PoffTitle
})

return nil
return teams, nil
}

func Teams(params bot.HandlerParams) error {
date := time.Now().Format(time.DateOnly)
func fetchLeagueTeams(league string) (TeamList, error) {
teams, err := fetchTeams()
if err != nil {
return nil, err
}

var lt TeamList

for _, t := range teams {
if t.League == league {
lt = append(lt, t)
}
}

return lt, nil
}

r, err := shell.Command(fmt.Sprintf(`
curl -s 'https://www.fangraphs.com/api/playoff-odds/odds?dateEnd=%s&dateDelta=&projectionMode=2&standingsType=div' | jq -r .[].abbName
`, date))
func PlayoffOdds(params bot.HandlerParams) error {
teams, err := fetchLeagueTeams("AL")
if err != nil {
return err
}
params.Privmsgf(params.Target, "AL %s", teams.String())

teams := strings.Split(r, "\n")
sort.Slice(teams, func(i, j int) bool {
return teams[i] < teams[j]
})

params.Privmsgf(params.Target, "Teams: %s", strings.Join(teams, " "))
teams, err = fetchLeagueTeams("NL")
if err != nil {
return err
}
params.Privmsgf(params.Target, "NL %s", teams.String())

return nil
}
27 changes: 27 additions & 0 deletions handlers/mlb/mlb_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package mlb

import (
"testing"
)

func TestFetchTeams(t *testing.T) {
teams, err := fetchTeams()
if err != nil {
t.Error(err)
}
t.Log(teams)
}

func TestFetchLeagueTeams(t *testing.T) {
for _, league := range []string{"AL", "NL"} {
t.Run(league, func(t *testing.T) {
teams, err := fetchLeagueTeams(league)
if err != nil {
t.Error(err)
}
if len(teams) != 15 {
t.Errorf("expected 15 teams, got %d", len(teams))
}
})
}
}
3 changes: 1 addition & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ func main() {
b.Handle(`(https?://\S+)`, handlers.Link)
b.Handle(`^!day`, handlers.NationalDay)
b.Handle(`\b69\b`, handlers.Nice)
b.Handle(`^mlb odds (...)?$`, mlb.SingleTeamOdds)
b.Handle(`^mlb teams$`, mlb.Teams)
b.Handle(`^!odds`, mlb.PlayoffOdds)
b.Handle(`^!pom`, handlers.POM)
b.Handle(`^("[^"]+)$`, handlers.Quote)
b.Handle(`^!remindme ([^\s]+) (.+)$`, handlers.RemindMe)
Expand Down

0 comments on commit 276e012

Please sign in to comment.