Compare commits

...

2 Commits

Author SHA1 Message Date
William Perron 122bf0e4cf
tmp
11 months ago
William Perron b75539416a
tmp
11 months ago

@ -2,6 +2,7 @@ package themis
import ( import (
"context" "context"
"database/sql"
"fmt" "fmt"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
@ -19,34 +20,71 @@ func (c Conflict) String() string {
return fmt.Sprintf("%s owned by #%d %s %s (%s)", c.Province, c.ClaimID, c.ClaimType, c.Claim, c.Player) return fmt.Sprintf("%s owned by #%d %s %s (%s)", c.Province, c.ClaimID, c.ClaimType, c.Claim, c.Player)
} }
const conflictQuery string = `SELECT name, player, claim_type, val, id FROM ( // const conflictQuery string = `SELECT name, player, claim_type, val, id FROM (
SELECT provinces.name, claims.player, claims.claim_type, claims.val, claims.id // SELECT provinces.name, claims.player, claims.claim_type, claims.val, claims.id
FROM claims // FROM claims
LEFT JOIN provinces ON claims.val = provinces.trade_node // LEFT JOIN provinces ON claims.val = provinces.trade_node
WHERE claims.claim_type = 'trade' AND claims.userid IS NOT ? // WHERE claims.claim_type = 'trade' AND claims.userid IS NOT ?
AND provinces.%[1]s = ? // AND provinces.%[1]s = ?
UNION // UNION
SELECT provinces.name, claims.player, claims.claim_type, claims.val, claims.id // SELECT provinces.name, claims.player, claims.claim_type, claims.val, claims.id
FROM claims // FROM claims
LEFT JOIN provinces ON claims.val = provinces.region // LEFT JOIN provinces ON claims.val = provinces.region
WHERE claims.claim_type = 'region' AND claims.userid IS NOT ? // WHERE claims.claim_type = 'region' AND claims.userid IS NOT ?
AND provinces.%[1]s = ? // AND provinces.%[1]s = ?
UNION // UNION
SELECT provinces.name, claims.player, claims.claim_type, claims.val, claims.id // SELECT provinces.name, claims.player, claims.claim_type, claims.val, claims.id
FROM claims // FROM claims
LEFT JOIN provinces ON claims.val = provinces.area // LEFT JOIN provinces ON claims.val = provinces.area
WHERE claims.claim_type = 'area' AND claims.userid IS NOT ? // WHERE claims.claim_type = 'area' AND claims.userid IS NOT ?
AND provinces.%[1]s = ? // AND provinces.%[1]s = ?
);` // );`
const conflictQuery string = `
WITH claiming AS (
SELECT province FROM claimables
WHERE typ = ?
AND name = ?
)
SELECT claimables.province, claims.player, claims.claim_type, claims.val, claims.id
FROM claims
INNER JOIN claimables
ON claims.claim_type = claimables.typ
AND claims.val = claimables.name
INNER JOIN claiming
ON claiming.province = claimables.province
WHERE claims.userid IS NOT ?`
func (s *Store) FindConflicts(ctx context.Context, userId, name string, claimType ClaimType) ([]Conflict, error) { func (s *Store) FindConflicts(ctx context.Context, userId, name string, claimType ClaimType) ([]Conflict, error) {
log.Debug().Ctx(ctx).Stringer("claim_type", claimType).Str("userid", userId).Msg("searching for potential conflicts") log.Debug().Ctx(ctx).Stringer("claim_type", claimType).Str("userid", userId).Msg("searching for potential conflicts")
stmt, err := s.db.PrepareContext(ctx, fmt.Sprintf(conflictQuery, claimTypeToColumn[claimType])) stmt, err := s.db.PrepareContext(ctx, conflictQuery)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to prepare conflicts query: %w", err) return nil, fmt.Errorf("failed to prepare conflicts query: %w", err)
} }
rows, err := stmt.QueryContext(ctx, userId, name, userId, name, userId, name) // =========================================================================
rows, err := s.db.QueryContext(ctx, `select claims.val, claims.claim_type, claims.player, claimables.province
from claims
inner join claimables on claims.val = claimables.name and claims.claim_type = claimables.typ;
`)
if err != nil {
panic(err)
}
res2 := make([]string, 0)
for rows.Next() {
var name, typ, play string
var pro sql.NullString
if err := rows.Scan(&name, &typ, &play, &pro); err != nil {
panic(err)
}
res2 = append(res2, fmt.Sprintf("%s, %s, %s, %s", name, typ, play, pro.String))
}
log.Debug().Strs("list", res2).Msg("existing claims")
// =========================================================================
rows, err = stmt.QueryContext(ctx, claimTypeToColumn[claimType], name, userId)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get conflicting provinces: %w", err) return nil, fmt.Errorf("failed to get conflicting provinces: %w", err)
} }

@ -28,17 +28,17 @@ func TestStore_FindConflicts(t *testing.T) {
want []Conflict want []Conflict
wantErr bool wantErr bool
}{ }{
{ // {
name: "same-player", // name: "same-player",
args: args{ // args: args{
context.TODO(), // context.TODO(),
"000000000000000001", // "000000000000000001",
"France", // "France",
CLAIM_TYPE_REGION, // CLAIM_TYPE_REGION,
}, // },
want: []Conflict{}, // want: []Conflict{},
wantErr: false, // wantErr: false,
}, // },
{ {
name: "overlapping", name: "overlapping",
args: args{ args: args{
@ -54,17 +54,17 @@ func TestStore_FindConflicts(t *testing.T) {
}, },
wantErr: false, wantErr: false,
}, },
{ // {
name: "no-overlap", // name: "no-overlap",
args: args{ // args: args{
context.TODO(), // context.TODO(),
"000000000000000002", // "000000000000000002",
"Scandinavia", // "Scandinavia",
CLAIM_TYPE_REGION, // CLAIM_TYPE_REGION,
}, // },
want: []Conflict{}, // want: []Conflict{},
wantErr: false, // wantErr: false,
}, // },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {

@ -1,6 +1,6 @@
module go.wperron.io/themis module go.wperron.io/themis
go 1.21 go 1.19
require ( require (
github.com/bwmarrin/discordgo v0.26.1 github.com/bwmarrin/discordgo v0.26.1

@ -0,0 +1,14 @@
create view if not exists claimables as
with
trades as (select distinct trade_node from provinces where trade_node != ''),
areas as (select distinct area from provinces where area != ''),
regions as (select distinct region from provinces where region != '')
select 'trade_node' as typ, provinces.trade_node as name, name as province, id
from provinces inner join trades on trades.trade_node = provinces.trade_node
union
select 'area' as typ, provinces.area as name, name as province, id
from provinces inner join areas on areas.area = provinces.area
union
select 'region' as typ, provinces.region as name, name as province, id
from provinces inner join regions on regions.region = provinces.region
;

@ -45,16 +45,17 @@ func NewStore(conn string) (*Store, error) {
return nil, fmt.Errorf("failed to initialize db migrate: %w", err) return nil, fmt.Errorf("failed to initialize db migrate: %w", err)
} }
err = m.Up()
if err != nil && !errors.Is(err, migrate.ErrNoChange) {
return nil, fmt.Errorf("failed to roll up migrations: %w", err)
}
ver, dirty, err := m.Version() ver, dirty, err := m.Version()
if err != nil { if err != nil && err != migrate.ErrNilVersion {
return nil, fmt.Errorf("failed to get database migration version: %w", err) return nil, fmt.Errorf("failed to get database migration version: %w", err)
} }
log.Debug().Uint("current_version", ver).Bool("dirty", dirty).Msg("running database migrations") log.Debug().Uint("current_version", ver).Bool("dirty", dirty).Msg("running database migrations")
err = m.Up()
if err != nil && !errors.Is(err, migrate.ErrNoChange) {
return nil, fmt.Errorf("failed to roll up migrations: %w", err)
}
return &Store{ return &Store{
db: db, db: db,

@ -3,10 +3,11 @@
package themis package themis
import ( import (
"context"
"time" "time"
) )
// Uptime returns the time elapsed since the start of the current process ID. // Uptime returns the time elapsed since the start of the current process ID.
func Uptime() (time.Duration, error) { func Uptime(ctx context.Context) (time.Duration, error) {
return 0, nil return 0, nil
} }

Loading…
Cancel
Save