Skip to content

Commit

Permalink
player search
Browse files Browse the repository at this point in the history
  • Loading branch information
BuckarooBanzay committed Oct 22, 2023
1 parent 8818907 commit feab9b0
Show file tree
Hide file tree
Showing 8 changed files with 337 additions and 103 deletions.
34 changes: 34 additions & 0 deletions player/columns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package player

import (
"github.com/minetest-go/mtdb/types"
)

func getColumns(dbtype types.DatabaseType) []string {
switch dbtype {
case types.DATABASE_SQLITE:
return []string{
"name", "pitch", "yaw",
"posx", "posy", "posz",
"hp", "breath",
"strftime('%s', creation_date)",
"strftime('%s', modification_date)",
}
case types.DATABASE_POSTGRES:
return []string{
"name", "pitch", "yaw",
"posx", "posy", "posz",
"hp", "breath",
"extract(epoch from creation_date)::int",
"extract(epoch from modification_date)::int",
}
default:
return nil
}
}

func scanPlayer(scan func(v ...any) error) (*Player, error) {
p := &Player{}
err := scan(&p.Name, &p.Pitch, &p.Yaw, &p.PosX, &p.PosY, &p.PosZ, &p.HP, &p.Breath, &p.CreationDate, &p.ModificationDate)
return p, err
}
67 changes: 67 additions & 0 deletions player/export.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package player

import (
"archive/zip"
"bufio"
"bytes"
"encoding/json"
)

func (r *PlayerRepository) Export(z *zip.Writer) error {
w, err := z.Create("player.json")
if err != nil {
return err
}
enc := json.NewEncoder(w)

rows, err := r.db.Query("select name from player")
if err != nil {
return err
}
defer rows.Close()

for rows.Next() {
name := ""
err = rows.Scan(&name)
if err != nil {
return err
}

player, err := r.GetPlayer(name)
if err != nil {
return err
}

err = enc.Encode(player)
if err != nil {
return err
}
}

return nil
}

func (r *PlayerRepository) Import(z *zip.Reader) error {
f, err := z.Open("player.json")
if err != nil {
return err
}
defer f.Close()

sc := bufio.NewScanner(f)
for sc.Scan() {
dc := json.NewDecoder(bytes.NewReader(sc.Bytes()))
e := &Player{}
err = dc.Decode(e)
if err != nil {
return err
}

err = r.CreateOrUpdate(e)
if err != nil {
return err
}
}

return nil
}
111 changes: 12 additions & 99 deletions player/player.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package player

import (
"archive/zip"
"bufio"
"bytes"
"database/sql"
"encoding/json"
"errors"
"fmt"
"strings"

"github.com/minetest-go/mtdb/types"
)
Expand All @@ -21,33 +19,10 @@ type PlayerRepository struct {
}

func (r *PlayerRepository) GetPlayer(name string) (*Player, error) {
var q string
switch r.dbtype {
case types.DATABASE_SQLITE:
q = `
select name,pitch,yaw,
posx,posy,posz,
hp,breath,
strftime('%s', creation_date),strftime('%s', modification_date)
from player
where name = $1
`
case types.DATABASE_POSTGRES:
q = `
select name,pitch,yaw,
posx,posy,posz,
hp,breath,
extract(epoch from creation_date)::int,extract(epoch from modification_date)::int
from player
where name = $1
`
default:
return nil, errors.New("invalid dbtype")
}
q := fmt.Sprintf("select %s from player where name = $1", strings.Join(getColumns(r.dbtype), ","))

row := r.db.QueryRow(q, name)
p := &Player{}
err := row.Scan(&p.Name, &p.Pitch, &p.Yaw, &p.PosX, &p.PosY, &p.PosZ, &p.HP, &p.Breath, &p.CreationDate, &p.ModificationDate)
p, err := scanPlayer(row.Scan)
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
Expand All @@ -64,13 +39,15 @@ func (r *PlayerRepository) CreateOrUpdate(p *Player) error {
name,pitch,yaw,
posx,posy,posz,
hp,breath,
creation_date,modification_date
creation_date,
modification_date
)
values(
$1,$2,$3,
$4,$5,$6,
$7,$8,
datetime($9, 'unixepoch'),datetime($10, 'unixepoch')
datetime($9, 'unixepoch'),
datetime($10, 'unixepoch')
)
`
case types.DATABASE_POSTGRES:
Expand All @@ -79,13 +56,15 @@ func (r *PlayerRepository) CreateOrUpdate(p *Player) error {
name,pitch,yaw,
posx,posy,posz,
hp,breath,
creation_date,modification_date
creation_date,
modification_date
)
values(
$1,$2,$3,
$4,$5,$6,
$7,$8,
to_timestamp($9),to_timestamp($10)
to_timestamp($9),
to_timestamp($10)
)
on conflict (name) do update
set
Expand All @@ -111,69 +90,3 @@ func (r *PlayerRepository) RemovePlayer(name string) error {
_, err := r.db.Exec("delete from player where name = $1", name)
return err
}

func (r *PlayerRepository) Count() (int64, error) {
row := r.db.QueryRow("select count(*) from player")
count := int64(0)
err := row.Scan(&count)
return count, err
}

func (r *PlayerRepository) Export(z *zip.Writer) error {
w, err := z.Create("player.json")
if err != nil {
return err
}
enc := json.NewEncoder(w)

rows, err := r.db.Query("select name from player")
if err != nil {
return err
}
defer rows.Close()

for rows.Next() {
name := ""
err = rows.Scan(&name)
if err != nil {
return err
}

player, err := r.GetPlayer(name)
if err != nil {
return err
}

err = enc.Encode(player)
if err != nil {
return err
}
}

return nil
}

func (r *PlayerRepository) Import(z *zip.Reader) error {
f, err := z.Open("player.json")
if err != nil {
return err
}
defer f.Close()

sc := bufio.NewScanner(f)
for sc.Scan() {
dc := json.NewDecoder(bytes.NewReader(sc.Bytes()))
e := &Player{}
err = dc.Decode(e)
if err != nil {
return err
}

err = r.CreateOrUpdate(e)
if err != nil {
return err
}
}

return nil
}
67 changes: 67 additions & 0 deletions player/player_search.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package player

import (
"fmt"
"strings"
)

func (repo *PlayerRepository) buildWhereClause(fields string, s *PlayerSearch) (string, []any) {
q := `select ` + fields + ` from player where true `
args := make([]any, 0)
i := 1

if s.Name != nil {
q += fmt.Sprintf(" and name = $%d", i)
args = append(args, *s.Name)
i++
}

if s.Namelike != nil {
q += fmt.Sprintf(" and name like $%d", i)
args = append(args, *s.Namelike)
i++
}

if s.OrderColumn != nil && orderColumns[*s.OrderColumn] {
order := Ascending
if s.OrderDirection != nil && orderDirections[*s.OrderDirection] {
order = *s.OrderDirection
}

q += fmt.Sprintf(" order by %s %s", *s.OrderColumn, order)
}

// limit result length to 1000 per default
limit := 1000
if s.Limit != nil {
limit = *s.Limit
}
q += fmt.Sprintf(" limit %d", limit)

return q, args
}

func (repo *PlayerRepository) Search(s *PlayerSearch) ([]*Player, error) {
q, args := repo.buildWhereClause(strings.Join(getColumns(repo.dbtype), ","), s)
rows, err := repo.db.Query(q, args...)
if err != nil {
return nil, err
}
list := make([]*Player, 0)
for rows.Next() {
p, err := scanPlayer(rows.Scan)
if err != nil {
return nil, err
}
list = append(list, p)
}
return list, nil
}

func (repo *PlayerRepository) Count(s *PlayerSearch) (int, error) {
q, args := repo.buildWhereClause("count(*)", s)
row := repo.db.QueryRow(q, args...)
count := 0
err := row.Scan(&count)
return count, err
}
Loading

0 comments on commit feab9b0

Please sign in to comment.