You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
2.1 KiB
104 lines
2.1 KiB
package dice
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"math/rand"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type diceRequest struct {
|
|
count int
|
|
diceType int
|
|
}
|
|
|
|
type DiceRoller interface {
|
|
Roll(request string) ([]int, error)
|
|
TableRoll() [2]int
|
|
}
|
|
|
|
type Roller struct {
|
|
Rand *rand.Rand
|
|
Seed int64
|
|
DiceRoller
|
|
}
|
|
|
|
func NewRoller(seed int64) *Roller {
|
|
return &Roller{
|
|
Rand: rand.New(rand.NewSource(seed)),
|
|
Seed: seed,
|
|
}
|
|
}
|
|
|
|
// RollToJSON takes a []int and returns JSON with those ints in "results"
|
|
func RollToJSON(rolls []int) ([]byte, error) {
|
|
result := struct {
|
|
Results []int `json:"results"`
|
|
}{
|
|
Results: rolls,
|
|
}
|
|
|
|
jsonResults, err := json.Marshal(result)
|
|
if err != nil {
|
|
return []byte{}, err
|
|
}
|
|
|
|
return jsonResults, nil
|
|
}
|
|
|
|
// RollToText takes a []int and returns them a spaced separated string
|
|
func RollToText(rolls []int) string {
|
|
results := []string{}
|
|
for _, r := range rolls {
|
|
results = append(results, strconv.Itoa(r))
|
|
}
|
|
response := strings.Join(results, " ")
|
|
response = response + "\n"
|
|
return response
|
|
}
|
|
|
|
// Roll takes a string in the format of "XdY" and returns []int for its results
|
|
func (r *Roller) Roll(request string) ([]int, error) {
|
|
var result []int
|
|
|
|
diceRequest, err := parseRoll(request)
|
|
if err != nil {
|
|
return result, err
|
|
}
|
|
|
|
for i := 1; i <= diceRequest.count; i++ {
|
|
result = append(result, r.Rand.Intn(diceRequest.diceType)+1)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// TableRoll returns a roll used for selecting an item on a Maze Rats table
|
|
func (r *Roller) TableRoll() [2]int {
|
|
result, _ := r.Roll("2d6")
|
|
return [2]int{result[0], result[1]}
|
|
}
|
|
|
|
func parseRoll(request string) (diceRequest, error) {
|
|
regexString := "[1-9][0-9]*d[1-9]+"
|
|
diceRegEx := regexp.MustCompile(regexString)
|
|
correctRequest := diceRegEx.Match([]byte(request))
|
|
if !correctRequest {
|
|
errMsg := fmt.Sprintf("Must pass string matching '%v' "+
|
|
"you passed '%v'",
|
|
regexString, request)
|
|
return diceRequest{}, errors.New(errMsg)
|
|
}
|
|
|
|
var parsedRequest []string = strings.Split(request, "d")
|
|
count, _ := strconv.Atoi(parsedRequest[0])
|
|
diceType, _ := strconv.Atoi(parsedRequest[1])
|
|
|
|
return diceRequest{
|
|
count: count,
|
|
diceType: diceType,
|
|
}, nil
|
|
}
|
|
|