-
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.
- Loading branch information
Showing
10 changed files
with
451 additions
and
17 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 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
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,153 @@ | ||
// Package endpoints provides access to the Fantasy Premier League API | ||
package endpoints | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
|
||
"github.com/AbdoAnss/go-fantasy-pl/api" | ||
"github.com/AbdoAnss/go-fantasy-pl/models" | ||
) | ||
|
||
const ( | ||
managerDetailsEndpoint = "/entry/%d/" | ||
managerHistoryEndpoint = "/entry/%d/history" | ||
managerGameWeekPicksEndpoint = "/entry/%d/event/%d/picks/" | ||
) | ||
|
||
type ManagerService struct { | ||
client api.Client | ||
bootstrapService *BootstrapService | ||
} | ||
|
||
func NewManagerService(client api.Client, bootstrap *BootstrapService) *ManagerService { | ||
return &ManagerService{ | ||
client: client, | ||
bootstrapService: bootstrap, | ||
} | ||
} | ||
|
||
func (ms *ManagerService) validateManager(manager *models.Manager) error { | ||
if manager == nil { | ||
return fmt.Errorf("received nil manager data") | ||
} | ||
if manager.ID == nil { | ||
return fmt.Errorf("manager ID is missing") | ||
} | ||
return nil | ||
} | ||
|
||
func (ms *ManagerService) GetManager(id int) (*models.Manager, error) { | ||
cacheKey := fmt.Sprintf("manager_%d", id) | ||
if cached, found := sharedCache.Get(cacheKey); found { | ||
if manager, ok := cached.(*models.Manager); ok { | ||
return manager, nil | ||
} | ||
} | ||
|
||
endpoint := fmt.Sprintf(managerDetailsEndpoint, id) | ||
resp, err := ms.client.Get(endpoint) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get manager data: %w", err) | ||
} | ||
defer resp.Body.Close() | ||
|
||
switch resp.StatusCode { | ||
case http.StatusOK: | ||
case http.StatusNotFound: | ||
return nil, fmt.Errorf("manager 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 manager models.Manager | ||
if err := json.Unmarshal(body, &manager); err != nil { | ||
return nil, fmt.Errorf("failed to decode manager data: %w", err) | ||
} | ||
|
||
if err := ms.validateManager(&manager); err != nil { | ||
return nil, err | ||
} | ||
|
||
sharedCache.Set(cacheKey, &manager, managerCacheTTL) | ||
|
||
return &manager, nil | ||
} | ||
|
||
func (ms *ManagerService) GetCurrentTeam(managerID int) (*models.ManagerTeam, error) { | ||
cacheKey := fmt.Sprintf("manager_team_%d", managerID) | ||
if cached, found := sharedCache.Get(cacheKey); found { | ||
if team, ok := cached.(*models.ManagerTeam); ok { | ||
return team, nil | ||
} | ||
} | ||
|
||
currentGameWeekID, err := ms.bootstrapService.GetCurrentGameWeek() | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get current game week: %w", err) | ||
} | ||
|
||
endpoint := fmt.Sprintf(managerGameWeekPicksEndpoint, managerID, currentGameWeekID) | ||
resp, err := ms.client.Get(endpoint) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get manager team: %w", err) | ||
} | ||
defer resp.Body.Close() | ||
|
||
if resp.StatusCode != http.StatusOK { | ||
return nil, fmt.Errorf("failed to get manager team: status %d", resp.StatusCode) | ||
} | ||
|
||
var team models.ManagerTeam | ||
if err := json.NewDecoder(resp.Body).Decode(&team); err != nil { | ||
return nil, fmt.Errorf("failed to decode manager team: %w", err) | ||
} | ||
|
||
sharedCache.Set(cacheKey, &team, managerCacheTTL) | ||
return &team, nil | ||
} | ||
|
||
func (ms *ManagerService) GetManagerHistory(id int) (*models.ManagerHistory, error) { | ||
cacheKey := fmt.Sprintf("manager_history_%d", id) | ||
if cached, found := sharedCache.Get(cacheKey); found { | ||
if ManagerHistory, ok := cached.(*models.ManagerHistory); ok { | ||
return ManagerHistory, nil | ||
} | ||
} | ||
|
||
endpoint := fmt.Sprintf(managerHistoryEndpoint, id) | ||
resp, err := ms.client.Get(endpoint) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get manager history data: %w", err) | ||
} | ||
defer resp.Body.Close() | ||
|
||
switch resp.StatusCode { | ||
case http.StatusOK: | ||
case http.StatusNotFound: | ||
return nil, fmt.Errorf("manager 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 managerHistory models.ManagerHistory | ||
if err := json.Unmarshal(body, &managerHistory); err != nil { | ||
return nil, fmt.Errorf("failed to decode manager data: %w", err) | ||
} | ||
|
||
sharedCache.Set(cacheKey, &managerHistory, managerCacheTTL) | ||
|
||
return &managerHistory, 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,121 @@ | ||
package endpoints_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/AbdoAnss/go-fantasy-pl/client" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
var testManagerClient *client.Client | ||
|
||
func init() { | ||
testManagerClient = client.NewClient() | ||
} | ||
|
||
func TestManagerEndpoints(t *testing.T) { | ||
t.Run("GetManager", func(t *testing.T) { | ||
// Using a known manager ID (you can replace with a valid one) | ||
managerID := 1387812 | ||
|
||
manager, err := testManagerClient.Managers.GetManager(managerID) | ||
assert.NoError(t, err, "expected no error when getting manager") | ||
assert.NotNil(t, manager, "expected manager to be returned") | ||
|
||
// Log manager details | ||
t.Logf("Manager Details:") | ||
t.Logf("ID: %d", *manager.ID) | ||
t.Logf("Name: %s", manager.GetFullName()) | ||
t.Logf("Team Name: %s", manager.Name) | ||
t.Logf("Overall Points: %d", manager.SummaryOverallPoints) | ||
t.Logf("Overall Rank: %d", manager.SummaryOverallRank) | ||
}) | ||
|
||
t.Run("GetNonExistentManager", func(t *testing.T) { | ||
manager, err := testManagerClient.Managers.GetManager(99999999) | ||
assert.Error(t, err, "expected error when getting non-existent manager") | ||
assert.Nil(t, manager, "expected nil manager for non-existent ID") | ||
assert.Contains(t, err.Error(), "not found", "expected 'not found' error message") | ||
}) | ||
|
||
t.Run("GetCurrentTeam", func(t *testing.T) { | ||
// Using same manager ID | ||
managerID := 1387812 | ||
|
||
team, err := testManagerClient.Managers.GetCurrentTeam(managerID) | ||
assert.NoError(t, err, "expected no error when getting current team") | ||
assert.NotNil(t, team, "expected team to be returned") | ||
|
||
// Log team details | ||
t.Logf("Current Team Details:") | ||
t.Logf("Number of Picks: %d", len(team.Picks)) | ||
|
||
// Log starting XI | ||
t.Log("Starting XI:") | ||
for _, pick := range team.GetStartingXI() { | ||
t.Logf("Position %d: Player ID %d (Captain: %v)", | ||
pick.Position, | ||
pick.Element, | ||
pick.IsCaptain) | ||
} | ||
|
||
// Log bench | ||
t.Log("Bench:") | ||
for _, pick := range team.GetBench() { | ||
t.Logf("Position %d: Player ID %d", | ||
pick.Position, | ||
pick.Element) | ||
} | ||
|
||
t.Logf("Team Value: £%.1fm", team.GetTeamValueInMillions()) | ||
t.Logf("Bank: £%.1fm", team.GetBankValueInMillions()) | ||
}) | ||
|
||
t.Run("GetManagerHistory", func(t *testing.T) { | ||
// Using same manager ID | ||
managerID := 1387812 | ||
|
||
history, err := testManagerClient.Managers.GetManagerHistory(managerID) | ||
assert.NoError(t, err, "expected no error when getting manager history") | ||
assert.NotNil(t, history, "expected history to be returned") | ||
|
||
// Log history details | ||
t.Logf("Manager History Details:") | ||
|
||
if len(history.Current) > 0 { | ||
t.Log("Current Season Performance:") | ||
for _, gw := range history.Current[:3] { // Show first 3 gameweeks | ||
t.Logf("GW%d: Points: %d, Overall Rank: %d", | ||
gw.Event, | ||
gw.Points, | ||
gw.OverallRank) | ||
} | ||
} | ||
|
||
if len(history.Past) > 0 { | ||
t.Log("Past Seasons:") | ||
for _, season := range history.Past { | ||
t.Logf("Season %s: Points: %d, Overall Rank: %d", | ||
season.SeasonName, | ||
season.TotalPoints, | ||
season.Rank) | ||
} | ||
} | ||
}) | ||
|
||
t.Run("CacheConsistency", func(t *testing.T) { | ||
managerID := 1387812 | ||
|
||
// First call | ||
manager1, err := testManagerClient.Managers.GetManager(managerID) | ||
assert.NoError(t, err) | ||
|
||
// Second call (should be from cache) | ||
manager2, err := testManagerClient.Managers.GetManager(managerID) | ||
assert.NoError(t, err) | ||
|
||
// Compare results | ||
assert.Equal(t, manager1.ID, manager2.ID, "cached manager should match original") | ||
assert.Equal(t, manager1.Name, manager2.Name, "cached manager name should match original") | ||
}) | ||
} |
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
Oops, something went wrong.