First commit

This commit is contained in:
2022-06-29 21:26:05 -04:00
commit e7559f0bf1
48 changed files with 8132 additions and 0 deletions

17
backend/models/frame.go Normal file
View File

@@ -0,0 +1,17 @@
package models
import (
"gorm.io/gorm"
)
type Frame struct {
gorm.Model
ID uint64 `json:"ID" gorm:"primaryKey"`
GameID uint64 `json:"game_id" gorm:"not null"`
Game Game `json:"game" gorm:"not null"`
Coins uint64 `json:"coins" gorm:";not null"`
Points uint64 `json:"points" gorm:"not null"`
FPS uint8 `json:"fps" gorm:"not null"`
ElapsedTime uint64 `json:"elapsed_time" gorm:"not null"`
Objects []Object `json:"objects"`
}

100
backend/models/game.go Normal file
View File

@@ -0,0 +1,100 @@
package models
import (
"errors"
"strings"
"gorm.io/gorm"
)
type Game struct {
gorm.Model
ID uint64 `json:"ID" gorm:"primaryKey"`
PlayerID uint64 `json:"player_id" gorm:"not null"`
Player Player `json:"player"`
LevelID uint64 `json:"level_id" gorm:"not null"`
Level Level `json:"level" gorm:"not null"`
OSID uint64 `json:"os_id" gorm:"not null"`
OS OS `json:"os" gorm:"not null"`
GodotVersionID uint64 `json:"godot_version_id" gorm:"not null"`
GodotVersion GodotVersion `json:"godot_version" gorm:"not null"`
ProcessorCount uint64 `json:"processor_count" gorm:"not null"`
ScreenCount uint8 `json:"screen_count" gorm:"not null"`
ScreenDPI uint8 `json:"screen_dpi" gorm:"not null"`
ScreenSize string `json:"screen_size" gorm:"not null"`
MachineId string `json:"machine_id" gorm:"not null"`
Locale string `json:"locale" gorm:"not null"`
GameVersion string `json:"game_version" gorm:"not null"`
Won bool `json:"won" gorm:"not null"`
Timestamp uint64 `json:"timestamp" gorm:"not null"`
Frames []Frame `json:"frames"`
}
func (game *Game) Validate() error {
if len(strings.TrimSpace(game.MachineId)) == 0 {
return errors.New("empty machine id")
}
return nil
}
// Cache the results of the queries here
// The object states and names should not be deleted so this should always be valid while running
var cachedStateNames = make(map[string]uint64)
var cachedObjectNames = make(map[string]uint64)
func (game *Game) BeforeCreate(tx *gorm.DB) error {
// Use the same player ID if the RUT is already in the DB
tx.Model(Player{}).Where(&Player{RUT: game.Player.RUT}).Find(&game.Player)
tx.Model(GodotVersion{}).Where(&GodotVersion{String: game.GodotVersion.String}).Find(&game.GodotVersion)
for frameIndex, frame := range game.Frames {
for objectIndex := range frame.Objects {
game.Frames[frameIndex].Objects[objectIndex].ObjectState.Name = game.Frames[frameIndex].Objects[objectIndex].State
game.Frames[frameIndex].Objects[objectIndex].ObjectName.Name = game.Frames[frameIndex].Objects[objectIndex].Name
// Use the existing state names in the database if they exist
if ID, ok := cachedStateNames[game.Frames[frameIndex].Objects[objectIndex].ObjectState.Name]; ok {
// The name is cached, no need to query the database
game.Frames[frameIndex].Objects[objectIndex].ObjectStateID = ID
game.Frames[frameIndex].Objects[objectIndex].ObjectState.ID = ID
} else {
var state ObjectState
result := tx.Model(ObjectState{}).Where(&ObjectState{Name: game.Frames[frameIndex].Objects[objectIndex].ObjectState.Name}).Find(&state)
if result.RowsAffected == 0 {
// Not in the database, so let's create it
tx.Create(&game.Frames[frameIndex].Objects[objectIndex].ObjectState)
game.Frames[frameIndex].Objects[objectIndex].ObjectStateID = game.Frames[frameIndex].Objects[objectIndex].ObjectState.ID
cachedStateNames[game.Frames[frameIndex].Objects[objectIndex].ObjectState.Name] = game.Frames[frameIndex].Objects[objectIndex].ObjectState.ID
} else {
// It is in the database, so use that
game.Frames[frameIndex].Objects[objectIndex].ObjectStateID = state.ID
game.Frames[frameIndex].Objects[objectIndex].ObjectState.ID = state.ID
cachedStateNames[game.Frames[frameIndex].Objects[objectIndex].ObjectState.Name] = state.ID
}
}
// Use the existing object names in the database if they exist
if ID, ok := cachedObjectNames[game.Frames[frameIndex].Objects[objectIndex].ObjectName.Name]; ok {
// The name is cached, no need to query the database
game.Frames[frameIndex].Objects[objectIndex].ObjectNameID = ID
game.Frames[frameIndex].Objects[objectIndex].ObjectName.ID = ID
} else {
var objectName ObjectName
result := tx.Model(ObjectName{}).Where(&ObjectName{Name: game.Frames[frameIndex].Objects[objectIndex].ObjectName.Name}).Find(&objectName)
if result.RowsAffected == 0 {
// Not in the database, so let's create it
tx.Create(&game.Frames[frameIndex].Objects[objectIndex].ObjectName)
game.Frames[frameIndex].Objects[objectIndex].ObjectNameID = game.Frames[frameIndex].Objects[objectIndex].ObjectName.ID
cachedObjectNames[game.Frames[frameIndex].Objects[objectIndex].ObjectName.Name] = game.Frames[frameIndex].Objects[objectIndex].ObjectName.ID
} else {
// It is in the database, so use that
game.Frames[frameIndex].Objects[objectIndex].ObjectNameID = objectName.ID
game.Frames[frameIndex].Objects[objectIndex].ObjectName.ID = objectName.ID
cachedObjectNames[game.Frames[frameIndex].Objects[objectIndex].ObjectName.Name] = objectName.ID
}
}
}
}
return nil
}

View File

@@ -0,0 +1,17 @@
package models
import "gorm.io/gorm"
type GodotVersion struct {
gorm.Model
ID uint64 `json:"ID" gorm:"primaryKey"`
Major uint8 `json:"major" gorm:"not null"`
Minor uint8 `json:"minor" gorm:"not null"`
Patch uint8 `json:"patch" gorm:"not null"`
Hex uint64 `json:"hex" gorm:"not null"`
Status string `json:"status" gorm:"not null"`
Build string `json:"build" gorm:"not null"`
Year uint16 `json:"year" gorm:"not null"`
Hash string `json:"hash" gorm:"unique;size:40;not null"`
String string `json:"string" gorm:"unique;not null"`
}

9
backend/models/level.go Normal file
View File

@@ -0,0 +1,9 @@
package models
import "gorm.io/gorm"
type Level struct {
gorm.Model
ID uint64 `json:"ID" gorm:"primaryKey"`
Name string `json:"rut" gorm:"unique;not null"`
}

20
backend/models/object.go Normal file
View File

@@ -0,0 +1,20 @@
package models
import "gorm.io/gorm"
type Object struct {
gorm.Model
ID uint64 `json:"ID" gorm:"primaryKey"`
FrameID uint64 `json:"frame_id" gorm:"not null"`
Frame Frame `json:"frame" gorm:"not null"`
ObjectNameID uint64 `json:"-" gorm:"not null"`
ObjectName ObjectName `json:"-" gorm:"not null"`
ObjectStateID uint64 `json:"-" gorm:"not null"`
ObjectState ObjectState `json:"-" gorm:"not null"`
Name string `json:"name" gorm:"-:all"`
State string `json:"state" gorm:"-:all"`
PositionX float64 `json:"position_x" gorm:"not null"`
PositionY float64 `json:"position_y" gorm:"not null"`
VelocityX float64 `json:"velocity_x" gorm:"not null"`
VelocityY float64 `json:"velocity_y" gorm:"not null"`
}

View File

@@ -0,0 +1,9 @@
package models
import "gorm.io/gorm"
type ObjectName struct {
gorm.Model
ID uint64 `json:"ID" gorm:"primaryKey"`
Name string `json:"name" gorm:"unique;not null"`
}

View File

@@ -0,0 +1,9 @@
package models
import "gorm.io/gorm"
type ObjectState struct {
gorm.Model
ID uint64 `json:"ID" gorm:"primaryKey"`
Name string `json:"name" gorm:"unique;not null"`
}

9
backend/models/os.go Normal file
View File

@@ -0,0 +1,9 @@
package models
import "gorm.io/gorm"
type OS struct {
gorm.Model
ID uint64 `json:"ID" gorm:"primaryKey"`
Name string `json:"name" gorm:"unique;size:8;not null"`
}

11
backend/models/player.go Normal file
View File

@@ -0,0 +1,11 @@
package models
import "gorm.io/gorm"
type Player struct {
gorm.Model
ID uint64 `json:"ID" gorm:"primaryKey"`
RUT string `json:"rut" gorm:"unique;size:9;not null"`
Name string `json:"name" gorm:"not null"`
Email string `json:"email" gorm:"unique;not null"`
}

32
backend/models/user.go Normal file
View File

@@ -0,0 +1,32 @@
package models
import (
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
gorm.Model
ID uint64 `json:"ID" gorm:"primaryKey"`
Name string `json:"name" gorm:"not null"`
Username string `json:"username" gorm:"unique; not null"`
Email string `json:"email" gorm:"unique;not null"`
Password string `json:"password" gorm:"not null"`
}
func (user *User) HashPassword(password string) error {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
if err != nil {
return err
}
user.Password = string(bytes)
return nil
}
func (user *User) CheckPassword(providedPassword string) error {
err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(providedPassword))
if err != nil {
return err
}
return nil
}