Compare commits

...

8 Commits
master ... tidy

Author SHA1 Message Date
85c8835e64 delete unused code 2024-11-26 15:18:04 -08:00
09ae8b4b38 extreme gorm 2024-11-26 15:14:06 -08:00
d11ee978dc gorming 2024-11-26 15:08:40 -08:00
ee7790dd39 delete everything that won't compile 2024-11-26 15:08:31 -08:00
103ae75640 submissions.Get no red underlines 2024-11-26 14:48:31 -08:00
d85a5a0669 run generate 2024-11-26 14:47:56 -08:00
6e2e95abaf extend submission object 2024-11-26 14:42:22 -08:00
a5009998a8 renaming and fixing red underlines 2024-11-26 14:37:18 -08:00
11 changed files with 365 additions and 493 deletions

View File

@ -125,6 +125,41 @@ func (s *Error) UnmarshalJSON(data []byte) error {
return s.Decode(d)
}
// Encode encodes bool as json.
func (o OptBool) Encode(e *jx.Encoder) {
if !o.Set {
return
}
e.Bool(bool(o.Value))
}
// Decode decodes bool from json.
func (o *OptBool) Decode(d *jx.Decoder) error {
if o == nil {
return errors.New("invalid: unable to decode OptBool to nil")
}
o.Set = true
v, err := d.Bool()
if err != nil {
return err
}
o.Value = bool(v)
return nil
}
// MarshalJSON implements stdjson.Marshaler.
func (s OptBool) MarshalJSON() ([]byte, error) {
e := jx.Encoder{}
s.Encode(&e)
return e.Bytes(), nil
}
// UnmarshalJSON implements stdjson.Unmarshaler.
func (s *OptBool) UnmarshalJSON(data []byte) error {
d := jx.DecodeBytes(data)
return s.Decode(d)
}
// Encode encodes int32 as json.
func (o OptInt32) Encode(e *jx.Encoder) {
if !o.Set {
@ -269,14 +304,63 @@ func (s *Submission) encodeFields(e *jx.Encoder) {
s.Date.Encode(e)
}
}
{
if s.Submitter.Set {
e.FieldStart("Submitter")
s.Submitter.Encode(e)
}
}
{
if s.AssetID.Set {
e.FieldStart("AssetID")
s.AssetID.Encode(e)
}
}
{
if s.AssetVersion.Set {
e.FieldStart("AssetVersion")
s.AssetVersion.Encode(e)
}
}
{
if s.Completed.Set {
e.FieldStart("Completed")
s.Completed.Encode(e)
}
}
{
if s.SubmissionType.Set {
e.FieldStart("SubmissionType")
s.SubmissionType.Encode(e)
}
}
{
if s.TargetAssetID.Set {
e.FieldStart("TargetAssetID")
s.TargetAssetID.Encode(e)
}
}
{
if s.StatusID.Set {
e.FieldStart("StatusID")
s.StatusID.Encode(e)
}
}
}
var jsonFieldsNameOfSubmission = [5]string{
0: "ID",
1: "DisplayName",
2: "Creator",
3: "GameID",
4: "Date",
var jsonFieldsNameOfSubmission = [12]string{
0: "ID",
1: "DisplayName",
2: "Creator",
3: "GameID",
4: "Date",
5: "Submitter",
6: "AssetID",
7: "AssetVersion",
8: "Completed",
9: "SubmissionType",
10: "TargetAssetID",
11: "StatusID",
}
// Decode decodes Submission from json.
@ -337,6 +421,76 @@ func (s *Submission) Decode(d *jx.Decoder) error {
}(); err != nil {
return errors.Wrap(err, "decode field \"Date\"")
}
case "Submitter":
if err := func() error {
s.Submitter.Reset()
if err := s.Submitter.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"Submitter\"")
}
case "AssetID":
if err := func() error {
s.AssetID.Reset()
if err := s.AssetID.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"AssetID\"")
}
case "AssetVersion":
if err := func() error {
s.AssetVersion.Reset()
if err := s.AssetVersion.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"AssetVersion\"")
}
case "Completed":
if err := func() error {
s.Completed.Reset()
if err := s.Completed.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"Completed\"")
}
case "SubmissionType":
if err := func() error {
s.SubmissionType.Reset()
if err := s.SubmissionType.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"SubmissionType\"")
}
case "TargetAssetID":
if err := func() error {
s.TargetAssetID.Reset()
if err := s.TargetAssetID.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"TargetAssetID\"")
}
case "StatusID":
if err := func() error {
s.StatusID.Reset()
if err := s.StatusID.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"StatusID\"")
}
default:
return d.Skip()
}

View File

@ -63,6 +63,52 @@ func (s *ErrorStatusCode) SetResponse(val Error) {
s.Response = val
}
// NewOptBool returns new OptBool with value set to v.
func NewOptBool(v bool) OptBool {
return OptBool{
Value: v,
Set: true,
}
}
// OptBool is optional bool.
type OptBool struct {
Value bool
Set bool
}
// IsSet returns true if OptBool was set.
func (o OptBool) IsSet() bool { return o.Set }
// Reset unsets value.
func (o *OptBool) Reset() {
var v bool
o.Value = v
o.Set = false
}
// SetTo sets value to v.
func (o *OptBool) SetTo(v bool) {
o.Set = true
o.Value = v
}
// Get returns value and boolean that denotes whether value was set.
func (o OptBool) Get() (v bool, ok bool) {
if !o.Set {
return v, false
}
return o.Value, true
}
// Or returns value if set, or given parameter if does not.
func (o OptBool) Or(d bool) bool {
if v, ok := o.Get(); ok {
return v
}
return d
}
// NewOptInt32 returns new OptInt32 with value set to v.
func NewOptInt32(v int32) OptInt32 {
return OptInt32{
@ -284,11 +330,18 @@ type PatchSubmissionStatusOK struct{}
// Ref: #/components/schemas/Submission
type Submission struct {
ID OptInt64 `json:"ID"`
DisplayName OptString `json:"DisplayName"`
Creator OptString `json:"Creator"`
GameID OptInt32 `json:"GameID"`
Date OptInt64 `json:"Date"`
ID OptInt64 `json:"ID"`
DisplayName OptString `json:"DisplayName"`
Creator OptString `json:"Creator"`
GameID OptInt32 `json:"GameID"`
Date OptInt64 `json:"Date"`
Submitter OptInt64 `json:"Submitter"`
AssetID OptInt64 `json:"AssetID"`
AssetVersion OptInt64 `json:"AssetVersion"`
Completed OptBool `json:"Completed"`
SubmissionType OptInt32 `json:"SubmissionType"`
TargetAssetID OptInt64 `json:"TargetAssetID"`
StatusID OptInt32 `json:"StatusID"`
}
// GetID returns the value of ID.
@ -316,6 +369,41 @@ func (s *Submission) GetDate() OptInt64 {
return s.Date
}
// GetSubmitter returns the value of Submitter.
func (s *Submission) GetSubmitter() OptInt64 {
return s.Submitter
}
// GetAssetID returns the value of AssetID.
func (s *Submission) GetAssetID() OptInt64 {
return s.AssetID
}
// GetAssetVersion returns the value of AssetVersion.
func (s *Submission) GetAssetVersion() OptInt64 {
return s.AssetVersion
}
// GetCompleted returns the value of Completed.
func (s *Submission) GetCompleted() OptBool {
return s.Completed
}
// GetSubmissionType returns the value of SubmissionType.
func (s *Submission) GetSubmissionType() OptInt32 {
return s.SubmissionType
}
// GetTargetAssetID returns the value of TargetAssetID.
func (s *Submission) GetTargetAssetID() OptInt64 {
return s.TargetAssetID
}
// GetStatusID returns the value of StatusID.
func (s *Submission) GetStatusID() OptInt32 {
return s.StatusID
}
// SetID sets the value of ID.
func (s *Submission) SetID(val OptInt64) {
s.ID = val
@ -341,6 +429,41 @@ func (s *Submission) SetDate(val OptInt64) {
s.Date = val
}
// SetSubmitter sets the value of Submitter.
func (s *Submission) SetSubmitter(val OptInt64) {
s.Submitter = val
}
// SetAssetID sets the value of AssetID.
func (s *Submission) SetAssetID(val OptInt64) {
s.AssetID = val
}
// SetAssetVersion sets the value of AssetVersion.
func (s *Submission) SetAssetVersion(val OptInt64) {
s.AssetVersion = val
}
// SetCompleted sets the value of Completed.
func (s *Submission) SetCompleted(val OptBool) {
s.Completed = val
}
// SetSubmissionType sets the value of SubmissionType.
func (s *Submission) SetSubmissionType(val OptInt32) {
s.SubmissionType = val
}
// SetTargetAssetID sets the value of TargetAssetID.
func (s *Submission) SetTargetAssetID(val OptInt64) {
s.TargetAssetID = val
}
// SetStatusID sets the value of StatusID.
func (s *Submission) SetStatusID(val OptInt32) {
s.StatusID = val
}
// Ref: #/components/schemas/SubmissionFilter
type SubmissionFilter struct {
ID OptInt64 `json:"ID"`

View File

@ -2,129 +2,32 @@ package controller
import (
"context"
"fmt"
"git.itzana.me/strafesnet/maps-service/internal/datastore"
"git.itzana.me/strafesnet/maps-service/internal/model"
"git.itzana.me/strafesnet/maps-service/api"
"github.com/pkg/errors"
"time"
)
type Maps struct {
*maps.UnimplementedMapsServiceServer
type Submissions struct {
Store datastore.Datastore
}
func (m Maps) Get(ctx context.Context, params *api.GetSubmissionParams) (*api.Submission, error) {
item, err := m.Store.Maps().Get(ctx, params.SubmissionID)
func (m Submissions) Get(ctx context.Context, params *api.GetSubmissionParams) (*api.Submission, error) {
item, err := m.Store.Submissions().Get(ctx, params.SubmissionID)
if err != nil {
if err == datastore.ErrNotExist {
return nil, status.Error(codes.NotFound, "map does not exit")
}
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to get map:").Error())
return nil, err
}
return &maps.MapResponse{
ID: item.ID,
DisplayName: item.DisplayName,
Creator: item.Creator,
GameID: item.GameID,
Date: item.Date.Unix(),
return &api.Submission{
ID: api.NewOptInt64(item.ID),
DisplayName: api.NewOptString(item.DisplayName),
Creator: api.NewOptString(item.Creator),
GameID: api.NewOptInt32(item.GameID),
Date: api.NewOptInt64(item.Date.Unix()),
Submitter: api.NewOptInt64(item.Submitter),
AssetID: api.NewOptInt64(item.AssetID),
AssetVersion: api.NewOptInt64(item.AssetVersion),
Completed: api.NewOptBool(item.Completed),
SubmissionType: api.NewOptInt32(item.SubmissionType),
TargetAssetID: api.NewOptInt64(item.TargetAssetID),
StatusID: api.NewOptInt32(item.StatusID),
}, nil
}
func (m Maps) GetList(ctx context.Context, list *maps.IdList) (*maps.MapList, error) {
items, err := m.Store.Maps().GetList(ctx, list.ID)
if err != nil {
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to get maps").Error())
}
var resp maps.MapList
for i := 0; i < len(items); i++ {
resp.Maps = append(resp.Maps, &maps.MapResponse{
ID: items[i].ID,
DisplayName: items[i].DisplayName,
Creator: items[i].Creator,
GameID: items[i].GameID,
Date: items[i].Date.Unix(),
})
}
return &resp, nil
}
func (m Maps) Update(ctx context.Context, request *maps.MapRequest) (*maps.NullResponse, error) {
updates := datastore.Optional()
updates.AddNotNil("display_name", request.DisplayName)
updates.AddNotNil("creator", request.Creator)
updates.AddNotNil("game_id", request.GameID)
if request.Date != nil {
updates.AddNotNil("date", time.Unix(request.GetDate(), 0))
}
if err := m.Store.Maps().Update(ctx, request.GetID(), updates); err != nil {
if err == datastore.ErrNotExist {
return nil, status.Error(codes.NotFound, "map does not exit")
}
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to update map:").Error())
}
return &maps.NullResponse{}, nil
}
func (m Maps) Create(ctx context.Context, request *maps.MapRequest) (*maps.IdMessage, error) {
item, err := m.Store.Maps().Create(ctx, model.Map{
ID: request.GetID(),
DisplayName: request.GetDisplayName(),
Creator: request.GetCreator(),
GameID: request.GetGameID(),
Date: time.Unix(request.GetDate(), 0),
})
if err != nil {
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to create map:").Error())
}
return &maps.IdMessage{ID: item.ID}, nil
}
func (m Maps) Delete(ctx context.Context, message *maps.IdMessage) (*maps.NullResponse, error) {
if err := m.Store.Maps().Delete(ctx, message.GetID()); err != nil {
if err == datastore.ErrNotExist {
return nil, status.Error(codes.NotFound, "map does not exit")
}
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to delete map:").Error())
}
return &maps.NullResponse{}, nil
}
func (m Maps) List(ctx context.Context, request *maps.ListRequest) (*maps.MapList, error) {
filter := datastore.Optional()
fmt.Println(request)
if request.Filter != nil {
filter.AddNotNil("display_name", request.GetFilter().DisplayName)
filter.AddNotNil("creator", request.GetFilter().Creator)
filter.AddNotNil("game_id", request.GetFilter().GameID)
}
items, err := m.Store.Maps().List(ctx, filter, model.Page{
Number: request.GetPage().GetNumber(),
Size: request.GetPage().GetSize(),
})
if err != nil {
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to get maps:").Error())
}
var resp maps.MapList
for i := 0; i < len(items); i++ {
resp.Maps = append(resp.Maps, &maps.MapResponse{
ID: items[i].ID,
DisplayName: items[i].DisplayName,
Creator: items[i].Creator,
GameID: items[i].GameID,
Date: items[i].Date.Unix(),
})
}
return &resp, nil
}

View File

@ -1,117 +1,9 @@
package controller
import (
"context"
"git.itzana.me/strafesnet/maps-service/internal/datastore"
"git.itzana.me/strafesnet/maps-service/internal/model"
"git.itzana.me/strafesnet/go-grpc/users"
"github.com/pkg/errors"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type Users struct {
*users.UnimplementedUsersServiceServer
Store datastore.Datastore
}
func (u Users) Get(ctx context.Context, request *users.IdMessage) (*users.UserResponse, error) {
ur, err := u.Store.Users().Get(ctx, request.ID)
if err != nil {
if err == datastore.ErrNotExist {
return nil, status.Error(codes.NotFound, err.Error())
}
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to get user").Error())
}
return &users.UserResponse{
ID: ur.ID,
Username: ur.Username,
StateID: ur.StateID,
}, nil
}
func (u Users) GetList(ctx context.Context, list *users.IdList) (*users.UserList, error) {
uList, err := u.Store.Users().GetList(ctx, list.ID)
if err != nil {
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to get users").Error())
}
var resp users.UserList
for i := 0; i < len(uList); i++ {
resp.Users = append(resp.Users, &users.UserResponse{
ID: uList[i].ID,
Username: uList[i].Username,
StateID: uList[i].StateID,
})
}
return &resp, nil
}
func (u Users) Update(ctx context.Context, request *users.UserRequest) (*users.NullResponse, error) {
updates := datastore.Optional()
updates.AddNotNil("state_id", request.StateID)
updates.AddNotNil("username", request.Username)
if err := u.Store.Users().Update(ctx, request.GetID(), updates); err != nil {
if err == datastore.ErrNotExist {
return nil, status.Error(codes.NotFound, err.Error())
}
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to update user").Error())
}
return &users.NullResponse{}, nil
}
func (u Users) Create(ctx context.Context, request *users.UserRequest) (*users.IdMessage, error) {
us, err := u.Store.Users().Create(ctx, model.User{
ID: request.GetID(),
Username: request.GetUsername(),
StateID: request.GetStateID(),
})
if err != nil {
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to create user").Error())
}
return &users.IdMessage{ID: us.ID}, nil
}
func (u Users) Delete(ctx context.Context, request *users.IdMessage) (*users.NullResponse, error) {
if err := u.Store.Users().Delete(ctx, request.GetID()); err != nil {
if err == datastore.ErrNotExist {
return nil, status.Error(codes.NotFound, err.Error())
}
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to delete user").Error())
}
return &users.NullResponse{}, nil
}
func (u Users) List(ctx context.Context, request *users.ListRequest) (*users.UserList, error) {
filters := datastore.Optional()
if request.Filter != nil {
filters.AddNotNil("id", request.GetFilter().ID)
filters.AddNotNil("state_id", request.GetFilter().StateID)
filters.AddNotNil("username", request.GetFilter().Username)
}
uList, err := u.Store.Users().List(ctx, filters, model.Page{
Number: request.GetPage().GetNumber(),
Size: request.GetPage().GetSize(),
})
if err != nil {
return nil, status.Error(codes.Internal, errors.Wrap(err, "failed to get filtered users").Error())
}
var uResp users.UserList
for i := 0; i < len(uList); i++ {
uResp.Users = append(uResp.Users, &users.UserResponse{
ID: uList[i].ID,
Username: uList[i].Username,
StateID: uList[i].StateID,
})
}
return &uResp, nil
}

View File

@ -3,7 +3,6 @@ package datastore
import (
"context"
"errors"
"time"
"git.itzana.me/strafesnet/maps-service/internal/model"
)
@ -13,25 +12,10 @@ var (
)
type Datastore interface {
Times() Times
Users() Users
Bots() Bots
Maps() Maps
Events() Events
Servers() Servers
Transactions() Transactions
Ranks() Ranks
Submissions() Submissions
}
type Times interface {
Get(ctx context.Context, id int64) (model.Time, error)
Create(ctx context.Context, time model.Time) (model.Time, error)
Update(ctx context.Context, id int64, values OptionalMap) error
Delete(ctx context.Context, id int64) error
List(ctx context.Context, filters OptionalMap, blacklisted bool, page model.Page, sort uint32) (int64, []model.Time, error)
Rank(ctx context.Context, id int64) (int64, error)
DistinctStylePairs(ctx context.Context) ([]model.Time, error)
}
type Users interface {
Get(ctx context.Context, id int64) (model.User, error)
@ -42,53 +26,11 @@ type Users interface {
List(ctx context.Context, filters OptionalMap, page model.Page) ([]model.User, error)
}
type Bots interface {
Get(ctx context.Context, id int64) (model.Bot, error)
GetList(ctx context.Context, id []int64) ([]model.Bot, error)
Create(ctx context.Context, bot model.Bot) (model.Bot, error)
type Submissions interface {
Get(ctx context.Context, id int64) (model.Submission, error)
GetList(ctx context.Context, id []int64) ([]model.Submission, error)
Create(ctx context.Context, time model.Submission) (model.Submission, error)
Update(ctx context.Context, id int64, values OptionalMap) error
Delete(ctx context.Context, id int64) error
List(ctx context.Context, filters OptionalMap, page model.Page) ([]model.Bot, error)
}
type Maps interface {
Get(ctx context.Context, id int64) (model.Map, error)
GetList(ctx context.Context, id []int64) ([]model.Map, error)
Create(ctx context.Context, time model.Map) (model.Map, error)
Update(ctx context.Context, id int64, values OptionalMap) error
Delete(ctx context.Context, id int64) error
List(ctx context.Context, filters OptionalMap, page model.Page) ([]model.Map, error)
}
type Events interface {
Latest(ctx context.Context, date int64, page model.Page) ([]model.Event, error)
Create(ctx context.Context, event model.Event) (model.Event, error)
Clean(ctx context.Context) error
}
type Servers interface {
Get(ctx context.Context, id string) (model.Server, error)
Create(ctx context.Context, server model.Server) (model.Server, error)
Update(ctx context.Context, id string, values OptionalMap) error
Delete(ctx context.Context, id string) error
DeleteByLastUpdated(ctx context.Context, date time.Time) error
List(ctx context.Context, filters OptionalMap, page model.Page) ([]model.Server, error)
}
type Transactions interface {
Balance(ctx context.Context, user int64) (int64, error)
Get(ctx context.Context, id string) (model.Transaction, error)
Create(ctx context.Context, transaction model.Transaction) (model.Transaction, error)
Update(ctx context.Context, id string, values OptionalMap) error
Delete(ctx context.Context, id string) error
List(ctx context.Context, filters OptionalMap, page model.Page) ([]model.Transaction, error)
}
type Ranks interface {
Delete(ctx context.Context, id int64) error
Get(ctx context.Context, user int64, style, game, mode int32, state []int32) (model.Rank, error)
List(ctx context.Context, style, game, mode int32, sort int64, state []int32, page model.Page) ([]model.Rank, error)
UpdateRankCalc(ctx context.Context) error
UpdateAll(ctx context.Context, style, game, mode int32) error
UpdateUsers(ctx context.Context, style, game, mode int32, users []int) error
List(ctx context.Context, filters OptionalMap, page model.Page) ([]model.Submission, error)
}

View File

@ -38,7 +38,7 @@ func New(migrate bool) (datastore.Datastore, error) {
sqlDB.SetMaxOpenConns(25)
if migrate {
if err := db.AutoMigrate(&model.Time{}, &model.User{}, &model.Bot{}, &model.Map{}, &model.Event{}, &model.Server{}, &model.Transaction{}, &model.Rank{}, &model.RankCalc{}); err != nil {
if err := db.AutoMigrate(&model.User{}, &model.Submission{}); err != nil {
log.WithField("error", err).Errorln("database migration failed")
return nil, err
}

View File

@ -11,34 +11,10 @@ type Gormstore struct {
cache *cache.Cache[[]byte]
}
func (g Gormstore) Times() datastore.Times {
return &Times{db: g.db}
}
func (g Gormstore) Users() datastore.Users {
return &Users{db: g.db}
}
func (g Gormstore) Bots() datastore.Bots {
return &Bots{db: g.db}
}
func (g Gormstore) Maps() datastore.Maps {
return &Maps{db: g.db}
}
func (g Gormstore) Events() datastore.Events {
return &Events{db: g.db}
}
func (g Gormstore) Servers() datastore.Servers {
return &Servers{db: g.db}
}
func (g Gormstore) Transactions() datastore.Transactions {
return &Transactions{db: g.db}
}
func (g Gormstore) Ranks() datastore.Ranks {
return &Ranks{db: g.db, cache: g.cache}
func (g Gormstore) Submissions() datastore.Submissions {
return &Submissions{db: g.db}
}

View File

@ -7,12 +7,12 @@ import (
"gorm.io/gorm"
)
type Maps struct {
type Submissions struct {
db *gorm.DB
}
func (m Maps) Get(ctx context.Context, id int64) (model.Map, error) {
var smap model.Map
func (m Submissions) Get(ctx context.Context, id int64) (model.Submission, error) {
var smap model.Submission
if err := m.db.WithContext(ctx).First(&smap, id).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return smap, datastore.ErrNotExist
@ -23,8 +23,8 @@ func (m Maps) Get(ctx context.Context, id int64) (model.Map, error) {
return smap, nil
}
func (m Maps) GetList(ctx context.Context, id []int64) ([]model.Map, error) {
var mapList []model.Map
func (m Submissions) GetList(ctx context.Context, id []int64) ([]model.Submission, error) {
var mapList []model.Submission
if err := m.db.WithContext(ctx).Find(&mapList, "id IN ?", id).Error; err != nil {
return mapList, err
}
@ -32,7 +32,7 @@ func (m Maps) GetList(ctx context.Context, id []int64) ([]model.Map, error) {
return mapList, nil
}
func (m Maps) Create(ctx context.Context, smap model.Map) (model.Map, error) {
func (m Submissions) Create(ctx context.Context, smap model.Submission) (model.Submission, error) {
if err := m.db.WithContext(ctx).Create(&smap).Error; err != nil {
return smap, err
}
@ -40,8 +40,8 @@ func (m Maps) Create(ctx context.Context, smap model.Map) (model.Map, error) {
return smap, nil
}
func (m Maps) Update(ctx context.Context, id int64, values datastore.OptionalMap) error {
if err := m.db.WithContext(ctx).Model(&model.Map{}).Where("id = ?", id).Updates(values.Map()).Error; err != nil {
func (m Submissions) Update(ctx context.Context, id int64, values datastore.OptionalMap) error {
if err := m.db.WithContext(ctx).Model(&model.Submission{}).Where("id = ?", id).Updates(values.Map()).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return datastore.ErrNotExist
}
@ -51,8 +51,8 @@ func (m Maps) Update(ctx context.Context, id int64, values datastore.OptionalMap
return nil
}
func (m Maps) Delete(ctx context.Context, id int64) error {
if err := m.db.WithContext(ctx).Delete(&model.Map{}, id).Error; err != nil {
func (m Submissions) Delete(ctx context.Context, id int64) error {
if err := m.db.WithContext(ctx).Delete(&model.Submission{}, id).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return datastore.ErrNotExist
}
@ -62,8 +62,8 @@ func (m Maps) Delete(ctx context.Context, id int64) error {
return nil
}
func (m Maps) List(ctx context.Context, filters datastore.OptionalMap, page model.Page) ([]model.Map, error) {
var maps []model.Map
func (m Submissions) List(ctx context.Context, filters datastore.OptionalMap, page model.Page) ([]model.Submission, error) {
var maps []model.Submission
if err := m.db.WithContext(ctx).Where(filters.Map()).Offset(int((page.Number - 1) * page.Size)).Limit(int(page.Size)).Find(&maps).Error; err != nil {
return nil, err
}

View File

@ -2,10 +2,17 @@ package model
import "time"
type Map struct {
ID int64
DisplayName string
Creator string
GameID int32
Date time.Time
type Submission struct {
ID int64
DisplayName string
Creator string
GameID int32
Date time.Time
Submitter int64 // UserID
AssetID int64
AssetVersion int64
Completed bool
SubmissionType int32 // 1=New 2=Fix
TargetAssetID int64 // where to upload map fix
StatusID int32
}

View File

@ -213,6 +213,26 @@ components:
Date:
type: integer
format: int64
Submitter:
type: integer
format: int64
AssetID:
type: integer
format: int64
AssetVersion:
type: integer
format: int64
Completed:
type: boolean
SubmissionType:
type: integer
format: int32
TargetAssetID:
type: integer
format: int64
StatusID:
type: integer
format: int32
SubmissionFilter:
type: object
properties:

157
server.go
View File

@ -8,6 +8,7 @@ import (
"git.itzana.me/strafesnet/maps-service/api"
"git.itzana.me/strafesnet/maps-service/internal/controller/submissions"
"git.itzana.me/strafesnet/maps-service/internal/controller/users"
"git.itzana.me/strafesnet/maps-service/internal/datastore/gormstore"
)
type apiServer struct {
@ -28,132 +29,16 @@ func (m *apiServer) NewError(ctx context.Context, err error) *api.ErrorStatusCod
}
}
// GetTimes implements api.Handler.
func (m *apiServer) ListTimes(ctx context.Context, params api.ListTimesParams) ([]api.Time, error) {
client := times.NewTimesServiceClient(m.client)
// Call the List method using params
req := &times.ListRequest{
Page: &times.Pagination{
Number: params.Page.GetPage(),
Size: params.Page.GetLimit(),
},
}
if filter, ok := params.Filter.Get(); ok {
if id := filter.GetID(); id.IsSet() {
req.Filter.ID = &id.Value
}
if time := filter.GetTime(); time.IsSet() {
req.Filter.Time = &time.Value
}
if userID := filter.GetUserID(); userID.IsSet() {
req.Filter.UserID = &userID.Value
}
if mapID := filter.GetMapID(); mapID.IsSet() {
req.Filter.MapID = &mapID.Value
}
if styleID := filter.GetStyleID(); styleID.IsSet() {
req.Filter.StyleID = &styleID.Value
}
if modeID := filter.GetModeID(); modeID.IsSet() {
req.Filter.ModeID = &modeID.Value
}
if gameID := filter.GetGameID(); gameID.IsSet() {
req.Filter.GameID = &gameID.Value
}
}
response, err := client.List(ctx, req)
if err != nil {
return nil, err
}
return convertTimes(response.Times), nil
}
// GetUser implements api.Handler.
func (m *apiServer) GetUser(ctx context.Context, params api.GetUserParams) (*api.User, error) {
client := users.NewUsersServiceClient(m.client)
response, err := client.Get(ctx, &users.IdMessage{
ID: params.UserID,
})
if err != nil {
return nil, err
}
return &api.User{
ID: api.NewOptInt64(response.ID),
Username: api.NewOptString(response.Username),
StateID: api.NewOptInt32(response.StateID),
}, nil
}
// ListRanks implements api.Handler.
func (m *apiServer) ListRanks(ctx context.Context, params api.ListRanksParams) ([]api.Rank, error) {
client := ranks.NewRanksServiceClient(m.client)
req := &ranks.ListRequest{
Page: &ranks.Pagination{
Number: params.Page.GetPage(),
Size: params.Page.GetLimit(),
},
}
if filter, ok := params.Filter.Get(); ok {
if gameID, ok := filter.GetGameID().Get(); ok {
req.GameID = gameID
}
if modeID, ok := filter.GetModeID().Get(); ok {
req.ModeID = modeID
}
if styleID, ok := filter.GetStyleID().Get(); ok {
req.StyleID = styleID
}
if sort, ok := filter.GetSort().Get(); ok {
req.Sort = sort
}
}
response, err := client.List(ctx, req)
if err != nil {
return nil, err
}
ranks := make([]api.Rank, len(response.Ranks))
for i, r := range response.Ranks {
ranks[i] = api.Rank{
ID: api.NewOptInt64(r.ID),
User: api.NewOptUser(api.User{
ID: api.NewOptInt64(r.User.ID),
Username: api.NewOptString(r.User.Username),
StateID: api.NewOptInt32(r.User.StateID),
}),
StyleID: api.NewOptInt32(r.StyleID),
ModeID: api.NewOptInt32(r.ModeID),
GameID: api.NewOptInt32(r.GameID),
Rank: api.NewOptFloat64(r.Rank),
Skill: api.NewOptFloat64(r.Skill),
UpdatedAt: api.NewOptInt64(r.UpdatedAt),
}
}
return ranks, nil
}
func main() {
// new grpc client
conn, err := grpc.Dial("localhost:9000", grpc.WithTransportCredentials(insecure.NewCredentials()))
db, err := gormstore.New(true)
if err != nil {
log.Fatal(err)
log.WithField("error", err).Fatalln("database startup failed")
return
}
svc := &apiServer{
client: conn,
submissions: db.Submissions(),
users: db.Users(),
}
srv, err := api.NewServer(
@ -168,33 +53,3 @@ func main() {
log.Fatal(err)
}
}
func convertTime(t *times.TimeResponse) api.Time {
return api.Time{
ID: api.NewOptInt64(t.ID),
Time: api.NewOptInt64(t.Time),
User: api.NewOptUser(api.User{
ID: api.NewOptInt64(t.User.ID),
Username: api.NewOptString(t.User.Username),
StateID: api.NewOptInt32(t.User.StateID),
}),
Map: api.NewOptMap(api.Map{
ID: api.NewOptInt64(t.Map.ID),
DisplayName: api.NewOptString(t.Map.DisplayName),
Creator: api.NewOptString(t.Map.Creator),
Date: api.NewOptInt64(t.Map.Date),
}),
Date: api.NewOptInt64(t.Date),
StyleID: api.NewOptInt32(t.StyleID),
ModeID: api.NewOptInt32(t.ModeID),
GameID: api.NewOptInt32(t.GameID),
}
}
func convertTimes(timeList []*times.TimeResponse) []api.Time {
times := make([]api.Time, len(timeList))
for i, t := range timeList {
times[i] = convertTime(t)
}
return times
}