Files
tipper/daemon/over05.go

251 lines
5.4 KiB
Go
Raw Permalink Normal View History

2026-07-21 05:29:37 +03:00
package daemon
/*
Футбольная стратегия.
ТБ 0.5 в 1м тайме
*/
import (
"fmt"
"gordenko.dev/dima/flashscore"
"gordenko.dev/dima/onexbet"
"gordenko.dev/dima/tipper/model"
)
/*
Алгоритм 2
ТБ 0.5 в Матче
До матча:
ТБ 2.5 (в матче) <=1.7
В 75% игр был гол
В Лайве:
Сумма атак обычных и опасных >= 135
6 ударов в сторону ворот OFF TARGET
4 удара в створ ON TARGET
До 70 минуты
*/
type Over05 struct {
id int64
notifyInTelegram bool
isChampAccepted func(string) bool
}
func NewOver05(opt StrategyOptions) Over05 {
if opt.ID == 0 {
panic("StrategyID not defined")
}
s := Over05{}
s.id = opt.ID
s.notifyInTelegram = opt.NotifyInTelegram
s.isChampAccepted = opt.IsChampAccepted
return s
}
func (s Over05) ID() int64 {
return s.id
}
func (s Over05) ShortName() string {
return fmt.Sprintf("#%d FT Over 0.5", s.id)
}
func (s Over05) IsNotifyInTelegram() bool {
return s.notifyInTelegram
}
func (s Over05) GetTelegramTipPattern() string {
return `Сигнал # %d.
Будет ГОЛ!
Алгоритм %d
Тотал Больше 0.5
Футбол. %s. %s
%s - %s
Коэф. %.3f`
}
type isInterestingNotesOver05 struct {
PriceOver25 float64 `json:"Over 2.5 price"`
MatchesAnalysed int `json:"matchesAnalysed"`
HasGoalInMatches int `json:"hasGoalInMatches"`
GoalsPercent float64 `json:"goalsPercent"`
}
func (s Over05) IsInteresting(report *TeamMatch) (notes interface{}, _ bool) {
var (
priceOver25 float64
foundPriceOver25 bool
//f flashscore.TotalOffer
)
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 := isInterestingNotesOver05{
PriceOver25: priceOver25,
MatchesAnalysed: matchCount,
HasGoalInMatches: hasGoalsInMatchCount,
GoalsPercent: goalsPercent,
}
//buf, _ := json.MarshalIndent(obj, "", " ")
return obj, true
}
func (s Over05) 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
}
if upd.HomeGoals > 0 || upd.AwayGoals > 0 {
// Если гол уже забили - выходим
return "гол уже забит", nil, Unwatch
}
// Ищем тотал Больше 0.5
// Минимальный курс
minPrice := 1.5
var (
minPriceCheckPassed bool
currentPrice float64
)
for _, over := range upd.Total.Over {
if over.Param == "0.5" {
if over.Price < minPrice {
return fmt.Sprintf("коэф. %.2f < %.2f", over.Price, minPrice), nil, Waiting
}
currentPrice = over.Price
minPriceCheckPassed = true
break
}
}
if !minPriceCheckPassed {
return "тотал 0.5 не найден", nil, Waiting
}
//
attacks := upd.HomeAttacks + upd.AwayAttacks + upd.HomeDangerousAttacks + upd.AwayDangerousAttacks
shotsOffTarget := upd.HomeShotsOffTarget + upd.AwayShotsOffTarget
shotsOnTarget := upd.HomeShotsOnTarget + upd.AwayShotsOnTarget
if attacks < 135 {
return fmt.Sprintf("%d атак < 135", 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: "0.5",
Price: currentPrice,
}, Bet
}
func (s Over05) 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 > 0 {
res.Status = model.Won
} else {
res.Status = model.Lost
}
res.Result = fmt.Sprintf("счет: %d-%d", stats.HomePoints, stats.AwayPoints)
return res
}