-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
classic league implementation is done
- Loading branch information
Showing
6 changed files
with
356 additions
and
34 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
This file was deleted.
Oops, something went wrong.
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
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 +1,141 @@ | ||
package endpoints | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
|
||
"github.com/AbdoAnss/go-fantasy-pl/api" | ||
"github.com/AbdoAnss/go-fantasy-pl/models" | ||
) | ||
|
||
const ( | ||
classicLeagueEndpoint = "/leagues-classic/%d/standings/?page_standings=%d" | ||
h2hLeagueEndpoint = "/leagues-h2h-matches/league/%d/" | ||
maxPageCache = 3 // Only cache first 3 pages | ||
) | ||
|
||
type LeagueService struct { | ||
client api.Client | ||
} | ||
|
||
func NewLeagueService(client api.Client) *LeagueService { | ||
return &LeagueService{ | ||
client: client, | ||
} | ||
} | ||
|
||
func (ls *LeagueService) GetClassicLeagueStandings(id, page int) (*models.ClassicLeague, error) { | ||
// Only cache first few pages to prevent memory bloat | ||
useCache := page <= maxPageCache | ||
|
||
if useCache { | ||
cacheKey := fmt.Sprintf("classic_league_%d_page_%d", id, page) | ||
if cached, found := sharedCache.Get(cacheKey); found { | ||
if league, ok := cached.(*models.ClassicLeague); ok { | ||
return league, nil | ||
} | ||
} | ||
} | ||
|
||
endpoint := fmt.Sprintf(classicLeagueEndpoint, id, page) | ||
resp, err := ls.client.Get(endpoint) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get league standings: %w", err) | ||
} | ||
defer resp.Body.Close() | ||
|
||
switch resp.StatusCode { | ||
case http.StatusOK: | ||
case http.StatusNotFound: | ||
return nil, fmt.Errorf("league with ID %d not found", id) | ||
default: | ||
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode) | ||
} | ||
|
||
body, err := io.ReadAll(resp.Body) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to read response body: %w", err) | ||
} | ||
|
||
var league models.ClassicLeague | ||
if err := json.Unmarshal(body, &league); err != nil { | ||
return nil, fmt.Errorf("failed to decode league data: %w", err) | ||
} | ||
|
||
if err := ls.validateLeague(&league); err != nil { | ||
return nil, err | ||
} | ||
|
||
if useCache { | ||
cacheKey := fmt.Sprintf("classic_league_%d_page_%d", id, page) | ||
sharedCache.Set(cacheKey, &league, leagueCacheTTL) | ||
} | ||
|
||
return &league, nil | ||
} | ||
|
||
/* | ||
func (ls *LeagueService) GetH2HLeague(id int) (*models.H2HLeague, error) { | ||
cacheKey := fmt.Sprintf("h2h_league_%d", id) | ||
if cached, found := sharedCache.Get(cacheKey); found { | ||
if league, ok := cached.(*models.H2HLeague); ok { | ||
return league, nil | ||
} | ||
} | ||
endpoint := fmt.Sprintf(h2hLeagueEndpoint, id) | ||
resp, err := ls.client.Get(endpoint) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get H2H league: %w", err) | ||
} | ||
defer resp.Body.Close() | ||
switch resp.StatusCode { | ||
case http.StatusOK: | ||
// Continue processing | ||
case http.StatusNotFound: | ||
return nil, fmt.Errorf("H2H league with ID %d not found", id) | ||
default: | ||
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode) | ||
} | ||
body, err := io.ReadAll(resp.Body) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to read response body: %w", err) | ||
} | ||
var league models.H2HLeague | ||
if err := json.Unmarshal(body, &league); err != nil { | ||
return nil, fmt.Errorf("failed to decode H2H league data: %w", err) | ||
} | ||
sharedCache.Set(cacheKey, &league, leagueCacheTTL) | ||
return &league, nil | ||
} | ||
*/ | ||
|
||
func (ls *LeagueService) validateLeague(league *models.ClassicLeague) error { | ||
if league == nil { | ||
return fmt.Errorf("received nil league data") | ||
} | ||
if league.League.ID == 0 { | ||
return fmt.Errorf("invalid league ID") | ||
} | ||
return nil | ||
} | ||
|
||
func (ls *LeagueService) GetTotalPages(league *models.ClassicLeague) int { | ||
if league == nil || len(league.Standings.Results) == 0 { | ||
return 0 | ||
} | ||
|
||
totalEntries := len(league.Standings.Results) | ||
if league.League.GetMaxEntries() > 0 { | ||
totalEntries = league.League.GetMaxEntries() | ||
} | ||
|
||
entriesPerPage := 50 // FPL default | ||
return (totalEntries + entriesPerPage - 1) / entriesPerPage | ||
} |
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,88 @@ | ||
package endpoints_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/AbdoAnss/go-fantasy-pl/client" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
var testLeagueClient *client.Client | ||
|
||
func init() { | ||
testLeagueClient = client.NewClient() | ||
} | ||
|
||
func TestLeagueEndpoints(t *testing.T) { | ||
t.Run("GetClassicLeague", func(t *testing.T) { | ||
// INPT Fantasy LeagueID | ||
leagueID := 1185652 | ||
page := 1 | ||
|
||
league, err := testLeagueClient.Leagues.GetClassicLeagueStandings(leagueID, page) | ||
assert.NoError(t, err, "expected no error when getting classic league") | ||
assert.NotNil(t, league, "expected league to be returned") | ||
|
||
// Log league details | ||
t.Logf("\nLeague Details:") | ||
t.Logf("League: %s", league.GetLeagueInfo()) | ||
t.Logf("Created: %s", league.League.GetCreationDate()) | ||
t.Logf("Type: %s", league.League.LeagueType) | ||
t.Logf("Last Updated: %s", league.GetUpdateTime()) | ||
t.Logf("Max Entries: %d", league.League.GetMaxEntries()) | ||
|
||
// Log standings | ||
t.Logf("\nTop 4 Managers:") | ||
for _, manager := range league.GetTopManagers(4) { | ||
t.Logf("%s", manager.GetManagerInfo()) | ||
t.Logf(" Points: %d (GW: %d)", manager.Total, manager.EventTotal) | ||
t.Logf(" Rank: %d %s", manager.Rank, manager.GetRankChangeString()) | ||
} | ||
|
||
// Log pagination | ||
t.Logf("\nPagination:") | ||
t.Logf("Current: %s", league.Standings.GetPageInfo()) | ||
t.Logf("Has Previous: %v", league.Standings.HasPreviousPage()) | ||
t.Logf("Has Next: %v", league.Standings.HasNext) | ||
}) | ||
|
||
t.Run("ValidateLeagueData", func(t *testing.T) { | ||
leagueID := 1185652 | ||
league, err := testLeagueClient.Leagues.GetClassicLeagueStandings(leagueID, 1) | ||
assert.NoError(t, err) | ||
|
||
// Validate league structure | ||
assert.Equal(t, leagueID, league.League.ID) | ||
assert.NotEmpty(t, league.League.Name) | ||
assert.NotZero(t, league.League.Created) | ||
|
||
// Validate standings | ||
topManagers := league.GetTopManagers(1) | ||
assert.NotEmpty(t, topManagers) | ||
assert.Greater(t, topManagers[0].Entry, 0) | ||
assert.NotEmpty(t, topManagers[0].GetManagerInfo()) | ||
assert.GreaterOrEqual(t, topManagers[0].Total, 0) | ||
}) | ||
|
||
t.Run("GetNonExistentLeague", func(t *testing.T) { | ||
league, err := testLeagueClient.Leagues.GetClassicLeagueStandings(99999999, 1) | ||
assert.Error(t, err) | ||
assert.Nil(t, league) | ||
assert.Contains(t, err.Error(), "not found") | ||
}) | ||
|
||
t.Run("CacheConsistency", func(t *testing.T) { | ||
leagueID := 1185652 | ||
|
||
league1, err := testLeagueClient.Leagues.GetClassicLeagueStandings(leagueID, 1) | ||
assert.NoError(t, err) | ||
|
||
league2, err := testLeagueClient.Leagues.GetClassicLeagueStandings(leagueID, 1) | ||
assert.NoError(t, err) | ||
|
||
assert.Equal(t, league1.GetLeagueInfo(), league2.GetLeagueInfo()) | ||
assert.Equal(t, | ||
league1.GetTopManagers(1)[0].GetManagerInfo(), | ||
league2.GetTopManagers(1)[0].GetManagerInfo()) | ||
}) | ||
} |
Oops, something went wrong.