summaryrefslogtreecommitdiffhomepage
path: root/src/dbx/mintages.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/dbx/mintages.go')
-rw-r--r--src/dbx/mintages.go182
1 files changed, 182 insertions, 0 deletions
diff --git a/src/dbx/mintages.go b/src/dbx/mintages.go
new file mode 100644
index 0000000..d78e59c
--- /dev/null
+++ b/src/dbx/mintages.go
@@ -0,0 +1,182 @@
+package dbx
+
+import (
+ "database/sql"
+ "slices"
+)
+
+type MintageData struct {
+ Standard []MSRow
+ Commemorative []MCRow
+}
+
+type msRowInternal struct {
+ Country string
+ Type MintageType
+ Year int
+ Denomination float64
+ Mintmark sql.Null[string]
+ Mintage sql.Null[int]
+ Reference sql.Null[string]
+}
+
+type mcRowInternal struct {
+ Country string
+ Type MintageType
+ Year int
+ Name string
+ Number int
+ Mintmark sql.Null[string]
+ Mintage sql.Null[int]
+ Reference sql.Null[string]
+}
+
+type MSRow struct {
+ Year int
+ Mintmark string
+ Mintages [ndenoms]int
+ References []string
+}
+
+type MCRow struct {
+ Year int
+ Name string
+ Number int
+ Mintmark string
+ Mintage int
+ Reference string
+}
+
+type MintageType int
+
+/* DO NOT REORDER! */
+const (
+ TypeCirc MintageType = iota
+ TypeNifc
+ TypeProof
+)
+
+/* DO NOT REORDER! */
+const (
+ MintageUnknown = -iota - 1
+ MintageInvalid
+)
+
+const ndenoms = 8
+
+func NewMintageType(s string) MintageType {
+ switch s {
+ case "circ":
+ return TypeCirc
+ case "nifc":
+ return TypeNifc
+ case "proof":
+ return TypeProof
+ }
+ /* TODO: Handle this */
+ panic("TODO")
+}
+
+func GetMintages(country string, typ MintageType) (MintageData, error) {
+ var (
+ zero MintageData
+ xs []MSRow
+ ys []MCRow
+ )
+
+ rs, err := db.Queryx(`
+ SELECT * FROM mintages_s
+ WHERE country = ? AND type = ?
+ ORDER BY year, mintmark, denomination
+ `, country, typ)
+ if err != nil {
+ return zero, err
+ }
+
+ for rs.Next() {
+ var x msRowInternal
+ if err = rs.StructScan(&x); err != nil {
+ return zero, err
+ }
+
+ loop:
+ msr := MSRow{
+ Year: x.Year,
+ Mintmark: sqlOr(x.Mintmark, ""),
+ References: make([]string, 0, ndenoms),
+ }
+ for i := range msr.Mintages {
+ msr.Mintages[i] = MintageUnknown
+ }
+ msr.Mintages[denomToIdx(x.Denomination)] =
+ sqlOr(x.Mintage, MintageUnknown)
+ if x.Reference.Valid {
+ msr.References = append(msr.References, x.Reference.V)
+ }
+
+ for rs.Next() {
+ var y msRowInternal
+ if err = rs.StructScan(&y); err != nil {
+ return zero, err
+ }
+
+ if x.Year != y.Year || x.Mintmark != y.Mintmark {
+ x = y
+ xs = append(xs, msr)
+ goto loop
+ }
+
+ msr.Mintages[denomToIdx(y.Denomination)] =
+ sqlOr(y.Mintage, MintageUnknown)
+ if y.Reference.Valid {
+ msr.References = append(msr.References, y.Reference.V)
+ }
+ }
+
+ xs = append(xs, msr)
+ }
+
+ if err = rs.Err(); err != nil {
+ return zero, err
+ }
+
+ rs, err = db.Queryx(`
+ SELECT * FROM mintages_c
+ WHERE country = ? AND type = ?
+ ORDER BY year, mintmark, number
+ `, country, typ)
+ if err != nil {
+ return zero, err
+ }
+
+ for rs.Next() {
+ var y mcRowInternal
+ if err = rs.StructScan(&y); err != nil {
+ return zero, err
+ }
+ ys = append(ys, MCRow{
+ Year: y.Year,
+ Name: y.Name,
+ Number: y.Number,
+ Mintmark: sqlOr(y.Mintmark, ""),
+ Mintage: sqlOr(y.Mintage, MintageUnknown),
+ Reference: sqlOr(y.Reference, ""),
+ })
+ }
+
+ return MintageData{xs, ys}, rs.Err()
+}
+
+func sqlOr[T any](v sql.Null[T], dflt T) T {
+ if v.Valid {
+ return v.V
+ }
+ return dflt
+}
+
+func denomToIdx(d float64) int {
+ return slices.Index([]float64{
+ 0.01, 0.02, 0.05, 0.10,
+ 0.20, 0.50, 1.00, 2.00,
+ }, d)
+}