Fix it
Pointer vs. value receivers are... interesting.
This commit is contained in:
parent
3e34e25f54
commit
99e372a4db
129
cardsim/stats.go
129
cardsim/stats.go
@ -118,8 +118,9 @@ func (s statFunc[T]) Visible() bool {
|
|||||||
return s.visible
|
return s.visible
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtractStats pulls all exported stats out of a struct. It puts fields before
|
// ExtractStats pulls all exported stats out of a struct. It puts methods before
|
||||||
// method.
|
// fields. If the calculated name of a method conflicts with the calculated
|
||||||
|
// name of a stat from a field, the method wins.
|
||||||
//
|
//
|
||||||
// A field is a stat if it is of some Stat type or is tagged with `cardsim:"stat"`,
|
// A field is a stat if it is of some Stat type or is tagged with `cardsim:"stat"`,
|
||||||
// `cardsim:"hidden"` (invisible stat), `cardsim:"round2"` (or any integer, 2 is
|
// `cardsim:"hidden"` (invisible stat), `cardsim:"round2"` (or any integer, 2 is
|
||||||
@ -148,58 +149,13 @@ func ExtractStats(x any) []Stat {
|
|||||||
typ := v.Type()
|
typ := v.Type()
|
||||||
|
|
||||||
var ret []Stat
|
var ret []Stat
|
||||||
fields := reflect.VisibleFields(typ)
|
|
||||||
for _, sf := range fields {
|
|
||||||
if !sf.IsExported() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
f := v.FieldByIndex(sf.Index)
|
|
||||||
if !f.CanInterface() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if s, ok := f.Interface().(Stat); ok {
|
|
||||||
ret = append(ret, s)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if t := sf.Tag.Get("cardsim"); t != "" {
|
|
||||||
isStat := false
|
|
||||||
isHidden := false
|
|
||||||
t = strings.ToLower(t)
|
|
||||||
t = strings.TrimSpace(t)
|
|
||||||
if strings.HasPrefix(t, "hidden") {
|
|
||||||
isStat = true
|
|
||||||
isHidden = true
|
|
||||||
t = t[6:]
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(t, "stat") {
|
|
||||||
isStat = true
|
|
||||||
t = t[4:]
|
|
||||||
}
|
|
||||||
var val string
|
|
||||||
if strings.HasPrefix(t, "round") {
|
|
||||||
isStat = true
|
|
||||||
t = t[5:]
|
|
||||||
n, _ := strconv.Atoi(t)
|
|
||||||
fs := fmt.Sprintf("%%.%df", n)
|
|
||||||
val = fmt.Sprintf(fs, f.Interface())
|
|
||||||
} else if isStat {
|
|
||||||
val = fmt.Sprint(f.Interface())
|
|
||||||
} else {
|
|
||||||
continue // not identifiably a stat
|
|
||||||
}
|
|
||||||
ret = append(ret, &StatLiteral{
|
|
||||||
Name: strings.Join(explode(sf.Name), " "),
|
|
||||||
Value: val,
|
|
||||||
IsVisible: !isHidden,
|
|
||||||
})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Else, not a stat.
|
|
||||||
}
|
|
||||||
|
|
||||||
lim := typ.NumMethod()
|
known := make(map[string]bool)
|
||||||
|
for _, vv := range []reflect.Value{v, v.Addr()} {
|
||||||
|
xt := vv.Type()
|
||||||
|
lim := xt.NumMethod()
|
||||||
for i := 0; i < lim; i++ {
|
for i := 0; i < lim; i++ {
|
||||||
m := typ.Method(i)
|
m := xt.Method(i)
|
||||||
if !m.IsExported() {
|
if !m.IsExported() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -223,11 +179,15 @@ func ExtractStats(x any) []Stat {
|
|||||||
if nameParts[0] != "Stat" {
|
if nameParts[0] != "Stat" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
n := strings.Join(nameParts[1:], ": ")
|
n := strings.Join(nameParts[1:], " ")
|
||||||
if n == "" {
|
if n == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val := v.Method(i).Call([]reflect.Value{})
|
if known[n] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
known[n] = true
|
||||||
|
val := vv.Method(i).Call([]reflect.Value{})
|
||||||
if len(val) != 1 {
|
if len(val) != 1 {
|
||||||
// This shouldn't happen - we already checked Out. Weird.
|
// This shouldn't happen - we already checked Out. Weird.
|
||||||
continue
|
continue
|
||||||
@ -241,6 +201,67 @@ func ExtractStats(x any) []Stat {
|
|||||||
IsVisible: !isHidden,
|
IsVisible: !isHidden,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fields := reflect.VisibleFields(typ)
|
||||||
|
for _, sf := range fields {
|
||||||
|
if !sf.IsExported() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
f := v.FieldByIndex(sf.Index)
|
||||||
|
if !f.CanInterface() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
iface := f.Interface()
|
||||||
|
if s, ok := iface.(Stat); ok {
|
||||||
|
if known[s.StatName()] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
known[s.StatName()] = true
|
||||||
|
ret = append(ret, s)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if t := sf.Tag.Get("cardsim"); t != "" {
|
||||||
|
isStat := false
|
||||||
|
isHidden := false
|
||||||
|
t = strings.ToLower(t)
|
||||||
|
t = strings.TrimSpace(t)
|
||||||
|
if strings.HasPrefix(t, "hidden") {
|
||||||
|
isStat = true
|
||||||
|
isHidden = true
|
||||||
|
t = t[6:]
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(t, "stat") {
|
||||||
|
isStat = true
|
||||||
|
t = t[4:]
|
||||||
|
}
|
||||||
|
var val string
|
||||||
|
if strings.HasPrefix(t, "round") {
|
||||||
|
isStat = true
|
||||||
|
t = t[5:]
|
||||||
|
n, _ := strconv.Atoi(t)
|
||||||
|
fs := fmt.Sprintf("%%.%df", n)
|
||||||
|
val = fmt.Sprintf(fs, iface)
|
||||||
|
} else if isStat {
|
||||||
|
val = fmt.Sprint(iface)
|
||||||
|
} else {
|
||||||
|
continue // not identifiably a stat
|
||||||
|
}
|
||||||
|
nm := strings.Join(explode(sf.Name), " ")
|
||||||
|
if known[nm] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
known[nm] = true
|
||||||
|
ret = append(ret, &StatLiteral{
|
||||||
|
Name: nm,
|
||||||
|
Value: val,
|
||||||
|
IsVisible: !isHidden,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Else, not a stat.
|
||||||
|
}
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ type SmokeTestCollection struct {
|
|||||||
Things int `cardsim:"stat"`
|
Things int `cardsim:"stat"`
|
||||||
MoreThings int `cardsim:"hidden"`
|
MoreThings int `cardsim:"hidden"`
|
||||||
FloatyThings float64 `cardsim:"round1"`
|
FloatyThings float64 `cardsim:"round1"`
|
||||||
|
Label string `cardsim:"stat"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SmokeTestCollection) Average() float64 {
|
func (c *SmokeTestCollection) Average() float64 {
|
||||||
|
@ -28,6 +28,10 @@ func main() {
|
|||||||
Name: "Flavor",
|
Name: "Flavor",
|
||||||
Value: "Lemon",
|
Value: "Lemon",
|
||||||
},
|
},
|
||||||
|
Things: 5,
|
||||||
|
MoreThings: 9,
|
||||||
|
FloatyThings: 123.456,
|
||||||
|
Label: "whee",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
p.Name = "Dave"
|
p.Name = "Dave"
|
||||||
|
Loading…
Reference in New Issue
Block a user