uof

package module
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 16, 2021 License: MIT Imports: 10 Imported by: 0

README

go-uof-sdk

Betradar Unified Odds Feed Go SDK

GoDoc Go Report Card Build Status Coverage Status

Why

From the Betradar docs:

SDK benefits over protocol/API

  • The SDK hides the separation between messages and API-lookups. The client system just receives the message objects where all information is prefilled by the SDK caches, and in some cases looked up in the background when the client system requests some more rarely requested information.
  • The SDK takes care of translations transparently. The client system just needs to define what languages it needs.
  • The SDK takes care of dynamic text markets and outright markets automatically, which requires some extra logic and lookups for someone not using the SDK.
  • The SDK handles initial connect and state, as well as recovery in case of a temporary disconnect. This needs to be handled manually by someone not using the SDK.
How

SDK se spaja na dva Betradar endpointa. Prvi je AMQP message queue, drugi je rest api. U kodu im odgovaraju paketi queue i api. Prvim kanalom, queue, dobijamo numericke, brzo promjenjive podatke. Najznacajniji predstavnik su promjene tecajeva. Drugi kanal je vezan us staticke, opisne podatke, koji tipicno ovise o jeziku u kojem ih prezentiramo. Npr. nazivi timova, igraca, razrada. Podaci u queue kanalu, kako su po prirodi numericki, nisu vezani uz neki jezik.

Izlaz je serijal poruka. Imamo tri grupe tipova poruka:

  • event messages; poruke vezane uz neki dogadjaj:
    • odds change
    • fixture change; npr vrijeme pocetka
    • bet cancel
    • bet settlement
    • bet stop
    • rollback bet settlement
    • rollback bet stop
  • api message; poruke koje su dogovor na neki api poziv:
    • fixture - detalji dogadjaja
    • markets - opsi razrada
    • player - opis igraca
  • system messages
    • alive
    • snapshot complete
    • connection status
    • producer state change

Za client aplikaciju nuzno je da razumije i da ne odgovarajuci nacin reagira na svaki tip poruke.

Treci tip poruka, system messages, je nuzno razumjeti za ostvarivanje pouzdane komunikacije.
Alive i snapshot complete su low level poruke. Od klijenta se ne ocekuje da reagira ne njih. Slijedeca dva tipa connection status i producer state change su puno znacajniji. Alive i snapshot pustamo van da bi klijent imao kompletnu sliku komunikacije, da bi mogao logirati i kasnije eventualno istrazivati probleme.

Connection status ima dva stanja up ili down. Up je ako smo uspjesno spojeni na Betradar AMQP message queue, down ako nismo. Kada izgubimo konekciju SDK ce emitirati down poruku, kada ju ponovo upsostavimo saljemo up. Slicno kao i prethodne dvije poruke na ovu takodjer nije nuzno reagirati ima informativno znacenje.

Sto je producer?
Sve event message types su vezane uz nekog producera. Producer je npr; live, prematch, svaki od virtuala. Produceri neovisno proizvode i salju poruke vezano uz dogadjaje koje pokrivaju.

Bitan tip sistemske poruke je producer state. U njoj dobijamo stanje svih producera na svaku promjenu bilo kojeg od njih. Svaki producer moze bit u jednom od tri stanja:

  • down
  • active
  • in recovery

Inicijalno svi produceri startaju u in recovery stanju. Kada recovery procedura zavrsi producer prelazi u active stanje. Bilo koji gubitak veze prebacuje sve producere u down stanje. Uspostava veze stavlja producere u in recovery stanje i pokrece recovery proceduru za sve.

Recovery procedura

Ogovornost je klijenta (korisnika SDK) da za svakog producera pamti zadnji timestamp poruke koja je uspjesno obradjena. Na pokretanju aplikacije SDK se inicijalizira tim timestamp-om za svakog producera kojeg klijent prati.
SDK ce na startu pokrenuti recovery proceduru za svako producera. Kijent ce na samom startu dobiti producer change poruku u kojoj su svi produceri u in recovery stanju. Kako zavrsi recovery za nekog od producera klijent ce dobiti producers change poruku u kojoj je promjenjeno stanje tog producera.
Od klijent aplikacije se ocekuje da reagira na producers change poruke na odgovarajuci nacin. Npr. da zaustavi kladnjenje na evente producera kada je on u stanju koje nije active duze od 20 sekundi.
Uputno je razumjeti SDK <-> Betradar komunikaciju tijekom recovery-ja: referenca

Primjer

koristenja SDK:

	err := sdk.Run(ctx,
		sdk.Credentials(bookmakerID, token),		
		sdk.Languages(uof.Languages("en,de,hr")),        
		sdk.Recovery(pc),
		sdk.Consumer(myConsumer),
	)
	if err != nil {
		log.Fatal(err)
	}

Credentials je nuzna postavka da bi se SDK znao spojiti na queue i api.
Languages defirnira zeljene jezike za statefull poruke.
Recovery omogucuje da za svaki producer postavimo zadnji uspjesno obradjeni timestamp od kojeg zelimo pokrenuti recovery proceduru.
Consumer je mjesto gdje klijent konzumira SDK poruke.
Primjer consumera:

    myConsumer(in <-chan *uof.Message) error) {
		for msg := range in {
            // handle msg
            // on fatal return error
		}
        // SDK is disconnected
		return nil
	}

Consumer cita sve poruke iz in kanala i obradi ih.
Clean exit se radi na nacin da klijent zatvori ctx koji je poslan u Run. Nakon toga ce SDK prekinuti queue konekciju, zavrsiti obradu svih do tada primljenih pourka i zatvoriti in kanale svih consumera. Nakon sto svi consumeri zavrse zavrsava i Run poziv.
Fatal, unclean, izlazak je moguc na nacin da handler vrati error prije nego je konzumirao sve poruke iz in kanala.

Examples

For sample staging client see cmd/client.
For sample replay see cmd/replay.

These examples require two env variables to be set:

export UOF_BOOKMAKER_ID=...  
export UOF_TOKEN=...  
Code linting

This project uses golangci-lint linter with config in .golangci.yml.

If you are using vscode add to your settings.json:

"go.lintTool":"golangci-lint",
"go.lintFlags": [
  "--fast"
]

or run it in terminal:

golangci-lint run ./...

The main difference with old golint is that we have disabled annoying warnings about not having a comment on exported (method|function|type|const) and package.

Notes
  • Staging environment weekend downtime:

The integration environment is available 24/5, Monday to Friday.
During the weekend there will be some planned 2 hour disconnections at fixed times:
Saturday: 14:00 - 16:00 UTC and 20:00 - 22:00 UTC
Sunday: 00:00 - 02:00 UTC and 13:00 - 15:00 UTC

Documentation

Index

Constants

View Source
const (
	InvalidName = "?"
)
View Source
const NoURN = URN("")

Variables

This section is empty.

Functions

func CurrentTimestamp

func CurrentTimestamp() int

CurrentTimestamp in milliseconds

func Hash

func Hash(s string) int

func UIDWithLang

func UIDWithLang(id int, lang Lang) int

Types

type APIError

type APIError struct {
	URL        string
	StatusCode int
	Response   string
	Inner      error
}

func (APIError) Error

func (e APIError) Error() string

func (APIError) Unwrap

func (e APIError) Unwrap() error

type Alive

type Alive struct {
	//	The producer that sent this alive message.
	Producer Producer `xml:"product,attr" json:"producer"`
	// Timestamp in milliseconds since epoch when this message was generated
	// according to generating system's clock.
	Timestamp int `xml:"timestamp,attr" json:"timestamp"`
	// If set to 0 this means the product is up again after downtime, and the
	// receiving client will have to issue recovery messages against the API to
	// start receiving any additional messages and get the current state.
	Subscribed int `xml:"subscribed,attr" json:"subscribed"`
}

Alive messages are sent by each producer every 10 seconds. This is indicating that the given producer is operating normally and you are able to receive messages from it. Reference: https://docs.betradar.com/display/BD/UOF+-+Alive

type BetCancel

type BetCancel struct {
	EventID   int      `json:"eventID"`
	EventURN  URN      `xml:"event_id,attr" json:"eventURN"`
	Producer  Producer `xml:"product,attr" json:"producer"`
	Timestamp int      `xml:"timestamp,attr" json:"timestamp"`
	RequestID *int     `xml:"request_id,attr,omitempty" json:"requestID,omitempty"`
	// If start and end time are specified, they designate a range in time for
	// which bets made should be cancelled. If there is an end_time but no
	// start_time, this means cancel all bets placed before the specified time. If
	// there is a start_time but no end_time this means, cancel all bets placed
	// after the specified start_time.
	StartTime    *int              `xml:"start_time,attr,omitempty" json:"startTime,omitempty"`
	EndTime      *int              `xml:"end_time,attr,omitempty" json:"endTime,omitempty"`
	SupercededBy *string           `xml:"superceded_by,attr,omitempty" json:"supercededBy,omitempty"`
	Markets      []BetCancelMarket `xml:"market" json:"market"`
}

A bet_cancel message is sent when a bet made on a particular market needs to be cancelled and refunded due to an error (which is different to a bet-settlement/refund). Reference: https://docs.betradar.com/display/BD/UOF+-+Bet+cancel

func (*BetCancel) UnmarshalXML

func (t *BetCancel) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML

type BetCancelMarket

type BetCancelMarket struct {
	ID         int  `xml:"id,attr" json:"id"`
	LineID     int  `json:"lineID"`
	VoidReason *int `xml:"void_reason,attr,omitempty" json:"voidReason,omitempty"`
}

func (*BetCancelMarket) UnmarshalXML

func (t *BetCancelMarket) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML

type BetSettlement

type BetSettlement struct {
	EventID   int      `json:"eventID"`
	EventURN  URN      `xml:"event_id,attr" json:"eventURN"`
	Producer  Producer `xml:"product,attr" json:"producer"`
	Timestamp int      `xml:"timestamp,attr" json:"timestamp"`
	RequestID *int     `xml:"request_id,attr,omitempty" json:"requestID,omitempty"`
	// Is this bet-settlement sent as a consequence of scouts reporting the
	// results live (1) or is this bet-settlement sent post-match when the
	// official results have been confirmed (2)
	Certainty *int8                 `xml:"certainty,attr" json:"certainty"` // May be one of 1, 2
	Markets   []BetSettlementMarket `xml:"outcomes>market" json:"outcomes"`
}

func (*BetSettlement) UnmarshalXML

func (t *BetSettlement) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type BetSettlementMarket

type BetSettlementMarket struct {
	ID         int               `xml:"id,attr" json:"id"`
	LineID     int               `json:"lineID"`
	Specifiers map[string]string `json:"specifiers,omitempty"`
	// Describes the reason for voiding certain outcomes for a particular market.
	// Only set if at least one of the outcomes have a void_factor. A list of void
	// reasons can be found above this table or by using the API at
	// https://iodocs.betradar.com/unifiedfeed#Betting-descriptions-GET-Void-reasons.
	VoidReason *int                   `xml:"void_reason,attr,omitempty" json:"voidReason,omitempty"`
	Result     *string                `xml:"result,attr,omitempty" json:"result,omitempty"`
	Outcomes   []BetSettlementOutcome `xml:"outcome" json:"outcome"`
}

func (*BetSettlementMarket) UnmarshalXML

func (t *BetSettlementMarket) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type BetSettlementOutcome

type BetSettlementOutcome struct {
	ID             int           `json:"id"`
	PlayerID       int           `json:"playerID"`
	Result         OutcomeResult `json:"result"`
	DeadHeatFactor float64       `json:"deadHeatFactor,omitempty"`
}

func (*BetSettlementOutcome) UnmarshalXML

func (t *BetSettlementOutcome) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type BetStop

type BetStop struct {
	EventID   int          `json:"eventID"`
	EventURN  URN          `xml:"event_id,attr" json:"eventURN"`
	Timestamp int          `xml:"timestamp,attr" json:"timestamp"`
	RequestID *int         `xml:"request_id,attr,omitempty" json:"requestID,omitempty"`
	Groups    []string     `json:"groups"`
	MarketIDs []int        `json:"marketsIDs"`
	Producer  Producer     `xml:"product,attr" json:"producer"`
	Status    MarketStatus `json:"status,omitempty"`
}

The bet_stop message is an optimized signal to indicate that all, or a set of markets should be instantly suspended (continue to display odds, but don't accept tickets). The same effect can also be achieved by sending an odds_change message that lists all the affected markets and moves them to status="-1" (suspended). It is important to keep in mind that only active markets should be set to suspended, and not markets that are already deactivated, settled or cancelled. This is also the case for the attribute market_status (explained HERE). If it is not present, the market should be moved to suspended. However, if the market is already deactivated, settled or cancelled this is not a good practice. Only move ACTIVE markets to suspended.

func (*BetStop) UnmarshalXML

func (t *BetStop) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type Body

type Body struct {
	// queue message types
	// Ref: https://docs.betradar.com/display/BD/UOF+-+Messages
	Alive                 *Alive                 `json:"alive,omitempty"`
	BetCancel             *BetCancel             `json:"betCancel,omitempty"`
	RollbackBetSettlement *RollbackBetSettlement `json:"rollbackBetSettlement,omitempty"`
	RollbackBetCancel     *RollbackBetCancel     `json:"rollbackBetCancel,omitempty"`
	SnapshotComplete      *SnapshotComplete      `json:"snapshotComplete,omitempty"`
	OddsChange            *OddsChange            `json:"oddsChange,omitempty"`
	FixtureChange         *FixtureChange         `json:"fixtureChange,omitempty"`
	BetSettlement         *BetSettlement         `json:"betSettlement,omitempty"`
	BetStop               *BetStop               `json:"betStop,omitempty"`
	// api response message types
	Fixture            *Fixture            `json:"fixture,omitempty"`
	Markets            MarketDescriptions  `json:"markets,omitempty"`
	Player             *Player             `json:"player,omitempty"`
	Competitor         *CompetitorPlayer   `json:"competitor,omitempty"`
	Tournament         *FixtureTournament  `json:"tournament,omitempty"`
	SummaryEventStatus *SummaryEventStatus `json:"summaryEventStatus,omitempty"`

	// sdk status message types
	Connection *Connection     `json:"connection,omitempty"`
	Producers  ProducersChange `json:"producerChange,omitempty"`
}

type CashoutStatus

type CashoutStatus int8
const (
	// available for cashout
	CashoutStatusAvailable CashoutStatus = 1
	// temporarily unavailable for cashout
	CashoutStatusUnavailable CashoutStatus = -1
	// permanently unavailable for cashout
	CashoutStatusClosed CashoutStatus = -2
)

func (*CashoutStatus) PtrVal

func (s *CashoutStatus) PtrVal() *int8

type Category

type Category struct {
	ID          int    `json:"id"`
	Name        string `xml:"name,attr" json:"name"`
	CountryCode string `xml:"country_code,attr,omitempty" json:"countryCode,omitempty"`
}

func (*Category) UnmarshalXML

func (t *Category) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type Clock

type Clock struct {
	// The playing minute of the match (or minute:second if available)
	// mm:ss (42:10)
	MatchTime *ClockTime `xml:"match_time,attr,omitempty" json:"matchTime,omitempty"`
	// How far into stoppage time is the match in minutes
	// mm:ss
	StoppageTime *ClockTime `xml:"stoppage_time,attr,omitempty" json:"stoppageTime,omitempty"`
	// Set to what the announce stoppage time is announced
	// mm:ss
	StoppageTimeAnnounced *ClockTime `xml:"stoppage_time_announced,attr,omitempty" json:"stoppageTimeAnnounced,omitempty"`
	// How many minutes remains of the match
	// mm:ss
	RemainingTime *ClockTime `xml:"remaining_time,attr,omitempty" json:"remainingTime,omitempty"`
	// How much time remains in the current period
	// mm:ss
	RemainingTimeInPeriod *ClockTime `xml:"remaining_time_in_period,attr,omitempty" json:"remainingTimeInPeriod,omitempty"`
	// true if the match clock is stopped otherwise false
	Stopped *bool `xml:"stopped,attr,omitempty" json:"stopped,omitempty"`
}

The sport_event_status may contain a clock element. This clock element includes various clock/time attributes that are sports specific.

type ClockTime

type ClockTime string

Values must match the pattern [0-9]+:[0-9]+|[0-9]+

func (*ClockTime) Minute

func (c *ClockTime) Minute() string

func (*ClockTime) PtrVal

func (c *ClockTime) PtrVal() *string

func (*ClockTime) String

func (c *ClockTime) String() string

type Competitor

type Competitor struct {
	ID           int                `json:"id"`
	Qualifier    string             `xml:"qualifier,attr,omitempty" json:"qualifier,omitempty"`
	Name         string             `xml:"name,attr" json:"name"`
	Abbreviation string             `xml:"abbreviation,attr" json:"abbreviation"`
	Country      string             `xml:"country,attr,omitempty" json:"country,omitempty"`
	CountryCode  string             `xml:"country_code,attr,omitempty" json:"countryCode,omitempty"`
	Virtual      bool               `xml:"virtual,attr,omitempty" json:"virtual,omitempty"`
	Players      []CompetitorPlayer `xml:"players>player,omitempty" json:"players,omitempty"`
}

func (*Competitor) UnmarshalXML

func (t *Competitor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type CompetitorPlayer

type CompetitorPlayer struct {
	ID           int    `json:"id"`
	Name         string `xml:"name,attr" json:"name"`
	Abbreviation string `xml:"abbreviation,attr" json:"abbreviation"`
	Nationality  string `xml:"nationality,attr,omitempty" json:"nationality,omitempty"`
}

func (*CompetitorPlayer) UnmarshalXML

func (t *CompetitorPlayer) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type CompetitorProfile

type CompetitorProfile struct {
	Competitor  CompetitorPlayer `xml:"competitor" json:"competitor"`
	GeneratedAt time.Time        `xml:"generated_at,attr,omitempty" json:"generatedAt,omitempty"`
}

type Connection

type Connection struct {
	Status    ConnectionStatus `json:"status"`
	Timestamp int              `json:"timestamp,omitempty"`
}

type ConnectionStatus

type ConnectionStatus int8
const (
	ConnectionStatusUp ConnectionStatus = iota
	ConnectionStatusDown
)

func (ConnectionStatus) String

func (cs ConnectionStatus) String() string

type Environment

type Environment int8
const (
	Production Environment = iota
	Staging
	Replay
)

type Error

type Error struct {
	Severity ErrorSeverity
	Op       string // logical operation
	Inner    error  // nested error
}

Inspiration:

https://peter.bourgon.org/blog/2019/09/11/programming-with-errors.html
https://commandcenter.blogspot.com/2017/12/error-handling-in-upspin.html
https://middlemost.com/failure-is-your-domain/

func E

func E(op string, inner error) Error

func Notice

func Notice(op string, inner error) Error

func (Error) Error

func (e Error) Error() string

func (Error) Unwrap

func (e Error) Unwrap() error

type ErrorSeverity

type ErrorSeverity int8
const (
	LogSeverity    ErrorSeverity = iota // log for later
	NoticeSeverity                      // oprator should be notified about this error
)

type EventReporting

type EventReporting int8
const (
	EventReportingNotAvailable EventReporting = 0
	EventReportingActive       EventReporting = 1
	EventReportingSuspended    EventReporting = -1
)

type EventStatus

type EventStatus int8
const (
	EventStatusNotStarted EventStatus = 0
	EventStatusLive       EventStatus = 1
	EventStatusSuspended  EventStatus = 2 // Used by the Premium Cricket odds producer
	EventStatusEnded      EventStatus = 3
	EventStatusClosed     EventStatus = 4
	// Only one of the above statuses are possible in the odds_change message in
	// the feed. However please note that other states are available in the API,
	// but will not appear in the odds_change message. These are as following:
	EventStatusCancelled   EventStatus = 5
	EventStatusDelayed     EventStatus = 6
	EventStatusInterrupted EventStatus = 7
	EventStatusPostponed   EventStatus = 8
	EventStatusAbandoned   EventStatus = 9
)

func (*EventStatus) PtrVal

func (s *EventStatus) PtrVal() *int8

func (EventStatus) Val

func (s EventStatus) Val() int8

type ExtraInfo

type ExtraInfo struct {
	Key   string `xml:"key,attr,omitempty" json:"key,omitempty"`
	Value string `xml:"value,attr,omitempty" json:"value,omitempty"`
}

ExtraInfo covers additional fixture information about the match, such as coverage information, extended markets offer, additional rules etc.

type Fixture

type Fixture struct {
	ID                 int       `xml:"-" json:"id"`
	URN                URN       `xml:"id,attr,omitempty" json:"urn"`
	StartTime          time.Time `xml:"start_time,attr,omitempty" json:"startTime,omitempty"`
	StartTimeConfirmed bool      `xml:"start_time_confirmed,attr,omitempty" json:"startTimeConfirmed,omitempty"`
	StartTimeTbd       bool      `xml:"start_time_tbd,attr,omitempty" json:"startTimeTbd,omitempty"`
	NextLiveTime       time.Time `xml:"next_live_time,attr,omitempty" json:"nextLiveTime,omitempty"`
	Liveodds           string    `xml:"liveodds,attr,omitempty" json:"liveodds,omitempty"`
	Status             string    `xml:"status,attr,omitempty" json:"status,omitempty"`
	Name               string    `xml:"name,attr,omitempty" json:"name,omitempty"`
	Type               string    `xml:"type,attr,omitempty" json:"type,omitempty"`
	Scheduled          time.Time `xml:"scheduled,attr,omitempty" json:"scheduled,omitempty"`
	ScheduledEnd       time.Time `xml:"scheduled_end,attr,omitempty" json:"scheduledEnd,omitempty"`
	ReplacedBy         string    `xml:"replaced_by,attr,omitempty" json:"replacedBy,omitempty"`

	Sport      Sport      `xml:"sport" json:"sport"`
	Category   Category   `xml:"category" json:"category"`
	Tournament Tournament `xml:"tournament,omitempty" json:"tournament,omitempty"`

	Round  Round  `xml:"tournament_round,omitempty" json:"round,omitempty"`
	Season Season `xml:"season,omitempty" json:"season,omitempty"`
	Venue  Venue  `xml:"venue,omitempty" json:"venue,omitempty"`

	ProductInfo ProductInfo  `xml:"product_info,omitempty" json:"productInfo,omitempty"`
	Competitors []Competitor `xml:"competitors>competitor,omitempty" json:"competitors,omitempty"`
	TvChannels  []TvChannel  `xml:"tv_channels>tv_channel,omitempty" json:"tvChannels,omitempty"`

	Home Competitor `json:"home"`
	Away Competitor `json:"away"`

	ExtraInfo []ExtraInfo  `xml:"extra_info>info,omitempty" json:"extraInfo,omitempty"`
	Races     []SportEvent `xml:"races>sport_event,omitempty" json:"races,omitempty"`
}

Fixtures describe static or semi-static information about matches and races. Reference: https://docs.betradar.com/display/BD/UOF+-+Fixtures+in+the+API

func (*Fixture) PP

func (f *Fixture) PP() string

PP pretty prints fixure row

func (*Fixture) UnmarshalXML

func (f *Fixture) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type FixtureChange

type FixtureChange struct {
	EventID      int                `json:"eventID"`
	EventURN     URN                `xml:"event_id,attr" json:"eventURN"`
	Producer     Producer           `xml:"product,attr" json:"producer"`
	Timestamp    int                `xml:"timestamp,attr" json:"timestamp"`
	RequestID    *int               `xml:"request_id,attr,omitempty" json:"requestID,omitempty"`
	ChangeType   *FixtureChangeType `xml:"change_type,attr,omitempty" json:"changeType,omitempty"`
	StartTime    *int               `xml:"start_time,attr" json:"startTime"`
	NextLiveTime *int               `xml:"next_live_time,attr,omitempty" json:"nextLiveTime,omitempty"`
}

You will receive a fixture change when you book a match, and also when/if the match is added to the live odds program. A fixture_change message is sent when a Betradar system has made a fixture change it deems is important. These are typically changes that affect events in the near-term (e.g. a match was added that starts in the next few minutes, a match was delayed and starts in a couple of minutes, etc.). The message is short and includes a bare minimum of relevant details about the addition/change. The recommended practice is to always to a follow-up API call to lookup the updated fixture information. Reference: https://docs.betradar.com/display/BD/UOF+-+Fixture+change

func (*FixtureChange) Schedule

func (fc *FixtureChange) Schedule() *time.Time

func (*FixtureChange) UnmarshalXML

func (fc *FixtureChange) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type FixtureChangeType

type FixtureChangeType int8

The change_type attribute (if present), describes what type of change that caused the message to be sent. In general, best practices are to always re-fetch the updated fixture from the API and not solely rely on the change_type and the message content. This is because multiple different changes could have been made. May be one of 1, 2, 3, 4, 5

const (
	// This is a new match/event that has been just added.
	FixtureChangeTypeNew FixtureChangeType = 1
	// Start-time update
	FixtureChangeTypeTime FixtureChangeType = 2
	// This sport event will not take place. It has been cancelled.
	FixtureChangeTypeCancelled FixtureChangeType = 3
	// The format of the sport-event has been updated (e.g. the number of sets to
	// play has been updated or the length of the match etc.)
	FixtureChangeTypeFromat FixtureChangeType = 4
	// Coverage update. Sent for example when liveodds coverage for some reason
	// cannot be offered for a match.
	FixtureChangeTypeCoverage FixtureChangeType = 5
)

type FixtureRsp

type FixtureRsp struct {
	Fixture     Fixture   `xml:"fixture" json:"fixture"`
	GeneratedAt time.Time `xml:"generated_at,attr,omitempty" json:"generatedAt,omitempty"`
}

type FixtureTournament

type FixtureTournament struct {
	ID         int        `xml:"-" json:"id"`
	URN        URN        `xml:"id,attr,omitempty" json:"urn"`
	Name       string     `xml:"name,attr,omitempty" json:"name,omitempty"`
	Sport      Sport      `xml:"sport" json:"sport"`
	Category   Category   `xml:"category" json:"category"`
	Tournament Tournament `xml:"tournament,omitempty" json:"tournament,omitempty"`
	Season     Season     `xml:"season,omitempty" json:"season,omitempty"`
	Groups     []Group    `xml:"groups>group,omitempty" json:"groups,omitempty"`
}

func (*FixtureTournament) UnmarshalXML

func (t *FixtureTournament) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type Gender

type Gender int8
const (
	GenderUnknown Gender = iota
	Male
	Female
)

type Group

type Group struct {
	Name        string       `xml:"name,attr,omitempty" json:"name"`
	Competitors []Competitor `xml:"competitor,omitempty" json:"competitors,omitempty"`
}
type Header struct {
	Type        MessageType     `json:"type,omitempty"`
	Scope       MessageScope    `json:"scope,omitempty"`
	Priority    MessagePriority `json:"priority,omitempty"`
	Lang        Lang            `json:"lang,omitempty"`
	SportID     int             `json:"sportID,omitempty"`
	EventID     int             `json:"eventID,omitempty"`
	EventURN    URN             `json:"eventURN,omitempty"`
	ReceivedAt  int             `json:"receivedAt,omitempty"`
	RequestedAt int             `json:"requestedAt,omitempty"`
	Producer    Producer        `json:"producer,omitempty"`
	Timestamp   int             `json:"timestamp,omitempty"`
}

type Lang

type Lang int8
const (
	LangNone Lang = iota
	LangSQI       // Albanian
	LangAA        // Arabic
	LangAZE       // Azerbaijan
	LangBS        // Bosnian
	LangBR        // Brazilian Portuguese
	LangBG        // Bulgarian
	LangZH        // Chinese (simplified)
	LangZHT       // Chinese (traditional)
	LangHR        // Croatian
	LangCZ        // Czech
	LangDA        // Danish
	LangNL        // Dutch
	LangEN        // English
	LangET        // Estonian
	LangFI        // Finnish
	LangFR        // French
	LangKA        // Georgian
	LangDE        // German
	LangEL        // Greek
	LangHEB       // Hebrew
	LangHU        // Hungarian
	LangID        // Indonesian
	LangJA        // Japanese
	LangKAZ       // Kazakh
	LangKO        // Korean
	LangLV        // Latvian
	LangLT        // Lithuanian
	LangML        // Macedonian
	LangNO        // Norwegian
	LangPL        // Polish
	LangPT        // Portuguese
	LangRO        // Romanian
	LangRU        // Russian
	LangSR        // Serbian
	LangSRL       // Serbian Latin
	LangSK        // Slovak
	LangSL        // Slovenian
	LangES        // Spanish
	LangSE        // Swedish
	LangTH        // Thai
	LangTR        // Turkish
	LangUKR       // Ukrainian
	LangVI        // Vietnamese
	LangIT        // Italian
)

func Languages

func Languages(codes string) []Lang

Languages transforms comma separatet list of language codes to Lang values array

func (Lang) Code

func (l Lang) Code() string

func (Lang) Name

func (l Lang) Name() string

func (*Lang) Parse

func (l *Lang) Parse(code string)

Parse converts language code to Lang value

func (Lang) String

func (l Lang) String() string

type Market

type Market struct {
	ID            int               `xml:"id,attr" json:"id"`
	LineID        int               `json:"lineID"`
	Specifiers    map[string]string `json:"sepcifiers,omitempty"`
	Status        MarketStatus      `xml:"status,attr,omitempty" json:"status,omitempty"`
	CashoutStatus *CashoutStatus    `xml:"cashout_status,attr,omitempty" json:"cashoutStatus,omitempty"`
	// If present, this is set to 1, which states that this is the most balanced
	// or recommended market line. This setting makes most sense for markets where
	// multiple lines are provided (e.g. the Totals market).
	Favourite *bool     `xml:"favourite,attr,omitempty" json:"favourite,omitempty"`
	Outcomes  []Outcome `xml:"outcome,omitempty" json:"outcome,omitempty"`
	// Timestamp in UTC when to betstop this market. Typically used for outrights
	// and typically is the start-time of the event the market refers to.
	NextBetstop *int `json:"nextBetstop,omitempty"`
}

Market describes the odds updates for a particular market. Betradar Unified Odds utilizes markets and market lines. Each market is a bet type identified with a unique ID and within a market, multiple different lines are often provided. Each of these lines is uniquely identified by additional specifiers (e.g. Total Goals 2.5 is the same market as Total Goals 1.5, but it is two different market lines. The market ID for both are the same, but the first one has a specifier ((goals=2.5)) and the other one has a specifier ((goals=1.5)) that uniquely identifies them). LineID is hash of specifier field used to uniquely identify lines in one market. One market line is uniquely identified by market id and line id.

func (*Market) UnmarshalXML

func (m *Market) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

Custom unmarshaling reasons:

  • To cover the case that: 'The default value is active if status is not present.'
  • To convert Specifiers and ExtendedSpecifiers fileds which are lists of key value attributes encoded in string to the map.
  • To calculate LineID; market line is uniquely identified by both market id and line id

func (Market) VariantSpecifier

func (m Market) VariantSpecifier() string

type MarketAttribute

type MarketAttribute struct {
	Name        string `xml:"name,attr" json:"name,omitempty"`
	Description string `xml:"description,attr" json:"description,omitempty"`
}

type MarketDescription

type MarketDescription struct {
	ID                     int               `xml:"id,attr" json:"id"`
	VariantID              int               `json:"variantID,omitempty"`
	Name                   string            `xml:"name,attr" json:"name,omitempty"`
	Description            string            `xml:"description,attr,omitempty" json:"description,omitempty"`
	IncludesOutcomesOfType string            `xml:"includes_outcomes_of_type,attr,omitempty" json:"includesOutcomesOfType,omitempty"`
	Variant                string            `xml:"variant,attr,omitempty" json:"variant,omitempty"`
	OutcomeType            OutcomeType       `json:"outcomeType,omitempty"`
	Groups                 []string          `json:"groups,omitempty"`
	Outcomes               []MarketOutcome   `xml:"outcomes>outcome,omitempty" json:"outcomes,omitempty"`
	Specifiers             []MarketSpecifier `xml:"specifiers>specifier,omitempty" json:"specifiers,omitempty"`
	Attributes             []MarketAttribute `xml:"attributes>attribute,omitempty" json:"attributes,omitempty"`
}

func (*MarketDescription) UnmarshalXML

func (t *MarketDescription) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type MarketDescriptions

type MarketDescriptions []MarketDescription

func (MarketDescriptions) Find

func (MarketDescriptions) Groups

func (md MarketDescriptions) Groups() map[string][]int

type MarketMetadata

type MarketMetadata struct {
	NextBetstop *int `xml:"next_betstop,attr,omitempty" json:"nextBetstop,omitempty"`
}

type MarketOutcome

type MarketOutcome struct {
	ID          int    `json:"id"`
	Name        string `xml:"name,attr" json:"name,omitempty"`
	Description string `xml:"description,attr,omitempty" json:"description,omitempty"`
}

func (*MarketOutcome) UnmarshalXML

func (t *MarketOutcome) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type MarketSpecifier

type MarketSpecifier struct {
	Type        SpecifierType `json:"type"`
	Name        string        `xml:"name,attr" json:"name,omitempty"`
	Description string        `xml:"description,attr,omitempty" json:"description,omitempty"`
}

func (*MarketSpecifier) UnmarshalXML

func (t *MarketSpecifier) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type MarketStatus

type MarketStatus int8

The default value is active if status is not present.

const (

	// Odds are provided and you can accept bets on the market.
	MarketStatusActive MarketStatus = 1
	// Odds continue to be provided but you should not accept bets on the market
	// for a short time (e.g. from right before a goal and until the goal has been
	// observed/confirmed).
	MarketStatusSuspended MarketStatus = -1
	// Odds are no longer provided for this market. A market can go back to Active
	// again i.e.: A total 3.5 market is deactivated since 0.5, 1.5 or 2.5 is the
	// most balanced market. However, if a goal is scored, then the 3.5 market
	// becomes the most balanced again, changing status to active. There are
	// numerous other reasons for this change as well, and it happens on a regular
	// basis.
	MarketStatusInactive MarketStatus = 0

	// Not a real market status. This status is normally seen under recovery, and
	// is a signal that the producer that sends this message is no longer sending
	// odds for this market. Odds will come from another producer going forward
	// (and might already have started coming from the new producer). Handed over
	// is also sent by the prematch producer when the Live Odds producer takes
	// over a market. If you have not received the live odds change yet, the
	// market should be suspended, otherwise the message can be ignored. If the
	// live odds change does not eventually appear, the market should likely be
	// deactivated.
	MarketStatusHandedOver MarketStatus = -2
	// Bet Settlement messages have been sent for this market, no further odds
	// will be provided. However, it should be noted that in rare cases (error
	// conditions), a settled market may be moved to cancelled by a bet_cancel
	// message.
	MarketStatusSettled MarketStatus = -3
	// This market has been cancelled. No further odds will be provided for this
	// market. This state is only seen during recovery for matches where the
	// system has sent out a cancellation message for that particular market.
	MarketStatusCancelled MarketStatus = -4
)

Reference: https://docs.betradar.com/display/BD/UOF+-+Market+status

func (*MarketStatus) PtrVal

func (m *MarketStatus) PtrVal() *int8

func (MarketStatus) Val

func (m MarketStatus) Val() int8

type MarketsRsp

type MarketsRsp struct {
	Markets MarketDescriptions `xml:"market,omitempty" json:"markets,omitempty"`
}

Markets betradar api response

type Message

type Message struct {
	Header `json:",inline"`
	Raw    []byte `json:"-"`
	Body   `json:",inline"`
}

func NewAPIMessage

func NewAPIMessage(lang Lang, typ MessageType, body []byte) (*Message, error)

func NewCompetitorMessage

func NewCompetitorMessage(lang Lang, competitor *CompetitorPlayer, requestedAt int) *Message

func NewConnnectionMessage

func NewConnnectionMessage(status ConnectionStatus) *Message

func NewFixtureMessage

func NewFixtureMessage(lang Lang, x Fixture, requestedAt int) *Message

func NewMarketsMessage

func NewMarketsMessage(lang Lang, ms MarketDescriptions, requestedAt int) *Message

func NewPlayerMessage

func NewPlayerMessage(lang Lang, player *Player, requestedAt int) *Message

func NewProducersChangeMessage

func NewProducersChangeMessage(pc ProducersChange) *Message

func NewQueueMessage

func NewQueueMessage(routingKey string, body []byte) (*Message, error)

func NewSummaryMessage

func NewSummaryMessage(lang Lang, s Summary, requestedAt int) *Message

func NewTournamentMessage

func NewTournamentMessage(lang Lang, x FixtureTournament, requestedAt int) *Message

func (*Message) Is

func (m *Message) Is(mt MessageType) bool

func (Message) Marshal

func (m Message) Marshal() []byte

func (Message) MarshalPretty

func (m Message) MarshalPretty() []byte

func (*Message) NewFixtureMessage

func (m *Message) NewFixtureMessage(lang Lang, f Fixture) *Message

func (*Message) UID

func (m *Message) UID() int

UID unique id for statefull messages Combines id of the content and language.

func (*Message) Unmarshal

func (m *Message) Unmarshal(buf []byte) error

type MessageKind

type MessageKind int8
const (
	MessageKindEvent MessageKind = iota
	MessageKindLexicon
	MessageKindSystem
)

type MessagePriority

type MessagePriority int8
const (
	MessagePriorityLow MessagePriority = iota
	MessagePriorityHigh
)

func (*MessagePriority) Parse

func (p *MessagePriority) Parse(priority string)

type MessageScope

type MessageScope int8
const (
	MessageScopePrematch MessageScope = iota
	MessageScopeLive
	MessageScopePrematchAndLive
	MessageScopeVirtuals
	MessageScopeSystem // system scope messages, like alive, product down
)

Scope of the message

func (*MessageScope) Parse

func (s *MessageScope) Parse(prematchInterest, liveInterest string)

type MessageType

type MessageType int8
const (
	MessageTypeOddsChange MessageType = iota
	MessageTypeFixtureChange
	MessageTypeBetCancel
	MessageTypeBetSettlement
	MessageTypeBetStop
	MessageTypeRollbackBetSettlement
	MessageTypeRollbackBetCancel
)

event related message types

const (
	MessageTypeFixture MessageType = iota + 32
	MessageTypeMarkets
	MessageTypePlayer
	MessageTypeCompetitor
	MessageTypeTournament
	MessageTypeSummary
)

api message types

const (
	MessageTypeAlive MessageType = iota + 64
	MessageTypeSnapshotComplete
	MessageTypeConnection
	MessageTypeProducersChange
)

system message types

const (
	MessageTypeUnknown MessageType = -1
)

func (MessageType) Kind

func (m MessageType) Kind() MessageKind

func (*MessageType) Parse

func (m *MessageType) Parse(name string)

func (MessageType) String

func (m MessageType) String() string

type OddsChange

type OddsChange struct {
	EventID  int `json:"eventID"`
	EventURN URN `xml:"event_id,attr" json:"eventURN"`
	// Specifies which producer generated these odds. At any given point in time
	// there should only be one product generating odds for a particular event.
	Producer  Producer `xml:"product,attr" json:"producer"`
	Timestamp int      `xml:"timestamp,attr" json:"timestamp"`
	Markets   []Market `json:"market,omitempty"`
	// values in range 0-6   /v1/descriptions/betting_status.xml
	BettingStatus *int `json:"bettingStatus,omitempty"`
	// values in range 0-87  /v1/descriptions/betstop_reasons.xml
	BetstopReason    *int              `json:"betstopReason,omitempty"`
	OddsChangeReason *int              `xml:"odds_change_reason,attr,omitempty" json:"oddsChangeReason,omitempty"` // May be one of 1
	EventStatus      *SportEventStatus `xml:"sport_event_status,omitempty" json:"sportEventStatus,omitempty"`

	OddsGenerationProperties *OddsGenerationProperties `xml:"odds_generation_properties,omitempty" json:"oddsGenerationProperties,omitempty"`
	RequestID                *int                      `xml:"request_id,attr,omitempty" json:"requestID,omitempty"`
}

OddsChange messages are sent whenever Betradar has new odds for some markets for a match. Odds changes can include a subset of all markets; if so, markets not reported remain unchanged. All outcomes possible within a market are reported. Reference: https://docs.betradar.com/display/BD/UOF+-+Odds+change

func (*OddsChange) Competitors

func (o *OddsChange) Competitors() []int

Competitors collects all competitors from outcomes

func (*OddsChange) EachCompetitor

func (o *OddsChange) EachCompetitor(handler func(int))

func (*OddsChange) EachPlayer

func (o *OddsChange) EachPlayer(handler func(int))

func (*OddsChange) EachVariantMarket

func (o *OddsChange) EachVariantMarket(handler func(int, string))

func (*OddsChange) UnmarshalXML

func (o *OddsChange) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML

type OddsGenerationProperties

type OddsGenerationProperties struct {
	ExpectedTotals    *float64 `xml:"expected_totals,attr,omitempty" json:"expectedTotals,omitempty"`
	ExpectedSupremacy *float64 `xml:"expected_supremacy,attr,omitempty" json:"expectedSupremacy,omitempty"`
}

Provided by the prematch odds producer only, and contains a few key-parameters that can be used in a client’s own special odds model, or even offer spread betting bets based on it.

type Outcome

type Outcome struct {
	ID            int      `json:"id"`
	PlayerID      int      `json:"playerID"`
	Competitors   []int    `json:"competitors"`
	Odds          *float64 `xml:"odds,attr,omitempty" json:"odds,omitempty"`
	Probabilities *float64 `xml:"probabilities,attr,omitempty" json:"probabilities,omitempty"`
	Active        *bool    `xml:"active,attr,omitempty" json:"active,omitempty"`
	Team          *Team    `xml:"team,attr,omitempty" json:"team,omitempty"`
}

func (*Outcome) UnmarshalXML

func (t *Outcome) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type OutcomeResult

type OutcomeResult int8
const (
	OutcomeResultUnknown         OutcomeResult = 0
	OutcomeResultLose            OutcomeResult = 1
	OutcomeResultWin             OutcomeResult = 2
	OutcomeResultVoid            OutcomeResult = 3
	OutcomeResultHalfLose        OutcomeResult = 4
	OutcomeResultHalfWin         OutcomeResult = 5
	OutcomeResultWinWithDeadHead OutcomeResult = 6
)

type OutcomeType

type OutcomeType int8
const (
	OutcomeTypeDefault OutcomeType = iota
	OutcomeTypePlayer
	OutcomeTypeCompetitor
	OutcomeTypeCompetitors
	OutcomeTypeFreeText
	OutcomeTypeUnknown OutcomeType = -1
)

type PeriodScore

type PeriodScore struct {
	// The match status of an event gives an indication of which context the
	// current match is in. Complete list available at:
	// /v1/descriptions/en/match_status.xml
	MatchStatusCode *int `xml:"match_status_code,attr" json:"matchStatusCode"`
	// Indicates what regular period this is
	Number *int `xml:"number,attr" json:"number"`
	// The number of points/goals/games the competitor designated as "home" has
	// scored for this period.
	HomeScore *int `xml:"home_score,attr" json:"homeScore"`
	// The number of points/goals/games the competitor designated as "away" has
	// scored for this period.
	AwayScore *int `xml:"away_score,attr" json:"awayScore"`
}

type Player

type Player struct {
	ID           int       `xml:"id,attr" json:"id"`
	Type         string    `xml:"type,attr,omitempty" json:"type,omitempty"`
	DateOfBirth  time.Time `xml:"date_of_birth,attr,omitempty" json:"dateOfBirth,omitempty"`
	Nationality  string    `xml:"nationality,attr,omitempty" json:"nationality,omitempty"`
	CountryCode  string    `xml:"country_code,attr,omitempty" json:"countryCode,omitempty"`
	Height       int       `xml:"height,attr,omitempty" json:"height,omitempty"`
	Weight       int       `xml:"weight,attr,omitempty" json:"weight,omitempty"`
	JerseyNumber int       `xml:"jersey_number,attr,omitempty" json:"jerseyNumber,omitempty"`
	Name         string    `xml:"name,attr,omitempty" json:"name,omitempty"`
	FullName     string    `xml:"full_name,attr,omitempty" json:"fullName,omitempty"`
	Nickname     string    `xml:"nickname,attr,omitempty" json:"nickname,omitempty"`
	Gender       Gender    `xml:"gender,attr,omitempty" json:"gender,omitempty"`
}

func (*Player) UnmarshalXML

func (t *Player) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type PlayerProfile

type PlayerProfile struct {
	Player      Player    `xml:"player" json:"player"`
	GeneratedAt time.Time `xml:"generated_at,attr,omitempty" json:"generatedAt,omitempty"`
}

type Producer

type Producer int8
const (
	ProducerUnknown  Producer = -1
	ProducerDefault  Producer = 0
	ProducerLiveOdds Producer = 1
	ProducerPrematch Producer = 3
)

func VirtualProducers

func VirtualProducers() []Producer

func (Producer) Code

func (p Producer) Code() string

func (Producer) Description

func (p Producer) Description() string

func (Producer) Name

func (p Producer) Name() string

func (Producer) Prematch

func (p Producer) Prematch() bool

Prematch means that producer markets are valid only for betting before the match starts.

func (Producer) RecoveryWindow

func (p Producer) RecoveryWindow() int

RecoveryWindow in milliseconds

func (Producer) Scope

func (p Producer) Scope() string

func (Producer) Sports

func (p Producer) Sports() bool

func (Producer) String

func (p Producer) String() string

func (Producer) Virtuals

func (p Producer) Virtuals() bool

type ProducerChange

type ProducerChange struct {
	Producer   Producer       `json:"producer,omitempty"`
	Status     ProducerStatus `json:"status,omitempty"`
	RecoveryID int            `json:"recoveryID,omitempty"`
	Timestamp  int            `json:"timestamp,omitempty"`
}

type ProducerStatus

type ProducerStatus int8
const (
	ProducerStatusDown       ProducerStatus = -1
	ProducerStatusActive     ProducerStatus = 1
	ProducerStatusInRecovery ProducerStatus = 2
)

type ProducersChange

type ProducersChange []ProducerChange

func (*ProducersChange) Add

func (p *ProducersChange) Add(producer Producer, timestamp int)

func (*ProducersChange) AddAll

func (p *ProducersChange) AddAll(producers []Producer, timestamp int)

type ProductInfo

type ProductInfo struct {
	Streaming            []StreamingChannel `xml:"streaming>channel,omitempty" json:"streaming,omitempty"`
	IsInLiveScore        string             `xml:"is_in_live_score,omitempty" json:"isInLiveScore,omitempty"`
	IsInHostedStatistics string             `xml:"is_in_hosted_statistics,omitempty" json:"isInHostedStatistics,omitempty"`
	IsInLiveCenterSoccer string             `xml:"is_in_live_center_soccer,omitempty" json:"isInLiveCenterSoccer,omitempty"`
	IsAutoTraded         string             `xml:"is_auto_traded,omitempty" json:"isAutoTraded,omitempty"`
	Links                []ProductInfoLink  `xml:"links>link,omitempty" json:"links,omitempty"`
}
type ProductInfoLink struct {
	Name string `xml:"name,attr" json:"name"`
	Ref  string `xml:"ref,attr" json:"ref"`
}

type Result

type Result struct {
	MatchStatusCode *int `xml:"match_status_code,attr" json:"matchStatusCode"`
	HomeScore       *int `xml:"home_score,attr" json:"homeScore"`
	AwayScore       *int `xml:"away_score,attr" json:"awayScore"`
}

type RollbackBetCancel

type RollbackBetCancel struct {
	EventID   int               `json:"eventID"`
	EventURN  URN               `xml:"event_id,attr" json:"eventURN"`
	Producer  Producer          `xml:"product,attr" json:"producer"`
	Timestamp int               `xml:"timestamp,attr" json:"timestamp"`
	RequestID *int              `xml:"request_id,attr,omitempty" json:"requestID,omitempty"`
	StartTime *int              `xml:"start_time,attr,omitempty" json:"startTime,omitempty"`
	EndTime   *int              `xml:"end_time,attr,omitempty" json:"endTime,omitempty"`
	Markets   []BetCancelMarket `xml:"market" json:"market"`
}

A Rollback_bet_cancel message is sent when a previous bet cancel should be undone (if possible). This may happen, for example, if a Betradar operator mistakenly cancels the wrong market (resulting in a bet_cancel being sent) during the game; before realizing the mistake.

func (*RollbackBetCancel) UnmarshalXML

func (t *RollbackBetCancel) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML

type RollbackBetSettlement

type RollbackBetSettlement struct {
	EventID   int               `json:"eventID"`
	EventURN  URN               `xml:"event_id,attr" json:"eventURN"`
	Producer  Producer          `xml:"product,attr" json:"producer"`
	Timestamp int               `xml:"timestamp,attr" json:"timestamp"`
	RequestID *int              `xml:"request_id,attr,omitempty" json:"requestID,omitempty"`
	Markets   []BetCancelMarket `xml:"market" json:"market"`
}

func (*RollbackBetSettlement) UnmarshalXML

func (t *RollbackBetSettlement) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type Round

type Round struct {
	ID                  int    `xml:"betradar_id,attr,omitempty" json:"id,omitempty"`
	Type                string `xml:"type,attr,omitempty" json:"type,omitempty"`
	Number              int    `xml:"number,attr,omitempty" json:"number,omitempty"`
	Name                string `xml:"name,attr,omitempty" json:"name,omitempty"`
	GroupLongName       string `xml:"group_long_name,attr,omitempty" json:"groupLongName,omitempty"`
	Group               string `xml:"group,attr,omitempty" json:"group,omitempty"`
	GroupID             string `xml:"group_id,attr,omitempty" json:"groupID,omitempty"`
	CupRoundMatches     int    `xml:"cup_round_matches,attr,omitempty" json:"cupRoundMatches,omitempty"`
	CupRoundMatchNumber int    `xml:"cup_round_match_number,attr,omitempty" json:"cupRoundMatchNumber,omitempty"`
	OtherMatchID        string `xml:"other_match_id,attr,omitempty" json:"otherMatchID,omitempty"`
}

type Season

type Season struct {
	ID        int    `json:"id"`
	StartDate string `xml:"start_date,attr" json:"startDate"`
	EndDate   string `xml:"end_date,attr" json:"endDate"`
	StartTime string `xml:"start_time,attr,omitempty" json:"startTime,omitempty"`
	EndTime   string `xml:"end_time,attr,omitempty" json:"endTime,omitempty"`
	Year      string `xml:"year,attr,omitempty" json:"year,omitempty"`
	Name      string `xml:"name,attr" json:"name"`
}

func (*Season) UnmarshalXML

func (t *Season) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type SnapshotComplete

type SnapshotComplete struct {
	Producer  Producer `xml:"product,attr" json:"producer"`
	Timestamp int      `xml:"timestamp,attr" json:"timestamp"`
	RequestID int      `xml:"request_id,attr" json:"requestID"`
}

SnapshotComplete message indicates that all messages relating to an initiate request for odds from the RESTful API have been processed. The request_id parameter returned is the request_id that was specified in the initiate_request POST to the API. If no request_id parameter was specified in the original request, no request_id parameter is present. It is highly recommended to set a request_id to some number. Reference: https://docs.betradar.com/display/BD/UOF+-+Snapshot+complete

type SpecifierType

type SpecifierType int8
const (
	SpecifierTypeString SpecifierType = iota
	SpecifierTypeInteger
	SpecifierTypeDecimal
	SpecifierTypeVariableText
	SpecifierTypeUnknown SpecifierType = -1
)

type Sport

type Sport struct {
	ID   int    `json:"id"`
	Name string `xml:"name,attr" json:"name"`
}

func (*Sport) UnmarshalXML

func (t *Sport) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type SportEvent

type SportEvent struct {
	ID           string    `xml:"id,attr,omitempty" json:"id,omitempty"`
	Name         string    `xml:"name,attr,omitempty" json:"name,omitempty"`
	Type         string    `xml:"type,attr,omitempty" json:"type,omitempty"`
	Scheduled    time.Time `xml:"scheduled,attr,omitempty" json:"scheduled,omitempty"`
	ScheduledEnd time.Time `xml:"scheduled_end,attr,omitempty" json:"scheduled_end,omitempty"`
}

SportEvent covers information about scheduled races in a stage For VHC and VDR information is in vdr/vhc:stage:<int> fixture with type="parent"

type SportEventStatus

type SportEventStatus struct {
	// High-level generic status of the match.
	Status EventStatus `xml:"status,attr" json:"status"`
	// Does Betradar have a scout watching the game.
	Reporting *EventReporting `xml:"reporting,attr,omitempty" json:"reporting,omitempty"`
	// Current score for the home team.
	HomeScore *int `xml:"home_score,attr,omitempty" json:"homeScore,omitempty"`
	// Current score for the away team.
	AwayScore *int `xml:"away_score,attr,omitempty" json:"awayScore,omitempty"`
	// Sports-specific integer code the represents the live match status (first period, 2nd break, etc.).
	MatchStatus *int `xml:"match_status,attr" json:"matchStatus"`
	// The player who has the serve at that moment.
	CurrentServer *Team `xml:"current_server,attr,omitempty" json:"currentServer,omitempty"`
	// The point score of the "home" player. The score will be 50 if the "home"
	// player has advantage. This attribute is also used for the tiebreak score
	// when the game is in a tiebreak.
	// (15 30 40 50)
	HomeGamescore *int `xml:"home_gamescore,attr,omitempty" json:"homeGamescore,omitempty"`
	// The point score of the "away" player. The score will be 50 if the "away"
	// player has advantage. This attribute is also used for the tiebreak score
	// when the game is in a tiebreak.
	AwayGamescore *int `xml:"away_gamescore,attr,omitempty" json:"awayGamescore,omitempty"`

	HomePenaltyScore   *int    `xml:"home_penalty_score,attr,omitempty" json:"homePenaltyScore,omitempty"`
	AwayPenaltyScore   *int    `xml:"away_penalty_score,attr,omitempty" json:"awayPenaltyScore,omitempty"`
	HomeLegscore       *int    `xml:"home_legscore,attr,omitempty" json:"homeLegscore,omitempty"`
	AwayLegscore       *int    `xml:"away_legscore,attr,omitempty" json:"awayLegscore,omitempty"`
	ExpediteMode       *bool   `xml:"expedite_mode,attr,omitempty" json:"expediteMode,omitempty"`
	Tiebreak           *bool   `xml:"tiebreak,attr,omitempty" json:"tiebreak,omitempty"`
	HomeSuspend        *int    `xml:"home_suspend,attr,omitempty" json:"homeSuspend,omitempty"`
	AwaySuspend        *int    `xml:"away_suspend,attr,omitempty" json:"awaySuspend,omitempty"`
	Balls              *int    `xml:"balls,attr,omitempty" json:"balls,omitempty"`
	Strikes            *int    `xml:"strikes,attr,omitempty" json:"strikes,omitempty"`
	Outs               *int    `xml:"outs,attr,omitempty" json:"outs,omitempty"`
	Bases              *string `xml:"bases,attr,omitempty" json:"bases,omitempty"`
	HomeBatter         *int    `xml:"home_batter,attr,omitempty" json:"homeBatter,omitempty"`
	AwayBatter         *int    `xml:"away_batter,attr,omitempty" json:"awayBatter,omitempty"`
	Possession         *int    `xml:"possession,attr,omitempty" json:"possession,omitempty"`
	Position           *int    `xml:"position,attr,omitempty" json:"position,omitempty"`
	Try                *int    `xml:"try,attr,omitempty" json:"try,omitempty"`
	Yards              *int    `xml:"yards,attr,omitempty" json:"yards,omitempty"`
	Throw              *int    `xml:"throw,attr,omitempty" json:"throw,omitempty"`
	Visit              *int    `xml:"visit,attr,omitempty" json:"visit,omitempty"`
	RemainingReds      *int    `xml:"remaining_reds,attr,omitempty" json:"remainingReds,omitempty"`
	Delivery           *int    `xml:"delivery,attr,omitempty" json:"delivery,omitempty"`
	HomeRemainingBowls *int    `xml:"home_remaining_bowls,attr,omitempty" json:"homeRemainingBowls,omitempty"`
	AwayRemainingBowls *int    `xml:"away_remaining_bowls,attr,omitempty" json:"awayRemainingBowls,omitempty"`
	CurrentEnd         *int    `xml:"current_end,attr,omitempty" json:"currentEnd,omitempty"`
	Innings            *int    `xml:"innings,attr,omitempty" json:"innings,omitempty"`
	Over               *int    `xml:"over,attr,omitempty" json:"over,omitempty"`
	HomePenaltyRuns    *int    `xml:"home_penalty_runs,attr,omitempty" json:"homePenaltyRuns,omitempty"`
	AwayPenaltyRuns    *int    `xml:"away_penalty_runs,attr,omitempty" json:"awayPenaltyRuns,omitempty"`
	HomeDismissals     *int    `xml:"home_dismissals,attr,omitempty" json:"homeDismissals,omitempty"`
	AwayDismissals     *int    `xml:"away_dismissals,attr,omitempty" json:"awayDismissals,omitempty"`
	CurrentCtTeam      *Team   `xml:"current_ct_team,attr,omitempty" json:"currentCtTeam,omitempty"`

	Clock        *Clock        `xml:"clock,omitempty" json:"clock,omitempty"`
	PeriodScores []PeriodScore `xml:"period_scores>period_score,omitempty" json:"periodScores,omitempty"`
	Results      []Result      `xml:"results>result,omitempty" json:"results,omitempty"`
	Statistics   *Statistics   `xml:"statistics,omitempty" json:"statistics,omitempty"`
}

The element "sport_event_status" is provided in the odds_change message. Status is the only required attribute for this element, and this attribute describes the current status of the sport-event itself (not started, live, ended, closed). Additional attributes are live-only attributes, and only provided while the match is live; additionally, which attributes are provided depends on the sport. Reference: https://docs.betradar.com/display/BD/UOF+-+Sport+event+status

type Statistics

type Statistics struct {
	YellowCards    *StatisticsScore `xml:"yellow_cards,omitempty" json:"yellowCards,omitempty"`
	RedCards       *StatisticsScore `xml:"red_cards,omitempty" json:"redCards,omitempty"`
	YellowRedCards *StatisticsScore `xml:"yellow_red_cards,omitempty" json:"yellowRedCards,omitempty"`
	Corners        *StatisticsScore `xml:"corners,omitempty" json:"corners,omitempty"`
}

type StatisticsScore

type StatisticsScore struct {
	Home int `xml:"home,attr" json:"home"`
	Away int `xml:"away,attr" json:"away"`
}

type StreamingChannel

type StreamingChannel struct {
	ID   int    `xml:"id,attr" json:"id"`
	Name string `xml:"name,attr" json:"name"`
}

type Summary

type Summary struct {
	SportEvent         Fixture             `xml:"sport_event" json:"sportEvent"`
	GeneratedAt        time.Time           `xml:"generated_at,attr,omitempty" json:"generatedAt,omitempty"`
	SummaryEventStatus *SummaryEventStatus `xml:"sport_event_status,omitempty" json:"summaryEventStatus,omitempty"`
}

type SummaryEventStatus

type SummaryEventStatus struct {
	Status       string        `xml:"status,attr" json:"status"`
	MatchStatus  string        `xml:"match_status,attr" json:"matchStatus"`
	HomeScore    *int          `xml:"home_score,attr,omitempty" json:"homeScore,omitempty"`
	AwayScore    *int          `xml:"away_score,attr,omitempty" json:"awayScore,omitempty"`
	PeriodScores []PeriodScore `xml:"period_scores>period_score,omitempty" json:"periodScores,omitempty"`
}

slici na sport_event_status ali statusi nisu int nego string

type Team

type Team int8
const (
	TeamHome Team = 1
	TeamAway Team = 2
)

func (*Team) PtrVal

func (t *Team) PtrVal() *int8

type Tournament

type Tournament struct {
	ID   int    `json:"id"`
	Name string `xml:"name,attr" json:"name"`
}

type TvChannel

type TvChannel struct {
	Name string `xml:"name,attr" json:"name"`
}

type URN

type URN string

func NewEventURN

func NewEventURN(eventID int) URN

func (URN) Empty

func (u URN) Empty() bool

func (URN) EventID

func (u URN) EventID() int

EventID tries to generate unique id for all types of events. Most comon are those with prefix sr:match for them we reserve positive id-s. All others got range in negative ids. Reference: https://docs.betradar.com/display/BD/MG+-+Entities

http://sdk.sportradar.com/content/unifiedfeedsdk/net/doc/html/e1f73019-73cd-c9f8-0d58-7fe25800abf2.htm

List of currently existing event types is taken from the combo box in the integration control page. From method "Fixture for a specified sport event". !!! Refactored to Producer + EventID in producer.

func (URN) ID

func (u URN) ID() int

func (URN) IsTournament

func (u URN) IsTournament() bool

func (*URN) Parse

func (u *URN) Parse(s string)

func (URN) Producer

func (u URN) Producer() Producer

func (URN) String

func (u URN) String() string

type Venue

type Venue struct {
	ID             int    `json:"id"`
	Name           string `xml:"name,attr" json:"name"`
	Capacity       int    `xml:"capacity,attr,omitempty" json:"capacity,omitempty"`
	CityName       string `xml:"city_name,attr,omitempty" json:"cityName,omitempty"`
	CountryName    string `xml:"country_name,attr,omitempty" json:"countryName,omitempty"`
	CountryCode    string `xml:"country_code,attr,omitempty" json:"countryCode,omitempty"`
	MapCoordinates string `xml:"map_coordinates,attr,omitempty" json:"mapCoordinates,omitempty"`
}

func (*Venue) UnmarshalXML

func (t *Venue) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

Directories

Path Synopsis
Package api connects to the Unified Feed API interface
Package api connects to the Unified Feed API interface
cmd
You cannot create your own queues.
You cannot create your own queues.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL