-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replace mlb odds with a single !odds which reports on all teams
- Loading branch information
Showing
4 changed files
with
129 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters