package importer import ( "bamort/bmrt/models" "encoding/csv" "encoding/json" "fmt" "os" "strconv" "strings" ) // ExportCharToVTT converts a BaMoRT character to VTT JSON format func ExportCharToVTT(char *models.Char) (*CharacterImport, error) { vtt := &CharacterImport{} // Basic info vtt.ID = fmt.Sprintf("bamort-character-%d", char.ID) vtt.Name = char.Name vtt.Rasse = char.Rasse vtt.Typ = char.Typ vtt.Alter = char.Alter vtt.Anrede = char.Anrede vtt.Grad = char.Grad vtt.Groesse = char.Groesse vtt.Gewicht = char.Gewicht vtt.Glaube = char.Glaube vtt.Hand = char.Hand vtt.Image = char.Image // LP vtt.Lp.Max = char.Lp.Max vtt.Lp.Value = char.Lp.Value // AP vtt.Ap.Max = char.Ap.Max vtt.Ap.Value = char.Ap.Value // B vtt.B.Max = char.B.Max vtt.B.Value = char.B.Value // Eigenschaften - convert from array to struct for _, e := range char.Eigenschaften { switch e.Name { case "Au": vtt.Eigenschaften.Au = e.Value case "Gs": vtt.Eigenschaften.Gs = e.Value case "Gw": vtt.Eigenschaften.Gw = e.Value case "In": vtt.Eigenschaften.In = e.Value case "Ko": vtt.Eigenschaften.Ko = e.Value case "PA": vtt.Eigenschaften.Pa = e.Value case "St": vtt.Eigenschaften.St = e.Value case "Wk": vtt.Eigenschaften.Wk = e.Value case "Zt": vtt.Eigenschaften.Zt = e.Value } } // Merkmale vtt.Merkmale.Augenfarbe = char.Merkmale.Augenfarbe vtt.Merkmale.Haarfarbe = char.Merkmale.Haarfarbe vtt.Merkmale.Sonstige = char.Merkmale.Sonstige // Gestalt vtt.Gestalt.Breite = char.Merkmale.Breite vtt.Gestalt.Groesse = char.Merkmale.Groesse // Bennies vtt.Bennies.Gg = char.Bennies.Gg vtt.Bennies.Sg = char.Bennies.Sg vtt.Bennies.Gp = char.Bennies.Gp // Erfahrungsschatz vtt.Erfahrungsschatz.Value = char.Erfahrungsschatz.ES // Spezialisierung vtt.Spezialisierung = char.Spezialisierung // Fertigkeiten for i, f := range char.Fertigkeiten { vtt.Fertigkeiten = append(vtt.Fertigkeiten, Fertigkeit{ ImportBase: ImportBase{ ID: fmt.Sprintf("bamort-skill-%d-%d", char.ID, i), Name: f.Name, }, Beschreibung: f.Beschreibung, Fertigkeitswert: f.Fertigkeitswert, Bonus: f.Bonus, Pp: f.Pp, Quelle: "", // Not stored in character skill }) } // Waffenfertigkeiten for i, w := range char.Waffenfertigkeiten { vtt.Waffenfertigkeiten = append(vtt.Waffenfertigkeiten, Waffenfertigkeit{ ImportBase: ImportBase{ ID: fmt.Sprintf("bamort-weaponskill-%d-%d", char.ID, i), Name: w.Name, }, Beschreibung: w.Beschreibung, Fertigkeitswert: w.Fertigkeitswert, Bonus: w.Bonus, Pp: w.Pp, Quelle: "", // Not stored in character skill }) } // Zauber for i, z := range char.Zauber { vtt.Zauber = append(vtt.Zauber, Zauber{ ImportBase: ImportBase{ ID: fmt.Sprintf("bamort-spell-%d-%d", char.ID, i), Name: z.Name, }, Beschreibung: z.Beschreibung, Bonus: z.Bonus, Quelle: z.Quelle, }) } // Waffen for i, w := range char.Waffen { vtt.Waffen = append(vtt.Waffen, Waffe{ ImportBase: ImportBase{ ID: fmt.Sprintf("bamort-weapon-%d-%d", char.ID, i), Name: w.Name, }, Beschreibung: w.Beschreibung, Gewicht: w.Gewicht, Wert: w.Wert, Anzahl: w.Anzahl, Anb: w.Anb, Schb: w.Schb, Abwb: w.Abwb, NameFuerSpezialisierung: w.NameFuerSpezialisierung, BeinhaltetIn: fmt.Sprintf("bamort-container-%d", w.ContainedIn), ContainedIn: w.ContainedIn, Magisch: Magisch{ IstMagisch: w.IstMagisch, Abw: w.Abw, Ausgebrannt: w.Ausgebrannt, }, }) } // Ausrüstung for i, a := range char.Ausruestung { vtt.Ausruestung = append(vtt.Ausruestung, Ausruestung{ ImportBase: ImportBase{ ID: fmt.Sprintf("bamort-equipment-%d-%d", char.ID, i), Name: a.Name, }, Beschreibung: a.Beschreibung, Gewicht: a.Gewicht, Wert: a.Wert, Anzahl: a.Anzahl, Bonus: a.Bonus, BeinhaltetIn: fmt.Sprintf("bamort-container-%d", a.ContainedIn), ContainedIn: a.ContainedIn, Magisch: Magisch{ IstMagisch: a.IstMagisch, Abw: a.Abw, Ausgebrannt: a.Ausgebrannt, }, }) } // Behältnisse for i, b := range char.Behaeltnisse { vtt.Behaeltnisse = append(vtt.Behaeltnisse, Behaeltniss{ ImportBase: ImportBase{ ID: fmt.Sprintf("bamort-container-%d-%d", char.ID, i), Name: b.Name, }, Beschreibung: b.Beschreibung, Gewicht: b.Gewicht, Wert: b.Wert, Tragkraft: b.Tragkraft, Volumen: b.Volumen, BeinhaltetIn: fmt.Sprintf("bamort-container-%d", b.ContainedIn), ContainedIn: b.ContainedIn, Magisch: Magisch{ IstMagisch: b.IstMagisch, Abw: b.Abw, Ausgebrannt: b.Ausgebrannt, }, }) } // Transportmittel for i, tm := range char.Transportmittel { vtt.Transportmittel = append(vtt.Transportmittel, Transportation{ ImportBase: ImportBase{ ID: fmt.Sprintf("bamort-transport-%d-%d", char.ID, i), Name: tm.Name, }, Beschreibung: tm.Beschreibung, Gewicht: int(tm.Gewicht), Wert: tm.Wert, Tragkraft: tm.Tragkraft, BeinhaltetIn: fmt.Sprintf("bamort-container-%d", tm.ContainedIn), ContainedIn: tm.ContainedIn, Magisch: Magisch{ IstMagisch: tm.IstMagisch, Abw: tm.Abw, Ausgebrannt: tm.Ausgebrannt, }, }) } return vtt, nil } // ExportCharToVTTFile exports a character to VTT JSON file func ExportCharToVTTFile(char *models.Char, filename string) error { vtt, err := ExportCharToVTT(char) if err != nil { return err } file, err := os.Create(filename) if err != nil { return err } defer file.Close() encoder := json.NewEncoder(file) encoder.SetIndent("", " ") return encoder.Encode(vtt) } // ExportSpellsToCSV exports spell master data to CSV format func ExportSpellsToCSV(spells []models.Spell, filename string) error { file, err := os.Create(filename) if err != nil { return err } defer file.Close() writer := csv.NewWriter(file) defer writer.Flush() // Header header := []string{ "Nr", "game_system", "name", "Beschreibung", "Quelle", "source_id", "page_number", "bonus", "stufe", "ap", "Art", "Zauberdauer", "Reichweite", "Wirkungsziel", "Wirkungsbereich", "Wirkungsdauer", "Ursprung", "Category", "learning_category", "Agens", "Reagens", "Material (Kosten)", } if err := writer.Write(header); err != nil { return err } // Data rows for i, spell := range spells { row := []string{ strconv.Itoa(i + 1), spell.GameSystem, spell.Name, spell.Beschreibung, spell.Quelle, strconv.Itoa(int(spell.SourceID)), strconv.Itoa(spell.PageNumber), strconv.Itoa(spell.Bonus), strconv.Itoa(spell.Stufe), spell.AP, spell.Art, spell.Zauberdauer, spell.Reichweite, spell.Wirkungsziel, spell.Wirkungsbereich, spell.Wirkungsdauer, spell.Ursprung, spell.Category, spell.LearningCategory, "", // Agens - not in current model "", // Reagens - not in current model "", // Material - not in current model } if err := writer.Write(row); err != nil { return err } } return nil } // ExportCharToCSV exports a character to CSV format (MOAM-compatible) func ExportCharToCSV(char *models.Char, filename string) error { file, err := os.Create(filename) if err != nil { return err } defer file.Close() writer := csv.NewWriter(file) writer.Comma = ';' defer writer.Flush() // Helper to write a row writeRow := func(fields ...string) error { return writer.Write(fields) } // Header: Name, Typ, Grad, Stand, Glaube, Herkunft if err := writeRow("Name", "Typ", "Grad", "Stand", "Glaube", "Herkunft"); err != nil { return err } stand := "" herkunft := "" if err := writeRow(char.Name, char.Typ, strconv.Itoa(char.Grad), stand, char.Glaube, herkunft); err != nil { return err } // Spezialisierung if err := writeRow("Spezialisierung", strings.Join(char.Spezialisierung, ";")); err != nil { return err } if err := writeRow(""); err != nil { // Empty line return err } // Basiseigenschaften if err := writeRow("Basiseigenschaften"); err != nil { return err } eigenschaftenMap := make(map[string]int) for _, e := range char.Eigenschaften { eigenschaftenMap[e.Name] = e.Value } if err := writeRow("St", strconv.Itoa(eigenschaftenMap["St"])); err != nil { return err } if err := writeRow("Gs", strconv.Itoa(eigenschaftenMap["Gs"])); err != nil { return err } if err := writeRow("Gw", strconv.Itoa(eigenschaftenMap["Gw"])); err != nil { return err } if err := writeRow("Ko", strconv.Itoa(eigenschaftenMap["Ko"])); err != nil { return err } if err := writeRow("In", strconv.Itoa(eigenschaftenMap["In"])); err != nil { return err } if err := writeRow("Zt", strconv.Itoa(eigenschaftenMap["Zt"])); err != nil { return err } if err := writeRow("Au", strconv.Itoa(eigenschaftenMap["Au"])); err != nil { return err } if err := writeRow("pA", strconv.Itoa(eigenschaftenMap["PA"])); err != nil { return err } if err := writeRow("Wk", strconv.Itoa(eigenschaftenMap["Wk"])); err != nil { return err } // LP, AP, B, SchB, AbB, AnB if err := writeRow("LP", "AP", "B", "SchB", "AbB", "AnB"); err != nil { return err } if err := writeRow( strconv.Itoa(char.Lp.Max), strconv.Itoa(char.Ap.Max), strconv.Itoa(char.B.Max), "0", // SchB - not in model "0", // AbB - not in model "0", // AnB - not in model ); err != nil { return err } if err := writeRow(""); err != nil { return err } // Raufen, Abwehr (not in current model, use defaults) if err := writeRow("Raufen", "Abwehr"); err != nil { return err } if err := writeRow("7", "14"); err != nil { return err } // Resistenz if err := writeRow("Resistenz Geist", "Resistenz Körper"); err != nil { return err } if err := writeRow("0", "0"); err != nil { return err } if err := writeRow("Bonus Resistenz Geist", "Bonus Resistenz Körper"); err != nil { return err } if err := writeRow("0", "0"); err != nil { return err } if err := writeRow(""); err != nil { return err } // Waffen if err := writeRow("Waffe", "Erfolgswert", "Angriffsbonus", "Schadensbonus", "Abwehrbonus", "Praxispunkte"); err != nil { return err } for _, w := range char.Waffen { // Find corresponding weapon skill erfolgswert := 0 for _, ws := range char.Waffenfertigkeiten { if strings.Contains(w.Name, ws.Name) || strings.Contains(ws.Name, w.Name) { erfolgswert = ws.Fertigkeitswert break } } if err := writeRow( w.Name, strconv.Itoa(erfolgswert), strconv.Itoa(w.Anb), strconv.Itoa(w.Schb), strconv.Itoa(w.Abwb), "0", ); err != nil { return err } } if err := writeRow(""); err != nil { return err } // Rüstung (armor from equipment) if err := writeRow("Rüstung", "RK", "Rüstungsbonus"); err != nil { return err } for _, a := range char.Ausruestung { if strings.Contains(strings.ToLower(a.Name), "rüstung") || strings.Contains(strings.ToLower(a.Name), "armor") { if err := writeRow(a.Name, strconv.Itoa(a.Bonus), "0"); err != nil { return err } } } if err := writeRow(""); err != nil { return err } // Fertigkeiten if err := writeRow("Fertigkeit", "Erfolgswert", "Bonus", "Praxispunkte"); err != nil { return err } for _, f := range char.Fertigkeiten { desc := f.Beschreibung if desc != "" { desc = " (" + desc + ")" } if err := writeRow( f.Name+desc, strconv.Itoa(f.Fertigkeitswert), strconv.Itoa(f.Bonus), strconv.Itoa(f.Pp), ); err != nil { return err } } if err := writeRow(""); err != nil { return err } // Zauber section (if character has spells) if len(char.Zauber) > 0 { if err := writeRow("Zaubern", "ZauB"); err != nil { return err } if err := writeRow("0", "0"); err != nil { // Placeholder values return err } if err := writeRow("Zauber", "Bonus", "Praxispunkte"); err != nil { return err } for _, z := range char.Zauber { if err := writeRow(z.Name, strconv.Itoa(z.Bonus), "0"); err != nil { return err } } if err := writeRow(""); err != nil { return err } } // Ausrüstung (equipment list) if err := writeRow("Ausrüstung"); err != nil { return err } var equipmentNames []string for _, a := range char.Ausruestung { equipmentNames = append(equipmentNames, a.Name) } for _, b := range char.Behaeltnisse { equipmentNames = append(equipmentNames, b.Name) } for _, t := range char.Transportmittel { equipmentNames = append(equipmentNames, t.Name) } if len(equipmentNames) > 0 { if err := writeRow(strings.Join(equipmentNames, ";")); err != nil { return err } } if err := writeRow(""); err != nil { return err } // Erfahrung if err := writeRow("Erfahrung"); err != nil { return err } if err := writeRow("Erfahrungsschatz", "EP", "Gold"); err != nil { return err } if err := writeRow( strconv.Itoa(char.Erfahrungsschatz.ES), "0", // EP not in model "0", // Gold not in model ); err != nil { return err } return nil }