286 lines
6.2 KiB
Go
286 lines
6.2 KiB
Go
package models
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"gralias/utils"
|
|
"time"
|
|
|
|
"github.com/rs/xid"
|
|
)
|
|
|
|
type WordColor string
|
|
|
|
const (
|
|
WordColorWhite = "amber"
|
|
WordColorBlue = "blue"
|
|
WordColorRed = "red"
|
|
WordColorBlack = "black"
|
|
WordColorUknown = "stone" // beige
|
|
)
|
|
|
|
func StrToWordColor(s string) WordColor {
|
|
switch s {
|
|
case "amber", "white":
|
|
return WordColorWhite
|
|
case "blue":
|
|
return WordColorBlue
|
|
case "red":
|
|
return WordColorRed
|
|
case "black":
|
|
return WordColorBlack
|
|
default:
|
|
return WordColorUknown
|
|
}
|
|
}
|
|
|
|
type Team struct {
|
|
Guessers []string
|
|
Mime string
|
|
Color string
|
|
}
|
|
|
|
type Action struct {
|
|
Actor string
|
|
ActorColor string
|
|
Action string // clue | guess
|
|
Word string
|
|
WordColor string
|
|
Number string // for clue
|
|
}
|
|
|
|
type BotPlayer struct {
|
|
Role UserRole // gueeser | mime
|
|
Team UserTeam
|
|
}
|
|
|
|
type Room struct {
|
|
ID string `json:"id" db:"id"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
// RoomName string `json:"room_name"`
|
|
RoomPass string `json:"room_pass"`
|
|
RoomLink string
|
|
CreatorName string `json:"creator_name"`
|
|
// PlayerList []string `json:"player_list"`
|
|
ActionHistory []Action
|
|
TeamTurn UserTeam
|
|
RedTeam Team
|
|
BlueTeam Team
|
|
Cards []WordCard
|
|
ThisTurnLimit uint8 // how many cards guessers can open this turn
|
|
OpenedThisTurn uint8 // how many cards have been opened this turn
|
|
WCMap map[string]WordColor
|
|
BotMap map[string]BotPlayer // key is bot name
|
|
Result uint8 // 0 for unknown; 1 is win for red; 2 if for blue;
|
|
BlueCounter uint8
|
|
RedCounter uint8
|
|
RedTurn bool // false is blue turn
|
|
MimeDone bool
|
|
IsPublic bool
|
|
// GameSettings *GameSettings `json:"settings"`
|
|
IsRunning bool `json:"is_running"`
|
|
Language string `json:"language" example:"en" form:"language"`
|
|
RoundTime int32 `json:"round_time"`
|
|
// ProgressPct uint32 `json:"progress_pct"`
|
|
IsOver bool
|
|
TeamWon UserTeam // blue | red
|
|
// needed for debug
|
|
LogJournal []string
|
|
}
|
|
|
|
func (r *Room) GetPlayerByName(name string) (role UserRole, team UserTeam, found bool) {
|
|
if r.RedTeam.Mime == name {
|
|
return "mime", "red", true
|
|
}
|
|
if r.BlueTeam.Mime == name {
|
|
return "mime", "blue", true
|
|
}
|
|
for _, guesser := range r.RedTeam.Guessers {
|
|
if guesser == name {
|
|
return "guesser", "red", true
|
|
}
|
|
}
|
|
for _, guesser := range r.BlueTeam.Guessers {
|
|
if guesser == name {
|
|
return "guesser", "blue", true
|
|
}
|
|
}
|
|
return "", "", false
|
|
}
|
|
|
|
func (r *Room) CanStart() error {
|
|
if r.IsRunning {
|
|
return errors.New("cannot start; game is already running")
|
|
}
|
|
if r.RedTeam.Mime == "" {
|
|
return errors.New("cannot start; red team has no mime")
|
|
}
|
|
if r.BlueTeam.Mime == "" {
|
|
return errors.New("cannot start; blue team has no mime")
|
|
}
|
|
if len(r.RedTeam.Guessers) == 0 {
|
|
return errors.New("cannot start; red team has no guessers")
|
|
}
|
|
if len(r.BlueTeam.Guessers) == 0 {
|
|
return errors.New("cannot start; blue team has no guessers")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func getGuesser(m map[string]BotPlayer, team UserTeam) string {
|
|
for k, v := range m {
|
|
if v.Team == team && v.Role == UserRoleGuesser {
|
|
return k
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// WhichBotToMove returns bot name that have to move or empty string
|
|
func (r *Room) WhichBotToMove() string {
|
|
fmt.Println("looking for bot to move", "team-turn:", r.TeamTurn,
|
|
"mime-done:", r.MimeDone, "bot-map:", r.BotMap, "is_running:", r.IsRunning,
|
|
"blueMime:", r.BlueTeam.Mime, "redMime:", r.RedTeam.Mime)
|
|
if !r.IsRunning {
|
|
return ""
|
|
}
|
|
switch r.TeamTurn {
|
|
case UserTeamBlue:
|
|
if !r.MimeDone {
|
|
_, ok := r.BotMap[r.BlueTeam.Mime]
|
|
if ok {
|
|
return r.BlueTeam.Mime
|
|
}
|
|
} else {
|
|
return getGuesser(r.BotMap, UserTeamBlue)
|
|
}
|
|
case UserTeamRed:
|
|
if !r.MimeDone {
|
|
_, ok := r.BotMap[r.RedTeam.Mime]
|
|
if ok {
|
|
return r.RedTeam.Mime
|
|
}
|
|
} else {
|
|
return getGuesser(r.BotMap, UserTeamRed)
|
|
}
|
|
default:
|
|
// how did we got here?
|
|
return ""
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (r *Room) GetOppositeTeamColor() UserTeam {
|
|
switch r.TeamTurn {
|
|
case "red":
|
|
return UserTeamBlue
|
|
case "blue":
|
|
return UserTeamRed
|
|
}
|
|
return UserTeamNone
|
|
}
|
|
|
|
func (r *Room) UpdateCounter() {
|
|
redCounter := uint8(0)
|
|
blueCounter := uint8(0)
|
|
for _, card := range r.Cards {
|
|
if card.Revealed {
|
|
continue
|
|
}
|
|
switch card.Color {
|
|
case WordColorRed:
|
|
redCounter++
|
|
case WordColorBlue:
|
|
blueCounter++
|
|
}
|
|
}
|
|
r.RedCounter = redCounter
|
|
r.BlueCounter = blueCounter
|
|
}
|
|
|
|
func (r *Room) ChangeTurn() {
|
|
switch r.TeamTurn {
|
|
case "blue":
|
|
r.TeamTurn = "red"
|
|
case "red":
|
|
r.TeamTurn = "blue"
|
|
default:
|
|
r.TeamTurn = "blue"
|
|
}
|
|
}
|
|
|
|
func (r *Room) RevealAllCards() {
|
|
for i := range r.Cards {
|
|
r.Cards[i].Revealed = true
|
|
}
|
|
}
|
|
|
|
func (r *Room) RevealSpecificWord(word string) {
|
|
for i, card := range r.Cards {
|
|
if card.Word == word {
|
|
r.Cards[i].Revealed = true
|
|
}
|
|
}
|
|
}
|
|
|
|
type WordCard struct {
|
|
Word string `json:"word"`
|
|
Color WordColor `json:"color"`
|
|
Revealed bool `json:"revealed"`
|
|
}
|
|
|
|
type GameSettings struct {
|
|
IsRunning bool `json:"is_running"`
|
|
Language string `json:"language" example:"en" form:"language"`
|
|
RoundTime int32 `json:"round_time"`
|
|
ProgressPct uint32 `json:"progress_pct"`
|
|
IsOver bool
|
|
}
|
|
|
|
// =====
|
|
|
|
type RoomReq struct {
|
|
// is not user or not unique
|
|
RoomPass string `json:"room_pass" form:"room_pass"`
|
|
RoomName string `json:"room_name" form:"room_name"`
|
|
// GameSettings
|
|
}
|
|
|
|
func (rr *RoomReq) CreateRoom(creator string) *Room {
|
|
roomID := xid.New().String()
|
|
return &Room{
|
|
// RoomName: ,
|
|
RoomPass: rr.RoomPass,
|
|
ID: roomID,
|
|
CreatedAt: time.Now(),
|
|
// PlayerList: []string{creator},
|
|
CreatorName: creator,
|
|
BotMap: make(map[string]BotPlayer),
|
|
}
|
|
}
|
|
|
|
// ====
|
|
|
|
type FullInfo struct {
|
|
State *UserState
|
|
Room *Room
|
|
List []*Room
|
|
LinkLogin string // room_id
|
|
}
|
|
|
|
func (f *FullInfo) ExitRoom() *Room {
|
|
// f.Room.PlayerList = utils.RemoveFromSlice(f.State.Username, f.Room.PlayerList)
|
|
f.Room.RedTeam.Guessers = utils.RemoveFromSlice(f.State.Username, f.Room.RedTeam.Guessers)
|
|
f.Room.BlueTeam.Guessers = utils.RemoveFromSlice(f.State.Username, f.Room.BlueTeam.Guessers)
|
|
if f.Room.RedTeam.Mime == f.State.Username {
|
|
f.Room.RedTeam.Mime = ""
|
|
}
|
|
if f.Room.BlueTeam.Mime == f.State.Username {
|
|
f.Room.BlueTeam.Mime = ""
|
|
}
|
|
f.State.ExitRoom()
|
|
resp := f.Room
|
|
f.Room = nil
|
|
return resp
|
|
}
|