// Package spotted answers what effect names other keyboards' definitions have // been seen to use for a given effect ID. // // It is evidence, not an answer, and the difference is the point. No definition // file, firmware image, protocol query or version number yields the spelling of // an effect for a board whose manufacturer never wrote one down, and the README // says so instead of filling the gap. What can be measured is what the boards // that did write theirs call the same number — and the measurement this package // carries shows why that is not a name: of the 122 definitions in VIA's // collection that file an rgb_matrix effect list, 95 are one manufacturer's, so // the most frequent spelling of nearly every ID is one house style. Worse, the // disagreement where it exists is not about spelling. Effect 7 is // `rainbow_moving_chevron` on 95 boards and `cycle_out_in` on 8, which are // different effects, not two ways of writing one. // // So every name here travels with the number of boards that wrote it and the // manufacturer behind most of them, and a caller that shows one to a user has to // show those too. A name without them is a guess wearing a count. package spotted import ( _ "embed" "encoding/json" "strconv" "sync" ) //go:embed spotted.json var raw []byte // Candidate is one spelling seen for an effect ID, and how many boards wrote it. type Candidate struct { Name string `json:"name"` Count int `json:"count"` } // Observation is what was seen for one effect ID under one value key. type Observation struct { // Boards is how many definitions listed this ID at all. It is the sample // size: a name backed by four boards is worth less than one backed by a // hundred and a half, and that difference is not visible anywhere else. Boards int `json:"boards"` // Candidates are the spellings, most frequent first. Candidates []Candidate `json:"candidates"` // TopVendor is the manufacturer behind the most of them and TopVendorCount how // many. A name whose share is nearly all one vendor is that vendor's // spelling, which is what this says. TopVendor string `json:"topVendor,omitempty"` TopVendorCount int `json:"topVendorCount,omitempty"` } // report is the generated measurement. Its shape is written by // internal/spotted/generate and must not be hand-edited. type report struct { Source string `json:"source"` Commit string `json:"commit"` Definitions int `json:"definitions"` // EffectBoards is how many of Definitions carried an effect list with names. // The gap to Definitions is the size of the problem: the rest either name one // of VIA's built-in menus or do not light up at all. EffectBoards int `json:"effectBoards"` Effects map[string]map[string]Observation `json:"effects"` } var ( once sync.Once loaded *report parse error ) func get() (*report, error) { once.Do(func() { loaded = &report{} parse = json.Unmarshal(raw, loaded) }) return loaded, parse } // Candidates returns what has been seen for an effect ID under a VIA value key, // and whether anything was. An ID nothing was seen for is not an error: most IDs // above 23 are unobserved, because only a handful of boards go that far. func Candidates(valueKey string, id int) (Observation, bool) { rep, err := get() if err != nil { return Observation{}, false } byID, ok := rep.Effects[valueKey] if !ok { return Observation{}, false } obs, ok := byID[strconv.Itoa(id)] return obs, ok } // Provenance describes what the measurement is a measurement of, for a caller to // print: where it came from, which commit, and how much of the collection // carried an effect list at all. type Provenance struct { Source string Commit string Definitions int EffectBoards int } // About reports where the measurement came from. A collection that moves means a // name in it ages, and the commit is what says how far. func About() (Provenance, bool) { rep, err := get() if err != nil { return Provenance{}, false } return Provenance{ Source: rep.Source, Commit: rep.Commit, Definitions: rep.Definitions, EffectBoards: rep.EffectBoards, }, true }