0% found this document useful (0 votes)
125 views

OddsMatrix Feed API Documentation ENGLISH

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
125 views

OddsMatrix Feed API Documentation ENGLISH

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 136

OddsMatrix Feed API Documentation

Last updated on 06-08-2024


OddsMatrix Feed User's Guide 2
Introduction 3
XML - SDQL 4
XML example 12
JSON - SDQL 21
Client-Server Communication 25
Pull Subscription 26
Push Subscription 27
Sports Model Entities 29
Event 30
Participant 39
Stats And Scores 43
Event Info Types 53
Event Actions Types and Details Types 58
Event Participant Info Types and Detail Types 61
Betting 63
Betting Types 72
Market 73
Location 75
Property 78
Other entities 80
Translation 84
All Statuses Explained 85
Java Connector 88
C# Connector 91
Client-Server Communication Errors 94
Client integration test scenarios 95
Using Sports Model Data 104
Introduction
Welcome to the OddsMatrix Feed User Guide!
This user guide describes how a client can retrieve the Odds Matrix data. You need to understand:
The protocol specification: the requests and responses exchanged by client and server.
If you're using Java, we provide a client-side java-connector.
If you're using .NET, we provide a client-side c#-connector.
The OddsMatrix Sports Model entities (matches, tournaments/leagues, participants, odds, betting types). Also, part of the model, the betting types (and
outcome types) are described in the documents: BettingTypes and BettingTypes Explained. In addition, check the Bet Types page.
All the entities are explained in the Sports Model Entities section.
For frequently asked questions, please check Using Sports Model Data.

3
XML - SDQL

SDQL (short for Sports Data Query Language) is a language for retrieving sports data managed by the Sports Engine using XML
documents.

If you're not using one of the provided connectors, you have to use the Sports Data Query Language constructs in order to communicate
with the server.

The SDQL language consists of SDQL constructs. An SDQL construct is an XML document.

All SDQL XML documents have the following structure and content:

1 <?xml version="1.0" encoding="UTF-8"?>


2
3 <sdql>
4
5 <!-- SDQL construct goes here -->
6
7 </sdql>

Below, each of the top-level SDQL constructs is described.

sports-model-object
The sports-model-object SDQL construct contains the representation of a sports model object. The general format of this SDQL construct is:

1 <sportsModelObjectName id=”” property1=”” property2=”” .../>

Here is an example of sports-model-object SDQL construct for a betting offer (not all the properties are present):

1 <BettingOffer id="41"
2 providerId="3000388"
3 sourceId="4"
4 outcomeId="180"
5 bettingTypeId="4"
6 statusId="2"
7 isLay="false"
8 isLive="true"
9 odds="51.0"
10 multiplicity="0"
11 slotNum="1"
12 lastChangedTime="2009-10-15 11:41:57.0" />

Please note that all the properties of the type date are expressed in GMT.

sports-model-object-change
The sports-model-object-change SDQL construct is used to communicate that a sports model object was created, updated or deleted.

The general format of the SDQL construct which represents a created sports model object is:

1 <sportsModelObjectName type=”create” id=”” property1=”” property2=”” .../>

4
The general format of the SDQL construct which represents an updated sports model object is:

1 <sportsModelObjectName type=”update” id=”” changedProperty1=”” changedProperty2=”” ... />

The general format of the SDQL construct which represents a deleted sports model object is:

1 <sportsModelObjectName type=”delete” id=””/>

A created betting offer looks like:

1 <BettingOffer type=”create” id="41"


2 providerId="3000388"
3 sourceId="4" outcomeId="180"
4 bettingTypeId="4" statusId="2"
5 isLay="false"
6 isLive="true" odds="51.0"
7 multiplicity="0" slotNum="1"
8 lastChangedTime="2009-10-15 11:41:57.0" />

An updated betting offer looks like:

1 <BettingOffer type=”update” id="41" odds="53.0"/>

A deleted betting offer looks like:

1 <BettingOffer type=”delete” id="41"/>

subscribe-request
The subscribe-request SDQL construct is used by the client to create a new subscription with the Sports Engine.

Node Name Node Type Description

subscriptionSpecificationName Attribute (String) Specifies the subscription specification


name.

Example:

1 <SubscribeRequest subscriptionSpecificationName="test"/>

subscribe-response
The subscribe-response SDQL construct is a response to a subscribe-request.

Node Name Node Type Description

subscriptionId Attribute (String) Contains a unique identifier for the new


subscription. All subsequent subscription
SDQL constructs will refer to the new
subscription by this subscriptionId.

subscriptionChecksum Attribute (String) A string that allows the server to check if


the given subscription has changed (used
by the resume feature)

Example:

5
1 <SubscribeResponse subscriptionId="8cf74ac6-5702-4421-9735-ec05dd85e27d"
2 subscriptionChecksum="BCB7687137CB458B1A3F1D00171E7F64"/>

initial-data

Initial data dump is sent by the Sports Engine to the client in batches. The initial-data SDQL construct represents a batch of the initial data
dump.

Node Name Node Type Description

batchId Attribute (int) Uniquely identifies the initial data batch.

batchesLeft Attribute (int) Specifies how many batches will be sent until the end of the initial data dump.

dumpComplete Attribute (boolean) Specifies whether the initial data dump is complete or not.

entities Element Entities within the initial data batch.

Example:

1 <InitialData batchId=”123” batchesLeft=”20” dumpComplete=”false”>


2
3 <entities>
4
5 <!-- sports-model-object constructs -->
6
7 </entities>
8
9 </InitialData>

get-next-initial-data-request
The client sends a get-next-initial-data-request SDQL construct when he wants to retrieve the next initial data dump batch.

Node Node Description


Name Type

subscripti Attribute The id received by client with the subscribe-response SDQL construct.
onId (String)

Example:

1 <GetNextInitialDataRequest subscriptionId=”8cf74ac6-5702-4421-9735-ec05dd85e27d”/>

get-next-initial-data-response
get-next-initial-data-response SDQL construct is the response to a get-next-initial-data-request and it encloses an initial-data SDQL
construct.

Node Node Type Description


Name

InitialData Element Batch of initial dump.

Example:

1 <GetNextInitialDataResponse>

6
2
3 <InitialData batchId=”123” batchesLeft=”20” dumpComplete=”false”>
4
5 <entities>
6
7 <!-- sports-model-object constructs -->
8
9 </entities>
10
11 </InitialData>
12
13 </GetNextInitialDataResponse>

update-data

The update-data SDQL construct contains 1..n updates on the Sport Data entities.

Node Name Node Type Description

batchId Attribute (long) Specifies the batch id.

batchUuid Attribute (String) Batch identifier unique across all the


SportsEngine

sports-model-object-change Elements The sports-model-object-change elements.

createdTime Attribute (Date) Specifies when the batch was created.

Note that the order of the sports-model-object-change elements is important. They must be applied to the subscription state in
the same order as they appear in the update-data.

Example:

1 <UpdateData batchId="12" batchUuid="41730026382|2" createdTime="2010-03-18 09:05:40.665">


2
3 <BettingOffer type=”update” id=”423” odds=”53.0”/> (old value 43.0)
4
5 <BettingOffer type=”delete” id=”423”/>
6
7 <!-- other sports-model-object-change elements will go here -->
8
9 </UpdateData>
10
11 <UpdateData batchId="14" batchUuid="41730026012|0" createdTime="2010-03-18 09:05:40.665">
12
13 <BettingOffer type=”create” id=”425” .../>
14
15 <!-- other sports-model-object-change elements will go here -->
16
17 </UpdateData>

7
Please note that the batchId(s) are not necessary consecutive. In the example above, the client will receive the batchId= 12 and
then batchId=14.

update-data-resume-request
The update-data-resume-request construct is sent by a client that wants to resume updates after some period of inactivity.

Node Name Node Type Description

subscriptionId Attribute (String) The ID received by client with the


subscribe-response SDQL construct.

subscriptionSpecificationName Attribute (String) Specifies the subscription specification


name.

subscriptionChecksum Attribute (String) The checksum received by client with the


subscribe-response SDQL construct.

sinceDate Attribute (String) Specifies the date from where server


should send changes. Expected date
format: yyyy-MM-dd HH:mm:ss.SSS ,
expected timezone: UTC.
To ensure no data loss, “sinceDate“
should be lower than disconnection time
(e.g. 1-2 min(s)).

Example:

1 <UpdateDataResumeSinceRequest subscriptionId="454f696d-7e2d-4f46-9611-576009de23b1"
2 subscriptionSpecificationName="your_subscription_name"
3 subscriptionChecksum="BCB7687137CB458B1A3F1D00171E7F64" sinceDate="2024-06-19 12:34:56.789" />

get-next-update-data-request

The client sends a get-next-update-data-request SDQL construct when he wants to retrieve the next updates.

Node Name Node Type Description

subscriptionId Attribute (String) The id received by client with the


subscribe-response SDQL construct.

Example:

1 <GetNextUpdateDataRequest subscriptionId=”454f696d-7e2d-4f46-9611-576009de23b1”/>

8
get-next-update-data-response
The get-next-update-data-response SDQL construct is the response to a get-next-update-data-request and it encloses none, one or more
update-data SDQL constructs.

Node Name Node Type Description

UpdateData Element update-data SDQL constructs.

Example:

1 <GetNextUpdateDataResponse>
2
3 <UpdateData batchId="12" batchUuid="41730026382|2" createdTime="2010-03-18 09:05:40.665">
4
5 <!-- sports-model-object-change elements will go here -->
6
7 </UpdateData>
8
9 <UpdateData batchId="13" batchUuid="41730026012|0" createdTime="2010-03-18 09:05:40.665">
10
11 <!-- sports-model-object-change elements will go here -->
12
13 </UpdateData>
14
15 <!-- Other update-data SDQL constructs will go here-->
16
17 </GetNextUpdateDataResponse>

unsubscribe-request
The unsubscribe-request SDQL construct is used by a client to unsubscribe a subscription.

Node Name Node Type Description

subscriptionId Attribute (String) The ID received by client with the


subscribe-response SDQL construct.

subscriptionSpecificationName Attribute (String) Specifies the subscription specification


name.

Example:

1 <UnsubscribeRequest subscriptionSpecificationName=”test”
2 subscriptionId=”454f696d-7e2d-4f46-9611-576009de23b1”/>

unsubscribe-response
The unsubscribe-response SDQL construct is a response to an unsubscribe-request.

Node Name Node Type Description

code Attribute (int) "0" indicates that the operation was successful.

9
"1" indicates that the operation was not successful.

message Attribute A human-readable message.


(String)

Example:

1 <UnsubscribeResponse code="0"
2 message=”Unsubscription was successful.”/>

ping-request
The ping-request SDQL construct is used by the Sports Engine to check if the TCP/IP connection with the client is still valid.

Node Name Node Type Description

id Attribute (String) Id of the ping request. Might be used for


debugging purposes.

Example: <PingRequest id=”96d-7e2d”/>

ping-response
The ping-response SDQL construct must be sent by the client as response to a ping-request SDQL construct.

Node Node Description


Nam Type
e

id Attrib Copied from the ID of the ping-request. Might be used for debugging purposes.
ute
(Strin
g)

Example:

1 <PingResponse id=”96d-7e2d”/>

error
The error SDQL construct can be sent at any time by the Sports Engine to indicate that something has gone wrong.

Node Name Node Type Description

code Attribute (int) The error codes are as follows:

"100" indicates an invalid request.


"200" indicates an i/o communication error.
"300" indicates that there are too many active subscriptions.
"301" indicates that subscribe-request was sent too often.
"304" indicates that get-next-initial-data-request was sent too often.
"305" indicates that get-next-update-data-request was sent too often.

10
"400" indicates that the update-data-resume-request was unsuccessful,
the client must do a subscribe-request if it gets this error code
"1000" indicates any other type of error.

message Attribute (String) A human-readable message.

Example:

1 <error code="300"
2 message=”Too many active subscriptions. Max active subscription number is 2”/>

11
XML example
This example contains the most important entities from the feed, limited to a single football match.

1. Initial data
1 <InitialData batchId="7" batchesLeft="165" dumpComplete="false">
2 <entities>
3 ....
4 <Provider id="3000984" version="0"
5 name="OMBE2 odds" locationId="226" url="http://www.betbrain.com" isBookmaker="true"
6 isBettingExchange="false" bettingCommissionVACs="0.0" isLiveOddsApproved="true"
7 isNewsSource="false" isEnabled="true"/>
8 ...
9 </entities>
10 </InitialData>

1 <InitialData batchId="9" batchesLeft="163" dumpComplete="false">


2 <entities>
3 ...
4 <BettingType id="47" version="0" name="Over/Under"
5 description="End score is over or under a certain threshold."/>
6 ...
7 <BettingType id="466" version="1" name="Home Away"
8 description="Home win or Away win, with money back on draw."/>
9 ...
10 <BettingType id="69" version="0" name="Home Draw Away"
11 description="Home win, Away win, or draw."/>
12 ...
13 </entities>
14 </InitialData>

1 <InitialData batchId="11" batchesLeft="161" dumpComplete="false">


2 <entities>
3 <ParticipantRole id="5" version="0" name="Pitcher"
4 description="In baseball, the pitcher is the player who throws the baseball
5 from the pitcher&#039;s mound toward the catcher to begin each play,
6 with the goal of retiring a batter,
7 who attempts to either make contact with the pitched ball or draw a walk"
8 isPrimary="false"/>
9 <ParticipantRole id="4" version="0" name="Primary" isPrimary="true"/>
10 <ParticipantRole id="3" version="0" name="Player" isPrimary="true"/>
11 <ParticipantRole id="2" version="0" name="Away" isPrimary="true"/>
12 <ParticipantRole id="1" version="0" name="Home" isPrimary="true"/>
13 <ParticipantRole id="7" version="0" name="Trainer"
14 description="The trainer of the pair jockey - horse." isPrimary="false"/>
15 <ParticipantRole id="6" version="0" name="Jockey"
16 description="A jockey is someone who rides horses in horse racing or steeplechase racing"
17 isPrimary="false"/>
18 </entities>
19 </InitialData>

1 <InitialData batchId="12" batchesLeft="160"


2 dumpComplete="false">

12
3 <entities>
4 ...
5 <Participant id="1" version="0" typeId="2"
6 name="Arsenal" countryId="77"/>
7 ...
8 <Participant id="13" version="0" typeId="2"
9 name="Newcastle United FC" countryId="77"/>
10 ...
11 <Participant id="66355" version="4" typeId="1" name="Mesut Ozil"
12 firstName="Mesut" lastName="Ozil" isMale="true" countryId="54"/>
13 ...
14 </entities>
15 </InitialData>

1 <InitialData batchId="42" batchesLeft="130" dumpComplete="false">


2 <entities>
3 <EventType id="2" version="0" name="Generic Tournament"/>
4 <EventType id="1" version="0" name="Generic Match"/>
5 </entities>
6 </InitialData>

1 <InitialData batchId="43" batchesLeft="129" dumpComplete="false">


2 <entities>
3 <EventPart id="1" version="0" name="Whole Event" orderNum="0"/>
4 <EventPart id="2" version="0" name="Whole Match" orderNum="1"
5 isDrawPossible="false"/>
6 <EventPart id="3" version="0" name="Ordinary Time"
7 parentId="2" orderNum="1" isDrawPossible="true"/>
8 <EventPart id="796" version="2" name="61 - 70 Minutes"
9 description="Game time 60:00 - 69:59"
10 parentId="3" orderNum="10" isDrawPossible="true"/>
11 <EventPart id="4" version="0" name="Overtime"
12 description="Includes Penalty Round too."
13 parentId="2" orderNum="3" isDrawPossible="false"/>
14 <EventPart id="797" version="2" name="71 - 80 Minutes"
15 description="Game time 70:00 - 79:59"
16 parentId="3" orderNum="11" isDrawPossible="true"/>
17 <EventPart id="5" version="2" name="1st Half (Ordinary Time)"
18 parentId="3" orderNum="1" isDrawPossible="true"/>
19 <EventPart id="534" version="0" name="Rest of 1st Half"
20 parentId="5" orderNum="1" isDrawPossible="true"/>
21 <EventPart id="6" version="2" name="2nd Half (Ordinary Time)"
22 parentId="3" orderNum="3" isDrawPossible="true"/>
23 <EventPart id="535" version="0"
24 name="Rest of 2nd Half"
25 parentId="6" orderNum="1"
26 isDrawPossible="true"/>
27 ...
28 </entities>
29 </InitialData>

1 <InitialData batchId="44" batchesLeft="128" dumpComplete="false">


2 <entities>
3 <EventStatus id="5" version="0"
4 name="Canceled"
5 description="The event has been canceled before start, will not be played later."/>
6 <EventStatus id="4" version="0"
7 name="Interrupted"

13
8 description="The event has been interrupted after start, will continue later."/>
9 <EventStatus id="3" version="0"
10 name="Ended"
11 description="The event has ended."/>
12 <EventStatus id="2" version="0"
13 name="In Progress"
14 description="The event is in progress."/>
15 <EventStatus id="1" version="0"
16 name="Pending"
17 description="The event has not started yet."/>
18 <EventStatus id="8" version="0"
19 name="Retired"
20 description="The event has been abandoned after start, will not continue.
21 A played has retired."/>
22 <EventStatus id="7" version="0"
23 name="Abandoned"
24 description="The event has been abandoned after start, will not continue."/>
25 <EventStatus id="6" version="0"
26 name="Walkover"
27 description="The event has been canceled before start, will not be played later.
28 A player wins by walkover"/>
29 </entities>
30 </InitialData>

1 <InitialData batchId="45" batchesLeft="127" dumpComplete="false">


2 <entities>
3 ...
4 <EventCategory id="77001" version="0" name="England" sportId="1"/>
5 ...
6 </entities>
7 </InitialData>

1 <InitialData batchId="46" batchesLeft="126" dumpComplete="false">


2 <entities>
3 ...
4 <EventTemplate id="1430" version="2"
5 name="Premier League"
6 eventTypeId="2"
7 sportId="1"
8 categoryId="77001"
9 url="http://www.premierleague.com/page/FixturesResults/0,,12306,00.html"
10 venueId="77" rootPartId="1"/>
11 ...
12 </entities>
13 </InitialData>

1 <InitialData batchId="47" batchesLeft="125" dumpComplete="false">


2 <entities>
3 ...
4 <Event id="109299123939856384" version="2" typeId="2"
5 isComplete="true" sportId="1" templateId="1430"
6 categoryId="77001" name="Premier League 2020/2021"
7 startTime="2020-09-11 00:00:00.000"
8 endTime="2021-06-30 00:00:00.000"
9 deleteTimeOffset="864000000" venueId="77"
10 statusId="2" hasLiveStatus="false" rootPartId="1"/>
11 ...
12 <Event id="125799081630027776" version="1"

14
13 typeId="1" isComplete="true"
14 sportId="1" parentId="109299123939856384"
15 parentPartId="1"
16 name="Arsenal vs Newcastle United FC" startTime="2021-01-18 20:00:00.000"
17 deleteTimeOffset="172800000"
18 statusId="1" hasLiveStatus="false" rootPartId="2"/>
19 ...
20 </entities>
21 </InitialData>

1 <InitialData batchId="52" batchesLeft="120" dumpComplete="false">


2 <entities>
3 ...
4 <EventParticipantRelation id="125799081630028800"
5 version="0" eventId="125799081630027776"
6 eventPartId="2" participantId="1" participantRoleId="1"/>
7 ...
8 <EventParticipantRelation id="125799081630029056"
9 version="0" eventId="125799081630027776"
10 eventPartId="2"
11 participantId="13"
12 participantRoleId="2"/>
13 ...
14 <EventParticipantRelation id="126957445763354880"
15 version="0" eventId="125799081630027776"
16 eventPartId="2"
17 participantId="66355"
18 participantRoleId="3"
19 parentParticipantId="1"/>
20 ...
21 </entities>
22 </InitialData>

1 <InitialData batchId="53" batchesLeft="119" dumpComplete="false">


2 <entities>
3 <Source id="9730156534460416" version="22945830"
4 collectorId="10" providerId="3000984"
5 lastCollectedTime="2021-01-15 13:26:37.771"/>
6 <Source id="9730157374894080" version="22927316"
7 collectorId="10" providerId="3000984"
8 lastCollectedTime="2021-01-15 13:26:38.273"/>
9 <Source id="91159533617106944" version="16717892"
10 collectorId="10" providerId="3000984"
11 lastCollectedTime="2021-01-15 13:26:37.294"/>
12 <Source id="91159537498935296"
13 version="16771479" collectorId="10" providerId="3000984"
14 lastCollectedTime="2021-01-15 13:26:39.018"/>
15 <Source id="91159541226622976"
16 version="16711183" collectorId="10" providerId="3000984"
17 lastCollectedTime="2021-01-15 13:26:37.750"/>
18 <Source id="9730156940390400"
19 version="22943822" collectorId="10" providerId="3000984"
20 lastCollectedTime="2021-01-15 13:26:37.426"/>
21 <Source id="9730157785542656"
22 version="22975580" collectorId="10" providerId="3000984"
23 lastCollectedTime="2021-01-15 13:26:37.580"/>
24 <Source id="9730158254780416"
25 version="22927756" collectorId="10" providerId="3000984"

15
26 lastCollectedTime="2021-01-15 13:26:37.257"/>
27 </entities>
28 </InitialData>

1 <InitialData batchId="63" batchesLeft="109" dumpComplete="false">


2 <entities>
3 <StreamingProvider id="3" version="0" name="Youtube"
4 urlTemplate="https://www.youtube.com/watch?v={channel}"/>
5 <StreamingProvider id="1" version="62" name="Twitch.tv"
6 urlTemplate="https://player.twitch.tv/?channel={channel}"/>
7 </entities>
8 </InitialData>

1 <InitialData batchId="64" batchesLeft="108" dumpComplete="false">


2 <entities>
3 <OutcomeStatus id="5" version="0"
4 name="Unknown"
5 description="The status of the outcome is unknown."/>
6 <OutcomeStatus id="4" version="0"
7 name="Unknown But Resolved"
8 description="The outcome is resolved but it is unknown whether it happened or not."/>
9 <OutcomeStatus id="3" version="0"
10 name="Did Not Happen"
11 description="The outcome did not happen."/>
12 <OutcomeStatus id="2" version="1"
13 name="Did Happen"
14 description="The outcome did happen."/>
15 <OutcomeStatus id="1" version="0"
16 name="Can Happen"
17 description="The outcome can still happen."/>
18 <OutcomeStatus id="9" version="0"
19 name="Cancelled"/>
20 <OutcomeStatus id="8" version="1" name="Void"
21 description="The entire wagered sum is reimbursed."/>
22 <OutcomeStatus id="7" version="2"
23 name="Half Lost"
24 description="Half of the wagered sum is reimbursed, the other half is lost."/>
25 <OutcomeStatus id="6" version="1"
26 name="Half Won"
27 description="Half of the wagered sum is multiplied by the quota, the other half is reimbursed."/>
28 </entities>
29 </InitialData>
30

1 <InitialData batchId="65" batchesLeft="107" dumpComplete="false">


2 <entities>
3 ...
4 <OutcomeType id="10" version="0"
5 name="Winner"
6 description="The winner of the event. Money lost on no-win."
7 hasParamFloat1="false" hasParamFloat2="false"
8 hasParamFloat3="false" hasParamBoolean1="false"
9 hasParamString1="false" hasParamParticipantId1="true"
10 paramParticipantId1Description="The id of the participant to win the event."
11 paramParticipant1MustBePrimary="true"
12 paramParticipant1MustBeRoot="true"
13 hasParamParticipantId2="false"
14 paramParticipant2MustBePrimary="false"

16
15 paramParticipant2MustBeRoot="false"
16 hasParamParticipantId3="false"
17 paramParticipant3MustBePrimary="false"
18 paramParticipant3MustBeRoot="false"
19 hasParamEventPartId1="false"/>
20 ...
21 <OutcomeType id="13" version="2" name="Total Score Over"
22 description="The total score is greater than a certain threshold." hasParamFloat1="true"
23 paramFloat1Description="The threshold." hasParamFloat2="false"
24 hasParamFloat3="false" hasParamBoolean1="false"
25 hasParamString1="false"
26 hasParamParticipantId1="false"
27 paramParticipant1MustBePrimary="false"
28 paramParticipant1MustBeRoot="false"
29 hasParamParticipantId2="false"
30 paramParticipant2MustBePrimary="false"
31 paramParticipant2MustBeRoot="false" hasParamParticipantId3="false"
32 paramParticipant3MustBePrimary="false"
33 paramParticipant3MustBeRoot="false"
34 hasParamEventPartId1="false"
35 hasParamScoringUnitId1="true"/>
36 ...
37 <OutcomeType id="14" version="2" name="Total Score Under"
38 description="The total score is less than a certain threshold."
39 hasParamFloat1="true" paramFloat1Description="The threshold."
40 hasParamFloat2="false" hasParamFloat3="false"
41 hasParamBoolean1="false"
42 hasParamString1="false" hasParamParticipantId1="false"
43 paramParticipant1MustBePrimary="false"
44 paramParticipant1MustBeRoot="false"
45 hasParamParticipantId2="false" paramParticipant2MustBePrimary="false"
46 paramParticipant2MustBeRoot="false" hasParamParticipantId3="false"
47 paramParticipant3MustBePrimary="false" paramParticipant3MustBeRoot="false"
48 hasParamEventPartId1="false" hasParamScoringUnitId1="true"/>
49 ...
50 </entities>
51 </InitialData>

1 <InitialData batchId="67" batchesLeft="105" dumpComplete="false">


2 <entities>
3 <BettingOfferStatus id="5" version="0"
4 name="Invalid"
5 isAvailable="false"
6 description="The betting offer is (potentially temporarily) invalid."/>
7 <BettingOfferStatus id="4" version="0"
8 name="Removed"
9 isAvailable="false"
10 description="The betting offer is (potentially temporarily) removed from the provider data source."/>
11 <BettingOfferStatus id="3" version="0"
12 name="Non-Participant"
13 isAvailable="false"
14 description="The participant associated with the (outright) betting offer
15 does not participate in the event (any more).
16 Used by some providers."/>
17 <BettingOfferStatus id="2" version="0"
18 name="Starting Price"
19 isAvailable="true"
20 description="The betting offer has no odds (yet) but bets can still be placed.

17
21 For example, in horse racing it is possible to bet on the (yet unknown) odds prevailing
22 in the on-course fixed-odds betting market at the time a race begins."/>
23 <BettingOfferStatus id="1"
24 version="0"
25 name="Standard"
26 isAvailable="true"
27 description="The betting offer has odds and is available for betting."/>
28 <BettingOfferStatus id="6"
29 version="0"
30 name="Resolved"
31 isAvailable="false"
32 description="The betting offer is resolved because the associated outcome is resolved."/>
33 </entities>
34 </InitialData>

1 <InitialData batchId="71" batchesLeft="101" dumpComplete="false">


2 <entities>
3 ...
4 <Outcome id="125799081678447616" version="1" typeId="10"
5 isNegation="false" statusId="1" eventId="125799081630027776"
6 eventPartId="3" paramParticipantId1="13"
7 paramScoringUnitId1="28" name="Newcastle United FC"/>
8 ...
9 <Outcome id="125799081678447872" version="1" typeId="10"
10 isNegation="false" statusId="1"
11 eventId="125799081630027776"
12 eventPartId="3" paramParticipantId1="1"
13 paramScoringUnitId1="28" name="Arsenal"/>
14 ...
15 <Outcome id="125799081678448384" version="1" typeId="11"
16 isNegation="false" statusId="1"
17 eventId="125799081630027776"
18 eventPartId="3" paramScoringUnitId1="28"
19 name="Draw"/>
20 ...
21 </entities>
22 </InitialData>

1 <InitialData batchId="79" batchesLeft="93" dumpComplete="false">


2 <entities>
3 ...
4 <Market id="126682153423602688"
5 version="1" name="Home Draw Away, Ordinary Time"
6 eventId="125799081630027776"
7 eventPartId="3" bettingTypeId="69"
8 scoringUnitId="28" numberOfOutcomes="3"
9 isComplete="true" isClosed="false"/>
10 ...
11 </entities>
12 </InitialData>

1 <InitialData batchId="82" batchesLeft="90" dumpComplete="false">


2 <entities>
3 ...
4 <MarketOutcomeRelation id="126682153423602944"
5 version="0" marketId="126682153423602688"
6 outcomeId="125799081678447616"/>
7 ...

18
8 <MarketOutcomeRelation id="126682153423603200"
9 version="0" marketId="126682153423602688"
10 outcomeId="125799081678447872"/>
11 ...
12 <MarketOutcomeRelation id="126682153423603456"
13 version="0" marketId="126682153423602688"
14 outcomeId="125799081678448384"/>
15 ...
16 </entities>
17 </InitialData>

1 <InitialData batchId="89" batchesLeft="83" dumpComplete="false">


2 <entities>
3 ...
4 <BettingOffer id="125799136195940864" version="33" providerId="3000984"
5 sourceId="9730156534460416" outcomeId="125799081678447616"
6 bettingTypeId="69" statusId="1" isLive="false" odds="7.5" multiplicity="0"
7 couponKey="?matchid=125799081630027776&#038;seOutcomeid=125799081678447616"
8 slotNum="1" lastChangedTime="2021-01-14 19:58:05.550"/>
9 ...
10 <BettingOffer id="125799136196988928" version="49" providerId="3000984"
11 sourceId="9730156534460416" outcomeId="125799081678447872" bettingTypeId="69"
12 statusId="1" isLive="false" odds="1.4545455" multiplicity="0"
13 couponKey="?matchid=125799081630027776&#038;seOutcomeid=125799081678447872"
14 slotNum="1" lastChangedTime="2021-01-15 13:05:07.625"/>
15 ...
16 <BettingOffer id="125799136195940608" version="26" providerId="3000984"
17 sourceId="9730156534460416" outcomeId="125799081678448384" bettingTypeId="69"
18 statusId="1" isLive="false" odds="4.5" multiplicity="0"
19 couponKey="?matchid=125799081630027776&#038;seOutcomeid=125799081678448384"
20 slotNum="1" lastChangedTime="2021-01-05 13:20:00.000"/>
21 ...
22 </entities>
23 </InitialData>

2. Updates for the previous initial data


After the initial dump, there are only incremental updates (create, delete or update)

Updates for existing entities:

1 <UpdateData batchId="187054356" batchUuid="52225078084|1"


2 createdTime="2021-01-15 13:26:41.855">
3 <Source type="update" id="9730156534460416" version="22945832"
4 lastCollectedTime="2021-01-15 13:26:41.799"/>
5 </UpdateData>

1 <UpdateData batchId="187290946" batchUuid="52327995192|0"


2 createdTime="2021-01-15 13:29:59.595">
3 <BettingOffer type="update" id="125799136195940864" version="34"
4 lastChangedTime="2021-01-15 13:29:59.571" odds="7.3"/>
5 <BettingOffer type="update" id="125799136195940608" version="27"
6 lastChangedTime="2021-01-15 13:29:59.571" odds="4.6"/>
7 </UpdateData>

Create new entities:

19
1 <UpdateData batchId="187319635" batchUuid="52327996529|0"
2 createdTime="2021-01-15 13:30:20.713">
3 <Outcome type="create" id="127067929377546240"
4 version="0" typeId="13"
5 isNegation="false" statusId="1"
6 eventId="125799081630027776"
7 eventPartId="3" paramFloat1="2.5"
8 paramScoringUnitId1="28" name="Over 2.5"/>
9 <Outcome type="create" id="127067929378594816"
10 version="0" typeId="14"
11 isNegation="false" statusId="1"
12 eventId="125799081630027776"
13 eventPartId="3" paramFloat1="2.5"
14 paramScoringUnitId1="28" name="Under 2.5"/>
15 </UpdateData>

Delete existing entities:

1 <UpdateData batchId="187324586" batchUuid="51965742642|7"


2 createdTime="2021-01-15 13:30:23.932">
3 <Outcome type="delete" id="127067929377546240"/>
4 <Outcome type="delete" id="127067929378594816"/>
5 </UpdateData>

20
JSON - SDQL
See XML - SDQL for message documentation.

Messages to sent to server (via push)

Subscribe request:

1 {
2 "SubscribeRequest": {
3 "subscriptionSpecificationName": "subscriptionName"
4 }
5 }

Ping Response:

1 {
2 "PingResponse": {
3 "id": "1"
4 }
5 }

Resume:

1 {
2 "UpdateDataResumeSinceRequest": {
3 "subscriptionId": "5e68f56c-b372-4bd9-a14c-88b192640649",
4 "subscriptionSpecificationName": "subscriptionName",
5 "subscriptionChecksum": "23C5004A2D4F904DCBFC014C75821906",
6 "sinceDate": "2024-06-19 12:34:56.789"
7 }
8 }

Messages sent by server

All message are send without white spaces, we added them in documentation for readability (ie: PingRequest message is :
{"PingRequest":{"id":"1"}} )

Push messages

Subscribe response:

1 {
2 "SubscribeResponse": {
3 "subscriptionChecksum": "23C5004A2D4F904DCBFC014C75821906",
4 "subscriptionId": "5e68f56c-b372-4bd9-a14c-88b192640649"
5 }
6 }

Ping Request:

1 {
2 "PingRequest": {
3 "id": "1"
4 }

21
5 }

Initial Data:

1 {
2 "InitialData": {
3 "dumpComplete": false,
4 "entities": [
5 {
6 "entityClass": "Sport",
7 "name": "Football",
8 "id": "1",
9 "version": 2
10 },
11 {
12 "entityClass": "Sport",
13 "name": "Tennis",
14 "id": "3",
15 "version": 0
16 }
17 ],
18 "batchId": 1,
19 "batchesLeft": "103"
20 }
21 }

Update Data:

1 {
2 "UpdateData": {
3 "changes": [
4 {
5 "lastChangedTime": "Mon Feb 03 10:37:07 GMT 2020",
6 "entityClass": "BettingOffer",
7 "odds": 20,
8 "id": "93182940718131712",
9 "type": "update",
10 "version": 41
11 },
12 {
13 "entityClass": "Source",
14 "id": "93560747352743936",
15 "type": "delete"
16 },
17 {
18 "lastChangedTime": "Mon Feb 03 10: 37:07 GMT 2020",
19 "entityClass": "BettingOffer",
20 "odds": 4.37,
21 "id": "93182940718131968",
22 "type": "update",
23 "version": 41
24 }
25 ],
26 "createdTime": "Mon Feb 03 10:37:07 GMT 2020",
27 "batchId": "1030",
28 "batchUuid": "50112421962|0"
29 }
30 }

22
Unsubscribe Response:

1 {
2 "UnsubscribeResponse": {
3 "code": 0,
4 "message": "Unsubscription was successful."
5 }
6 }

Error message:

1 {
2 "error": {
3 "code": 100,
4 "message": "No subscriptionSpecificationName found for subscriptionId 12345"
5 }
6 }

Pull messages

GetNextInitialDataResponse:

1 {
2 "GetNextInitialDataResponse": {
3 "InitialData": [
4 {
5 "dumpComplete": false,
6 "entities": [
7 {
8 "entityClass": "Sport",
9 "name": "Football",
10 "id": "1",
11 "version": 2
12 },
13 {
14 "entityClass": "Sport",
15 "name": "Tennis",
16 "id": "3",
17 "version": 0
18 }
19 ],
20 "batchId": 1,
21 "batchesLeft": "103"
22 }
23 ]
24 }
25 }

GetNextUpdateDataResponse:

1 {
2 "GetNextUpdateDataResponse": {
3 "UpdateData": [
4 {
5 "changes": [
6 {
7 "lastCollectedTime": "2020-02-03 12:37:07.000",
8 "entityClass": "Source",
9 "providerId": "3000000",

23
10 "collectorId": "123",
11 "id": "123456789",
12 "type": "create",
13 "version": 0
14 },
15 {
16 "entityClass": "BettingOffer",
17 "id": "93182940718131968",
18 "type": "update",
19 "version": "41"
20 },
21 {
22 "entityClass": "Source",
23 "id": "93560747352743936",
24 "type": "delete"
25 }
26 ],
27 "createdTime": "2020-02-03 12:37:07.000",
28 "batchId": "1030",
29 "batchUuid": "50112421962|0"
30 },
31 {
32 "changes": [
33 {
34 "entityClass": "BettingOffer",
35 "id": "93182940718131968",
36 "type": "delete"
37 }
38 ],
39 "createdTime": "2020-02-03 12:37:08.000",
40 "batchId": "1031",
41 "batchUuid": "50112421963|0"
42 }
43 ]
44 }
45 }

24
Client-Server Communication
Pull and Push Subscriptions
A client can communicate with the server in two ways: Pull and Push.
In Pull mode, the client initiates the communication and then, it keeps asking the server for updates. In Pull mode, the clients connect using HTTP.
In Push mode, the client initiates the communication and then, the server keeps pushing the updates to the client. In Push mode, the clients connect using TCP/IP
sockets.
Here is the Access Matrix:

AccessType Subscription Pull Subscription Push


TCP/IP Socket N/A Yes

HTTP Yes N/A

You can find more details on these two types of subscriptions in the following sections: Push Subscription and Pull Subscription.

25
Pull Subscription
An easy-to-use alternative to sockets is to access the Sports Engine using HTTP GET requests. Simple URLs can be used to invoke the following actions: subscribe,
get-next-initial-data, get-next-update-data and unsubscribe. Please note that all the Sports Engine responses will be compressed using the GZIP algorithm.
SDQL constructs exchanged between Sports Engine and Client are depicted in the use case below.
Use Case: Normal Flow
1. Client sends to Sports Engine a subscribe-request.
2. Sports Engine sends to Client a subscribe-response.
3. Client sends to Sports Engine a get-next-initial-data-request.
4. Sports Engine sends to Client a get-next-initial-data-response.
5. Repeat steps 3 and 4 until the initial data dump is over.
6. Client sends to Sports Engine a get-next-update-data-request.
7. Sports Engine sends to Client a get-next-update-data-response.
8. Repeat steps 6 and 7 until Client sends an unsubscribe-request.
Here is an example: using HTTP GET requests, the Normal Flow looks like:
1. Client sends a subscribe-request:
XML: http://server:8081/xmlfeed?requestType=SubscribeRequest&subscriptionSpecificationName=test
JSON: http://server:8081/jsonfeed?requestType=SubscribeRequest&subscriptionSpecificationName=test
2. Sports Engine sends to Client a subscribe-response construct from which the client gets the subscriptionId. Let's suppose that the subscriptionId = 12.
See XML - SDQL or JSON - SDQL for the responses format.
3. Client sends a get-next-initial-data-request:
XML: http://server:8081/xmlfeed?requestType=GetNextInitialDataRequest&subscriptionId=12
JSON: http://server:8081/jsonfeed?requestType=GetNextInitialDataRequest&subscriptionId=12
4. Sports Engine sends to Client the first batch from the initial data dump. One of the attributes is dumpComplete.
5. If dumpComplete=false, Client repeats from step 3. If dumpComplete=true , it means that Client got the whole initial data dump and moves on to step 6.
6. Client sends to Sports Engine a get-next-update-data-request SDQL construct:
XML: http://server:8081/xmlfeed?requestType=GetNextUpdateDataRequest&subscriptionId=12
JSON: http://server:8081/jsonfeed?requestType=GetNextUpdateDataRequest&subscriptionId=12
7. Sports Engine sends to Client a get-next-update-data-response SDQL construct.
8. Steps 6 and 7 repeats until client unsubscribes:
XML: http://server:8081/xmlfeed?requestType=UnsubscribeRequest&subscriptionSpecificationName=test&subscriptionId=12
JSON: http://server:8081/jsonfeed?requestType=UnsubscribeRequest&subscriptionSpecificationName=test&subscriptionId=12
Usage restrictions
1. Client is allowed to send no more than 1 subscribe-request per hour for each active subscription.
2. Client is allowed to send no more than 24 subscribe-request per 24 hours no matter how many subscriptions he has.
3. Client is allowed to send no more than 1 get-next-update-data-request per 30 seconds for each active subscription.
4. Client must send at least 1 get-next-update-data-request every 5 minutes, otherwise the subscription times out.

26
Push Subscription
When subscribing to the Sports Engine in push mode, the client opens a TCP/IP connection to the Sports Engine.
To choose between XML - SDQL and JSON - SDQL, all you have to do is send the subscribe-request message in the chosen format and the server will respond with
the same format.
SDQL constructs exchanged between Sports Engine and Client are depicted in the use case below.
Use Case: Normal Flow
1. Client sends to Sports Engine a subscribe-request SDQL construct.
2. Sports Engine sends to Client a subscribe-response SDQL construct.
3. Sports Engine keeps sending to Client initial-data SDQL constructs until the initial data dump is over.
4. Sports Engine keeps sending to Client update-data SDQL constructs until Client sends an unsubscribe-request or the Client closes the connection.
Use case: Network connection is broken for a few minutes between client and SportsEngine
1. Client disconnects
2. After a few minutes network connection is reestablished
3. Client sends to Sports Engine an update-data-resume-request SDQL construct to get the updates missed during the outage
4. Sports Engine sends to Client the missing update-data SDQL constructs and after them the new update-data SDQL constructs
At this time SportsEngine is able to give the missing updates for about 30 minutes. This limit might change in the future.
Client is allowed 5 minutes to read all missing updates, otherwise it is disconnected. Client may try again to resume the subscription.
If the client remains disconnected for long time or if the update-data-resume-request returns error code 400 (cannot return missing updates), the client must do a new
subscribe-request.

To verify that the TCP/IP connection between the client and the Sports Engine is still valid, Sports Engine regularly sends ping-request SDQL constructs to which the
client must answer with ping-response SDQL constructs. If ping-response SDQL constructs are not received by the Sports Engine in a certain time, the Sports Engine
will close the connection. The exact time after which the Sports Engine will close the connection is client dependent, the default is set to 1 minute.

Usage restrictions
Client must send ping-response SDQL constructs, otherwise the subscription will time out.
Client is allowed to send no more than 24 subscribe-request SDQL constructs per 24 hours no matter how many subscriptions he has.
Client is allowed to send no more than 1 subscribe-request SDQL construct per corresponding time threshold for each active subscription.
SubscribeRequest thresholds (minutes) are [1, 2, 5, 10, 15, 30, your_threshold*] since the last successful SubscribeRequest. The current threshold will be
reset after your_threshold* time passed since last successful SubscribeRequest.
Example: 1st request - 1 minute, 2nd request - 2 minutes, 3rd request - 5 minutes, etc.

your_threshold* - Min time between requests in your subscription.

Usage TCP/IP Sockets


Using sockets, clients create a TCP/IP connection to the Sports Engine and then send and receive SDQL constructs over that connection. The bytes are (and must
be) encoded using the UTF-8 character encoding scheme and compressed using the GZIP algorithm. Each SDQL construct must be preceded by a length string
(indicating the length of the SDQL construct, and encoded using UTF-8) and a null byte, e.g. a byte whose value is 0 (zero), as follows:

length 0 SDQL construct (UTF-8 encoded and GZIP-ed)

Implementation pseudocode

Sending a message to the server:


1. Build the message
Ex: subscribe request:
XML:
<?xml version="1.0" encoding="UTF-8"?>
<sdql>
<SubscribeRequest subscriptionSpecificationName="SubscriptionName"/>
</sdql>
JSON:
{"SubscribeRequest":{"subscriptionSpecificationName":"subscriptionName"}}
2. Compress the message using the GZIP algorithm.
3. Calculate the length of the GZIPPED message. The message should be an array of bytes, making the length of the message = the length of the array. IE: the
number of bytes in the GZIPPED message
4. Convert the number from point 3 to a string (Ex: from 123 to “123”)
5. Write on the socket the length (the string obtained at point 4)

27
6. Write on the socket a zero byte (a byte whose value is 0)
7. Write on the socket the gzipped message

Reading a message from the server:


1. Read bytes until you find a zero byte.
2. Convert the read bytes to a string.
3. Convert the String from point 2 to a number (Integer), let’s call it N
4. Read exactly N bytes from the socket.
5. Decompress the message from point 4 using GZIP algorithm
6. Convert the result from 5 to a string.

Java Example on Reading/Writting a SDQL construct

The example below shows how to read a SDQL construct from the server.

private static int MAX_PDU_CONTENT_BYTE_SIZE = 15 * 1024 * 1024; // 15M


private byte[] PDU_CONTENT_BYTE_ARRAY = new byte[MAX_PDU_CONTENT_BYTE_SIZE];

public SDQLConstruct readSDQLConstruct(InputStream is) throws IOException, XMLStreamException {

// read length and 0 byte


ByteArrayOutputStream baosLength = new ByteArrayOutputStream();
for (int i = is.read(); i != 0; i = is.read()) {
baosLength.write(i);
}

int length = Integer.parseInt(new String(baosLength.toByteArray()));

// read SDQL construct (as gzipped bytes)


byte[] sdqlConstructAsGzippedBytes = PDU_CONTENT_BYTE_ARRAY; // reusing the array
for (int numBytesRead = 0; numBytesRead != length;)
numBytesRead += is.read(sdqlConstructAsGzippedBytes, numBytesRead, length - numBytesRead);

ByteArrayInputStream bais = new ByteArrayInputStream(sdqlConstructAsGzippedBytes, 0, length);


GZIPInputStream gzipis = new GZIPInputStream(bais);

return readFromPushStream(gzipis); //Get the SDQL construct by parsing the XML represented by the gzipped bytes
}

The example below shows how to send a SDQL construct to the server.

public static void writePDU(OutputStream os, SDQLConstruct sdqlConstruct) throws IOException, XMLStreamException {

ByteArrayOutputStream baos = new ByteArrayOutputStream();


GZIPOutputStream gzipos = new GZIPOutputStream(baos);

write(gzipos, sdqlConstruct); //transform the sdqlConstruct into XML


gzipos.close();

byte[] sqdlConstructAsGzippedBytes = baos.toByteArray();


byte[] sqdlConstructLengthBytes = Integer.toString(sqdlConstructAsGzippedBytes.length).getBytes("UTF-8");

os.write(sqdlConstructLengthBytes);
os.write(0);
os.write(sqdlConstructAsGzippedBytes);
os.flush();
}

28
Sports Model Entities
Welcome to the Sports Model Entities
The Sports Model is OddsMatrix's domain model for the sports domain. It details and defines all important sports concepts, such as events, participants, outcomes,
and bets.
The goal and purpose of the Sports Model is to model (i.e. express) all concepts relevant to the sports domain, both those existing now and those that will be
introduced in the future.
This flexibility and extendability is achieved by explicitly modelling only the primary concepts (e.g. Event and Participant) and their relationships (e.g. EventParticipant),
and then model their sub-concepts (e.g. matches and leagues) as data (of e.g. an EventType) rather than as their own explicitly modelled concepts.
The Sports Model described here is a conceptual one, although special effort has been taken to ensure that it transforms easily into a database design. Therefore, it
closely resembles an Entity/Relation (E/R) diagram.
For further reading, see the individual diagrams for Event, Participant, Outcome, Betting, etc. With each diagram, start with the main entity type (e.g. the Event entity
type in the Event diagram) and work your way "outwards" to associated entity types.
Enjoy!

Sample database
Check out database sample for reference. To keep small size, it contains few Football, Tennis and Basketball events and related data only.
Disclaimer:
1. It is intended to be a starting point in feed integration. While we aim to keep it updated, please check if db schema is compatible to the actual data you receive.
2. There are no foreign keys defined, because we validate model consistency at application level. Feel free to add them in case you need them.
3. There are no indexes defined, feel free to add them according to your use-cases.
db_sample.zip

29
Event
1. Diagram

2. Classifiers
2.1 Class Event
Represents a real-world sports event.
Each event has a type that determines its properties.
When splitting an event into sub-events (or event parts), we can choose to model these sub-events either as events or as event parts. We use the following
guidelines:
* Model as an event if the sub-event is normally regarded as its own event, e.g. matches within a league.
* Model as an event part if the sub-event is a part of a (fixed) structural breakdown of the (parent) event, e.g. a set within a tennis match.
The concept of rounds (primarily for use with leagues) is modelled as round event parts. See EventPart for more details.

30
2.1.1 Event attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version
by 1.

isComplete(boolean) True if the event is structurally complete, and false otherwise. It cannot be null. An event is
structurally complete if all relevant EventParticipantRelation entities exist, and false otherwise.

typeId(long,readOnly) A reference to the event type. Cannot be null.

sportId(long,readOnly) A reference to the event sport. Cannot be null.

templateId(Long) A reference to the event template, or null if none, unknown or not applicable.

categoryId(Long) A reference to the event category, or null if none, unknown or not applicable.

promotionId(Long) A reference to the event to which participants of this event may promote, or null if unknown or
not applicable. This is normally used with promotion (and relegation) within league systems.
For example, within the English football league system the "Football League One" (level 3)
promotes to "Football League Championship" (level 2) which promotes to "Premier League"
(level 1).
The promotionId can be used to e.g. order league systems into a tree structure for improved
user navigation.

parentId(Long,readOnly) A reference to the parent of this event, or null if none, unknown or not applicable. For example:
If a match is part of a cup, then the cup will be the parent of the match.

parentPartId(Long) A reference into the parent's event part hierarchy at which this event takes/took place, or null if
none, unknown, or not applicable.
For example, if a match takes/took place within "Round 13" of a league, then the parentPart will
refer to "Round 13".

name(String) The name of the event. Can be null. Its maximum length is 255 characters. For matches, the
name will be null, as it can (and should) be automatically inferred from the home/away
participant names.

shortCode(String) Alpha numerical ID, as short as possible, up to 5-6 characters, assigned to this event. Can be
null. Two events cannot have the same (not-null) shortCode at the same time. After event is
deleted, its short code will be assigned to other event later on.

startTime(Date) The planned start time (in GMT) of the event, or null if unknown or not applicable.

endTime(Date) The planned end time (in GMT) of the event, or null if unknown or not applicable.

deleteTimeOffset(long) Specifies the number of milliseconds after event end (according to the statusId property) that
this event can be safely deleted (or moved to history). Cannot be null. Must be 0 or greater.
There are two primary use cases for having deleteTimeOffset > 0:
1) Results. Adding event results (after event end) requires that the event outcomes are still
present in the system, or can still be created. This requires that the event itself is still present in
the system.
2) Event creation. Many events (e.g. tournaments) are seasonal and quite similar from one
season to another. To make event creation is easy (e.g. by copy'n'paste) we want to keep old
events in the system until their newer counterparts have been created.

venueId(Long) A reference to the venue (Location entity) at which the event takes place, or null if unknown or
not applicable.
If the event takes place a several venues, then the event venue is the smallest aggregate
venue. For example: The "English Premiership 2008/2009" league will take place in England.

statusId(long) A reference to the event status. Cannot be null.

hasLiveStatus(boolean) True if the event status is (or will be) updated live, and false if not. Cannot be null. The event
status is represented by the statusId and currentPartId properties.

rootPartId(long,readOnly) A reference to the root event part that describes the (fixed) part structure of this event. Cannot
be null. A default "empty" root event part hierarchy will be provided. Events with an unknown
event part hierarchy can then reference to this.
The rootPartId must be determined at event creation time. The creator can determine the
rootPart in three ways:
(1) Use the rootPartId property of an associated event template (if any).
(2) Use EventPartDefaultUsage.
(3) Custom, i.e. use whatever.

currentPartId(Long) Refers to the part within the rootPart that is the current part. Is null if the event is not currently
taking place, or if the exact current part is not known.

31
Name Description
For example, for the "Champions League 2008/2009" event, the currentPart can be "Group
Phase", "Knockout 1/8", etc.
For example, for a football match, the currentPart can be "First Half", "Second Half", etc.

url(String) A URL associated with the event, or null if none or unknown. If not null then url must be a valid
URL. Its maximum length is 255 characters.

popularity(Integer) A measure of the popularity of this event, or null if unknown. The value (if any) will be zero or
greater. The higher the number the more popular the event is.
The popularity measure is entirely BetBrain-specific and is used to order events for improved
user navigation. It is primarily used to order league systems (within a given sport and country),
and to order leagues that promote to the same league (i.e. have the same promotionId).

note(String) An internal-use-only note. May be null. The maximum length is 255 characters.

2.2 Class EventType


Represents a type of event, for example "league", "race", or "match".
The event type concept is crucial in the modeling of events. Indeed, it is the key to model any type of real-world event.
Every event is associated with exactly one event type. It is the event type that determines the semantics of the event and its properties.
An event type can only be used in certain contexts, such as certain sports, as specified by EventTypeUsage.

2.2.1 EventType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the event type, for example "League" or "Match". It cannot be null or empty, and is unique among event types. The maximum
length is 255 characters.

description(String) A description of the event type, or null if none. Its maximum length is 255 characters.

2.3 Class EventTypeUsage - Not published


Specifies the contexts (i.e. sports) in which an event type can be used.
The tuple (eventTypeId, sportId) must be unique.

2.3.1 EventTypeUsage attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

eventTypeId(long,readOnly) A reference to an event type. It cannot be null.

sportId(long,readOnly) A reference to a sport. It cannot be null.

minPrimaryParticipantTimeBetweenEvents(Long) The minimum time (in milliseconds) between events (of same sport and event type) that share a primary
participant. Must be 0 or greater, or null if no limit.

minEventDuration(long) The primary concept here is the Event, which models a real-world event. Through the use of the generic
EventType, we can model any type of event.

maxEventDuration(long) The maximum event duration (in milliseconds). Must be greater than or equal to minEventDuration.
Cannot be null.

2.4 Class Sport


Represents a real-world sport. Sports can be arranged hierarchically. See Other entities for more information.

2.5 Class EventParticipantRestriction


Represents a restriction of what (primary) participants can participate in a certain event. These restrictions only applies to primary participants, and not to secondary
participants (such as sponsors).
There are logical ANDs between the property values. A property value of null means that there is no restriction associated with that specific property.

32
It is specific to the event type how the restrictions are interpreted in regards to sub-events. The normal interpretation, however, is as follows: A participant in a sub-
event must satisfy the first constraint meet on the path of events from the sub-event to the (root) super event.
The tuple (eventId, participantTypeId) must be unique.

2.5.1 EventParticipantRestriction attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the
entity will increment the version by 1.

eventId(long,readOnly) A reference to the event to which this restriction applies.


Cannot be null.

participantTypeId(long,readOnly) A reference to the ParticipantType to which this restriction


applies. Cannot be null.

participantIsMale(Boolean,readOnly) True if the participant must be male, false if female, or null no


gender restriction.

participantMinAge(Integer,readOnly) The minimum participant age (in years), or null if no


restriction. This age is relative to event start time. If not null,
then the participantMinAge must be non-negative, and less
than or equal to participantMaxAge (if not null).

participantMaxAge(Integer,readOnly) The maximum participant age (in years), or null if no


restriction. This age is relative to event start time. If not null,
then the participantMaxAge must be non-negative, and
greater than or equal to participantMinAge (if not null).

participantPartOfLocationId(Long,readOnly) The participant location (e.g. country) must be a (sub-)part of


this location, or null if no restriction.

2.6 Class EventParticipantRelation


Specifies that a certain participant participates in a certain event (or event part), in what role(s) and as part of what parent(s) (if any).
The EventParticipantRelation can model a lot. [Design note: Maybe even too much. Maybe we should separate it into several classes; but the drawback with doing
this is increased complexity and decreased lookup performance.]
We can model:
(1) Event (part) participation: That a participant participates in one or more parts of an event.
(2) Role participation: In what capacity the participant participates in the event. This is specified as roles. A participant can have multiple roles in the same event.
(3) Indirect participation: That a participant participates indirectly through another participant. For example, a player participates (indirectly) because he is part of the
team that participates (directly) in the event.
(4) Out-of-game participation: Referees, coaches, sponsors, etc.
(5) Line ups. For this we simply use the EventParticipantRelation entities associated with the first event part of the event.
With matches, the home and away participants can be found by looking up by (eventId, <first>, X, "Home"/"Away", null). "X" is the id of the Home/Away participant.
Generally, a sub-event can only include in-game participants that are also in-game participants on the parent event.
The tuple (eventId, eventPartId, participantId, participantRoleId, parentParticipantId) is unique.

2.6.1 EventParticipantRelation attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes


applied to the entity will increment the version
by 1.

eventId(long,readOnly) A reference to the event. Cannot be null.

eventPartId(long,readOnly) A reference to the event part. Cannot be null.

participantId(long,readOnly) A reference to the participant. Cannot be null.

participantRoleId(long) A reference to a role that the participant


plays/played in the event. Cannot be null.
Note that every participant plays at least one
role in an event. However, this role may not be
known (to us). If so, then a more
general/abstract role must be chosen.

33
Name Description
parentParticipantId(Long) A reference to the parent participant of this
participant, or null if none. This property is
typically used with team players.

2.7 Class ProviderEventRelation


The ProviderEventRelation contains provider-specific event information, such as the provider start and end times for the event. The tuple (providerId, eventId) must be
unique.

2.7.1 ProviderEventRelation attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be
null.

version(int) The current version of this entity. Any


changes applied to the entity will
increment the version by 1.

providerId(long,readOnly) A reference to the provider. Cannot be


null.

eventId(long,readOnly) A reference to the event. Cannot be


null.

startTime(Date) The (collected) planned startTime (in


GMT) of the event according to the
associated provider. Null if none.

endTime(Date) The (collected) planned endTime (in


GMT) of the event according to the
associated provider. Null if none.

timeQualityRank(int) A (comparable) quality rank of the


estimated correctness of the start and
end times. Cannot be null, and must be
equal to or greater than zero.

offersLiveOdds(boolean) True if the provider intends to offer live


odds for this event, and false if not.
Cannot be null.

offersLiveTV(boolean) True if the provider intends to


broadcast the event live (as TV), and
false if not. Cannot be null.

2.8 Class EventStatus


Provides the status of an event, i.e. whether it has not started yet (i.e. is pending), is in progress, or has ended.

2.8.1 EventStatus attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity
will increment the version by 1.

name(String) The human-readable name of the status, e.g. "Pending", "In


Progress", or "Ended". The name cannot be null or empty, and it
must be unique among all event statuses. Its maximum length is
255 characters.

description(String) A description of this status. May be null. The maximum length is 255
characters.

2.9 Class EventTemplate


A template to which real events can refer.
The event template can be thought of as an event factory.
The primary purpose of the event template is to provide a means for relating recurring events.
For example, "Champions League" will be the event template for the "Champions League 2008", "Champions League 2009", etc. events.

34
The properties contain the current values. These will be copied as needed to the event instances as they are created. Therefore, event template properties can
change without affecting the history of event instances.
The tuple (name, eventTypeId, sportId) must be unique among event templates.

2.9.1 EventTemplate attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to


the entity will increment the version by 1.

name(String) The name of the event class. It cannot be null or empty. Its
maximum length is 255 characters.

eventTypeId(long,readOnly) A reference to the event type. Cannot be null.

sportId(long,readOnly) A reference to the sport. Cannot be null.

categoryId(long) A reference to the event category, or null if not applicable.

tier(Integer) An internal-use-only property (null value in this case). Offers


a way to rank tournaments by importance, lower value
means higher importance (1 is the highest).

url(String) A url, or null if none. If not null then it must be a valid URL.
Its maximum length is 255 characters.

venueId(Long) A reference to the venue (Location entity) at which new


event instances take place, or null if unknown or not
applicable.

rootPartId(Long) A reference to the root part of new event instances, or null if


unknown or not applicable.

isCyber(Boolean) An internal-use-only property (null value in this case). True,


if template of a tournament where computer plays against
another computer, false otherwise.

note(String) An internal-use-only note. May be null. The maximum


length is 255 characters.

2.10 Class EventCategory


The EventCategory groups events into certain categories (i.e ATP, WTA etc. for Tennis). The tuple (name, sportId) must be unique.

2.10.1 EventCategory attributes

Name Description
id(long,readOnly) The unique id of this
entity. Cannot be null.

version(int) The current version of


this entity. Any
changes applied to the
entity will increment
the version by 1.

name(String) The name of the


category. Cannot be
null.
Example: ATP

sportId(long,readOnly) A reference to a sport.


Cannot be null.

note(String) An internal-use-only
note. May be null. The
maximum length is 255
characters.

2.11 Class EventPartDefaultUsage


Provides a way to find an event part hierarchy for use with a newly created event.
The event part hierarchy is found as follows:
1. Lookup rootPartId by parentEventId=Event.parentId. If no hit then lookup using parentEvent.parentId and so on (up the event path towards the event path root). If
no hit, then continue.

35
2. Lookup rootPartId by {eventTypeId, sportId}. There must always be a hit here.
If parentEventId is null then eventTypeId and sportId must both be non-null. And if parentEventId is not null then sportId and eventTypeId must both be null.
The tuples {parentEventId} and {eventTypeId, sportId) must be unique.

2.11.1 EventPartDefaultUsage attributes

Name Description
id(long,readOnly) The unique id of this entity.
Cannot be null.

version(int) The current version of this


entity. Any changes applied to
the entity will increment the
version by 1.

parentEventId(Long,readOnly) A reference to an event


template. Cannot be null if
eventTypeId or sportId is null.
Must be null if eventTypeId or
sportId is not null.

eventTypeId(Long,readOnly) A reference to an event type.


Cannot be null if parentEventId
is null. Must be null if
parentEventId is not null.

sportId(Long,readOnly) A reference to a sport. Cannot


be null if parentEventId is null.
Must be null if parentEventId is
not null.

rootPartId(long,readOnly) A reference to the root event


part. Cannot be null.

2.12 Class EventPart


The event part provides a way of breaking down an event into smaller parts, typically using some fixed structure. The structure is hierarchical. Sub event parts may
overlap in time.
A root event part will always be "Whole Event".
For matches, there will be event parts as follows (for football):
1. Whole Match (= root part)
1.1 Ordinary Time (The standard match time containing 1st half and 2nd half of the match) - Has Whole Match as a parent eventPart.
1.1.1 First Half (The 1st half of the match and the extra time awarded by the referee) - Has Ordinary Time as a parent eventPart
1.1.2 Second Half (The 2nd half of the match and the extra time awarded by the referee) - Has Ordinary Time as a parent eventPart
1.2 Overtime (The Overtime in case of a draw during Ordinary Time) - Has Whole Match as a parent eventPart
1.2.1 Overtime Excluding Penalty Round (The overtime excluding the penalty round) - Has Overtime as a parent eventPart
1.2.1.1 First Half (The 1st half of the Overtime and the extra time awarded by the referee) - Has Overtime Excluding Penalty Round as a parent eventPart
1.2.1.2 Second Half (The 2nd half of the Overtime and the extra time awarded by the referee) - Has Overtime Excluding Penalty Round as a parent eventPart
1.2.2 Penalty Round (The eventPart representing the Penalty round) - Has Overtime as a parent eventPart
For leagues, there will be event parts representing each league round. We will follow the convention that if the "All Rounds" root part has id X, then the sub round
parts will have ids X+1, X+2, ..., X+N, where N is the number of rounds in the league.
For cups, there will be event parts for qualification, group and knockout phases, e.g. 1/8, 1/4, etc.
For race tournaments, there will be event parts for each race phase, e.g. "all races before the mountains".

2.12.1 EventPart attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will
increment the version by 1.

name(String) The name of the event part, e.g. "First Half". The name cannot be null or
empty. Its maximum length is 255 characters.

description(String) A description of this event part. May be null. The maximum length is 255
characters.

parentId(Long,readOnly) A reference to the parent event part, or null if none. Will be null only for root
event parts.

36
Name Description
orderNum(int) A sequential number used to time-order event parts with the same parent.
Cannot be null. For example, the orderNum of "First Half" can be 1 while the
orderNum of "Second Half" can be 2. This indicates that "Second Half"
comes after "First Half".

isDrawPossible(Boolean,readOnly) True if the event part can end in a draw, false if the event part cannot end in
a draw, or null otherwise.

isBreak(boolean) True if the event part is an intermission, false otherwise.


Published to internal clients only.

2.13 Class EventActionTypeUsage - Not published


Specifies how event action types (and hence their event action instances) can be used across event types and sports.
The tuple (eventActionTypeId, eventTypeId, sportId) must be unique.

2.13.1 EventActionTypeUsage attributes

Name Description
id(long,readOnly) The unique id of this
entity. Cannot be
null.

version(int) The current version


of this entity. Any
changes applied to
the entity will
increment the
version by 1.

eventActionTypeId(long,readOnly) A reference to the


event action type.
Cannot be null.

eventTypeId(long,readOnly) A reference to an
event type. Cannot
be null.

sportId(long,readOnly) A reference to a
sport. Cannot be
null.

2.14 Class StreamingProviderEventRelation


The StreamingProviderEventRelation contains provider-specific streaming event information. The tuple (streamingproviderId, eventId, channel) must be unique.

2.14.1 StreamingProviderEventRelation attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the
entity will increment the version by 1.

streamingproviderId(long,readOnly) A reference to the streaming provider. Cannot be null.

eventId(long, readOnly) A reference to the event. Cannot be null.

channel(String, readOnly) The channel where the streaming provider broadcasts the
event. Cannot be null.
The channel may be used with StreamingProvider.urlTemplate
to find out streaming URL
Example: channel="pro_cast2",
StreamingProvider.urlTemplate="https://www.twitch.tv/{channel}"
=> streaming URL="https://www.twitch.tv/pro_cast2"

language(String, readOnly) The channel language, or null if unknown.

2.15 Class StreamingProvider


Represents a real-world currency, such as Twitch, Youtube, etc.

37
2.15.1 StreamingProvider attributes

Name Description
id(long,readOnly) The unique id of this entity.
Cannot be null.

version(int) The current version of this


entity. Any changes applied to
the entity will increment the
version by 1.

name(String) The name of the streaming


platform. Cannot be null or
empty. Its maximum length is
255 characters.

urlTemplate(String) A URL template to the


streaming platform's web site.
Cannot be null or empty. Its
maximum length is 255
characters.

38
Participant
1 Diagram

2 Classifiers
2.1 Class Participant
Represents a real-world participant.
The term participant should be understood broadly and includes any (real-world) entity that can (theoretically) participate in an event.
A participant's properties, and the semantics thereof, is determined by the participant type.

2.1.1 Participant attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

typeId(long,readOnly) A reference to ParticipantType. Cannot be null.

name(String) The name of the participant. It is not null and non-empty, and its maximum length is 255 characters.

firstName(String) The first name of the participant, including middle-names (if any). It is null if unknown or not applicable. If it is not null, then
it is non-empty and its maximum length is 255 characters.

lastName(String) The last name of the participant. It is null if unknown or not applicable. If it is not null, then it is non-empty and its
maximum length is 255 characters.

shortName(String) The shortened/abbreviated/commonly used name of the participant (if any). If it is not null, then it is non-empty and its
maximum length is 255 characters.

isMale(Boolean) Indicates the gender of the participant: True if male, false if female, and null if unknown or not applicable.

birthTime(Date) The time of birth for this participant, or null if unknown or not applicable.

countryId(Long) A reference to the location (which must be a country) that is the nationality of this participant. It is null if unknown or not
applicable.
It is also null if the participant has a multiple nationality. [Design note: In time we'll need to represent this in its own
relational table.]

url(String) A URL associated with the participant, or null if none or unknown. If not null then url must be a valid URL. Its maximum

39
Name Description
length is 255 characters.

logoURL(String) An URL of the participant logo/crest, or null if none or unknown. If not null then url must be a valid URL. Its maximum
length is 255 characters.

retirementTime(Date) The time of retirement (in GMT) for this participant, or null if not retried, unknown, or not applicable.
Aside from its direct information value, this property is useful in determining which participants are "current" and which can
be moved to the history.

lastEventParticipationTime(Date) Indicates when the participant last participated in an event, or null if currently participating in an event.
[not published to clients]

note(String) An internal-use-only note. May be null. The maximum length is 255 characters.

2.2 Class ParticipantUsage


Specifies the possible sports that a participant can participate in.
The tuple (participantId, sportId) must be unique.

2.2.1 ParticipantUsage attributes

Name Desciption
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

participantId(long,readOnly) A reference to the participant. It cannot be null.

sportId(long,readOnly) A reference to the sport. It cannot be null.

2.3 Class EventParticipantRelation


Specifies that a certain participant participates in a certain event (or event part), in what role(s) (if any), and as part of what parent(s) (if any).
The EventParticipantRelation can model a lot. [Design note: Maybe even too much. Maybe we should separate it into several classes; but the drawback with doing
this is increased complexity and decreased lookup performance.]
We can model:
(1) Event (part) participation: That a participant participates in one or more parts of an event.
(2) Role participation: In what capacity the participant participates in the event. This is specified as roles. A participant can have multiple roles in the same event.
(3) Indirect participation: That a participant participates indirectly through another participant. For example, a player participates (indirectly) because he is part of the
team that participates (directly) in the event.
(4) Out-of-game participation: Referees, coaches, sponsors, etc.
(5) Line ups. For this we simply use the EventParticipantRelation entities associated with the first event part of the event.
With matches, the home and away participants can be found by looking up by (eventId, <first>, X, "Home"/"Away", null). "X" is the id of the Home/Away participant.
Generally, a sub-event can only include in-game participants that are also in-game participants on the parent event.
The tuple (eventId, eventPartId, participantId, participantRoleId, parentParticipantId) is unique.

2.3.1 EventParticipantRelation attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

eventId(long,readOnly) A reference to the event. Cannot be null.

eventPartId(long,readOnly) A reference to the event part. Cannot be null.

participantId(long,readOnly) A reference to the participant. Cannot be null.

participantRoleId(long) A reference to a role that the participant plays/played in the event. Cannot be null.
Note that every participant plays at least one role in an event. However, this role may not be known (to us). If so, then a more
general/abstract role must be chosen.

parentParticipantId(Long) A reference to the parent participant of this participant, or null if none. This property is typically used with team players.

40
2.4 Class ParticipantRole
A ParticipantRole defines a specific role that a Participant can "play" (or have/had) in an event.
[Design note: We do not currently organize participant roles in a hierarchical manner, e.g. "Player" is a parent of "Attacker". We can add this later, if needed, using a
parentId property or by adding a ParticipantRoleRelation entity type.]
Examples : Home, Away, Attacker, Player, Midfielder, Defender, Keeper, Substitute, Referee, Coach

2.4.1 ParticipantRole attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the role. It is not null and not empty, and it must be unique among participant roles.

description(String) A description of the participant role, or null if none. Its maximum length is 255 characters.

isPrimary(boolean,readOnly) True if this role is a primary (in-game) role, and false otherwise. Cannot be null.
Participants that participate in an event in a primary role constitute that event's primary (i.e. actual and in-game) participants.
For example, "Attacker" and "Player" are primary roles, while "Coach" and "Referee" are not.

2.5 Class ParticipantTypeRoleUsage - not published to clients


Associates participant types and roles with sports. The tuple (participantTypeId, participantRoleId, sportId) must be unique.

2.5.1 ParticipantTypeRoleUsage attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

participantTypeId(long,readOnly) A reference to the participant type. It cannot be null.

participantRoleId(long,readOnly) A reference to the participant role. It cannot be null.

sportId(long,readOnly) A reference to the sport. It cannot be null.

2.6 Class ParticipantType


Defines the various types of participant.

2.6.1 ParticipantType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the participant type. It cannot be null or empty, and it must be unique among participant types.

description(String) A description of the participant type, or null if none. Its maximum length is 255 characters.

isIndividual(boolean,readOnly) True if participants of this type are individuals, and false if not.

hasName(Boolean,readOnly) True if the participant's name property will be non-null, false if null, and null if either null or non-null.

hasFirstName(Boolean,readOnly) True if the participant's firstName property will be non-null, false if null, and null if either null or non-null.

hasLastName(Boolean,readOnly) True if the participant's lastName property will be non-null, false if null, and null if either null or non-null.

hasIsMale(Boolean,readOnly) True if the participant's isMale property will be non-null, false if null, and null if either null or non-null.

hasBirthTime(Boolean,readOnly) True if the participant's birthTime property will be non-null, false if null, and null if either null or non-null.

hasNationalityId(Boolean,readOnly) True if the participant's nationalityId property will be non-null, false if null, and null if either null or non-null.

hasRetirementTime(Boolean,readOnly) True if the participant's retirementTime property will be non-null, false if null, and null if either null or non-null.

41
2.7 Class ParticipantRelation
Defines a relationship between two participants, including the associated roles, in a certain time period.
The nature of the relationship is defined by the relation type.
All relations are unidirectional. However, depending on type, some reversals may hold semantic meaning, for example the reverse of "Owns" is "Owned By".
The primary use of the ParticipantRelation is to express player-team relations, along with the role(s) that the player have in the team.
The tuple (typeId, fromParticipantId, toParticipantId, paramParticipantRoleId) must be unique within the same time period.

2.7.1 ParticipantRelation attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

typeId(long,readOnly) A reference to the participant relation type. It cannot be null.

fromParticipantId(long,readOnly) A reference to the "from" participant. It cannot be null.

toParticipantId(long,readOnly) A reference to the "to" participant. It cannot be null.

startTime(Date) The start of the time period of the relation, or null if unknown or "always applied in past".

endTime(Date) The end of the time period of the relation, or null if unknown or "always applies in future".

paramParticipantRoleId(Long,readOnly) A reference to the participant role, if any.


The relation type determines whether the participant role can be null, and whether it relates to the "from participant"
or the "to participant". The participant role (if any) must be a possible role for the participant with which it is
associated.

2.8 Class ParticipantRelationType


Specifies the various relation types.
Examples:
* "Plays For" (e.g. player plays for team)
- paramParticipantRoleId(s) specify which role(s), if any, the player (as default) fulfills in the team. For use with e.g. general (i.e. non-event specific) team line-ups.
* "Owned By" (e.g. horse owned by person)
- paramParticipantRoleId is null.
The paramParticipantRoleId depends on the type.

2.8.1 ParticipantRelationType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the relation type. The name cannot be null or empty, and it must be unique among participant
relation types. Its maximum length is 255 characters.

description(String) A description of the participant relation type, or null if none. Its maximum length is 255 characters.

hasParamParticipantRoleId(Boolean,readOnly) True if the participant relation's paramParticipantRoleId property will be non-null, false if null, and null if either
null or non-null.

paramParticipantRoleIdDescription(String) A description of the paramParticipantRoleId property, or null if none. Its maximum length is 255 characters.

42
Stats And Scores
1. Diagram

2. Classifiers
2.1 Class Event
Represents a real-world sports event. See Event.

2.2 Class EventAction


Represents a zero-time event (or action) within an event, e.g. a goal, a ball possession change, a card given, a substitution, a penalty kick, etc.
Also known as an event incident.

2.2.1 EventAction attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

statusId(long) A reference to the status. Cannot be null.

typeId(long,readOnly) A reference to the event action type. Cannot be null.

eventId(long,readOnly) A reference to the event in which the action occurs. Cannot be null.

providerId(long,readOnly) A reference to the provider (source) that originally created this action. Cannot be null.

eventPartId(long,readOnly) A reference to the event part.

paramFloat1(Float,readOnly) A generic parameter slot whose value and semantics is determined by the event action type.

paramParticipantId1(Long,readOnly) A generic parameter slot whose value and semantics is determined by the event action type. If not null then it is a
reference to a participant.

43
Name Description
paramParticipantId2(Long,readOnly) A generic parameter slot whose value and semantics is determined by the event action type. If not null then it is a
reference to a participant.

isManuallySet(boolean) True if the event action was created/updated manually or false otherwise.
Published to internal clients only.

2.3 Class EventActionStatus


Provides the status (and availabilty) of an event action.

2.3.1 EventActionStatus attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the status. Cannot be null or empty, and must be unique among all statuses. Its maximum length is 255
characters.

isAvailable(boolean,readOnly) True if the associated event action is available, and false otherwise. Cannot be null.

description(String) A description of this status. May be null. The maximum length is 255 characters.

2.4 Class EventActionType


Defines the possible types of actions that can take place in an event.
Each event action has a type that determines its properties.
Examples:
* Event Started (by time)
* Event Ended (by time)
* Goal Scored (by participant1)
* Substitution (out: participant1, in: participant2)
* Penalty Kick (kicker: participant1)
* Yellow Card (to participant1)
* Red Card (to participant1)

2.4.1 EventActionType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the type. The name cannot be null or empty, and it must be unique among types. Its maximum
length is 255 characters.

description(String) A description of the event action type, or null if none. Its maximum length is 255 characters.

hasParamFloat1(Boolean,readOnly) True if the event action's paramFloat1 property will be non-null, false if null, and null if either null or non-null.

paramFloat1Description(String) A description of the paramFloat1 property, or null if none. Its maximum length is 255 characters.

hasParamParticipantId1(Boolean,readOnly) True if the event action's paramParticipantId1 property will be non-null, false if null, and null if either null or non-
null.

paramParticipantId1Description(String) A description of the paramParticipantId1 property, or null if none. Its maximum length is 255 characters.

hasParamParticipantId2(Boolean,readOnly) True if the event action's paramParticipantId2 property will be non-null, false if null, and null if either null or non-
null.

paramParticipantId2Description(String) A description of the paramParticipantId2 property, or null if none. Its maximum length is 255 characters.

2.5 Class EventActionTypeUsage


Specifies how event action types (and hence their event action instances) can be used across event types, sports and event parts.
The tuple (eventActionTypeId, eventTypeId, sportId, eventPartId) must be unique.

44
2.5.1 EventActionTypeUsage attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

eventActionTypeId(long,readOnly) A reference to the event action type. Cannot be null.

eventTypeId(long,readOnly) A reference to an event type. Cannot be null.

eventPartId(long,readOnly) A reference to the event part. Cannot be null.

sportId(long,readOnly) A reference to a sport. Cannot be null.

2.6 Class EventActionDetail


Represents a detail of an event action.
For example the time of a substitution or the starting time of a game.

2.6.1 EventActionDetail attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

typeId(long,readOnly) A reference to the type. Cannot be null.

eventActionId(long) A reference to the event action. Cannot be null.

statusId(long) A reference to the status. Cannot be null.

paramFloat1(Float) A generic parameter slot whose value and semantics is determined by the event action detail type.

paramFloat2(Float) A generic parameter slot whose value and semantics is determined by the event action detail type.

paramParticipantId1(Long) A generic parameter slot whose value and semantics is determined by the event action detail type. If not null then it is a reference
to a participant.

paramString1(String) A generic parameter slot whose value and semantics is determined by the event action detail type.

paramBoolean1(Boolean) A generic parameter slot whose value and semantics is determined by the event action detail type.

isManuallySet(boolean) True if the event action detail was created/updated manually or false otherwise.
Published to internal clients only.

2.7 Class EventActionDetailStatus


Provides the status (and availabilty) of an event action detail.

2.7.1 EventActionDetailStatus attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the status. Cannot be null or empty, and must be unique among all statuses. Its maximum length is 255
characters.

isAvailable(boolean,readOnly) True if the associated event action detail is available, and false otherwise. Cannot be null.

description(String) A description of this status. May be null. The maximum length is 255 characters.

2.8 Class EventActionDetailType


Defines the possible types of event action details that are related to an event action.
Each event action detail has a type that determines its properties.
Examples:
* Team (by participant1)
* Loosing Points (by float1)

45
* Scoring Method (by string1)
* Assist (by participant1)
* Timer (by float1)

2.8.1 EventActionDetailType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the event action detail type. Cannot be null or empty, and must be unique among all event action
detail types. Its maximum length is 255 characters.

description(String) A description of the event action detail type, or null if none. Its maximum length is 255 characters.

hasParamFloat1(Boolean,readOnly) True if the event action detail's paramFloat1 property will be non-null, false if null, and null if either null or non-
null.

paramFloat1Description(String) A description of the paramFloat1 property, or null if none. Its maximum length is 255 characters.

hasParamFloat2(Boolean,readOnly) True if the event action detail's paramFloat2 property will be non-null, false if null, and null if either null or non-
null.

paramFloat2Description(String) A description of the paramFloat2 property, or null if none. Its maximum length is 255 characters.

hasParamParticipantId1(Boolean,readOnly) True if the event action detail's paramParticipantId1 property will be non-null, false if null, and null if either null
or non-null.

paramParticipantId1Description(String) A description of the paramParticipantId1 property, or null if none. Its maximum length is 255 characters.

hasParamString1(Boolean,readOnly) True if the event action detail's paramString1 property will be non-null, false if null, and null if either null or non-
null.

paramString1Description(String) A description of the paramString1 property, or null if none. Its maximum length is 255 characters.

paramString1PossibleValues(String,readOnly) Contains the possible (non-null) values of the event action detail's paramString1 property. The values are listed
in CSV format. Whether null is a possible value is determined by the hasParamString1 property.

hasParamBoolean1(Boolean,readOnly) True if the event action detail's paramBoolean1 property will be non-null, false if null, and null if either null or
non-null.

paramBoolean1Description(String) A description of the paramBoolean1 property, or null if none. Its maximum length is 255 characters.

2.9 Class EventActionDetailTypeUsage


Specifies how event action detail types (and hence their event action detail instances) can be used across event action types and sports.
The tuple (eventActionDetailTypeId, eventActionTypeId, sportId) must be unique.

2.9.1 EventActionDetailTypeUsage attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

eventActionDetailTypeId(long,readOnly) A reference to an event action detail type. Cannot be null.

eventActionTypeId(long,readOnly) A reference to an event action type. Cannot be null.

sportId(long,readOnyly A reference to a sport. Cannot be null.

2.10 Class EventInfo


Contains statistical information about the incidents (actions) that happen in an event.
For example: the total number of red cards in the event is X.

2.10.1 EventInfo attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

46
Name Description
statusId(long) A reference to the status. Cannot be null.

typeId(long,readOnly) A reference to the type. Cannot be null.

eventId(long,readOnly) A reference to the event. Cannot be null.

providerId(long,readOnly) A reference to the data source provider. Cannot be null.

statusId(long) A reference to the status. Cannot be null.

eventPartId(long,readOnly) A reference to the event part. Cannot be null.

paramFloat1(Float) A generic parameter slot whose value and semantics is determined by the event info type.

paramFloat2(Float) A generic parameter slot whose value and semantics is determined by the event info type.

paramParticipantId1(Long) A generic parameter slot whose value and semantics is determined by the event info type. If not null then it is a reference
to a participant.

paramParticipantId2(Long) A generic parameter slot whose value and semantics is determined by the event info type. If not null then it is a reference
to a participant.

paramEventPartId1(Long) A generic parameter slot whose value and semantics is determined by the event info type. If not null then it is a reference
to an event part.

paramString1(String) A generic parameter slot whose value and semantics is determined by the event info type.

paramBoolean1(Boolean) A generic parameter slot whose value and semantics is determined by the event info type.

paramEventStatusId1(Long) A generic parameter slot whose value and semantics is determined by the event info type. If not null then it is a reference
to an event status.

paramTime1(Date) A generic parameter slot whose value and semantics is determined by the event info type.

paramScoringUnitId1(Long, A reference to the scoring unit. Can be null.


readOnly)

isManuallySet(boolean) True if the event info was created/updated manually or false otherwise.
Published to internal clients only.

2.11 Class EventInfoStatus


Provides the status (and availability) of an event info.

2.11.1 EventInfoStatus attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the status. Cannot be null or empty, and must be unique among all statuses. Its maximum length is 255
characters.

isAvailable(boolean,readOnly) True if the associated event info is available, and false otherwise. Cannot be null.

description(String) A description of this status. May be null. The maximum length is 255 characters.

2.12 Class EventInfoType


Defines the possible types of event infos that can take place in an event.
Each event info has a type that determines its properties.
Examples:
* Score (by float1, float2, participant1, participant2)
* Possesion (by participant1)
* Suspensions (by float1, float2, participant1, participant2)
* Corners (by float1, float2, participant1, participant2)

47
2.12.1 EventInfoType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the type. The name cannot be null or empty, and it must be unique among types. Its
maximum length is 255 characters.

description(String) A description of this type. May be null. The maximum length is 255 characters.

hasParamFloat1(Boolean,readOnly) True if the event info's paramFloat1 property will be non-null, false if null, and null if either null or non-
null.

paramFloat1Description(String) A description of the paramFloat1 property, or null if none. Its maximum length is 255 characters.

hasParamFloat2(Boolean,readOnly) True if the event info's paramFloat2 property will be non-null, false if null, and null if either null or non-
null.

paramFloat2Description(String) A description of the paramFloat2 property, or null if none. Its maximum length is 255 characters.

hasParamParticipantId1(Boolean,readOnly) True if the event info's paramParticipantId1 property will be non-null, false if null, and null if either null
or non-null.

paramParticipantId1Description(String) A description of the paramParticipantId1 property, or null if none. Its maximum length is 255
characters.

hasParamParticipantId2(Boolean,readOnly) True if the event info's paramParticipantId2 property will be non-null, false if null, and null if either null
or non-null.

paramParticipantId2Description(String) A description of the paramParticipantId2 property, or null if none. Its maximum length is 255
characters.

hasParamEventPartId1(Boolean,readOnly) True if the event info's paramEventPartId1 property will be non-null, false if null, and null if either null
or non-null.

paramEventPartId1Description(String) A description of the paramEventPartId1 property, or null if none. Its maximum length is 255
characters.

hasParamString1(Boolean,readOnly) True if the event info's paramString1 property will be non-null, false if null, and null if either null or
non-null.

paramString1Description(String) A description of the paramString1 property, or null if none. Its maximum length is 255 characters.

paramString1PossibleValues(String,readOnly) Contains the possible (non-null) values of the event info's paramString1 property. The values are
listed in CSV format. Whether null is a possible value is determined by the hasParamString1
property.

hasParamBoolean1(Boolean,readOnly) True if the event info's paramBoolean1 property will be non-null, false if null, and null if either null or
non-null.

paramBoolean1Description(String) A description of the paramBoolean1 property, or null if none. Its maximum length is 255 characters.

hasParamEventStatusId1(Boolean,readOnly) True if the event info's paramEventStatusId1 property will be non-null, false if null, and null if either
null or non-null.

paramEventStatusId1Description(String) A description of the paramEventStatusId1 property, or null if none. Its maximum length is 255
characters.

hasParamTime1(Boolean,readOnly) True if the event info's paramTime1 property will be non-null, false if null, and null if either null or non-
null.

paramTime1Description(String) A description of the paramTime1 property, or null if none. Its maximum length is 255 characters.

paramParticipantIdsMustBeOrdered(boolean,readOnly) Specifies if the event info's paramParticipantId1 and paramParticipantId2 properties must be
ascending ordered. It can be true only if hasParamParticipantId1 and hasParamParticipantId2 are
true.

hasParamScoringUnitId1(boolean,readOnly) True if the event info's paramScoringUnitId1 property will be non-null, false if null, and null if either
null or non-null.

paramScoringUnitId1Description(String) A description of the paramScoringUnitId1 property, or null if none. Its maximum length is 255
characters.

2.13 Class EventInfoTypeUsage


Specifies how event info types (and hence their event info instances) can be used across event types, event parts and sports.
The tuple (eventInfoTypeId, eventTypeId, eventPartId, sportId) must be unique.

48
2.13.1 EventInfoTypeUsage attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

eventInfoTypeId(long,readOnly) A reference to an event info type. Cannot be null.

eventTypeId(long,readOnly) A reference to an event type. Cannot be null.

eventPartId(long,readOnly) A reference to an event action part. Cannot be null.

sportId(long,readOnly) A reference to a sport. Cannot be null.

scoringUnitId(Long,readOnly) A reference to a scoring unit or null if none or not applicable.

2.14 Class EventParticipantInfo


Contains information about the participants that take part in an event.

2.14.1 EventParticipantInfo attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

typeId(long,readOnly) A reference to the type. Cannot be null.

eventId(long,readOnly) A reference to the event. Cannot be null.

providerId(long,readOnly) A reference to the data source provider. Cannot be null.

statusId(long) A reference to the status. Cannot be null.

eventPartId(long,readOnly) A reference to the event part. Cannot be null.

participantId(long,readOnly) A reference to the participant. Cannot be null.

isManuallySet(boolean) True if the event participant info was created/updated manually or false otherwise.
Published to internal clients only.

2.15 Class EventParticipantInfoStatus


Provides the status (and availabilty) of an event participant info.

2.15.1 EventParticipantInfoStatus attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the status. Cannot be null or empty, and must be unique among all statuses. Its maximum length is 255
characters.

isAvailable(boolean,readOnly) True if the associated event participant info is available, and false otherwise. Cannot be null.

description(String) A description of this status. May be null. The maximum length is 255 characters.

2.16 Class EventParticipantInfoType


Defines the possible types of participant infos that can take place in an event.
Each event participant info has a type that determines its properties.
Examples:
* Lineup (by participant)

49
2.16.1 EventParticipantInfoType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the type. The name cannot be null or empty, and it must be unique among types. Its maximum length is 255 characters.

description(String) A description of this type. May be null. The maximum length is 255 characters.

2.17 Class EventParticipantInfoTypeUsage


Specifies how event participant info types (and hence their event participant info instances) can be used across event types, event parts and sports.
The tuple (eventParticipantInfoTypeId, eventTypeId, eventPartId, sportId) must be unique.

2.17.1 EventParticipantInfoTypeUsage attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

eventParticipantInfoTypeId(long,readOnly) A reference to an event participant info type. Cannot be null.

eventTypeId(long,readOnly) A reference to an event type. Cannot be null.

eventPartId(long,readOnly) A reference to an event part. Cannot be null.

sportId(long,readOnly) A reference to a sport. Cannot be null.

2.18 Class EventParticipantInfoDetail


Represents a detail of an event participant info.
For example the shirt number or the team of a participant that is part of an event when the game begins.

2.18.1 EventParticipantInfoDetail attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

statusId(long) A reference to the status. Cannot be null.

typeId(long,readOnly) A reference to the type. Cannot be null.

eventParticipantInfoId(long,readOnly) A reference to the event participant info. Cannot be null.

paramFloat1(Float) A generic parameter slot whose value and semantics is determined by the event participant info detail type.

paramParticipantId1(Long) A generic parameter slot whose value and semantics is determined by the event participant info detail type. If not null
then it is a reference to a participant.

paramBoolean1(Boolean) A generic parameter slot whose value and semantics is determined by the event participant info detail type.

2.19 Class EventParticipantInfoDetailStatus


Provides the status (and availabilty) of an event participant info detail.

2.19.1 EventParticipantInfoDetail attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the status. Cannot be null or empty, and must be unique among all statuses. Its maximum length is 255
characters.

50
isAvailable(boolean,readOnly) True if the associated event participant info detail is available, and false otherwise. Cannot be null.

description(String) A description of this status. May be null. The maximum length is 255 characters.

2.20 Class EventParticipantInfoDetailType


Defines the possible types of event participant info details that are related to an event participant info.
Each event participant info detail has a type that determines its properties.
Examples:
* Shirt Number (by float1)
* Player Team (by participant1)
* Substitute (by boolean1)

2.20.1 EventParticipantInfoDetailType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the type. The name cannot be null or empty, and it must be unique among types. Its maximum
length is 255 characters.

description(String) A description of this type. May be null. The maximum length is 255 characters.

hasParamFloat1(Boolean,readOnly) True if the event participant info detail's paramFloat1 property will be non-null, false if null, and null if either null or
non-null.

paramFloat1Description(String) A description of the paramFloat1 property, or null if none. Its maximum length is 255 characters.

hasParamParticipantId1(Boolean,readOnly) True if the event participant info detail's paramParticipantId1 property will be non-null, false if null, and null if either
null or non-null.

paramParticipantId1Description(String) A description of the paramParticipantId1 property, or null if none. Its maximum length is 255 characters.

hasParamBoolean1(Boolean,readOnly) True if the event participant info detail's paramBoolean1 property will be non-null, false if null, and null if either null
or non-null.

paramBoolean1Description(String) A description of the paramBoolean1 property, or null if none. Its maximum length is 255 characters.

hasParamString1(Boolean,readOnly) True if the event participant info detail's paramString1 property will be non-null, false if null, and null if either null
or non-null.

paramString1Description(String) A description of the paramString1 property, or null if none. Its maximum length is 255 characters.

paramString1PossibleValues(String) Contains the possible (non-null) values of the participant info detail's paramString1 property. The values are listed
in CSV format. Whether null is a possible value is determined by the hasParamString1 property.

2.21 Class EventParticipantInfoDetailTypeUsage


Specifies how event participant info detail types (and hence their event participant info detail instances) can be used across event participant info types and sports.
The tuple (eventParticipantInfoDetailTypeId, eventParticipantInfoTypeId, sportId) must be unique.

2.21.1 EventParticipantInfoDetailTypeUsage attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

eventParticipantInfoDetailTypeId(long,readOnly) A reference to an event participant info detail type. Cannot be null.

eventParticipantInfoTypeId(long,readOnly) A reference to an event participant info type. Cannot be null.

sportId(long,readOnly) A reference to a sport. Cannot be null.

2.22 Class ScoringUnit


Represents the mean of scoring.
Examples: Goal, Corner, Yellow card, Touchdown, etc.

51
2.22.1 ScoringUnit attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the scoring unit. The name cannot be null or empty, and it must be unique among types. Its maximum length is 255
characters.

description(String) A description of this scoring unit. May be null. The maximum length is 255 characters.

52
Event Info Types

Id Name
1 Score

2 Yellow Cards

3 Yellow-Red
Cards

4 Red Cards

5 Free kicks

6 Offsides

7 Goal Kicks

8 Throw-ins

9 Corners

10 Penalty Kicks

11 Suspensions

12 Substitutions

13 Penalty Kicks
Missed

14 Penalty Kicks
Scored

15 Points Won

16 Drives

17 Passes

18 Turnovers

19 Coach
Challenges

20 One-Point
Conversions

21 Two-Points
Conversions

22 Touchdowns

23 Safeties

24 Field Goals

26 Penalties Total
Time

27 Penalty Shots

28 Two Minutes
Penalties

29 Two-Plus-Two Minutes
Penalties

30 Five Minutes
Penalties

31 Active Penalties

33 Race To 5 Points
Score

34 Race To 10 Points
Score

35 Race To 15 Points
Score

53
Id Name
36 Race To 20 Points
Score

37 Serve

38 Game Points

39 Set Points

40 Possession

41 Assists

42 Fouls

43 Free Throws
Missed

44 Free Throws
Scored

45 Free Throws
Pending

46 Free Throws
Awarded

47 Rebounds

48 Three Pointers

49 Two Pointers

50 Points per set

51 Number of event
parts

53 Aces

54 Double Faults

55 Breaks

57 Deciding point
rule

58 No Tiebreak in the Last


Set

59 Surface

60 Number of Points in
Tiebreak

62 Hits

63 Errors

64 Misses

65 Tries

66 Four points

67 Six points

68 Overs

69 Extras

70 Wickets

71 Yards
Distance

72 Active Down

73 Yards To Next
Down

76 Penalty Throw
Missed

77 Penalty Throw
Scored

54
Id Name
78 Games
Won

79 Runs

80 Home
Runs

81 One Runs

83 Two Runs

84 Three Runs

85 One Home
Runs

86 Two Home
Runs

87 Three Home
Runs

88 Grand
Slams

89 Outs

90 Race To 3 Points
Score

91 Minutes per
quarter

92 Current event
status

93 Bets cut-off time

94 Coverage

95 Match Time

96 Remaining time in
period

98 Highest
Breaks

99 Current Football Match


Action

100 Shots On
Target

101 Shots Off Target

102 Possession
Percentage

104 Win Percentage 1st


Serve

105 Break Point


Conversions

106 Win Percentage 2nd


Serve

107 Current Tennis Match


Action

108 Current Basketball Match


Action

109 Super-Tiebreak in Final


Set

110 Goals

111 Behinds

112 180s

116 Current Innings


Status

55
Id Name
118 Team
Declared

119 Number Of
Runners

122 Bomb Timer

123 Current CounterTerrorist


Team

124 Period Time

127 Number Of
Rounds

139 Frags

140 Towers

141 Barracks

142 Aegis

143 Net Worth

144 Kills

145 Inhibitors

146 Dragons

147 Barons

149 Gold

151 Decision

152 Race Type

153 Dangerball

154 Roshans

155 Worker Kills

156 Godlike Streak

157 Mega Creeps


Spawned

158 Courier Kill

159 Largest Multi Kill

160 Bomb
Planted

162 Wides

163 Boundaries

165 Penalties
Taken

166 Penalties
Converted

167 Rushing
Yards

168 Sacks

169 Drop Goals

170 Checkouts

171 Centuries

173 Service
Breaks

174 Headshots

175 Damage

56
Id Name
177 Attempted Field
Goals

178 Blocks

179 Three Pointers


Attempted

180 Two Pointers


Attempted

181 Steals

182 Offensive
Rebounds

183 Defensive
Rebounds

184 Technical Fouls

185 Free Throws


Percentage

186 Two Pointers


Percentage

187 Three Pointers


Percentage

188 Field Goals


Percentage

189 Missed Field


Goals

190 Offense Yards

191 Passing Yards

192 Penalties Yards

193 Punts

194 Rushing
Touchdowns

195 Passing
Touchdowns

196 Turnover
Touchdowns

197 Interceptions
Thrown

198 Fumbles Lost

199 First Downs

200 Longest Team


Touchdown

201 Longest Team Field


Goal

202 Match Time


Multiplier

203 Dangerball 2

204 Chosen
Round

57
Event Actions Types and Details Types
Event Action Types

Id Name
7 Goal
Scored

8 Yellow Card
Shown

9 Yellow-Red Card
Shown

10 Red Card
Shown

11 Substitution

12 Penalty Kick
Awarded

13 Penalty Kick
Missed

14 Corner Kick

15 Drive

16 Touchdown
Scored

17 Two Point Conversion


Scored

18 Extra Point
Scored

19 Field Goal
Scored

20 Safety
Scored

21 Point Scored

22 Timeout

23 Game
Point

24 Set Point

25 Two Points
Scored

26 Three Points
Scored

27 Free Throw
Scored

28 Free Throw
Missed

29 Game
Won

30 Tie-break
Won

31 Set Won

32 Point Won

33 Suspension

34 Try Scored

35 Conversion
Scored

58
Id Name
36 Drop Goal
Scored

37 Exclusion

38 Penalty Throw
Awarded

39 Penalty Throw
Scored

40 Penalty Throw
Missed

41 Penalty Round
Kick

44 Race to X
Points

45 End Of
Over

46 Race to X
Frames

47 Race to X
Games

48 Race to X
Goals

49 Baron Slain

50 Dragon Slain

51 Roshan
Slain

52 Tower
Destroyed

53 Worker Killed

54 Barrack
Destroyed

55 Inhibitor
Destroyed

57 Kill

58 Power-up Rune
Spawned

59 Race to X Kills

60 Race to X
Rounds

61 Round
Won

63 Dragon
Spawned

64 Ball Potted

65 Turnover
Commited

66 180 Scored

67 Foul
Commited

69 Leg Won

70 Match
Ended

71 Jump Ball
Winner

72 Missed Field
Goal

59
Id Name
73 Single
Scored

74 First Basket
Scored

76 First Touchdown
Scored

77 First Points
Scored

78 First Team To Call


Timeout

Event Action Detail Types

Id Name
1 Team

2 Timer

3 Player

4 Drive Result

5 Suspension
Minutes

6 Break

7 Losing
Points

8 Scoring
Method

9 Assist

10 Secondary
Assist

11 Converted

12 First Participant To
X

13 Runs
Scored

14 Wickets
Lost

15 Method Of
Scoring

16 Power-up Rune
Type

17 Victim

18 Headshot

20 Dragon
Type

21 Colour

22 Result
Type

23 Basketball Method Of
Scoring

24 Am. Football Method Of


Scoring

60
Event Participant Info Types and Detail Types
Event Participant Info Types

Id Name
1 Lineup

2 Performance

3 Number of Players in Team

4 Batsman Performance

5 Bowler Performance

Event Participant Info Detail Types

Id Name
1 Shirt Number

2 Player Team

3 Substitute

4 Finish Position

5 Starting position

6 Points Scored

7 Starting Price

8 Non Runner

9 Number

10 Draw

11 Number of Players

12 Run

13 Balls Faced

14 Fours

15 Sixes

16 Strike Rate

17 Overs

18 Maiden

19 Runs Conceded

20 Wicket

22 Wide

23 No Ball

24 Zeros

25 Economy Rate

26 Did Not Finish

27 Form

28 Deaths

29 Kills

30 Assists

31 Level

61
Id Name
32 Hero Healing

33 Hero Damage

34 Gold

35 Worth

36 Tower Damage

37 Rush Yards

38 Passing Yards

39 Rebounds

40 Three Pointers

41 Blocks

42 Steals

44 Field Goals

45 Field Goals Attempted

46 Two Pointers

47 Two Pointers Attempted

48 Three Pointers Attempted

49 Free Throws

50 Free Throws Attempted

51 Plus/Minus Points

52 Offensive Rebounds

53 Deffensive Rebounds

54 Fouls

55 Turnovers

56 Blocked Shots

57 Blocks Against

58 Technical Fouls

59 Minutes Played

60 Did Not Play

61 Kicking Points

62 Receiving Yards

63 Rushing Attempts

64 Longest Thrown Pass

65 Longest Received Pass

66 Receptions

68 Passing Touchdowns

69 Interceptions

70 Touchdowns

62
Betting
1. Diagram

2. Classifiers
2.1 Class BettingOffer
A betting offer represents an opportunity for a bet between two parties: the odds/bet provider and a better/punter (typically a private person). A betting offer is tied to a
Source from which it is collected.
A betting offer can either back or lay an outcome. A back bet is on the outcome to happen. A lay bet is on the outcome NOT to happen. Hence, a betting offer is a lay
bet if its associated outcome's isNegation property is true, and is a back bet otherwise.
For reasons given below, all betting offers are modelled as back bets. A lay bet is then a back bet on the outcome not to happen. The negation of the outcome lies with
the outcome, not with the betting offer. Thus the back and lay bets on the same (conceptual) outcome will be modelled here as bets on two different outcomes, i.e. the
back outcome and the (negated) lay outcome. Note that the betting offer odds value always holds the back odds, so lay odds will need to be converted. (See the odds
property for more information.)
When finding outcome partitions (and finding e.g. surebets and valuebets), it is much preferred if all betting offers are back bets. We can do this by converting lay bets
to back bets by creating negated outcomes and converting the lay odds to back odds.
For example, in Home-Draw-Away, if we have a back bet on Home, and a lay bet on Home, then we can convert the lay bet to a back bet on one (or both) of the
following two outcomes:

63
(1) "Draw-Away"
(2) Not "Home"
These two outcomes are semantically equivalent.
Note that outcome partitions can then be found without looking at the betting offer, which is how it should be.
In the example above, Home and Not Home will obviously form an outcome partition. This outcome partition will be easily identified because:
(1) The back bet on "Home" will point to "Home" outcome.
(2) The back bet on "Not Home" will point to "Not Home" outcome.
In fact, we can quickly (and generically) find all back/lay-based (in fact: all negation-based) outcome partitions by simply pairing outcomes with their negations. The
following tuple must be unique: (providerId, outcomeId, bettingTypeId, multiplicity, slotNum)

2.1.1 BettingOffer attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

providerId(long,readOnly) A reference to the data source provider. Cannot be null.

sourceId(long) A reference to the source that this betting offer was collected from. Cannot be null.

outcomeId(long,readOnly) A reference to the outcome. Cannot be null.


If this outcome "happens" (i.e. becomes a result) then the bet is won, otherwise it is lost. (Note, however, that some bets may be
settled otherwise, for example in case of event cancellations or bet voiding.)

bettingTypeId(long,readOnly) A reference to the betting type. Cannot be null. This betting type equals the betting type that the betting offer is associated with in
the source.

statusId(long) A reference to the status. Cannot be null.

isLive(Boolean) True if the betting offer is available during a live event. It can only be true if the event is currently in progress or interrupted.
False if the betting offer is not available when the event starts.
Null if the betting offer will be available both before and after the event starts.

When the event is finished (Ended, Cancelled, Abandoned, Retired, Walkover), the IsLive property will not change value.

odds(Float) The all-important odds value (in EU style).


It is normally not null. However, in certain sports and under certain conditions it can be, as dictated by the betting offer status,
e.g. Starting Price. If not null, then the odds must be at least 1.
The odds value is always the back odds, and never the lay odds. If the betting offer is a lay, then the lay odds must be converted
to back odds as follows : backOdds = layOdds / (layOdds - 1)
And vice versa : layOdds = backOdds / (backOdds - 1)

multiplicity(Integer,readOnly) Represents the multiplicity of the bet. Null if unknown. 0 if single. >0 if the bet requires X more bets (from the same provider) to
be taken in addition to this one. Among several bets, the highest multiplicity constraint must be satisfied.
For example, if a provider lists the following three bets:
Bet 1 with multiplicity 0 (i.e. single)
Bet 2 with multiplicity 1
Bet 3 with multiplicity 2
Bet 4 with multiplicity 1
Then a punter can take Bet 1 alone. If he wants to take Bet 2 (or Bet 4), he must take at least one other bet. If he wants to take
Bet 3, he must take at least two other bets.
The multiple bet is settled as one bet. To win the multiple bet, all the individual (contained) bets must be won, otherwise the
multiple bet is lost. For example, if a multiple bet has a multiplicity of 2, and the bets taken have the odds 1.5, 2.0, 3.5 then - if
the multiple bet is won - the punter gets 1.5 x 2.0 x 3.5 = 10.5 times his money back.

volume(Float) The Volume specifies the amount of money available for winning, or null if not applicable (e.g. with bookmakers). Not null for
betting exchanges. Cannot be negative.

volumeCurrencyId(Long) A reference to the currency of the volume property. Must be null if volume is null. And must be non-null if volume is not null.

couponKey(String) The couponKey is used to generate the betting slip URL. May be null if none or unknown. The process of how the couponKey is
turned into a betting slip URL is considered outside the scope of the Sports Model. Its maximum length is 255 characters.

slotNum(int,readOnly) For use with betting exchanges only where there are three back/lay bets on each outcome, each with separate odds and
amounts. With bookmakers the value is always 1. With betting exchanges it is (normally) 1, 2, or 3. Cannot be null and must be
positive.

lastChangedTime(Date) The time (in GMT) at which one of the following properties was last updated: statusId, odds, multiplicity, volume,
volumeCurrencyId. If none if these properties have ever been updated, then the betting offer creation time is used. The property
is never null.

64
2.2 Class BettingOfferStatus
Provides the status (and availabilty) of a betting offer.

2.2.1 BettingOfferStatus attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the status. Cannot be null or empty, and must be unique among all statuses. Its maximum length is 255
characters.

isAvailable(boolean,readOnly) True if the associated betting offer is available for betting, and false otherwise. Cannot be null.

description(String) A description of this status. May be null. The maximum length is 255 characters.

2.3 Class Source


Represents a source from which we collect data.
The primary purpose of the source entity is to provide a means of associating (any) collected data with a (static) key for the source it was collected from (the
{collectorId, sourceKey} pair), and when we last collected data from the source (lastCollectionTime).
The tuple (collectorId, sourceKey) must be unique.

2.3.1 Source attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

collectorId(long,readOnly) A reference to the data source collector. Cannot be null or non-positive. Note that the Sports Model does not contain a Collector
entity. The collectorId is hence a remote reference whose meaning is determined by the creator of the source entity.

providerId(long,readOnly) A reference to the data source provider. Cannot be null.

sourceKey(String,readOnly) Represents a unique key for this source, such as a (static) XML feed URL. Cannot be null or empty. Its maximum length is 255
characters.
Not published to clients and hence it is null on client's side.

lastCollectedTime(Date) The time (in GMT) at which data was last collected from the source.

lastUpdateTime(Date) The time (in GMT) at which the source was last updated, or null if unknown. Some sources may be updated regularly, e.g. every
minute, rather than on-demand, and make the time of update available for collection. If so, then this property is set to that time.

2.4 Class Provider


A provider is the owner of a data source. The provider provides that data to us.
Typically, we will have at least some of the provider's data in our system. But not always, e.g. we may just be mapping to it. See the "Mapping" pane.

2.41. Provider attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the provider. Cannot be null or empty. Its maximum length is 255 characters.

locationId(long) A reference to the Location (typically a nation) to which the provider is most closely affiliated. Cannot be null.

url(String) A URL to the provider's web site. Can be null. If not null then the url must be a valid URL. Its maximum length is 255
characters.

isBookmaker(boolean) True if the provider is a bookmaker, and false otherwise. Cannot be null.

isBettingExchange(boolean) True if the provider is a betting exchange, and false otherwise. Cannot be null.

bettingCommissionVACs(float) The commission used internally by the betting VACs. It cannot be null or negative, and is expressed as a percentage. In
practice, most commissions are between 0% (for bookmakers) and 5% (for low-volume punters on betting exchanges).

isEnabled(boolean) True if this provider is enabled (i.e. is active), and false if disabled (i.e. is inactive). Cannot be null.

65
Name Description
note(String) An internal-use-only note. May be null. The maximum length is 255 characters.

2.5 Class BettingType


A betting type is a convenient label for a fixed way of grouping outcomes according to their type and parameters. The primary use of betting types is to help define
betting markets.

2.5.1 BettingType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the betting type. Cannot be null or empty, and must be unique among all betting types. Its maximum length is 255 characters.

description(String) A description of the betting type, or null if none. Its maximum length is 255 characters.

2.6 Class BettingTypeUsage


Specifies the contexts (i.e. event types and sports) in which betting types can be used. The tuple (bettingTypeId, eventTypeId, sportId) must be unique.

2.6.1 BettingTypeUsage attributes

Name Description
id(long,readOnly) The id of this entity.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

bettingTypeId(long,readOnly) A reference to a betting type. Cannot be null.

eventTypeId(long,readOnly) A reference to an event type. Cannot be null.

sportId(long,readOnly) A reference to a sport. Cannot be null.

eventPartId(long,readOnly) A reference to an event part. Cannot be null.

2.7 Class Outcome


Represents an event outcome, e.g. that a certain participant wins the event.
Each outcome has a status that determines whether the outcome came true (i.e. is a result), didn't come true, is still a potential outcome (that you can e.g. bet on), or
"unknown". See OutcomeStatus for more information.
Each Outcome has a type that determines which properties are used, along with their semantics. See OutcomeType for more information.
Each outcome has an eventId and an eventPartId that defines the scope of the Outcome within the event, e.g. "First Half" within a football match.

2.7.1 Outcome attributes

Name Description
id(long,readOnly) The unique id of this entity.
Cannot be null.

version(int) The current version of this


entity. Any changes applied to
the entity will increment the
version by 1.

typeId(long,readOnly) A reference to the type. Cannot


be null.

isNegation(boolean,readOnly) True if this outcome is a


negation, i.e. for the outcome
not to happen. And false
otherwise. Cannot be null.

statusId(long) A reference to the outcome


status. Cannot be null.

eventId(long,readOnly) A reference to the event.

66
Name Description
Cannot be null.

eventPartId(long,readOnly) A reference to the event part.


Cannot be null. For example,
an outcome might apply only to
the First Half event part of a
football match.

paramFloat1(Float,readOnly) A generic parameter slot


whose value and semantics is
determined by the outcome
type.

paramFloat2(Float,readOnly) A generic parameter slot


whose value and semantics is
determined by the outcome
type.

paramFloat3(Float,readOnly) A generic parameter slot


whose value and semantics is
determined by the outcome
type.

paramFloat4(Float,readOnly) A generic parameter slot


whose value and semantics is
determined by the outcome
type.

paramFloat5(Float,readOnly) A generic parameter slot


whose value and semantics is
determined by the outcome
type.

paramBoolean1(Boolean,readOnly) A generic parameter slot


whose value and semantics is
determined by the outcome
type.

paramString1(String,readOnly) A generic parameter slot


whose value and semantics is
determined by the outcome
type.

paramParticipantId1(Long,readOnly) A generic parameter slot


whose value and semantics is
determined by the outcome
type. If not null then it is a
reference to a participant.

paramParticipantId2(Long,readOnly) A generic parameter slot


whose value and semantics is
determined by the outcome
type. If not null then it is a
reference to a participant.

paramParticipantId3(Long,readOnly) A generic parameter slot


whose value and semantics is
determined by the outcome
type. If not null then it is a
reference to a participant.

paramEventPartId1(Long,readOnly) A generic parameter slot


whose value and semantics is
determined by the outcome
type. If not null then it is a
reference to an event part.

paramScoringUnitId1(Long, A reference to the scoring unit.


readOnly) Can be null.

name(String) The name of the outcome. Can


be null. Its maximum length is
255 characters. Null if not
included into subscription.
Ex: "Over 6.5" (for
Over/Under), "Arsenal (-0.5)"
(for Asian Handicap)

code(String) A template from which the


name can be calculated. Can
be null. Its maximum length is
255 characters.
Published to internal clients
only.

67
Name Description
settlementRequired(Boolean) Internal only property. True if
we offered OM odds on the
outcome and settlement is
required or false otherwise.
Published to internal clients
only. Null for external clients.

isStatusManuallySet(boolean) True if the outcome was


manually settled or false
otherwise.
Published to internal clients
only.

2.8 Class OutcomeStatus


Provides the status of an outcome. An outcome whose status is resolved is not bettable.

2.8.1 OutcomeStatus attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the outcome status. Cannot be null or empty, and must be unique across all outcome statuses. Its maximum length is 255
characters.

description(String) A description of this status. May be null. The maximum length is 255 characters.

Please note that the following outcome statuses are NOT used unless you have settlement included in your subscription.

id name description
2 Did Happen The outcome did happen, i.e. it is an event result.

3 Did Not Happen The outcome did not happen.

6 Half Won Half of the wagered sum is multiplied by the quota, the other half is reimbursed.

7 Half Lost Half of the wagered sum is reimbursed, the other half is lost.

8 Void The entire wagered sum is reimbursed.

9 Cancelled The entire wagered sum is reimbursed.

2.9 Class OutcomeTypeBettingTypeRelation


Relates outcome types and betting types.

2.9.1 OutcomeTypeBettingTypeRelation attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

outcomeTypeId(long,readOnly) A reference to the outcome type. Cannot be null.

bettingTypeId(long,readOnly) A reference to the betting type. Cannot be null.

2.10 Class OutcomeType


Defines a specific type of outcome.
Examples:
* WINNER
* DRAW
* SCORE, e.g. "4:2" or "9.8:9.6"

68
* TOTAL SCORE, e.g. number of goals
* TOTAL SCORE IS LESS THAN
* TOTAL SCORE IS LESS THAN OR EQUAL TO
* TOTAL SCORE IS GREATER THAN
* TOTAL SCORE IS GREATER THAN OR EQUAL TO
* TOTAL SCORE BY PLAYER, e.g. number of goals by player
* FIRST TO SCORE, e.g. first goal scorer
* NEXT TO SCORE, e.g. next goal scorer
* LAST TO SCORE, e.g. last goal scorer

2.10.1 OutcomeType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the outcome type. Cannot be null or empty, and must be unique across all outcome types.
Its maximum length is 255 characters.

description(String) A description of the outcome type, or null if none. Its maximum length is 255 characters.

hasParamFloat1(Boolean,readOnly) True if the outcome's paramFloat1 property will be non-null, false if null, and null if either null or non-
null.

paramFloat1Description(String) A description of the paramFloat1 property, or null if none. Its maximum length is 255 characters.

hasParamFloat2(Boolean,readOnly) True if the outcome's paramFloat2 property will be non-null, false if null, and null if either null or non-
null.

paramFloat2Description(String) A description of the paramFloat2 property, or null if none. Its maximum length is 255 characters.

hasParamFloat3(Boolean,readOnly) True if the outcome's paramFloat3 property will be non-null, false if null, and null if either null or non-
null.

paramFloat3Description(String) A description of the paramFloat3 property, or null if none. Its maximum length is 255 characters.

hasParamFloat4(Boolean,readOnly) True if the outcome's paramFloat4 property will be non-null, false if null, and null if either null or non-
null.

paramFloat4Description(String) A description of the paramFloat4 property, or null if none. Its maximum length is 255 characters.

hasParamFloat5(Boolean,readOnly) True if the outcome's paramFloat5 property will be non-null, false if null, and null if either null or non-
null.

paramFloat5Description(String) A description of the paramFloat5 property, or null if none. Its maximum length is 255 characters.

hasParamBoolean1(Boolean,readOnly) True if the outcome's paramBoolean1 property will be non-null, false if null, and null if either null or non-
null.

paramBoolean1Description(String) A description of the paramBoolean1 property, or null if none. Its maximum length is 255 characters.

hasParamString1(Boolean,readOnly) True if the outcome's paramString1 property will be non-null, false if null, and null if either null or non-
null.

paramString1Description(String) A description of the paramString1 property, or null if none. Its maximum length is 255 characters.

paramString1PossibleValues(String,readOnly) Contains the possible (non-null) values of the outcome's paramString1 property. The values are listed
in CSV format. Whether null is a possible value is determined by the hasParamString1 property.

hasParamParticipantId1(Boolean,readOnly) True if the outcome's paramParticipantId1 property will be non-null, false if null, and null if either null or
non-null.

paramParticipantId1Description(String) A description of the paramParticipantId1 property, or null if none. Its maximum length is 255 characters.

paramParticipant1MustBePrimary(boolean,readOnly) True if the outcome's paramParticipantId1 property must refer to a participant that has a primary role in
the event, and false if there is no such constraint.

paramParticipant1MustBeRoot(boolean,readOnly) True if the outcome's paramParticipantId1 property must refer to a participant that is a root participant
in the event, and false if there is no such constraint.

paramParticipant1MustHaveRoleId(Long,readOnly) Refers to a participant role that the participant refered to by the outcome's paramParticipantId1
property must have, or null if there is no such constraint.

hasParamParticipantId2(Boolean,readOnly) True if the outcome's paramParticipantId2 property will be non-null, false if null, and null if either null or
non-null.

paramParticipantId2Description(String) A description of the paramParticipantId2 property, or null if none. Its maximum length is 255 characters.

paramParticipant2MustBePrimary(boolean,readOnly) True if the outcome's paramParticipantId2 property must refer to a participant that has a primary role in
the event, and false if there is no such constraint.

69
Name Description
paramParticipant2MustBeRoot(boolean,readOnly) True if the outcome's paramParticipantId2 property must refer to a participant that is a root participant
in the event, and false if there is no such constraint.

paramParticipant2MustHaveRoleId(Long,readOnly) Refers to a participant role that the participant refered to by the outcome's paramParticipantId2
property must have, or null if there is no such constraint.

hasParamParticipantId3(Boolean,readOnly) True if the outcome's paramParticipantId3 property will be non-null, false if null, and null if either null or
non-null.

paramParticipantId3Description(String) A description of the paramParticipantId3 property, or null if none. Its maximum length is 255 characters.

paramParticipant3MustBePrimary(boolean,readOnly) True if the outcome's paramParticipantId3 property must refer to a participant that has a primary role in
the event, and false if there is no such constraint.

paramParticipant3MustBeRoot(boolean,readOnly) True if the outcome's paramParticipantId3 property must refer to a participant that is a root participant
in the event, and false if there is no such constraint.

paramParticipant3MustHaveRoleId(Long,readOnly) Refers to a participant role that the participant refered to by the outcome's paramParticipantId3
property must have, or null if there is no such constraint.

hasParamEventPartId1(Boolean,readOnly) True if the outcome's paramEventPartId1 property will be non-null, false if null, and null if either null or
non-null.

paramEventPartId1Description(String) A description of the paramEventPartId1 property, or null if none. Its maximum length is 255 characters.

hasParamScoringUnitId1(Boolean,readOnly) True if the outcome's paramScoringUnitId1 property will be non-null, false if null, and null if either null or
non-null.

paramScoringUnitId1Description(String) A description of the paramScoringUnitId1 property, or null if none. Its maximum length is 255
characters.

2.11 Class OutcomeTypeUsage


Specifies the contexts (by event type, event part, sport and scoring unit) in which outcome types can be used.
The tuple (outcomeTypeId, eventTypeId, eventPartId, sportId) must be unique.

2.11.1 OutcomeTypeUsage attributes

Name Description
id(long,readOnly) The id of this entity.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

outcomeTypeId(long,readOnly) A reference to an outcome type. Cannot be null.

eventTypeId(long,readOnly) A reference to an event type. Cannot be null.

eventPartId(long,readOnly) A reference to an event part. Cannot be null.

sportId(long,readOnly) A reference to a sport. Cannot be null.

scoringUnitId(Long,readOnly) A reference to the scoring unit. Can be null.

2.12 Class OutcomeValidation - not published to clients


Represents the validation of one or more Outcome properties, based on a (outcomeTypeId, eventTypeId, eventPartId, sportId) lookup key.
The lookup key does not need to be unique, i.e. the same Outcome (properties) can be validated by more than one OutcomeValidation entity.
The tuple (typeId, outcomeTypeId, eventTypeId, eventPartId, sportId, paramString1) must be unique.

2.12.1 OutcomeValidation attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

typeId(long,readOnly) A reference to the outcome validation type. Cannot be null.

outcomeTypeId(long,readOnly) A reference to the outcome type to which this outcome validation applies. Cannot be null.

eventTypeId(long,readOnly) A reference to the event type to which this outcome validation applies. Cannot be null.

eventPartId(long,readOnly) A reference to the event part to which this outcome validation applies. Cannot be null.

70
Name Description
sportId(long,readOnly) A reference to the sport to which this outcome validation applies. Cannot be null.

paramString1(String) A generic parameter slot whose value and semantics is determined by the outcome validation type. Its maximum length is 255
characters.

2.13 Class OutcomeValidationType - not published to clients


Defines a specific type of Outcome validation, such as valid property-value combinations and min-max value ranges.

2.13.1 OutcomeValidationType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the outcome parameter validation type. Cannot be null or empty, and must be unique among all outcome
validation types. Its maximum length is 255 characters.

description(String) A description of the outcome validation type, or null if none. Its maximum length is 255 characters.

hasParamString1(Boolean,readOnly) True if the outcome validation entity's paramString1 property will be non-null, false if null, and null if either null or non-
null.

paramString1Description(String) A description of the paramString1 property, or null if none. Its maximum length is 255 characters.

71
Betting Types

 Examples of how to retrieve odds for specific markets can be found in our Using Sports Model Data section.

Betting Types Particularities

 Info on how to correctly retrieve data for specific Bet Types.

Asian Handicap

For 2 way Handicaps, the two outcomes have opposite handicap values (for instance 1.5, -1.5).

Home Draw Away With Handicap (HAD)

For HAD, the two outcomes that refer to Home and Away participants have opposite handicap values (for instance 1, -1).
Draw will have as Outcome.paramParticipantId1 the participant with lowest id, while paramFloat1 will refer to the handicap corresponding to that participant.

Correct Score

For Correct Score, ParticipantId1 and ParticipantId2 do not reflect the Home Away order. Instead, ParticipantId1 will hold the participant with the lowest id, while
ParticipantId1 the participant with the highest id.
Pay extra attention to how float1 - float2 are set (the exact score), as they'll need to follow the participants order, which, as stated above, can be reversed.

Head To Head (H2H)

- a direct comparison, a duel between two participants (which of two teams will be placed higher in the tournament, which of the two players will score most in the
tournament, etc)
For H2H, ParamParticipantId1 will hold the participant with the lowest id, while ParamParticipantId2 the participant with the highest id.
paramString1 defines the winner of the 'duel'. 1 - participant in ParamParticipantId1 will win, 2 - participant in ParamParticipantId2 will win.

Head To Head To Head (H3H)

- a comparison on how three participants will perform in a competition


For H3H, ParamParticipantId1 will hold the participant with the lowest id, ParamParticipantId2 the participant with in-between id value, while ParamParticipantId3 the
participant with the highest id.
paramString1 defines the winner of the 'duel'. 1 - participant in ParamParticipantId1 will win, 2 - participant in ParamParticipantId2 will win, 3 - participant in
ParamParticipantId3 will win.

72
Market
1 Diagram

2 Classifiers
2.1 Class Market
Represents a real-world sports betting market.

2.1.1 Market attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes


applied to the entity will increment the version by
1.

name(String) The name of the market. Cannot be null or empty.


Its maximum length is 255 characters.

eventId(long,readOnly) A reference to the event in which the action


occurs. Cannot be null.

eventPartId(long,readOnly) A reference to the event part. Cannot be null.

bettingTypeId(long,readOnly) A reference to the betting type. Cannot be null.

scoringUnitId(long,readOnly) A reference to the scoring unit. Null if market does


not use scoring unit.

discriminator(String,readOnly) A discriminator user to differentiate the markets


with the same bettingType, eventPart and
parameters.
For example, then can be multiple markets for
Time of goal 1 (time of 1st Goal), with different
intervals:
1-45|46-90|none with selection 1-45, 46-90
and NONE
1-15|16-30|31-45|46-60|61-75|76-90|none with
selections 1-15,16-30,31-45,46-60,61-75,76-
90 and NONE

73
numberOfOutcomes(Integer, The number of outcomes (i.e. selections) in
readOnly) market. Or null for markets with unknown number
of outcomes.

isComplete(boolean) True, market is structurally complete (i.e. all


outcomes exist and are linked to the market via
MarketOutcomeRelation)
If the numberOfOutcomes is unknown (null), this
property will be always false.

isClosed(boolean) True, when all outcomes in market are resolved.

paramFloat1(Float,readOnly) A generic parameter slot whose value and


semantics is determined by the market type.

paramFloat2(Float,readOnly) A generic parameter slot whose value and


semantics is determined by the market type.

paramFloat3(Float,readOnly) A generic parameter slot whose value and


semantics is determined by the market type.

paramFloat4(Float,readOnly) A generic parameter slot whose value and


semantics is determined by the market type.

paramFloat5(Float,readOnly) A generic parameter slot whose value and


semantics is determined by the market type.

paramString1(String,readOnly) A generic parameter slot whose value and


semantics is determined by the market type.

paramParticipantId1(Long,readOnly) A generic parameter slot whose value and


semantics is determined by the market type. If not
null then it is a reference to a participant.

paramParticipantId2(Long,readOnly) A generic parameter slot whose value and


semantics is determined by the market type. If not
null then it is a reference to a participant.

paramParticipantId3(Long,readOnly) A generic parameter slot whose value and


semantics is determined by the market type. If not
null then it is a reference to a participant.

2.2 Class MarketOutcomeRelation


Specifies that a certain outcome is part of a certain market.

2.1.1 Market attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

marketId(long,readOnly) A reference to the market. Cannot be null.

outcomeId(long,readOnly) A reference to the outcome. Cannot be null.

2.3 Class Event


Represents a real-world sports event. See Event for more information.

2.4 Class Outcome


Represents an event outcome, e.g. that a certain participant wins the event. See Betting for more information.

74
Location
1. Diagram

2. Classifiers
2.1 Class Location
Represents a location in the real world, such as the entire world, country regions, countries, stadiums, horse racing tracks, golf courts, etc.
Every Location has a type that defines the semantics of the location, e.g. whether it is a country or not. Also, the type determines which properties apply to a Location
instance.

2.1.1 Location attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

typeId(long,readOnly) A reference to the location type. Cannot be null.

name(String) The name of the location. The name cannot be null or empty. The maximum length is 255 characters.

code(String) The unique code of the location, or null if unknown, none, or not applicable. If the code is not null, then is must be non-empty and unique
within the location type. The maximum length is 255 characters.

isHistoric(boolean) True if this location is an historic location that no longer exists, and false if it still exists.

url(String) A URL to the official website of the location, or null if unknown, none, or not applicable. If not null, then the url must be a valid URL. The
maximum length is 255 characters.

note(String) An internal-use-only note. May be null. The maximum length is 255 characters.

2.2 Class LocationType


Represents a specific type of location, for example country or city.
Below is a list of sample location types, along with examples and properties unique to them.

75
World - fx. World (i.e. the plant Earth)
Continent - fx. Africa, Europe
Country - fx. Denmark
- properties: the ISO 3166 country code, optionally appended with a single number for sub-countries, e.g. "GB1" for England (part of Great Britain) (Countries
are downloaded from http://www.iso.org/iso/country_codes/iso_3166_code_lists.htm)
Miscellaneous - Groups of Regions fx. North and Central America, UK and Ireland.

2.2.1 LocationType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the location type, for example "Country" or "City". The name cannot be null or empty, and is unique among location
types.

description(String) A description of the location type, or null if none. Its maximum length is 255 characters.

hasCode(Boolean,readOnly) True if the location's code property will be non-null, false if null, and null if either null or non-null.

codeDescription(String) A description of the code property, or null if none. Its maximum length is 255 characters.

2.3 Class LocationRelation


Relates two locations. The nature of the relationship is given by the type.
The relation is explicitly unidirectional. However, depending on the semantics of its type, it may also be bidirectional.
The tuple (type, fromLocation, toLocation) must be unique.

2.3.1 LocationRelation attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

typeId(long,readOnly) The relation type. It cannot be null.

fromLocationId(long,readOnly) The relation "from" location. It cannot be null.

toLocationId(long,readOnly) The relation "to" location. It cannot be null.

2.4 Class LocationRelationType


The type of a relation between two locations.
Examples : "Part-Of". In reverse, it means "Contains". Transitivity applies.

2.4.1 LocationRelationType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the relation. It cannot be null or empty, and it must be unique among relations. Its maximum length is 255 characters.

description(String) A description of the location relation type, or null if none. Its maximum length is 255 characters.

2.5 Class LocationTypeUsage - not published to clients


Specifies the context (i.e. sports) in which the location type can be used.
The tuple (locationTypeId, sportId) must be unique.

2.5.1 LocationTypeUsage attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

76
Name Description
version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

locationTypeId(long,readOnly) A reference to a location type. It cannot be null.

sportId(long,readOnly) A reference to a sport. Cannot be null.

77
Property
1 Diagram

The primary concept here is the EntityProperty, which models an entity property as data and hence allow for the dynamic addition and removal of properties.

2 Classifiers
2.1 Class EntityPropertyType
The property type defines the property value type.
Examples: Integer, Long, Float, Boolean, String, and Date.
The tuple (name) must be unique.

2.1.1 EntityPropertyType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the entity property type. It cannot be null or empty, and it must be unique. The maximum length is 255 characters.

description(String) A description of the entity property type, or null if none. Its maximum length is 255 characters.

2.2 Class EntityProperty


Represents a property on an entity type, for example "weight" on a Participant.
The tuple (entityTypeId, name) must be unique.

2.2.1 EntityProperty attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

typeId(long,readOnly) A reference to the property type. Cannot be null.

78
Name Description
entityTypeId(long,readOnly) A reference to the entity type. Cannot be null.

name(String) The name of the entity property. It cannot be null or empty. The maximum length is 255 characters.

description(String) A description of the entity property, or null if none. Its maximum length is 255 characters.

2.3 Class EntityType


Represents an entity type as data. It is primarily for use with the EntityProperty entity.
All entity types in the Sports Model can be represented as an EntityType instance. See the name property for more information.
The tuple (name) must be unique.

2.3.1 EntityType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the entity type. This name must match exactly the name of the entity type, for example "Event" and "Participant". It cannot be
null or empty, and it must be unique. The maximum length is 255 characters.

description(String) A description of the entity type, or null if none. Its maximum length is 255 characters.

2.4 Class EntityPropertyValue


Represents a property value. The tuple (entityPropertyId, entityId) must be unique.

2.4.1 EntityPropertyValue attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

entityProperyId(long,readOnly) A reference to the entity property. Cannot be null.

entityId(long,readOnly) A reference to the entity. Cannot be null. The type of the entity can be determined via the entity property.

value(String) The property value, represented as a String. The property value must valid according to the property type.

79
Other entities
1 Diagram

2 Classifiers
2.1 Class Currency
Represents a real-world currency, such as US Dollars (USD), British Pounds (GBP), Euros (EUR), and Danish Crowns (DKK).

2.1.1 Currency attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the currency, for example "US Dollar" or "Pound Sterling". It cannot be null or empty, and it must be unique. The maximum
length is 255 characters.

code(String,readOnly) The three letter ISO 4217 currency code, for example "DKK", "USD", "EUR", and "GBP". It cannot be null, contains exactly three
characters, and is unique among currencies.

2.2 Class Source


Represents a source from which we collect data.
The primary purpose of the source entity is to provide a means of associating (any) collected data with a (static) key for the source it was collected from (the
{collectorId, sourceKey} pair), and when we last collected data from the source (lastCollectionTime).
The tuple (collectorId, providerId, sourceKey) must be unique.

2.2.1 Source attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

collectorId(long,readOnly) A reference to the data source collector. Cannot be null or non-positive.


Note that the Sports Model does not contain a Collector entity. The collectorId is hence a remote reference whose meaning is
determined by the creator of the source entity.

80
Name Description
providerId(long,readOnly) A reference to the data source provider. Cannot be null.

sourceKey(String,readOnly) Represents a unique key for this source, such as a (static) XML feed URL. Cannot be null or empty. Its maximum length is 255
characters.
[not published to clients]

lastCollectedTime(Date) The time (in GMT) at which data was last collected from the source.

lastUpdateTime(Date) The time (in GMT) at which the source was last updated, or null if unknown.
Some sources may be updated regularly, e.g. every minute, rather than on-demand, and make the time of update available for
collection. If so, then this property is set to that time.

2.3 Class Sport


Represents a real-world sport.
Sports can be arranged hierarchically.

2.3.1 Sport attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the sport, for example "Football" or "Baseball". It cannot be null or empty and is unique among sports. The maximum
length is 255 characters.

description(String) A description of this sport. May be null. The maximum length is 255 characters.

parentId(Long,readOnly) A reference to a parent sport, or null if none. Sports without parents are known as root (or top-level) sports. Sports with a parent are
known as sub-sports. Sports that have sub-sports are normally abstract.

2.4 Class Provider


A provider is the owner of a data source. The provider provides that data to us.
Typically, we will have at least some of the provider's data in our system. But not always, e.g. we may just be mapping to it. See the "Mapping" pane.

2.4.1 Provider attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the provider. Cannot be null or empty. Its maximum length is 255 characters.

locationId(long) A reference to the Location (typically a nation) to which the provider is most closely affiliated. Cannot be null.

url(String) A URL to the provider's web site. Can be null. If not null then the url must be a valid URL. Its maximum length is 255
characters.

isBookmaker(boolean) True if the provider is a bookmaker, and false otherwise. Cannot be null.

isBettingExchange(boolean) True if the provider is a betting exchange, and false otherwise. Cannot be null.

bettingCommissionVACs(float) The commission used internally by the betting VACs.


It cannot be null or negative, and is expressed as a percentage. In practice, most commissions are between 0% (for
bookmakers) and 5% (for low-volume punters on betting exchanges).

isEnabled(boolean) True if this provider is enabled (i.e. is active), and false if disabled (i.e. is inactive). Cannot be null.

note(String) An internal-use-only note. May be null. The maximum length is 255 characters.

2.5 Class SystemMessageType - not published to clients


Represents a system message type.
Examples:
* ModelApp restart.
* Scheduled ModelApp upgrade.
* Collector undeployed.

81
2.5.1 SystemMessageType attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the system message type. It cannot be null or empty, and it must be unique. The maximum length is 255
characters.

description(String) A description of the system message type, or null if none. Its maximum length is 255 characters.

hasParamLong1(Boolean,readOnly) True if the system message's paramLong1 property will be non-null, false if null, and null if either null or non-null.

paramLong1Description(String) A description of the paramLong1 property, or null if none. Its maximum length is 255 characters.

hasParamTime1(Boolean,readOnly) True if the system message's paramTime1 property will be non-null, false if null, and null if either null or non-null.

paramTime1Description(String) A description of the paramTime1 property, or null if none. Its maximum length is 255 characters.

2.6 Class SystemMessage - not published to clients


A system message represents a message (or notification) related to the state of the SportsEngine system.
Examples of such messages:
* ModelApp will be restarted in 10 minutes. Expected downtime: 30 minutes.
* Collector (or maybe Provider) with id 10 has been removed from the system.
* Collector (or maybe Provider) with id 10 has been removed from the system.

2.6.1 SystemMessage attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

typeId(long,readOnly) A reference to the system message type. Cannot be null.

description(String,readOnly) A brief description of the system message. It cannot be null or empty. The maximum length is 255 characters.

createdTime(Date,readOnly) The time (in GMT) at which the system message was created. Cannot be null.

paramLong1(Long,readOnly) A generic parameter slot whose value and semantics is determined by the system message type.

paramTime1(Date,readOnly) A generic parameter slot whose value and semantics is determined by the system message type.

2.7 Class ProviderEntityMapping


The ProviderEntityMapping is a one-to-one, id-based mapping between a provider's entity and an entity of the Sports Model.
Many-to-one and one-to-many mappings will be represented by multiple (one-to-one) mapping entities.
The tuple (providerId, providerEntityTypeId, providerEntityId, entityTypeId, entityId) must be unique.

2.7.1 ProviderEntityMapping attributes

Name Desciption
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

providerId(long,readOnly) A reference to the provider to which this mapping applies. Cannot be null.

providerEntityTypeId(String,readOnly) A provider-unique identifier for the entity type, e.g. "Event" or "Player". Cannot be null.

providerEntityId(String,readOnly) A provider-unique identifier for the entity, e.g. "e19412". Cannot be null.

entityTypeId(long,readOnly) A reference to the entity type (in the Sports Model). Cannot be null.

entityId(long,readOnly) A reference to the entity (in the Sports Model). Cannot be null.

2.8 Class StreamingProvider


Represents a real-world currency, such as Twitch.tv, Youtube, etc.

82
2.8.1 StreamingProvider attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The name of the streaming platform. Cannot be null or empty. Its maximum length is 255 characters.

locationId(long) A reference to the Location (typically a nation) to which the provider is most closely affiliated. Cannot be null.

urlTemplate(String) A URL template to the streaming platform's web site. Cannot be null or empty. Its maximum length is 255 characters.

83
Translation
If you use our JAVA connector, in order to get Translation related entities, you must use version 3.0.9 or newer.

1 Diagram

2 Classifiers
2.1 Class Translation
Represents a translation for a specific Sports Model entity.

2.1.1 Translation attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

name(String) The translation. The name cannot be null or empty. The maximum length is 255 characters.

entityId(long) A reference to the translated entity. Cannot be null.

entityTypeId(long) A reference to an EntityType. Must be used to get the referenced translated entity class. Cannot be null.

languageId(long) A reference to a language. Cannot be null.

lastChangedDate(Date) The date when this translation was last changed. Cannot be null.

2.2 Class Language


Represents a specific language.

2.2.1 Language attributes

Name Description
id(long,readOnly) The unique id of this entity. Cannot be null.

version(int) The current version of this entity. Any changes applied to the entity will increment the version by 1.

code(String) The language code. (ex: en-US, en-GB, de-DE etc.). Cannot be null.

createDate(Date) The date when the language was created in our system. Cannot be null.

84
All Statuses Explained
Event Statuses
These are the possible values for the Event Status entity.

Id Name Description
1 Pending The event has not started yet.

2 In Progress The event is in progress.

3 Ended The event has ended.

4 Interrupted The event has been interrupted after start, will continue later.

5 Canceled The event has been canceled before start, will not be played later.

6 Walkover The event has been canceled before start, will not be played later.
A player wins by walkover.

7 Abandoned The event has been abandoned after start, will not continue.

8 Retired The event has been abandoned after start, will not continue. A
played has retired.

Important:
The property Event.hasLiveStatus is indicating if the status of the event is covered live (hasLiveStatus = true) or it is estimated from Event.startTime (hasLiveStatus =
false).
Important:
While, in theory, some transitions from one state to another should not be possible, in practice, depending on the data we receive, all transitions are possible.
Most common transitions:
Pending → In progress → Ended
Pending → In progress → Interrupted → In progress → Ended
Pending → Canceled
Pending → Walkover
Pending → In progress → Abandoned
Pending → In progress → Retired
Less common transitions:
In progress → Ended → In progress (our data sources update/correct the status of the event)

Outcome Statuses
These are the possible values for the Outcome Status entity.

Id Name Settlement Description


1 Can Open The outcome can still happen.
Happen

2 Did Happen Won The outcome did happen.

3 Did Not Lost The outcome did not happen.


Happen

4 Unknown Settled, but is not The outcome is resolved (no odds available for
But known betting on this outcome) but it is unknown
Resolved whether it happened or not.
e.g. 1st half ends, all outcomes on 1st half are
set to this status. Later, the status can change,
for example, to 'Did Happen'.

5 Unknown Unknown The status of the outcome is unknown.

6 Half Won Half Won Half of the wagered sum is multiplied by the
quota, the other half is reimbursed.

7 Half Lost Half Lost Half of the wagered sum is reimbursed, the
other half is lost.

8 Void Void The outcome is void because not all the


possibilities were considered.

85
Id Name Settlement Description
e.g: For a Home Away market, if the result was
Draw, then the home and away outcomes are
voided. The entire wagered sum is
reimbursed.

9 Cancelled Void If the event does not play or is it abandoned.


The entire wagered sum is reimbursed.

Important:
All transitions are possible.
Most common transitions:
Can happen → Did Happen (or Did not happen, or Half Won, or Half Lost, or Void)
Can happen → Unknown but resolved (when the event part ends and there is no settlement info yet) → Did Happen (or Did not happen, or Half Won, or Half Lost, or
Void)
Can happen → Canceled
Less common transitions:
Did Happen (or Did not happen, or Half Won, or Half Lost, or Void) → Can happen (in case of canceling previous settlement)
Did Happen → Did not happen (in case of resettlement)

BettingOffer Statuses
These are the possible values for the BettingOfferStatus entity.

Id Name Available Description


for
betting
1 Standard true The betting offer has odds and is available for
betting.

2 Starting true The betting offer has no odds (yet) but bets
Price can still be placed. For example, in horse
racing it is possible to bet on the (yet
unknown) odds prevailing in the on-course
fixed-odds betting market at the time a race
begins.

3 Non- false The participant associated with the (outright)


Participant betting offer does not participate in the event
any more.

4 Removed false The betting offer is (potentially temporarily)


removed i.e. not available.

5 Invalid false The betting offer is (potentially temporarily)


invalid.

6 Resolved false The betting offer is resolved because the


associated outcome is settled.

7 Suspended false The betting offer is temporarily removed from


the provider data source.

Important:
While, in theory, some transitions from one state to another should not be possible, in practice, depending on the data we receive, all transitions are possible.
Most common transitions:
Standard → Removed (odds are suspended) → Standard
Standard → Suspended → Standard
Standard → Suspended → Removed
Standard → Invalid (odds are manual invalidated or a match moves from non-live to live) → Standard
Starting Price → Removed
Standard → Non Participant
All → Resolved
Less common transitions:
Resolved → Removed → Standard (when the outcome moves from Did Happen, etc → Can happen)
Outcome-BettingOffer Relationship:
When an outcome becomes settled, the BettingOffer.statusId moves to 6 (Resolved).

86
Stats and Scores Statuses
These are the possible values for EventActionStatus,EventActionDetailStatus,EventInfoStatus,EventParticipantInfoStatus,EventParticipantInfoDetailStatus entities.

Id Name Is Description
available
1 Standard true The entity (EventAction, EventInfo, etc) is
active and it could be relied on.

2 Removed false The entity (EventAction, EventInfo, etc) is not


longer available and it could NOT be relied on.

3 Invalid false The entity (EventAction, EventInfo, etc) is not


longer valid. E.g. A goal was scored and then
canceled making the corresponding
EventAction invalid.

4 Resolved true This is final state. It could be relied on, no


updates are expected unless for late
corrections.

Important:
While, in theory, some transitions from one state to another should not be possible, in practice, depending on the data we receive, all transitions are possible.
Most common transitions:
Standard → Resolved
Standard → Removed (data source does not cover the corresponding event anymore)
Less common transitions:
Standard → Invalid (correction)
Resolved → Standard (correction on Event status, e.g.: an Event moves from Ended → In Progress, or from 2nd Half to 1st Half)

87
Java Connector
The Sports Engine Publication Component (SEPC) is the component to which clients connect in order to get the Sports Engine data.
We provide a Java-based connector which knows how to connect to and communicate with the SEPC:
Current version: SEPC-connector-4.0.0.jar. The java sources can be downloaded here: SEPC-connector-4.0.0-sources.jar

On EveryMatrix Community, the connectors can be downloaded from: Knowledge Center > Document Library > OddsMatrix > API documentation >
OddsMatrix Feed Documentation.

Main SEPC connector classes


The SEPC connector API contains the following classes:

SEPCConnector : base class for connectors.


SEPCPushConnector: push connector implementation.
SEPCPullConnector: pull connector implementation.
SEPCConnectorListener: connector listener interface that allows client code to receive SportsEngine data, initial dump data is received in one big chunk
SEPCStreamedConnectorListener: stream connector listener that allows client code to receive SportsEngine data, initial dump data is received in small
chunks (preferred for large subscriptions)

SEPC Connector API usage


1. Connecting to SportsEngine

Depending on the type of communication with the Sports Engine, you can use a pull connector or a push connector.
The pull connector uses an HTTP connection and the push connector uses a Socket based connection.
Both constructors take the SEPC host and port as arguments.

Push connector

SEPCConnector sepcPushConnector = new SEPCPushConnector("sept.oddsmatrix.com", 7000);

Pull connector

SEPCConnector sepcPullConnector = new SEPCPullConnector("sept.oddsmatrix.com", 8081);

2. Getting data from SportsEngine

2.1 Create a connector listener

A ConnectorListener should be used to get data from SportsEngine if the initial dump data doesn't contain too many entities

Usage:
The connector listener interface contains two notify methods that are called by the connector during its execution:
notifyInitialDump called after successfully obtaining the initial data from the SEPC.

notifyEntityUpdates called after successfully obtaining an update data batch from the SEPC.

public class ConnectorListenerTest implements SEPCConnectorListener {

public void notifyInitialDump(List<? extends Entity> entities) {

// implement custom logic here


}

public void notifyEntityUpdates(EntityChangeBatch entityChangeBatch) {

// implement custom logic here


}

88
}

2.2 Create a streamed connector listener


This interface should be used if the initial dump data contains many entities.
Usage:
The connector listener interface contains four notify methods that are called by the connector during its execution:
notifyInitialDumpToBeRetrieved called before initial data starts to be sent from the SEPC.
notifyPartialInitialDumpRetrieved called multiple times when partial initial dump data is sent from the SEPC.
notifyInitialDumpRetrieved called after successfully obtaining the entire initial data from the SEPC.
notifyEntityUpdates called after successfully obtaining an update data batch from the SEPC. Implementation details for push connector:
notifyEntityUpdates call is made from a separate thread, to decouple data reading from data processing.
if data processing is slow, update data (transformed later into EntityChangeBatch) objects will accumulate in a blocking queue, increasing client
integration memory footprint or even blocking data reading when the queue fills up.
update data queue capacity is 1 000 000 entries by default, but it is configurable (SEPCPushConnector#setUpdateDataConstructsQueueCapacity).
connector periodically logs update data queue size, client is encouraged to actively monitor it
(SEPCPushConnector#getNumberOfPendingUpdateDataConstructs) because accumulation means slow data processing which translates into delayed
data.

public class SEPCTestConnectorListener implements SEPCStreamedConnectorListener {

public void notifyInitialDumpToBeRetrieved() {

System.out.println("Initial dump starting ");


}

@Override
public void notifyPartialInitialDumpRetrieved(List<? extends Entity> entities) {

System.out.println("Initial dump batch entities received " + entities.size());


}

@Override
public void notifyInitialDumpRetrieved() {

System.out.println("Initial dump done ");


}

@Override
public void notifyEntityUpdatesRetrieved(EntityChangeBatch entityChangeBatch) {

System.out.println("Notifying entity update... entity changes size:


" + entityChangeBatch.getEntityChanges().size());
}
}

3. Register the connector listener or the streamed connector listener

connector.addConnectorListener(connectorListener);

or

connector.addStreamedConnectorListener(streamedConnectorListener)

3.1 Resume settings


SEPCconnector automatically sends an update-data-resume-request upon a disconnection period to get the missing changes and resume data consumption.
Specifically, connector requests all data from last EntityChangeBatch time minus 2 minutes, in order to make sure no change gets lost. This means server re-sends
some data, but connector automatically drops changes already received.

4. Start the connector

connector.start("subscriptionName");

89
The connector will start a background thread and will make requests to the SEPC.
The connector class is not thread safe, so it is not recommended to make multiple parallel calls to the start() method.
The connector will call the execution flow for the given subscription and Listener will be called with the initial dump and updates.

4.1. Start the connector with resume

start with resume

connector.startWithResume
("subscriptionName", "subscriptionId", "subscriptionChecksum", "lastEntityChangeBatchTime");

The connector will call the execution flow for the given subscription and Listener will be called with updates.
Provide values for subscriptionId, subscriptionChecksum and lastAppliedEntityChangeBatchTime from the last EntityChangeBatch you have processed:

EntityChangeBatch

@Override
public void notifyEntityUpdatesRetrieved(EntityChangeBatch entityChangeBatch) {

entityChangeBatch.getSubscriptionId();
entityChangeBatch.getSubscriptionCheckSum();
entityChangeBatch.getUuid();
}

To make sure no change gets lost, connector requests resume data from last EntityChangeBatch time you provided minus 2 minutes. This means some recent
updates will be sent again by server and it's client responsibility to filter it out / ignore data already received.
5. Stop the connector
To stop the connector thread, call the stop() method on the connector. Do this before you close your application.
Between the start() and stop() method calls, any other client logic unrelated to the connector can be called.

connector.stop();

6. Connector Logging
To see the logs produced by the connector during its execution, you must define a log4j appender for the library, e.g.

<appender name="com.betbrain.sepc.connector" class="org.apache.log4j.FileAppender">


<param name="File" value="logs/connector.log"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p %c{2} [%t] - %m%n"/>
</layout>
</appender>

90
C# Connector
The Sports Engine Publication Component (SEPC) is the component to which clients connect in order to get the Sports Engine data.
We provide a C#-based connector which knows how to connect to and communicate with the SEPC.
Current version: om-connector-dotnet-2.0.0.zip
To add the library to your project, add a local source with the path to where you download the om-connector.2.0.0.nupkg file and add it like a normal Nuget package
to the project.

On EveryMatrix Community, the file can be downloaded from: Knowledge Center > Document Library > OddsMatrix > API documentation > OddsMatrix Feed
Documentation.

Changelog

1.0.0 - Initial release


1.0.1 - Fixed reconnect timeouts
1.0.2 - Data model updated
1.0.3 - Fix NullReferenceException in EventInfoType XML parsing
1.0.4 - SocketIdleTime defaults to 3 minutes and can now be configured on push connector
1.0.5 - Add .NET Framework 4.7.2 support
1.0.6 - Add resume feature
1.0.7 - Fix "null" values bug on updates
1.0.8 - Fix EntityDelete type getter
1.0.9 - Fix SetReconnectInterval interval check
1.0.10 - Fix SDQLError code parsing
1.0.11 - Add start with resume functionality
1.0.12 - Fix resume retry on IOException
1.0.13 - Added BettingOfferStatuses.Suspended_id
1.0.14 - Make SubscriptionId and SubscriptionChecksum available for start with resume
1.0.15 - Add ToString for entity logging
1.0.16 - Add logoUrl on Participant
1.0.17 - Fix NumberFormatException for locales that do not use dot separator for floats
1.1.0 - Make Start method non-blocking and start connector thread in foreground. Update C# version from 7.1 to 9
2.0.0 - Fixed date parsing. All DateTime objects are in local timezone now.
- Handle properly end of stream.
- Convert EntityUpdate property values from String to their proper type.
- Push updates asynchronously to separate data reading from data processing.
- Change "start with resume" to start from last batch time instead of last batch UUID.
- Removed "IEntityChangeBatchProcessingMonitor", it's not needed anymore as SDK automatically resumes from last received batch.
- Log received XML messages with debug level.

SEPC Connector API usage


1. Create a connector
Communication with Sports Engine is done using a socked based connection.
The constructor takes the SEPC host and port as arguments.

SEPCPushConnector connector = new SEPCPushConnector("sept.oddsmatrix.com", 7000);

2. Create a connector listener


a. IConnectorListener
The connector listener interface contains two notify methods that are called by the connector during its execution:
NotifyInitialDump called after successfully obtaining the initial data from the SEPC.
NotifyEntityUpdates called after successfully obtaining an update data batch from the SEPC.

class CustomListener : IConnectorListener


{
public void NotifyInitialDump(List<Entity> initialDump)
{
// implement custom logic here
}

public void NotifyEntityUpdates(EntityChangeBatch entityChangeBatch)


{
// implement custom logic here
}

91
}

b. IStreamedConnectorListener
The connector streamed listener interface contains four notify methods that are called by the connector during its execution:
NotifyInitialDumpToBeRetrieved called before getting the initial data from the SEPC
NotifyPartialInitialDumpRetrieved called after successfully obtaining each initial data batch from the SEPC
NotifyInitialDumpRetrieved called after successfully obtaining the initial data from the SEPC
NotifyEntityUpdatesRetrieved called after successfully obtaining an update data batch from the SEPC. Implementation details for push connector:
notifyEntityUpdates call is made from a separate thread, to decouple data reading from data processing.
if data processing is slow, update data (transformed later into EntityChangeBatch) objects will accumulate in a blocking queue, increasing client
integration memory footprint or even blocking data reading when the queue fills up.
update data queue capacity is 1 000 000 entries by default, but it is configurable (SEPCPushConnector#setUpdateDataConstructsQueueCapacity).
connector periodically logs update data queue size, client is encouraged to actively monitor it
(SEPCPushConnector#getNumberOfPendingUpdateDataConstructs) because accumulation means slow data processing which translates into delayed
data.

class CustomStreamedListener : IStreamedConnectorListener


{
public void NotifyInitialDumpToBeRetrieved()
{
// implement custom logic here
}

public void NotifyPartialInitialDumpRetrieved(List<Entity> entities)


{
// implement custom logic here
}

public void NotifyInitialDumpRetrieved()


{
// implement custom logic here
}

public void NotifyEntityUpdatesRetrieved(EntityChangeBatch entityChangeBatch)


{
// implement custom logic here
}
}

3. Register the connector listener

connector.AddConnectorListener(connectorListener);
connector.AddStreamedConnectorListener(streamedConnectorListener);

3.2 Resume settings (requires version 1.0.6 or newer)


SEPCconnector can be set to automatically send an update-data-resume-request upon a disconnection period to get the missing updates and restart data
consumption.
Specifically, connector requests all data from last EntityChangeBatch time minus 2 minutes, in order to make sure no change gets lost. This means server re-sends
some data, but connector automatically drops changes already received.

4. Start the connector

connector.Start("subscriptionName");

The connector will start a background thread and will make requests to the SEPC.
The connector class is not thread safe, so it is not recommended to make multiple parallel calls to the Start() method.
The connector will call the execution flow for the given subscription and Listener will be called with the initial dump and updates.

4.1. Start the connector with resume (requires version 1.0.14 or newer)

connector.StartWithResume("subscriptionName", "subscriptionId", "subscriptionChecksum", "lastAppliedEntityChangeBa

92
SubscriptionId and SubscriptionChecksum can be retrieved by SEPCPushConnector::GetSubscriptionId and SEPCPushConnector::GetSubscriptionChecksum
methods just before closing the connection.

5. Stop the connector


To stop the connector thread, call the Stop() method on the connector. Do this before you close your application.
Between the Start() and Stop() method calls, any other client logic unrelated to the connector can be called.

connector.Stop();

6. Connector Logging
To see the logs produced by the connector during its execution, you must define a log4net appender for the library (log4net.config.xml), e.g.

<log4net debug="false">
<appender name="ConsoleAppender" type="log4net.Appender.ManagedColoredConsoleAppender">
<mapping>
<level value="ERROR" />
<foreColor value="Red" />
</mapping>
<mapping>
<level value="WARN" />
<foreColor value="Yellow" />
</mapping>
<mapping>
<level value="ALL" />
<foreColor value="White" />
</mapping>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %level %logger{2} [%thread] %message %newline" />
</layout>
</appender>

<root>
<level value="INFO" />
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>

For this file to be used at runtime, please add the following block inside <Project> tag in your *.csproj file

<ItemGroup>
<None Update="log4net.config.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

93
Client-Server Communication Errors
1. Error message: "No subscriptionSpecificationName found for subscriptionId 450055 Either the subscriptionId is invalid or you might have been disconnected"
2. Error message: "Too many active subscriptions. Max active subscriptions is 1"
3. Error message: "SubscribeRequest sent too often. Allowed: 1 per 3600 seconds."
4. Error message: " SubscribeRequest sent too often. Maximum Number of Subscribe Requests exceeded. Closest time for next request Wed Oct 16 08:35:45
GMT 2013"

1. Error message: "No subscriptionSpecificationName found for subscriptionId 450055 Either the subscriptionId is invalid or you might have been disconnected"
Cause: You receive this error because the Sports Engine was restarted or you got disconnected. Most of the times, a client is disconnected when it has no activity. For
the Pull mode restrictions, please check the Pull Subscription Page. For the Push mode restrictions, please check the Push Subscription Page.
What you can do: Re-subscribe (subscribe-request SDQL construct).

2. Error message: "Too many active subscriptions. Max active subscriptions is 1"
Cause: You receive this error when the number of active subscriptions you are allowed to have in the same time is exceeded. Please note that a subscription remains
active until it times out, unless you explicitly unsubscribe.
What you can do: Use only the max number of allowed subscriptions. If the number of maximum simultaneous active subscription is set too low for you, contact our
tech team.

3. Error message: "SubscribeRequest sent too often. Allowed: 1 per 3600 seconds. SubscribeRequest sent too often. Closest time for next request Tue Oct 15
11:14:09 GMT 2013"
Cause: You receive this error because you tried to resubscribe (subscribe-request SDQL construct) more often than a certain threshold (in this case 3600 sec).
What you can do: Wait until you're allowed to resubscribe.

4. Error message: "SubscribeRequest sent too often. Maximum Number of Subscribe Requests exceeded. Closest time for next request Wed Oct 16 08:35:45 GMT
2013"
Cause: You receive this error because you tried to resubscribe (subscribe-request SDQL construct) more than X times in 24 h. For the Pull mode restrictions, please
check the Pull Subscription Page. For the Push mode restrictions, please check the Push Subscription Page.
What you can do: Wait until you're allowed to resubscribe.

'

94
Client integration test scenarios
Event Related scenarios
Scenario 1: Pre-live match creation

1. The server creates a pre-live match.


2. The server creates outcomes, markets, betting offers, associated to the match created in step 1.
Expected behavior: Match should appear on the client front-end.

Scenario 2: Live match creation

1. The server creates a live match.


2. The server creates outcomes, markets, betting offers, associated to the match created in step 1.
Expected behavior: Match should appear on the client front-end.

Scenario 3: Tournament creation

Step 1: The server creates a tournament


Step 2: The server creates outcomes, markets, betting offers associated to the tournament created in step 1.
Expected behavior: Tournament should appear on the client front-end.

Scenario 4: Match going from pre-live to live

1. The server receives information that the match goes live.


2. The server invalidates all available pre-live betting offers.
Tech details: BettingOffer.statusId is updated from 1 (Standard) → 5 (Invalid), for betting offers with BettingOffer.isLive=false.
3. The match status is updated to 'In Progress'
Tech details: Event.statusId is updated from 1 (Pending) → 2 (In Progress)
2. The server receives match live odds
3.1 Some of the already existing betting offers are updated as live.
Tech details: BettingOffer.statusId is updated from 5 (Invalid) → 1 (Standard) and BettingOffer.isLive is updated from false → true
3.2. Some betting offers are created (they were not offered in pre-live)
Expected behavior: Pre-live odds are not shown anymore, live odds shown when available on the client front-end.

Scenario 5: Match going from pre-live to ended

1. The server receives information that the match has ended.


2. The server resolves all betting offers.
Tech details: BettingOffer.statusId is updated to 6 (Resolved).
3 The server resolves all outcomes.
Tech details: Outcome.statusId is updated to from 1 (Can happen) → 4 (Unknown but resolved).
4 The match status is updated to 'Ended'.
Tech details Event.statusId is updated from 1 (Pending) → 3 (Ended)
Expected behavior: Pre-live odds are not shown anymore.

Scenario 6: Match going from live to pre-live

1. The server receives information that the match goes back from live to pre-live.
2. The server invalidates all available live betting offers.
Tech details: BettingOffer.statusId is updated from 1 (Standard) → 5 (Invalid), for betting offers with BettingOffer.isLive=true.
3 The match status is updated to 'Pending'.
Tech details Event.statusId is updated from 2 (In Progress) → 1 (Pending).
4. The server receives match pre-live odds
5.1 Some of the already existing betting offers are updated as pre-live.

95
Tech details: BettingOffer.statusId is updated from 5 (Invalid) → 1 (Standard) and BettingOffer.isLive is updated from true → false.
5.2. Some betting offers are created (they were not offered in live)
Expected behavior: Live odds are not shown anymore, pre-live odds shown when available on the client front-end.

Scenario 7: Match going from live to ended

1. The server receives information that the match has ended.


2. The server resolves all betting offers.
Tech details: BettingOffer.statusId is updated to 6 (Resolved).
3. The server resolves all outcomes that are not yet settled.
Tech details: Outcome.statusId is updated to from 1 (Can happen) → 4 (Unknown but resolved).
4. The match status is updated to 'Ended'
Tech details: Event.statusId is updated from 2 (In progress) → 3 (Ended)
Expected behavior: Live odds are not shown anymore on the client front-end.

Scenario 8: Match going from ended to live

1. The server receives information that the match goes back from ended to live.
2. The server re-opens all outcomes which have the status 'Unknown but resolved'.
Tech details: Outcome.statusId is updated to from 4 (Unknown but resolved) → 1 (Can happen).
1.2 The match status is updated to 'In progress'.
Tech details: Event.statusId is updated from 3 (Ended) → 2 (In progress).
Expected behavior: Live odds shown when available on the client front-end.

Scenario 9: Match going from live to interrupted

1. The server receives information that the match is interrupted.


2. The match status is updated to 'Interrupted'
Tech details: Event.statusId is updated from 2 (In progress) → 4 (Interrupted)
Expected behavior: Event is marked as "interrupted" on the client front-end.

Scenario 10: Match going from live to abandoned

1. The server receives information that the match has been abandoned.
2. The match status is updated to 'Abandoned'
Tech details: Event.statusId is updated from 2 (In progress) → 7 (Abandoned)
3. The server resolves all outcomes that are not yet settled.
Tech details: Outcome.statusId is updated to from 1 (Can happen) → 4 (Unknown but resolved).
4. The server resolves all betting offers.
Tech details: BettingOffer.statusId is updated to 6 (Resolved).
Expected behavior: Live odds are not shown anymore on the client front-end.

Scenario 11: Match going from live to retired

1. The server receives information that the match has been abandoned.
2. The match status is updated to 'Retired'
Tech details: Event.statusId is updated from 2 (In progress) → 8 (Retired)
3. The server resolves all outcomes that are not yet settled.
Tech details: Outcome.statusId is updated to from 1 (Can happen) → 4 (Unknown but resolved).
4. The server resolves all betting offers.
Tech details: BettingOffer.statusId is updated to 6 (Resolved).
Expected behavior: Live odds are not shown anymore on the client front-end.

Scenario 12: Match is deleted

1. The server receives a request to delete an event.


2. The server deletes betting offers, markets, outcomes and all entities associated to the match in step 1.

96
3. The server deletes the match.
Expected behavior: The match is no longer available on client front-end.
*We usually delete events 1 day after they were ended.

Scenario 13: Match is deleted and recreated

1. The server receives a request to delete an event because of an error in the event information (wrong tournament, wrong participants etc.)
2. The server deletes betting offers, markets, outcomes and all entities associated to the match in step 1.
3. The server deletes the match.
4. The match is recreated with the correct information. Follow Scenario 1 (non-live) or Scenario 2 (live)
Expected behavior: The old match is no longer available and the new match is available on client front-end.

Scenario 14: Match participants swap roles

1. The server receives information that match is not A vs B, but B vs A.


2. The server sends the participants swap updates
Tech details: EventParticipantRelation for participant A is updated to participant role 'Away' (ParticipantRole.id=2) and EventParticipantRelation for participant B
is updated to participant role 'Homr' (ParticipantRole.id=1)
Expected behavior: The match is listed as B vs A on client front-end. Please note that outcomes, markets do not change.

Scenario 15: Match start time is updated

1. The server receives the new start time.


2. The match start time is updated.
Tech details: The Event.startTime is updated.
Expected behavior: The start time of the match match is updated on client front-end.

Scenario 16: Match start time and status are updated

1. The server receives the new start time.


2. The match start time is updated.
Tech details: The Event.startTime is updated.
3. Event status is updated according to the new startTime. *
Tech details: The Event.statusId is updated.
Expected behavior: The start time and status of the match match are updated on client front-end.
* Only if we don't have information about match status (Event.hasLiveStatus=false), match status is computed in relation to the start time.

Scenario 17: Current Event Part is Updated (ex. for a Football Match from 1st Half → Halftime → 2nd Half)

1. The server receives half time signal.


2. The match current event part is updated from 1st Half to Halftime.
Tech details: The Event.currentEventPartId is updated from 5 - 1st Half (Ordinary Time) → 621 - Halftime.
3. The server resolves all outcomes on the 1st Half that are not yet settled.
Tech details: Outcome.statusId is updated to from 1 (Can happen) → 4 (Unknown but resolved).
4. The server resolves all betting offers on the 1st Half.
Tech details: BettingOffer.statusId is updated to 6 (Resolved).
5. The server receives 2nd half signal.
6. The match current event part is updated from Halftime to 2nd Half.
Tech details: The Event.currentEventPartId is updated from 621 - (Halftime) → 6 - (2nd Half (Ordinary Time)).
Expected behavior: The current event part of the match match is updated and the odds for 1st Half are not shown on client front-end.
In some cases the transition can be 1st Half → 2nd Half (no halftime information).

Scenario: Current Event Part is changed to a previous value (ex. for a Football Match from 2nd Half → 1st Half)

1. The server receives 1st half signal.


2. The match current event part is updated from 2nd Half to 1st Half.
Tech details: The Event.currentEventPart is updated from 6 - (2nd Half (Ordinary Time)) → 5 - (1st Half (Ordinary Time)).
3. The server opens all outcomes on the 1st Half that are not yet settled or settled at the end of the eventPart.

97
Tech details: Outcome.statusId is updated to from 4 (Unknown but resolved) → 1 (Can happen).
Expected behavior: The current event part of the match match is updated to 1st Halft and live odds are shown when available on the client front-end.

Scenario : Match hasLiveStatus* change from false to true.

1. The server receives information about the event status


2. Event.hasLiveStatus is updated from 'false' to 'true'.
3. Update event status if needed**.
Tech details: if needed, Event.statusId will be updated.
3.5 If status is updated, follow other scenarios (4-11).
Expected behavior:
* Event.hasLiveStatus - True if the event status is (or will be) updated live, and false if not. Cannot be null. The event status is represented by the statusId and
currentPartId properties.
** If Event.hasLiveStatus is false, the statusId of the event is calculated based on the Event.startTime.

Scenario : Match hasLiveStatus change from true to false.

1. The server no longer receives information about the event status


2. Event.hasLiveStatus is updated from 'true' to 'false'.
3. Update event status if needed, according to the start time of the Event*.
Tech details: if needed, Event.statusId will be updated.
3.5 If status is updated, follow other scenarios (4-11).
Expected behavior:
* If the start time is in the future, the event status will be pending. If the start time has passed and a certain amount of time, based on sport has passed, the status will
be ended, else will be in progress.

Odds related scenarios:


Scenario: Market/Outcome/Odds creation for Home/Away

1. The outcome for one participant to win is created.


Tech details: Update with Outcome create is sent.
2. Incomplete market is create for Home/Away
Tech details: Market and MarketOutcomeRelation create.
Market is created with Market.isComplete = 'false' and Market.numberOfOutcomes = 2.
MarketOutcomeRelation is created with the MarketOutcomeRelation.marketId = market id from step 2 and the MarketOutcomeRelation.outcomeId = outcome id
from step 1.
3. The outcome for the other participant to win is created.
Tech details: Update with Outcome create is sent.
4. Market is completed with the other outcome.
Tech details: MarketOutcomeRelation is created with the MarketOutcomeRelation.marketId = market id from step 2 and the MarketOutcomeRelation.outcomeId =
outcome id from step 3.
Update Market.isComplete from 'false' → 'true'.
5. Betting Offers are created. Note: this can also happen after the outcomes and before MartketOutcomesRelations are created.
Tech details: Betting offers with outcomeId = outcomes from step 1 and 3 and bettingTypeId = 70 (HomeAway)
Expected behavior: When the market becomes complete, if the status of the betting offers is standard, the odds are shown on client front-end, otherwise are not
shown.

Scenario: Use incomplete markets.

Some market have variable number of outcome and it noes not have the isComplete notion. Exemple: Correct score - some outcome can be added or removed during
a game and it does not have a set of predefined outcome (like Home/Away)
1. Market is created with Market.isComplete = 'false' and Market.numberOfOutcomes = null.
2. MarketOutcomeRelations are created.
Market.isComplete is never updated to true because Market.numberOfOutcome = null.
Expected behavior: Market should be used.

Scenario : Standard Betting Offer is suspended

1. The server receives suspend for a Betting Offer.

98
2. Server changes the status of the Betting Offer to removed.
Tech details: BettingOffer.statusId is updated from 1 (Standard) → 4 (Removed).
Expected behavior: Odds are removed from client front-end.

Scenario : Suspended Betting Offer is unsuspended

1. The server receives unsuspend for a Betting Offer.


2. Server changes the status of the Betting Offer to standard.
Tech details: BettingOffer.statusId is updated from 4 (Removed) → 1 (Standard).
Expected behavior: Odds are shown on client front-end.

Scenario : Standard Betting Offer is invalidated

1. The server receives invalid signal for a Betting Offer.


2. Server changes the status of the Betting Offer to invalid.
Tech details: BettingOffer.statusId is updated from 1 (Standard) → 5 (Invalid).
Expected behavior: Odds are removed from client front-end.

Scenario : Invalid Betting Offer is valid again

1. The server receives validation for a Betting Offer.


2. Server changes the status of the Betting Offer to standard.
Tech details: BettingOffer.statusId is updated from 5 (Invalid) → 1 (Standard).
Expected behavior: Odds are shown on client front-end.

Scenario : Invalid Betting Offer is removed

1. The server receives remove for a Betting Offer.


2. Server changes the status of the Betting Offer to removed.
Tech details: BettingOffer.statusId is updated from 5 (Invalid) → 4 (Removed).
Expected behavior: Nothing changes on front-end.

Scenario : Standard Betting Offer is resolved

1. The server receives resolved signal for a Betting Offer.


2. Server changes the status of the Betting Offer to resolved.
Tech details: BettingOffer.statusId is updated from 1 (Standard) → 6 (Resolved).
Expected behavior: Odds are removed from client front-end.

Scenario : Removed Betting Offer is resolved

1. The server receives resolved signal for a Betting Offer.


2. Server changes the status of the Betting Offer to resolved.
Tech details: BettingOffer.statusId is updated from 4 (Removed) → 6 (Resolved).
Expected behavior: Nothing changes on front-end.

Scenario : Invalid Betting Offer is resolved

1. The server receives resolved signal for a Betting Offer.


2. Server changes the status of the Betting Offer to resolved.
Tech details: BettingOffer.statusId is updated from 4 (Removed) → 6 (Resolved).
Expected behavior: Nothing changes on front-end.

Scenario: Betting Offer coverage is lost

1. Source is not updated.


Tech details: Source.lastCollectedTime is not updated for a period of time.
2. If too much time passed (for example 10 seconds on live and 1 minute on prelive), remove all the betting offers for that source

99
Tech details: If now - Source.lastCollectedTime > XX Seconds then find all the BettingOffers with souceId = source from 1 and remove them.
Expected behavior: Betting offers with old source are removed from client front-end.

Scenario: Betting Offer coverage is regained

1. Source is updated after it was marked as old.


Tech details: Source.lastCollectedTime is updated after the threshold was previously hit. If (now - Source.oldLastCollectedTime > XX seconds) and (now -
Source.newLastCollectedTime < XX seconds) then find all betting offers with sourceId = source and show them.
Expected behavior: Betting offers with the updated source are shown on client front-end.

Scenario: Betting Offer is deleted

1. Server sends Betting Offer delete.


Expected behavior: Odds are not available on client front-end

Scenario: All betting offers from a market (Home/Away) are removed

1. Server sends remove for home odds


Tech details: BettingOffer for Outcome Home Winner is updated with statusId = 4 (Removed) *
2. Server sends remove for away odds
Tech details: BettingOffer for Outcome Away Winner is updated with statusId = 4 (Removed)
Now, all the odds for the market Home/Away are removed.
Tech details: Having the marketId for "Home/Away" we can search all the outcomes for this market, via MarketOutcomeRelation and check the status of the
BettingOffers for those Outcomes.
Possible behavior: Entire market is removed from client front-end after XX seconds.
* Order is not guarantee: away odds can be removed first.

Scenario: Betting Offers from a line are removed (Over/Under 2.5)

1. Server sends remove for over 2.5


Tech details: BettingOffer for Outcome Over 2.5 is updated with statusId = 4 (Removed) *
2. Server sends remove for under 2.5
Tech details: BettingOffer for Outcome Under 2.5 is updated with statusId = 4 (Removed)
Now, all the odds for the line 2.5 are removed.
Tech details: Having the marketId for "Over/Under 2.5" we can search all the outcomes for this market, via MarketOutcomeRelation and check the status of the
BettingOffers for those Outcomes.
Possible behavior: Line for 2.5 is removed from client front-end after XX seconds.
* Order is not guarantee: under odds can be removed first.

Scenario: Market is closed

1. Server receives settlement for all outcomes within a market.


2. Server sends market close signal.
Tech details: Market.isClosed is updated from 'false' → 'true'.
Expected behavior: Market is removed from client front-end.

Scenario: Market is re-opened

1. Server receives correction and reopens an outcome.


2. Server sends market open signal.
Tech details: Market.isClosed is updated from 'true' → 'false'.
Expected behavior: Market is shown on client front-end.

Scenario: Outcome is closed - outcome is settled, but the settlement is unknown yet

2. Server sends outcome status update.


Tech details: Outcome.statusId is changed from 1 (Can Happen) → 4 (Unknown but resolved).
Expected behavior: Odds are removed from client front-end.

100
Scenario: Outcome is reopen

2. Server sends outcome open.


Tech details: Outcome.statusId is changed from a settled status* → 1 (Can happen)
Expected behavior: Odds are shown from client front-end.
* See statuses explained for more details.

Scenario: Outcome is settled

2. Server sends outcome settlement


Tech details: Outcome.statusId is changed to one of the settled statuses.*
Expected behavior: Odds are removed from client front-end.
* See statuses explained for more details.

Scenario: Settled Outcome is deleted

1. Server sends delete for a settled outcome (all betting offers related to this outcome are already deleted).
Expected behavior: Outcome is not available on client front-end.

Scenario: Not Settled Outcome is deleted

1. Server sends delete for a not settled outcome (all betting offers related to this outcome are already deleted).
Expected behavior: Outcome is not available on client front-end. Clients must do manual settlement for all the bets linked to this outcome.

Scenario: Outcome is deleted and recreated (with another id)

1. Server sends delete for an outcome (all betting offers related to this outcome are already deleted).
2. Server sends create for the same outcome but with a different id.

Scenario: All odds for an event are removed

1. Server sends remove for a betting offer


Tech details: BettingOffer is updated with statusId = 4 (Removed) *
...
n. Server sends remove for last betting offer
Tech details: BettingOffer is updated with statusId = 4 (Removed)
Now, all the odds for the event are removed.
Tech details: Having an eventId we can search all the outcomes for this event and check the status of the BettingOffers for those Outcomes.
Possible behavior: Event is removed from client front-end
* Order is not guarantee: betting offers can be removed in any order.

Stats and scores related scenarios:


Scenario: Scores are created while the match is live

1. Server creates a score for football ordinary time.


Tech details: EventInfo with typeId=1 (Score), statusId=1 (Standard) and eventPartId=3 (Ordinary Time) is created.
Expected behavior: Score is shown on client front-end.
* This applies for other score-like eventInfos too. e.g. (2 - Yellow cards; 9 - Corners)

Scenario: Scores are created while the match is ended

1. Server creates a score for football ordinary time.


Tech details: EventInfo with typeId=1 (Score), statusId=4 (Resolved) and eventPartId=3 (Ordinary Time) is created.
Expected behavior: Score is shown on client front-end as the final score for given eventPart.
* This applies for other score-like eventInfos too. e.g. (2 - Yellow cards; 9 - Corners)

Scenario: Score is updated

1. Server sends an update for an existing score.


Tech details: EventInfo.paramFloat1 and/or EventInfo.paramFloat2 is updated. e.g. 1-0 → 1-1

101
Expected behavior: Score is updated on client front-end for given eventPart.

Scenario: Score is updated (Correction)

1. Server sends an update for an existing score.


Tech details: EventInfo.paramFloat1 and/or EventInfo.paramFloat2 is updated. e.g. 1-1 → 1-0 (Football); 15-15 → 30-0 (Tennis)
Expected behavior: Score is updated on client front-end for given eventPart.

Scenario: Score status is updated (Correction)

1. Server sends an update for an existing score.


Tech details: EventInfo.statusId updated from 4 (Resolved) → 1 (Standard).
Expected behavior: Score is updated as inPlay score on client front-end.

Scenario: Score is resolved

1. Server sends an update for an existing score.


Tech details: EventInfo.statusId updated from 1 (Standard), 2(Removed) or 3 (Invalid) → 4 (Resolved).
Expected behavior: Score is updated as the final score and is shown on client front-end as such.

Scenario: Score is invalidated

1. Server sends an update for an existing score.


Tech details: EventInfo.statusId updated from 1(Standard), 2(Removed) or 4(Resolved) → 3 (Invalid).
Expected behavior: Score is removed from client front-end.

Scenario: Score is removed

1. Server sends an update for an existing score.


Tech details: EventInfo.statusId from updated 1 (Standard) → 2 (Removed).
Expected behavior: Score is removed from client front-end.

Scenario: Score is revalidated

1. Server sends an update for an existing score.


Tech details: EventInfo.statusId from updated 2 (Removed) or 3(Invalid) → 1 (Standard).
Expected behavior: Score is shown on client front-end
* See statuses explained for more details.

Scenario: Score is deleted

1. Server sends delete for an existing score.


Expected behavior: Score is removed from client front-end

Scenario: Displaying score for Baseball

1. Server sends score create for a baseball match on 1st Inning.


Tech details: EventInfo is created with typeId=1 (Score), eventPart=73 (1st Inning) and one of the paramFloats= -1.
Expected behavior: Score is shown only for one participant. The participant with -1 score is yet to play, so its score is not existent.

Scenario: Displaying match time (ex. Football)

1. Server sends match time create.


Tech details: EventInfo is created with typeId=95 (Match Time), paramFloat1 = 10.
2. Server sends match time update.
Tech details: EventInfo is uptadated with paramFloat1 = 10 → 11.
Expected behavior: Match time is displayed on client front-end, first 10 and after is updated to 11.

102
Scenario: Displaying Remaining time in period (ex. Ice Hockey)

1. Server sends remaining time in period create


Tech details: EventInfo is created with typeId=96 (Remaining time in period), paramFloat1 = 19.
2. Server sends match time update.
Tech details: EventInfo is uptadated with paramFloat1 = 19 → 18.
Expected behavior: Remaining time is displayed on client front-end, first 19 and after is updated to 18.

Scenario: 4th Goal of the match is scores. Details will be send as Event Actions and Event Action Details

1. Server sends Event Action for 4th Goal with details about which team scored, the time of the goal and the method of scoring.
Tech details: EventAction is created with typeId = 7 (Goal Scored) and paramFloat1 = 4
EventActionDetails is created with typeId = 1 (Team), paramParticipantId = the participant who scored and eventActionId = the eventAction from
above
EventActionDetails is created with typeId = 2 (Times), paramFloat1 = 48 (min 48) and eventActionId = the eventAction from above
EventActionDetails is created with typeId = 15 (Method Of Scoring), paramString1 = "Penalty" and eventActionId = the eventAction from above
Expected behavior: If the Event Actions are used, the message about the goal being scored with the details will be shown on client front-end.

Others scenarios:
Scenario: Participant name is updated

1. Server sends participant name update.


Tech details: Participant.name is updated.
Expected behavior: Participant name is updated on client front-end.

Scenario: Participant name contains special characters.

1. Server sends create participant with name containing special characters.


Tech details: Participant.name has special characters, ex: Byåsen Toppfotball, Rødovre Håndboldklub (W).
Expected behavior: Participant name is updated on client front-end.

Scenario: Adding a player into a game: adding Mesut Ozil playing for Arsenal in the game Chelsea vs Arsenal

1. Server will send a new Event Participant Relation to the client.


Tech details: EventParticipantRelation will be created with eventId = id of Chelsea vs Arsenal, participantId = 66355 (Mesut Ozil), participantRoleId = 3 (player)
and parentParticipantId = 1 (Arsenal)

Scenario: Remove a player from a game: removing Mesut Ozil from Arsenal in the game Chelsea vs Arsenal

1. Server will send a delete Event Participant Relation to the client.


Tech details: EventParticipantRelation delete is send.

Scenario: Betting Offer delete/create cycles.

In some cases, the server will send delete on a betting offer than create the same betting offer with the same id or a different id (both being possible).
1. Betting offer with id 12 is deleted.
Tech details: BettingOffer with id 12 is deleted.
4. Betting offer with id 12765is created with the same properties as betting offer 12 had when deleted.
Tech details: BettingOffer with id 12 is deleted.
3. Betting offer with id 765 is deleted.
Tech details: BettingOffer with id 12 is deleted.
4. Betting offer with id 12 is created with the same properties as betting offers 12 and 765 had when deleted, except for the odds, that were changed.
Tech details: BettingOffer with id 12 is deleted.

103
Using Sports Model Data
Check out sample database from Sports Model Entities page.

A. Category: Match and Tournament

1. Which are the event types?


2. How to find the match participants?
3. How to find to which tournament a match belongs
to?
4. How to find the tournament participants?
5. How to find a tournament (league)?
B. Category: Event Part

1. How to find all the event parts for a tennis match?


2. How to find all the event parts for a basketball tournament?

C. Category: Betting Offers

1. How to tell whether odds are stale?


2. How to get the 1x2 odds offered by provider P for a football match? (Version 1 - starting from BettingOffer)
3. How to get the 1x2 odds offered by provider P for a football match? (Version 2 - starting from Market)
4. How to get the Over/Under odds offered by provider P for a football match? (Version 1 - starting from BettingOffer)
5. How to get the Over/Under odds offered by provider P for a football match? (Version 2 - starting from Market)
6. How to get the Asian Handicap odds offered by provider P for a football match? (Version 1 - starting from BettingOffer)
7. How to get the Asian Handicap odds offered by provider P for a football match? (Version 2 - starting from Market)
8. How to get the Home Draw Away With Handicap (HAD) odds offered by provider P for a football match? (starting from Market)
9. How to get the Team Score Over/Under odds offered by provider P for a football match? (starting from Market)
10. How to get the Scorings Over/Under In Time Range - and other related bet types - odds offered by provider P for a football
match?(starting from Market)
11. How to get the Correct Score odds offered by provider P for a football match? (starting from Market)
12. How to get the Asian Handicap with Score odds offered by provider P for a football match? (starting from Market)
13. How to get tournament winner odds? (starting from Market)
14. How to get outright betting types?

D. Stats & Scores

1. How to get the score for a match?


2. How to get all the goal scored eventAction for a match?
3. How to get the team/participant that scored each goal in a match?
4. How to get the time eventAction Detail for every goal scored in a
match?

A1. Which are the Event Types?

At this moment, there are two types of events: match and tournament (or league).

Query

1 SELECT id, name


2 FROM eventtype;

104
id name

1 Generic Match

2 Generic
Tournament

A2. How to find the match participants?

Suppose we have the event(match) with the id 180315003979616256 (this is the id for the match: Bayern Munchen - Ratiopharm Ulm).

Query

1 SELECT epr.eventId, p.name AS participantName, pr.id AS roleId, pr.name AS roleName


2 FROM eventparticipantrelation epr
3 INNER JOIN participant p ON epr.participantId = p.id
4 INNER JOIN participantrole pr ON pr.id = epr.participantRoleId
5 WHERE eventId = 180315003979616256
6 LIMIT 7;

eventId participantName roleId roleName

180315003979616256 Ratiopharm Ulm 2 Away

180315003979616256 Bayern Munchen 1 Home

180315003979616256 Vladimir Lucic 3 Player

180315003979616256 Augustine Rubit 3 Player

180315003979616256 Thomas Klepeisz 3 Player

180315003979616256 Jallow Karim 3 Player

180315003979616256 Zugic Fedor 3 Player

A3. How to find to which tournament a match belongs to?

Suppose we have the event(match) with the id 180315003979616256.

Query

1 SELECT e1.id AS matchId, e2.id AS tournamentId, e2.name AS tournamentName


2 FROM event e1
3 INNER JOIN event e2 ON e1.parentId = e2.id
4 WHERE e1.id = 180315003979616256;

matchId tournamentId tournamentName

180315003979616256 179863658187247616 BBL 2022/2023

A4. How to find the tournament participants?


Suppose we have the event(tournament) with id 206369842.The participants of a tournament can be players or teams.

105
You can retrieve the players:

Query

1 SELECT epr.eventId, p.name AS participantName, pr.id AS roleId, pr.name AS roleName


2 FROM eventparticipantrelation epr
3 INNER JOIN participant p ON epr.participantId = p.id
4 INNER JOIN participantrole pr ON pr.id = epr.participantRoleId
5 WHERE eventId = 180315003979616256 AND epr.participantRoleId = 3
6 LIMIT 3;

eventId participantName roleId roleName

180315003979616256 Vladimir Lucic 3 Player

180315003979616256 Augustine Rubit 3 Player

180315003979616256 Thomas Klepeisz 3 Player

You can retrieve the teams:

Query

1 SELECT epr.eventId, p.name AS participantName, pr.id AS roleId, pr.name AS roleName


2 FROM eventparticipantrelation epr
3 INNER JOIN participant p ON epr.participantId = p.id
4 INNER JOIN participantrole pr ON pr.id = epr.participantRoleId
5 WHERE eventId = 6124641273397248 AND epr.participantRoleId = 4
6 LIMIT 3;

eventId participantName roleId roleName

6124641273397248 Chile 4 Primary

6124641273397248 Hungary 4 Primary

6124641273397248 Panama 4 Primary

A5. How to find a tournament (league)?

Suppose you are looking for the English Premier League.

Query

1 SELECT e.id AS eventId, e.name AS tournamentName, l.id AS locationId, l.name AS locationName


2 FROM event e
3 INNER JOIN location l ON e.venueId = l.id
4 WHERE e.typeId = 2 and l.name = "England";

eventId tournamentName locationId locationName

172350176981209088 Premier League 2022/2023 77 England

106
B1. How to find all the event parts for a tennis match?

Event parts are organized in hierarchies. For each sport, there is a hierarchy root for matches and a hierarchy root for tournament.

Suppose you are interested in the hierarchy root for tennis matches.

Query

1 SELECT id, eventTypeId, sportId, rootPartId


2 FROM eventpartdefaultusage
3 WHERE sportId = 3 AND eventTypeId = 1;

id eventTypeId sportId rootPartId

4 1 3 20

The root event part for tennis matches has the id = 20. Once you know the hierarchy root, you can navigate in the hierarchy. Here is the root
event part:

Query

1 SELECT id, name, parentId


2 FROM eventpart
3 WHERE id = 20;

id name parentId

20 Whole Match NULL

Which are the children of 'Whole Match'?

Query

1 SELECT id, name, parentId


2 FROM eventpart
3 WHERE parentId = 20;

id name parentId

21 1st Set 20

22 2nd Set 20

23 3rd Set 20

24 4th Set 20

25 5th Set 20

496 Rest of Match 20

Going deeper, which are the children of '1st Set'?

Query

1 SELECT id, name, parentId


2 FROM eventpart
3 WHERE parentId = 21;

107
id name parentId

401 1st Game (1st Set) 21

402 2nd Game (1st Set) 21

403 3rd Game (1st Set) 21

404 4th Game (1st Set) 21

405 5th Game (1st Set) 21

406 6th Game (1st Set) 21

407 7th Game (1st Set) 21

408 8th Game (1st Set) 21

409 9th Game (1st Set) 21

410 10th Game (1st Set) 21

411 11th Game (1st Set) 21

412 12th Game (1st Set) 21

413 13th Game (1st Set) 21

574 Tie-Break (1st Set) 21

B2. How to find all the event parts for a basketball tournament?

Event parts are organized in hierarchies. For each sport, there is a hierarchy root for matches and a hierarchy root for tournament.

Suppose you are interested in the hierarchy root for basketball tournaments.

Query

1 SELECT id, eventTypeId, sportId, rootPartId


2 FROM eventpartdefaultusage
3 WHERE sportId = 8 AND eventTypeId = 2;

id eventTypeId sportId rootPartId

13 2 8 1

The root event part for basketball tournaments has the id = 1. Once you know the hierarchy root, you can navigate in the hierarchy. Here is
the root event part:

Query

1 SELECT id, name, parentId


2 FROM eventpart
3 WHERE id = 1;

id name parentId

108
1 Whole Event NULL

Which are the children of 'Whole Event'?

Query

1 SELECT id, name, parentId


2 FROM eventpart
3 WHERE parentId = 1;

id name parentId

As you can see, the result is empty.

Note: Right now, for tournaments, the event part hierarchy contains only one event part, Whole Event.

C1. How to tell whether odds are stale?

Use the Source entity referenced by a BettingOffer.

Query

1 SELECT bo.id AS bettingOfferId, odds, lastChangedTime, s.lastCollectedTime


2 FROM bettingoffer bo
3 INNER JOIN source s ON bo.sourceId = s.id
4 LIMIT 1;

bettingOfferId odds lastChangedTime lastCollectedTime

91168097006928896 5 2022-09-28 09:00:44 2022-10-01 17:25:15

The property BettingOffer.lastChangeTime is the time of the last BettingOffer update.


The property Source.lastCollectedTime is the last time when the BettingOffer was checked. This value compared to current time gives the
odds freshness.

C2. How to get the 1x2 odds offered by provider P for a football match? (Version 1)

Suppose you want to retrieve the 1x2 odds for the event part "Ordinary Time" offered by OddsMatrix for the match with the id
181613058696728576 (Manchester City vs Manchester United).
We know that: 1x2 bet type id is 69, OddsMatrix id is 3000984 , 'Ordinary Time' id is 3.

Query

1 SELECT providerId, bettingTypeId, odds, eventId, o.id AS outcomeId


2 FROM bettingoffer bo
3 INNER JOIN outcome o ON bo.outcomeId = o.id
4 INNER JOIN event e ON o.eventId = e.id
5 WHERE e.id = 181613058696728576 AND bo.bettingTypeId = 69 AND providerId = 3000984 AND o.eventPartId = 3;

109
providerId bettingTypeId odds eventId outcomeId

3000984 69 1.3846154 181613058696728576 181613058745029120

3000984 69 7.5 181613058696728576 181613058749222912

3000984 69 5.5 181613058696728576 181613058749223680

We have the odds, we need to interpret the outcomes. The outcome properties are generic, they have different meanings for different types.

Query

1 SELECT id, typeId, paramFloat1, paramFloat2, paramFloat3,


2 paramBoolean1, paramString1, paramParticipantId1,
3 paramParticipantId2, paramParticipantId3, paramEventPartId1
4 FROM outcome
5 WHERE id IN (181613058745029120, 181613058749222912, 181613058749223680);

id typ para para para paramB param paramPart paramParti paramParti paramEve
eId mFloa mFloa mFloa oolean1 String icipantId1 cipantId2 cipantId3 ntPartId1
t1 t2 t3 1

1816130587450291 10 NULL NULL NULL NULL NULL 50 NULL NULL NULL


20

1816130587492229 10 NULL NULL NULL NULL NULL 11 NULL NULL NULL


12

1816130587492236 11 NULL NULL NULL NULL NULL NULL NULL NULL NULL
80

Note that there are 3 outcomes: two of type 10 and one of type 11.

Query

1 SELECT id, NAME, DESCRIPTION, paramParticipantId1Description


2 FROM outcometype
3 WHERE id = 11;

id name description paramParticipantId1Description

11 Draw The match is a draw. NULL

The outcome 181613058749223680 which has the type 11 refers to 'Draw'.

Query

1 SELECT id, name, description, paramParticipantId1Description


2 FROM outcometype
3 WHERE id = 10;

id name description paramParticipantId1Description

10 Winner The winner of the event. The id of the participant to win the event.
Money lost on no-win.

The generic parameter paramParticipantId1 refers to the 'id of the participant to win the event'.

110
The outcome 181613058745029120, refers to the participant with id 50. The outcome 181613058749222912 refers to the participant with id
11.

Let's see the participants:

Query

1 SELECT id, name


2 FROM participant
3 WHERE id in (50, 11);

id name

11 Manchester United

50 Manchester City

In the end, let's see everything in one query:

Query

1 SELECT providerId , bettingTypeId, odds, p.name


2 FROM bettingoffer bo
3 INNER JOIN outcome o ON bo.outcomeId = o.id
4 INNER JOIN event e ON o.eventId = e.id
5 LEFT OUTER JOIN participant p ON o.paramParticipantId1 = p.id
6 WHERE e.id = 181613058696728576 AND bo.bettingTypeId = 69 AND providerId = 3000984 AND o.eventPartId = 3;

providerId bettingTypeId odds name

3000984 69 7.5 Manchester United

3000984 69 1.3846154 Manchester City

3000984 69 5.5 NULL

C3. How to get the 1x2 odds offered by provider P for a football match? (Version 2)

Suppose you want to retrieve the 1x2 odds for the event part "Ordinary Time" offered by Bet365 for the match with the id
181613058696728576 (Manchester City vs Manchester United).

We know that: 1x2 bet type id is 69, OddsMatrix id is 3000984, 'Ordinary Time' id is 3.

Query

1 SELECT m.name AS marketName, o.id AS outcomeId, odds


2 FROM market m
3 INNER JOIN marketoutcomerelation mor ON m.id = mor.marketId
4 INNER JOIN outcome o ON o.id = mor.outcomeId
5 INNER JOIN bettingoffer bo ON bo.outcomeId = o.id
6 WHERE m.bettingTypeId = 69 AND m.eventPartId = 3 AND m.eventId = 181613058696728576 AND providerId = 3000984;

marketName outcomeId odds

111
Home Draw Away, Ordinary Time 181613058745029120 1.3846154

Home Draw Away, Ordinary Time 181613058749222912 7.5

Home Draw Away, Ordinary Time 181613058749223680 5.5

We have the odds, we need to interpret the outcomes. The outcome properties are generic, they have different meanings for different types.

Query

1 SELECT id, typeId, paramFloat1, paramFloat2, paramFloat3, paramBoolean1,


2 paramString1, paramParticipantId1, paramParticipantId2, paramParticipantId3, paramEventPartId1
3 FROM outcome
4 WHERE id IN (181613058745029120, 181613058749222912, 181613058749223680);

id typ paramF paramFloat para paramB param paramPart paramParti paramParti paramEve
eId loat1 2 mFloa oolean1 String icipantId1 cipantId2 cipantId3 ntPartId1
t3 1

181613058 10 NULL NULL NULL NULL NULL 50 NULL NULL NULL


745029120

181613058 10 NULL NULL NULL NULL NULL 11 NULL NULL NULL


749222912

181613058 11 NULL NULL NULL NULL NULL NULL NULL NULL NULL
749223680

Note that there are 3 outcomes: two of type 10 and one of type 11.

Query

1 SELECT id, name, description, paramParticipantId1Description


2 FROM outcometype
3 WHERE id in (10, 11);

id name description paramParticipantId1Description

10 Winner The winner of the event. Money lost on no-win. The id of the participant to win the event.

11 Draw The match is a draw. NULL

The outcome 181613058749223680 which has the type 11 refers to 'Draw'.

The generic parameter paramParticipantId1 refers to the 'id of the participant to win the event'.

The outcomes with typeId = 10 refer to the participants with ids 50 and 11

Let's see the participants:

Query

1 SELECT id, name


2 FROM participant
3 WHERE id IN (11, 50);

id name

11 Manchester United

112
50 Manchester City

In the end, let's see everything in one query:

Query

1 SELECT m.name AS marketName, odds, p.name AS participantName


2 FROM market m
3 INNER JOIN marketoutcomerelation mor ON m.id = mor.marketId
4 INNER JOIN outcome o ON o.id = mor.outcomeId
5 INNER JOIN bettingoffer bo ON bo.outcomeId = o.id
6 LEFT OUTER JOIN participant p ON p.id = o.paramParticipantId1
7 WHERE m.bettingTypeId = 69 AND m.eventPartId = 3 AND m.eventId = 181613058696728576 AND providerId = 3000984;

marketName odds participantName

Home Draw Away, Ordinary Time 7.5 Manchester United

Home Draw Away, Ordinary Time 1.3846154 Manchester City

Home Draw Away, Ordinary Time 5.5 NULL

C4. How to get the Over/Under odds offered by provider P for a football match?

Suppose you want to retrieve the Over/Under odds for the event part "Ordinary Time" offered by Bet365 for the match with the id 206795928
(Newcastle United FC - Chelsea).
We know that: Over/Under bet type id is 47, Bet3655 id is 3000181, 'Ordinary Time' id is 3.

Query

1 SELECT providerId, bettingTypeId, odds, eventId, o.id AS outcomeId


2 FROM bettingoffer bo
3 INNER JOIN outcome o ON bo.outcomeId = o.id
4 INNER JOIN event e ON o.eventId = e.id
5 WHERE e.id = 181613058696728576 AND bo.bettingTypeId = 47 AND providerId = 3000984 AND o.eventPartId = 3
6 LIMIT 2;

providerId bettingTypeId odds eventId outcomeId

3000984 47 1.3076923 181613058696728576 181613058739785728

3000984 47 3.4 181613058696728576 181613058739785984

We have the odds, we need to interpret the outcomes. The outcome properties are generic, they have different meanings for different types.

Query

1 SELECT id, typeId, paramFloat1, paramFloat2, paramFloat3, paramBoolean1,


2 paramString1, paramParticipantId1, paramParticipantId2, paramParticipantId3, paramEventPartId1
3 FROM outcome
4 WHERE id IN (181613058739785728, 181613058739785984);

id typ para para para paramB param paramParti paramParti paramParti paramEve
eId mFlo mFlo mFlo oolean1 String cipantId1 cipantId2 cipantId3 ntPartId1

113
at1 at2 at3 1

1816130587397857 13 2.25 NULL NULL NULL NULL NULL NULL NULL NULL
28

1816130587397859 14 2.25 NULL NULL NULL NULL NULL NULL NULL NULL
84

Note that there are 2 outcomes: one of type 13 and one of type 14.

Query

1 SELECT id, NAME, description, paramFloat1Description


2 FROM outcometype
3 WHERE id IN (13, 14);

id name description paramFloat1Description

13 Total Score Over The total score is greater than a certain threshold. The threshold.

14 Total Score Under The total score is less than a certain threshold. The threshold.

The outcome of type 13 refers to Over and the outcome of type 14 refers to Under. For both outcomes the generic parameter paramFloat1
refers to 2.25

In the end, let's see everything in one query:

Query

1 SELECT providerId, bettingTypeId, odds, ot.name AS outcomeTypeName, o.paramFloat1 AS threshold


2 FROM bettingoffer bo
3 INNER JOIN outcome o ON bo.outcomeId = o.id
4 INNER JOIN event e ON o.eventId = e.id
5 LEFT OUTER JOIN participant p ON o.paramParticipantId1 = p.id
6 INNER JOIN outcomeType ot ON o.typeId= ot.id
7 WHERE e.id = 181613058696728576
8 AND bo.bettingTypeId = 47 AND providerId = 3000984
9 AND o.eventPartId = 3 AND paramFloat1 = 2.25;

providerId bettingTypeId odds outcomeTypeName threshold

3000984 47 3.4 Total Score Under 2.25

3000984 47 1.3076923 Total Score Over 2.25

C5. How to get the Over/Under odds offered by provider P for a football match? (Version 2)

Suppose you want to retrieve the Over/Under odds for the event part "Ordinary Time" offered by Bet365 for the match with the id
181613058471284736 (West Ham United - Wolverhampton Wanderers).

We know that: Over/Under bet type id is 47, OddsMatrix id is 3000984, 'Ordinary Time' id is 3.

First, let's see how Over/Under markets are modeled:

114
Query

1 SELECT name, bettingtypeid, paramfloat1, paramfloat2, paramfloat3, paramparticipantid1


2 FROM market m
3 WHERE m.bettingtypeid = 47 AND m.eventpartid = 3 AND m.eventid = 181613058471284736
4 LIMIT 5;

name bettingTypeId paramFloat1 paramFloat2 paramFloat3 paramParticipantId1

Over/Under 3.5, Ordinary Time 47 3.5 NULL NULL NULL

Over/Under 1.75, Ordinary Time 47 1.75 NULL NULL NULL

Over/Under 1.5, Ordinary Time 47 1.5 NULL NULL NULL

Over/Under 3, Ordinary Time 47 3 NULL NULL NULL

Over/Under 2.25, Ordinary Time 47 2.25 NULL NULL NULL

Market entities, as Outcome entities, are modeled in a generic fashion. For Over/Under, the Market.paramFloat1 describes the threshold.
So, let's see how to retrieve odds for Over/Under 1.5

Query

1 SELECT m.name AS marketname, o.id AS outcomeid , odds


2 FROM market m
3 INNER JOIN marketoutcomerelation mor
4 ON m.id = mor.marketid
5 INNER JOIN outcome o
6 ON o.id = mor.outcomeid
7 INNER JOIN bettingoffer bo
8 ON bo.outcomeid = o.id
9 WHERE m.bettingtypeid = 47 AND m.eventpartid = 3
10 AND m.eventid = 181613058471284736
11 AND providerid = 3000984 AND m.paramfloat1 = 1.5;

marketName outcomeId odds

Over/Under 1.5, Ordinary Time 181613058526926336 1.2857143

Over/Under 1.5, Ordinary Time 181613058533217024 3.5

We have the odds, we need to interpret the outcomes. The outcome properties are generic, they have different meanings for different types.

Query

1 SELECT id, typeid, paramfloat1, paramfloat2, paramfloat3, paramboolean1, paramstring1, paramparticipantid1,


paramparticipantid2, paramparticipantid3, parameventpartid1
2 FROM outcome
3 WHERE id in (181613058526926336, 181613058533217024);

id typ para para para paramB param paramParti paramParti paramParti paramEve
eId mFlo mFlo mFlo oolean1 String cipantId1 cipantId2 cipantId3 ntPartId1
at1 at2 at3 1

1816130585269263 13 1.5 NULL NULL NULL NULL NULL NULL NULL NULL
36

115
1816130585332170 14 1.5 NULL NULL NULL NULL NULL NULL NULL NULL
24

Note that there are 2 outcomes: one of type 13 and one of type 14.

id name description paramFloat1Description

13 Total Score Over The total score is greater than a certain threshold. The threshold.

14 Total Score Under The total score is less than a certain threshold. The threshold.

The outcome of type 13 refers to Over and the outcome of type 14 refers to Under. For both outcomes the generic parameter paramFloat1
refers to 1.5

In the end, let's see everything in one query:

Query

1 SELECT m.name AS marketname, m.paramfloat1 AS threshold, ot.name, odds


2 FROM market m
3 INNER JOIN marketoutcomerelation mor
4 ON m.id = mor.marketid
5 INNER JOIN outcome o
6 ON o.id = mor.outcomeid
7 INNER JOIN outcometype ot
8 ON ot.id = o.typeid
9 INNER JOIN bettingoffer bo
10 ON bo.outcomeid = o.id
11 WHERE m.bettingtypeid = 47 AND m.eventpartid = 3
12 AND m.eventid = 181613058471284736 AND providerid = 3000984
13 AND m.paramfloat1 = 1.5;

marketName threshold name odds

Over/Under 1.5, Ordinary Time 1.5 Total Score Over 1.2857143

Over/Under 1.5, Ordinary Time 1.5 Total Score Under 3.5

C6. How to get the Asian Handicap odds offered by provider P for a football match (version 1)?

Suppose you want to retrieve the Asian Handicap odds for the event part "Ordinary Time" offered by OddsMatrix for the match with the id
181613058696728576 (Manchester City - Manchester United).

We know that: Asian Handicap bet type id is 48, OddsMatrix id is 3000984, 'Ordinary Time' id is 3.

Query

1 SELECT providerid , bettingtypeid, odds, eventid, o.id AS outcomeid


2 FROM bettingoffer bo
3 INNER JOIN outcome o
4 ON bo.outcomeid = o.id
5 INNER JOIN event e
6 ON o.eventid = e.id
7 WHERE e.id = 181613058696728576 AND bo.bettingtypeid = 48
8 AND providerid = 3000984 AND o.eventpartid = 3
9 LIMIT 2;

116
providerId bettingTypeId odds eventId outcomeId

3000984 48 1.3571428 181613058696728576 181613058742931456

3000984 48 1.6451613 181613058696728576 181613058747125760

We have the odds, we need to interpret the outcomes. The outcome properties are generic, they have different meanings for different types.

Query

1 SELECT id, typeid, paramfloat1, paramfloat2, paramfloat3, paramboolean1, paramstring1,


2 paramparticipantid1, paramparticipantid2, paramparticipantid3, parameventpartid1
3 FROM outcome
4 WHERE id in (181613058742931456, 181613058747125760);

id typ para para para paramB param paramParti paramParti paramParti paramEve
eId mFlo mFlo mFlo oolean1 String cipantId1 cipantId2 cipantId2 ntPartId1
at1 at2 at3 1

1816130587429314 60 -0.5 NULL NULL NULL NULL 50 NULL NULL NULL


56

1816130587471257 60 1.75 NULL NULL NULL NULL 11 NULL NULL NULL


60

Note that there are two outcomes with typeId 60.

Query

1 SELECT id, name, paramFloat1Description, paramParticipantId1Description


2 FROM outcometype
3 WHERE id = 60;

id name paramFloat1Description paramParticipantId1Description

60 Handicap Winner With Money Back on Draw The handicap value. The id of the participant to win the event.

The generic parameter paramFloat1 refers to 1.75, respectively to -0.5. Within a market, for Asian Handicap, the two outcomes have
opposite handicap values (in our case 1.75, -0.5).

The generic parameter paramParticipantId1 refers to the 'id of the participant to win the event'.

The outcome 181613058747125760 refers to the participant with id 11. The outcome 181613058742931456 refers to the participant with id
50.

Let's see the participants:

Query

1 SELECT id, name


2 FROM participant
3 WHERE id IN (11, 50);

id name

11 Manchester United

50 Manchester City

117
In the end, let's see everything in one query:

Query

1 SELECT providerId , bettingTypeId, odds, p.name, o.paramFloat1 AS handicap


2 FROM bettingoffer bo
3 INNER JOIN outcome o
4 ON bo.outcomeId = o.id
5 INNER JOIN event e
6 ON o.eventId = e.id
7 INNER JOIN participant p
8 ON o.paramParticipantId1 = p.id
9 WHERE e.id = 181613058696728576
10 AND bo.bettingTypeId = 48 AND providerId = 3000984 AND o.eventPartId = 3
11 LIMIT 2;

providerId bettingTypeId odds name handicap

3000984 48 1.3571428 Manchester City -0.5

3000984 48 1.6451613 Manchester United 1.75

C7. How to get the Asian Handicap odds offered by provider P for a football match? (Version 2)

Suppose you want to retrieve the Asian Handicap odds for the event part "Ordinary Time" offered by OddsMatrix for the match with id
181613058696728576 (Manchester City - Manchester United).

We know that: Asian Handicap bet type id is 48, Bet3655 id is 3000181, 'Ordinary Time' id is 3.

First, let's see how Asian Handicap markets are modeled:

Query

1 SELECT name, bettingTypeId, paramFloat1, paramFloat2, paramFloat3, paramParticipantId1


2 FROM market m
3 WHERE m.bettingTypeId = 48 AND m.eventPartId = 3 AND m.eventId = 181613058696728576
4 LIMIT 5;

name bettingTypeId paramFloat paramFloat paramFloat paramParticipantId1


1 2 3

Asian Handicap (-2.25), Ordinary Time 48 2.25 NULL NULL 11

Asian Handicap (-1.25), Ordinary Time 48 1.25 NULL NULL 11

Asian Handicap (-2.5), Ordinary Time 48 2.5 NULL NULL 11

Asian Handicap (-0.5), Ordinary Time 48 0.5 NULL NULL 11

Asian Handicap (-2), Ordinary Time 48 2 NULL NULL 11

Market entities, as Outcome entities, are modeled in a generic fashion. For Asian Handicap, the Market.paramFloat1 describes the handicap
value. So, let's see how to retrieve odds for Asian Handicap 1.5

118
Query

1 SELECT m.name AS marketname, o.id AS outcomeid , odds FROM market m


2 INNER JOIN marketoutcomerelation mor ON m.id = mor.marketid
3 INNER JOIN outcome o ON o.id = mor.outcomeid
4 INNER JOIN bettingoffer bo ON bo.outcomeid = o.id
5 WHERE m.bettingtypeid = 48 AND m.eventpartid = 3
6 AND m.eventid = 181613058696728576 AND providerid = 3000984
7 AND m.paramfloat1 = 1.5;

marketName outcomeId odds

Asian Handicap (1.5), Ordinary Time 181613058745028608 1.8474576

Asian Handicap (1.5), Ordinary Time 181613058747127040 1.9708738

We have the odds, we need to interpret the outcomes. The outcome properties are generic, they have different meanings for different types.

Query

1 SELECT id, typeid, paramfloat1, paramfloat2, paramfloat3, paramboolean1,


2 paramstring1, paramparticipantid1, paramparticipantid2,
3 paramparticipantid3, parameventpartid1
4 FROM outcome
5 WHERE id in (181613058745028608, 181613058747127040);

id typ para para para paramB param paramParti paramParti paramParti paramEve
eId mFlo mFlo mFlo oolean1 String cipantId1 cipantId2 cipantId3 ntPartId1
at1 at2 at3 1

1816130587450286 60 1.5 NULL NULL NULL NULL 11 NULL NULL NULL


08

1816130587471270 60 -1.5 NULL NULL NULL NULL 50 NULL NULL NULL


40

Note that there are two outcomes with typeId 60.

Query

1 SELECT id, name, paramfloat1description, paramparticipantid1description


2 FROM outcometype
3 WHERE id = 60;

id name paramFloat1Description paramParticipantId1Description

60 Handicap Winner With Money Back On Draw The handicap value. The id of the participant to win the event.

The generic parameter Outcome.paramFloat1 refers to 1.5, respectively to -1.5. Within a market, for Asian Handicap, the two outcomes
have opposite handicap values (in our case 1.5, -1.5).

The generic parameter paramParticipantId1 refers to the 'id of the participant to win the event'.

The outcome 181613058745028608 refers to the participant with id 11. The outcome 181613058747127040 refers to the participant with id
50.

Let's see the participants:

119
Query

1 SELECT id, name


2 FROM participant
3 WHERE id in (11, 50);

id name

11 Manchester United

50 Manchester City

In the end, let's see everything in one query:

Query

1 SELECT m.name AS marketname, o.paramfloat1 AS handicap, p.name AS participantname, odds


2 FROM market m
3 INNER JOIN marketoutcomerelation mor
4 ON m.id = mor.marketid
5 INNER JOIN outcome o
6 ON o.id = mor.outcomeid
7 INNER JOIN participant p
8 ON p.id = o.paramparticipantid1
9 INNER JOIN bettingoffer bo
10 ON bo.outcomeid = o.id
11 WHERE m.bettingtypeid = 48 AND m.eventpartid = 3
12 AND m.eventid = 181613058696728576
13 AND providerid = 3000984 AND m.paramfloat1 = 1.5;

marketName handicap participantName odds

Asian Handicap (1.5), Ordinary Time 1.5 Manchester United 1.8474576

Asian Handicap (1.5), Ordinary Time -1.5 Manchester City 1.9708738

C8. How to get the Home Draw Away With Handicap (HAD) odds offered by provider P for a football match?

Suppose you want to retrieve the Home Draw Away With Handicap odds for the event part "Ordinary Time" offered by Bet365 for the match
with id 181613058696728576 (Manchester City - Manchester United).

We know that: HAD bet type id is 8, OddsMatrix id is 3000984, 'Ordinary Time' id is 3.

Query

1 SELECT name, bettingtypeid, paramfloat1, paramfloat2, paramfloat3, paramparticipantid1


2 FROM market m
3 WHERE m.bettingtypeid = 8 AND m.eventpartid = 3 AND m.eventid = 181613058696728576
4 LIMIT 5;

name bettingType paramFloa paramFloa paramFloa paramParticipantI


Id t1 t2 t3 d1

Home Draw Away with Handicap (-1), Ordinary Time 8 1 NULL NULL 11

Home Draw Away with Handicap (-3), Ordinary Time 8 3 NULL NULL 11

120
Home Draw Away with Handicap (1), Ordinary Time 8 -1 NULL NULL 11

Home Draw Away with Handicap (-4), Ordinary Time 8 4 NULL NULL 11

Home Draw Away with Handicap (-2), Ordinary Time 8 2 NULL NULL 11

Market entities, as Outcome entities, are modeled in a generic fashion. For Home Draw Away With Handicap, the Market.paramFloat1
describes the handicap value. So, let's see how to retrieve odds for Home Draw Away With Handicap 1.

Query

1 SELECT m.name AS marketname, o.id AS outcomeid, odds


2 FROM market m
3 INNER JOIN marketoutcomerelation mor
4 ON m.id = mor.marketid
5 INNER JOIN outcome o
6 ON o.id = mor.outcomeid
7 INNER JOIN bettingoffer bo
8 ON bo.outcomeid = o.id
9 WHERE m.bettingtypeid = 8 AND m.eventpartid = 3
10 AND m.eventid = 181613058696728576 AND providerid = 3000984 AND m.paramfloat1 = 1;

marketName outcomeId odds

Home Draw Away with Handicap (-1), Ordinary Time 181616222964969728 3

Home Draw Away with Handicap (-1), Ordinary Time 181616222978600960 1.877193

Home Draw Away with Handicap (-1), Ordinary Time 181616222978601216 4

We have the odds, we need to interpret the outcomes. The outcome properties are generic, they have different meanings for different types.

Query

1 SELECT id, typeid, paramfloat1, paramfloat2, paramfloat3, paramboolean1, paramstring1,


2 paramparticipantid1, paramparticipantid2, paramparticipantid3, parameventpartid1
3 FROM outcome
4 WHERE id in (181616222964969728, 181616222978600960, 181616222978601216);

id typ para para para paramB param paramParti paramParti paramParti paramEve
eId mFlo mFlo mFlo oolean1 String cipantId1 cipantId2 cipantId3 ntPartId1
at1 at2 at3 1

1816162229649697 15 1 NULL NULL NULL NULL 11 NULL NULL NULL


28

1816162229786009 15 -1 NULL NULL NULL NULL 50 NULL NULL NULL


60

1816162229786012 16 1 NULL NULL NULL NULL 11 NULL NULL NULL


16

Note that there are 3 outcomes: two of type 15 and one of type 16.

Query

1 SELECT id, name, description, paramparticipantid1description


2 FROM outcometype

121
3 WHERE id in (15, 16);

id name description paramParticipantId1Description

15 Handicap The winner of the event, given a certain The id of the participant to win the event.
Winner handicap.

16 Handicap The match is a draw, given a certain The lowest participant id. The event is won at exactly the
Draw handicap. handicap value.

The generic parameter Outcome.paramFloat1 refers to 1, respectively to -1. Within a market, for HAD, the two outcomes that refer to Home
and Away participants have opposite handicap values (in our case 1, -1).

Draw will have as Outcome.paramParticipantId1 the participant with lowest id, while paramFloat1 will refer to the handicap corresponding to
that participant.

The generic parameter paramParticipantId1 refers to the 'id of the participant to win the event'.

Or the ‘id of the participant who wins the event at exactly the handicap value’ in case of Handicap Draw. As mentioned, by convention,
Handicap Draw will take the lowest participantId.

The outcome 181616222964969728 refers to the participant with id 11.

The outcome 181616222978600960 refers to the participant with id 50.

The outcome 181616222978601216 refers to Draw.

Let's see the participants:

Query

1 SELECT id, name


2 FROM participant
3 WHERE id in (11, 50);

id name

11 Manchester United

50 Manchester City

In the end, let's see everything in one query:

Query

1 SELECT m.name AS marketname, o.typeid AS outcometype,


2 o.paramfloat1 AS handicap,
3 p.name AS participantname, odds
4 FROM market m
5 INNER JOIN marketoutcomerelation mor
6 ON m.id = mor.marketid
7 INNER JOIN outcome o
8 ON o.id = mor.outcomeid
9 INNER JOIN participant p
10 ON p.id = o.paramparticipantid1
11 INNER JOIN bettingoffer bo
12 ON bo.outcomeid = o.id
13 WHERE m.bettingtypeid = 8 AND m.eventpartid = 3
14 AND m.eventid = 181613058696728576 AND providerid = 3000984 AND m.paramfloat1 = 1;

122
marketName outcomeType handicap participantName odds

Home Draw Away with Handicap (1), Ordinary Time 15 -1 Manchester City 1.877193

Home Draw Away with Handicap (1), Ordinary Time 15 1 Manchester United 3

Home Draw Away with Handicap (1), Ordinary Time 16 1 Manchester United 4

C9. How to get the Team Score Over/Under and other related bet types odds offered by provider P for a football match? (starting
from market)

Suppose you want to retrieve the Team Score Over/Under odds for the event part "Ordinary Time" offered by Bet365 for the match with id
181613058696728576 (Manchester City - Manchester United).

We know that: Team Score Over/Under bet type id is 77, OddsMatrix id is 3000984, 'Ordinary Time' id is 3.

First, let's see how Team Score Over/Under markets are modeled:

Query

1 SELECT name, bettingtypeid, paramfloat1, paramfloat2, paramfloat3, paramparticipantid1


2 FROM market m
3 WHERE m.bettingtypeid = 77 AND m.eventpartid = 3 AND m.eventid = 181613058696728576
4 LIMIT 5;

name bettingTyp paramFlo paramFlo paramFlo paramParticipant


eId at1 at2 at3 Id1

Manchester City Score Over/Under 2.5, Ordinary Time 77 2.5 NULL NULL 50

Manchester United Score Over/Under 0.5, Ordinary 77 0.5 NULL NULL 11


Time

Manchester City Score Over/Under 2, Ordinary Time 77 2 NULL NULL 50

Manchester City Score Over/Under 2.25, Ordinary Time 77 2.25 NULL NULL 50

Manchester City Score Over/Under 1.75, Ordinary Time 77 1.75 NULL NULL 50

Market entities, as Outcome entities, are modeled in a generic fashion. For Team Score Over/Under, the Market.paramFloat1 describes the
threshold. So, let's see how to retrieve odds for Over/Under 2.5

Query

1 SELECT m.name AS marketname, o.id AS outcomeid , odds


2 FROM market m
3 INNER JOIN marketoutcomerelation mor
4 ON m.id = mor.marketid
5 INNER JOIN outcome o
6 ON o.id = mor.outcomeid
7 INNER JOIN bettingoffer bo
8 ON bo.outcomeid = o.id
9 WHERE m.bettingtypeid = 77 AND m.eventpartid = 3
10 AND m.eventid = 181613058696728576
11 AND providerid = 3000984 AND m.paramfloat1 = 2.5;

marketName outcomeId odds

123
Manchester City Score Over/Under 2.5, Ordinary Time 181613058743981312 1.7299271

Manchester City Score Over/Under 2.5, Ordinary Time 181613058746078464 2.02

Manchester United Score Over/Under 2.5, Ordinary Time 181616224612282624 10

Manchester United Score Over/Under 2.5, Ordinary Time 181616224640594176 1.04

We have the odds, we need to interpret the outcomes. The outcome properties are generic, they have different meanings for different types.

Query

1 SELECT id, typeid, paramfloat1, paramfloat2, paramfloat3, paramboolean1,


2 paramstring1, paramparticipantid1, paramparticipantid2,
3 paramparticipantid3, parameventpartid1
4 FROM outcome
5 WHERE id IN (181613058743981312, 181613058746078464, 181616224612282624, 181616224640594176);

id typ para para para paramB param paramParti paramParti paramParti paramEve
eId mFlo mFlo mFlo oolean1 String cipantId1 cipantId2 cipantId3 ntPartId1
at1 at2 at3 1

1816130587439813 67 2.5 NULL NULL 0 NULL 50 NULL NULL NULL


12

1816130587460784 67 2.5 NULL NULL 1 NULL 50 NULL NULL NULL


64

1816162246122826 67 2.5 NULL NULL 1 NULL 11 NULL NULL NULL


24

1816162246405941 67 2.5 NULL NULL 0 NULL 11 NULL NULL NULL


76

Note that there are 4 outcomes of type 67.

Query

1 SELECT id, name, description, paramboolean1description, paramparticipantid1description


2 FROM outcometype
3 WHERE id IN (67);

id name description paramBoolean1Description paramParticipantI


d1Description

67 Team Score The number of goals scored by a team is over or True if over threshold, and false if The team.
Over/Under under a certain threshold. under threshold.

The generic parameter Outcome.paramFloat1 refers to the threshold value, in this case 2.5.

The generic parameter paramParticipantId1 refers to the 'The team.

The generic parameter paramBoolean1 is true if 'Over' and false if 'Under'

The outcomes 181613058743981312 and 181613058746078464 refer to the participant with id 50.

The outcomes 181616224612282624 and 181616224640594176 refer to the participant with id 11.

Let's see the participants:

124
Query

1 SELECT id, name


2 FROM participant
3 WHERE id in (11, 50);

id name

11 Manchester United

50 Manchester City

In the end, let's see everything in one query:

Query

1 SELECT m.name AS marketname, m.paramfloat1 AS threshold,


2 o.paramboolean1 AS ou, p.name AS participantname, odds
3 FROM market m
4 INNER JOIN marketoutcomerelation mor
5 ON m.id = mor.marketid
6 INNER JOIN outcome o
7 ON o.id = mor.outcomeid
8 INNER JOIN participant p
9 ON p.id = o.paramparticipantid1
10 INNER JOIN bettingoffer bo
11 ON bo.outcomeid = o.id
12 WHERE m.bettingtypeid = 77 AND m.eventpartid = 3
13 AND m.eventid = 181613058696728576
14 AND providerid = 3000984 AND m.paramfloat1 = 2.5;

marketName threshold OU participantName odds

Manchester City Score Over/Under 2.5, Ordinary Time 2.5 0 Manchester City 1.7299271

Manchester City Score Over/Under 2.5, Ordinary Time 2.5 1 Manchester City 2.02

Manchester United Score Over/Under 2.5, Ordinary Time 2.5 1 Manchester United 10

Manchester United Score Over/Under 2.5, Ordinary Time 2.5 0 Manchester United 1.04

C10. How to get the Scorings Over/Under In Time Range - and other related bet types - odds offered by provider P for a football
match? (starting from market)

Suppose you want to retrieve the Scorings Over/Under In Time Range odds for the event part "Ordinary Time", minutes 1 - 15 range, offered
by BWin for the match with id 181613058696728576 (Manchester City - Manchester United).

We know that: Scorings Over/Under In Time Range bet type id is 82, OddsMatrix id is 3000984, 'Ordinary Time' id is 3.

First, let's see how Scorings Over/Under In Time Range markets are modeled:

Query

1 SELECT name, bettingtypeid,


2 paramfloat1, paramfloat2, paramfloat3, paramparticipantid1
3 FROM market m
4 WHERE m.bettingtypeid = 82
5 AND m.eventpartid = 3 AND m.eventid = 181613058696728576

125
6 LIMIT 5;

name bettingTypeI paramFloat paramFloat paramFloat paramParticipantId


d 1 2 3 1

Goals Over/Under 0.5 In 1-15, Ordinary Time 82 1 15 05 NULL

Goals Over/Under 0.5 In 15-30, Ordinary Time 82 15 30 0.5 NULL

Goals Over/Under 0.5 In 30-45, Ordinary Time 82 30 45 0.5 NULL

Goals Over/Under 0.5 In 45-60, Ordinary Time 82 45 60 0.5 NULL

Goals Over/Under 0.5 In 60-75, Ordinary Time 82 60 75 0.5 NULL

Market entities, as Outcome entities, are modeled in a generic fashion.

For Scorings Over/Under In Time Range, the Market.paramFloat1 describes the lower bound of the range, Market.paramFloat2 describes
the upper bound of the range (null if none) and Market.paramFloat3 describes the threshold.

So, let's see how to retrieve odds for Over/Under 0.5 in the first 15 minutes of the match.

Query

1 SELECT m.name AS marketname, o.id AS outcomeid , odds


2 FROM market m
3 INNER JOIN marketoutcomerelation mor
4 ON m.id = mor.marketid
5 INNER JOIN outcome o
6 ON o.id = mor.outcomeid
7 INNER JOIN bettingoffer bo
8 ON bo.outcomeid = o.id
9 WHERE m.bettingtypeid = 82 AND m.eventpartid = 3
10 AND m.eventid = 181613058696728576 AND providerid = 3000984
11 AND m.paramfloat1 = 1
12 AND m.paramfloat2 = 15 AND m.paramfloat3 = 0.5;

marketName outcomeId odds

Goals Over/Under 0.5 In 1-15, Ordinary Time 181616858914575616 2.4

Goals Over/Under 0.5 In 1-15, Ordinary Time 181616858914575872 1.4545455

We have the odds, we need to interpret the outcomes. The outcome properties are generic, they have different meanings for different types.

Query

1 SELECT id, typeid, paramfloat1, paramfloat2,


2 paramfloat3, paramboolean1,
3 paramstring1, paramparticipantid1, paramparticipantid2,
4 paramparticipantid3, parameventpartid1
5 FROM outcome
6 WHERE id IN (181616858914575616, 181616858914575872);

id typ para para para paramB param paramParti paramParti paramParti paramEve
eId mFlo mFlo mFlo oolean1 String cipantId1 cipantId2 cipantId3 ntPartId1
at1 at2 at3 1

126
1816168589145756 73 1 15 0.5 1 NULL NULL NULL NULL NULL
16

1816168589145758 73 1 15 0.5 0 NULL NULL NULL NULL NULL


72

Note that there are two outcomes with typeId 73.

Query

1 SELECT id, name, description, paramboolean1description


2 FROM outcometype
3 WHERE id IN (73);

id name description paramBoolean1Descr


iption

73 Scorings The number of goals scored within a certain time range is over or under a certain True if over threshold,
Over/Under In threshold. (The time range is in minutes and relative to the start of the event part.) and false if under
Time Range threshold.

The generic parameter Outcome.paramFloat1 refers to the lower bound of the range.

The generic parameter Outcome.paramFloat2 refers to the upper bound of the range (or null, if none).

The generic parameter Outcome.paramFloat3 refers to the threshold, in this case 0.5.

The generic parameter paramBoolean1 is true if 'Over' and false if 'Under'

The outcome 181616858914575616 refers to Over 0.5.

The outcome 181616858914575872 refers to Under 0.5.

In the end, let's see everything in one query:

Query

1 SELECT m.name AS marketname, m.paramfloat1 AS lowerrange,


2 m.paramfloat2 AS upperrange, m.paramfloat3 AS threshold,
3 if(o.paramboolean1 = 1, "over", "under") AS ou, odds
4 FROM market m
5 INNER JOIN marketoutcomerelation mor
6 ON m.id = mor.marketid
7 INNER JOIN outcome o
8 ON o.id = mor.outcomeid
9 INNER JOIN bettingoffer bo
10 ON bo.outcomeid = o.id
11 WHERE m.bettingtypeid = 82 AND m.eventpartid = 3
12 AND m.eventid = 181613058696728576 AND providerid = 3000984
13 AND m.paramfloat1 = 1 AND m.paramfloat2 = 15 AND m.paramfloat3 = 0.5;

marketName lowerrange upperrange threshold OU odds

Goals Over/Under 0.5 In 1-15, Ordinary Time 1 15 0.5 OVER 2.4

Goals Over/Under 0.5 In 1-15, Ordinary Time 1 15 0.5 UNDER 1.4545455

C11. How to get the Correct Score odds offered by provider P for a football match? (starting from market)

127
Suppose you want to retrieve the Correct Score odds for the event part "Ordinary Time" offered by BWin for the match with the id
181613058471284736 (West Ham United - Wolverhampton Wanderers).

We know that: Correct Score bet type id is 45, OddsMatrix id is 3000984, 'Ordinary Time' id is 3.

Query

1 SELECT m.name AS marketname, o.id AS outcomeid, odds


2 FROM market m
3 INNER JOIN marketoutcomerelation mor
4 ON m.id = mor.marketid
5 INNER JOIN outcome o
6 ON o.id = mor.outcomeid
7 INNER JOIN bettingoffer bo
8 ON bo.outcomeid = o.id
9 WHERE m.bettingtypeid = 45 AND m.eventpartid = 3
10 AND m.eventid = 181613058471284736 AND providerid = 3000984
11 LIMIT 5;

marketName outcomeId odds

Correct Score, Ordinary Time 181616852541534208 201

Correct Score, Ordinary Time 181616852541534976 61

Correct Score, Ordinary Time 181616852542583040 41

Correct Score, Ordinary Time 181616852542583296 151

Correct Score, Ordinary Time 181616852550972416 151

We have the odds, we need to interpret the outcomes. The outcome properties are generic, they have different meanings for different types.

Query

1 SELECT id, typeId, paramFloat1, paramFloat2, paramBoolean1,


2 paramString1, paramParticipantId1, paramParticipantId2, paramParticipantId3, paramEventPartId1
3 FROM outcome
4 WHERE id IN (181616852541534208, 181616852541534976, 181616852542583040,
5 181616852542583296, 181616852550972416);

id typ param param paramBo param paramPartic paramPartic paramPartic paramEven


eId Float1 Float2 olean1 String1 ipantId1 ipantId2 ipantId3 tPartId1

1816168525415342 12 2 4 NULL NULL 19 62 NULL NULL


08

1816168525415349 12 2 3 NULL NULL 19 62 NULL NULL


76

1816168525425830 12 1 3 NULL NULL 19 62 NULL NULL


40

1816168525425832 12 1 4 NULL NULL 19 62 NULL NULL


96

1816168525509724 12 3 4 NULL NULL 19 62 NULL NULL


16

128
Note that the outcomes are of type 12.

Query

1 SELECT id, name, description, paramfloat1description, paramfloat2description,


2 paramparticipantid1description, paramparticipantid2description
3 FROM outcometype
4 WHERE id = 12;

id na description paramFloat1Descripti paramFloat2Description paramParticipantId paramParticipantId2D


me on 1Description escription

12 Sco The exact Number of goals scored Number of goals scored The first participant The second participant
re match score, by the first participant. by the second participant. id, with the lowest id. id, with the highest id.
Exa e.g. 4:2.
ct

The generic parameter Outcome.paramFloat1 refers to the number of goals scored by the first participant.

The generic parameter Outcome.paramFloat2 refers to the number of goals scored by the second participant.

The generic parameter paramParticipantId1 refers to the participant with the lowest id.

The generic parameter paramParticipantId2 refers to the participant with the highest id.

Let's see the participants:

Query

1 SELECT id, name


2 FROM participant
3 WHERE id IN (19, 62);

id name

19 West Ham United

62 Wolverhampton Wanderers

In the end, let's retrieve odds for Manchester City - Manchester United, score 1 - 0

Query

1 SELECT m.name AS marketname, o.typeid AS outcometype, o.paramfloat1 AS goals,


2 o.paramfloat2 AS goals, p1.name AS participantname1, p2.name AS participantname2, odds FROM market m
3 INNER JOIN marketoutcomerelation mor ON m.id = mor.marketid
4 INNER JOIN outcome o ON o.id = mor.outcomeid
5 INNER JOIN participant p1 ON p1.id = o.paramparticipantid1
6 INNER JOIN participant p2 ON p2.id = o.paramparticipantid2
7 INNER JOIN bettingoffer bo ON bo.outcomeid = o.id
8 WHERE m.bettingtypeid = 45 AND m.eventpartid = 3
9 AND m.eventid = 181613058696728576 AND providerid = 3000984
10 AND o.paramfloat1 = 0 AND o.paramfloat2 = 1;

Please mind that o.paramParticipantId1 will have the id of Manchester United, as it is the lowest (11) and o.paramParticipantId2
the id of Manchester City (50), which does not reflect the Home Away order, therefore the score values (float 1 - float 2) need to be
reversed.

129
marketName outcomeType goals goals participantName1 participantName2 odds

Correct Score, Ordinary Time 12 0 1 Manchester United Manchester City 9.5

and odds for Manchester City - Manchester United, score 0 - 1

Query

1 SELECT m.name AS marketname, o.typeid AS outcometype, o.paramfloat1 AS goals,


2 o.paramfloat2 AS goals, p1.name AS participantname1,
3 p2.name AS participantname2, odds FROM market m
4 INNER JOIN marketoutcomerelation mor ON m.id = mor.marketid
5 INNER JOIN outcome o ON o.id = mor.outcomeid
6 INNER JOIN participant p1 ON p1.id = o.paramparticipantid1
7 INNER JOIN participant p2 ON p2.id = o.paramparticipantid2
8 INNER JOIN bettingoffer bo ON bo.outcomeid = o.id
9 WHERE m.bettingtypeid = 45 AND m.eventpartid = 3
10 AND m.eventid = 181613058696728576 AND providerid = 3000984
11 AND o.paramfloat1 = 1 AND o.paramfloat2 = 0;

marketName outcomeType goals goals participantName1 participantName2 odds

Correct Score, Ordinary Time 12 1 0 Manchester United Manchester City 23

C12. How to get the Asian Handicap with Score odds offered by provider P for a football match? (starting from market)

Suppose you want to retrieve the “Asian Handicap With Score” odds for the event part "Ordinary Time" offered by OddsMatrix for the match
with the id 183613581320896512 (West Ham United vs Wolverhampton Wanderers).

We know that: “AH with Score” bet type id is 355, OddsMatrix id is 3000984, 'Ordinary Time' id is 3.

Query

1 SELECT id, name, bettingTypeId, paramFloat1 AS score_team_1,


2 paramFloat2 AS score_team_2, paramFloat3 AS handicap,
3 paramParticipantId1 AS handicap_team
4 FROM market m
5 WHERE m.bettingTypeId = 355
6 AND m.eventPartId = 3
7 AND m.eventId = 181613058471284736
8 LIMIT 10;

Market entities, as Outcome entities, are modeled in a generic fashion. For Asian Handicap, the Market.paramFloat1 and
Market.paramFloat2 describe the score, while Market.paramFloat3 describes the handicap value.

id name bettingTypeId score_team_1 score_team_2 handicap handicap_team

18361082321684 Asian Handicap 355 0 0 -0.5 West Ham


0704 (-0.5) [0:0], United
Ordinary Time

18361082321788 Asian Handicap 355 0 0 0 West Ham


9792 (0) [0:0], United
Ordinary Time

130
18361089054905 Asian Handicap 355 0 0 -0.75 West Ham
1392 (-0.75) [0:0], United
Ordinary Time

18361089055009 Asian Handicap 355 0 0 -0.25 West Ham


9968 (-0.25) [0:0], United
Ordinary Time

18361089055010 Asian Handicap 355 0 0 -1 West Ham


0480 (-1) [0:0], United
Ordinary Time

18361112263142 Asian Handicap 355 0 0 -1.25 West Ham


6048 (-1.25) [0:0], United
Ordinary Time

18361112267756 Asian Handicap 355 0 0 0.25 West Ham


3392 (0.25) [0:0], United
Ordinary Time

18361231195044 Asian Handicap 355 0 0 0.5 West Ham


2496 (0.5) [0:0], United
Ordinary Time

18361358131565 Asian Handicap 355 1 0 0.25 West Ham


3632 (0.25) [1:0], United
Ordinary Time

18361358132089 Asian Handicap 355 1 0 -0.25 West Ham


6512 (-0.25) [1:0], United
Ordinary Time

So, let's see how to retrieve odds for “Asian Handicap (-0.25) [1:0], Ordinary Time“, ID 183613581320896512:

1 SELECT m.name AS marketName, o.name AS outcomeName, odds


2 FROM market m
3 INNER JOIN marketoutcomerelation mor ON m.id = mor.marketId
4 INNER JOIN outcome o ON o.id = mor.outcomeId
5 INNER JOIN bettingoffer bo ON bo.outcomeId = o.id
6 WHERE m.id = 183613581320896512 AND providerId = 3000984;

marketName outcomeName odds

Asian Handicap (-0.25) [1:0], Ordinary Time (West Ham United 1-0) West Ham United 2.2
-0.25

Asian Handicap (-0.25) [1:0], Ordinary Time (West Ham United 1-0) Wolverhampton 1.6451613
Wanderers 0.25

C13. How to get tournament winner odds? (starting from market)

Suppose you want to retrieve the Bwin odds to win tournament with ID 206230140992253952 (England Premier League 2023/2024).

We know that: ‘Tournament winner' betting type ID is 7, 'Bwin’ provider ID is 3000006, 'Whole Event' event part ID is 1.

Query

131
1 SELECT m.name AS marketName, o.name AS outcomeName, odds
2 FROM market m
3 INNER JOIN marketoutcomerelation mor ON m.id = mor.marketId
4 INNER JOIN outcome o ON o.id = mor.outcomeId
5 INNER JOIN bettingoffer bo ON bo.outcomeId = o.id
6 WHERE m.bettingTypeId = 7 AND m.eventPartId = 1 AND m.eventId = 206230140992253952 AND providerId = 3000006;

marketName outcomeName odds

Tournament Winner Manchester City 1.44

Tournament Winner Arsenal 7

Tournament Winner Liverpool 8.5

Tournament Winner Tottenham Hotspur 21

Tournament Winner Manchester United 41

Tournament Winner Brighton and Hove Albion 41

Tournament Winner Newcastle United FC 51

Tournament Winner Chelsea 51

Tournament Winner Aston Villa 201

Tournament Winner West Ham United 201

Tournament Winner Brentford 501

Tournament Winner Crystal Palace FC 501

Tournament Winner Fulham 1001

Tournament Winner Nottingham Forest 1001

Tournament Winner Wolverhampton Wanderers 1001

Tournament Winner Bournemouth AFC 1001

Tournament Winner Burnley FC 1001

Tournament Winner Everton 1001

Tournament Winner Sheffield United FC 2501

Tournament Winner Luton Town 3001

C14. How to get outright betting types?

We know that: ‘Tournament' event type ID is 2, 'Football’ sport ID is 1.

Query

1 SELECT bt.id AS BettingTypeID, bt.name AS BettingTypeName, ep.id AS EventPartID, ep.name AS EventPartName


2 FROM bettingtypeusage btu
3 INNER JOIN bettingtype bt on btu.bettingtypeid = bt.id
4 INNER JOIN eventpart ep on btu.eventpartid = ep.id
5 WHERE eventtypeid = 2 and sportid = 1;

132
BettingTypeID BettingTypeName EventPartID EventPartNa
me

7 Winner 1 Whole Event

25 Top Goalscorer 1 Whole Event

26 Relegation 1 Whole Event

27 Promotion 1 Whole Event

28 Top X 1 Whole Event

37 Qualification 1 Whole Event

57 Rock Bottom 1 Whole Event

119 Name The Finalists 1 Whole Event

124 Head To Head 1 Whole Event

128 Head To Head To Head 1 Whole Event

216 Win And Each Way 1 Whole Event

240 Straight Forecast 1 Whole Event

241 Reverse Forecast 1 Whole Event

246 Reverse Tricast 1 Whole Event

297 Player Of The Tournament 1 Whole Event

298 Young Player Of The Tournament 1 Whole Event

299 Best Goalkeeper 1 Whole Event

300 Highest Scoring Team 1 Whole Event

301 Lowest Scoring Team 1 Whole Event

302 Team To Concede Most Goals 1 Whole Event

303 Team To Concede Least Goals 1 Whole Event

304 Team To Score Fastest Goal 1 Whole Event

312 To Stay Up 1 Whole Event

313 Top Promoted Team 1 Whole Event

314 Relegation Double 1 Whole Event

315 Relegation Treble 1 Whole Event

392 To Finish In Top Half 1 Whole Event

393 To Finish In Bottom Half 1 Whole Event

411 Special Bets 1 Whole Event

715 Top Assistman 1 Whole Event

133
D1. How to get the match score?

Query

1 SELECT e.name, IF(epr.participantRoleId = 1, ei.paramFloat1, ei.paramFloat2) AS homeGoals,


2 IF(epr.participantRoleId = 1, ei.paramFloat2, ei.paramFloat1) AS awayGoals
3 FROM event e
4 INNER JOIN eventinfo ei
5 ON e.id = ei.eventId
6 INNER JOIN eventparticipantrelation epr
7 ON (ei.paramParticipantId1 = epr.participantId AND ei.eventId = epr.eventId)
8 INNER JOIN eventinfotype eit
9 ON ei.typeId = eit.id
10 INNER JOIN eventpart ep
11 ON ei.eventPartId = ep.id
12 WHERE eit.id = 1 AND ep.id = 2 AND ei.eventPartId = 2 AND e.id = 181613058237452288
13 AND ei.providerId = 3000979;

Result on Sample database:

name homeGoals awayGoals

Liverpool vs Brighton and Hove Albion 3 3

D2. How to get all the ‘goal scored’ actions for a match?

Query

1 SELECT e.name AS matchName, ea.id as actionId, ea.paramFloat1 AS no_of_goal


2 FROM eventaction ea
3 INNER JOIN event e ON ea.eventId = e.id
4 WHERE ea.eventId = 181613058237452288 AND ea.typeId = 7 AND ea.providerId = 3000979
5 AND ea.eventPartId = 2;

Result on Sample database:

matchName actionId no_of_goal

Liverpool vs Brighton and Hove Albion 183602576395105536 1

Liverpool vs Brighton and Hove Albion 183603429468304640 2

Liverpool vs Brighton and Hove Albion 183604443714976512 3

Liverpool vs Brighton and Hove Albion 183606876752082176 4

Liverpool vs Brighton and Hove Albion 183607463399945472 5

Liverpool vs Brighton and Hove Albion 183608746471092736 6

134
D3. How to get the Teams/participants that scored each goal in a match?

Query

1 SELECT p.name AS participantName, ea.paramFloat1 AS no_of_goal


2 FROM eventaction ea
3 INNER JOIN eventactiondetail ead
4 ON ea.id = ead.eventActionId
5 INNER JOIN participant p
6 ON ead.paramParticipantId1 = p.id
7 INNER JOIN participanttype pt
8 ON p.typeId = pt.id
9 WHERE ea.eventId = 181613058237452288 AND ea.typeId = 7 AND pt.id = 1 AND
10 ea.eventPartId = 2 AND ead.typeId = 3 AND ea.providerId = 3000979;

Result on Sample database:

participantName no_of_goal

Leandro Trossard 1

Leandro Trossard 2

Roberto Firmino Barbosa de Oliveira 3

Roberto Firmino Barbosa de Oliveira 4

Adam Webster 5

Leandro Trossard 6

D4. How to get the time of each goal scored in a match?

Query

1 SELECT ea.paramFloat1 AS no_of_goal, ead.paramFloat1 AS min


2 FROM eventaction ea
3 INNER JOIN eventactiondetail ead
4 ON ea.id = ead.eventActionId
5 WHERE ea.eventId = 181613058237452288 AND ea.typeId = 7 AND ead.typeId = 2 AND
6 ea.providerId = 3000979 AND ea.eventPartId = 2
7 ORDER BY ead.paramFloat1 ASC;

Result on Sample database:

no_of_goal min

1 4

2 17

3 33

4 54

135
5 63

6 83

136

You might also like