test a vote for someone saying themself
parent
354d07d6bf
commit
1738ce7d19
|
|
@ -157,16 +157,14 @@ func (v01 *V01) serveGM(w http.ResponseWriter, r *http.Request) {
|
||||||
case "/gm/rpc/vote":
|
case "/gm/rpc/vote":
|
||||||
v01.serveGMVote(w, r)
|
v01.serveGMVote(w, r)
|
||||||
case "/gm/rpc/elect":
|
case "/gm/rpc/elect":
|
||||||
panic("TODO swap or shuffle")
|
v01.serveGMElect(w, r)
|
||||||
case "/gm/rpc/shuffle":
|
case "/gm/rpc/shuffle":
|
||||||
v01.serveGMShuffle(w, r)
|
v01.serveGMShuffle(r)
|
||||||
v01.cfg.Quiet = false
|
|
||||||
case "/gm/rpc/swap":
|
case "/gm/rpc/swap":
|
||||||
if errCode, err := v01.serveGMSwap(r, r.URL.Query().Get("a"), r.URL.Query().Get("b")); err != nil {
|
if errCode, err := v01.serveGMSwap(r.URL.Query().Get("a"), r.URL.Query().Get("b")); err != nil {
|
||||||
http.Error(w, err.Error(), errCode)
|
http.Error(w, err.Error(), errCode)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v01.cfg.Quiet = false
|
|
||||||
default:
|
default:
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
}
|
}
|
||||||
|
|
@ -235,12 +233,35 @@ func (v01 *V01) serveGMFillNonPlayerAliases(w http.ResponseWriter, r *http.Reque
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v01 *V01) serveGMElect(w http.ResponseWriter, r *http.Request) {
|
||||||
|
alias := r.URL.Query().Get("alias")
|
||||||
|
votes := map[string]int{}
|
||||||
|
for _, v := range v01.cfg.Users {
|
||||||
|
if v2 := strings.Split(v.Message, "//"); len(v2) > 1 {
|
||||||
|
votes[v2[1]] = votes[v2[1]] + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
threshold := 0.1 + float64(len(votes))/2.0
|
||||||
|
winner := ""
|
||||||
|
for k, v := range votes {
|
||||||
|
if float64(v) > threshold {
|
||||||
|
winner = k
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if winner == "" {
|
||||||
|
v01.serveGMShuffle(r)
|
||||||
|
} else if _, err := v01.serveGMSwap(winner, alias); err != nil {
|
||||||
|
v01.serveGMShuffle(r)
|
||||||
|
}
|
||||||
|
yaml.NewEncoder(w).Encode(votes)
|
||||||
|
}
|
||||||
|
|
||||||
func (v01 *V01) serveGMVote(w http.ResponseWriter, r *http.Request) {
|
func (v01 *V01) serveGMVote(w http.ResponseWriter, r *http.Request) {
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
counts := map[string]string{}
|
counts := map[string]string{}
|
||||||
for k, v := range v01.cfg.Users {
|
for k, v := range v01.cfg.Users {
|
||||||
if strings.HasPrefix(v.Alias, "//") {
|
if strings.Contains(v.Message, "//") {
|
||||||
counts[k] = "voted"
|
counts[k] = "voted"
|
||||||
} else {
|
} else {
|
||||||
counts[k] = "voting"
|
counts[k] = "voting"
|
||||||
|
|
@ -254,12 +275,12 @@ func (v01 *V01) serveGMVote(w http.ResponseWriter, r *http.Request) {
|
||||||
if _, ok2 := v01.cfg.Users[candidate]; !ok || !ok2 {
|
if _, ok2 := v01.cfg.Users[candidate]; !ok || !ok2 {
|
||||||
http.Error(w, "bad voter/candidate", http.StatusBadRequest)
|
http.Error(w, "bad voter/candidate", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
v.Alias = "//" + candidate
|
v.Message = strings.Split(v.Message, "//")[0] + "//" + candidate
|
||||||
v01.cfg.Users[voter] = v
|
v01.cfg.Users[voter] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v01 *V01) serveGMShuffle(w http.ResponseWriter, r *http.Request) {
|
func (v01 *V01) serveGMShuffle(r *http.Request) {
|
||||||
poolSize := len(v01.cfg.Users)
|
poolSize := len(v01.cfg.Users)
|
||||||
if altSize := len(v01.cfg.Players); altSize > poolSize {
|
if altSize := len(v01.cfg.Players); altSize > poolSize {
|
||||||
poolSize = altSize
|
poolSize = altSize
|
||||||
|
|
@ -286,12 +307,13 @@ func (v01 *V01) serveGMShuffle(w http.ResponseWriter, r *http.Request) {
|
||||||
i += 1
|
i += 1
|
||||||
}
|
}
|
||||||
v01.servePutBroadcastValue(strings.Join(msg, ", "))
|
v01.servePutBroadcastValue(strings.Join(msg, ", "))
|
||||||
|
v01.cfg.Quiet = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v01 *V01) serveGMSwap(r *http.Request, nameA, nameB string) (int, error) {
|
func (v01 *V01) serveGMSwap(nameA, nameB string) (int, error) {
|
||||||
getUserNameFor := func(like string) string {
|
getUserNameFor := func(like string) string {
|
||||||
for k, v := range v01.cfg.Users {
|
for k, v := range v01.cfg.Users {
|
||||||
if k == like || v.Alias == like {
|
if k == like || v.Alias == like || (strings.Contains(v.Message, "//") && strings.Split(v.Message, "//")[0] == like) {
|
||||||
return k
|
return k
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -310,5 +332,7 @@ func (v01 *V01) serveGMSwap(r *http.Request, nameA, nameB string) (int, error) {
|
||||||
a.Player, b.Player = b.Player, a.Player
|
a.Player, b.Player = b.Player, a.Player
|
||||||
v01.cfg.Users[userA] = a
|
v01.cfg.Users[userA] = a
|
||||||
v01.cfg.Users[userB] = b
|
v01.cfg.Users[userB] = b
|
||||||
|
v01.cfg.Quiet = false
|
||||||
|
v01.servePutBroadcastValue(fmt.Sprintf(`%s is now player %v and %s is now player %v`, userA, a.Player, userB, b.Player))
|
||||||
return http.StatusOK, nil
|
return http.StatusOK, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -241,6 +241,10 @@ func TestServeGM(t *testing.T) {
|
||||||
t.Run("vote", func(t *testing.T) {
|
t.Run("vote", func(t *testing.T) {
|
||||||
type result map[string]string
|
type result map[string]string
|
||||||
|
|
||||||
|
t.Run("cast vote", func(t *testing.T) {
|
||||||
|
t.Error("not impl")
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("get non vote", func(t *testing.T) {
|
t.Run("get non vote", func(t *testing.T) {
|
||||||
v01 := NewV01(ctx, nil)
|
v01 := NewV01(ctx, nil)
|
||||||
v01.cfg.Users = map[string]configUser{"bel": {}}
|
v01.cfg.Users = map[string]configUser{"bel": {}}
|
||||||
|
|
@ -260,7 +264,7 @@ func TestServeGM(t *testing.T) {
|
||||||
|
|
||||||
t.Run("get mid vote", func(t *testing.T) {
|
t.Run("get mid vote", func(t *testing.T) {
|
||||||
v01 := NewV01(ctx, nil)
|
v01 := NewV01(ctx, nil)
|
||||||
v01.cfg.Users = map[string]configUser{"bel": {Alias: "//zach"}}
|
v01.cfg.Users = map[string]configUser{"bel": {Message: "driver//zach"}}
|
||||||
resp := do(v01, "/gm/rpc/vote", "", "GET")
|
resp := do(v01, "/gm/rpc/vote", "", "GET")
|
||||||
var result result
|
var result result
|
||||||
if err := yaml.Unmarshal(resp.Body.Bytes(), &result); err != nil {
|
if err := yaml.Unmarshal(resp.Body.Bytes(), &result); err != nil {
|
||||||
|
|
@ -291,7 +295,107 @@ func TestServeGM(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("elect", func(t *testing.T) {
|
t.Run("elect", func(t *testing.T) {
|
||||||
t.Error("not impl")
|
type result map[string]int
|
||||||
|
|
||||||
|
t.Run("happy", func(t *testing.T) {
|
||||||
|
v01 := NewV01(ctx, nil)
|
||||||
|
v01.cfg.Users = map[string]configUser{
|
||||||
|
"bel": configUser{Message: "driver//zach", Player: 1},
|
||||||
|
"zach": configUser{Message: "pizza//bel"},
|
||||||
|
"bill": configUser{Message: "//bel", Player: 2},
|
||||||
|
}
|
||||||
|
resp := do(v01, "/gm/rpc/elect?alias=pizza", "")
|
||||||
|
var result result
|
||||||
|
if err := yaml.Unmarshal(resp.Body.Bytes(), &result); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if len(result) != 2 {
|
||||||
|
t.Error(result)
|
||||||
|
} else if result["bel"] != 2 {
|
||||||
|
t.Error(result)
|
||||||
|
} else if result["zach"] != 1 {
|
||||||
|
t.Error(result)
|
||||||
|
}
|
||||||
|
if v01.cfg.Users["bel"].Player != 0 {
|
||||||
|
t.Error(v01.cfg.Users["bel"].Player)
|
||||||
|
} else if v01.cfg.Users["zach"].Player != 1 {
|
||||||
|
t.Error(v01.cfg.Users["zach"].Player)
|
||||||
|
}
|
||||||
|
if v01.cfg.Users["broadcast"].Message != `bel is now player 0 and zach is now player 1` {
|
||||||
|
t.Error(v01.cfg.Users["broadcast"].Message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("self", func(t *testing.T) {
|
||||||
|
v01 := NewV01(ctx, nil)
|
||||||
|
v01.cfg.Players = []configPlayer{{}}
|
||||||
|
v01.cfg.Users = map[string]configUser{
|
||||||
|
"bel": configUser{Message: "driver//zach", Player: 1},
|
||||||
|
"zach": configUser{Message: "//bel"},
|
||||||
|
"bill": configUser{Message: "//bel"},
|
||||||
|
}
|
||||||
|
resp := do(v01, "/gm/rpc/elect?alias=driver", "")
|
||||||
|
var result result
|
||||||
|
if err := yaml.Unmarshal(resp.Body.Bytes(), &result); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if len(result) != 2 {
|
||||||
|
t.Error(result)
|
||||||
|
} else if result["bel"] != 2 {
|
||||||
|
t.Error(result)
|
||||||
|
} else if result["zach"] != 1 {
|
||||||
|
t.Error(result)
|
||||||
|
}
|
||||||
|
if !strings.HasSuffix(v01.cfg.Users["broadcast"].Message, `is now player 1`) || strings.Contains(v01.cfg.Users["broadcast"].Message, ",") {
|
||||||
|
t.Error(v01.cfg.Users["broadcast"].Message)
|
||||||
|
}
|
||||||
|
assignments := map[int]int{}
|
||||||
|
for _, v := range v01.cfg.Users {
|
||||||
|
assignments[v.Player] = assignments[v.Player] + 1
|
||||||
|
}
|
||||||
|
if len(assignments) != 2 {
|
||||||
|
t.Error(assignments)
|
||||||
|
} else if assignments[0] != 3 {
|
||||||
|
t.Error(assignments[0])
|
||||||
|
} else if assignments[1] != 1 {
|
||||||
|
t.Error(assignments[1])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("tie", func(t *testing.T) {
|
||||||
|
v01 := NewV01(ctx, nil)
|
||||||
|
v01.cfg.Players = []configPlayer{{}}
|
||||||
|
v01.cfg.Users = map[string]configUser{
|
||||||
|
"bel": configUser{Message: "driver//zach", Player: 1},
|
||||||
|
"zach": configUser{Message: "pizza//bel"},
|
||||||
|
}
|
||||||
|
resp := do(v01, "/gm/rpc/elect?alias=pizza", "")
|
||||||
|
var result result
|
||||||
|
if err := yaml.Unmarshal(resp.Body.Bytes(), &result); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if len(result) != 2 {
|
||||||
|
t.Error(result)
|
||||||
|
} else if result["bel"] != 1 {
|
||||||
|
t.Error(result)
|
||||||
|
} else if result["zach"] != 1 {
|
||||||
|
t.Error(result)
|
||||||
|
}
|
||||||
|
if !strings.HasSuffix(v01.cfg.Users["broadcast"].Message, `is now player 1`) || strings.Contains(v01.cfg.Users["broadcast"].Message, ",") {
|
||||||
|
t.Error(v01.cfg.Users["broadcast"].Message)
|
||||||
|
}
|
||||||
|
assignments := map[int]int{}
|
||||||
|
for _, v := range v01.cfg.Users {
|
||||||
|
assignments[v.Player] = assignments[v.Player] + 1
|
||||||
|
}
|
||||||
|
if len(assignments) != 2 {
|
||||||
|
t.Error(assignments)
|
||||||
|
} else if assignments[0] != 2 {
|
||||||
|
t.Error(assignments[0])
|
||||||
|
} else if assignments[1] != 1 {
|
||||||
|
t.Error(assignments[1])
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("shuffle", func(t *testing.T) {
|
t.Run("shuffle", func(t *testing.T) {
|
||||||
|
|
@ -367,10 +471,10 @@ func TestServeGM(t *testing.T) {
|
||||||
t.Error(i)
|
t.Error(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assignments := map[int]struct{}{}
|
assignments := map[int]int{}
|
||||||
for _, v := range v01.cfg.Users {
|
for _, v := range v01.cfg.Users {
|
||||||
if v.Player > 0 {
|
if v.Player > 0 {
|
||||||
assignments[v.Player] = struct{}{}
|
assignments[v.Player] = assignments[v.Player] + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lesser := c.users
|
lesser := c.users
|
||||||
|
|
@ -380,6 +484,11 @@ func TestServeGM(t *testing.T) {
|
||||||
if len(assignments) != lesser {
|
if len(assignments) != lesser {
|
||||||
t.Error(assignments)
|
t.Error(assignments)
|
||||||
}
|
}
|
||||||
|
for _, v := range assignments {
|
||||||
|
if v != 1 {
|
||||||
|
t.Error(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue