Skip to content

Commit

Permalink
Auto Vassal module
Browse files Browse the repository at this point in the history
  • Loading branch information
sayden committed Nov 4, 2024
1 parent bc529f2 commit 8e9b3ed
Show file tree
Hide file tree
Showing 20 changed files with 881 additions and 259 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ server/static/img.png
server/tmp

.vscode

vassal_modules
3 changes: 0 additions & 3 deletions card.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,7 @@ func (c *Card) ToCanvas(template *CardsTemplate) (*gg.Context, error) {
isLastAreaOfCard := areaIndex != numberOfAreas
c.Areas[areaIndex].Height = int(math.Floor(areasHeights[areaIndex]))

// area.Width = (template.Width) - int(template.Margins*2)
// areaCanvas, err := c.processAreav2(template, &area, c.Areas[areaIndex].Height, isLastAreaOfCard)
areaCanvas, err := c.ProcessAreav2(&areaCounter, template, int(math.Floor(areasHeights[areaIndex])), isLastAreaOfCard)
// areaCanvas, err := area.Canvas(false)
if err != nil {
return nil, err
}
Expand Down
11 changes: 2 additions & 9 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"flag"
"os"
"runtime/pprof"

"github.com/alecthomas/kong"
"github.com/charmbracelet/log"
Expand All @@ -19,7 +18,7 @@ var Cli struct {
Json JsonOutput `cmd:"" help:"Generate a JSON of some short, by transforming another JSON as input"`

// Vassal is used to generate a Vassal module for testing purposes.
Vassal vassal `cmd:"" help:"Create a vassal module for testing. It searches for the 'template.xml' in the same folder"` //FIXME
Vassal vassalCli `cmd:"" help:"Create a vassal module for testing. It searches for the 'template.xml' in the same folder"` //FIXME

GenerateTemplate GenerateTemplate `cmd:"" help:"Generates a new counter template file with default values"`

Expand All @@ -28,20 +27,14 @@ var Cli struct {

func main() {
flag.Parse()
f, err := os.Create("cpu.prof")
if err != nil {
log.Fatal(err)
}
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()

logger.SetReportTimestamp(false)
logger.SetReportCaller(false)
logger.SetLevel(log.DebugLevel)

ctx := kong.Parse(&Cli)

err = ctx.Run()
err := ctx.Run()
ctx.FatalIfErrorf(err)

logger.Info("Done")
Expand Down
20 changes: 15 additions & 5 deletions cmd/vassal.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,23 @@ package main

import (
"github.com/alecthomas/kong"
"github.com/sayden/counters/pipelines"
"github.com/sayden/counters/output"
)

type vassal struct {
pipelines.VassalConfig
type vassalCli struct {
Templates []string `help:"List of templates to embed in the Vassal module" short:"t"`
OutputPath string `help:"Path to the temp folder" short:"o"`
output.VassalConfig
}

func (i *vassal) Run(ctx *kong.Context) error {
return pipelines.CSVToVassalFile(i.VassalConfig)
func (i *vassalCli) Run(ctx *kong.Context) error {
if i.Templates != nil {
return i.TemplatesToVassal()
}

return output.CSVToVassalFile(i.VassalConfig)
}

func (v *vassalCli) TemplatesToVassal() error {
return output.VassalModule(v.OutputPath, v.Templates)
}
38 changes: 20 additions & 18 deletions counter.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,20 @@ import (
"text/template"

"github.com/fogleman/gg"
"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/thehivecorporation/log"
)

func init() {
var err error
pieceSlotTemplate, err = template.New("piece_text").Parse(Template_NewVassalPiece)
if err != nil {
panic(fmt.Errorf("could not parse template string %w", err))
}
}

var pieceSlotTemplate *template.Template

// Counter is POGO-like holder for data needed for other parts to fill and draw
// a counter in a container
type Counter struct {
Expand Down Expand Up @@ -72,7 +81,7 @@ func (c *Counter) GetTextInPosition(i int) string {
// filenumber: CounterTemplate.PositionNumberForFilename. So it will always be fixed number
// position: The position of the text in the counter (0-16)
// suffix: A suffix on the file. Constant
func (c *Counter) GetCounterFilename(position int, filenamesInUse *sync.Map) string {
func (c *Counter) GetCounterFilename(sideName string, position int, filenamesInUse *sync.Map) string {
if c.Filename != "" {
return c.Filename
}
Expand All @@ -91,7 +100,6 @@ func (c *Counter) GetCounterFilename(position int, filenamesInUse *sync.Map) str
// This way, the positional based name will always be the first part of the filename
// while the manual title will come later. This is useful when using prototypes so that
// counters with the same positional name are close together in the destination folder
// by "formation" (belonging) instead of by "use" (title)
name = ""

if c.Extra.Side != "" {
Expand Down Expand Up @@ -132,6 +140,12 @@ func (c *Counter) GetCounterFilename(position int, filenamesInUse *sync.Map) str
res = strings.TrimSpace(res)

filenamesInUse.Store(res, true)
if c.Extra == nil {
c.Extra = &Extra{}
}
if sideName != "" {
res = sideName + "_" + res
}
c.Extra.Title = res

res += ".png"
Expand Down Expand Up @@ -230,35 +244,23 @@ func (c *Counter) ToVassal(sideName string) error {
return nil
}

pieceTemplate := "+/null/prototype;Basic Pieces emb2;" +
"{{ .FlipName }};128;A;;128;;;128;;;;1;false;0;0;" +
"{{ .BackFilename }};Back;true;Flip;;;false;;1;1;false;;;;Description;1.0;;true\\ piece;;;" +
"{{ .FrontFilename }};" +
"{{ .PieceName }}/ -1\\ null;0;0;;1;ppScale;1.0"

xmlTemplate, err := template.New("xml").Parse(pieceTemplate)
if err != nil {
return fmt.Errorf("could not parse template string %w", err)
}

uuid := uuid.New().String()
buf := bytes.NewBufferString("")
pieceTemp := PieceTemplateData{
FrontFilename: c.Filename,
BackFilename: c.Extra.Title + "_back.png",
FlipName: sideName,
PieceName: c.Filename,
Id: uuid,
Id: c.Extra.Title,
}

err = xmlTemplate.ExecuteTemplate(buf, "xml", pieceTemp)
err := pieceSlotTemplate.ExecuteTemplate(buf, "piece_text", pieceTemp)
if err != nil {
return fmt.Errorf("could not execute template %w", err)
}

piece := PieceSlot{
EntryName: c.Filename,
Gpid: uuid,
Gpid: c.Extra.Title,
Height: c.Height,
Width: c.Width,
Data: buf.String(),
Expand Down
9 changes: 5 additions & 4 deletions counter_prototype.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ func (p *CounterPrototype) ToCounters(filenamesInUse *sync.Map, sideName string,

var counterFilename string
if p.Extra != nil && p.Extra.TitlePosition != nil {
counterFilename = newCounter.GetCounterFilename(*p.Extra.TitlePosition, filenamesInUse)
counterFilename = newCounter.GetCounterFilename(sideName, *p.Extra.TitlePosition, filenamesInUse)
} else {
counterFilename = newCounter.GetCounterFilename(positionNumberForFilename, filenamesInUse)
counterFilename = newCounter.GetCounterFilename(sideName, positionNumberForFilename, filenamesInUse)
}
newCounter.Filename = counterFilename

Expand All @@ -74,7 +74,7 @@ func (p *CounterPrototype) ToCounters(filenamesInUse *sync.Map, sideName string,
if sideName != "" {
err = backCounter.ToVassal(sideName)
if err != nil {
log.Warn("could not create vassal piece")
log.Warn("could not create vassal piece", err)
}
}

Expand All @@ -84,9 +84,10 @@ func (p *CounterPrototype) ToCounters(filenamesInUse *sync.Map, sideName string,
if sideName != "" {
err = newCounter.ToVassal(sideName)
if err != nil {
log.Warn("could not create vassal piece")
log.Warn("could not create vassal piece", err)
}
}

cts = append(cts, newCounter)
}

Expand Down
33 changes: 22 additions & 11 deletions counter_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package counters

import (
"encoding/json"
"os"
"sort"
"sync"

Expand Down Expand Up @@ -33,6 +32,13 @@ type CounterTemplate struct {
Prototypes map[string]CounterPrototype `json:"prototypes,omitempty"`
}

type VassalCounterTemplateSettings struct {
SideName string `json:"side_name,omitempty"`
ModuleName string `json:"module_name,omitempty"`
MapFile string `json:"map_file,omitempty"`
HexGrid *HexGrid `json:"hex_grid,omitempty"`
}

// ParseCounterTemplate reads a JSON file and parses it into a CounterTemplate after applying it some default settings (if not
// present in the file)
func ParseCounterTemplate(byt []byte, filenamesInUse *sync.Map) (t *CounterTemplate, err error) {
Expand All @@ -52,14 +58,6 @@ func ParseCounterTemplate(byt []byte, filenamesInUse *sync.Map) (t *CounterTempl

t.ApplyCounterWaterfallSettings()

// Request body contains the current working directory to use
// This is relevant because we need to use relavite paths
if t.WorkingDirectory != "" {
if err = os.Chdir(os.ExpandEnv(t.WorkingDirectory)); err != nil {
return nil, err
}
}

return
}

Expand Down Expand Up @@ -131,7 +129,7 @@ func (t *CounterTemplate) ParsePrototype() (*CounterTemplate, error) {
// JSON counters to Counters
newTemplate, err := t.ExpandPrototypeCounterTemplate(filenamesInUse)
if err != nil {
return nil, errors.Wrap(err, "error trying to convert a counter template into another counter template")
return nil, errors.Wrap(err, "error trying to expand prototype template")
}

byt, err := json.Marshal(newTemplate)
Expand Down Expand Up @@ -174,7 +172,20 @@ func (t *CounterTemplate) ExpandPrototypeCounterTemplate(filenamesInUse *sync.Ma
}

t.Prototypes = nil
return t, nil
}

if t.Counters != nil {
for i, counter := range t.Counters {
if counter.Filename == "" {
var counterFilename string
if counter.Extra != nil && counter.Extra.TitlePosition != nil {
counterFilename = counter.GetCounterFilename(t.Vassal.SideName, *counter.Extra.TitlePosition, filenamesInUse)
} else {
counterFilename = counter.GetCounterFilename(t.Vassal.SideName, t.PositionNumberForFilename, filenamesInUse)
}
t.Counters[i].Filename = counterFilename
}
}
}

return t, nil
Expand Down
4 changes: 2 additions & 2 deletions counter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestGetCounterFilename(t *testing.T) {
counter: Counter{
Texts: []Text{
{Settings: Settings{Position: 0}, String: "Test"}},
Extra: &Extra{Title: stringP("ExtraTitle")},
Extra: &Extra{Title: "ExtraTitle"},
},
position: 0,
suffix: "suffix",
Expand Down Expand Up @@ -75,7 +75,7 @@ func TestGetCounterFilename(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.counter.GetCounterFilename(tt.position, tt.suffix, tt.filenumber, tt.filenamesInUse)
got := tt.counter.GetCounterFilename("side", tt.position, tt.filenamesInUse)

Check failure on line 78 in counter_test.go

View workflow job for this annotation

GitHub Actions / build

cannot use tt.filenamesInUse (variable of type map[string]bool) as *sync.Map value in argument to tt.counter.GetCounterFilename
if got != tt.expected {
t.Errorf("GetCounterFilename() = '%v', want '%v'", got, tt.expected)
}
Expand Down
33 changes: 31 additions & 2 deletions fsops/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import (
"encoding/json"
"encoding/xml"
"fmt"
"io"
"os"
"path/filepath"
"strings"

"github.com/charmbracelet/log"
"github.com/pkg/errors"
"github.com/thehivecorporation/log"
)

func ReadMarkupFile(markupFilepath string, destination interface{}) error {
Expand Down Expand Up @@ -39,7 +40,7 @@ func ReadMarkupFile(markupFilepath string, destination interface{}) error {
func FilenameExistsInFolder(filename, folder string) bool {
fs, err := os.ReadDir(folder)
if err != nil {
log.WithError(err).Fatal("could not read images folder")
log.Fatal("could not read images folder", "error", err)
}

for _, file := range fs {
Expand Down Expand Up @@ -83,3 +84,31 @@ func GetFilenamesForPath(path string) ([]string, error) {

return images, nil
}

// CopyFile copies a file from src to dst. If dst does not exist, it will be created.
func CopyFile(src, dst string) error {
fullpath, err := filepath.Abs(src)
if err != nil {
return err
}

sourceFile, err := os.Open(fullpath)
if err != nil {
log.Error("Copying file", "src", fullpath, "dst", dst)
return err
}
defer sourceFile.Close()

destinationFile, err := os.Create(dst)
if err != nil {
return err
}
defer destinationFile.Close()

_, err = io.Copy(destinationFile, sourceFile)
if err != nil {
return err
}

return destinationFile.Sync()
}
Loading

0 comments on commit 8e9b3ed

Please sign in to comment.