diff --git a/client/nuxt.config.js b/client/nuxt.config.js
index b1dc13d..21abfbe 100644
--- a/client/nuxt.config.js
+++ b/client/nuxt.config.js
@@ -22,7 +22,10 @@ export default {
],
components: true,
modules: ['@nuxtjs/axios'],
- plugins: [{ src: '~/plugins/engine', mode: 'client' }],
+ plugins: [
+ { src: '~/plugins/engine', mode: 'client' },
+ { src: '~/plugins/formatter', mode: 'client' },
+ ],
axios: { proxy: true },
publicRuntimeConfig: {
serverBaseUrl: '/',
diff --git a/client/src/components/admin/AdminTileGameinfo.vue b/client/src/components/admin/AdminTileGameinfo.vue
index 060919d..6527544 100644
--- a/client/src/components/admin/AdminTileGameinfo.vue
+++ b/client/src/components/admin/AdminTileGameinfo.vue
@@ -6,6 +6,10 @@
@@ -55,7 +55,19 @@ export default {
this.$emit('reload')
this.isReloading = true
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 '-'
+ },
},
}
diff --git a/client/src/plugins/formatter.js b/client/src/plugins/formatter.js
new file mode 100644
index 0000000..e63d837
--- /dev/null
+++ b/client/src/plugins/formatter.js
@@ -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,
+ })
+}
diff --git a/server/src/application/getGameInfo.go b/server/src/application/getGameInfo.go
index b4a6243..1dfee15 100644
--- a/server/src/application/getGameInfo.go
+++ b/server/src/application/getGameInfo.go
@@ -31,6 +31,8 @@ func (app *Application) GetGameInfo(usr *user.User, w http.ResponseWriter, r *ht
return
} else {
gameInfo.Players[i].AuthCode = playerUser.GetAuthCode()
+ gameInfo.Players[i].Created = playerUser.GetCreated()
+ gameInfo.Players[i].LastLoggedIn = playerUser.GetLastLoggedIn()
}
}
diff --git a/server/src/application/syncHandler.go b/server/src/application/syncHandler.go
index d7f20b1..471f483 100644
--- a/server/src/application/syncHandler.go
+++ b/server/src/application/syncHandler.go
@@ -21,6 +21,9 @@ func (app *Application) SyncHandler(usr *user.User, w http.ResponseWriter, r *ht
return
}
+ usr.UpdateHeartbeat()
+ usr.SaveUser()
+
app.updatePlayerIsConnected(usr)
eng := gm.GetEngine()
eng.SyncHandler(w, r)
diff --git a/server/src/game/game.go b/server/src/game/game.go
index e2b8724..150ce6e 100644
--- a/server/src/game/game.go
+++ b/server/src/game/game.go
@@ -6,6 +6,7 @@ import (
"os"
"sirlab.de/go/knowyt/engine"
"sirlab.de/go/knowyt/quote"
+ "time"
)
func NewGameFromFile(id, fileName string) (*Game, error) {
@@ -22,6 +23,7 @@ func NewGameFromFile(id, fileName string) (*Game, error) {
id: id,
filename: fileName,
name: gmJson.Name,
+ created: gmJson.Created,
eng: engine.NewEngine(),
players: make(map[string]playerInfo, 0),
state: STATE_IDLE,
@@ -40,6 +42,7 @@ func NewGame(id, fileName, name string) (*Game, error) {
eng: engine.NewEngine(),
players: make(map[string]playerInfo, 0),
state: STATE_IDLE,
+ created: time.Now().Unix(),
quotes: make(map[string]*quote.Quote, 0),
}
@@ -51,7 +54,8 @@ func (gm *Game) SaveGame() error {
defer gm.mu.Unlock()
gmJson := GameJson{
- Name: gm.name,
+ Name: gm.name,
+ Created: gm.created,
}
if jsonBytes, err := json.Marshal(gmJson); err != nil {
return err
diff --git a/server/src/game/getGameInfo.go b/server/src/game/getGameInfo.go
index 4281fb2..f9d25a0 100644
--- a/server/src/game/getGameInfo.go
+++ b/server/src/game/getGameInfo.go
@@ -18,6 +18,7 @@ func (gm *Game) initGameInfoJson() *GameInfoJson {
gameInfo := GameInfoJson{
Name: gm.name,
+ Created: gm.created,
State: gm.state,
Players: make([]PlayerInfoJson, 0),
NumQuotesLeft: numQuotesLeft,
@@ -26,12 +27,14 @@ func (gm *Game) initGameInfoJson() *GameInfoJson {
for _, player := range gm.players {
gameInfo.Players = append(gameInfo.Players, PlayerInfoJson{
- Id: player.id,
- Name: player.name,
- Score: player.score,
- IsPlaying: player.isPlaying,
- IsIdle: player.isIdle,
- Role: player.role,
+ Id: player.id,
+ Name: player.name,
+ Created: player.created,
+ LastLoggedIn: player.lastLoggedIn,
+ Score: player.score,
+ IsPlaying: player.isPlaying,
+ IsIdle: player.isIdle,
+ Role: player.role,
})
}
diff --git a/server/src/game/player.go b/server/src/game/player.go
index 1330c87..1deaaf5 100644
--- a/server/src/game/player.go
+++ b/server/src/game/player.go
@@ -62,12 +62,14 @@ func (gm *Game) AddPlayer(usr *user.User) {
}
gm.players[usrId] = playerInfo{
- id: usrId,
- name: usr.GetName(),
- isPlaying: false,
- isIdle: true,
- score: 0,
- role: usr.GetRole(),
+ id: usrId,
+ name: usr.GetName(),
+ created: usr.GetCreated(),
+ lastLoggedIn: usr.GetLastLoggedIn(),
+ isPlaying: false,
+ isIdle: true,
+ score: 0,
+ role: usr.GetRole(),
}
}
@@ -83,6 +85,8 @@ func (gm *Game) UpdatePlayer(usr *user.User) {
}
player.name = usr.GetName()
+ player.created = usr.GetCreated()
+ player.lastLoggedIn = usr.GetLastLoggedIn()
gm.players[usrId] = player
}
diff --git a/server/src/game/struct.go b/server/src/game/struct.go
index a8d1549..396d39d 100644
--- a/server/src/game/struct.go
+++ b/server/src/game/struct.go
@@ -30,12 +30,14 @@ const (
)
type playerInfo struct {
- id string
- name string
- isPlaying bool
- isIdle bool
- score int
- role string
+ id string
+ name string
+ created int64
+ lastLoggedIn int64
+ isPlaying bool
+ isIdle bool
+ score int
+ role string
}
type Source struct {
@@ -60,6 +62,7 @@ type Game struct {
id string
filename string
name string
+ created int64
players map[string]playerInfo
eng *engine.Engine
state string
@@ -69,7 +72,8 @@ type Game struct {
}
type GameJson struct {
- Name string `json:"name"`
+ Name string `json:"name"`
+ Created int64 `json:"created"`
}
type Quote struct {
@@ -84,6 +88,8 @@ type QuotesInfo struct {
type PlayerInfoJson struct {
Id string `json:"id"`
Name string `json:"name"`
+ Created int64 `json:"created"`
+ LastLoggedIn int64 `json:"lastLoggedIn"`
Score int `json:"score"`
IsPlaying bool `json:"isPlaying"`
IsIdle bool `json:"isIdle"`
@@ -94,6 +100,7 @@ type PlayerInfoJson struct {
type GameInfoJson struct {
Name string `json:"name"`
+ Created int64 `json:"created"`
State string `json:"state"`
Players []PlayerInfoJson `json:"players"`
NumQuotesLeft int `json:"numQuotesLeft"`
diff --git a/server/src/user/struct.go b/server/src/user/struct.go
index 55e42b8..a88d602 100644
--- a/server/src/user/struct.go
+++ b/server/src/user/struct.go
@@ -11,21 +11,25 @@ const (
)
type User struct {
- mu sync.Mutex
- id string
- filename string
- authcode string
- name string
- role string
- gameId string
- cameo *User
+ mu sync.Mutex
+ id string
+ filename string
+ authcode string
+ name string
+ role string
+ gameId string
+ created int64
+ lastLoggedIn int64
+ cameo *User
}
type UserJson struct {
- Authcode string `json:"authcode"`
- Name string `json:"name"`
- Role string `json:"role"`
- GameId string `json:"game"`
+ Authcode string `json:"authcode"`
+ Name string `json:"name"`
+ Role string `json:"role"`
+ GameId string `json:"game"`
+ Created int64 `json:"created"`
+ LastLoggedIn int64 `json:"lastLoggedIn"`
}
type UserinfoJson struct {
diff --git a/server/src/user/user.go b/server/src/user/user.go
index 9be7d25..3548e31 100644
--- a/server/src/user/user.go
+++ b/server/src/user/user.go
@@ -6,6 +6,7 @@ import (
"os"
"path"
"strings"
+ "time"
)
func NewUserFromFile(fileName string) (*User, error) {
@@ -22,12 +23,14 @@ func NewUserFromFile(fileName string) (*User, error) {
_, fileNameShort := path.Split(fileName)
id := strings.TrimSuffix(fileNameShort, ".json")
return &User{
- id: id,
- name: userJson.Name,
- filename: fileName,
- role: userJson.Role,
- authcode: userJson.Authcode,
- gameId: userJson.GameId,
+ id: id,
+ name: userJson.Name,
+ filename: fileName,
+ role: userJson.Role,
+ authcode: userJson.Authcode,
+ gameId: userJson.GameId,
+ lastLoggedIn: userJson.LastLoggedIn,
+ created: userJson.Created,
}, nil
}
}
@@ -36,9 +39,11 @@ func CreateUser(fileName, gameId string) *User {
_, fileNameShort := path.Split(fileName)
id := strings.TrimSuffix(fileNameShort, ".json")
return &User{
- id: id,
- filename: fileName,
- gameId: gameId,
+ id: id,
+ filename: fileName,
+ gameId: gameId,
+ lastLoggedIn: 0,
+ created: time.Now().Unix(),
}
}
@@ -47,10 +52,12 @@ func (usr *User) SaveUser() error {
defer usr.mu.Unlock()
userJson := UserJson{
- Name: usr.name,
- Authcode: usr.authcode,
- Role: usr.role,
- GameId: usr.gameId,
+ Name: usr.name,
+ Authcode: usr.authcode,
+ Role: usr.role,
+ GameId: usr.gameId,
+ Created: usr.created,
+ LastLoggedIn: usr.lastLoggedIn,
}
if jsonBytes, err := json.Marshal(userJson); err != nil {
return err
@@ -153,3 +160,15 @@ func (usr *User) GetCameo() *User {
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()
+}
|