492 lines
18 KiB
Go
492 lines
18 KiB
Go
package result
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log/slog"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/config"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
|
|
)
|
|
|
|
type Service struct {
|
|
repo *repository.Store
|
|
config *config.Config
|
|
logger *slog.Logger
|
|
client *http.Client
|
|
betSvc bet.Service
|
|
}
|
|
|
|
func NewService(repo *repository.Store, cfg *config.Config, logger *slog.Logger, betSvc bet.Service) *Service {
|
|
return &Service{
|
|
repo: repo,
|
|
config: cfg,
|
|
logger: logger,
|
|
client: &http.Client{Timeout: 10 * time.Second},
|
|
betSvc: betSvc,
|
|
}
|
|
}
|
|
|
|
type ResultCheck struct {
|
|
}
|
|
|
|
func (s *Service) FetchAndProcessResults(ctx context.Context) error {
|
|
// TODO: Optimize this because there could be many bet outcomes for the same odd
|
|
// Take market id and match result as param and update all the bet outcomes at the same time
|
|
events, err := s.repo.GetExpiredUpcomingEvents(ctx)
|
|
if err != nil {
|
|
s.logger.Error("Failed to fetch events")
|
|
return err
|
|
}
|
|
fmt.Printf("Expired Events: %d \n", len(events))
|
|
|
|
for _, event := range events {
|
|
eventID, err := strconv.ParseInt(event.ID, 10, 64)
|
|
if err != nil {
|
|
s.logger.Error("Failed to parse event id")
|
|
return err
|
|
}
|
|
outcomes, err := s.repo.GetBetOutcomeByEventID(ctx, eventID)
|
|
if err != nil {
|
|
s.logger.Error("Failed to get pending bet outcomes", "error", err)
|
|
return err
|
|
}
|
|
|
|
for _, outcome := range outcomes {
|
|
if outcome.Expires.After(time.Now()) {
|
|
continue
|
|
}
|
|
|
|
sportID, err := strconv.ParseInt(event.SportID, 10, 64)
|
|
if err != nil {
|
|
s.logger.Error("Sport ID is invalid", "event_id", outcome.EventID, "error", err)
|
|
continue
|
|
}
|
|
result, err := s.fetchResult(ctx, outcome.EventID, outcome.OddID, outcome.MarketID, sportID, outcome)
|
|
if err != nil {
|
|
s.logger.Error("Failed to fetch result", "event_id", outcome.EventID, "error", err)
|
|
continue
|
|
}
|
|
|
|
// _, err = s.repo.CreateResult(ctx, domain.CreateResult{
|
|
// BetOutcomeID: outcome.ID,
|
|
// EventID: outcome.EventID,
|
|
// OddID: outcome.OddID,
|
|
// MarketID: outcome.MarketID,
|
|
// Status: result.Status,
|
|
// Score: result.Score,
|
|
// })
|
|
// if err != nil {
|
|
// s.logger.Error("Failed to store result", "bet_outcome_id", outcome.ID, "error", err)
|
|
// continue
|
|
// }
|
|
|
|
_, err = s.repo.UpdateBetOutcomeStatus(ctx, outcome.ID, result.Status)
|
|
if err != nil {
|
|
s.logger.Error("Failed to update bet outcome status", "bet_outcome_id", outcome.ID, "error", err)
|
|
continue
|
|
}
|
|
}
|
|
err = s.repo.DeleteEvent(ctx, event.ID)
|
|
if err != nil {
|
|
s.logger.Error("Failed to remove event", "event_id", event.ID, "error", err)
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// func (s *Service) FetchAndStoreResult(ctx context.Context, eventID string) error {
|
|
// url := fmt.Sprintf("https://api.b365api.com/v1/bet365/result?token=%s&event_id=%s", s.config.Bet365Token, eventID)
|
|
|
|
// res, err := s.client.Get(url)
|
|
// if err != nil {
|
|
// s.logger.Error("Failed to fetch result", "event_id", eventID, "error", err)
|
|
// return fmt.Errorf("failed to fetch result: %w", err)
|
|
// }
|
|
// defer res.Body.Close()
|
|
|
|
// if res.StatusCode != http.StatusOK {
|
|
// s.logger.Error("Unexpected status code", "event_id", eventID, "status_code", res.StatusCode)
|
|
// return fmt.Errorf("unexpected status code: %d", res.StatusCode)
|
|
// }
|
|
|
|
// var apiResp domain.BaseResultResponse
|
|
// if err := json.NewDecoder(res.Body).Decode(&apiResp); err != nil {
|
|
// s.logger.Error("Failed to decode result", "event_id", eventID, "error", err)
|
|
// return fmt.Errorf("failed to decode result: %w", err)
|
|
// }
|
|
|
|
// if apiResp.Success != 1 || len(apiResp.Results) == 0 {
|
|
// s.logger.Error("Invalid API response", "event_id", eventID)
|
|
// return fmt.Errorf("no result returned from API")
|
|
// }
|
|
|
|
// r := apiResp.Results[0]
|
|
// if r.TimeStatus != "3" {
|
|
// s.logger.Warn("Match not yet completed", "event_id", eventID)
|
|
// return fmt.Errorf("match not yet completed")
|
|
// }
|
|
|
|
// eventIDInt, err := strconv.ParseInt(eventID, 10, 64)
|
|
// if err != nil {
|
|
// s.logger.Error("Failed to parse event_id", "event_id", eventID, "error", err)
|
|
// return fmt.Errorf("failed to parse event_id: %w", err)
|
|
// }
|
|
|
|
// halfScore := ""
|
|
// if r.Scores.FirstHalf.Home != "" {
|
|
// halfScore = fmt.Sprintf("%s-%s", r.Scores.FirstHalf.Home, r.Scores.FirstHalf.Away)
|
|
// }
|
|
|
|
// result := domain.Result{
|
|
// EventID: eventIDInt,
|
|
// Status: domain.OUTCOME_STATUS_PENDING,
|
|
// Score: r.SS,
|
|
// FullTimeScore: r.SS,
|
|
// HalfTimeScore: halfScore,
|
|
// SS: r.SS,
|
|
// Scores: make(map[string]domain.Score),
|
|
// }
|
|
// for k, v := range map[string]domain.Score{
|
|
// "1": r.Scores.FirstHalf,
|
|
// "2": r.Scores.SecondHalf,
|
|
// } {
|
|
// result.Scores[k] = domain.Score{
|
|
// Home: v.Home,
|
|
// Away: v.Away,
|
|
// }
|
|
// }
|
|
|
|
// return s.repo.InsertResult(ctx, result)
|
|
// }
|
|
|
|
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)
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
|
if err != nil {
|
|
s.logger.Error("Failed to create request", "event_id", eventID, "error", err)
|
|
return domain.CreateResult{}, err
|
|
}
|
|
|
|
resp, err := s.client.Do(req)
|
|
if err != nil {
|
|
s.logger.Error("Failed to fetch result", "event_id", eventID, "error", err)
|
|
return domain.CreateResult{}, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
s.logger.Error("Unexpected status code", "event_id", eventID, "status_code", resp.StatusCode)
|
|
return domain.CreateResult{}, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
|
}
|
|
|
|
var resultResp domain.BaseResultResponse
|
|
if err := json.NewDecoder(resp.Body).Decode(&resultResp); err != nil {
|
|
s.logger.Error("Failed to decode result", "event_id", eventID, "error", err)
|
|
return domain.CreateResult{}, err
|
|
}
|
|
|
|
if resultResp.Success != 1 || len(resultResp.Results) == 0 {
|
|
s.logger.Error("Invalid API response", "event_id", eventID)
|
|
return domain.CreateResult{}, fmt.Errorf("invalid API response")
|
|
}
|
|
|
|
var result domain.CreateResult
|
|
switch sportID {
|
|
case domain.FOOTBALL:
|
|
result, err = s.parseFootball(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
|
if err != nil {
|
|
s.logger.Error("Failed to parse football", "event_id", eventID, "market_id", marketID, "error", err)
|
|
return domain.CreateResult{}, err
|
|
}
|
|
|
|
case domain.BASKETBALL:
|
|
result, err = s.parseBasketball(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
|
if err != nil {
|
|
s.logger.Error("Failed to parse basketball", "event_id", eventID, "market_id", marketID, "error", err)
|
|
return domain.CreateResult{}, err
|
|
}
|
|
case domain.ICE_HOCKEY:
|
|
result, err = s.parseIceHockey(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
|
if err != nil {
|
|
s.logger.Error("Failed to parse ice hockey", "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)
|
|
}
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
func (s *Service) parseFootball(resultRes json.RawMessage, eventID, oddID, marketID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
|
var fbResp domain.FootballResultResponse
|
|
if err := json.Unmarshal(resultRes, &fbResp); err != nil {
|
|
s.logger.Error("Failed to unmarshal football result", "event_id", eventID, "error", err)
|
|
return domain.CreateResult{}, err
|
|
}
|
|
result := fbResp
|
|
if result.TimeStatus != "3" {
|
|
s.logger.Warn("Match not yet completed", "event_id", eventID)
|
|
return domain.CreateResult{}, fmt.Errorf("match not yet completed")
|
|
}
|
|
|
|
finalScore := parseSS(result.SS)
|
|
firstHalfScore := parseSS(fmt.Sprintf("%s-%s", result.Scores.FirstHalf.Home, result.Scores.FirstHalf.Away))
|
|
|
|
corners := parseStats(result.Stats.Corners)
|
|
status, err := s.evaluateFootballOutcome(outcome, finalScore, firstHalfScore, corners, result.Events)
|
|
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,
|
|
Score: result.SS,
|
|
}, nil
|
|
|
|
}
|
|
|
|
func (s *Service) parseBasketball(response json.RawMessage, eventID, oddID, marketID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
|
var basketBallRes domain.BasketballResultResponse
|
|
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
|
|
}
|
|
if basketBallRes.TimeStatus != "3" {
|
|
s.logger.Warn("Match not yet completed", "event_id", eventID)
|
|
return domain.CreateResult{}, fmt.Errorf("match not yet completed")
|
|
}
|
|
|
|
status, err := s.evaluateBasketballOutcome(outcome, basketBallRes)
|
|
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,
|
|
Score: basketBallRes.SS,
|
|
}, nil
|
|
|
|
}
|
|
|
|
func (s *Service) parseIceHockey(response json.RawMessage, eventID, oddID, marketID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
|
var iceHockeyRes domain.IceHockeyResultResponse
|
|
if err := json.Unmarshal(response, &iceHockeyRes); err != nil {
|
|
s.logger.Error("Failed to unmarshal football result", "event_id", eventID, "error", err)
|
|
return domain.CreateResult{}, err
|
|
}
|
|
if iceHockeyRes.TimeStatus != "3" {
|
|
s.logger.Warn("Match not yet completed", "event_id", eventID)
|
|
return domain.CreateResult{}, fmt.Errorf("match not yet completed")
|
|
}
|
|
|
|
status, err := s.evaluateIceHockeyOutcome(outcome, iceHockeyRes)
|
|
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,
|
|
Score: iceHockeyRes.SS,
|
|
}, nil
|
|
|
|
}
|
|
|
|
func parseScore(home string, away string) struct{ Home, Away int } {
|
|
homeVal, _ := strconv.Atoi(strings.TrimSpace(home))
|
|
awaVal, _ := strconv.Atoi(strings.TrimSpace(away))
|
|
return struct{ Home, Away int }{Home: homeVal, Away: awaVal}
|
|
}
|
|
|
|
func parseSS(scoreStr string) struct{ Home, Away int } {
|
|
parts := strings.Split(scoreStr, "-")
|
|
if len(parts) != 2 {
|
|
return struct{ Home, Away int }{0, 0}
|
|
}
|
|
home, _ := strconv.Atoi(strings.TrimSpace(parts[0]))
|
|
away, _ := strconv.Atoi(strings.TrimSpace(parts[1]))
|
|
return struct{ Home, Away int }{Home: home, Away: away}
|
|
}
|
|
|
|
func parseStats(stats []string) struct{ Home, Away int } {
|
|
if len(stats) != 2 {
|
|
return struct{ Home, Away int }{0, 0}
|
|
}
|
|
home, _ := strconv.Atoi(stats[0])
|
|
away, _ := strconv.Atoi(stats[1])
|
|
return struct{ Home, Away int }{Home: home, Away: away}
|
|
}
|
|
|
|
// evaluateOutcome determines the outcome status based on market type and odd
|
|
func (s *Service) evaluateFootballOutcome(outcome domain.BetOutcome, finalScore, firstHalfScore struct{ Home, Away int }, corners struct{ Home, Away int }, events []map[string]string) (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)
|
|
}
|
|
|
|
switch outcome.MarketID {
|
|
case int64(domain.FOOTBALL_FULL_TIME_RESULT):
|
|
return evaluateFullTimeResult(outcome, finalScore)
|
|
case int64(domain.FOOTBALL_GOALS_OVER_UNDER):
|
|
return evaluateGoalsOverUnder(outcome, finalScore)
|
|
case int64(domain.FOOTBALL_CORRECT_SCORE):
|
|
return evaluateCorrectScore(outcome, finalScore)
|
|
case int64(domain.FOOTBALL_HALF_TIME_RESULT):
|
|
return evaluateHalfTimeResult(outcome, firstHalfScore)
|
|
case int64(domain.FOOTBALL_ASIAN_HANDICAP):
|
|
return evaluateAsianHandicap(outcome, finalScore)
|
|
case int64(domain.FOOTBALL_GOAL_LINE):
|
|
return evaluateGoalLine(outcome, finalScore)
|
|
case int64(domain.FOOTBALL_FIRST_HALF_ASIAN_HANDICAP):
|
|
return evaluateAsianHandicap(outcome, firstHalfScore)
|
|
case int64(domain.FOOTBALL_FIRST_HALF_GOAL_LINE):
|
|
return evaluateGoalLine(outcome, firstHalfScore)
|
|
case int64(domain.FOOTBALL_FIRST_TEAM_TO_SCORE):
|
|
return evaluateFirstTeamToScore(outcome, events)
|
|
case int64(domain.FOOTBALL_GOALS_ODD_EVEN):
|
|
return evaluateGoalsOddEven(outcome, finalScore)
|
|
case int64(domain.FOOTBALL_DOUBLE_CHANCE):
|
|
return evaluateDoubleChance(outcome, finalScore)
|
|
case int64(domain.FOOTBALL_DRAW_NO_BET):
|
|
return evaluateDrawNoBet(outcome, finalScore)
|
|
default:
|
|
s.logger.Warn("Market type not implemented", "market_name", outcome.MarketName)
|
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("market type not implemented: %s", outcome.MarketName)
|
|
}
|
|
}
|
|
|
|
func (s *Service) evaluateBasketballOutcome(outcome domain.BetOutcome, res domain.BasketballResultResponse) (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)
|
|
}
|
|
|
|
finalScore := parseSS(res.SS)
|
|
|
|
firstHalfScore := parseScore(res.Scores.FirstHalf.Home, res.Scores.FirstHalf.Away)
|
|
secondHalfScore := struct{ Home, Away int }{Home: finalScore.Home - firstHalfScore.Home, Away: finalScore.Away - firstHalfScore.Away}
|
|
|
|
firstQuarter := parseScore(res.Scores.FirstQuarter.Home, res.Scores.FirstQuarter.Away)
|
|
secondQuarter := parseScore(res.Scores.SecondQuarter.Home, res.Scores.SecondQuarter.Away)
|
|
thirdQuarter := parseScore(res.Scores.ThirdQuarter.Home, res.Scores.ThirdQuarter.Away)
|
|
fourthQuarter := parseScore(res.Scores.FourthQuarter.Home, res.Scores.FourthQuarter.Away)
|
|
|
|
switch outcome.MarketID {
|
|
case int64(domain.BASKETBALL_GAME_LINES):
|
|
return evaluateGameLines(outcome, finalScore)
|
|
case int64(domain.BASKETBALL_RESULT_AND_BOTH_TEAMS_TO_SCORE_X_POINTS):
|
|
return evaluateResultAndBTTSX(outcome, finalScore)
|
|
case int64(domain.BASKETBALL_DOUBLE_RESULT):
|
|
return evaluateDoubleResult(outcome, firstHalfScore, secondHalfScore)
|
|
case int64(domain.BASKETBALL_MATCH_RESULT_AND_TOTAL):
|
|
return evaluateResultAndTotal(outcome, finalScore)
|
|
case int64(domain.BASKETBALL_MATCH_HANDICAP_AND_TOTAL):
|
|
return evaluateHandicapAndTotal(outcome, finalScore)
|
|
case int64(domain.BASKETBALL_GAME_TOTAL_ODD_EVEN):
|
|
return evaluateGoalsOddEven(outcome, finalScore)
|
|
case int64(domain.BASKETBALL_TEAM_TOTALS):
|
|
return evaluateGoalsOddEven(outcome, finalScore)
|
|
|
|
case int64(domain.BASKETBALL_FIRST_HALF):
|
|
return evaluateGameLines(outcome, firstHalfScore)
|
|
case int64(domain.BASKETBALL_FIRST_HALF_TEAM_TOTALS):
|
|
return evaluateTeamTotal(outcome, firstHalfScore)
|
|
case int64(domain.BASKETBALL_FIRST_HALF_HANDICAP_AND_TOTAL):
|
|
return evaluateHandicapAndTotal(outcome, firstHalfScore)
|
|
case int64(domain.BASKETBALL_FIRST_HALF_BOTH_TEAMS_TO_SCORE_X_POINTS):
|
|
return evaluateBTTSX(outcome, firstHalfScore)
|
|
case int64(domain.BASKETBALL_FIRST_HALF_DOUBLE_CHANCE):
|
|
return evaluateDoubleChance(outcome, firstHalfScore)
|
|
case int64(domain.BASKETBALL_FIRST_HALF_TOTAL_ODD_EVEN):
|
|
return evaluateGoalsOddEven(outcome, firstHalfScore)
|
|
case int64(domain.BASKETBALL_FIRST_HALF_MONEY_LINE_3_WAY):
|
|
return evaluateMoneyLine3Way(outcome, firstHalfScore)
|
|
case int64(domain.BASKETBALL_HIGHEST_SCORING_HALF):
|
|
return evaluateHighestScoringHalf(outcome, firstHalfScore, secondHalfScore)
|
|
|
|
case int64(domain.BASKETBALL_FIRST_QUARTER):
|
|
return evaluateGameLines(outcome, firstQuarter)
|
|
case int64(domain.BASKETBALL_FIRST_QUARTER_TEAM_TOTALS):
|
|
return evaluateTeamTotal(outcome, firstQuarter)
|
|
case int64(domain.BASKETBALL_FIRST_QUARTER_TOTAL_ODD_EVEN):
|
|
return evaluateGoalsOddEven(outcome, firstQuarter)
|
|
case int64(domain.BASKETBALL_FIRST_QUARTER_HANDICAP_AND_TOTAL):
|
|
return evaluateHandicapAndTotal(outcome, firstQuarter)
|
|
case int64(domain.BASKETBALL_FIRST_QUARTER_DOUBLE_CHANCE):
|
|
return evaluateDoubleChance(outcome, firstQuarter)
|
|
case int64(domain.BASKETBALL_HIGHEST_SCORING_QUARTER):
|
|
return evaluateHighestScoringQuarter(outcome, firstQuarter, secondQuarter, thirdQuarter, fourthQuarter)
|
|
|
|
default:
|
|
s.logger.Warn("Market type not implemented", "market_name", outcome.MarketName)
|
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("market type not implemented: %s", outcome.MarketName)
|
|
}
|
|
}
|
|
|
|
func (s *Service) evaluateIceHockeyOutcome(outcome domain.BetOutcome, res domain.IceHockeyResultResponse) (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)
|
|
}
|
|
finalScore := parseSS(res.SS)
|
|
firstPeriod := parseScore(res.Scores.FirstPeriod.Home, res.Scores.FirstPeriod.Away)
|
|
secondPeriod := parseScore(res.Scores.SecondPeriod.Home, res.Scores.SecondPeriod.Away)
|
|
thirdPeriod := parseScore(res.Scores.ThirdPeriod.Home, res.Scores.ThirdPeriod.Away)
|
|
|
|
regulation := []struct{ Home, Away int }{
|
|
firstPeriod,
|
|
secondPeriod,
|
|
thirdPeriod,
|
|
}
|
|
switch outcome.MarketID {
|
|
case int64(domain.ICE_HOCKEY_GAME_LINES):
|
|
return evaluateGameLines(outcome, finalScore)
|
|
case int64(domain.ICE_HOCKEY_THREE_WAY):
|
|
return evaluateGameLines(outcome, finalScore)
|
|
case int64(domain.ICE_HOCKEY_FIRST_PERIOD):
|
|
return evaluateGameLines(outcome, firstPeriod)
|
|
case int64(domain.ICE_HOCKEY_DRAW_NO_BET):
|
|
return evaluateDrawNoBet(outcome, finalScore)
|
|
case int64(domain.ICE_HOCKEY_DOUBLE_CHANCE):
|
|
return evaluateDoubleChance(outcome, finalScore)
|
|
case int64(domain.ICE_HOCKEY_WINNING_MARGIN):
|
|
return evaluateWinningMargin(outcome, finalScore)
|
|
case int64(domain.ICE_HOCKEY_HIGHEST_SCORING_PERIOD):
|
|
return evaluateHighestScoringPeriod(outcome, firstPeriod, secondPeriod, thirdPeriod)
|
|
case int64(domain.ICE_HOCKEY_TIED_AFTER_REGULATION):
|
|
return evaluateTiedAfterRegulation(outcome, regulation)
|
|
case int64(domain.ICE_HOCKEY_GAME_TOTAL_ODD_EVEN):
|
|
return evaluateGoalsOddEven(outcome, finalScore)
|
|
}
|
|
|
|
return domain.OUTCOME_STATUS_PENDING, nil
|
|
}
|