fix marge conflict
This commit is contained in:
commit
6d6b574c0b
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// "context"
|
// "context"
|
||||||
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,8 @@ CREATE TABLE events (
|
||||||
match_period INT,
|
match_period INT,
|
||||||
is_live BOOLEAN,
|
is_live BOOLEAN,
|
||||||
status TEXT,
|
status TEXT,
|
||||||
fetched_at TIMESTAMP DEFAULT now()
|
fetched_at TIMESTAMP DEFAULT now(),
|
||||||
|
source TEXT DEFAULT 'b365api'
|
||||||
);
|
);
|
||||||
CREATE TABLE odds (
|
CREATE TABLE odds (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@ INSERT INTO events (
|
||||||
added_time,
|
added_time,
|
||||||
match_period,
|
match_period,
|
||||||
is_live,
|
is_live,
|
||||||
status
|
status,
|
||||||
|
source
|
||||||
)
|
)
|
||||||
VALUES (
|
VALUES (
|
||||||
$1,
|
$1,
|
||||||
|
|
@ -41,7 +42,8 @@ VALUES (
|
||||||
$17,
|
$17,
|
||||||
$18,
|
$18,
|
||||||
$19,
|
$19,
|
||||||
$20
|
$20,
|
||||||
|
$21
|
||||||
) ON CONFLICT (id) DO
|
) ON CONFLICT (id) DO
|
||||||
UPDATE
|
UPDATE
|
||||||
SET sport_id = EXCLUDED.sport_id,
|
SET sport_id = EXCLUDED.sport_id,
|
||||||
|
|
@ -63,6 +65,7 @@ SET sport_id = EXCLUDED.sport_id,
|
||||||
match_period = EXCLUDED.match_period,
|
match_period = EXCLUDED.match_period,
|
||||||
is_live = EXCLUDED.is_live,
|
is_live = EXCLUDED.is_live,
|
||||||
status = EXCLUDED.status,
|
status = EXCLUDED.status,
|
||||||
|
source = EXCLUDED.source,
|
||||||
fetched_at = now();
|
fetched_at = now();
|
||||||
-- name: InsertUpcomingEvent :exec
|
-- name: InsertUpcomingEvent :exec
|
||||||
INSERT INTO events (
|
INSERT INTO events (
|
||||||
|
|
@ -80,7 +83,8 @@ INSERT INTO events (
|
||||||
league_cc,
|
league_cc,
|
||||||
start_time,
|
start_time,
|
||||||
is_live,
|
is_live,
|
||||||
status
|
status,
|
||||||
|
source
|
||||||
)
|
)
|
||||||
VALUES (
|
VALUES (
|
||||||
$1,
|
$1,
|
||||||
|
|
@ -97,7 +101,8 @@ VALUES (
|
||||||
$12,
|
$12,
|
||||||
$13,
|
$13,
|
||||||
false,
|
false,
|
||||||
'upcoming'
|
'upcoming',
|
||||||
|
$14
|
||||||
) ON CONFLICT (id) DO
|
) ON CONFLICT (id) DO
|
||||||
UPDATE
|
UPDATE
|
||||||
SET sport_id = EXCLUDED.sport_id,
|
SET sport_id = EXCLUDED.sport_id,
|
||||||
|
|
@ -114,6 +119,7 @@ SET sport_id = EXCLUDED.sport_id,
|
||||||
start_time = EXCLUDED.start_time,
|
start_time = EXCLUDED.start_time,
|
||||||
is_live = false,
|
is_live = false,
|
||||||
status = 'upcoming',
|
status = 'upcoming',
|
||||||
|
source = EXCLUDED.source,
|
||||||
fetched_at = now();
|
fetched_at = now();
|
||||||
-- name: ListLiveEvents :many
|
-- name: ListLiveEvents :many
|
||||||
SELECT id
|
SELECT id
|
||||||
|
|
@ -135,6 +141,7 @@ SELECT id,
|
||||||
start_time,
|
start_time,
|
||||||
is_live,
|
is_live,
|
||||||
status,
|
status,
|
||||||
|
source,
|
||||||
fetched_at
|
fetched_at
|
||||||
FROM events
|
FROM events
|
||||||
WHERE is_live = false
|
WHERE is_live = false
|
||||||
|
|
@ -156,6 +163,7 @@ SELECT id,
|
||||||
start_time,
|
start_time,
|
||||||
is_live,
|
is_live,
|
||||||
status,
|
status,
|
||||||
|
source,
|
||||||
fetched_at
|
fetched_at
|
||||||
FROM events
|
FROM events
|
||||||
WHERE start_time < now()
|
WHERE start_time < now()
|
||||||
|
|
@ -197,6 +205,7 @@ SELECT id,
|
||||||
start_time,
|
start_time,
|
||||||
is_live,
|
is_live,
|
||||||
status,
|
status,
|
||||||
|
source,
|
||||||
fetched_at
|
fetched_at
|
||||||
FROM events
|
FROM events
|
||||||
WHERE is_live = false
|
WHERE is_live = false
|
||||||
|
|
@ -235,6 +244,7 @@ SELECT id,
|
||||||
start_time,
|
start_time,
|
||||||
is_live,
|
is_live,
|
||||||
status,
|
status,
|
||||||
|
source,
|
||||||
fetched_at
|
fetched_at
|
||||||
FROM events
|
FROM events
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: auth.sql
|
// source: auth.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: bet.sql
|
// source: bet.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: branch.sql
|
// source: branch.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: company.sql
|
// source: company.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: copyfrom.go
|
// source: copyfrom.go
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: events.sql
|
// source: events.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
@ -37,6 +37,7 @@ SELECT id,
|
||||||
start_time,
|
start_time,
|
||||||
is_live,
|
is_live,
|
||||||
status,
|
status,
|
||||||
|
source,
|
||||||
fetched_at
|
fetched_at
|
||||||
FROM events
|
FROM events
|
||||||
WHERE is_live = false
|
WHERE is_live = false
|
||||||
|
|
@ -60,6 +61,7 @@ type GetAllUpcomingEventsRow struct {
|
||||||
StartTime pgtype.Timestamp `json:"start_time"`
|
StartTime pgtype.Timestamp `json:"start_time"`
|
||||||
IsLive pgtype.Bool `json:"is_live"`
|
IsLive pgtype.Bool `json:"is_live"`
|
||||||
Status pgtype.Text `json:"status"`
|
Status pgtype.Text `json:"status"`
|
||||||
|
Source pgtype.Text `json:"source"`
|
||||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,6 +90,7 @@ func (q *Queries) GetAllUpcomingEvents(ctx context.Context) ([]GetAllUpcomingEve
|
||||||
&i.StartTime,
|
&i.StartTime,
|
||||||
&i.IsLive,
|
&i.IsLive,
|
||||||
&i.Status,
|
&i.Status,
|
||||||
|
&i.Source,
|
||||||
&i.FetchedAt,
|
&i.FetchedAt,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -116,6 +119,7 @@ SELECT id,
|
||||||
start_time,
|
start_time,
|
||||||
is_live,
|
is_live,
|
||||||
status,
|
status,
|
||||||
|
source,
|
||||||
fetched_at
|
fetched_at
|
||||||
FROM events
|
FROM events
|
||||||
WHERE start_time < now()
|
WHERE start_time < now()
|
||||||
|
|
@ -138,6 +142,7 @@ type GetExpiredUpcomingEventsRow struct {
|
||||||
StartTime pgtype.Timestamp `json:"start_time"`
|
StartTime pgtype.Timestamp `json:"start_time"`
|
||||||
IsLive pgtype.Bool `json:"is_live"`
|
IsLive pgtype.Bool `json:"is_live"`
|
||||||
Status pgtype.Text `json:"status"`
|
Status pgtype.Text `json:"status"`
|
||||||
|
Source pgtype.Text `json:"source"`
|
||||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,6 +171,7 @@ func (q *Queries) GetExpiredUpcomingEvents(ctx context.Context) ([]GetExpiredUpc
|
||||||
&i.StartTime,
|
&i.StartTime,
|
||||||
&i.IsLive,
|
&i.IsLive,
|
||||||
&i.Status,
|
&i.Status,
|
||||||
|
&i.Source,
|
||||||
&i.FetchedAt,
|
&i.FetchedAt,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -194,6 +200,7 @@ SELECT id,
|
||||||
start_time,
|
start_time,
|
||||||
is_live,
|
is_live,
|
||||||
status,
|
status,
|
||||||
|
source,
|
||||||
fetched_at
|
fetched_at
|
||||||
FROM events
|
FROM events
|
||||||
WHERE is_live = false
|
WHERE is_live = false
|
||||||
|
|
@ -243,6 +250,7 @@ type GetPaginatedUpcomingEventsRow struct {
|
||||||
StartTime pgtype.Timestamp `json:"start_time"`
|
StartTime pgtype.Timestamp `json:"start_time"`
|
||||||
IsLive pgtype.Bool `json:"is_live"`
|
IsLive pgtype.Bool `json:"is_live"`
|
||||||
Status pgtype.Text `json:"status"`
|
Status pgtype.Text `json:"status"`
|
||||||
|
Source pgtype.Text `json:"source"`
|
||||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -278,6 +286,7 @@ func (q *Queries) GetPaginatedUpcomingEvents(ctx context.Context, arg GetPaginat
|
||||||
&i.StartTime,
|
&i.StartTime,
|
||||||
&i.IsLive,
|
&i.IsLive,
|
||||||
&i.Status,
|
&i.Status,
|
||||||
|
&i.Source,
|
||||||
&i.FetchedAt,
|
&i.FetchedAt,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -348,6 +357,7 @@ SELECT id,
|
||||||
start_time,
|
start_time,
|
||||||
is_live,
|
is_live,
|
||||||
status,
|
status,
|
||||||
|
source,
|
||||||
fetched_at
|
fetched_at
|
||||||
FROM events
|
FROM events
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
|
|
@ -372,6 +382,7 @@ type GetUpcomingByIDRow struct {
|
||||||
StartTime pgtype.Timestamp `json:"start_time"`
|
StartTime pgtype.Timestamp `json:"start_time"`
|
||||||
IsLive pgtype.Bool `json:"is_live"`
|
IsLive pgtype.Bool `json:"is_live"`
|
||||||
Status pgtype.Text `json:"status"`
|
Status pgtype.Text `json:"status"`
|
||||||
|
Source pgtype.Text `json:"source"`
|
||||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -394,6 +405,7 @@ func (q *Queries) GetUpcomingByID(ctx context.Context, id string) (GetUpcomingBy
|
||||||
&i.StartTime,
|
&i.StartTime,
|
||||||
&i.IsLive,
|
&i.IsLive,
|
||||||
&i.Status,
|
&i.Status,
|
||||||
|
&i.Source,
|
||||||
&i.FetchedAt,
|
&i.FetchedAt,
|
||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
|
|
@ -420,7 +432,8 @@ INSERT INTO events (
|
||||||
added_time,
|
added_time,
|
||||||
match_period,
|
match_period,
|
||||||
is_live,
|
is_live,
|
||||||
status
|
status,
|
||||||
|
source
|
||||||
)
|
)
|
||||||
VALUES (
|
VALUES (
|
||||||
$1,
|
$1,
|
||||||
|
|
@ -442,7 +455,8 @@ VALUES (
|
||||||
$17,
|
$17,
|
||||||
$18,
|
$18,
|
||||||
$19,
|
$19,
|
||||||
$20
|
$20,
|
||||||
|
$21
|
||||||
) ON CONFLICT (id) DO
|
) ON CONFLICT (id) DO
|
||||||
UPDATE
|
UPDATE
|
||||||
SET sport_id = EXCLUDED.sport_id,
|
SET sport_id = EXCLUDED.sport_id,
|
||||||
|
|
@ -464,6 +478,7 @@ SET sport_id = EXCLUDED.sport_id,
|
||||||
match_period = EXCLUDED.match_period,
|
match_period = EXCLUDED.match_period,
|
||||||
is_live = EXCLUDED.is_live,
|
is_live = EXCLUDED.is_live,
|
||||||
status = EXCLUDED.status,
|
status = EXCLUDED.status,
|
||||||
|
source = EXCLUDED.source,
|
||||||
fetched_at = now()
|
fetched_at = now()
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
@ -488,6 +503,7 @@ type InsertEventParams struct {
|
||||||
MatchPeriod pgtype.Int4 `json:"match_period"`
|
MatchPeriod pgtype.Int4 `json:"match_period"`
|
||||||
IsLive pgtype.Bool `json:"is_live"`
|
IsLive pgtype.Bool `json:"is_live"`
|
||||||
Status pgtype.Text `json:"status"`
|
Status pgtype.Text `json:"status"`
|
||||||
|
Source pgtype.Text `json:"source"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) InsertEvent(ctx context.Context, arg InsertEventParams) error {
|
func (q *Queries) InsertEvent(ctx context.Context, arg InsertEventParams) error {
|
||||||
|
|
@ -512,6 +528,7 @@ func (q *Queries) InsertEvent(ctx context.Context, arg InsertEventParams) error
|
||||||
arg.MatchPeriod,
|
arg.MatchPeriod,
|
||||||
arg.IsLive,
|
arg.IsLive,
|
||||||
arg.Status,
|
arg.Status,
|
||||||
|
arg.Source,
|
||||||
)
|
)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -532,7 +549,8 @@ INSERT INTO events (
|
||||||
league_cc,
|
league_cc,
|
||||||
start_time,
|
start_time,
|
||||||
is_live,
|
is_live,
|
||||||
status
|
status,
|
||||||
|
source
|
||||||
)
|
)
|
||||||
VALUES (
|
VALUES (
|
||||||
$1,
|
$1,
|
||||||
|
|
@ -549,7 +567,8 @@ VALUES (
|
||||||
$12,
|
$12,
|
||||||
$13,
|
$13,
|
||||||
false,
|
false,
|
||||||
'upcoming'
|
'upcoming',
|
||||||
|
$14
|
||||||
) ON CONFLICT (id) DO
|
) ON CONFLICT (id) DO
|
||||||
UPDATE
|
UPDATE
|
||||||
SET sport_id = EXCLUDED.sport_id,
|
SET sport_id = EXCLUDED.sport_id,
|
||||||
|
|
@ -566,6 +585,7 @@ SET sport_id = EXCLUDED.sport_id,
|
||||||
start_time = EXCLUDED.start_time,
|
start_time = EXCLUDED.start_time,
|
||||||
is_live = false,
|
is_live = false,
|
||||||
status = 'upcoming',
|
status = 'upcoming',
|
||||||
|
source = EXCLUDED.source,
|
||||||
fetched_at = now()
|
fetched_at = now()
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
@ -583,6 +603,7 @@ type InsertUpcomingEventParams struct {
|
||||||
LeagueName pgtype.Text `json:"league_name"`
|
LeagueName pgtype.Text `json:"league_name"`
|
||||||
LeagueCc pgtype.Text `json:"league_cc"`
|
LeagueCc pgtype.Text `json:"league_cc"`
|
||||||
StartTime pgtype.Timestamp `json:"start_time"`
|
StartTime pgtype.Timestamp `json:"start_time"`
|
||||||
|
Source pgtype.Text `json:"source"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) InsertUpcomingEvent(ctx context.Context, arg InsertUpcomingEventParams) error {
|
func (q *Queries) InsertUpcomingEvent(ctx context.Context, arg InsertUpcomingEventParams) error {
|
||||||
|
|
@ -600,6 +621,7 @@ func (q *Queries) InsertUpcomingEvent(ctx context.Context, arg InsertUpcomingEve
|
||||||
arg.LeagueName,
|
arg.LeagueName,
|
||||||
arg.LeagueCc,
|
arg.LeagueCc,
|
||||||
arg.StartTime,
|
arg.StartTime,
|
||||||
|
arg.Source,
|
||||||
)
|
)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
||||||
|
|
@ -196,6 +196,7 @@ type Event struct {
|
||||||
IsLive pgtype.Bool `json:"is_live"`
|
IsLive pgtype.Bool `json:"is_live"`
|
||||||
Status pgtype.Text `json:"status"`
|
Status pgtype.Text `json:"status"`
|
||||||
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
FetchedAt pgtype.Timestamp `json:"fetched_at"`
|
||||||
|
Source pgtype.Text `json:"source"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Notification struct {
|
type Notification struct {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: notification.sql
|
// source: notification.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: odds.sql
|
// source: odds.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: otp.sql
|
// source: otp.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: referal.sql
|
// source: referal.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: result.sql
|
// source: result.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: ticket.sql
|
// source: ticket.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: transactions.sql
|
// source: transactions.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: transfer.sql
|
// source: transfer.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: user.sql
|
// source: user.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: virtual_games.sql
|
// source: virtual_games.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Code generated by sqlc. DO NOT EDIT.
|
// Code generated by sqlc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// sqlc v1.28.0
|
// sqlc v1.29.0
|
||||||
// source: wallet.sql
|
// source: wallet.sql
|
||||||
|
|
||||||
package dbgen
|
package dbgen
|
||||||
|
|
|
||||||
2
go.mod
2
go.mod
|
|
@ -18,6 +18,8 @@ require (
|
||||||
golang.org/x/crypto v0.36.0
|
golang.org/x/crypto v0.36.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
require github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,35 @@ type Event struct {
|
||||||
MatchPeriod int
|
MatchPeriod int
|
||||||
IsLive bool
|
IsLive bool
|
||||||
Status string
|
Status string
|
||||||
|
Source string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BetResult struct {
|
||||||
|
Success int `json:"success"`
|
||||||
|
Pager struct {
|
||||||
|
Page int `json:"page"`
|
||||||
|
PerPage int `json:"per_page"`
|
||||||
|
Total int `json:"total"`
|
||||||
|
}
|
||||||
|
Results []struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
SportID string `json:"sport_id"`
|
||||||
|
Time string `json:"time"`
|
||||||
|
League struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"league"`
|
||||||
|
Home struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"home"`
|
||||||
|
Away *struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"away"`
|
||||||
|
} `json:"results"`
|
||||||
|
}
|
||||||
|
|
||||||
type UpcomingEvent struct {
|
type UpcomingEvent struct {
|
||||||
ID string // Event ID
|
ID string // Event ID
|
||||||
SportID string // Sport ID
|
SportID string // Sport ID
|
||||||
|
|
@ -38,6 +66,7 @@ type UpcomingEvent struct {
|
||||||
LeagueName string // League name
|
LeagueName string // League name
|
||||||
LeagueCC string // League country code
|
LeagueCC string // League country code
|
||||||
StartTime time.Time // Converted from "time" field in UNIX format
|
StartTime time.Time // Converted from "time" field in UNIX format
|
||||||
|
Source string // bet api provider (bet365, betfair)
|
||||||
}
|
}
|
||||||
type MatchResult struct {
|
type MatchResult struct {
|
||||||
EventID string
|
EventID string
|
||||||
|
|
|
||||||
|
|
@ -151,3 +151,142 @@ type IceHockeyResultResponse struct {
|
||||||
ConfirmedAt string `json:"confirmed_at"`
|
ConfirmedAt string `json:"confirmed_at"`
|
||||||
Bet365ID string `json:"bet365_id"`
|
Bet365ID string `json:"bet365_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CricketResultResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
SportID string `json:"sport_id"`
|
||||||
|
Time string `json:"time"`
|
||||||
|
TimeStatus string `json:"time_status"`
|
||||||
|
League struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
CC string `json:"cc"`
|
||||||
|
} `json:"league"`
|
||||||
|
Home struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ImageID string `json:"image_id"`
|
||||||
|
CC string `json:"cc"`
|
||||||
|
} `json:"home"`
|
||||||
|
Away struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ImageID string `json:"image_id"`
|
||||||
|
CC string `json:"cc"`
|
||||||
|
} `json:"away"`
|
||||||
|
SS string `json:"ss"`
|
||||||
|
Extra struct {
|
||||||
|
HomePos string `json:"home_pos"`
|
||||||
|
AwayPos string `json:"away_pos"`
|
||||||
|
NumberOfPeriods string `json:"numberofperiods"`
|
||||||
|
PeriodLength string `json:"periodlength"`
|
||||||
|
StadiumData map[string]string `json:"stadium_data"`
|
||||||
|
} `json:"extra"`
|
||||||
|
HasLineup int `json:"has_lineup"`
|
||||||
|
ConfirmedAt string `json:"confirmed_at"`
|
||||||
|
Bet365ID string `json:"bet365_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type VolleyballResultResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
SportID string `json:"sport_id"`
|
||||||
|
Time string `json:"time"`
|
||||||
|
TimeStatus string `json:"time_status"`
|
||||||
|
League struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
CC string `json:"cc"`
|
||||||
|
} `json:"league"`
|
||||||
|
Home struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ImageID string `json:"image_id"`
|
||||||
|
CC string `json:"cc"`
|
||||||
|
} `json:"home"`
|
||||||
|
Away struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ImageID string `json:"image_id"`
|
||||||
|
CC string `json:"cc"`
|
||||||
|
} `json:"away"`
|
||||||
|
SS string `json:"ss"`
|
||||||
|
Scores struct {
|
||||||
|
FirstSet Score `json:"1"`
|
||||||
|
SecondSet Score `json:"2"`
|
||||||
|
ThirdSet Score `json:"3"`
|
||||||
|
FourthSet Score `json:"4"`
|
||||||
|
FivethSet Score `json:"5"`
|
||||||
|
} `json:"scores"`
|
||||||
|
Stats struct {
|
||||||
|
PointsWonOnServe []string `json:"points_won_on_serve"`
|
||||||
|
LongestStreak []string `json:"longest_streak"`
|
||||||
|
} `json:"stats"`
|
||||||
|
InplayCreatedAt string `json:"inplay_created_at"`
|
||||||
|
InplayUpdatedAt string `json:"inplay_updated_at"`
|
||||||
|
Bet365ID string `json:"bet365_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DartsResultResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
SportID string `json:"sport_id"`
|
||||||
|
Time string `json:"time"`
|
||||||
|
TimeStatus string `json:"time_status"`
|
||||||
|
League struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
CC string `json:"cc"`
|
||||||
|
} `json:"league"`
|
||||||
|
Home struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ImageID string `json:"image_id"`
|
||||||
|
CC string `json:"cc"`
|
||||||
|
} `json:"home"`
|
||||||
|
Away struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ImageID string `json:"image_id"`
|
||||||
|
CC string `json:"cc"`
|
||||||
|
} `json:"away"`
|
||||||
|
SS string `json:"ss"`
|
||||||
|
InplayCreatedAt string `json:"inplay_created_at"`
|
||||||
|
InplayUpdatedAt string `json:"inplay_updated_at"`
|
||||||
|
ConfirmedAt string `json:"confirmed_at"`
|
||||||
|
Bet365ID string `json:"bet365_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FutsalResultResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
SportID string `json:"sport_id"`
|
||||||
|
Time string `json:"time"`
|
||||||
|
TimeStatus string `json:"time_status"`
|
||||||
|
League struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
CC string `json:"cc"`
|
||||||
|
} `json:"league"`
|
||||||
|
Home struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ImageID string `json:"image_id"`
|
||||||
|
CC string `json:"cc"`
|
||||||
|
} `json:"home"`
|
||||||
|
Away struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ImageID string `json:"image_id"`
|
||||||
|
CC string `json:"cc"`
|
||||||
|
} `json:"away"`
|
||||||
|
SS string `json:"ss"`
|
||||||
|
Scores struct {
|
||||||
|
FirstPeriod Score `json:"1"`
|
||||||
|
SecondPeriod Score `json:"2"`
|
||||||
|
ThirdPeriod Score `json:"3"`
|
||||||
|
TotalScore Score `json:"4"`
|
||||||
|
} `json:"scores"`
|
||||||
|
Events []map[string]string `json:"events"`
|
||||||
|
InplayCreatedAt string `json:"inplay_created_at"`
|
||||||
|
InplayUpdatedAt string `json:"inplay_updated_at"`
|
||||||
|
ConfirmedAt string `json:"confirmed_at"`
|
||||||
|
Bet365ID string `json:"bet365_id"`
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,72 @@ const (
|
||||||
ICE_HOCKEY_ALTERNATIVE_TOTAL_TWO_WAY IceHockeyMarket = 170240
|
ICE_HOCKEY_ALTERNATIVE_TOTAL_TWO_WAY IceHockeyMarket = 170240
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type CricketMarket int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Main
|
||||||
|
CRICKET_TO_WIN_THE_MATCH CricketMarket = 1246
|
||||||
|
CRICKET_TEAM_TOP_BATTER CricketMarket = 1241
|
||||||
|
CRICKET_TEAM_TOP_BOWLE CricketMarket = 1242
|
||||||
|
CRICKET_PLAYER_OF_THE_MATCH CricketMarket = 346
|
||||||
|
CRICKET_FIRST_WICKET_METHOD CricketMarket = 30205
|
||||||
|
|
||||||
|
// First Over
|
||||||
|
CRICKET_FIRST_OVER_TOTAL_RUNS CricketMarket = 300336
|
||||||
|
CRICKET_FIRST_OVER_TOTAL_RUNS_Odd_Even CricketMarket = 300118
|
||||||
|
|
||||||
|
// Inninigs 1
|
||||||
|
CRICKET_FIRST_INNINIGS_SCORE CricketMarket = 300338
|
||||||
|
CRICKET_INNINGS_OF_MATCH_BOWLED_OUT CricketMarket = 300108
|
||||||
|
|
||||||
|
// Match
|
||||||
|
CRICKET_TOP_MATCH_BATTER CricketMarket = 30245
|
||||||
|
CRICKET_TOP_MATCH_BOWLER CricketMarket = 30246
|
||||||
|
)
|
||||||
|
|
||||||
|
type VolleyballMarket int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
VOLLEYBALL_GAME_LINES VolleyballMarket = 910000
|
||||||
|
VOLLEYBALL_CORRECT_SET_SCORE VolleyballMarket = 910201
|
||||||
|
VOLLEYBALL_MATCH_TOTAL_ODD_EVEN VolleyballMarket = 910217
|
||||||
|
VOLLEYBALL_SET_ONE_LINES VolleyballMarket = 910204
|
||||||
|
VOLLEYBALL_SET_ONE_TO_GO_TO_EXTRA_POINTS VolleyballMarket = 910209
|
||||||
|
VOLLEYBALL_SET_ONE_TOTAL_ODD_EVEN VolleyballMarket = 910218
|
||||||
|
)
|
||||||
|
|
||||||
|
type DartsMarket int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Main
|
||||||
|
DARTS_MATCH_WINNER DartsMarket = 703 // match_winner
|
||||||
|
DARTS_MATCH_DOUBLE DartsMarket = 150228 // match_double
|
||||||
|
DARTS_MATCH_TREBLE DartsMarket = 150230 // match_treble
|
||||||
|
DARTS_CORRECT_LEG_SCORE DartsMarket = 150015 // correct_leg_score
|
||||||
|
DARTS_TOTAL_LEGS DartsMarket = 150117 // total_legs
|
||||||
|
|
||||||
|
DARTS_MOST_HUNDERED_EIGHTYS DartsMarket = 150030 // "most_180s"
|
||||||
|
DARTS_TOTAL_HUNDERED_EIGHTYS DartsMarket = 150012 // total_180s
|
||||||
|
DARTS_MOST_HUNDERED_EIGHTYS_HANDICAP DartsMarket = 150227 // most_180s_handicap
|
||||||
|
DARTS_PLAYER_HUNDERED_EIGHTYS DartsMarket = 150121 // player_180s
|
||||||
|
DARTS_FIRST_DART DartsMarket = 150125 // first_dart
|
||||||
|
)
|
||||||
|
|
||||||
|
type FutsalMarket int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Main
|
||||||
|
FUTSAL_GAME_LINES FutsalMarket = 830001
|
||||||
|
FUTSAL_MONEY_LINE FutsalMarket = 830130
|
||||||
|
|
||||||
|
// Others
|
||||||
|
FUTSAL_DOUBLE_RESULT_9_WAY FutsalMarket = 830124
|
||||||
|
|
||||||
|
// Score
|
||||||
|
FUTSAL_TEAM_TO_SCORE_FIRST FutsalMarket = 830141
|
||||||
|
FUTSAL_RACE_TO_GOALS FutsalMarket = 830142
|
||||||
|
)
|
||||||
|
|
||||||
type AmericanFootballMarket int64
|
type AmericanFootballMarket int64
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -214,6 +280,50 @@ var SupportedMarkets = map[int64]bool{
|
||||||
int64(ICE_HOCKEY_ALTERNATIVE_PUCK_LINE_TWO_WAY): false,
|
int64(ICE_HOCKEY_ALTERNATIVE_PUCK_LINE_TWO_WAY): false,
|
||||||
int64(ICE_HOCKEY_ALTERNATIVE_TOTAL_TWO_WAY): false,
|
int64(ICE_HOCKEY_ALTERNATIVE_TOTAL_TWO_WAY): false,
|
||||||
|
|
||||||
|
// Cricket Markets
|
||||||
|
int64(CRICKET_TO_WIN_THE_MATCH): true,
|
||||||
|
|
||||||
|
int64(CRICKET_FIRST_OVER_TOTAL_RUNS_Odd_Even): false,
|
||||||
|
int64(CRICKET_FIRST_INNINIGS_SCORE): false,
|
||||||
|
int64(CRICKET_INNINGS_OF_MATCH_BOWLED_OUT): false,
|
||||||
|
int64(CRICKET_FIRST_OVER_TOTAL_RUNS): false,
|
||||||
|
int64(CRICKET_TEAM_TOP_BATTER): false,
|
||||||
|
int64(CRICKET_TEAM_TOP_BOWLE): false,
|
||||||
|
int64(CRICKET_PLAYER_OF_THE_MATCH): false,
|
||||||
|
int64(CRICKET_FIRST_WICKET_METHOD): false,
|
||||||
|
int64(CRICKET_TOP_MATCH_BATTER): false,
|
||||||
|
int64(CRICKET_TOP_MATCH_BOWLER): false,
|
||||||
|
|
||||||
|
// Volleyball Markets
|
||||||
|
int64(VOLLEYBALL_GAME_LINES): true,
|
||||||
|
int64(VOLLEYBALL_CORRECT_SET_SCORE): true,
|
||||||
|
int64(VOLLEYBALL_MATCH_TOTAL_ODD_EVEN): true,
|
||||||
|
|
||||||
|
int64(VOLLEYBALL_SET_ONE_LINES): false,
|
||||||
|
int64(VOLLEYBALL_SET_ONE_TO_GO_TO_EXTRA_POINTS): false,
|
||||||
|
int64(VOLLEYBALL_SET_ONE_TOTAL_ODD_EVEN): false,
|
||||||
|
|
||||||
|
// Darts Markets
|
||||||
|
int64(DARTS_MATCH_WINNER): true,
|
||||||
|
int64(DARTS_TOTAL_LEGS): true,
|
||||||
|
int64(DARTS_CORRECT_LEG_SCORE): false,
|
||||||
|
int64(DARTS_MATCH_DOUBLE): false,
|
||||||
|
int64(DARTS_MATCH_TREBLE): false,
|
||||||
|
|
||||||
|
int64(DARTS_MOST_HUNDERED_EIGHTYS): false,
|
||||||
|
int64(DARTS_TOTAL_HUNDERED_EIGHTYS): false,
|
||||||
|
int64(DARTS_MOST_HUNDERED_EIGHTYS_HANDICAP): false,
|
||||||
|
int64(DARTS_PLAYER_HUNDERED_EIGHTYS): false,
|
||||||
|
int64(DARTS_FIRST_DART): false,
|
||||||
|
|
||||||
|
// Futsal Markets
|
||||||
|
int64(FUTSAL_MONEY_LINE): true,
|
||||||
|
int64(FUTSAL_GAME_LINES): true,
|
||||||
|
int64(FUTSAL_TEAM_TO_SCORE_FIRST): true,
|
||||||
|
|
||||||
|
int64(FUTSAL_DOUBLE_RESULT_9_WAY): false,
|
||||||
|
int64(FUTSAL_RACE_TO_GOALS): false,
|
||||||
|
|
||||||
// American Football Markets
|
// American Football Markets
|
||||||
int64(AMERICAN_FOOTBALL_MONEY_LINE): true,
|
int64(AMERICAN_FOOTBALL_MONEY_LINE): true,
|
||||||
int64(AMERICAN_FOOTBALL_SPREAD): true,
|
int64(AMERICAN_FOOTBALL_SPREAD): true,
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ func (s *Store) SaveEvent(ctx context.Context, e domain.Event) error {
|
||||||
MatchPeriod: pgtype.Int4{Int32: int32(e.MatchPeriod), Valid: true},
|
MatchPeriod: pgtype.Int4{Int32: int32(e.MatchPeriod), Valid: true},
|
||||||
IsLive: pgtype.Bool{Bool: e.IsLive, Valid: true},
|
IsLive: pgtype.Bool{Bool: e.IsLive, Valid: true},
|
||||||
Status: pgtype.Text{String: e.Status, Valid: true},
|
Status: pgtype.Text{String: e.Status, Valid: true},
|
||||||
|
Source: pgtype.Text{String: e.Source, Valid: true},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
func (s *Store) SaveUpcomingEvent(ctx context.Context, e domain.UpcomingEvent) error {
|
func (s *Store) SaveUpcomingEvent(ctx context.Context, e domain.UpcomingEvent) error {
|
||||||
|
|
@ -57,6 +58,7 @@ func (s *Store) SaveUpcomingEvent(ctx context.Context, e domain.UpcomingEvent) e
|
||||||
LeagueName: pgtype.Text{String: e.LeagueName, Valid: true},
|
LeagueName: pgtype.Text{String: e.LeagueName, Valid: true},
|
||||||
LeagueCc: pgtype.Text{String: e.LeagueCC, Valid: true},
|
LeagueCc: pgtype.Text{String: e.LeagueCC, Valid: true},
|
||||||
StartTime: pgtype.Timestamp{Time: e.StartTime, Valid: true},
|
StartTime: pgtype.Timestamp{Time: e.StartTime, Valid: true},
|
||||||
|
Source: pgtype.Text{String: e.Source, Valid: true},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,6 +87,7 @@ func (s *Store) GetAllUpcomingEvents(ctx context.Context) ([]domain.UpcomingEven
|
||||||
LeagueName: e.LeagueName.String,
|
LeagueName: e.LeagueName.String,
|
||||||
LeagueCC: e.LeagueCc.String,
|
LeagueCC: e.LeagueCc.String,
|
||||||
StartTime: e.StartTime.Time.UTC(),
|
StartTime: e.StartTime.Time.UTC(),
|
||||||
|
Source: e.Source.String,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return upcomingEvents, nil
|
return upcomingEvents, nil
|
||||||
|
|
@ -112,6 +115,7 @@ func (s *Store) GetExpiredUpcomingEvents(ctx context.Context) ([]domain.Upcoming
|
||||||
LeagueName: e.LeagueName.String,
|
LeagueName: e.LeagueName.String,
|
||||||
LeagueCC: e.LeagueCc.String,
|
LeagueCC: e.LeagueCc.String,
|
||||||
StartTime: e.StartTime.Time.UTC(),
|
StartTime: e.StartTime.Time.UTC(),
|
||||||
|
Source: e.Source.String,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return upcomingEvents, nil
|
return upcomingEvents, nil
|
||||||
|
|
@ -165,6 +169,7 @@ func (s *Store) GetPaginatedUpcomingEvents(ctx context.Context, limit domain.Val
|
||||||
LeagueName: e.LeagueName.String,
|
LeagueName: e.LeagueName.String,
|
||||||
LeagueCC: e.LeagueCc.String,
|
LeagueCC: e.LeagueCc.String,
|
||||||
StartTime: e.StartTime.Time.UTC(),
|
StartTime: e.StartTime.Time.UTC(),
|
||||||
|
Source: e.Source.String,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalCount, err := s.queries.GetTotalEvents(ctx, dbgen.GetTotalEventsParams{
|
totalCount, err := s.queries.GetTotalEvents(ctx, dbgen.GetTotalEventsParams{
|
||||||
|
|
@ -212,6 +217,7 @@ func (s *Store) GetUpcomingEventByID(ctx context.Context, ID string) (domain.Upc
|
||||||
LeagueName: event.LeagueName.String,
|
LeagueName: event.LeagueName.String,
|
||||||
LeagueCC: event.LeagueCc.String,
|
LeagueCC: event.LeagueCc.String,
|
||||||
StartTime: event.StartTime.Time.UTC(),
|
StartTime: event.StartTime.Time.UTC(),
|
||||||
|
Source: event.Source.String,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
func (s *Store) UpdateFinalScore(ctx context.Context, eventID, fullScore, status string) error {
|
func (s *Store) UpdateFinalScore(ctx context.Context, eventID, fullScore, status string) error {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,30 @@ func New(token string, store *repository.Store) Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) FetchLiveEvents(ctx context.Context) error {
|
func (s *service) FetchLiveEvents(ctx context.Context) error {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
urls := []struct {
|
||||||
|
name string
|
||||||
|
source string
|
||||||
|
}{
|
||||||
|
{"https://api.b365api.com/v1/bet365/inplay?sport_id=%d&token=%s", "bet365"},
|
||||||
|
{"https://api.b365api.com/v1/betfair/sb/inplay?sport_id=%d&token=%s", "betfair"},
|
||||||
|
{"https://api.b365api.com/v1/1xbet/inplay?sport_id=%d&token=%s", "1xbet"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, url := range urls {
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
s.fetchLiveEvents(ctx, url.name, url.source)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) fetchLiveEvents(ctx context.Context, url, source string) error {
|
||||||
sportIDs := []int{1, 13, 78, 18, 91, 16, 17, 14, 12, 3, 2, 4, 83, 15, 92, 94, 8, 19, 36, 66, 9, 75, 90, 95, 110, 107, 151, 162, 148}
|
sportIDs := []int{1, 13, 78, 18, 91, 16, 17, 14, 12, 3, 2, 4, 83, 15, 92, 94, 8, 19, 36, 66, 9, 75, 90, 95, 110, 107, 151, 162, 148}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
@ -39,7 +63,7 @@ func (s *service) FetchLiveEvents(ctx context.Context) error {
|
||||||
go func(sportID int) {
|
go func(sportID int) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
url := fmt.Sprintf("https://api.b365api.com/v1/bet365/inplay?sport_id=%d&token=%s", sportID, s.token)
|
url := fmt.Sprintf(url, sportID, s.token)
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf(" Failed request for sport_id=%d: %v\n", sportID, err)
|
fmt.Printf(" Failed request for sport_id=%d: %v\n", sportID, err)
|
||||||
|
|
@ -49,13 +73,41 @@ func (s *service) FetchLiveEvents(ctx context.Context) error {
|
||||||
|
|
||||||
body, _ := io.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
events := []domain.Event{}
|
||||||
|
switch source {
|
||||||
|
case "bet365":
|
||||||
|
events = handleBet365prematch(body, sportID)
|
||||||
|
case "betfair":
|
||||||
|
events = handleBetfairprematch(body, sportID, source)
|
||||||
|
case "1xbet":
|
||||||
|
// betfair and 1xbet have the same result structure
|
||||||
|
events = handleBetfairprematch(body, sportID, source)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, event := range events {
|
||||||
|
if err := s.store.SaveEvent(ctx, event); err != nil {
|
||||||
|
fmt.Printf("Could not store live event [id=%s]: %v\n", event.ID, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(sportID)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
fmt.Println("All live events fetched and stored.")
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleBet365prematch(body []byte, sportID int) []domain.Event {
|
||||||
var data struct {
|
var data struct {
|
||||||
Success int `json:"success"`
|
Success int `json:"success"`
|
||||||
Results [][]map[string]interface{} `json:"results"`
|
Results [][]map[string]interface{} `json:"results"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
events := []domain.Event{}
|
||||||
if err := json.Unmarshal(body, &data); err != nil || data.Success != 1 {
|
if err := json.Unmarshal(body, &data); err != nil || data.Success != 1 {
|
||||||
fmt.Printf(" Decode failed for sport_id=%d\nRaw: %s\n", sportID, string(body))
|
fmt.Printf(" Decode failed for sport_id=%d\nRaw: %s\n", sportID, string(body))
|
||||||
return
|
return events
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, group := range data.Results {
|
for _, group := range data.Results {
|
||||||
|
|
@ -83,33 +135,88 @@ func (s *service) FetchLiveEvents(ctx context.Context) error {
|
||||||
Status: "live",
|
Status: "live",
|
||||||
MatchPeriod: getInt(ev["MD"]),
|
MatchPeriod: getInt(ev["MD"]),
|
||||||
AddedTime: getInt(ev["TA"]),
|
AddedTime: getInt(ev["TA"]),
|
||||||
|
Source: "bet365",
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.store.SaveEvent(ctx, event); err != nil {
|
events = append(events, event)
|
||||||
fmt.Printf("Could not store live event [id=%s]: %v\n", event.ID, err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}(sportID)
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Wait()
|
return events
|
||||||
fmt.Println("All live events fetched and stored.")
|
}
|
||||||
return nil
|
|
||||||
|
func handleBetfairprematch(body []byte, sportID int, source string) []domain.Event {
|
||||||
|
var data struct {
|
||||||
|
Success int `json:"success"`
|
||||||
|
Results []map[string]interface{} `json:"results"`
|
||||||
|
}
|
||||||
|
|
||||||
|
events := []domain.Event{}
|
||||||
|
if err := json.Unmarshal(body, &data); err != nil || data.Success != 1 {
|
||||||
|
fmt.Printf(" Decode failed for sport_id=%d\nRaw: %s\n", sportID, string(body))
|
||||||
|
return events
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ev := range data.Results {
|
||||||
|
homeRaw, _ := ev["home"].(map[string]interface{})
|
||||||
|
homeId, _ := homeRaw["id"].(string)
|
||||||
|
|
||||||
|
awayRaw, _ := ev["home"].(map[string]interface{})
|
||||||
|
awayId, _ := awayRaw["id"].(string)
|
||||||
|
|
||||||
|
event := domain.Event{
|
||||||
|
ID: getString(ev["id"]),
|
||||||
|
SportID: fmt.Sprintf("%d", sportID),
|
||||||
|
TimerStatus: getString(ev["time_status"]),
|
||||||
|
HomeTeamID: homeId,
|
||||||
|
AwayTeamID: awayId,
|
||||||
|
StartTime: time.Now().UTC().Format(time.RFC3339),
|
||||||
|
IsLive: true,
|
||||||
|
Status: "live",
|
||||||
|
Source: source,
|
||||||
|
}
|
||||||
|
|
||||||
|
events = append(events, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
return events
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) FetchUpcomingEvents(ctx context.Context) error {
|
func (s *service) FetchUpcomingEvents(ctx context.Context) error {
|
||||||
sportIDs := []int{1, 18, 17}
|
var wg sync.WaitGroup
|
||||||
|
urls := []struct {
|
||||||
|
name string
|
||||||
|
source string
|
||||||
|
}{
|
||||||
|
{"https://api.b365api.com/v1/bet365/upcoming?sport_id=%d&token=%s&page=%d", "bet365"},
|
||||||
|
{"https://api.b365api.com/v1/betfair/sb/upcoming?sport_id=%d&token=%s&page=%d", "betfair"},
|
||||||
|
{"https://api.b365api.com/v1/1xbet/upcoming?sport_id=%d&token=%s&page=%d", "1xbet"},
|
||||||
|
}
|
||||||
|
|
||||||
for _, sportID := range sportIDs {
|
for _, url := range urls {
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
s.fetchUpcomingEventsFromProvider(ctx, url.name, url.source)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) fetchUpcomingEventsFromProvider(ctx context.Context, url, source string) {
|
||||||
|
sportIDs := []int{1, 18, 17}
|
||||||
var totalPages int = 1
|
var totalPages int = 1
|
||||||
var page int = 0
|
var page int = 0
|
||||||
var limit int = 150
|
var limit int = 100
|
||||||
var count int = 0
|
var count int = 0
|
||||||
|
for _, sportID := range sportIDs {
|
||||||
for page <= totalPages {
|
for page <= totalPages {
|
||||||
page = page + 1
|
page = page + 1
|
||||||
url := fmt.Sprintf("https://api.b365api.com/v1/bet365/upcoming?sport_id=%d&token=%s&page=%d", sportID, s.token, page)
|
url := fmt.Sprintf("https://api.b365api.com/v1/bet365/upcoming?sport_id=%d&token=%s&page=%d", sportID, s.token, page)
|
||||||
log.Printf("📡 Fetching data for sport %d event data page %d/%d", sportID, page, min(limit, totalPages))
|
log.Printf("📡 Fetching data for event data page %d", page)
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("❌ Failed to fetch event data for page %d: %v", page, err)
|
log.Printf("❌ Failed to fetch event data for page %d: %v", page, err)
|
||||||
|
|
@ -118,31 +225,8 @@ func (s *service) FetchUpcomingEvents(ctx context.Context) error {
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, _ := io.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
var data struct {
|
var data domain.BetResult
|
||||||
Success int `json:"success"`
|
|
||||||
Pager struct {
|
|
||||||
Page int `json:"page"`
|
|
||||||
PerPage int `json:"per_page"`
|
|
||||||
Total int `json:"total"`
|
|
||||||
}
|
|
||||||
Results []struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
SportID string `json:"sport_id"`
|
|
||||||
Time string `json:"time"`
|
|
||||||
League struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
} `json:"league"`
|
|
||||||
Home struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
} `json:"home"`
|
|
||||||
Away *struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
} `json:"away"`
|
|
||||||
} `json:"results"`
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(body, &data); err != nil || data.Success != 1 {
|
if err := json.Unmarshal(body, &data); err != nil || data.Success != 1 {
|
||||||
log.Printf("❌ Failed to parse json data")
|
log.Printf("❌ Failed to parse json data")
|
||||||
continue
|
continue
|
||||||
|
|
@ -182,6 +266,7 @@ func (s *service) FetchUpcomingEvents(ctx context.Context) error {
|
||||||
LeagueName: ev.League.Name,
|
LeagueName: ev.League.Name,
|
||||||
LeagueCC: "",
|
LeagueCC: "",
|
||||||
StartTime: time.Unix(startUnix, 0).UTC(),
|
StartTime: time.Unix(startUnix, 0).UTC(),
|
||||||
|
Source: source,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ev.Away != nil {
|
if ev.Away != nil {
|
||||||
|
|
@ -209,8 +294,6 @@ func (s *service) FetchUpcomingEvents(ctx context.Context) error {
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getString(v interface{}) string {
|
func getString(v interface{}) string {
|
||||||
|
|
|
||||||
|
|
@ -182,32 +182,33 @@ func evaluateAsianHandicap(outcome domain.BetOutcome, score struct{ Home, Away i
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return domain.OUTCOME_STATUS_ERROR, err
|
return domain.OUTCOME_STATUS_ERROR, err
|
||||||
}
|
}
|
||||||
continue
|
} else {
|
||||||
}
|
|
||||||
newOutcome, err = checkMultiOutcome(newOutcome, domain.OUTCOME_STATUS_LOSS)
|
newOutcome, err = checkMultiOutcome(newOutcome, domain.OUTCOME_STATUS_LOSS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return domain.OUTCOME_STATUS_ERROR, err
|
fmt.Printf("multi outcome check error")
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
continue
|
|
||||||
} else if adjustedHomeScore < adjustedAwayScore {
|
} else if adjustedHomeScore < adjustedAwayScore {
|
||||||
if outcome.OddHeader == "2" {
|
if outcome.OddHeader == "2" {
|
||||||
newOutcome, err = checkMultiOutcome(newOutcome, domain.OUTCOME_STATUS_WIN)
|
newOutcome, err = checkMultiOutcome(newOutcome, domain.OUTCOME_STATUS_WIN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return domain.OUTCOME_STATUS_ERROR, err
|
return domain.OUTCOME_STATUS_ERROR, err
|
||||||
}
|
}
|
||||||
continue
|
} else {
|
||||||
}
|
|
||||||
newOutcome, err = checkMultiOutcome(newOutcome, domain.OUTCOME_STATUS_LOSS)
|
newOutcome, err = checkMultiOutcome(newOutcome, domain.OUTCOME_STATUS_LOSS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return domain.OUTCOME_STATUS_ERROR, err
|
fmt.Printf("multi outcome check error")
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, err
|
||||||
}
|
}
|
||||||
continue
|
}
|
||||||
} else if adjustedHomeScore == adjustedAwayScore {
|
}
|
||||||
|
if newOutcome == domain.OUTCOME_STATUS_PENDING {
|
||||||
newOutcome, err = checkMultiOutcome(newOutcome, domain.OUTCOME_STATUS_VOID)
|
newOutcome, err = checkMultiOutcome(newOutcome, domain.OUTCOME_STATUS_VOID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return domain.OUTCOME_STATUS_ERROR, err
|
fmt.Printf("multi outcome check error")
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, err
|
||||||
}
|
}
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newOutcome, nil
|
return newOutcome, nil
|
||||||
|
|
@ -498,9 +499,33 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid odd header: %s", outcome.OddHeader)
|
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid odd header: %s", outcome.OddHeader)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result and Total betting is a type of bet where the bettor predicts
|
func evaluateTotalLegs(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
// the outcome of a match and whether the total number of points scored will be over or under a specified number.
|
total, err := strconv.ParseFloat(outcome.OddName, 64)
|
||||||
func evaluateResultAndTotal(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
if err != nil {
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid : %s", outcome.OddName)
|
||||||
|
}
|
||||||
|
|
||||||
|
totalLegs := float64(score.Home + score.Away)
|
||||||
|
|
||||||
|
switch outcome.OddHeader {
|
||||||
|
case "Over":
|
||||||
|
if totalLegs > total {
|
||||||
|
return domain.OUTCOME_STATUS_WIN, nil
|
||||||
|
}
|
||||||
|
return domain.OUTCOME_STATUS_LOSS, nil
|
||||||
|
case "Under":
|
||||||
|
if totalLegs < total {
|
||||||
|
return domain.OUTCOME_STATUS_WIN, nil
|
||||||
|
}
|
||||||
|
return domain.OUTCOME_STATUS_LOSS, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid odd header: %s", outcome.OddHeader)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Result and Total betting is a type of bet where the bettor predicts
|
||||||
|
// the outcome of a match and whether the total number of points scored will be over or under a specified number.
|
||||||
|
func evaluateResultAndTotal(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
|
|
||||||
// The handicap will be in the format "U {float}" or "O {float}"
|
// The handicap will be in the format "U {float}" or "O {float}"
|
||||||
// U and O denoting over and under for this case
|
// U and O denoting over and under for this case
|
||||||
|
|
@ -548,11 +573,11 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
default:
|
default:
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("failed to parse over and under: %s", outcome.OddName)
|
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("failed to parse over and under: %s", outcome.OddName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Team Total betting is a type of bet where the bettor predicts the total number of points scored by a specific team in a match
|
// Team Total betting is a type of bet where the bettor predicts the total number of points scored by a specific team in a match
|
||||||
// is over or under a specified number.
|
// is over or under a specified number.
|
||||||
func evaluateTeamTotal(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
func evaluateTeamTotal(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
|
|
||||||
// The handicap will be in the format "U {float}" or "O {float}"
|
// The handicap will be in the format "U {float}" or "O {float}"
|
||||||
// U and O denoting over and under for this case
|
// U and O denoting over and under for this case
|
||||||
|
|
@ -594,11 +619,11 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
default:
|
default:
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("failed to parse over and under: %s", outcome.OddName)
|
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("failed to parse over and under: %s", outcome.OddName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result and Both Teams To Score X Points is a type of bet where the bettor predicts whether both teams will score a certain number of points
|
// Result and Both Teams To Score X Points is a type of bet where the bettor predicts whether both teams will score a certain number of points
|
||||||
// and also the result fo the match
|
// and also the result fo the match
|
||||||
func evaluateResultAndBTTSX(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
func evaluateResultAndBTTSX(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
|
|
||||||
// The name parameter will hold value "name": "{team_name} and {Yes | No}"
|
// The name parameter will hold value "name": "{team_name} and {Yes | No}"
|
||||||
// The best way to do this is to evaluate backwards since there might be
|
// The best way to do this is to evaluate backwards since there might be
|
||||||
|
|
@ -623,6 +648,10 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid threshold: %s", outcome.OddHeader)
|
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid threshold: %s", outcome.OddHeader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// above code removes any space from team name, so do the same for outcome.HomeTeamName and outcome.AwayTeamName
|
||||||
|
outcome.HomeTeamName = strings.Join(strings.Split(outcome.HomeTeamName, " "), "")
|
||||||
|
outcome.AwayTeamName = strings.Join(strings.Split(outcome.AwayTeamName, " "), "")
|
||||||
|
|
||||||
switch teamName {
|
switch teamName {
|
||||||
case outcome.HomeTeamName:
|
case outcome.HomeTeamName:
|
||||||
if score.Home > score.Away {
|
if score.Home > score.Away {
|
||||||
|
|
@ -646,10 +675,10 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
|
|
||||||
return domain.OUTCOME_STATUS_LOSS, nil
|
return domain.OUTCOME_STATUS_LOSS, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Both Teams To Score X Points is a type of bet where the bettor predicts whether both teams will score a certain number of points.
|
// Both Teams To Score X Points is a type of bet where the bettor predicts whether both teams will score a certain number of points.
|
||||||
func evaluateBTTSX(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
func evaluateBTTSX(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
threshold, err := strconv.ParseInt(outcome.OddName, 10, 64)
|
threshold, err := strconv.ParseInt(outcome.OddName, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid threshold: %s", outcome.OddName)
|
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid threshold: %s", outcome.OddName)
|
||||||
|
|
@ -670,10 +699,10 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
}
|
}
|
||||||
|
|
||||||
return domain.OUTCOME_STATUS_LOSS, nil
|
return domain.OUTCOME_STATUS_LOSS, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Money Line 3 Way betting is a type of bet where the bettor predicts the outcome of a match with three possible outcomes: home win, away win, or draw.
|
// Money Line 3 Way betting is a type of bet where the bettor predicts the outcome of a match with three possible outcomes: home win, away win, or draw.
|
||||||
func evaluateMoneyLine3Way(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
func evaluateMoneyLine3Way(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
switch outcome.OddName {
|
switch outcome.OddName {
|
||||||
case "1": // Home win
|
case "1": // Home win
|
||||||
if score.Home > score.Away {
|
if score.Home > score.Away {
|
||||||
|
|
@ -693,22 +722,21 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
default:
|
default:
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid odd name: %s", outcome.OddName)
|
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid odd name: %s", outcome.OddName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Double Result betting is a type of bet where the bettor predicts the outcome of a match at both half-time and full-time.
|
func evaluateDoubleResult(outcome domain.BetOutcome, firstHalfScore struct{ Home, Away int }, fullTimeScore struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
func evaluateDoubleResult(outcome domain.BetOutcome, firstHalfScore struct{ Home, Away int }, secondHalfScore struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
|
||||||
halfWins := strings.Split(outcome.OddName, "-")
|
halfWins := strings.Split(outcome.OddName, "-")
|
||||||
if len(halfWins) != 2 {
|
if len(halfWins) != 2 {
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid odd name: %s", outcome.OddName)
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid odd name: %s", outcome.OddName)
|
||||||
}
|
}
|
||||||
firstHalfWinner := strings.TrimSpace(halfWins[0])
|
firstHalfWinner := strings.TrimSpace(halfWins[0])
|
||||||
secondHalfWinner := strings.TrimSpace(halfWins[1])
|
fullTimeWinner := strings.TrimSpace(halfWins[1])
|
||||||
|
|
||||||
if firstHalfWinner != outcome.HomeTeamName && firstHalfWinner != outcome.AwayTeamName && firstHalfWinner != "Tie" {
|
if firstHalfWinner != outcome.HomeTeamName && firstHalfWinner != outcome.AwayTeamName && firstHalfWinner != "Tie" {
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddname: %s", firstHalfWinner)
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid oddname: %s", firstHalfWinner)
|
||||||
}
|
}
|
||||||
if secondHalfWinner != outcome.HomeTeamName && secondHalfWinner != outcome.AwayTeamName && secondHalfWinner != "Tie" {
|
if fullTimeWinner != outcome.HomeTeamName && fullTimeWinner != outcome.AwayTeamName && fullTimeWinner != "Tie" {
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddname: %s", firstHalfWinner)
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid oddname: %s", firstHalfWinner)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
|
@ -721,19 +749,19 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case secondHalfWinner == outcome.HomeTeamName && firstHalfScore.Home < firstHalfScore.Away:
|
case fullTimeWinner == outcome.HomeTeamName && fullTimeScore.Home < fullTimeScore.Away:
|
||||||
return domain.OUTCOME_STATUS_LOSS, nil
|
return domain.OUTCOME_STATUS_LOSS, nil
|
||||||
case secondHalfWinner == outcome.AwayTeamName && firstHalfScore.Away < firstHalfScore.Home:
|
case fullTimeWinner == outcome.AwayTeamName && fullTimeScore.Away < fullTimeScore.Home:
|
||||||
return domain.OUTCOME_STATUS_LOSS, nil
|
return domain.OUTCOME_STATUS_LOSS, nil
|
||||||
case secondHalfWinner == "Tie" && firstHalfScore.Home != firstHalfScore.Away:
|
case fullTimeWinner == "Tie" && fullTimeScore.Home != fullTimeScore.Away:
|
||||||
return domain.OUTCOME_STATUS_LOSS, nil
|
return domain.OUTCOME_STATUS_LOSS, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return domain.OUTCOME_STATUS_WIN, nil
|
return domain.OUTCOME_STATUS_WIN, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Highest Scoring Half betting is a type of bet where the bettor predicts which half of the match will have the highest total score.
|
// Highest Scoring Half betting is a type of bet where the bettor predicts which half of the match will have the highest total score.
|
||||||
func evaluateHighestScoringHalf(outcome domain.BetOutcome, firstScore struct{ Home, Away int }, secondScore struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
func evaluateHighestScoringHalf(outcome domain.BetOutcome, firstScore struct{ Home, Away int }, secondScore struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
firstHalfTotal := firstScore.Home + firstScore.Away
|
firstHalfTotal := firstScore.Home + firstScore.Away
|
||||||
secondHalfTotal := secondScore.Home + secondScore.Away
|
secondHalfTotal := secondScore.Home + secondScore.Away
|
||||||
switch outcome.OddName {
|
switch outcome.OddName {
|
||||||
|
|
@ -753,10 +781,10 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
||||||
}
|
}
|
||||||
return domain.OUTCOME_STATUS_LOSS, nil
|
return domain.OUTCOME_STATUS_LOSS, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Highest Scoring Quarter betting is a type of bet where the bettor predicts which quarter of the match will have the highest score.
|
// Highest Scoring Quarter betting is a type of bet where the bettor predicts which quarter of the match will have the highest score.
|
||||||
func evaluateHighestScoringQuarter(outcome domain.BetOutcome, firstScore struct{ Home, Away int }, secondScore struct{ Home, Away int }, thirdScore struct{ Home, Away int }, fourthScore struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
func evaluateHighestScoringQuarter(outcome domain.BetOutcome, firstScore struct{ Home, Away int }, secondScore struct{ Home, Away int }, thirdScore struct{ Home, Away int }, fourthScore struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
firstQuarterTotal := firstScore.Home + firstScore.Away
|
firstQuarterTotal := firstScore.Home + firstScore.Away
|
||||||
secondQuarterTotal := secondScore.Home + secondScore.Away
|
secondQuarterTotal := secondScore.Home + secondScore.Away
|
||||||
thirdQuarterTotal := thirdScore.Home + thirdScore.Away
|
thirdQuarterTotal := thirdScore.Home + thirdScore.Away
|
||||||
|
|
@ -787,10 +815,10 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
||||||
}
|
}
|
||||||
return domain.OUTCOME_STATUS_LOSS, nil
|
return domain.OUTCOME_STATUS_LOSS, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Team With Highest Scoring Quarter betting is a type of bet where the bettor predicts which team will have the highest score in a specific quarter.
|
// Team With Highest Scoring Quarter betting is a type of bet where the bettor predicts which team will have the highest score in a specific quarter.
|
||||||
func evaluateTeamWithHighestScoringQuarter(outcome domain.BetOutcome, firstScore struct{ Home, Away int }, secondScore struct{ Home, Away int }, thirdScore struct{ Home, Away int }, fourthScore struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
func evaluateTeamWithHighestScoringQuarter(outcome domain.BetOutcome, firstScore struct{ Home, Away int }, secondScore struct{ Home, Away int }, thirdScore struct{ Home, Away int }, fourthScore struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
homeTeamHighestQuarter := max(firstScore.Home, secondScore.Home, thirdScore.Home, fourthScore.Home)
|
homeTeamHighestQuarter := max(firstScore.Home, secondScore.Home, thirdScore.Home, fourthScore.Home)
|
||||||
awayTeamHighestQuarter := max(firstScore.Away, secondScore.Away, thirdScore.Away, fourthScore.Away)
|
awayTeamHighestQuarter := max(firstScore.Away, secondScore.Away, thirdScore.Away, fourthScore.Away)
|
||||||
|
|
||||||
|
|
@ -811,11 +839,11 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
||||||
}
|
}
|
||||||
return domain.OUTCOME_STATUS_LOSS, nil
|
return domain.OUTCOME_STATUS_LOSS, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handicap and Total betting is a combination of spread betting and total points betting
|
// Handicap and Total betting is a combination of spread betting and total points betting
|
||||||
// where the bettor predicts the outcome of a match with a point spread and the total number of points scored is over or under a specified number.
|
// where the bettor predicts the outcome of a match with a point spread and the total number of points scored is over or under a specified number.
|
||||||
func evaluateHandicapAndTotal(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
func evaluateHandicapAndTotal(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
|
|
||||||
nameSplit := strings.Split(outcome.OddName, " ")
|
nameSplit := strings.Split(outcome.OddName, " ")
|
||||||
// Evaluate from bottom to get the threshold and find out if its over or under
|
// Evaluate from bottom to get the threshold and find out if its over or under
|
||||||
|
|
@ -843,10 +871,12 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
}
|
}
|
||||||
|
|
||||||
teamName := strings.TrimSpace(strings.Join(nameSplit[:len(nameSplit)-4], ""))
|
teamName := strings.TrimSpace(strings.Join(nameSplit[:len(nameSplit)-4], ""))
|
||||||
|
|
||||||
adjustedHomeScore := float64(score.Home)
|
adjustedHomeScore := float64(score.Home)
|
||||||
adjustedAwayScore := float64(score.Away)
|
adjustedAwayScore := float64(score.Away)
|
||||||
|
|
||||||
|
outcome.HomeTeamName = strings.Join(strings.Split(outcome.HomeTeamName, " "), "")
|
||||||
|
outcome.AwayTeamName = strings.Join(strings.Split(outcome.AwayTeamName, " "), "")
|
||||||
|
|
||||||
switch teamName {
|
switch teamName {
|
||||||
case outcome.HomeTeamName:
|
case outcome.HomeTeamName:
|
||||||
adjustedHomeScore += handicap
|
adjustedHomeScore += handicap
|
||||||
|
|
@ -864,25 +894,25 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("failed parsing team name: %s", outcome.OddName)
|
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("failed parsing team name: %s", outcome.OddName)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Winning Margin betting is a type of bet where the bettor predicts the margin of victory in a match.
|
func evaluateWinningMargin(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
func evaluateWinningMargin(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
if len(outcome.OddName) < 1 {
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
||||||
marginSplit := strings.Split(outcome.OddName, "")
|
|
||||||
if len(marginSplit) < 1 {
|
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
|
||||||
}
|
|
||||||
|
|
||||||
margin, err := strconv.ParseInt(marginSplit[0], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isGtr := false
|
isGtr := false
|
||||||
if len(marginSplit) == 2 {
|
idx := len(outcome.OddName)
|
||||||
isGtr = marginSplit[1] == "+"
|
if outcome.OddName[idx-1] == '+' {
|
||||||
|
isGtr = true
|
||||||
|
idx--
|
||||||
}
|
}
|
||||||
|
|
||||||
|
margin, err := strconv.ParseInt(outcome.OddName[:idx], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
||||||
|
}
|
||||||
|
|
||||||
switch outcome.OddHeader {
|
switch outcome.OddHeader {
|
||||||
case "1":
|
case "1":
|
||||||
if score.Home == (score.Away + int(margin)) {
|
if score.Home == (score.Away + int(margin)) {
|
||||||
|
|
@ -892,19 +922,19 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
}
|
}
|
||||||
return domain.OUTCOME_STATUS_LOSS, nil
|
return domain.OUTCOME_STATUS_LOSS, nil
|
||||||
case "2":
|
case "2":
|
||||||
if (score.Home + int(margin)) == score.Away {
|
if score.Away == (score.Home + int(margin)) {
|
||||||
return domain.OUTCOME_STATUS_WIN, nil
|
return domain.OUTCOME_STATUS_WIN, nil
|
||||||
} else if isGtr && (score.Home+int(margin)) > score.Away {
|
} else if isGtr && score.Away > (score.Home+int(margin)) {
|
||||||
return domain.OUTCOME_STATUS_WIN, nil
|
return domain.OUTCOME_STATUS_WIN, nil
|
||||||
}
|
}
|
||||||
return domain.OUTCOME_STATUS_LOSS, nil
|
return domain.OUTCOME_STATUS_LOSS, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddheader: %s", outcome.OddHeader)
|
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddheader: %s", outcome.OddHeader)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Highest Scoring Period betting is a type of bet where the bettor predicts which period of the match will have the highest total score.
|
// Highest Scoring Period betting is a type of bet where the bettor predicts which period of the match will have the highest total score.
|
||||||
func evaluateHighestScoringPeriod(outcome domain.BetOutcome, firstScore struct{ Home, Away int }, secondScore struct{ Home, Away int }, thirdScore struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
func evaluateHighestScoringPeriod(outcome domain.BetOutcome, firstScore struct{ Home, Away int }, secondScore struct{ Home, Away int }, thirdScore struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
firstPeriodTotal := firstScore.Home + firstScore.Away
|
firstPeriodTotal := firstScore.Home + firstScore.Away
|
||||||
secondPeriodTotal := secondScore.Home + secondScore.Away
|
secondPeriodTotal := secondScore.Home + secondScore.Away
|
||||||
thirdPeriodTotal := thirdScore.Home + thirdScore.Away
|
thirdPeriodTotal := thirdScore.Home + thirdScore.Away
|
||||||
|
|
@ -930,10 +960,10 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
||||||
}
|
}
|
||||||
return domain.OUTCOME_STATUS_LOSS, nil
|
return domain.OUTCOME_STATUS_LOSS, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tied After Regulation is a type of bet where the bettor predicts whether the match will end in a tie after regulation time.
|
// Tied After Regulation is a type of bet where the bettor predicts whether the match will end in a tie after regulation time.
|
||||||
func evaluateTiedAfterRegulation(outcome domain.BetOutcome, scores []struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
func evaluateTiedAfterRegulation(outcome domain.BetOutcome, scores []struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
totalScore := struct{ Home, Away int }{0, 0}
|
totalScore := struct{ Home, Away int }{0, 0}
|
||||||
for _, score := range scores {
|
for _, score := range scores {
|
||||||
totalScore.Home += score.Home
|
totalScore.Home += score.Home
|
||||||
|
|
@ -952,11 +982,10 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
return domain.OUTCOME_STATUS_LOSS, nil
|
return domain.OUTCOME_STATUS_LOSS, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return domain.OUTCOME_STATUS_ERROR, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid oddname: %s", outcome.OddName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// evaluateRugbyOutcome evaluates the outcome of a Rugby bet
|
func evaluateRugbyOutcome(outcome domain.BetOutcome, result *domain.RugbyResultResponse) (domain.OutcomeStatus, error) {
|
||||||
func evaluateRugbyOutcome(outcome domain.BetOutcome, result *domain.RugbyResultResponse) (domain.OutcomeStatus, error) {
|
|
||||||
finalScore := parseSS(result.SS)
|
finalScore := parseSS(result.SS)
|
||||||
|
|
||||||
switch outcome.MarketName {
|
switch outcome.MarketName {
|
||||||
|
|
@ -969,10 +998,9 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
default:
|
default:
|
||||||
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported rugby market: %s", outcome.MarketName)
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported rugby market: %s", outcome.MarketName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// evaluateBaseballOutcome evaluates the outcome of a Baseball bet
|
func evaluateBaseballOutcome(outcome domain.BetOutcome, result *domain.BaseballResultResponse) (domain.OutcomeStatus, error) {
|
||||||
func evaluateBaseballOutcome(outcome domain.BetOutcome, result *domain.BaseballResultResponse) (domain.OutcomeStatus, error) {
|
|
||||||
finalScore := parseSS(result.SS)
|
finalScore := parseSS(result.SS)
|
||||||
|
|
||||||
switch outcome.MarketName {
|
switch outcome.MarketName {
|
||||||
|
|
@ -985,4 +1013,13 @@ func evaluateTotalOverUnder(outcome domain.BetOutcome, score struct{ Home, Away
|
||||||
default:
|
default:
|
||||||
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported baseball market: %s", outcome.MarketName)
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported baseball market: %s", outcome.MarketName)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func evaluateVolleyballGamelines(outcome domain.BetOutcome, score struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
|
switch outcome.OddName {
|
||||||
|
case "Total":
|
||||||
|
return evaluateTotalOverUnder(outcome, score)
|
||||||
|
default:
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("invalid odd name: %s", outcome.OddName)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,9 @@ func (s *Service) FetchAndProcessResults(ctx context.Context) error {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func (s *Service) fetchResult(ctx context.Context, eventID, oddID, marketID, sportID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
func (s *Service) fetchResult(ctx context.Context, eventID, oddID, marketID, sportID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
||||||
url := fmt.Sprintf("https://api.b365api.com/v1/bet365/result?token=%s&event_id=%d", s.config.Bet365Token, eventID)
|
// url := fmt.Sprintf("https://api.b365api.com/v1/bet365/result?token=%s&event_id=%d", s.config.Bet365Token, eventID)
|
||||||
|
url := fmt.Sprintf("https://api.b365api.com/v1/event/view?token=%s&event_id=%d", s.config.Bet365Token, eventID)
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Error("Failed to create request", "event_id", eventID, "error", err)
|
s.logger.Error("Failed to create request", "event_id", eventID, "error", err)
|
||||||
|
|
@ -261,18 +263,70 @@ func (s *Service) fetchResult(ctx context.Context, eventID, oddID, marketID, spo
|
||||||
switch sportID {
|
switch sportID {
|
||||||
case domain.FOOTBALL:
|
case domain.FOOTBALL:
|
||||||
result, err = s.parseFootball(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
result, err = s.parseFootball(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to parse football", "event id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
case domain.BASKETBALL:
|
case domain.BASKETBALL:
|
||||||
result, err = s.parseBasketball(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
result, err = s.parseBasketball(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to parse basketball", "event id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
case domain.ICE_HOCKEY:
|
case domain.ICE_HOCKEY:
|
||||||
result, err = s.parseIceHockey(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
result, err = s.parseIceHockey(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to parse ice hockey", "event id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
|
case domain.CRICKET:
|
||||||
|
result, err = s.parseCricket(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to parse cricket", "event id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
|
case domain.VOLLEYBALL:
|
||||||
|
result, err = s.parseVolleyball(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to parse volleyball", "event id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
|
case domain.DARTS:
|
||||||
|
result, err = s.parseDarts(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to parse darts", "event id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
|
case domain.FUTSAL:
|
||||||
|
result, err = s.parseFutsal(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to parse futsal", "event id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
case domain.AMERICAN_FOOTBALL:
|
case domain.AMERICAN_FOOTBALL:
|
||||||
result, err = s.parseNFL(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
result, err = s.parseNFL(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to parse american football", "event id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
case domain.RUGBY_UNION:
|
case domain.RUGBY_UNION:
|
||||||
result, err = s.parseRugbyUnion(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
result, err = s.parseRugbyUnion(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to parse rugby_union", "event id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
case domain.RUGBY_LEAGUE:
|
case domain.RUGBY_LEAGUE:
|
||||||
result, err = s.parseRugbyLeague(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
result, err = s.parseRugbyLeague(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to parse rugby_league", "event id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
case domain.BASEBALL:
|
case domain.BASEBALL:
|
||||||
result, err = s.parseBaseball(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
result, err = s.parseBaseball(resultResp.Results[0], eventID, oddID, marketID, outcome)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to parse baseball", "event id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
s.logger.Error("Unsupported sport", "sport", sportID)
|
s.logger.Error("Unsupported sport", "sport", sportID)
|
||||||
return domain.CreateResult{}, fmt.Errorf("unsupported sport: %v", sportID)
|
return domain.CreateResult{}, fmt.Errorf("unsupported sport: %v", sportID)
|
||||||
|
|
@ -352,6 +406,7 @@ func (s *Service) parseFootball(resultRes json.RawMessage, eventID, oddID, marke
|
||||||
|
|
||||||
func (s *Service) parseBasketball(response json.RawMessage, eventID, oddID, marketID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
func (s *Service) parseBasketball(response json.RawMessage, eventID, oddID, marketID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
||||||
var basketBallRes domain.BasketballResultResponse
|
var basketBallRes domain.BasketballResultResponse
|
||||||
|
|
||||||
if err := json.Unmarshal(response, &basketBallRes); err != nil {
|
if err := json.Unmarshal(response, &basketBallRes); err != nil {
|
||||||
s.logger.Error("Failed to unmarshal basketball result", "event_id", eventID, "error", err)
|
s.logger.Error("Failed to unmarshal basketball result", "event_id", eventID, "error", err)
|
||||||
return domain.CreateResult{}, err
|
return domain.CreateResult{}, err
|
||||||
|
|
@ -416,6 +471,121 @@ func (s *Service) parseIceHockey(response json.RawMessage, eventID, oddID, marke
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) parseCricket(response json.RawMessage, eventID, oddID, marketID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
||||||
|
var cricketRes domain.CricketResultResponse
|
||||||
|
|
||||||
|
if err := json.Unmarshal(response, &cricketRes); err != nil {
|
||||||
|
s.logger.Error("Failed to unmarshal football result", "event_id", eventID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
|
if cricketRes.TimeStatus != "3" {
|
||||||
|
s.logger.Warn("Match not yet completed", "event_id", eventID)
|
||||||
|
return domain.CreateResult{}, fmt.Errorf("match not yet completed")
|
||||||
|
}
|
||||||
|
|
||||||
|
status, err := s.evaluateCricketOutcome(outcome, cricketRes)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.CreateResult{
|
||||||
|
BetOutcomeID: 0,
|
||||||
|
EventID: eventID,
|
||||||
|
OddID: oddID,
|
||||||
|
MarketID: marketID,
|
||||||
|
Status: status,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) parseVolleyball(response json.RawMessage, eventID, oddID, marketID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
||||||
|
var volleyballRes domain.VolleyballResultResponse
|
||||||
|
|
||||||
|
if err := json.Unmarshal(response, &volleyballRes); err != nil {
|
||||||
|
s.logger.Error("Failed to unmarshal football result", "event_id", eventID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
|
if volleyballRes.TimeStatus != "3" {
|
||||||
|
s.logger.Warn("Match not yet completed", "event_id", eventID)
|
||||||
|
return domain.CreateResult{}, fmt.Errorf("match not yet completed")
|
||||||
|
}
|
||||||
|
|
||||||
|
status, err := s.evaluateVolleyballOutcome(outcome, volleyballRes)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.CreateResult{
|
||||||
|
BetOutcomeID: 0,
|
||||||
|
EventID: eventID,
|
||||||
|
OddID: oddID,
|
||||||
|
MarketID: marketID,
|
||||||
|
Status: status,
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) parseDarts(response json.RawMessage, eventID, oddID, marketID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
||||||
|
var dartsRes domain.DartsResultResponse
|
||||||
|
|
||||||
|
if err := json.Unmarshal(response, &dartsRes); err != nil {
|
||||||
|
s.logger.Error("Failed to unmarshal football result", "event_id", eventID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if dartsRes.TimeStatus != "3" {
|
||||||
|
s.logger.Warn("Match not yet completed", "event_id", eventID)
|
||||||
|
return domain.CreateResult{}, fmt.Errorf("match not yet completed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// result for dart is limited
|
||||||
|
// only ss is given, format with 2-4
|
||||||
|
status, err := s.evaluateDartsOutcome(outcome, dartsRes)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.CreateResult{
|
||||||
|
BetOutcomeID: 0,
|
||||||
|
EventID: eventID,
|
||||||
|
OddID: oddID,
|
||||||
|
MarketID: marketID,
|
||||||
|
Status: status,
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) parseFutsal(response json.RawMessage, eventID, oddID, marketID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
||||||
|
var futsalRes domain.FutsalResultResponse
|
||||||
|
|
||||||
|
if err := json.Unmarshal(response, &futsalRes); err != nil {
|
||||||
|
s.logger.Error("Failed to unmarshal football result", "event_id", eventID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if futsalRes.TimeStatus != "3" {
|
||||||
|
s.logger.Warn("Match not yet completed", "event_id", eventID)
|
||||||
|
return domain.CreateResult{}, fmt.Errorf("match not yet completed")
|
||||||
|
}
|
||||||
|
|
||||||
|
status, err := s.evaluateFutsalOutcome(outcome, futsalRes)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to evaluate outcome", "event_id", eventID, "market_id", marketID, "error", err)
|
||||||
|
return domain.CreateResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.CreateResult{
|
||||||
|
BetOutcomeID: 0,
|
||||||
|
EventID: eventID,
|
||||||
|
OddID: oddID,
|
||||||
|
MarketID: marketID,
|
||||||
|
Status: status,
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) parseNFL(resultRes json.RawMessage, eventID, oddID, marketID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
func (s *Service) parseNFL(resultRes json.RawMessage, eventID, oddID, marketID int64, outcome domain.BetOutcome) (domain.CreateResult, error) {
|
||||||
var nflResp domain.NFLResultResponse
|
var nflResp domain.NFLResultResponse
|
||||||
if err := json.Unmarshal(resultRes, &nflResp); err != nil {
|
if err := json.Unmarshal(resultRes, &nflResp); err != nil {
|
||||||
|
|
@ -730,6 +900,92 @@ func (s *Service) evaluateIceHockeyOutcome(outcome domain.BetOutcome, res domain
|
||||||
return domain.OUTCOME_STATUS_PENDING, nil
|
return domain.OUTCOME_STATUS_PENDING, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) evaluateCricketOutcome(outcome domain.BetOutcome, res domain.CricketResultResponse) (domain.OutcomeStatus, error) {
|
||||||
|
if !domain.SupportedMarkets[outcome.MarketID] {
|
||||||
|
s.logger.Warn("Unsupported market type", "market_name", outcome.MarketName)
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported market type: %s", outcome.MarketName)
|
||||||
|
}
|
||||||
|
|
||||||
|
score := parseSS(res.SS)
|
||||||
|
|
||||||
|
switch outcome.MarketID {
|
||||||
|
case int64(domain.CRICKET_TO_WIN_THE_MATCH):
|
||||||
|
return evaluateFullTimeResult(outcome, score)
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) evaluateVolleyballOutcome(outcome domain.BetOutcome, res domain.VolleyballResultResponse) (domain.OutcomeStatus, error) {
|
||||||
|
if !domain.SupportedMarkets[outcome.MarketID] {
|
||||||
|
s.logger.Warn("Unsupported market type", "market_name", outcome.MarketName)
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported market type: %s", outcome.MarketName)
|
||||||
|
}
|
||||||
|
|
||||||
|
score := parseSS(res.SS)
|
||||||
|
|
||||||
|
// res.SS example: { 2-3 } is the win count not actuall score of sets
|
||||||
|
// for total score we need every set's score
|
||||||
|
firstSet := parseScore(res.Scores.FirstSet.Home, res.Scores.FirstSet.Away)
|
||||||
|
secondSet := parseScore(res.Scores.SecondSet.Home, res.Scores.SecondSet.Away)
|
||||||
|
thirdSet := parseScore(res.Scores.ThirdSet.Home, res.Scores.ThirdSet.Away)
|
||||||
|
fourthSet := parseScore(res.Scores.FourthSet.Home, res.Scores.FourthSet.Away)
|
||||||
|
fivethSet := parseScore(res.Scores.FivethSet.Home, res.Scores.FivethSet.Away)
|
||||||
|
|
||||||
|
totalScore := struct{ Home, Away int }{Home: 0, Away: 0}
|
||||||
|
totalScore.Home = firstSet.Home + secondSet.Home + thirdSet.Home + fourthSet.Home + fivethSet.Home
|
||||||
|
totalScore.Away = firstSet.Away + secondSet.Away + thirdSet.Away + fourthSet.Away + fivethSet.Away
|
||||||
|
|
||||||
|
switch outcome.MarketID {
|
||||||
|
case int64(domain.VOLLEYBALL_GAME_LINES):
|
||||||
|
return evaluateVolleyballGamelines(outcome, totalScore)
|
||||||
|
case int64(domain.VOLLEYBALL_MATCH_TOTAL_ODD_EVEN):
|
||||||
|
return evaluateGoalsOddEven(outcome, totalScore)
|
||||||
|
case int64(domain.VOLLEYBALL_CORRECT_SET_SCORE):
|
||||||
|
return evaluateCorrectScore(outcome, score)
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) evaluateDartsOutcome(outcome domain.BetOutcome, res domain.DartsResultResponse) (domain.OutcomeStatus, error) {
|
||||||
|
if !domain.SupportedMarkets[outcome.MarketID] {
|
||||||
|
s.logger.Warn("Unsupported market type", "market_name", outcome.MarketName)
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported market type: %s", outcome.MarketName)
|
||||||
|
}
|
||||||
|
|
||||||
|
score := parseSS(res.SS)
|
||||||
|
|
||||||
|
switch outcome.MarketID {
|
||||||
|
case int64(domain.DARTS_MATCH_WINNER):
|
||||||
|
return evaluateFullTimeResult(outcome, score)
|
||||||
|
case int64(domain.DARTS_TOTAL_LEGS):
|
||||||
|
return evaluateTotalLegs(outcome, score)
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) evaluateFutsalOutcome(outcome domain.BetOutcome, res domain.FutsalResultResponse) (domain.OutcomeStatus, error) {
|
||||||
|
if !domain.SupportedMarkets[outcome.MarketID] {
|
||||||
|
s.logger.Warn("Unsupported market type", "market_name", outcome.MarketName)
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, fmt.Errorf("unsupported market type: %s", outcome.MarketName)
|
||||||
|
}
|
||||||
|
|
||||||
|
score := parseSS(res.SS)
|
||||||
|
|
||||||
|
switch outcome.MarketID {
|
||||||
|
case int64(domain.FUTSAL_GAME_LINES):
|
||||||
|
return evaluateGameLines(outcome, score)
|
||||||
|
case int64(domain.FUTSAL_MONEY_LINE):
|
||||||
|
return evaluateMoneyLine(outcome, score)
|
||||||
|
case int64(domain.FUTSAL_TEAM_TO_SCORE_FIRST):
|
||||||
|
return evaluateFirstTeamToScore(outcome, res.Events)
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.OUTCOME_STATUS_PENDING, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) evaluateNFLOutcome(outcome domain.BetOutcome, finalScore struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
func (s *Service) evaluateNFLOutcome(outcome domain.BetOutcome, finalScore struct{ Home, Away int }) (domain.OutcomeStatus, error) {
|
||||||
if !domain.SupportedMarkets[outcome.MarketID] {
|
if !domain.SupportedMarkets[outcome.MarketID] {
|
||||||
s.logger.Warn("Unsupported market type", "market_name", outcome.MarketName)
|
s.logger.Warn("Unsupported market type", "market_name", outcome.MarketName)
|
||||||
|
|
|
||||||
|
|
@ -1,49 +1 @@
|
||||||
package result
|
package result
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestEvaluateFootballOutcome(t *testing.T) {
|
|
||||||
service := &Service{} // or your real logger
|
|
||||||
|
|
||||||
// Mock outcome
|
|
||||||
outcome := domain.BetOutcome{
|
|
||||||
ID: 1,
|
|
||||||
BetID: 1,
|
|
||||||
EventID: 1001,
|
|
||||||
OddID: 2001,
|
|
||||||
SportID: 1, // Assuming 1 = Football
|
|
||||||
HomeTeamName: "Manchester",
|
|
||||||
AwayTeamName: "Liverpool",
|
|
||||||
MarketID: int64(domain.FOOTBALL_FULL_TIME_RESULT),
|
|
||||||
MarketName: "Full Time Result",
|
|
||||||
Odd: 1.75,
|
|
||||||
OddName: "2", // Home win
|
|
||||||
OddHeader: "1",
|
|
||||||
OddHandicap: "",
|
|
||||||
Status: domain.OUTCOME_STATUS_PENDING, // Initial status
|
|
||||||
Expires: time.Now().Add(24 * time.Hour),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parsed result (simulate Bet365 JSON)
|
|
||||||
finalScore := struct{ Home, Away int }{Home: 2, Away: 1}
|
|
||||||
firstHalfScore := struct{ Home, Away int }{Home: 1, Away: 1}
|
|
||||||
secondHalfScore := struct{ Home, Away int }{Home: 1, Away: 0}
|
|
||||||
corners := struct{ Home, Away int }{Home: 5, Away: 3}
|
|
||||||
halfTimeCorners := struct{ Home, Away int }{Home: 2, Away: 2}
|
|
||||||
events := []map[string]string{
|
|
||||||
{"type": "goal", "team": "home", "minute": "23"},
|
|
||||||
{"type": "goal", "team": "away", "minute": "34"},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Act
|
|
||||||
status, _ := service.evaluateFootballOutcome(outcome, finalScore, firstHalfScore, secondHalfScore, corners, halfTimeCorners, events)
|
|
||||||
|
|
||||||
fmt.Printf("\n\nBet Outcome: %v\n\n", &status)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
package result
|
package result
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
@ -301,3 +303,678 @@ func TestBaseballMarkets(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEvaluateFootballOutcome(t *testing.T) {
|
||||||
|
service := &Service{} // or your real logger
|
||||||
|
|
||||||
|
// Mock outcome
|
||||||
|
outcome := domain.BetOutcome{
|
||||||
|
ID: 1,
|
||||||
|
BetID: 1,
|
||||||
|
EventID: 1001,
|
||||||
|
OddID: 2001,
|
||||||
|
SportID: 1, // Assuming 1 = Football
|
||||||
|
HomeTeamName: "Manchester",
|
||||||
|
AwayTeamName: "Liverpool",
|
||||||
|
MarketID: int64(domain.FOOTBALL_FULL_TIME_RESULT),
|
||||||
|
MarketName: "Full Time Result",
|
||||||
|
Odd: 1.75,
|
||||||
|
OddName: "2", // Home win
|
||||||
|
OddHeader: "1",
|
||||||
|
OddHandicap: "",
|
||||||
|
Status: domain.OUTCOME_STATUS_PENDING, // Initial status
|
||||||
|
Expires: time.Now().Add(24 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parsed result (simulate Bet365 JSON)
|
||||||
|
finalScore := struct{ Home, Away int }{Home: 2, Away: 1}
|
||||||
|
firstHalfScore := struct{ Home, Away int }{Home: 1, Away: 1}
|
||||||
|
secondHalfScore := struct{ Home, Away int }{Home: 1, Away: 0}
|
||||||
|
corners := struct{ Home, Away int }{Home: 5, Away: 3}
|
||||||
|
halfTimeCorners := struct{ Home, Away int }{Home: 2, Away: 2}
|
||||||
|
events := []map[string]string{
|
||||||
|
{"type": "goal", "team": "home", "minute": "23"},
|
||||||
|
{"type": "goal", "team": "away", "minute": "34"},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Act
|
||||||
|
status, _ := service.evaluateFootballOutcome(outcome, finalScore, firstHalfScore, secondHalfScore, corners, halfTimeCorners, events)
|
||||||
|
|
||||||
|
fmt.Printf("\n\nBet Outcome: %v\n\n", &status)
|
||||||
|
|
||||||
|
}
|
||||||
|
func TestEvaluateTotalLegs(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"OverTotalLegs", domain.BetOutcome{OddName: "3", OddHeader: "Over"}, struct{ Home, Away int }{2, 4}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"OverTotalLegs", domain.BetOutcome{OddName: "3", OddHeader: "Under"}, struct{ Home, Away int }{2, 4}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"UnderTotalLegs", domain.BetOutcome{OddName: "7", OddHeader: "Under"}, struct{ Home, Away int }{2, 3}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateTotalLegs(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateGameLines(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"GameLines - Total", domain.BetOutcome{OddName: "Total", OddHandicap: "O 5.5"}, struct{ Home, Away int }{2, 4}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"GameLines - Total", domain.BetOutcome{OddName: "Total", OddHandicap: "O 5.5"}, struct{ Home, Away int }{2, 3}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"GameLines - Money Line", domain.BetOutcome{OddName: "Money Line", OddHeader: "1"}, struct{ Home, Away int }{2, 3}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"GameLines - Money Line", domain.BetOutcome{OddName: "Money Line", OddHeader: "1"}, struct{ Home, Away int }{3, 2}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateGameLines(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateFirstTeamToScore(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
events []map[string]string
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"HomeScoreFirst", domain.BetOutcome{OddName: "1", HomeTeamName: "Team A", AwayTeamName: "Team B"}, []map[string]string{
|
||||||
|
{"text": "1st Goal - Team A"},
|
||||||
|
}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"AwayScoreFirst", domain.BetOutcome{OddName: "2", HomeTeamName: "Team A", AwayTeamName: "Team B"}, []map[string]string{
|
||||||
|
{"text": "1st Goal - Team A"},
|
||||||
|
}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"AwayScoreFirst", domain.BetOutcome{OddName: "2", HomeTeamName: "Team A", AwayTeamName: "Team B"}, []map[string]string{
|
||||||
|
{"text": "1st Goal - Team B"},
|
||||||
|
}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateFirstTeamToScore(tt.outcome, tt.events)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateGoalsOverUnder(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"LosingGoalsOver", domain.BetOutcome{OddHeader: "Over", OddName: "13"}, struct{ Home, Away int }{7, 5}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"WinningGoalsOver", domain.BetOutcome{OddHeader: "Over", OddName: "11"}, struct{ Home, Away int }{7, 5}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningGoalsUnder", domain.BetOutcome{OddHeader: "Under", OddName: "12"}, struct{ Home, Away int }{6, 5}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateGoalsOverUnder(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateGoalsOddEven(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"WinningOddGoals", domain.BetOutcome{OddName: "Odd"}, struct{ Home, Away int }{7, 4}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"LosingEvenGoals", domain.BetOutcome{OddName: "Even"}, struct{ Home, Away int }{7, 4}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"WinningEvenGoals", domain.BetOutcome{OddName: "Even"}, struct{ Home, Away int }{6, 6}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateGoalsOddEven(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateCorrectScore(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"CorrectScore", domain.BetOutcome{OddName: "7-4"}, struct{ Home, Away int }{7, 4}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"CorrectScore", domain.BetOutcome{OddName: "6-6"}, struct{ Home, Away int }{6, 6}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"IncorrectScore", domain.BetOutcome{OddName: "2-3"}, struct{ Home, Away int }{7, 4}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateCorrectScore(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateHighestScoringHalf(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
firstScore struct{ Home, Away int }
|
||||||
|
secondScore struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"Winning1stHalf", domain.BetOutcome{OddName: "1st Half"}, struct{ Home, Away int }{1, 1}, struct{ Home, Away int }{0, 0}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"Losing1stHalf", domain.BetOutcome{OddName: "1st Half"}, struct{ Home, Away int }{1, 1}, struct{ Home, Away int }{2, 2}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"Losing2ndHalf", domain.BetOutcome{OddName: "2nd Half"}, struct{ Home, Away int }{0, 0}, struct{ Home, Away int }{0, 0}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"Winning2ndHalf", domain.BetOutcome{OddName: "2nd Half"}, struct{ Home, Away int }{1, 1}, struct{ Home, Away int }{2, 2}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateHighestScoringHalf(tt.outcome, tt.firstScore, tt.secondScore)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateHighestScoringQuarter(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
firstScore struct{ Home, Away int }
|
||||||
|
secondScore struct{ Home, Away int }
|
||||||
|
thirdScore struct{ Home, Away int }
|
||||||
|
fourthScore struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"Winning1stQuarter", domain.BetOutcome{OddName: "1st Quarter"},
|
||||||
|
struct{ Home, Away int }{1, 1},
|
||||||
|
struct{ Home, Away int }{0, 0},
|
||||||
|
struct{ Home, Away int }{1, 0},
|
||||||
|
struct{ Home, Away int }{0, 0},
|
||||||
|
domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"Losing1stQuarter", domain.BetOutcome{OddName: "1st Quarter"},
|
||||||
|
struct{ Home, Away int }{1, 1},
|
||||||
|
struct{ Home, Away int }{0, 0},
|
||||||
|
struct{ Home, Away int }{1, 1},
|
||||||
|
struct{ Home, Away int }{0, 0},
|
||||||
|
domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"Losing2ndQuarter", domain.BetOutcome{OddName: "2nd Quarter"},
|
||||||
|
struct{ Home, Away int }{1, 1},
|
||||||
|
struct{ Home, Away int }{0, 0},
|
||||||
|
struct{ Home, Away int }{1, 1},
|
||||||
|
struct{ Home, Away int }{0, 0},
|
||||||
|
domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"Winning3rdQuarter", domain.BetOutcome{OddName: "3rd Quarter"},
|
||||||
|
struct{ Home, Away int }{1, 0},
|
||||||
|
struct{ Home, Away int }{0, 0},
|
||||||
|
struct{ Home, Away int }{1, 1},
|
||||||
|
struct{ Home, Away int }{0, 0},
|
||||||
|
domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"Wining4thQuarter", domain.BetOutcome{OddName: "4th Quarter"},
|
||||||
|
struct{ Home, Away int }{1, 1},
|
||||||
|
struct{ Home, Away int }{0, 0},
|
||||||
|
struct{ Home, Away int }{1, 1},
|
||||||
|
struct{ Home, Away int }{2, 2},
|
||||||
|
domain.OUTCOME_STATUS_WIN},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateHighestScoringQuarter(tt.outcome, tt.firstScore, tt.secondScore, tt.thirdScore, tt.fourthScore)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateWinningMargin(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"WinningMargin", domain.BetOutcome{OddHeader: "1", OddName: "12"}, struct{ Home, Away int }{12, 0}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningMargin", domain.BetOutcome{OddHeader: "2", OddName: "3"}, struct{ Home, Away int }{1, 4}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningMargin", domain.BetOutcome{OddHeader: "1", OddName: "3+"}, struct{ Home, Away int }{4, 0}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningMargin", domain.BetOutcome{OddHeader: "2", OddName: "12+"}, struct{ Home, Away int }{0, 13}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"LosingMargin", domain.BetOutcome{OddHeader: "2", OddName: "3"}, struct{ Home, Away int }{0, 4}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"LosingMargin", domain.BetOutcome{OddHeader: "2", OddName: "3+"}, struct{ Home, Away int }{1, 3}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateWinningMargin(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateDoubleResult(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
firstHalfScore struct{ Home, Away int }
|
||||||
|
fullTimeScore struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"WinningHomeAway", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team A - Team B"}, struct{ Home, Away int }{1, 0}, struct{ Home, Away int }{1, 2}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningAwayHome", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team B - Team A"}, struct{ Home, Away int }{0, 1}, struct{ Home, Away int }{2, 1}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningTie", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Tie - Tie"}, struct{ Home, Away int }{1, 1}, struct{ Home, Away int }{2, 2}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningTieAway", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Tie - Team B"}, struct{ Home, Away int }{1, 1}, struct{ Home, Away int }{1, 2}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"LosingHomeAway", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team A - Team B"}, struct{ Home, Away int }{1, 0}, struct{ Home, Away int }{2, 0}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"LosingTie", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Tie - Tie"}, struct{ Home, Away int }{1, 0}, struct{ Home, Away int }{1, 1}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"LosingTieAway", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Tie - Team A"}, struct{ Home, Away int }{1, 1}, struct{ Home, Away int }{1, 2}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"BadInput", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team A - "}, struct{ Home, Away int }{1, 1}, struct{ Home, Away int }{1, 2}, domain.OUTCOME_STATUS_PENDING},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateDoubleResult(tt.outcome, tt.firstHalfScore, tt.fullTimeScore)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateHighestScoringPeriod(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
firstScore struct{ Home, Away int }
|
||||||
|
secondScore struct{ Home, Away int }
|
||||||
|
thirdScore struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"Winning1stPeriod", domain.BetOutcome{OddName: "Period 1"}, struct{ Home, Away int }{2, 2}, struct{ Home, Away int }{1, 1}, struct{ Home, Away int }{0, 0}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"Winning2ndPeriod", domain.BetOutcome{OddName: "Period 2"}, struct{ Home, Away int }{2, 2}, struct{ Home, Away int }{2, 3}, struct{ Home, Away int }{0, 0}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"Winning3rdPeriod", domain.BetOutcome{OddName: "Period 3"}, struct{ Home, Away int }{2, 2}, struct{ Home, Away int }{2, 3}, struct{ Home, Away int }{3, 3}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningTie", domain.BetOutcome{OddName: "Tie"}, struct{ Home, Away int }{2, 2}, struct{ Home, Away int }{2, 2}, struct{ Home, Away int }{0, 0}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"Losing1stPeriod", domain.BetOutcome{OddName: "Period 1"}, struct{ Home, Away int }{2, 2}, struct{ Home, Away int }{2, 3}, struct{ Home, Away int }{0, 0}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"Losing3rdPeriod", domain.BetOutcome{OddName: "Period 3"}, struct{ Home, Away int }{2, 2}, struct{ Home, Away int }{2, 3}, struct{ Home, Away int }{0, 0}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateHighestScoringPeriod(tt.outcome, tt.firstScore, tt.secondScore, tt.thirdScore)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvalauteTiedAfterRegulation(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score []struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"WinningTied", domain.BetOutcome{OddName: "Yes"}, []struct{ Home, Away int }{{1, 0}, {0, 1}, {2, 2}}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningTied", domain.BetOutcome{OddName: "Yes"}, []struct{ Home, Away int }{{1, 1}, {0, 1}, {2, 2}, {2, 1}}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningNotTied", domain.BetOutcome{OddName: "No"}, []struct{ Home, Away int }{{0, 0}, {0, 0}, {0, 0}, {1, 0}}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"LosingTied", domain.BetOutcome{OddName: "Yes"}, []struct{ Home, Away int }{{0, 2}, {0, 0}, {0, 0}, {0, 0}}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"LosingNotTied", domain.BetOutcome{OddName: "No"}, []struct{ Home, Away int }{{0, 0}, {0, 0}, {0, 0}, {0, 0}}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateTiedAfterRegulation(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateTeamTotal(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"WinningHomeUnder", domain.BetOutcome{OddHandicap: "Under 3", OddHeader: "1"}, struct{ Home, Away int }{2, 0}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningHomeOver", domain.BetOutcome{OddHandicap: "Over 2", OddHeader: "1"}, struct{ Home, Away int }{3, 1}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningAwayOver", domain.BetOutcome{OddHandicap: "Over 2", OddHeader: "2"}, struct{ Home, Away int }{1, 3}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"LosingHomeOver", domain.BetOutcome{OddHandicap: "Over 2", OddHeader: "1"}, struct{ Home, Away int }{1, 2}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"LosingAwayOver", domain.BetOutcome{OddHandicap: "Over 2", OddHeader: "2"}, struct{ Home, Away int }{1, 2}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateTeamTotal(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDrawNoBet(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"WinningHome", domain.BetOutcome{OddName: "1"}, struct{ Home, Away int }{1, 0}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningAway", domain.BetOutcome{OddName: "2"}, struct{ Home, Away int }{1, 2}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"LosingHome", domain.BetOutcome{OddName: "1"}, struct{ Home, Away int }{1, 2}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"Tie", domain.BetOutcome{OddName: "1"}, struct{ Home, Away int }{1, 1}, domain.OUTCOME_STATUS_VOID},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateDrawNoBet(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateMoneyLine(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"WinningHome", domain.BetOutcome{OddHeader: "1"}, struct{ Home, Away int }{1, 0}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningAway", domain.BetOutcome{OddHeader: "2"}, struct{ Home, Away int }{1, 2}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningTie", domain.BetOutcome{OddHeader: "Tie"}, struct{ Home, Away int }{2, 2}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"LosingTie", domain.BetOutcome{OddHeader: "1"}, struct{ Home, Away int }{1, 2}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"LosingAway", domain.BetOutcome{OddHeader: "2"}, struct{ Home, Away int }{3, 2}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateMoneyLine(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateDoubleChance(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"WinningHomeOrDraw", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "1 or Draw"}, struct{ Home, Away int }{1, 0}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningHomeOrDraw", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team A or Draw"}, struct{ Home, Away int }{1, 0}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningAwayOrDraw", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Draw or Team B"}, struct{ Home, Away int }{0, 1}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"LosingHomeorAway", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "1 or 2"}, struct{ Home, Away int }{1, 1}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"LosingAwayOrDraw", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Draw or 2"}, struct{ Home, Away int }{2, 1}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateDoubleChance(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateResultAndTotal(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"WinningHomeOver", domain.BetOutcome{OddHeader: "1", OddHandicap: "Over 4"}, struct{ Home, Away int }{3, 2}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningHomeUnder", domain.BetOutcome{OddHeader: "1", OddHandicap: "Under 4"}, struct{ Home, Away int }{2, 1}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningAwayUnder", domain.BetOutcome{OddHeader: "2", OddHandicap: "Under 4"}, struct{ Home, Away int }{1, 2}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"LosingHomeOver", domain.BetOutcome{OddHeader: "1", OddHandicap: "Under 4"}, struct{ Home, Away int }{3, 2}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"LosingAwayUnder", domain.BetOutcome{OddHeader: "2", OddHandicap: "Under 4"}, struct{ Home, Away int }{2, 2}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateResultAndTotal(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCheckMultiOutcome(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.OutcomeStatus
|
||||||
|
secondOutcome domain.OutcomeStatus
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"Win-Win", domain.OUTCOME_STATUS_WIN, domain.OUTCOME_STATUS_WIN, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"Win-Void", domain.OUTCOME_STATUS_WIN, domain.OUTCOME_STATUS_VOID, domain.OUTCOME_STATUS_HALF},
|
||||||
|
{"Win-Loss", domain.OUTCOME_STATUS_WIN, domain.OUTCOME_STATUS_LOSS, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"Loss-Loss", domain.OUTCOME_STATUS_LOSS, domain.OUTCOME_STATUS_LOSS, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"Loss-Void", domain.OUTCOME_STATUS_LOSS, domain.OUTCOME_STATUS_VOID, domain.OUTCOME_STATUS_VOID},
|
||||||
|
{"Loss-Win", domain.OUTCOME_STATUS_LOSS, domain.OUTCOME_STATUS_WIN, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"Void-Win", domain.OUTCOME_STATUS_VOID, domain.OUTCOME_STATUS_WIN, domain.OUTCOME_STATUS_VOID},
|
||||||
|
{"Void-Loss", domain.OUTCOME_STATUS_VOID, domain.OUTCOME_STATUS_LOSS, domain.OUTCOME_STATUS_VOID},
|
||||||
|
{"Void-Void", domain.OUTCOME_STATUS_VOID, domain.OUTCOME_STATUS_VOID, domain.OUTCOME_STATUS_VOID},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := checkMultiOutcome(tt.outcome, tt.secondOutcome)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateBTTSX(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"WinningBothScoreX", domain.BetOutcome{OddName: "3", OddHeader: "Yes"}, struct{ Home, Away int }{3, 4}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningBothScoreLess", domain.BetOutcome{OddName: "3", OddHeader: "No"}, struct{ Home, Away int }{2, 1}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"LosingBothScoreX", domain.BetOutcome{OddName: "3", OddHeader: "Yes"}, struct{ Home, Away int }{2, 4}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"LosingBothScoreLess", domain.BetOutcome{OddName: "3", OddHeader: "No"}, struct{ Home, Away int }{2, 4}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateBTTSX(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateResultAndBTTSX(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"WinningHomeAndBothScoreX", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team A and Yes", OddHeader: "3"}, struct{ Home, Away int }{4, 3}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningHomeAndBothScoreLess", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team A and No", OddHeader: "3"}, struct{ Home, Away int }{2, 1}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningAwayAndBothScoreX", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team B and Yes", OddHeader: "3"}, struct{ Home, Away int }{3, 4}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningAwayAndBothScoreLess", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team B and No", OddHeader: "3"}, struct{ Home, Away int }{1, 2}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"LosingHomeAndBothScoreX", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team A and Yes", OddHeader: "3"}, struct{ Home, Away int }{3, 4}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"LosingHomeAndBothScoreX", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team B and Yes", OddHeader: "3"}, struct{ Home, Away int }{4, 2}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"LosingAwayAndBothScoreX", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team B and Yes", OddHeader: "3"}, struct{ Home, Away int }{2, 4}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateResultAndBTTSX(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateMoneyLine3Way(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"WinningHome", domain.BetOutcome{OddName: "1"}, struct{ Home, Away int }{1, 0}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningAway", domain.BetOutcome{OddName: "2"}, struct{ Home, Away int }{1, 2}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"WinningTie", domain.BetOutcome{OddName: "Tie"}, struct{ Home, Away int }{2, 2}, domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"LosingTie", domain.BetOutcome{OddName: "1"}, struct{ Home, Away int }{1, 2}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"LosingAway", domain.BetOutcome{OddName: "2"}, struct{ Home, Away int }{3, 2}, domain.OUTCOME_STATUS_LOSS},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateMoneyLine3Way(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateAsianHandicap(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Home -1 Win",
|
||||||
|
outcome: domain.BetOutcome{OddHeader: "1", OddHandicap: "-1"},
|
||||||
|
score: struct{ Home, Away int }{Home: 2, Away: 0},
|
||||||
|
expected: domain.OUTCOME_STATUS_WIN,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Home -0.5 Win",
|
||||||
|
outcome: domain.BetOutcome{OddHeader: "1", OddHandicap: "-0.5"},
|
||||||
|
score: struct{ Home, Away int }{Home: 1, Away: 0},
|
||||||
|
expected: domain.OUTCOME_STATUS_WIN,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Home -1 Void",
|
||||||
|
outcome: domain.BetOutcome{OddHeader: "1", OddHandicap: "-1"},
|
||||||
|
score: struct{ Home, Away int }{Home: 1, Away: 0},
|
||||||
|
expected: domain.OUTCOME_STATUS_VOID,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Away +3 Win",
|
||||||
|
outcome: domain.BetOutcome{OddHeader: "2", OddHandicap: "3"},
|
||||||
|
score: struct{ Home, Away int }{Home: 1, Away: 2},
|
||||||
|
expected: domain.OUTCOME_STATUS_WIN,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Split Handicap Home -0.5,-1 Win/Win",
|
||||||
|
outcome: domain.BetOutcome{OddHeader: "1", OddHandicap: "-0.5,-1"},
|
||||||
|
score: struct{ Home, Away int }{Home: 2, Away: 0},
|
||||||
|
expected: domain.OUTCOME_STATUS_WIN,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Split Handicap Home -0.5,-1 Win/Void",
|
||||||
|
outcome: domain.BetOutcome{OddHeader: "1", OddHandicap: "-0.5,-1"},
|
||||||
|
score: struct{ Home, Away int }{Home: 1, Away: 0},
|
||||||
|
expected: domain.OUTCOME_STATUS_WIN,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Invalid Handicap",
|
||||||
|
outcome: domain.BetOutcome{OddHeader: "1", OddHandicap: "invalid"},
|
||||||
|
score: struct{ Home, Away int }{Home: 1, Away: 0},
|
||||||
|
expected: domain.OUTCOME_STATUS_ERROR,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateAsianHandicap(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateHandicapAndTotal(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outcome domain.BetOutcome
|
||||||
|
score struct{ Home, Away int }
|
||||||
|
expected domain.OutcomeStatus
|
||||||
|
}{
|
||||||
|
{"Home +2.5 Over 3", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team A +2.5 & Over 3"},
|
||||||
|
struct{ Home, Away int }{4, 0},
|
||||||
|
domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"Away +2.5 Over 4", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team B +2.5 & Over 4"},
|
||||||
|
struct{ Home, Away int }{1, 5},
|
||||||
|
domain.OUTCOME_STATUS_WIN},
|
||||||
|
{"Home +2.5 Over 3", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team A +2.5 & Over 3"},
|
||||||
|
struct{ Home, Away int }{2, 0},
|
||||||
|
domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"Home -3.5 Over 3", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team A -2.5 & Over 3"},
|
||||||
|
struct{ Home, Away int }{4, 3},
|
||||||
|
domain.OUTCOME_STATUS_LOSS},
|
||||||
|
{"Away -3 Over 4", domain.BetOutcome{HomeTeamName: "Team A", AwayTeamName: "Team B", OddName: "Team B -3 & Over 4"},
|
||||||
|
struct{ Home, Away int }{3, 5},
|
||||||
|
domain.OUTCOME_STATUS_LOSS},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
status, _ := evaluateHandicapAndTotal(tt.outcome, tt.score)
|
||||||
|
if status != tt.expected {
|
||||||
|
t.Errorf("expected %d, got %d", tt.expected, status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
5
makefile
5
makefile
|
|
@ -39,6 +39,11 @@ migrations/up:
|
||||||
@echo 'Running up migrations...'
|
@echo 'Running up migrations...'
|
||||||
@docker compose up migrate
|
@docker compose up migrate
|
||||||
|
|
||||||
|
.PHONY: postgres
|
||||||
|
postgres:
|
||||||
|
@echo 'Running postgres db...'
|
||||||
|
docker compose -f docker-compose.yml exec postgres psql -U root -d gh
|
||||||
|
|
||||||
.PHONY: swagger
|
.PHONY: swagger
|
||||||
swagger:
|
swagger:
|
||||||
@swag init -g cmd/main.go
|
@swag init -g cmd/main.go
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user