cricket support
This commit is contained in:
parent
252bf04b1e
commit
7e1a126ead
|
|
@ -175,6 +175,41 @@ type IceHockeyResultResponse struct {
|
|||
Bet365ID string `json:"bet365_id"`
|
||||
}
|
||||
|
||||
type CricketResultResponse struct {
|
||||
ID string `json:"id"`
|
||||
SportID string `json:"sport_id"`
|
||||
Time string `json:"time"`
|
||||
TimeStatus string `json:"time_status"`
|
||||
League struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
CC string `json:"cc"`
|
||||
} `json:"league"`
|
||||
Home struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
ImageID string `json:"image_id"`
|
||||
CC string `json:"cc"`
|
||||
} `json:"home"`
|
||||
Away struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
ImageID string `json:"image_id"`
|
||||
CC string `json:"cc"`
|
||||
} `json:"away"`
|
||||
SS string `json:"ss"`
|
||||
Extra struct {
|
||||
HomePos string `json:"home_pos"`
|
||||
AwayPos string `json:"away_pos"`
|
||||
NumberOfPeriods string `json:"numberofperiods"`
|
||||
PeriodLength string `json:"periodlength"`
|
||||
StadiumData map[string]string `json:"stadium_data"`
|
||||
} `json:"extra"`
|
||||
HasLineup int `json:"has_lineup"`
|
||||
ConfirmedAt string `json:"confirmed_at"`
|
||||
Bet365ID string `json:"bet365_id"`
|
||||
}
|
||||
|
||||
type Score struct {
|
||||
Home string `json:"home"`
|
||||
Away string `json:"away"`
|
||||
|
|
|
|||
|
|
@ -91,6 +91,29 @@ const (
|
|||
ICE_HOCKEY_ALTERNATIVE_TOTAL_TWO_WAY IceHockeyMarket = 170240
|
||||
)
|
||||
|
||||
type CricketMarket int64
|
||||
|
||||
const (
|
||||
// Main
|
||||
CRICKET_TO_WIN_THE_MATCH CricketMarket = 1246
|
||||
CRICKET_TEAM_TOP_BATTER CricketMarket = 1241
|
||||
CRICKET_TEAM_TOP_BOWLE CricketMarket = 1242
|
||||
CRICKET_PLAYER_OF_THE_MATCH CricketMarket = 346
|
||||
CRICKET_FIRST_WICKET_METHOD CricketMarket = 30205
|
||||
|
||||
// First Over
|
||||
CRICKET_FIRST_OVER_TOTAL_RUNS CricketMarket = 300336
|
||||
CRICKET_FIRST_OVER_TOTAL_RUNS_Odd_Even CricketMarket = 300118
|
||||
|
||||
// Inninigs 1
|
||||
CRICKET_FIRST_INNINIGS_SCORE CricketMarket = 300338
|
||||
CRICKET_INNINGS_OF_MATCH_BOWLED_OUT CricketMarket = 300108
|
||||
|
||||
// Match
|
||||
CRICKET_TOP_MATCH_BATTER CricketMarket = 30245
|
||||
CRICKET_TOP_MATCH_BOWLER CricketMarket = 30246
|
||||
)
|
||||
|
||||
// TODO: Move this into the database so that it can be modified dynamically
|
||||
|
||||
var SupportedMarkets = map[int64]bool{
|
||||
|
|
@ -164,4 +187,18 @@ var SupportedMarkets = map[int64]bool{
|
|||
|
||||
int64(ICE_HOCKEY_ALTERNATIVE_PUCK_LINE_TWO_WAY): false,
|
||||
int64(ICE_HOCKEY_ALTERNATIVE_TOTAL_TWO_WAY): false,
|
||||
|
||||
// Cricket Markets
|
||||
int64(CRICKET_TO_WIN_THE_MATCH): true,
|
||||
int64(CRICKET_FIRST_OVER_TOTAL_RUNS_Odd_Even): true,
|
||||
int64(CRICKET_FIRST_INNINIGS_SCORE): true,
|
||||
|
||||
int64(CRICKET_INNINGS_OF_MATCH_BOWLED_OUT): false,
|
||||
int64(CRICKET_FIRST_OVER_TOTAL_RUNS): false,
|
||||
int64(CRICKET_TEAM_TOP_BATTER): false,
|
||||
int64(CRICKET_TEAM_TOP_BOWLE): false,
|
||||
int64(CRICKET_PLAYER_OF_THE_MATCH): false,
|
||||
int64(CRICKET_FIRST_WICKET_METHOD): false,
|
||||
int64(CRICKET_TOP_MATCH_BATTER): false,
|
||||
int64(CRICKET_TOP_MATCH_BOWLER): false,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -709,3 +709,46 @@ func evaluateTiedAfterRegulation(outcome domain.BetOutcome, scores []struct{ Hom
|
|||
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
||||
}
|
||||
|
||||
// Cricket evalations
|
||||
func evaluateInningScore(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||
var inningsScore int
|
||||
if outcome.OddName == "1" {
|
||||
inningsScore = score.Home
|
||||
} else if outcome.OddName == "2" {
|
||||
inningsScore = score.Away
|
||||
} else {
|
||||
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid odd header: %s", outcome.OddHeader)
|
||||
}
|
||||
|
||||
parts := strings.Fields(outcome.OddHeader)
|
||||
if len(parts) != 2 {
|
||||
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid odd format: %s", outcome.OddHeader)
|
||||
}
|
||||
|
||||
evalType := parts[0]
|
||||
|
||||
threshold, err := strconv.ParseFloat(parts[1], 64)
|
||||
if err != nil {
|
||||
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid threshold value: %s", parts[1])
|
||||
}
|
||||
|
||||
switch evalType {
|
||||
case "Over":
|
||||
if float64(inningsScore) > threshold {
|
||||
return domain.OUTCOME_STATUS_WIN, nil
|
||||
}
|
||||
return domain.OUTCOME_STATUS_LOSS, nil
|
||||
case "Under":
|
||||
if float64(inningsScore) < threshold {
|
||||
return domain.OUTCOME_STATUS_WIN, nil
|
||||
}
|
||||
return domain.OUTCOME_STATUS_LOSS, nil
|
||||
case "Exactly":
|
||||
if float64(inningsScore) == threshold {
|
||||
return domain.OUTCOME_STATUS_WIN, nil
|
||||
}
|
||||
return domain.OUTCOME_STATUS_LOSS, nil
|
||||
default:
|
||||
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid comparison operator: %s", evalType)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,8 @@ func (s *Service) FetchAndProcessResults(ctx context.Context) error {
|
|||
// }
|
||||
|
||||
func (s *Service) fetchResult(ctx context.Context, eventID, oddID, marketID, sportID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
||||
url := fmt.Sprintf("https://api.b365api.com/v1/bet365/result?token=%s&event_id=%d", s.config.Bet365Token, eventID)
|
||||
// url := fmt.Sprintf("https://api.b365api.com/v1/bet365/result?token=%s&event_id=%d", s.config.Bet365Token, eventID)
|
||||
url := fmt.Sprintf("https://api.b365api.com/v1/event/view?token=%s&event_id=%d", s.config.Bet365Token, eventID)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to create request", "event_id", eventID, "error", err)
|
||||
|
|
@ -219,6 +220,12 @@ func (s *Service) fetchResult(ctx context.Context, eventID, oddID, marketID, spo
|
|||
s.logger.Error("Failed to parse ice hockey", "event id", eventID, "market_id", marketID, "error", err)
|
||||
return domain.CreateResult{}, err
|
||||
}
|
||||
case domain.CRICKET:
|
||||
result, err = s.parseCricket(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to parse cricket", "event id", eventID, "market_id", marketID, "error", err)
|
||||
return domain.CreateResult{}, err
|
||||
}
|
||||
default:
|
||||
s.logger.Error("Unsupported sport", "sport", sportID)
|
||||
return domain.CreateResult{}, fmt.Errorf("unsupported sport: %v", sportID)
|
||||
|
|
@ -263,6 +270,10 @@ func (s *Service) parseFootball(resultRes json.RawMessage, eventID, oddID, marke
|
|||
|
||||
func (s *Service) parseBasketball(response json.RawMessage, eventID, oddID, marketID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
||||
var basketBallRes domain.BasketballResultResponse
|
||||
|
||||
// TODO: here !!
|
||||
fmt.Println(string(response))
|
||||
|
||||
if err := json.Unmarshal(response, &basketBallRes); err != nil {
|
||||
s.logger.Error("Failed to unmarshal football result", "event_id", eventID, "error", err)
|
||||
return domain.CreateResult{}, err
|
||||
|
|
@ -317,6 +328,33 @@ func (s *Service) parseIceHockey(response json.RawMessage, eventID, oddID, marke
|
|||
|
||||
}
|
||||
|
||||
func (s *Service) parseCricket(response json.RawMessage, eventID, oddID, marketID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
||||
var cricketRes domain.CricketResultResponse
|
||||
|
||||
if err := json.Unmarshal(response, &cricketRes); err != nil {
|
||||
s.logger.Error("Failed to unmarshal football result", "event_id", eventID, "error", err)
|
||||
return domain.CreateResult{}, err
|
||||
}
|
||||
if cricketRes.TimeStatus != "3" {
|
||||
s.logger.Warn("Match not yet completed", "event_id", eventID)
|
||||
return domain.CreateResult{}, fmt.Errorf("match not yet completed")
|
||||
}
|
||||
|
||||
status, err := s.evaluateCricketOutcome(outcome, cricketRes)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", err)
|
||||
return domain.CreateResult{}, err
|
||||
}
|
||||
|
||||
return domain.CreateResult{
|
||||
BetOutcomeID: 0,
|
||||
EventID: eventID,
|
||||
OddID: oddID,
|
||||
MarketID: marketID,
|
||||
Status: status,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseScore(home string, away string) struct{ Home, Away int } {
|
||||
homeVal, _ := strconv.Atoi(strings.TrimSpace(home))
|
||||
awaVal, _ := strconv.Atoi(strings.TrimSpace(away))
|
||||
|
|
@ -487,3 +525,23 @@ func (s *Service) evaluateIceHockeyOutcome(outcome domain.BetOutcome, res domain
|
|||
|
||||
return domain.OUTCOME_STATUS_PENDING, nil
|
||||
}
|
||||
|
||||
func (s *Service) evaluateCricketOutcome(outcome domain.BetOutcome, res domain.CricketResultResponse) (domain.OutcomeStatus, error) {
|
||||
if !domain.SupportedMarkets[outcome.MarketID] {
|
||||
s.logger.Warn("Unsupported market type", "market_name", outcome.MarketName)
|
||||
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported market type: %s", outcome.MarketName)
|
||||
}
|
||||
|
||||
score := parseSS(res.SS)
|
||||
|
||||
switch outcome.MarketID {
|
||||
case int64(domain.CRICKET_TO_WIN_THE_MATCH):
|
||||
return evaluateFullTimeResult(outcome, score)
|
||||
case int64(domain.CRICKET_FIRST_OVER_TOTAL_RUNS_Odd_Even):
|
||||
return evaluateGoalsOddEven(outcome, score)
|
||||
case int64(domain.CRICKET_FIRST_INNINIGS_SCORE):
|
||||
return evaluateInningScore(outcome, score)
|
||||
}
|
||||
|
||||
return domain.OUTCOME_STATUS_PENDING, nil
|
||||
}
|
||||
|
|
|
|||
5
makefile
5
makefile
|
|
@ -27,6 +27,11 @@ migrations/up:
|
|||
@echo 'Running up migrations...'
|
||||
@migrate -path ./db/migrations -database $(DB_URL) up
|
||||
|
||||
.PHONY: postgres
|
||||
postgres:
|
||||
@echo 'Running postgres db...'
|
||||
docker compose -f compose.db.yaml exec postgres psql -U root -d gh
|
||||
|
||||
.PHONY: swagger
|
||||
swagger:
|
||||
@swag init -g cmd/main.go
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user