added tests for real char exported from Moam

This commit is contained in:
2026-02-27 12:00:43 +01:00
parent 64eacdab47
commit f738aafe7a
12 changed files with 5071 additions and 3 deletions
+686 -1
View File
@@ -5,6 +5,8 @@ import (
"encoding/json"
"os"
"testing"
"github.com/stretchr/testify/assert"
)
// TestDetectMoamFormat verifies that Moam VTT format can be detected
@@ -39,7 +41,7 @@ func TestDetectNonMoamFormat(t *testing.T) {
}
}
// TestConvertMoamToBMRT verifies conversion from Moam to BMRT format
// TestConvertMoamToBMRT verifies conversion from Moam Import data to BMRT format
func TestConvertMoamToBMRT(t *testing.T) {
data, err := os.ReadFile("testdata/moam_character.json")
if err != nil {
@@ -291,3 +293,686 @@ func TestContainerHierarchy(t *testing.T) {
t.Errorf("Expected weapon in container-1, got '%s'", bmrt.Waffen[0].BeinhaltetIn)
}
}
// testing a real char
func TestCharRealEinskaldir(t *testing.T) {
data, err := os.ReadFile("testdata/einskaldir.json")
if err != nil {
t.Fatalf("Failed to read test data: %v", err)
}
var moamChar MoamCharacter
if err := json.Unmarshal(data, &moamChar); err != nil {
t.Fatalf("Failed to parse Moam JSON: %v", err)
}
bmrt, err := toBMRT(&moamChar)
assert.NoErrorf(t, err, "Conversion to BMRT failed")
assert.Equalf(t, "Einskaldir", bmrt.Name, "Expected name 'Einskaldir', got '%s'", bmrt.Name)
}
// TestGalaxisKessariusRufusComprehensive tests the complete conversion of the Galaxis character
// including all slices, umlauts (UTF-8), and container relationships
func TestGalaxisKessariusRufusComprehensive(t *testing.T) {
data, err := os.ReadFile("testdata/galaxis-kessarius-rufus.json")
if err != nil {
t.Fatalf("Failed to read test data: %v", err)
}
var moamChar MoamCharacter
if err := json.Unmarshal(data, &moamChar); err != nil {
t.Fatalf("Failed to parse Moam JSON: %v", err)
}
bmrt, err := toBMRT(&moamChar)
assert.NoError(t, err, "Conversion to BMRT failed")
// Test basic character data with umlauts
assert.Equal(t, "Galaxis Kessarius Rufus", bmrt.Name, "Character name mismatch")
assert.Equal(t, 13, bmrt.Grad, "Character grade mismatch")
assert.Equal(t, "Mensch", bmrt.Rasse, "Character race mismatch")
assert.Equal(t, "Thaumaturg", bmrt.Typ, "Character type mismatch")
assert.Equal(t, 19, bmrt.Groesse, "Character size mismatch")
assert.Equal(t, 10, bmrt.Gewicht, "Character weight mismatch")
assert.Equal(t, 18, bmrt.Alter, "Character age mismatch")
assert.Equal(t, "Mittelschicht", bmrt.SocialClass, "Social class mismatch")
assert.Equal(t, "Jakchos", bmrt.Glaube, "Religion mismatch")
// Test eigenschaften
assert.Equal(t, 96, bmrt.Eigenschaften.St, "Stärke (St) mismatch")
assert.Equal(t, 65, bmrt.Eigenschaften.Gs, "Geschicklichkeit (Gs) mismatch")
assert.Equal(t, 62, bmrt.Eigenschaften.Gw, "Gewandtheit (Gw) mismatch")
assert.Equal(t, 87, bmrt.Eigenschaften.Ko, "Konstitution (Ko) mismatch")
assert.Equal(t, 76, bmrt.Eigenschaften.In, "Intelligenz (In) mismatch")
assert.Equal(t, 100, bmrt.Eigenschaften.Zt, "Zaubertaltent (Zt) mismatch")
// Test LP/AP/B
assert.Equal(t, 19, bmrt.Lp.Max, "LP Max mismatch")
assert.Equal(t, 19, bmrt.Lp.Value, "LP Value mismatch")
assert.Equal(t, 61, bmrt.Ap.Max, "AP Max mismatch")
assert.Equal(t, 61, bmrt.Ap.Value, "AP Value mismatch")
assert.Equal(t, 28, bmrt.B.Max, "B Max mismatch")
// Test Fertigkeiten (sample with umlauts)
assert.Equal(t, 29, len(bmrt.Fertigkeiten), "Fertigkeiten count mismatch")
// Sample fertigkeiten with umlauts
var gelaendelauf *importer.Fertigkeit
var geschaeftssinn *importer.Fertigkeit
var ueberleben *importer.Fertigkeit
var ueberlebenGebirge *importer.Fertigkeit
for i := range bmrt.Fertigkeiten {
f := &bmrt.Fertigkeiten[i]
switch f.Name {
case "Geländelauf":
gelaendelauf = f
case "Geschäftssinn":
geschaeftssinn = f
case "Überleben":
ueberleben = f
case "Überleben:Gebirge":
ueberlebenGebirge = f
}
}
assert.NotNil(t, gelaendelauf, "Geländelauf not found")
assert.Equal(t, 12, gelaendelauf.Fertigkeitswert, "Geländelauf value mismatch")
assert.Equal(t, "KOD5 112", gelaendelauf.Quelle, "Geländelauf source mismatch")
assert.NotNil(t, geschaeftssinn, "Geschäftssinn not found")
assert.Equal(t, 10, geschaeftssinn.Fertigkeitswert, "Geschäftssinn value mismatch")
assert.Equal(t, "KOD5 113", geschaeftssinn.Quelle, "Geschäftssinn source mismatch")
assert.NotNil(t, ueberleben, "Überleben not found")
assert.Equal(t, 8, ueberleben.Fertigkeitswert, "Überleben value mismatch")
assert.Equal(t, "Wald", ueberleben.Beschreibung, "Überleben description mismatch")
assert.NotNil(t, ueberlebenGebirge, "Überleben:Gebirge not found")
assert.Equal(t, 5, ueberlebenGebirge.Fertigkeitswert, "Überleben:Gebirge value mismatch")
// Test Waffenfertigkeiten (all with umlauts)
assert.Equal(t, 3, len(bmrt.Waffenfertigkeiten), "Waffenfertigkeiten count mismatch")
var armbrueste *importer.Waffenfertigkeit
var blasrohre *importer.Waffenfertigkeit
for i := range bmrt.Waffenfertigkeiten {
wf := &bmrt.Waffenfertigkeiten[i]
switch wf.Name {
case "Armbrüste":
armbrueste = wf
case "Blasrohre":
blasrohre = wf
}
}
assert.NotNil(t, armbrueste, "Armbrüste not found")
assert.Equal(t, 7, armbrueste.Fertigkeitswert, "Armbrüste value mismatch")
assert.NotNil(t, blasrohre, "Blasrohre not found")
assert.Equal(t, 9, blasrohre.Fertigkeitswert, "Blasrohre value mismatch")
// Test Zauber (sample with umlauts and special characters)
assert.Equal(t, 34, len(bmrt.Zauber), "Zauber count mismatch")
var staerke *importer.Zauber
var vergroessern *importer.Zauber
var zuendersalz *importer.Zauber
var loeschsalz *importer.Zauber
var feuerFinger *importer.Zauber
var handauflegen *importer.Zauber
for i := range bmrt.Zauber {
z := &bmrt.Zauber[i]
switch z.Name {
case "Stärke (S)":
staerke = z
case "Vergrößern (S)":
vergroessern = z
case "Zündersalz":
zuendersalz = z
case "Löschsalz":
loeschsalz = z
case "Feuerfinger (R)":
feuerFinger = z
case "Handauflegen":
handauflegen = z
}
}
assert.NotNil(t, staerke, "Stärke (S) not found")
assert.Equal(t, "MYS5 61", staerke.Quelle, "Stärke source mismatch")
assert.NotNil(t, vergroessern, "Vergrößern (S) not found")
assert.Equal(t, "MYS5 61", vergroessern.Quelle, "Vergrößern source mismatch")
assert.NotNil(t, zuendersalz, "Zündersalz not found")
assert.Equal(t, "MYS5 50", zuendersalz.Quelle, "Zündersalz source mismatch")
assert.NotNil(t, loeschsalz, "Löschsalz not found")
assert.Equal(t, "MYS5 48", loeschsalz.Quelle, "Löschsalz source mismatch")
assert.NotNil(t, feuerFinger, "Feuerfinger (R) not found")
assert.Equal(t, "MYS5 53", feuerFinger.Quelle, "Feuerfinger source mismatch")
assert.NotNil(t, handauflegen, "Handauflegen not found")
assert.Equal(t, "ARK5 143", handauflegen.Quelle, "Handauflegen source mismatch")
// Test Waffen
assert.Equal(t, 4, len(bmrt.Waffen), "Waffen count mismatch")
var armbrust *importer.Waffe
for i := range bmrt.Waffen {
if bmrt.Waffen[i].Name == "Armbrust:leicht" {
armbrust = &bmrt.Waffen[i]
break
}
}
assert.NotNil(t, armbrust, "Armbrust:leicht not found")
assert.Equal(t, 2.5, armbrust.Gewicht, "Armbrust weight mismatch")
assert.Equal(t, 40.0, armbrust.Wert, "Armbrust value mismatch")
assert.Equal(t, 1, armbrust.Anzahl, "Armbrust count mismatch")
// Test Ausruestung (with umlauts and container references)
assert.Equal(t, 11, len(bmrt.Ausruestung), "Ausruestung count mismatch")
var lederruestung *importer.Ausruestung
var koecher *importer.Ausruestung
var seil *importer.Ausruestung
for i := range bmrt.Ausruestung {
a := &bmrt.Ausruestung[i]
switch a.Name {
case "Lederrüstung":
lederruestung = a
case "Köcher, Bolzen":
koecher = a
case "Seil":
seil = a
}
}
assert.NotNil(t, lederruestung, "Lederrüstung not found")
assert.Equal(t, 13.0, lederruestung.Gewicht, "Lederrüstung weight mismatch")
assert.Equal(t, 30.0, lederruestung.Wert, "Lederrüstung value mismatch")
assert.Equal(t, "", lederruestung.BeinhaltetIn, "Lederrüstung should not be in container")
assert.NotNil(t, koecher, "Köcher not found")
assert.Equal(t, 0.3, koecher.Gewicht, "Köcher weight mismatch")
assert.NotNil(t, seil, "Seil not found")
assert.Equal(t, 0.075, seil.Gewicht, "Seil weight mismatch per unit")
assert.Equal(t, 20, seil.Anzahl, "Seil count mismatch")
assert.Equal(t, "moam-container-47422", seil.BeinhaltetIn, "Seil should be in Lederrucksack")
// Test Behaeltnisse (containers) and ContainedIn relationships
assert.Equal(t, 3, len(bmrt.Behaeltnisse), "Behaeltnisse count mismatch")
var lederrucksack *importer.Behaeltniss
var guerteltasche *importer.Behaeltniss
var lederhuelle *importer.Behaeltniss
for i := range bmrt.Behaeltnisse {
b := &bmrt.Behaeltnisse[i]
switch b.Name {
case "Lederrucksack":
lederrucksack = b
case "Gürteltasche, Leder":
guerteltasche = b
case "Lederhülle":
lederhuelle = b
}
}
assert.NotNil(t, lederrucksack, "Lederrucksack not found")
assert.Equal(t, "moam-container-47422", lederrucksack.ID, "Lederrucksack ID mismatch")
assert.Equal(t, 0.5, lederrucksack.Gewicht, "Lederrucksack weight mismatch")
assert.Equal(t, 25.0, lederrucksack.Tragkraft, "Lederrucksack capacity mismatch")
assert.Equal(t, "", lederrucksack.BeinhaltetIn, "Lederrucksack should not be in another container")
assert.NotNil(t, guerteltasche, "Gürteltasche not found")
assert.Equal(t, "für 20 Münzen", guerteltasche.Beschreibung, "Gürteltasche description with umlaut mismatch")
assert.Equal(t, 1.0, guerteltasche.Tragkraft, "Gürteltasche capacity mismatch")
assert.NotNil(t, lederhuelle, "Lederhülle not found")
assert.Equal(t, "wasserdicht für Schriftrollen", lederhuelle.Beschreibung, "Lederhülle description with umlaut mismatch")
// Verify items contained in Lederrucksack (moam-container-47422)
itemsInBackpack := 0
for i := range bmrt.Ausruestung {
if bmrt.Ausruestung[i].BeinhaltetIn == "moam-container-47422" {
itemsInBackpack++
}
}
assert.Equal(t, 6, itemsInBackpack, "Expected 6 items in Lederrucksack")
// Test Transportmittel
assert.Equal(t, 0, len(bmrt.Transportmittel), "Transportmittel should be empty")
assert.NotNil(t, bmrt.Transportmittel, "Transportmittel should not be nil")
// Test gestalt with umlauts
assert.Equal(t, "klein", bmrt.Gestalt.Groesse, "Gestalt Größe mismatch")
assert.Equal(t, "breit", bmrt.Gestalt.Breite, "Gestalt Breite mismatch")
// Test merkmale (should preserve UTF-8 empty strings)
assert.NotNil(t, bmrt.Merkmale, "Merkmale should not be nil")
// Test erfahrungsschatz
assert.Equal(t, 3960, bmrt.Erfahrungsschatz.Value, "Erfahrungsschatz mismatch")
}
// TestDorinSchnellhammerComprehensive tests the complete conversion of the Dorin Schnellhammer character
// including all slices, umlauts (UTF-8), specializations, and container relationships
func TestDorinSchnellhammerComprehensive(t *testing.T) {
data, err := os.ReadFile("testdata/dorin-schnellhammer.json")
if err != nil {
t.Fatalf("Failed to read test data: %v", err)
}
var moamChar MoamCharacter
if err := json.Unmarshal(data, &moamChar); err != nil {
t.Fatalf("Failed to parse Moam JSON: %v", err)
}
bmrt, err := toBMRT(&moamChar)
assert.NoError(t, err, "Conversion to BMRT failed")
// Test basic character data with umlauts
assert.Equal(t, "Dorin Schnellhammer", bmrt.Name, "Character name mismatch")
assert.Equal(t, 16, bmrt.Grad, "Character grade mismatch")
assert.Equal(t, "Zwerg", bmrt.Rasse, "Character race mismatch")
assert.Equal(t, "Krieger", bmrt.Typ, "Character type mismatch")
assert.Equal(t, 145, bmrt.Groesse, "Character size mismatch")
assert.Equal(t, 78, bmrt.Gewicht, "Character weight mismatch")
assert.Equal(t, 74, bmrt.Alter, "Character age mismatch")
assert.Equal(t, "Volk", bmrt.SocialClass, "Social class mismatch")
assert.Equal(t, "Mahal", bmrt.Glaube, "Religion mismatch")
assert.Equal(t, "beide", bmrt.Hand, "Handedness mismatch")
// Test Spezialisierung
assert.Equal(t, 3, len(bmrt.Spezialisierung), "Spezialisierung count mismatch")
assert.Contains(t, bmrt.Spezialisierung, "Kriegshammer", "Missing Kriegshammer specialization")
assert.Contains(t, bmrt.Spezialisierung, "Schlachtbeil", "Missing Schlachtbeil specialization")
assert.Contains(t, bmrt.Spezialisierung, "Streitaxt", "Missing Streitaxt specialization")
// Test eigenschaften
assert.Equal(t, 99, bmrt.Eigenschaften.St, "Stärke (St) mismatch")
assert.Equal(t, 75, bmrt.Eigenschaften.Gs, "Geschicklichkeit (Gs) mismatch")
assert.Equal(t, 70, bmrt.Eigenschaften.Gw, "Gewandtheit (Gw) mismatch")
assert.Equal(t, 92, bmrt.Eigenschaften.Ko, "Konstitution (Ko) mismatch")
// Test LP/AP/B
assert.Equal(t, 20, bmrt.Lp.Max, "LP Max mismatch")
assert.Equal(t, 20, bmrt.Lp.Value, "LP Value mismatch")
assert.Equal(t, 56, bmrt.Ap.Max, "AP Max mismatch")
assert.Equal(t, 56, bmrt.Ap.Value, "AP Value mismatch")
assert.Equal(t, 24, bmrt.B.Max, "B Max mismatch")
// Test Fertigkeiten (sample with umlauts)
var anfuehren *importer.Fertigkeit
var beidhaendiger *importer.Fertigkeit
var gelaendelauf *importer.Fertigkeit
var kampfVollruestung *importer.Fertigkeit
for i := range bmrt.Fertigkeiten {
f := &bmrt.Fertigkeiten[i]
switch f.Name {
case "Anführen":
anfuehren = f
case "Beidhändiger Kampf":
beidhaendiger = f
case "Geländelauf":
gelaendelauf = f
case "Kampf in Vollrüstung":
kampfVollruestung = f
}
}
assert.NotNil(t, anfuehren, "Anführen not found")
assert.Equal(t, 10, anfuehren.Fertigkeitswert, "Anführen value mismatch")
assert.NotNil(t, beidhaendiger, "Beidhändiger Kampf not found")
assert.Equal(t, 15, beidhaendiger.Fertigkeitswert, "Beidhändiger Kampf value mismatch")
assert.NotNil(t, gelaendelauf, "Geländelauf not found")
assert.Equal(t, 14, gelaendelauf.Fertigkeitswert, "Geländelauf value mismatch")
assert.NotNil(t, kampfVollruestung, "Kampf in Vollrüstung not found")
assert.Equal(t, 15, kampfVollruestung.Fertigkeitswert, "Kampf in Vollrüstung value mismatch")
// Test Waffenfertigkeiten (with umlauts)
assert.Equal(t, 7, len(bmrt.Waffenfertigkeiten), "Waffenfertigkeiten count mismatch")
var armbrueste *importer.Waffenfertigkeit
var boegen *importer.Waffenfertigkeit
for i := range bmrt.Waffenfertigkeiten {
wf := &bmrt.Waffenfertigkeiten[i]
switch wf.Name {
case "Armbrüste":
armbrueste = wf
case "Bögen":
boegen = wf
}
}
assert.NotNil(t, armbrueste, "Armbrüste not found")
assert.Equal(t, 11, armbrueste.Fertigkeitswert, "Armbrüste value mismatch")
assert.NotNil(t, boegen, "Bögen not found")
assert.Equal(t, 10, boegen.Fertigkeitswert, "Bögen value mismatch")
// Test Zauber (should be empty)
assert.Equal(t, 0, len(bmrt.Zauber), "Zauber should be empty for warrior")
assert.NotNil(t, bmrt.Zauber, "Zauber should not be nil")
// Test Waffen
assert.Greater(t, len(bmrt.Waffen), 0, "Should have weapons")
var armbrust *importer.Waffe
for i := range bmrt.Waffen {
if bmrt.Waffen[i].Name == "Armbrust:leicht" {
armbrust = &bmrt.Waffen[i]
break
}
}
assert.NotNil(t, armbrust, "Armbrust:leicht not found")
// Test Ausruestung (with umlauts)
assert.Greater(t, len(bmrt.Ausruestung), 0, "Should have equipment")
var kettenruestung *importer.Ausruestung
for i := range bmrt.Ausruestung {
if bmrt.Ausruestung[i].Name == "Kettenrüstung" {
kettenruestung = &bmrt.Ausruestung[i]
break
}
}
assert.NotNil(t, kettenruestung, "Kettenrüstung not found")
assert.Equal(t, 20.0, kettenruestung.Gewicht, "Kettenrüstung weight mismatch")
assert.Equal(t, 100.0, kettenruestung.Wert, "Kettenrüstung value mismatch")
// Test Behaeltnisse (containers) with umlauts
assert.Equal(t, 4, len(bmrt.Behaeltnisse), "Behaeltnisse count mismatch")
var lederrucksack *importer.Behaeltniss
var beutel *importer.Behaeltniss
for i := range bmrt.Behaeltnisse {
b := &bmrt.Behaeltnisse[i]
switch b.Name {
case "Lederrucksack":
lederrucksack = b
case "Beutel, Leder":
beutel = b
}
}
assert.NotNil(t, lederrucksack, "Lederrucksack not found")
assert.Equal(t, "moam-container-59617", lederrucksack.ID, "Lederrucksack ID mismatch")
assert.Equal(t, "für 25 kg", lederrucksack.Beschreibung, "Lederrucksack description with umlaut mismatch")
assert.Equal(t, 25.0, lederrucksack.Tragkraft, "Lederrucksack capacity mismatch")
assert.Equal(t, "", lederrucksack.BeinhaltetIn, "Lederrucksack should not be in another container")
assert.NotNil(t, beutel, "Beutel, Leder not found")
assert.Equal(t, "für 20 Münzen", beutel.Beschreibung, "Beutel description with umlaut mismatch")
// Verify items contained in Lederrucksack (moam-container-59617)
itemsInBackpack := 0
for i := range bmrt.Ausruestung {
if bmrt.Ausruestung[i].BeinhaltetIn == "moam-container-59617" {
itemsInBackpack++
}
}
assert.Equal(t, 5, itemsInBackpack, "Expected 5 items in Lederrucksack")
// Test Transportmittel
assert.Equal(t, 1, len(bmrt.Transportmittel), "Should have 1 transportmittel")
assert.Equal(t, "Reitpferd (Transportmittel)", bmrt.Transportmittel[0].Name, "Transportmittel name mismatch")
// Test gestalt
assert.Equal(t, "klein", bmrt.Gestalt.Groesse, "Gestalt Größe mismatch")
assert.Equal(t, "normal", bmrt.Gestalt.Breite, "Gestalt Breite mismatch")
// Test erfahrungsschatz
assert.Equal(t, 5586, bmrt.Erfahrungsschatz.Value, "Erfahrungsschatz mismatch")
// Test Image transfer - Dorin has a base64 image
assert.NotEmpty(t, bmrt.Image, "Character image should be transferred")
assert.Contains(t, bmrt.Image, "data:image;base64,", "Image should be base64 encoded")
assert.Greater(t, len(bmrt.Image), 100, "Image data should be substantial")
}
// TestNicoloSikeriComprehensive tests the complete conversion of the Nicolo Sikeri character
// including all slices, umlauts (UTF-8), priest spells, and container relationships
func TestNicoloSikeriComprehensive(t *testing.T) {
data, err := os.ReadFile("testdata/nicolo-sikeri.json")
if err != nil {
t.Fatalf("Failed to read test data: %v", err)
}
var moamChar MoamCharacter
if err := json.Unmarshal(data, &moamChar); err != nil {
t.Fatalf("Failed to parse Moam JSON: %v", err)
}
bmrt, err := toBMRT(&moamChar)
assert.NoError(t, err, "Conversion to BMRT failed")
// Test basic character data
assert.Equal(t, "Nicolo Sikeri", bmrt.Name, "Character name mismatch")
assert.Equal(t, 7, bmrt.Grad, "Character grade mismatch")
assert.Equal(t, "Mensch", bmrt.Rasse, "Character race mismatch")
assert.Equal(t, "Priester, Beschützer", bmrt.Typ, "Character type with umlaut mismatch")
assert.Equal(t, 172, bmrt.Groesse, "Character size mismatch")
assert.Equal(t, 80, bmrt.Gewicht, "Character weight mismatch")
assert.Equal(t, 23, bmrt.Alter, "Character age mismatch")
assert.Equal(t, "Volk", bmrt.SocialClass, "Social class mismatch")
assert.Equal(t, "Notuns", bmrt.Glaube, "Religion mismatch")
// Test Spezialisierung (should be empty)
assert.Equal(t, 0, len(bmrt.Spezialisierung), "Spezialisierung should be empty")
assert.NotNil(t, bmrt.Spezialisierung, "Spezialisierung should not be nil")
// Test eigenschaften
assert.Equal(t, 95, bmrt.Eigenschaften.St, "Stärke (St) mismatch")
assert.Equal(t, 99, bmrt.Eigenschaften.Gs, "Geschicklichkeit (Gs) mismatch")
assert.Equal(t, 89, bmrt.Eigenschaften.Gw, "Gewandtheit (Gw) mismatch")
assert.Equal(t, 100, bmrt.Eigenschaften.Zt, "Zaubertalent (Zt) mismatch")
// Test LP/AP/B
assert.Equal(t, 15, bmrt.Lp.Max, "LP Max mismatch")
assert.Equal(t, 15, bmrt.Lp.Value, "LP Value mismatch")
assert.Equal(t, 34, bmrt.Ap.Max, "AP Max mismatch")
assert.Equal(t, 29, bmrt.Ap.Value, "AP Value mismatch")
assert.Equal(t, 23, bmrt.B.Max, "B Max mismatch")
// Test Merkmale with umlauts
assert.NotNil(t, bmrt.Merkmale, "Merkmale should not be nil")
assert.Equal(t, "Schwarz", bmrt.Merkmale.Haarfarbe, "Haarfarbe mismatch")
assert.Equal(t, "grün", bmrt.Merkmale.Augenfarbe, "Augenfarbe with umlaut mismatch")
// Test Waffenfertigkeiten
assert.Equal(t, 2, len(bmrt.Waffenfertigkeiten), "Waffenfertigkeiten count mismatch")
var einhandschlagwaffen *importer.Waffenfertigkeit
for i := range bmrt.Waffenfertigkeiten {
if bmrt.Waffenfertigkeiten[i].Name == "Einhandschlagwaffen" {
einhandschlagwaffen = &bmrt.Waffenfertigkeiten[i]
break
}
}
assert.NotNil(t, einhandschlagwaffen, "Einhandschlagwaffen not found")
assert.Equal(t, 9, einhandschlagwaffen.Fertigkeitswert, "Einhandschlagwaffen value mismatch")
// Test Zauber (priest spells with umlauts)
assert.Equal(t, 18, len(bmrt.Zauber), "Zauber count mismatch")
// Check for spell with umlaut 'ö'
foundBoesen := false
for i := range bmrt.Zauber {
if bmrt.Zauber[i].Name == "Austreibung des Bösen" {
foundBoesen = true
assert.Equal(t, "ARK5 136", bmrt.Zauber[i].Quelle, "Austreibung des Bösen source mismatch")
break
}
}
assert.True(t, foundBoesen, "Austreibung des Bösen not found")
// Check for spell with umlaut 'ä'
foundStaerke := false
for i := range bmrt.Zauber {
if bmrt.Zauber[i].Name == "Stärke" {
foundStaerke = true
assert.Equal(t, "ARK5 115", bmrt.Zauber[i].Quelle, "Stärke source mismatch")
break
}
}
assert.True(t, foundStaerke, "Stärke not found")
// Test Waffen
assert.Equal(t, 3, len(bmrt.Waffen), "Waffen count mismatch")
var kriegshammer *importer.Waffe
var streitaxt *importer.Waffe
for i := range bmrt.Waffen {
w := &bmrt.Waffen[i]
switch w.Name {
case "Kriegshammer":
kriegshammer = w
case "Streitaxt":
streitaxt = w
}
}
assert.NotNil(t, kriegshammer, "Kriegshammer not found")
assert.Equal(t, 2.5, kriegshammer.Gewicht, "Kriegshammer weight mismatch")
assert.NotNil(t, streitaxt, "Streitaxt not found")
assert.Equal(t, 2.5, streitaxt.Gewicht, "Streitaxt weight mismatch")
// Test Behaeltnisse (containers) with umlauts
assert.Equal(t, 8, len(bmrt.Behaeltnisse), "Behaeltnisse count mismatch")
var lederrucksack *importer.Behaeltniss
var guerteltasche *importer.Behaeltniss
var lederhuelle *importer.Behaeltniss
var tuschegefaess *importer.Behaeltniss
for i := range bmrt.Behaeltnisse {
b := &bmrt.Behaeltnisse[i]
switch b.Name {
case "Lederrucksack":
lederrucksack = b
case "Gürteltasche, Leder":
guerteltasche = b
case "Lederhülle":
lederhuelle = b
case "Tuschegefäß":
tuschegefaess = b
}
}
assert.NotNil(t, lederrucksack, "Lederrucksack not found")
assert.Equal(t, "moam-container-53059", lederrucksack.ID, "Lederrucksack ID mismatch")
assert.Equal(t, "für 25 kg", lederrucksack.Beschreibung, "Lederrucksack description with umlaut mismatch")
assert.Equal(t, 25.0, lederrucksack.Tragkraft, "Lederrucksack capacity mismatch")
assert.Equal(t, "", lederrucksack.BeinhaltetIn, "Lederrucksack should not be in another container")
assert.NotNil(t, guerteltasche, "Gürteltasche not found")
assert.Equal(t, "für 20 Münzen", guerteltasche.Beschreibung, "Gürteltasche description with umlaut mismatch")
assert.NotNil(t, lederhuelle, "Lederhülle not found")
assert.Equal(t, "wasserdicht für Schriftrollen", lederhuelle.Beschreibung, "Lederhülle description with umlaut mismatch")
assert.NotNil(t, tuschegefaess, "Tuschegefäß not found")
assert.Equal(t, "1/20 Liter", tuschegefaess.Beschreibung, "Tuschegefäß description mismatch")
// Verify items contained in Lederrucksack (moam-container-53059)
itemsInBackpack := 0
for i := range bmrt.Ausruestung {
if bmrt.Ausruestung[i].BeinhaltetIn == "moam-container-53059" {
itemsInBackpack++
}
}
assert.Equal(t, 6, itemsInBackpack, "Expected 6 items in Lederrucksack")
// Test Transportmittel (should be empty)
assert.Equal(t, 0, len(bmrt.Transportmittel), "Transportmittel should be empty")
assert.NotNil(t, bmrt.Transportmittel, "Transportmittel should not be nil")
// Test gestalt
assert.Equal(t, "mittel", bmrt.Gestalt.Groesse, "Gestalt Größe mismatch")
assert.Equal(t, "breit", bmrt.Gestalt.Breite, "Gestalt Breite mismatch")
// Test erfahrungsschatz
assert.Equal(t, 1300, bmrt.Erfahrungsschatz.Value, "Erfahrungsschatz mismatch")
// Test Image transfer - Nicolo has a base64 image
assert.NotEmpty(t, bmrt.Image, "Character image should be transferred")
assert.Contains(t, bmrt.Image, "data:image;base64,", "Image should be base64 encoded")
assert.Greater(t, len(bmrt.Image), 100, "Image data should be substantial")
// Verify image starts with correct PNG header (after base64 prefix)
assert.Contains(t, bmrt.Image, "iVBORw0KGgo", "Image should contain PNG base64 signature")
}
// TestImageTransfer verifies that character images are correctly transferred during conversion
func TestImageTransfer(t *testing.T) {
// Test 1: Character WITH image (Dorin Schnellhammer)
data, err := os.ReadFile("testdata/dorin-schnellhammer.json")
assert.NoError(t, err, "Failed to read Dorin test data")
var dorinChar MoamCharacter
err = json.Unmarshal(data, &dorinChar)
assert.NoError(t, err, "Failed to parse Dorin JSON")
dorinBmrt, err := toBMRT(&dorinChar)
assert.NoError(t, err, "Dorin conversion to BMRT failed")
// Verify image was transferred
assert.NotEmpty(t, dorinBmrt.Image, "Dorin image should be transferred")
assert.Contains(t, dorinBmrt.Image, "data:image;base64,", "Image should have base64 prefix")
assert.Greater(t, len(dorinBmrt.Image), 1000, "Image should have substantial data")
// Test 2: Character WITH image (Nicolo Sikeri)
data, err = os.ReadFile("testdata/nicolo-sikeri.json")
assert.NoError(t, err, "Failed to read Nicolo test data")
var nicoloChar MoamCharacter
err = json.Unmarshal(data, &nicoloChar)
assert.NoError(t, err, "Failed to parse Nicolo JSON")
nicoloBmrt, err := toBMRT(&nicoloChar)
assert.NoError(t, err, "Nicolo conversion to BMRT failed")
// Verify image was transferred
assert.NotEmpty(t, nicoloBmrt.Image, "Nicolo image should be transferred")
assert.Contains(t, nicoloBmrt.Image, "data:image;base64,", "Image should have base64 prefix")
// Test 3: Character WITHOUT image (Galaxis)
data, err = os.ReadFile("testdata/galaxis-kessarius-rufus.json")
assert.NoError(t, err, "Failed to read Galaxis test data")
var galaxisChar MoamCharacter
err = json.Unmarshal(data, &galaxisChar)
assert.NoError(t, err, "Failed to parse Galaxis JSON")
galaxisBmrt, err := toBMRT(&galaxisChar)
assert.NoError(t, err, "Galaxis conversion to BMRT failed")
// Verify no image field (empty string is acceptable)
assert.Empty(t, galaxisBmrt.Image, "Galaxis should have no image")
// Test 4: Round-trip conversion preserves image
convertedMoam, err := fromBMRT(dorinBmrt)
assert.NoError(t, err, "Failed to convert back to MOAM")
// Verify image survived round-trip
assert.Equal(t, dorinBmrt.Image, convertedMoam.Image, "Image should be preserved in round-trip conversion")
assert.NotEmpty(t, convertedMoam.Image, "Round-trip image should not be empty")
}
+7
View File
@@ -9,6 +9,12 @@ require (
github.com/gin-gonic/gin v1.11.0
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/bytedance/gopkg v0.1.3 // indirect
@@ -35,6 +41,7 @@ require (
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/quic-go/quic-go v0.59.0 // indirect
github.com/stretchr/testify v1.11.1
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.3.1 // indirect
golang.org/x/arch v0.24.0 // indirect
+8
View File
@@ -43,6 +43,10 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
@@ -62,6 +66,8 @@ github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -93,6 +99,8 @@ golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+8
View File
@@ -31,6 +31,7 @@ type AdapterMetadata struct {
SupportedExtensions []string `json:"supported_extensions"`
SupportedVersions []string `json:"supported_game_versions"`
Capabilities []string `json:"capabilities"`
Description string `json:"description"`
}
// DetectResponse contains the confidence score and detected version
@@ -82,6 +83,7 @@ func metadataHandler(c *gin.Context) {
SupportedExtensions: []string{".json"},
SupportedVersions: []string{"5.x"},
Capabilities: []string{"import", "export", "detect"},
Description: "Adapter for importing and exporting characters in the Moam VTT JSON format Supports Characters created for Midgard Version 5.",
}
c.JSON(http.StatusOK, metadata)
@@ -251,6 +253,11 @@ func toBMRT(moam *MoamCharacter) (*importer.CharacterImport, error) {
if bmrt.Spezialisierung == nil {
bmrt.Spezialisierung = []string{}
}
if moam.Stand == "" {
bmrt.SocialClass = "Mittelschicht" // Default social class if not specified
} else {
bmrt.SocialClass = moam.Stand
}
// Note: Moam-specific fields like "Stand" are dropped during conversion
// If we needed to preserve them, we would store them in Extensions field
@@ -272,6 +279,7 @@ func fromBMRT(bmrt *importer.CharacterImport) (*MoamCharacter, error) {
moam := &MoamCharacter{
CharacterImport: *bmrt,
}
moam.Stand = bmrt.SocialClass // Map social class back to Moam's "Stand"
// Could set Moam-specific defaults here if needed
// For example: moam.Stand = "Nicht festgelegt"
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,848 @@
{
"id": "moam-character-21323",
"name": "Galaxis Kessarius Rufus",
"grad": 13,
"erfahrungsschatz": {
"value": 3960
},
"spezialisierung": [],
"anrede": "er",
"rasse": "Mensch",
"typ": "Thaumaturg",
"groesse": 19,
"gewicht": 10,
"gestalt": {
"groesse": "klein",
"breite": "breit"
},
"stand": "Mittelschicht",
"alter": 18,
"glaube": "Jakchos",
"lp": {
"value": 19,
"max": 19
},
"ap": {
"value": 61,
"max": 61
},
"b": {
"max": 28
},
"hand": "links",
"merkmale": {
"haarfarbe": "",
"augenfarbe": "",
"sonstige": ""
},
"eigenschaften": {
"st": 96,
"gs": 65,
"gw": 62,
"ko": 87,
"in": 76,
"zt": 100,
"pa": 100,
"au": 76,
"wk": 74
},
"bennies": {
"sg": 7,
"gg": 0,
"gp": 0
},
"fertigkeiten": [
{
"id": "moam-ability-horen",
"name": "Hören",
"fertigkeitswert": 6,
"quelle": "KOD5 99"
},
{
"id": "moam-ability-nachtsicht",
"name": "Nachtsicht",
"fertigkeitswert": 6,
"quelle": "KOD5 99"
},
{
"id": "moam-ability-riechen",
"name": "Riechen",
"fertigkeitswert": 6,
"quelle": "KOD5 99"
},
{
"id": "moam-ability-sechster_sinn",
"name": "Sechster Sinn",
"fertigkeitswert": 6,
"quelle": "KOD5 100"
},
{
"id": "moam-ability-sehen",
"name": "Sehen",
"fertigkeitswert": 6,
"quelle": "KOD5 100"
},
{
"id": "moam-ability-wahrnehmung",
"name": "Wahrnehmung",
"fertigkeitswert": 6,
"quelle": "KOD5 98"
},
{
"id": "moam-ability-376923",
"name": "Alchimie",
"fertigkeitswert": 9,
"bonus": 0,
"pp": 0,
"beschreibung": null,
"quelle": "KOD5 102"
},
{
"id": "moam-ability-762171",
"name": "Beredsamkeit",
"fertigkeitswert": 8,
"bonus": 0,
"pp": 0,
"beschreibung": null,
"quelle": "KOD5 105"
},
{
"id": "moam-ability-762178",
"name": "Fallenmechanik",
"fertigkeitswert": 8,
"bonus": 0,
"pp": 0,
"beschreibung": null,
"quelle": "KOD5 110"
},
{
"id": "moam-ability-762180",
"name": "Gel\u00e4ndelauf",
"fertigkeitswert": 12,
"bonus": 0,
"pp": 0,
"beschreibung": null,
"quelle": "KOD5 112"
},
{
"id": "moam-ability-762177",
"name": "Gesch\u00e4ftssinn",
"fertigkeitswert": 10,
"bonus": 0,
"pp": 0,
"beschreibung": null,
"quelle": "KOD5 113"
},
{
"id": "moam-ability-376922",
"name": "Giftmischen",
"fertigkeitswert": 7,
"bonus": 0,
"pp": 1,
"beschreibung": null,
"quelle": ""
},
{
"id": "moam-ability-762172",
"name": "Klettern",
"fertigkeitswert": 12,
"bonus": 0,
"pp": 0,
"beschreibung": null,
"quelle": "KOD5 115"
},
{
"id": "moam-ability-762179",
"name": "Laufen",
"fertigkeitswert": 8,
"bonus": 0,
"pp": 0,
"beschreibung": null,
"quelle": "KOD5 116"
},
{
"id": "moam-ability-762169",
"name": "Lesen von Zauberschrift",
"fertigkeitswert": 8,
"bonus": 0,
"pp": 0,
"beschreibung": null,
"quelle": "KOD5 117"
},
{
"id": "moam-ability-376924",
"name": "Pflanzenkunde",
"fertigkeitswert": 9,
"bonus": 0,
"pp": 0,
"beschreibung": null,
"quelle": "KOD5 120"
},
{
"id": "moam-ability-35333",
"name": "Robustheit",
"fertigkeitswert": 9,
"bonus": 0,
"pp": 0,
"beschreibung": null,
"quelle": "KOD5 97"
},
{
"id": "moam-ability-376818",
"name": "Schreiben",
"fertigkeitswert": 12,
"bonus": 0,
"pp": 0,
"beschreibung": "Chryseisch",
"quelle": "KOD5 124"
},
{
"id": "moam-ability-762176",
"name": "Schreiben",
"fertigkeitswert": 8,
"bonus": 0,
"pp": 0,
"beschreibung": "Erainisch",
"quelle": "KOD5 124"
},
{
"id": "moam-ability-762173",
"name": "Seilkunst",
"fertigkeitswert": 12,
"bonus": 0,
"pp": 1,
"beschreibung": null,
"quelle": "KOD5 126"
},
{
"id": "moam-ability-376815",
"name": "Sprache",
"fertigkeitswert": 12,
"bonus": 0,
"pp": 0,
"beschreibung": "Chryseisch",
"quelle": "KOD5 127"
},
{
"id": "moam-ability-376816",
"name": "Sprache",
"fertigkeitswert": 12,
"bonus": 0,
"pp": 0,
"beschreibung": "Comentang",
"quelle": "KOD5 127"
},
{
"id": "moam-ability-762183",
"name": "Sprache",
"fertigkeitswert": 8,
"bonus": 0,
"pp": 0,
"beschreibung": "Erainisch",
"quelle": "KOD5 127"
},
{
"id": "moam-ability-762182",
"name": "Sprache",
"fertigkeitswert": 8,
"bonus": 0,
"pp": 0,
"beschreibung": "Valianisch",
"quelle": "KOD5 127"
},
{
"id": "moam-ability-762181",
"name": "Sprache",
"fertigkeitswert": 8,
"bonus": 0,
"pp": 0,
"beschreibung": "Waelska",
"quelle": "KOD5 127"
},
{
"id": "moam-ability-762170",
"name": "Thaumagraphie",
"fertigkeitswert": 8,
"bonus": 0,
"pp": 0,
"beschreibung": null,
"quelle": "MYS5 23"
},
{
"id": "moam-ability-762175",
"name": "\u00dcberleben",
"fertigkeitswert": 8,
"bonus": 0,
"pp": 0,
"beschreibung": "Wald",
"quelle": "KOD5 131"
},
{
"id": "moam-ability-762174",
"name": "\u00dcberleben:Gebirge",
"fertigkeitswert": 5,
"bonus": 0,
"pp": 0,
"beschreibung": "Gebirge",
"quelle": ""
},
{
"id": "moam-ability-376817",
"name": "Zauberkunde",
"fertigkeitswert": 8,
"bonus": 0,
"pp": 1,
"beschreibung": null,
"quelle": "KOD5 134"
}
],
"waffenfertigkeiten": [
{
"id": "moam-ability-762184",
"name": "Armbr\u00fcste",
"fertigkeitswert": 7,
"bonus": 0,
"pp": 0,
"beschreibung": null,
"quelle": "KOD5 144"
},
{
"id": "moam-ability-762185",
"name": "Blasrohre",
"fertigkeitswert": 9,
"bonus": 0,
"pp": 0,
"beschreibung": null,
"quelle": "KOD5 144"
},
{
"id": "moam-ability-762186",
"name": "Stichwaffen",
"fertigkeitswert": 6,
"bonus": 0,
"pp": 0,
"beschreibung": null,
"quelle": "KOD5 139"
}
],
"zauber": [
{
"id": "moam-spell-124479",
"name": "Bannen von Zauberwerk (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 55"
},
{
"id": "moam-spell-266056",
"name": "Befestigen (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 55"
},
{
"id": "moam-spell-266062",
"name": "Bittersalz",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 44"
},
{
"id": "moam-spell-266041",
"name": "Feuerfinger (R)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 53"
},
{
"id": "moam-spell-266057",
"name": "Feuerlanze (R)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 53"
},
{
"id": "moam-spell-266058",
"name": "Flammenklinge (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 57"
},
{
"id": "moam-spell-266047",
"name": "Flammenkreis (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 57"
},
{
"id": "moam-spell-266065",
"name": "Fliegensalz",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 46"
},
{
"id": "moam-spell-266066",
"name": "Funkensalz",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 46"
},
{
"id": "moam-spell-266060",
"name": "Haarsalz",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 46"
},
{
"id": "moam-spell-266042",
"name": "Handauflegen",
"bonus": 0,
"beschreibung": null,
"quelle": "ARK5 143"
},
{
"id": "moam-spell-266044",
"name": "Hauch des Winters (R)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 53"
},
{
"id": "moam-spell-266055",
"name": "Heranholen (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 58"
},
{
"id": "moam-spell-266064",
"name": "Hitzsalz",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 46"
},
{
"id": "moam-spell-266059",
"name": "Jucksalz",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 47"
},
{
"id": "moam-spell-266043",
"name": "Kr\u00e4ftigen (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 58"
},
{
"id": "moam-spell-266040",
"name": "Lauschen (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 58"
},
{
"id": "moam-spell-266067",
"name": "L\u00f6schsalz",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 48"
},
{
"id": "moam-spell-266054",
"name": "Rost (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 59"
},
{
"id": "moam-spell-266061",
"name": "Schleichsalz",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 49"
},
{
"id": "moam-spell-266037",
"name": "Sehen in Dunkelheit (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 60"
},
{
"id": "moam-spell-266039",
"name": "Sehen von Verborgenem",
"bonus": 0,
"beschreibung": null,
"quelle": "ARK5 113"
},
{
"id": "moam-spell-266052",
"name": "Silberstaub (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 61"
},
{
"id": "moam-spell-266053",
"name": "St\u00e4rke (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 61"
},
{
"id": "moam-spell-266048",
"name": "Stille (R)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 53"
},
{
"id": "moam-spell-266063",
"name": "Stottersalz",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 49"
},
{
"id": "moam-spell-266068",
"name": "Trampelsalz",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 50"
},
{
"id": "moam-spell-266049",
"name": "Unsichtbarkeit (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 61"
},
{
"id": "moam-spell-266051",
"name": "Vergr\u00f6\u00dfern (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 61"
},
{
"id": "moam-spell-266050",
"name": "Wasseratmen (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 64"
},
{
"id": "moam-spell-266038",
"name": "Zauberlicht (R)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 53"
},
{
"id": "moam-spell-266046",
"name": "Zauberschloss (S)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 66"
},
{
"id": "moam-spell-266045",
"name": "Zauberschl\u00fcssel (R)",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 53"
},
{
"id": "moam-spell-266069",
"name": "Z\u00fcndersalz",
"bonus": 0,
"beschreibung": null,
"quelle": "MYS5 50"
}
],
"waffen": [
{
"id": "moam-weapon-127083",
"name": "Armbrust:leicht",
"nameFuerSpezialisierung": "Armbrust:leicht",
"beschreibung": null,
"gewicht": 2.5,
"wert": 40.0,
"anb": 0,
"schb": 0,
"abwb": 0,
"anzahl": 1,
"beinhaltet_in": null,
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-weapon-127080",
"name": "Blasrohr:kurz",
"nameFuerSpezialisierung": "Blasrohr:kurz",
"beschreibung": null,
"gewicht": 0.5,
"wert": 5.0,
"anb": 0,
"schb": 0,
"abwb": 0,
"anzahl": 1,
"beinhaltet_in": null,
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-weapon-127081",
"name": "Blasrohr:lang",
"nameFuerSpezialisierung": "Blasrohr:lang",
"beschreibung": null,
"gewicht": 2.0,
"wert": 8.0,
"anb": 0,
"schb": 0,
"abwb": 0,
"anzahl": 1,
"beinhaltet_in": null,
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-weapon-127082",
"name": "Dolch",
"nameFuerSpezialisierung": "Dolch",
"beschreibung": null,
"gewicht": 0.5,
"wert": 5.0,
"anb": 0,
"schb": 0,
"abwb": 0,
"anzahl": 1,
"beinhaltet_in": null,
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
}
],
"ausruestung": [
{
"id": "moam-armor-48741",
"name": "Lederr\u00fcstung",
"beschreibung": null,
"gewicht": 13.0,
"wert": 30.0,
"bonus": 0,
"anzahl": 1,
"beinhaltet_in": null,
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-item-287440",
"name": "Armbrustbolzen",
"beschreibung": null,
"gewicht": 0.15,
"wert": 0.3,
"anzahl": 30,
"beinhaltet_in": null,
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-item-287436",
"name": "Blasrohrnadel",
"beschreibung": null,
"gewicht": 0.02,
"wert": 0.1,
"anzahl": 20,
"beinhaltet_in": null,
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-item-287435",
"name": "Decke, warm",
"beschreibung": null,
"gewicht": 2.0,
"wert": 4.0,
"anzahl": 1,
"beinhaltet_in": "moam-container-47422",
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-item-287437",
"name": "Dolchscheide, einfach",
"beschreibung": null,
"gewicht": 0.1,
"wert": 2.0,
"anzahl": 1,
"beinhaltet_in": null,
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-item-287443",
"name": "Feuerstein und Zunder",
"beschreibung": null,
"gewicht": 0.0,
"wert": 1.0,
"anzahl": 1,
"beinhaltet_in": "moam-container-47422",
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-item-287445",
"name": "Heiltrunk (1W6)",
"beschreibung": null,
"gewicht": 0.0,
"wert": 200.0,
"anzahl": 1,
"beinhaltet_in": "moam-container-47422",
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-item-287439",
"name": "K\u00f6cher, Bolzen",
"beschreibung": null,
"gewicht": 0.3,
"wert": 2.0,
"anzahl": 0,
"beinhaltet_in": null,
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-item-287438",
"name": "Kreidest\u00fcck",
"beschreibung": null,
"gewicht": 0.02,
"wert": 0.2,
"anzahl": 1,
"beinhaltet_in": "moam-container-47422",
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-item-287442",
"name": "Seil",
"beschreibung": null,
"gewicht": 0.075,
"wert": 1.0,
"anzahl": 20,
"beinhaltet_in": "moam-container-47422",
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-item-287444",
"name": "Zauber\u00f6l",
"beschreibung": null,
"gewicht": 0.2,
"wert": 20.0,
"anzahl": 1,
"beinhaltet_in": "moam-container-47422",
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
}
],
"behaeltnisse": [
{
"id": "moam-container-47423",
"name": "G\u00fcrteltasche, Leder",
"beschreibung": "f\u00fcr 20 M\u00fcnzen",
"gewicht": 0.01,
"wert": 2.0,
"volumen": 0.25,
"tragkraft": 1.0,
"beinhaltet_in": null,
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-container-47424",
"name": "Lederh\u00fclle",
"beschreibung": "wasserdicht f\u00fcr Schriftrollen",
"gewicht": 0.03,
"wert": 3.0,
"volumen": 0.3,
"tragkraft": 0.5,
"beinhaltet_in": null,
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
},
{
"id": "moam-container-47422",
"name": "Lederrucksack",
"beschreibung": "f\u00fcr 25 kg",
"gewicht": 0.5,
"wert": 4.0,
"volumen": 25.0,
"tragkraft": 25.0,
"beinhaltet_in": null,
"magisch": {
"ist_magisch": false,
"abw": 0,
"ausgebrannt": false
}
}
],
"transportmittel": [
]
}
+1 -1
View File
@@ -15,7 +15,7 @@
"groesse": "mittel",
"breite": "normal"
},
"stand": "Bürger",
"stand": "Mittelschicht",
"alter": 25,
"glaube": "keine",
"lp": {
File diff suppressed because one or more lines are too long
+1
View File
@@ -179,6 +179,7 @@ type CharacterImport struct {
Groesse int `json:"groesse"`
Gewicht int `json:"gewicht"`
Glaube string `json:"glaube"`
SocialClass string `json:"social_class"`
Hand string `json:"hand"`
Fertigkeiten []Fertigkeit `json:"fertigkeiten"`
Zauber []Zauber `json:"zauber"`
+1 -1
View File
@@ -17,8 +17,8 @@ type AdapterMetadata struct {
Version string `json:"version"` // e.g., "1.0"
BmrtVersions []string `json:"bmrt_versions"` // Supported BMRT versions
SupportedExtensions []string `json:"supported_extensions"` // e.g., [".json"]
BaseURL string `json:"base_url"` // e.g., "http://adapter-foundry:8181"
Capabilities []string `json:"capabilities"` // e.g., ["import", "export", "detect"]
BaseURL string `json:"base_url"` // e.g., "http://adapter-foundry:8181"
Healthy bool `json:"healthy"` // Runtime health status
LastCheckedAt time.Time `json:"last_checked_at"`
LastError string `json:"last_error,omitempty"`