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 Boon ) func (l Lane) String() string { switch l { case Any: return "⬜ Boon" 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 Boon: return "Boon" 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-boon.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 != Boon { 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(270, 115) ctx.Rotate(270 * math.Pi / 180) ctx.DrawStringAnchored(fmt.Sprintf("%d", 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) // draw rotated // finished := ctx.Image() // w := finished.Bounds().Dx() // h := finished.Bounds().Dy() // rotated := gg.NewContext(h, w) // rotated.Translate(float64(h)/2, float64(w)/2) // rotated.Rotate(90 * math.Pi / 180) // rotated.DrawImageAnchored(finished, 0, 0, 0.5, 0.5) 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", "Boon", "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))] }