ictgj-voting/model_votes.go

152 lines
3.4 KiB
Go

package main
import (
"errors"
"fmt"
"strconv"
"time"
)
// A Choice is a ranking of a game in a vote
type GameChoice struct {
Team string // UUID of team
Rank int
}
// A Vote is a collection of game rankings
type Vote struct {
Timestamp time.Time
ClientId string // UUID of client
Choices []GameChoice
mPath []string // The path in the DB to this team
}
func NewVote(clId string, tm time.Time) (*Vote, error) {
if clId == "" {
return nil, errors.New("Client ID is required")
}
if tm.IsZero() {
tm = time.Now()
}
vt := new(Vote)
vt.Timestamp = tm
vt.mPath = []string{"jam", "votes", clId, tm.Format(time.RFC3339)}
return vt, nil
}
func (vt *Vote) SetChoices(ch []string) error {
// Clear any previous choices from this vote
vt.Choices = []GameChoice{}
for i, v := range ch {
vt.Choices = append(vt.Choices, GameChoice{Rank: i, Team: v})
}
return nil
}
func (gj *Gamejam) GetVoteWithTimeString(clId, ts string) (*Vote, error) {
timestamp, err := time.Parse(time.RFC3339, ts)
if err != nil {
return nil, err
}
return gj.GetVote(clId, timestamp)
}
func (gj *Gamejam) GetVote(clId string, ts time.Time) (*Vote, error) {
for i := range gj.Votes {
if gj.Votes[i].ClientId == clId && gj.Votes[i].Timestamp == ts {
return &gj.Votes[i], nil
}
}
return nil, errors.New("Couldn't find requested vote")
}
func (gj *Gamejam) AddVote(vt *Vote) error {
// Make sure that this isn't a duplicate
if _, err := gj.GetVote(vt.ClientId, vt.Timestamp); err == nil {
return errors.New("Duplicate Vote")
}
gj.Votes = append(gj.Votes, *vt)
return nil
}
/**
* DB Functions
* These are generally just called when the app starts up or when the periodic 'save' runs
*/
// LoadAllVotes loads all votes for the jam out of the database
func (gj *Gamejam) LoadAllVotes() []Vote {
var err error
var ret []Vote
if err = gj.m.openDB(); err != nil {
return ret
}
defer gj.m.closeDB()
votesPath := []string{"jam", "votes"}
var cliUUIDs []string
if cliUUIDs, err = gj.m.bolt.GetBucketList(votesPath); err != nil {
return ret
}
for _, cId := range cliUUIDs {
vtsPth := append(votesPath, cId)
var times []string
if times, err = gj.m.bolt.GetBucketList(vtsPth); err != nil {
// Error reading this bucket, move on to the next
continue
}
for _, t := range times {
fmt.Println("Loading Vote", cId, t)
if vt, err := gj.LoadVote(cId, t); err == nil {
ret = append(ret, *vt)
}
}
}
return ret
}
// Load a vote from the DB and return it
func (gj *Gamejam) LoadVote(clientId, t string) (*Vote, error) {
var tm time.Time
var err error
if tm, err = time.Parse(time.RFC3339, t); err != nil {
return nil, errors.New("Error loading vote: " + err.Error())
}
vt, err := NewVote(clientId, tm)
if err != nil {
return nil, errors.New("Error creating vote: " + err.Error())
}
var choices []string
if choices, err = gj.m.bolt.GetKeyList(vt.mPath); err != nil {
return nil, errors.New("Error creating vote: " + err.Error())
}
for _, v := range choices {
ch := new(GameChoice)
var rank int
if rank, err = strconv.Atoi(v); err == nil {
ch.Rank = rank
if ch.Team, err = gj.m.bolt.GetValue(vt.mPath, v); err == nil {
vt.Choices = append(vt.Choices, *ch)
}
}
}
return vt, nil
}
func (gj *Gamejam) SaveVote(vt *Vote) error {
var err error
if err = gj.m.openDB(); err != nil {
return err
}
defer gj.m.closeDB()
for _, v := range vt.Choices {
m.bolt.SetValue(vt.mPath, strconv.Itoa(v.Rank), v.Team)
}
return nil
}