package main import ( "encoding/json" "fmt" "math" "math/rand/v2" "os" "strings" "github.com/fogleman/gg" ) type Lane int const ( Any Lane = iota Red Green Blue ) type Type int const ( Unit Type = iota Spell Passive ) func (l Lane) String() string { switch l { case Any: return "⬜ Passive" case Red: return "🟥 Red" case Green: return "🟩 Green" case Blue: return "🟦 Blue" default: panic("unknwon") } } func (t Type) String() string { switch t { case Unit: return "Unit" case Passive: return "Passive" case Spell: return "Spell" default: panic("unknown") } } func main() { type ( jsonfront struct { Name string `json:"name"` Type string `json:"type"` Cost int `json:"cost"` Image string `json:"image"` Horizontal bool `json:"isHorizontal"` } jsoncard struct { // required Id string `json:"id"` Face struct { Front jsonfront `json:"front"` } `json:"face"` Name string `json:"name"` Type string `json:"type"` Cost int `json:"cost"` Token bool `json:"isToken"` // custom Lane string `json:"Lane"` Entropy int `json:"Entropy"` Force int `json:"Force"` Legal map[string]bool `json:"_legal"` } ) thejson := make(map[string]jsoncard) for i := range len(CARDS) { card := &CARDS[i] if len(card.name) == 0 { card.name = generateTemporaryName() } var ( baseimg string color [3]float64 ) switch card.lane { case Red: baseimg = "base-red.png" color = [3]float64{248.0 / 255.0, 120.0 / 255.0, 143.0 / 255.0} case Green: baseimg = "base-green.png" color = [3]float64{126.0 / 255.0, 229.0 / 255.0, 166.0 / 255.0} case Blue: baseimg = "base-blue.png" color = [3]float64{120.0 / 255.0, 190.0 / 255.0, 248.0 / 255.0} default: color = [3]float64{184.0 / 255.0, 184.0 / 255.0, 184.0 / 255.0} baseimg = "base-passive.png" } img, err := gg.LoadImage("docs/" + baseimg) if err != nil { panic(err) } ctx := gg.NewContextForImage(img) if err := ctx.LoadFontFace("docs/SFCamera.ttf", 64); err != nil { panic(err) } // Draw force if card.typ != Passive { ctx.SetRGB(1, 1, 1) ctx.Push() { ctx.Translate(120, 115) ctx.Rotate(270 * math.Pi / 180) ctx.DrawStringAnchored(fmt.Sprintf("%d", card.force), 0, 0, 0.5, 0.5) } ctx.Pop() } // Draw entropy or recovery ctx.SetRGB(color[0], color[1], color[2]) ctx.Push() { ctx.Translate(273, 115) ctx.Rotate(270 * math.Pi / 180) var prefix string if card.typ == Passive { prefix = "+" } ctx.DrawStringAnchored(fmt.Sprintf("%s%d", prefix, max(card.entropy, card.recovery)), 0, 0, 0.5, 0.5) } ctx.Pop() if err := ctx.LoadFontFace("docs/SFCamera.ttf", 30); err != nil { panic(err) } // Draw description cleandesc := strings.NewReplacer("{{", "", "}}", "").Replace(card.desc) ctx.SetRGBA(0, 0, 0, 0.9) ctx.Push() { ctx.Translate(435, 985) ctx.Rotate(270 * math.Pi / 180) ctx.DrawStringWrapped(fmt.Sprintf("#%03d %s - %s\n%s", i, card.name, card.typ.String(), cleandesc), 0, 0, 0.0, 0.0, 900, 1.80, gg.AlignLeft) } ctx.Pop() id := fmt.Sprintf("%03d", i) if err := ctx.SavePNG("docs/" + id + ".png"); err != nil { panic(err) } thejson[id] = jsoncard{ Id: id, Face: struct { Front jsonfront `json:"front"` }{ jsonfront{ Name: card.name, Type: card.typ.String(), Image: fmt.Sprintf("https://docs.brut.systems/judah/entropy/%s.png", id), Cost: card.entropy, Horizontal: true, }, }, Token: card.token, Name: card.name, Type: card.typ.String(), Cost: card.entropy, Entropy: card.entropy, Force: card.force, Lane: card.lane.String(), Legal: map[string]bool{ "playtest": true, }, } } enc, err := json.MarshalIndent(thejson, "", " ") if err != nil { panic(err) } if err := os.WriteFile("CardList.json", enc, 0644); err != nil { panic(err) } } func generateTemporaryName() string { var ( adjectives = []string{ "Absent", "Ambient", "Bare", "Blunt", "Civic", "Composite", "Concave", "Dull", "Errant", "Excess", "Flat", "Former", "Gross", "Inland", "Lateral", "Live", "Lucid", "Moot", "Vampiric", "Nominal", "Convergent", "Partial", "Passive", "Raging", "Polar", "Residual", "Rote", "Soft", "Spent", "Terminal", "Warm", } nouns = []string{ "Aperture", "Axis", "Bulk", "Cartilage", "Compact", "Contour", "Conviction", "Cortex", "Deficit", "Dividend", "Dosage", "Shrine", "Filament", "Gesture", "Gradient", "Inlet", "Judgement", "Mandate", "Membrane", "Morale", "Offset", "Posture", "Precinct", "Prospect", "Rapport", "Reflex", "Mutation", "Substrate", "Surplus", "Tendon", "Volume", } ) return adjectives[rand.IntN(len(adjectives))] + nouns[rand.IntN(len(nouns))] }