Files
tipper/daemon/onexbet.go
2026-07-21 05:29:37 +03:00

876 lines
28 KiB
Go
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package daemon
import (
"fmt"
"sort"
"strconv"
"strings"
"time"
"gordenko.dev/dima/flashscore"
"gordenko.dev/dima/onexbet"
"gordenko.dev/dima/tipper/model"
"gordenko.dev/dima/web/api"
"gordenko.dev/dima/ws"
)
func (s *Daemon) tryLinkToLiveMatch(sportID int, liveMatch onexbet.LiveMatch) {
matchName := fmt.Sprintf("%s - %s", liveMatch.Home, liveMatch.Away)
s.logger.Printf("try link: %s\n", matchName)
// Если уже распознан - пропускаем
// На всякий пожарный проверка
//_, ok := s.onexbetMatchToTeamMatch[liveMatch.MatchID]
//if ok {
// s.logger.Printf("try link: %s\n", matchName)
// return
//}
// Если этот матч уже проверяли - игнорируем
s.mutex.Lock()
unrecognizedMatches, ok := s.unrecognizedOnexbetMatches[sportID]
if !ok {
s.logger.Printf("unrecognized matches for the sport %d not found\n", sportID)
return
}
if unrecognizedMatches[liveMatch.MatchID] {
//s.logger.Printf("Match (%s) is unrecognized. Don't repeat identification\n", matchName)
s.mutex.Unlock()
return
}
s.mutex.Unlock()
homeTeamCandidates, err := s.fsmodel.ListTeamCandidates(sportID, liveMatch.Home)
if err != nil {
s.logger.Printf("fsmodel.ListFootballTeamCandidates: %s\n", err)
return
}
//s.logger.Printf("homeTeamCandidates (for %s): %q", liveMatch.Home, homeTeamCandidates)
awayTeamCandidates, err := s.fsmodel.ListTeamCandidates(sportID, liveMatch.Away)
if err != nil {
s.logger.Printf("fsmodel.ListFootballTeamCandidates: %s\n", err)
return
}
//s.logger.Printf("awayTeamCandidates (for %s): %q", liveMatch.Away, awayTeamCandidates)
//
teamMatches, ok := s.teamMatches[sportID]
if !ok {
err = fmt.Errorf("Not found matches for the sportID %d", sportID)
return
}
for _, match := range teamMatches {
var isTeamsSwapped bool
isIdentified := s.tryIdentifyMatch(match.Home.TeamID, match.Away.TeamID,
homeTeamCandidates, awayTeamCandidates)
if !isIdentified {
// Пробуем опознать если home и away поменять местами
isIdentified = s.tryIdentifyMatch(match.Home.TeamID, match.Away.TeamID,
awayTeamCandidates, homeTeamCandidates)
isTeamsSwapped = true
}
if isIdentified {
if !match.Home.WasLinked {
err = s.fsmodel.SetTeamWasLinked(match.Home.TeamID)
if err != nil {
s.logger.Printf("fsmodel.SetTeamWasLinked: %s; teamID=%s\n",
err, match.Home.TeamID)
}
s.mutex.Lock()
match.Home.WasLinked = true
s.mutex.Unlock()
}
if !match.Away.WasLinked {
err = s.fsmodel.SetTeamWasLinked(match.Away.TeamID)
if err != nil {
s.logger.Printf("fsmodel.SetTeamWasLinked: %s; teamID=%s\n",
err, match.Away.TeamID)
}
s.mutex.Lock()
match.Away.WasLinked = true
s.mutex.Unlock()
}
s.mutex.Lock()
match.IsLinkedToOnexbet = true
match.OnexbetMatchID = liveMatch.MatchID
match.OnexbetStatsMatchID = liveMatch.StatsMatchID
match.Score = liveMatch.Score
match.ScoreByPeriods = liveMatch.ScoreByPeriods
match.CurrentPeriod = liveMatch.CurrentPeriod
match.IsTeamsSwapped = isTeamsSwapped
s.onexbetMatchToTeamMatch[liveMatch.MatchID] = match
s.identifiedMatches[liveMatch.MatchID] = true
s.logger.Printf("Identified: %s; %s; %s\n", matchName, liveMatch.MatchID, match.MatchID)
// Матч опознан и перешел в inplay
s.publisher.Publish(
getChannel(match.SportID),
WSMessageInplayStatusChanged,
InplayStatusMessage{
MatchID: match.MatchID,
IsInplay: match.IsInplay,
IsLinkedToOnexbet: match.IsLinkedToOnexbet,
},
)
s.mutex.Unlock()
return
}
}
s.mutex.Lock()
// Кешируем негативный результат, чтобы не искать в базе ежеминутно
// Если пользователь распознает новые матчи, - кэш будет очищен
unrecognizedMatches, ok = s.unrecognizedOnexbetMatches[sportID]
if !ok {
return
}
unrecognizedMatches[liveMatch.MatchID] = true
s.mutex.Unlock()
s.logger.Printf("Match (%s; %s) is not identified. Added to unrecognized\n", matchName, liveMatch.MatchID)
}
func (s *Daemon) tryIdentifyMatch(homeTeamID, awayTeamID string, homeTeamCandidates, awayTeamCandidates []string) (_ bool) {
for _, candidateHomeTeamID := range homeTeamCandidates {
if homeTeamID == candidateHomeTeamID {
// Если нашли совпадение для home - ищем совпадение для away
for _, candidateAwayTeamID := range awayTeamCandidates {
if awayTeamID == candidateAwayTeamID {
// Mатч идентифицирован
return true
}
}
}
}
return
}
func (s *Daemon) onOnexbetWsClientConnected(conn *ws.Conn) {
s.logger.Printf("Onexbet Ws Client Connected\n")
}
/*
func (s *Daemon) onOnexbetMatchFinished(conn *ws.Conn, in onexbet.WatchReq) {
s.mutex.Lock()
defer s.mutex.Unlock()
match, ok := s.onexbetMatchToTeamMatch[in.MatchID]
if !ok {
return
}
match.IsInplay = false
}
*/
func (s *Daemon) onOnexbetTeamLiveMatches(conn *ws.Conn, in onexbet.LiveMatchesMessage) {
//s.logger.Println("onOnexbetTeamLiveMatches")
//s.logger.Printf("onexbetMatchToTeamMatch size: %d\n", len(s.onexbetMatchToTeamMatch))
sportID, ok := onexbetSportToFlashscoreSport[in.SportID]
if !ok {
s.logger.Printf("Bug: unknown OnexbetSport %d\n", in.SportID)
return
}
s.logger.Printf("Onexbet live matches: %d, watching: %d; Inplay: %d\n",
len(in.Matches), len(in.Watching), len(s.onexbetMatchToTeamMatch))
liveMap := make(map[string]onexbet.LiveMatch)
// В цикле рашем 3 задачи:
// - формируем словарь из live матчей на сайте 1xBet, для удобства дальнейшей обработки
// - для матчей в inplay проверяем не появился ли liveMatch.StatsMatchID, по которому
// можно будет узнать результат матча на сайте 1xBet
// - пытаемся распознать новые матчи
for _, liveMatch := range in.Matches {
liveMap[liveMatch.MatchID] = liveMatch
match, ok := s.onexbetMatchToTeamMatch[liveMatch.MatchID]
if ok {
s.logger.Printf("Match (%s - %s) already identified\n", match.Home.CanonicalName, match.Away.CanonicalName)
// ВАЖНО!
// liveMatch.StatsMatchID появится когда матч перейдет в лайв.
if match.OnexbetStatsMatchID == "" && liveMatch.StatsMatchID != "" {
match.OnexbetStatsMatchID = liveMatch.StatsMatchID
match.Score = liveMatch.Score
match.ScoreByPeriods = liveMatch.ScoreByPeriods
match.CurrentPeriod = liveMatch.CurrentPeriod
}
} else {
if !s.identifiedMatches[liveMatch.MatchID] {
// Матча нет среди распознанных - пытаемся опознать
s.tryLinkToLiveMatch(sportID, liveMatch)
}
}
}
var watchingMap = make(map[string]bool)
for _, onexbetMatchID := range in.Watching {
watchingMap[onexbetMatchID] = true
_, isMatchInInplay := s.onexbetMatchToTeamMatch[onexbetMatchID]
if !isMatchInInplay {
// Матча больше нет в inplay. Если 1xbet присылает его в Watching -
// значит API-запрос Unwatch где-то потерялся. Поэтому отправляем снова.
s.onexbetAPIClient.Call(api.CallReq{
FuncName: "unwatch",
In: onexbet.WatchReq{
SportID: in.SportID,
MatchID: onexbetMatchID,
},
})
}
}
// Цикл по inplay матчам
//if sportID == flashscore.Tennis {
//
//s.checkInplayTennisMatches(liveMap, watchingMap)
//} else {
s.checkInplayTeamMatches(sportID, in.SportID, liveMap, watchingMap)
//}
}
//func (s *Daemon) checkInplayTennisMatches(liveMap map[string]bool, watchingMap map[string]bool) {
//for onexbetMatchID, match := range s.onexbetMatchToTeamMatch {
//if match.
//}
//}
func (s *Daemon) checkInplayTeamMatches(sportID int, onexbetSportID onexbet.OnexbetSport, liveMap map[string]onexbet.LiveMatch, watchingMap map[string]bool) {
for onexbetMatchID, match := range s.onexbetMatchToTeamMatch {
if match.SportID != sportID {
// Если другой спорт - пропускаем матч
continue
}
liveMatch, isIn1xbetLive := liveMap[onexbetMatchID]
if !isIn1xbetLive {
// МАТЧИ могут просто исчезать из ЛАЙВ списка, поэтому просто удалять
// нельзя! Сперва запросим результат матча у 1xbet и решим что делать.
//err := s.processMatchDisappearedFromLive(match, onexbetMatchID)
//if err != nil {
// s.logger.Printf("processMatchDisappearedFromLive: %s\n", err)
//}
s.logger.Printf("Inplay match (%s - %s) not found in 1xbet live matches. Remove from inplay\n",
match.Home.CanonicalName, match.Away.CanonicalName)
s.removeMatchFromInplay(match, onexbetMatchID)
} else {
if !watchingMap[onexbetMatchID] {
// Матч есть в лайве 1xbet (liveMap) - но нет в наблюдаемых. Например,
// перезагрузился 1xbet демон, или отписались.
if len(match.Strategies) > 0 {
// Если еще есть не сработавшие стратегии - начинаем наблюдать.
//s.logger.Printf("Watch: %d, %s\n", in.SportID, onexbetMatchID)
// Подписываемся на матчи, которые только что идентифицировали + на те, которые
// пропали из watch списка (например из-за перезагрузки 1xBET демона)
for _, strategy := range match.Strategies {
if strategy.IsNeedToWatch(liveMatch) {
// Если хотя бы одной стратегии нужно наблюдать за матчем
// - подписываемся и прерываем цикл
match.IsInplay = true
s.onexbetAPIClient.Call(api.CallReq{
FuncName: "watch",
In: onexbet.WatchReq{
SportID: onexbetSportID,
MatchID: onexbetMatchID,
},
})
s.mutex.Lock()
// Матч дабавили в inplay
s.publisher.Publish(
getChannel(match.SportID),
WSMessageInplayStatusChanged,
InplayStatusMessage{
MatchID: match.MatchID,
IsInplay: match.IsInplay,
IsLinkedToOnexbet: match.IsLinkedToOnexbet,
},
)
s.mutex.Unlock()
// ВАЖНО!
break
}
}
} else {
s.mutex.Lock()
//s.logger.Printf("Unwatch: %d, %s\n", in.SportID, onexbetMatchID)
// Матч больше не интересен
// Все стратегии сработали - отписываемся от матча
delete(s.onexbetMatchToTeamMatch, onexbetMatchID)
match.IsInplay = false
s.onexbetAPIClient.Call(api.CallReq{
FuncName: "unwatch",
In: onexbet.WatchReq{
SportID: onexbetSportID,
MatchID: onexbetMatchID,
},
})
// Матч убрали из inplay
s.publisher.Publish(
getChannel(match.SportID),
WSMessageInplayStatusChanged,
InplayStatusMessage{
MatchID: match.MatchID,
IsInplay: match.IsInplay,
IsLinkedToOnexbet: match.IsLinkedToOnexbet,
},
)
s.mutex.Unlock()
}
} else {
// Матч есть в лайве 1xbet (liveMap) и в наблюдаемых - все OK.
// Ничего не делаем.
}
}
}
}
/*
func (s *Daemon) processMatchDisappearedFromLive(match *TeamMatch, onexbetMatchID string) (err error) {
if match.OnexbetStatsMatchID == "" {
// Ситуация возвожна, когда матч появился на короткий срок, OnexbetStatsMatchID еще
// не получил и затем исчез.
err = fmt.Errorf("1xBet match %s has empty OnexbetStatsMatchID", onexbetMatchID)
return
}
matchResult, err := onexbet.GetTeamMatchResult(match.OnexbetStatsMatchID)
if err != nil {
err = fmt.Errorf("onexbet.GetTeamMatchResult: %s", err)
return
}
if matchResult.Status != onexbet.StatusMatchCompleted {
// Если матч не завершен - пропускаем. Предполагаем что матч просто
// временно исчез из лайва
return
}
// Матч завершен - загружаем прогнозы, чтобы выставить результаты
tips, err := s.model.ListMatchTips(match.MatchID)
if err != nil {
err = fmt.Errorf("model.ListMatchTips: %s; matchID=%s", err, match.MatchID)
return
}
if len(tips) > 0 {
// На один матч может быть несколько прогнозов, поэтому важно знать что результаты
// всех прогнозов удалось записать в БД. Пока все результаты записать не удастся -
// это метод будет вызыватся снова и снова.
for _, tip := range tips {
err = s.trySetTipResult(tip, matchResult)
if err != nil {
err = fmt.Errorf("trySetTipResult: %s; tipID=%d", err, tip.TipID)
return
}
}
}
// Результат всех прогнозов по матчу успешно записан либо прогнозов не было.
// В любом случае - удаляем матч из лайва.
s.removeMatchFromInplay(match, onexbetMatchID)
return
}
*/
func (s *Daemon) removeMatchFromInplay(match *TeamMatch, onexbetMatchID string) {
s.mutex.Lock()
defer s.mutex.Unlock()
delete(s.onexbetMatchToTeamMatch, onexbetMatchID)
match.IsInplay = false
// Матч убрали из inplay
s.publisher.Publish(
getChannel(match.SportID),
WSMessageInplayStatusChanged,
InplayStatusMessage{
MatchID: match.MatchID,
IsInplay: match.IsInplay,
IsLinkedToOnexbet: match.IsLinkedToOnexbet,
},
)
}
type WhyNot struct {
MatchID string `json:"matchID"`
Comment string `json:"comment"`
Time string `json:"time"`
HomeGoals int `json:"homeGoals"`
AwayGoals int `json:"awayGoals"`
GamePace float64 `json:"gamePace"`
GamePaceFrame int `json:"gamePaceFrame"` // count from Zero
}
//func (s *Daemon) onOnexbetTennisLiveMatchData(conn *ws.Conn, upd onexbet.TeamLiveMatchData) {
// s.mutex.Lock()
// defer s.mutex.Unlock()
// s.logger.Printf("tennis MatchData: %s\n", upd.MatchID)
//}
/*
type TeamLiveMatchData struct {
MatchID string `json:"matchID"`
HomeAttacks int `json:"homeAttacks"`
HomeDangerousAttacks int `json:"homeDangerousAttacks"`
HomeShotsOnTarget int `json:"homeShotsOnTarget"`
HomeShotsOffTarget int `json:"homeShotsOffTarget"`
AwayAttacks int `json:"awayAttacks"`
AwayDangerousAttacks int `json:"awayDangerousAttacks"`
AwayShotsOnTarget int `json:"awayShotsOnTarget"`
AwayShotsOffTarget int `json:"awayShotsOffTarget"`
CurrentTime int `json:"currentTime"`
HomeGoals int `json:"homeGoals"`
AwayGoals int `json:"awayGoals"`
Winner *Winner3Way `json:"winner"`
Total Total `json:"total"`
Handicap Handicap `json:"handicap"`
IndividualTotalHome Total `json:"individualTotalHome"`
IndividualTotalAway Total `json:"individualTotalAway"`
H1 Half `json:"h1"` // 1st half
// tennis
Winner2Way *Winner2Way `json:"winner2way"`
// score
Score Score `json:"score"`
ScoreByPeriods map[int]Score `json:"scoreByPeriods"`
CurrentPeriod int `json:"currentPeriod"`
Periods map[int]Period `json:"periods"`
}
*/
func swapTeamLiveMatchData(d onexbet.TeamLiveMatchData) onexbet.TeamLiveMatchData {
d.AwayAttacks, d.HomeAttacks = d.HomeAttacks, d.AwayAttacks
d.AwayDangerousAttacks, d.HomeDangerousAttacks = d.HomeDangerousAttacks, d.AwayDangerousAttacks
d.AwayShotsOnTarget, d.HomeShotsOnTarget = d.HomeShotsOnTarget, d.AwayShotsOnTarget
d.AwayShotsOffTarget, d.HomeShotsOffTarget = d.HomeShotsOffTarget, d.AwayShotsOffTarget
d.AwayGoals, d.HomeGoals = d.HomeGoals, d.AwayGoals
if d.Winner != nil {
d.Winner.Away, d.Winner.Home = d.Winner.Home, d.Winner.Away
}
if d.Winner2Way != nil {
d.Winner2Way.Away, d.Winner2Way.Home = d.Winner2Way.Home, d.Winner2Way.Away
}
d.Handicap.Away, d.Handicap.Home = d.Handicap.Home, d.Handicap.Away
d.IndividualTotalAway, d.IndividualTotalHome = d.IndividualTotalHome, d.IndividualTotalAway
d.H1.IndividualTotalAway, d.H1.IndividualTotalHome = d.H1.IndividualTotalHome, d.H1.IndividualTotalAway
d.Score.Away, d.Score.Home = d.Score.Home, d.Score.Away
for periodNumber, score := range d.ScoreByPeriods {
score.Away, score.Home = score.Home, score.Away
d.ScoreByPeriods[periodNumber] = score
}
for periodNumber, period := range d.Periods {
period.Handicap.Away, period.Handicap.Home = period.Handicap.Home, period.Handicap.Away
d.Periods[periodNumber] = period
}
return d
}
func (s *Daemon) onOnexbetTeamLiveMatchData(conn *ws.Conn, upd onexbet.TeamLiveMatchData) {
s.mutex.Lock()
defer s.mutex.Unlock()
s.logger.Printf("MatchData: %s\n", upd.MatchID)
// маппинг -
match, ok := s.onexbetMatchToTeamMatch[upd.MatchID]
if !ok {
return
}
if match.IsTeamsSwapped {
upd = swapTeamLiveMatchData(upd)
}
//if match.SportID == flashscore.Handball {
//x, _ := json.MarshalIndent(upd, "", " ")
//fmt.Printf("MatchID: %s (1xbet MatchID: %s), Time: %d, HomeGoals: %d, AwayGoals: %d\n",
// match.MatchID, upd.MatchID, upd.CurrentTime, upd.HomeGoals, upd.AwayGoals)
//}
channel := getChannel(match.SportID)
//s.logger.Printf("Onexbet TeamLiveMatchData: sportID %d, channel %s\n", match.SportID, channel)
var (
triggeredStrategyIDs []int64
comments []string
strategyIDs []int
)
for strategyID := range match.Strategies {
strategyIDs = append(strategyIDs, int(strategyID))
}
sort.Ints(strategyIDs)
for _, strategyID := range strategyIDs {
strategy := match.Strategies[int64(strategyID)]
// Если по стратегии уже дали прогноз
//if match.EndedStrategies[strategy.ID()] {
// continue
//}
whyNot, bet, code := strategy.GetTip(match, upd)
switch code {
case Waiting:
// pass
//s.logger.Printf("Waiting: %s\n", whyNot)
// Отправить в websocket
comments = append(comments, fmt.Sprintf("%s:<br>%s", strategy.ShortName(), whyNot))
case Unwatch:
s.logger.Printf("Unwatch: %s\n", whyNot)
triggeredStrategyIDs = append(triggeredStrategyIDs, strategy.ID())
comments = append(comments, fmt.Sprintf("%s:<br>%s", strategy.ShortName(), whyNot))
case Bet:
triggeredStrategyIDs = append(triggeredStrategyIDs, strategy.ID())
var err error
//var tip model.Tip
//var tipPrice float64
tip := model.Tip{
SportID: int64(match.SportID),
StrategyID: strategy.ID(),
MatchID: match.MatchID,
TipTime: time.Now().Unix(),
ChampID: match.Champ.ChampID,
ChampName: match.Champ.Name,
MatchName: fmt.Sprintf("%s - %s", match.Home.CanonicalName, match.Away.CanonicalName),
Market: bet.Market,
Side: bet.Side,
Param: bet.Param,
Price: bet.Price,
CurrentMatchTime: upd.CurrentTime,
OnexbetStatsMatchID: match.OnexbetStatsMatchID,
IsTeamsSwapped: match.IsTeamsSwapped,
}
champRatings, ok := s.champRatings[match.SportID]
if ok {
// обновляем рейтинги чемпионатов
key := ChampRatingKey{
ChampID: tip.ChampID,
StrategyID: tip.StrategyID,
}
rating, ok := champRatings[key]
if ok {
//if (rating.Won+rating.Lost) >= 6 && rating.GetAccuracy() >= 75 {
if rating.GetAccuracy() >= 70 {
tip.IsRated = true
}
}
}
s.logger.Printf("Bet: %#v\n", tip)
tip.TipID, err = s.model.AddTip(tip)
if err != nil {
s.logger.Printf("model.AddTip: %s\n", err)
} else {
// Отправить в websocket
// Добавили новый Tip
s.publisher.Publish(channel, WSMessageTipsChanged, nil)
if match.SportID == flashscore.Football {
// Для футбола только рейтинговые чемпионаты
// Отправить в телеграм
if strategy.IsNotifyInTelegram() && tip.IsRated {
// Отправлять ли в телеграм
msg := fmt.Sprintf(strategy.GetTelegramTipPattern(), tip.TipID, strategy.ID(),
match.Zone.Name, match.Champ.Name,
match.Home.CanonicalName, match.Away.CanonicalName,
bet.Price)
telegramChatID, hasChat := sportToTelegramChatID[match.SportID]
if hasChat {
err = sendMessageToTelegramGroup(telegramChatID, msg)
if err != nil {
s.logger.Printf("send tip to Telegram: %s\n", err)
}
} else {
s.logger.Printf("Sport %d hasn't telegram chat\n", match.SportID)
}
}
} else if match.SportID == flashscore.Handball {
if strategy.IsNotifyInTelegram() && tip.IsRated {
param, err := strconv.ParseFloat(bet.Param, 64)
if err != nil {
s.logger.Printf("Wrong bet param: %s; param=%s\n", err, bet.Param)
} else {
var betterParam1, betterParam2 float64
switch strategy.(type) {
case HandballFTOver, HandballP1Over:
betterParam1 = param - 1
betterParam2 = param - 2
case HandballFTUnder, HandballP1Under:
betterParam1 = param + 1
betterParam2 = param + 2
default:
panic(fmt.Sprintf("Unknown strategy %#v\n", strategy))
}
// Для гандбола отправляем все прогнозы
msg := fmt.Sprintf(strategy.GetTelegramTipPattern(), tip.TipID, strategy.ID(),
match.Zone.Name, match.Champ.Name,
match.Home.CanonicalName, match.Away.CanonicalName,
param, bet.Price, param, betterParam1, betterParam2)
telegramChatID, hasChat := sportToTelegramChatID[match.SportID]
if hasChat {
err = sendMessageToTelegramGroup(telegramChatID, msg)
if err != nil {
s.logger.Printf("send tip to Telegram: %s\n", err)
}
} else {
s.logger.Printf("Sport %d hasn't telegram chat\n", match.SportID)
}
}
}
} else if match.SportID == flashscore.Tennis {
if strategy.IsNotifyInTelegram() {
msg := fmt.Sprintf(bet.TelegramMessage, tip.TipID)
telegramChatID, hasChat := sportToTelegramChatID[match.SportID]
if hasChat {
err = sendMessageToTelegramGroup(telegramChatID, msg)
if err != nil {
s.logger.Printf("send tip to Telegram: %s\n", err)
}
} else {
s.logger.Printf("Sport %d hasn't telegram chat\n", match.SportID)
}
}
}
}
}
}
for _, strategyID := range triggeredStrategyIDs {
delete(match.Strategies, strategyID)
}
if len(match.Strategies) == 0 {
// Все стратегии сработали - отписываемся от матча
s.logger.Printf("Unwatch: %d, %s\n", match.SportID, upd.MatchID)
// Матч больше не интересен
delete(s.onexbetMatchToTeamMatch, upd.MatchID)
match.IsInplay = false
s.onexbetAPIClient.Call(api.CallReq{
FuncName: "unwatch",
In: onexbet.WatchReq{
SportID: flashscoreSportToOnexbetSport[match.SportID],
MatchID: upd.MatchID, // onexbetMatchID
},
})
}
if match.SportID == flashscore.Tennis {
if len(comments) > 0 {
s.publisher.Publish(
channel,
WSMessageWhyNot,
WhyNot{
MatchID: match.MatchID,
Comment: strings.Join(comments, "<br><br>"),
Time: "",
HomeGoals: upd.HomeGoals,
AwayGoals: upd.AwayGoals,
GamePace: match.GamePace,
GamePaceFrame: match.GamePaceFrame,
})
}
} else {
if len(comments) > 0 {
s.publisher.Publish(
channel,
WSMessageWhyNot,
WhyNot{
MatchID: match.MatchID,
Comment: strings.Join(comments, "<br><br>"),
Time: fmt.Sprintf("%s", time.Duration(upd.CurrentTime)*time.Second),
HomeGoals: upd.HomeGoals,
AwayGoals: upd.AwayGoals,
GamePace: match.GamePace,
GamePaceFrame: match.GamePaceFrame,
})
}
}
}
/*
var tipTextPattern string
switch strategyID {
case 1:
tipTextPattern = tipTextAlgo1Pattern
case 2:
tipTextPattern = tipTextAlgo2Pattern
case 3:
tipTextPattern = tipTextAlgo3Pattern
case 100:
tipTextPattern = tipTextAlgo100Pattern
}
*/
/*
switch strategyID {
case 1:
var price float64
for _, over := range upd.H1.Total.Over {
if over.Param == "0.5" {
price = over.Price
}
}
tipPrice = price
tip = model.Tip{
SportID: SportFootball,
StrategyID: int64(strategyID),
MatchID: match.MatchID,
TipTime: time.Now().Unix(),
ChampName: match.Champ.Name,
MatchName: fmt.Sprintf("%s - %s", match.Home.CanonicalName, match.Away.CanonicalName),
Market: MarketTotal1stHalf,
Side: SideOver,
Param: "0.5",
Price: price,
CurrentMatchTime: upd.CurrentTime,
OnexbetStatsMatchID: match.OnexbetStatsMatchID,
}
case 2:
var price float64
for _, over := range upd.Total.Over {
if over.Param == "0.5" {
price = over.Price
}
}
tipPrice = price
tip = model.Tip{
SportID: SportFootball,
StrategyID: int64(strategyID),
MatchID: match.MatchID,
TipTime: time.Now().Unix(),
ChampName: match.Champ.Name,
MatchName: fmt.Sprintf("%s - %s", match.Home.CanonicalName, match.Away.CanonicalName),
Market: MarketTotal,
Side: SideOver,
Param: "0.5",
Price: price,
CurrentMatchTime: upd.CurrentTime,
OnexbetStatsMatchID: match.OnexbetStatsMatchID,
}
case 3:
var price float64
for _, over := range upd.Total.Over {
if over.Param == "1.5" {
price = over.Price
}
}
tipPrice = price
tip = model.Tip{
SportID: SportFootball,
StrategyID: int64(strategyID),
MatchID: match.MatchID,
TipTime: time.Now().Unix(),
ChampName: match.Champ.Name,
MatchName: fmt.Sprintf("%s - %s", match.Home.CanonicalName, match.Away.CanonicalName),
Market: MarketTotal,
Side: SideOver,
Param: "1.5",
Price: price,
CurrentMatchTime: upd.CurrentTime,
OnexbetStatsMatchID: match.OnexbetStatsMatchID,
}
case 100:
var price float64
for _, over := range upd.H1.Total.Over {
if over.Param == "0.5" {
price = over.Price
}
}
tipPrice = price
tip = model.Tip{
SportID: SportFootball,
StrategyID: int64(strategyID),
MatchID: match.MatchID,
TipTime: time.Now().Unix(),
ChampName: match.Champ.Name,
MatchName: fmt.Sprintf("%s - %s", match.Home.CanonicalName, match.Away.CanonicalName),
Market: MarketTotal1stHalf,
Side: SideOver,
Param: "0.5",
Price: price,
CurrentMatchTime: upd.CurrentTime,
OnexbetStatsMatchID: match.OnexbetStatsMatchID,
}
}
*/