| // Copyright 2015 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Package internal defines common functions used by both rock paper scissors |
| // clients and servers. |
| package internal |
| |
| import ( |
| "bytes" |
| "errors" |
| "fmt" |
| "math/rand" |
| "os" |
| "os/user" |
| "time" |
| |
| "v.io/v23" |
| "v.io/v23/context" |
| "v.io/v23/naming" |
| "v.io/x/lib/vlog" |
| "v.io/x/ref/examples/rps" |
| ) |
| |
| // CreateName creates a name using the username and hostname. |
| func CreateName() string { |
| hostname, err := os.Hostname() |
| if err != nil { |
| vlog.Fatalf("os.Hostname failed: %v", err) |
| } |
| u, err := user.Current() |
| if err != nil { |
| vlog.Fatalf("user.Current failed: %v", err) |
| } |
| return u.Username + "@" + hostname |
| } |
| |
| // FindJudge returns a random rock-paper-scissors judge from the mount table. |
| func FindJudge(ctx *context.T) (string, error) { |
| judges, err := findAll(ctx, "judge") |
| if err != nil { |
| return "", err |
| } |
| if len(judges) > 0 { |
| return judges[rand.Intn(len(judges))], nil |
| } |
| return "", errors.New("no judges") |
| } |
| |
| // FindPlayer returns a random rock-paper-scissors player from the mount table. |
| func FindPlayer(ctx *context.T) (string, error) { |
| players, err := findAll(ctx, "player") |
| if err != nil { |
| return "", err |
| } |
| if len(players) > 0 { |
| return players[rand.Intn(len(players))], nil |
| } |
| return "", errors.New("no players") |
| } |
| |
| // FindScoreKeepers returns all the rock-paper-scissors score keepers from the |
| // mount table. |
| func FindScoreKeepers(ctx *context.T) ([]string, error) { |
| sKeepers, err := findAll(ctx, "scorekeeper") |
| if err != nil { |
| return nil, err |
| } |
| return sKeepers, nil |
| } |
| |
| func findAll(ctx *context.T, t string) ([]string, error) { |
| start := time.Now() |
| ns := v23.GetNamespace(ctx) |
| c, err := ns.Glob(ctx, "rps/"+t+"/*") |
| if err != nil { |
| vlog.Infof("mt.Glob failed: %v", err) |
| return nil, err |
| } |
| var servers []string |
| for e := range c { |
| switch v := e.(type) { |
| case *naming.GlobReplyError: |
| vlog.VI(1).Infof("findAll(%q) error for %q: %v", t, v.Value.Name, v.Value.Error) |
| case *naming.GlobReplyEntry: |
| servers = append(servers, v.Value.Name) |
| } |
| } |
| vlog.VI(1).Infof("findAll(%q) elapsed: %s", t, time.Now().Sub(start)) |
| return servers, nil |
| } |
| |
| // FormatScoreCard returns a string representation of a score card. |
| func FormatScoreCard(score rps.ScoreCard) string { |
| buf := bytes.NewBufferString("") |
| var gameType string |
| switch score.Opts.GameType { |
| case rps.Classic: |
| gameType = "Classic" |
| case rps.LizardSpock: |
| gameType = "LizardSpock" |
| default: |
| gameType = "Unknown" |
| } |
| fmt.Fprintf(buf, "Game Type: %s\n", gameType) |
| fmt.Fprintf(buf, "Number of rounds: %d\n", score.Opts.NumRounds) |
| fmt.Fprintf(buf, "Judge: %s\n", score.Judge) |
| fmt.Fprintf(buf, "Player 1: %s\n", score.Players[0]) |
| fmt.Fprintf(buf, "Player 2: %s\n", score.Players[1]) |
| for i, r := range score.Rounds { |
| roundOffset := r.StartTime.Sub(score.StartTime) |
| roundTime := r.EndTime.Sub(r.StartTime) |
| fmt.Fprintf(buf, "Round %2d: Player 1 played %-10q. Player 2 played %-10q. Winner: %d %-28s [%-10s/%-10s]\n", |
| i+1, r.Moves[0], r.Moves[1], r.Winner, r.Comment, roundOffset, roundTime) |
| } |
| fmt.Fprintf(buf, "Winner: %d\n", score.Winner) |
| fmt.Fprintf(buf, "Time: %s\n", score.EndTime.Sub(score.StartTime)) |
| return buf.String() |
| } |