blob: 5ecb1437c635dfd70a844a8f5577f62839e66ce0 [file] [log] [blame]
// 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()
}