feat: user last logged in/created

This commit is contained in:
Settel 2022-04-12 14:16:03 +02:00
parent 4fc4730e34
commit 6305c7beda
12 changed files with 141 additions and 49 deletions

View File

@ -22,7 +22,10 @@ export default {
], ],
components: true, components: true,
modules: ['@nuxtjs/axios'], modules: ['@nuxtjs/axios'],
plugins: [{ src: '~/plugins/engine', mode: 'client' }], plugins: [
{ src: '~/plugins/engine', mode: 'client' },
{ src: '~/plugins/formatter', mode: 'client' },
],
axios: { proxy: true }, axios: { proxy: true },
publicRuntimeConfig: { publicRuntimeConfig: {
serverBaseUrl: '/', serverBaseUrl: '/',

View File

@ -6,6 +6,10 @@
<td>{{ gameinfo.name }}</td> <td>{{ gameinfo.name }}</td>
<td><div class="admin-tile-gameinfo__edit-game-name" @click="editName()"></div></td> <td><div class="admin-tile-gameinfo__edit-game-name" @click="editName()"></div></td>
</tr> </tr>
<tr>
<td>Created:</td>
<td colspan="2">{{ $formatter.date(gameinfo.created) }}</td>
</tr>
<tr> <tr>
<td># Players:</td> <td># Players:</td>
<td colspan="2">{{ players.length }}</td> <td colspan="2">{{ players.length }}</td>

View File

@ -22,10 +22,10 @@
v-for="player in players" v-for="player in players"
:key="player.id" :key="player.id"
> >
<td>{{ player.name }}</td> <td>{{ player.name }}{{ player.role === 'gamemaster' ? ' 👑' : '' }}</td>
<td>{{ player.numQuotes }}</td> <td>{{ player.numQuotes }}</td>
<td>{{ player.score }}</td> <td>{{ player.score }}</td>
<td>{{ player.isPlaying ? (player.isIdle ? 'idle' : 'active') : '-'}}</td> <td>{{ getPlayerStatus(player) }}</td>
</tr> </tr>
<tr> <tr>
<td colspan="4"> <td colspan="4">
@ -55,7 +55,19 @@ export default {
this.$emit('reload') this.$emit('reload')
this.isReloading = true this.isReloading = true
setTimeout(() => { this.isReloading = false }, 500) setTimeout(() => { this.isReloading = false }, 500)
} },
getPlayerStatus(player) {
if (player.isPlaying && !player.isIdle) {
return 'active'
} else {
if (player.lastLoggedIn) {
return this.$formatter.datetime(player.lastLoggedIn)
} else if (player.isPlaying) {
return 'idle'
}
}
return '-'
},
}, },
} }
</script> </script>

View File

@ -0,0 +1,27 @@
export default (context, inject) => {
const leftPad2Digits = (val) => val < 10 ? '0' + val : '' + val
const date = (time) => {
if (!time) return
const d = new Date(time * 1000)
return `${1900 + d.getYear()}-` +
`${leftPad2Digits(d.getMonth() + 1)}-` +
`${leftPad2Digits(d.getDate())}`
}
const datetime = (time) => {
if (!time) return
const d = new Date(time * 1000)
return `${date(time)}, ` +
`${leftPad2Digits(d.getHours())}:` +
`${leftPad2Digits(d.getMinutes())}:` +
`${leftPad2Digits(d.getSeconds())}`
}
inject('formatter', {
date,
datetime,
})
}

View File

@ -31,6 +31,8 @@ func (app *Application) GetGameInfo(usr *user.User, w http.ResponseWriter, r *ht
return return
} else { } else {
gameInfo.Players[i].AuthCode = playerUser.GetAuthCode() gameInfo.Players[i].AuthCode = playerUser.GetAuthCode()
gameInfo.Players[i].Created = playerUser.GetCreated()
gameInfo.Players[i].LastLoggedIn = playerUser.GetLastLoggedIn()
} }
} }

View File

@ -21,6 +21,9 @@ func (app *Application) SyncHandler(usr *user.User, w http.ResponseWriter, r *ht
return return
} }
usr.UpdateHeartbeat()
usr.SaveUser()
app.updatePlayerIsConnected(usr) app.updatePlayerIsConnected(usr)
eng := gm.GetEngine() eng := gm.GetEngine()
eng.SyncHandler(w, r) eng.SyncHandler(w, r)

View File

@ -6,6 +6,7 @@ import (
"os" "os"
"sirlab.de/go/knowyt/engine" "sirlab.de/go/knowyt/engine"
"sirlab.de/go/knowyt/quote" "sirlab.de/go/knowyt/quote"
"time"
) )
func NewGameFromFile(id, fileName string) (*Game, error) { func NewGameFromFile(id, fileName string) (*Game, error) {
@ -22,6 +23,7 @@ func NewGameFromFile(id, fileName string) (*Game, error) {
id: id, id: id,
filename: fileName, filename: fileName,
name: gmJson.Name, name: gmJson.Name,
created: gmJson.Created,
eng: engine.NewEngine(), eng: engine.NewEngine(),
players: make(map[string]playerInfo, 0), players: make(map[string]playerInfo, 0),
state: STATE_IDLE, state: STATE_IDLE,
@ -40,6 +42,7 @@ func NewGame(id, fileName, name string) (*Game, error) {
eng: engine.NewEngine(), eng: engine.NewEngine(),
players: make(map[string]playerInfo, 0), players: make(map[string]playerInfo, 0),
state: STATE_IDLE, state: STATE_IDLE,
created: time.Now().Unix(),
quotes: make(map[string]*quote.Quote, 0), quotes: make(map[string]*quote.Quote, 0),
} }
@ -51,7 +54,8 @@ func (gm *Game) SaveGame() error {
defer gm.mu.Unlock() defer gm.mu.Unlock()
gmJson := GameJson{ gmJson := GameJson{
Name: gm.name, Name: gm.name,
Created: gm.created,
} }
if jsonBytes, err := json.Marshal(gmJson); err != nil { if jsonBytes, err := json.Marshal(gmJson); err != nil {
return err return err

View File

@ -18,6 +18,7 @@ func (gm *Game) initGameInfoJson() *GameInfoJson {
gameInfo := GameInfoJson{ gameInfo := GameInfoJson{
Name: gm.name, Name: gm.name,
Created: gm.created,
State: gm.state, State: gm.state,
Players: make([]PlayerInfoJson, 0), Players: make([]PlayerInfoJson, 0),
NumQuotesLeft: numQuotesLeft, NumQuotesLeft: numQuotesLeft,
@ -26,12 +27,14 @@ func (gm *Game) initGameInfoJson() *GameInfoJson {
for _, player := range gm.players { for _, player := range gm.players {
gameInfo.Players = append(gameInfo.Players, PlayerInfoJson{ gameInfo.Players = append(gameInfo.Players, PlayerInfoJson{
Id: player.id, Id: player.id,
Name: player.name, Name: player.name,
Score: player.score, Created: player.created,
IsPlaying: player.isPlaying, LastLoggedIn: player.lastLoggedIn,
IsIdle: player.isIdle, Score: player.score,
Role: player.role, IsPlaying: player.isPlaying,
IsIdle: player.isIdle,
Role: player.role,
}) })
} }

View File

@ -62,12 +62,14 @@ func (gm *Game) AddPlayer(usr *user.User) {
} }
gm.players[usrId] = playerInfo{ gm.players[usrId] = playerInfo{
id: usrId, id: usrId,
name: usr.GetName(), name: usr.GetName(),
isPlaying: false, created: usr.GetCreated(),
isIdle: true, lastLoggedIn: usr.GetLastLoggedIn(),
score: 0, isPlaying: false,
role: usr.GetRole(), isIdle: true,
score: 0,
role: usr.GetRole(),
} }
} }
@ -83,6 +85,8 @@ func (gm *Game) UpdatePlayer(usr *user.User) {
} }
player.name = usr.GetName() player.name = usr.GetName()
player.created = usr.GetCreated()
player.lastLoggedIn = usr.GetLastLoggedIn()
gm.players[usrId] = player gm.players[usrId] = player
} }

View File

@ -30,12 +30,14 @@ const (
) )
type playerInfo struct { type playerInfo struct {
id string id string
name string name string
isPlaying bool created int64
isIdle bool lastLoggedIn int64
score int isPlaying bool
role string isIdle bool
score int
role string
} }
type Source struct { type Source struct {
@ -60,6 +62,7 @@ type Game struct {
id string id string
filename string filename string
name string name string
created int64
players map[string]playerInfo players map[string]playerInfo
eng *engine.Engine eng *engine.Engine
state string state string
@ -69,7 +72,8 @@ type Game struct {
} }
type GameJson struct { type GameJson struct {
Name string `json:"name"` Name string `json:"name"`
Created int64 `json:"created"`
} }
type Quote struct { type Quote struct {
@ -84,6 +88,8 @@ type QuotesInfo struct {
type PlayerInfoJson struct { type PlayerInfoJson struct {
Id string `json:"id"` Id string `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Created int64 `json:"created"`
LastLoggedIn int64 `json:"lastLoggedIn"`
Score int `json:"score"` Score int `json:"score"`
IsPlaying bool `json:"isPlaying"` IsPlaying bool `json:"isPlaying"`
IsIdle bool `json:"isIdle"` IsIdle bool `json:"isIdle"`
@ -94,6 +100,7 @@ type PlayerInfoJson struct {
type GameInfoJson struct { type GameInfoJson struct {
Name string `json:"name"` Name string `json:"name"`
Created int64 `json:"created"`
State string `json:"state"` State string `json:"state"`
Players []PlayerInfoJson `json:"players"` Players []PlayerInfoJson `json:"players"`
NumQuotesLeft int `json:"numQuotesLeft"` NumQuotesLeft int `json:"numQuotesLeft"`

View File

@ -11,21 +11,25 @@ const (
) )
type User struct { type User struct {
mu sync.Mutex mu sync.Mutex
id string id string
filename string filename string
authcode string authcode string
name string name string
role string role string
gameId string gameId string
cameo *User created int64
lastLoggedIn int64
cameo *User
} }
type UserJson struct { type UserJson struct {
Authcode string `json:"authcode"` Authcode string `json:"authcode"`
Name string `json:"name"` Name string `json:"name"`
Role string `json:"role"` Role string `json:"role"`
GameId string `json:"game"` GameId string `json:"game"`
Created int64 `json:"created"`
LastLoggedIn int64 `json:"lastLoggedIn"`
} }
type UserinfoJson struct { type UserinfoJson struct {

View File

@ -6,6 +6,7 @@ import (
"os" "os"
"path" "path"
"strings" "strings"
"time"
) )
func NewUserFromFile(fileName string) (*User, error) { func NewUserFromFile(fileName string) (*User, error) {
@ -22,12 +23,14 @@ func NewUserFromFile(fileName string) (*User, error) {
_, fileNameShort := path.Split(fileName) _, fileNameShort := path.Split(fileName)
id := strings.TrimSuffix(fileNameShort, ".json") id := strings.TrimSuffix(fileNameShort, ".json")
return &User{ return &User{
id: id, id: id,
name: userJson.Name, name: userJson.Name,
filename: fileName, filename: fileName,
role: userJson.Role, role: userJson.Role,
authcode: userJson.Authcode, authcode: userJson.Authcode,
gameId: userJson.GameId, gameId: userJson.GameId,
lastLoggedIn: userJson.LastLoggedIn,
created: userJson.Created,
}, nil }, nil
} }
} }
@ -36,9 +39,11 @@ func CreateUser(fileName, gameId string) *User {
_, fileNameShort := path.Split(fileName) _, fileNameShort := path.Split(fileName)
id := strings.TrimSuffix(fileNameShort, ".json") id := strings.TrimSuffix(fileNameShort, ".json")
return &User{ return &User{
id: id, id: id,
filename: fileName, filename: fileName,
gameId: gameId, gameId: gameId,
lastLoggedIn: 0,
created: time.Now().Unix(),
} }
} }
@ -47,10 +52,12 @@ func (usr *User) SaveUser() error {
defer usr.mu.Unlock() defer usr.mu.Unlock()
userJson := UserJson{ userJson := UserJson{
Name: usr.name, Name: usr.name,
Authcode: usr.authcode, Authcode: usr.authcode,
Role: usr.role, Role: usr.role,
GameId: usr.gameId, GameId: usr.gameId,
Created: usr.created,
LastLoggedIn: usr.lastLoggedIn,
} }
if jsonBytes, err := json.Marshal(userJson); err != nil { if jsonBytes, err := json.Marshal(userJson); err != nil {
return err return err
@ -153,3 +160,15 @@ func (usr *User) GetCameo() *User {
return usr.cameo return usr.cameo
} }
func (usr *User) GetCreated() int64 {
return usr.created
}
func (usr *User) GetLastLoggedIn() int64 {
return usr.lastLoggedIn
}
func (usr *User) UpdateHeartbeat() {
usr.lastLoggedIn = time.Now().Unix()
}