package daemon /* Футбольная стратегия. ТБ 0.5 в 1м тайме */ import ( "fmt" "gordenko.dev/dima/flashscore" "gordenko.dev/dima/onexbet" "gordenko.dev/dima/tipper/model" ) /* Алгоритм 3 ТБ 1.5 в Матче До матча: ТБ 2.5 (в матче) <=1.7 В 75% игр был гол КФ фаворита <=1.4 В Лайве: Сумма атак обычных и опасных >= 125 6 ударов в сторону ворот 4 удара в створ До 70 минуты */ type Over15 struct { id int64 notifyInTelegram bool isChampAccepted func(string) bool } func NewOver15(opt StrategyOptions) Over15 { if opt.ID == 0 { panic("StrategyID not defined") } s := Over15{} s.id = opt.ID s.notifyInTelegram = opt.NotifyInTelegram s.isChampAccepted = opt.IsChampAccepted return s } func (s Over15) ID() int64 { return s.id } func (s Over15) ShortName() string { return fmt.Sprintf("#%d FT Over 1.5", s.id) } func (s Over15) IsNotifyInTelegram() bool { return s.notifyInTelegram } func (s Over15) GetTelegramTipPattern() string { return `Сигнал # %d. Будет 2й ГОЛ! Алгоритм %d Тотал Больше 1.5 Футбол. %s. %s %s - %s Коэф. %.3f` } type isInterestingNotesOver15 struct { PriceOver25 float64 `json:"Over 2.5 price"` MatchesAnalysed int `json:"matchesAnalysed"` HasGoalInMatches int `json:"hasGoalInMatches"` GoalsPercent float64 `json:"goalsPercent"` FavoritePrice float64 `json:"favoritePrice"` } func (s Over15) IsInteresting(report *TeamMatch) (notes interface{}, _ bool) { var favoritePrice float64 = 2 for _, offer := range report.Odds.Winner { if offer.Home < favoritePrice && offer.Home > 1.01 { favoritePrice = offer.Home } if offer.Away < favoritePrice && offer.Away > 1.01 { favoritePrice = offer.Away } } if favoritePrice > 1.4 { return } var ( priceOver25 float64 foundPriceOver25 bool ) for _, total := range report.Odds.FullTimeTotal { if total.Total != "2.5" { continue } // 2.5 for _, offer := range total.Offers { if offer.Bookmaker == flashscore.Bookmaker1xBet { priceOver25 = offer.Over foundPriceOver25 = true break } } if foundPriceOver25 { break } else { // 1xBet не нашли // Берем первый коэф. if len(total.Offers) > 0 { priceOver25 = total.Offers[0].Over foundPriceOver25 = true } break } } if priceOver25 > 1.7 { return } var ( matchCount int hasGoalsInMatchCount int ) for _, match := range report.HomeTeamMatches { if match.HomeGoals > 0 || match.AwayGoals > 0 { hasGoalsInMatchCount++ } matchCount++ } for _, match := range report.AwayTeamMatches { if match.HomeGoals > 0 || match.AwayGoals > 0 { hasGoalsInMatchCount++ } matchCount++ } for _, match := range report.H2H { if match.HomeGoals > 0 || match.AwayGoals > 0 { hasGoalsInMatchCount++ } matchCount++ } if matchCount == 0 { return } // matchCount - 100% // goalsInMatchCount - x% goalsPercent := float64(hasGoalsInMatchCount*100) / float64(matchCount) if goalsPercent < 75 { return } obj := isInterestingNotesOver15{ PriceOver25: priceOver25, MatchesAnalysed: matchCount, HasGoalInMatches: hasGoalsInMatchCount, GoalsPercent: goalsPercent, FavoritePrice: favoritePrice, } //buf, _ := json.MarshalIndent(obj, "", " ") return obj, true } func (s Over15) GetTip(match *TeamMatch, upd onexbet.TeamLiveMatchData) (_ string, _ *BetDetails, _ TipCode) { if upd.CurrentTime == 0 { // ВАЖНО! // Матч еще не начался. Избегаем деления на 0 при вычислении attacksRatio return "матч не начался", nil, Waiting } // Прогнозы даем до 70 минуты включительно. maxTime := 70 * 60 if upd.CurrentTime > maxTime { return "70 минут уже отыграли", nil, Unwatch } goals := upd.HomeGoals + upd.AwayGoals if goals > 1 { // Если 2 гола уже забили - выходим return "уже забили более 1 гола", nil, Unwatch } if goals == 0 { return "счет 0:0", nil, Waiting } // Ищем тотал Больше 1.5 // Минимальный курс minPrice := 1.5 var ( minPriceCheckPassed bool currentPrice float64 ) for _, over := range upd.Total.Over { if over.Param == "1.5" { if over.Price < minPrice { return fmt.Sprintf("коэф. %.2f < %.2f", over.Price, minPrice), nil, Waiting } currentPrice = over.Price minPriceCheckPassed = true break } } if !minPriceCheckPassed { return "тотал 1.5 не найден", nil, Waiting } // attacks := upd.HomeAttacks + upd.AwayAttacks + upd.HomeDangerousAttacks + upd.AwayDangerousAttacks shotsOffTarget := upd.HomeShotsOffTarget + upd.AwayShotsOffTarget shotsOnTarget := upd.HomeShotsOnTarget + upd.AwayShotsOnTarget if attacks < 125 { return fmt.Sprintf("%d атак < 125", attacks), nil, Waiting } if shotsOffTarget < 6 { return fmt.Sprintf("%d shotsOffTarget < 6", shotsOffTarget), nil, Waiting } if shotsOnTarget < 4 { return fmt.Sprintf("%d shotsOnTarget < 4", shotsOnTarget), nil, Waiting } return "", &BetDetails{ Market: MarketTotal, Side: SideOver, Param: "1.5", Price: currentPrice, }, Bet } func (s Over15) GetResult(tip model.Tip, stats onexbet.TeamMatchResult) (_ *TipResult) { //buf, _ := json.MarshalIndent(stats, "", " ") //fmt.Printf("%s\n", buf) if stats.Status != onexbet.StatusMatchCompleted { return } res := new(TipResult) goals := stats.HomePoints + stats.AwayPoints if goals > 1 { res.Status = model.Won } else { res.Status = model.Lost } res.Result = fmt.Sprintf("счет: %d-%d", stats.HomePoints, stats.AwayPoints) return res }