2 Commits

Author SHA1 Message Date
8d9303c8bc stats manual in README 2023-04-04 12:29:36 -07:00
ad9e5764f1 Allow renaming of extracted stats via tag. 2023-04-04 12:14:04 -07:00
4 changed files with 33 additions and 3 deletions

View File

@ -42,7 +42,7 @@ A bucket of game state.
### Stat
An arbitrary variable (or function, if it's calculated) tagged with some stuff to make it easier to display to the player.
An arbitrary variable (or function, if it's calculated) tagged with some stuff to make it easier to display to the player. Stats can be extracted automatically (see "Stat Extraction" below).
### StatsCollection
@ -57,3 +57,26 @@ There are some special errors that Rules can use to "communicate with" the rule
### Messages
For now, strings but inconvenient. Intended to provide forwards compatibility when we eventually include some way to format text, where all the stuff written for "it's just a string" would break if not for having this extra type in the way to wrap it where we can stay compatible with "it's just a string" mode.
## Stat Extraction
The function `ExtractStats` creates a stats list automatically by searching through a struct's fields and methods. The following things are recognized as stats:
* any method with a name like `StatFoo` or `HiddenStatFoo` (the latter are marked as invisible stats, which show up only in debug mode with the implementation in BasicStatsPane)
* any exported field with a type that is already a `Stat`; the `Stored[T]` and `Hidden[T]` generic types are containers for this
* any exported field tagged with `cardsim:"stat"`
* or `cardsim:"hidden"` for hidden stats. `"hiddenstat"` also works.
* you can use `"round2"` to round to two decimal places -- you can use any integer here, not just 2. works with both `float` types.
* `"hiddenround3"` (or any other number) creates a hidden rounded stat.
* To change the display name of a stat, use a separate tag phrase in addition to the stat tag, `cardsim_name:"name"`.
* For example: `cardsim:"stat" cardsim_name:"Stat Display Name"` creates a visible stat that shows up as "Stat Display Name".
* `cardsim:"hiddenround1" cardsim_name:"Hidden Rounded Stat"` creates an invisible stat that shows up, rounded to one decimal place, as "Hidden Rounded Stat".
Stat extraction can implement most or all of your type's `Stats` method for you:
```
func (e *ExampleType) Stats() []cardsim.Stat {
return cardsim.ExtractStats(e)
}
```
ExtractStats puts methods first (lexicographically), then fields (in the order they appear). You can use `cardsim.SortStats` to instead put visible stats before hidden stats, alphabetized (case-insensitive).

View File

@ -138,6 +138,10 @@ func (s statFunc[T]) Visible() bool {
// start of another word, if it's not at the end). To insert a space between
// consecutive capital letters, insert an underscore (`_`). This name inference
// trims "Stat" and "HiddenStat" off the front of method names.
//
// To override the name extracted from a field name, add `cardsim_name:"name"`
// to the tag, where the name part is the name you want to use. It will not be
// formatted further - use normal spaces, capitalization, etc.
func ExtractStats(x any) []Stat {
v := reflect.ValueOf(x)
for k := v.Kind(); k == reflect.Pointer || k == reflect.Interface; k = v.Kind() {
@ -248,6 +252,9 @@ func ExtractStats(x any) []Stat {
continue // not identifiably a stat
}
nm := strings.Join(explode(sf.Name), " ")
if t := sf.Tag.Get("cardsim_name"); t != "" {
nm = t
}
if known[nm] {
continue
}

View File

@ -85,7 +85,7 @@ func (i inverseDivision) OptionText(p *player) (cardsim.Message, error) {
func (i inverseDivision) Enact(p *player) (cardsim.Message, error) {
if p.Stats.Number.Value == 0 {
return nil, errors.New("you can't divide by zero!")
return nil, errors.New("you can't divide by zero")
}
p.Stats.Number.Value = int(i) / p.Stats.Number.Value
return cardsim.MsgStr("Inverse divided."), nil

View File

@ -12,7 +12,7 @@ type SmokeTestCollection struct {
Flavor cardsim.Stored[string]
Things int `cardsim:"stat"`
Things int `cardsim:"stat" cardsim_name:"A Renamed Thing"`
MoreThings int `cardsim:"hidden"`
FloatyThings float64 `cardsim:"round1"`
Label string `cardsim:"stat"`