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 }