Character display

added FeChar (FrontEndCharacter)
added marker for innate skills (angeborene Fertigkeiten) and category
added selector for innate skills at import
added marker for improvable skills
TestGetCharacters against real database
changed favicon
server frontend on '192.168.0.48', 'localhost','terrra.local'
added view DeleteCharView
fixed errors on rendering datasheetview
serve backend on 192.168.0.48
This commit is contained in:
2025-01-18 20:59:35 +01:00
parent dfe3602d20
commit 30a990b0cf
16 changed files with 209 additions and 26 deletions
+37 -1
View File
@@ -61,7 +61,8 @@ func GetCharacter(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve character"})
return
}
c.JSON(http.StatusOK, character)
feChar := ToFeChar(&character)
c.JSON(http.StatusOK, feChar)
}
func UpdateCharacter(c *gin.Context) {
var character Char
@@ -119,3 +120,38 @@ func AddFertigkeit(charID uint, fertigkeit *skills.Fertigkeit) error {
// Append the new Fertigkeit to the slice of the characters property
//character.Fertigkeiten = append(character.Fertigkeiten, fertigkeit)
func ToFeChar(object *Char) *FeChar {
feC := &FeChar{
Char: *object,
}
skills, innateSkills, categories := splitSkills(object.Fertigkeiten)
feC.Fertigkeiten = skills
feC.InnateSkills = innateSkills
feC.CategorizedSkills = categories
return feC
}
func splitSkills(object []skills.Fertigkeit) ([]skills.Fertigkeit, []skills.Fertigkeit, map[string][]skills.Fertigkeit) {
var normSkills []skills.Fertigkeit
var innateSkills []skills.Fertigkeit
//var categories map[string][]skills.Fertigkeit
categories := make(map[string][]skills.Fertigkeit)
for _, skill := range object {
gsmsk := skill.GetGsm()
if gsmsk.Improvable {
category := "Unkategorisiert"
if gsmsk.ID != 0 && gsmsk.Category != "" {
category = gsmsk.Category
}
normSkills = append(normSkills, skill)
if _, exists := categories[category]; !exists {
categories[category] = make([]skills.Fertigkeit, 0)
}
categories[category] = append(categories[category], skill)
} else {
innateSkills = append(innateSkills, skill)
}
}
return normSkills, innateSkills, categories
}
+10
View File
@@ -106,9 +106,16 @@ type CharList struct {
Public bool `json:"public"`
}
type FeChar struct {
Char
CategorizedSkills map[string][]skills.Fertigkeit `json:"categorizedskills"`
InnateSkills []skills.Fertigkeit `json:"innateskills`
}
func (object *Char) TableName() string {
return dbPrefix + "_" + "chars"
}
func (object *Char) First(name string) error {
err := database.DB.
Preload("Lp").
@@ -132,6 +139,7 @@ func (object *Char) First(name string) error {
}
return nil
}
func (object *Char) FirstID(name string) error {
err := database.DB.
Preload("Lp").
@@ -155,6 +163,7 @@ func (object *Char) FirstID(name string) error {
}
return nil
}
func (object *Char) Create() error {
err := database.DB.Transaction(func(tx *gorm.DB) error {
// Save the main character record
@@ -166,6 +175,7 @@ func (object *Char) Create() error {
return err
}
func (object *Char) Delete() error {
err := database.DB.Transaction(func(tx *gorm.DB) error {
// delete the main character record
+2
View File
@@ -22,6 +22,8 @@ type Skill struct {
Initialkeitswert int `json:"initialwert"`
Bonuseigenschaft string `json:"bonuseigenschaft,omitempty"`
Improvable bool `json:"improvable"`
InnateSkill bool `json:"innateskill"`
Category string `json:"category"`
}
type WeaponSkill struct {
+30
View File
@@ -180,6 +180,32 @@ type CharacterImport struct {
Image string `json:"image,omitempty"`
}
const (
SKILL_HOEREN = "Hören"
SKILL_NACHTSICHT = "Nachtsicht"
SKILL_RIECHEN = "Riechen"
SKILL_SECHSTERSINN = "Sechster Sinn"
SKILL_SEHEN = "Sehen"
SKILL_WAHRNEHMUNG = "Wahrnehmung"
)
var nonImprovableSkills = []string{
SKILL_HOEREN,
SKILL_NACHTSICHT,
SKILL_RIECHEN,
SKILL_SECHSTERSINN,
SKILL_SEHEN,
SKILL_WAHRNEHMUNG,
}
func isImprovableSkill(name string) bool {
for _, skill := range nonImprovableSkills {
if skill == name {
return false
}
}
return true
}
func TransformImportFertigkeit2GSDMaster(object *Fertigkeit) (*gsmaster.Skill, error) {
gsmobj := gsmaster.Skill{}
@@ -194,10 +220,14 @@ func TransformImportFertigkeit2GSDMaster(object *Fertigkeit) (*gsmaster.Skill, e
gsmobj.Initialkeitswert = object.Fertigkeitswert
gsmobj.Quelle = object.Quelle
gsmobj.Bonuseigenschaft = "check"
gsmobj.Improvable = false
re := regexp.MustCompile(`moam-ability-\\d+`)
if re.MatchString(object.ID) {
gsmobj.Improvable = true
}
if !gsmobj.Improvable {
gsmobj.Improvable = isImprovableSkill(gsmobj.Name)
}
gsmobj.System = "midgard"
err = gsmobj.Create()
if err != nil {
+32 -1
View File
@@ -1,6 +1,9 @@
package skills
import "bamort/models"
import (
"bamort/gsmaster"
"bamort/models"
)
var dbPrefix = "skill"
@@ -11,12 +14,18 @@ type Fertigkeit struct {
Bonus int `json:"bonus,omitempty"`
Pp int `json:"pp,omitempty"`
Bemerkung string `json:"bemerkung"`
Improvable bool `json:"improvable"`
Category string `json:"category"`
}
type Waffenfertigkeit struct {
Fertigkeit
}
type AngeboreneFertigkeit struct {
Fertigkeit
}
type Zauber struct {
models.BamortCharTrait
Beschreibung string `json:"beschreibung"`
@@ -33,3 +42,25 @@ func (object *Waffenfertigkeit) TableName() string {
func (object *Zauber) TableName() string {
return dbPrefix + "_" + "spells"
}
func (object *Fertigkeit) GetGsm() *gsmaster.Skill {
var gsmsk gsmaster.Skill
gsmsk.First(object.Name)
if gsmsk.ID == 0 {
return nil
}
return &gsmsk
}
func (object *Fertigkeit) GetCategory() string {
if object.Category != "" {
return object.Category
}
var gsmsk gsmaster.Skill
gsmsk.First(object.Name)
if gsmsk.ID == 0 {
return "Unkategorisiert"
}
object.Category = gsmsk.Category
return object.Category
}
+4 -4
View File
@@ -128,8 +128,8 @@ func TestListCharacters(t *testing.T) {
func TestGetCharacters(t *testing.T) {
SetupTestDB()
TestCreateChar(t)
TestRegisterUser(t)
//TestCreateChar(t)
//TestRegisterUser(t)
// Initialize a Gin router
r := gin.Default()
router.SetupGin(r)
@@ -143,8 +143,8 @@ func TestGetCharacters(t *testing.T) {
})
// Create a test HTTP request
req, _ := http.NewRequest("GET", "/api/characters/1", nil)
req.Header.Set("Content-Type", "application/json")
req, _ := http.NewRequest("GET", "/api/characters/9", nil)
//req.Header.Set("Content-Type", "application/json")
req.Header.Set("Content-Type", "application/json")
//req.Header.Set("Authorization", "Bearer ${token}")
req.Header.Set("Authorization", "Bearer dc7a780.1:bba7f4daabda117f2a2c14263")
+9 -9
View File
@@ -23,17 +23,17 @@ func SetupTestDB() {
if err != nil {
panic("failed to connect to the test database")
}
//*/
/* //testin with persitant MariaDB
dsn := "bamort:bG4)efozrc@tcp(192.168.0.5:3306)/bamort?charset=utf8mb4&parseTime=True&loc=Local"
//dsn := "root:26Osiris-Mar@tcp(192.168.0.5:3306)/bamort?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect to the test database")
}
//*/
database.DB = db
}
//*/
/* //testin with persitant MariaDB
dsn := "bamort:bG4)efozrc@tcp(192.168.0.5:3306)/bamort?charset=utf8mb4&parseTime=True&loc=Local"
//dsn := "root:26Osiris-Mar@tcp(192.168.0.5:3306)/bamort?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect to the test database")
}
//*/
if !migrationDone {
err := MigrateStructure()
if err != nil {
+1
View File
@@ -1,2 +1,3 @@
Moam_export
CharType.go
Moam_Images
+2 -1
View File
@@ -2,7 +2,8 @@
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<!-- <link rel="icon" href="/favicon.ico">-->
<link rel="icon" href="/favicon.png">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

+10 -4
View File
@@ -35,6 +35,7 @@ import WeaponView from "./WeaponView.vue"; // Component for character history
import SpellView from "./SpellView.vue"; // Component for character history
import EquipmentView from "./EquipmentView.vue"; // Component for character equipment
import ExperianceView from "./ExperianceView.vue"; // Component for character history
import DeleteCharView from "./DeleteCharView.vue"; // Component for character history
export default {
@@ -47,18 +48,22 @@ export default {
SpellView,
EquipmentView,
ExperianceView,
DeleteCharView,
},
data() {
return {
character: {},
currentView: "DatasheetView", // Default view
lastView: "DatasheetView",
menus: [
{ id: 1, name: "Datasheet", component: "DatasheetView" },
{ id: 2, name: "Skill", component: "SkillView" },
{ id: 2, name: "Weapon", component: "WeaponView" },
{ id: 2, name: "Spell", component: "SpellView" },
{ id: 2, name: "Equipment", component: "EquipmentView" },
{ id: 2, name: "Experiance", component: "ExperianceView" },
{ id: 3, name: "Weapon", component: "WeaponView" },
{ id: 4, name: "Spell", component: "SpellView" },
{ id: 5, name: "Equipment", component: "EquipmentView" },
{ id: 6, name: "Experiance", component: "ExperianceView" },
{ id: 6, name: "DeleteChar", component: "DeleteCharView" },
//{ id: 3, name: "History", component: "HistoryView" },
//{ id: 2, name: "Notes", component: "NotesView" },
//{ id: 2, name: "Campagne", component: "CampagneView" },
@@ -74,6 +79,7 @@ export default {
},
methods: {
changeView(view) {
this.lastView = this.currentView;
this.currentView = view;
},
},
+4 -4
View File
@@ -25,16 +25,16 @@
Heimat: {{ character.heimat || 'x' }}Alba,
Stand: {{ character.heimat || 'x' }}Mittelschicht.
</p>
<p>
Hort für Grad 3: 125 GS, für nächsten Grad: 250 GS.
<p v-if="character.rasse==='Zwerg'">
Hort für Grad {{ character.grad || 'x' }}: 125 GS, für nächsten Grad: 250 GS.
</p>
<p>
<strong>Spezialisierung:</strong> {{ character.spezialisierung || '-'}}.
</p>
<p>
Alter: {{ character.alter || 'xx' }},
<strong v-if="character.hand='rechts'"> Rechtshänder</strong>
<strong v-else-if="character.hand='links'"> Linkshänder</strong>
<strong v-if="character.hand=='rechts'"> Rechtshänder</strong>
<strong v-else-if="character.hand=='links'"> Linkshänder</strong>
<strong v-else> Beidhändig</strong>,
Größe: {{ character.groesse }}cm,
Gewicht: {{ character.gewicht }}kg,
@@ -0,0 +1,61 @@
<template>
<div class="cd-view">
<DeleteCharView
v-if="showDeleteDialog"
:character="character"
@deleted="handleDeleted"
@cancel="handleCancel"
/>
<p>Are you sure you want to delete {{ character.name }}?</p>
<button @click="deleteCharacter">Yes</button>
<button @click="$emit('cancel')">No</button>
</div>
</template>
<script>
export default {
name: "DeleteCharView",
props: {
character: {
type: Object,
required: true
}
},
methods: {
async deleteCharacter() {
try {
const response = await fetch(`/api/characters/${this.character.id}`, {
method: 'DELETE'
});
if (response.ok) {
this.$emit('deleted');
} else {
console.error('Failed to delete character');
}
} catch (error) {
console.error('Error:', error);
}
},
handleCancel() {
this.showDeleteDialog = false;
// Optional: Go back in router history
this.$router.go(-1);
},
handleDeleted() {
this.$router.push('/characters');
}
}
};
</script>
<style>
/*
.cd-view {
text-align: center;
}
button {
margin: 5px;
}*/
</style>
+1 -1
View File
@@ -1,6 +1,6 @@
<template>
<div class="cd-view">
Experiance and Level information
</div> <!--- end character -datasheet-->
</template>
+2 -1
View File
@@ -28,6 +28,7 @@ export default {
History:'Logbuch',
Notes:'Notizen',
Campagne:'Kampagne',
DeleteChar:'Figur löschen',
//Character:'Charakter',
},
equipment:{
@@ -43,7 +44,7 @@ export default {
skill:{
name:'Name',
description:'Beschreibung',
value:'Fertigkeitswert',
value:'EW',
note:'Bemerkung',
bonus:'Bonus',
pp:'PP',
+4
View File
@@ -15,4 +15,8 @@ export default defineConfig({
'@': fileURLToPath(new URL('./src', import.meta.url))
},
},
server: {
//port: 8080,
host: ['192.168.0.48', 'localhost','terrra.local'],
},
})