package character import ( "bamort/bmrt/models" "bamort/database" "fmt" "net/http" "github.com/gin-gonic/gin" ) // PracticePointResponse repräsentiert die Antwort für Praxispunkte einer Fertigkeit type PracticePointResponse struct { SkillName string `json:"skill_name"` SkillDescription string `json:"skill_description,omitempty"` Amount int `json:"amount"` } // PracticePointActionResponse repräsentiert die erweiterte Antwort für PP-Aktionen type PracticePointActionResponse struct { Success bool `json:"success"` Message string `json:"message"` RequestedSkill string `json:"requested_skill"` // Ursprünglich angefragter Name TargetSkill string `json:"target_skill"` // Tatsächlich betroffene Fertigkeit IsSpell bool `json:"is_spell"` // Ob es sich um einen Zauber handelt PracticePoints []PracticePointResponse `json:"practice_points"` // Aktuelle PP-Liste } // GetPracticePoints gibt die verfügbaren Praxispunkte eines Charakters zurück func GetPracticePoints(c *gin.Context) { // Charakter-ID aus der URL abrufen charID := c.Param("id") // Charakter aus der Datenbank laden var character models.Char if err := character.FirstID(charID); err != nil { respondWithError(c, http.StatusNotFound, "Charakter nicht gefunden") return } // Praxispunkte aus den Fertigkeiten extrahieren var practicePoints []PracticePointResponse for _, skill := range character.Fertigkeiten { if skill.Pp > 0 { practicePoints = append(practicePoints, PracticePointResponse{ SkillName: skill.Name, SkillDescription: skill.Beschreibung, Amount: skill.Pp, }) } } for _, skill := range character.Waffenfertigkeiten { if skill.Pp > 0 { practicePoints = append(practicePoints, PracticePointResponse{ SkillName: skill.Name, SkillDescription: skill.Beschreibung, Amount: skill.Pp, }) } } c.JSON(http.StatusOK, practicePoints) } // UpdatePracticePoints aktualisiert die Praxispunkte eines Charakters func UpdatePracticePoints(c *gin.Context) { // Charakter-ID aus der URL abrufen charID := c.Param("id") // Charakter aus der Datenbank laden var character models.Char if err := character.FirstID(charID); err != nil { respondWithError(c, http.StatusNotFound, "Charakter nicht gefunden") return } // Check ownership if !checkCharacterOwnership(c, &character) { return } // Request-Parameter abrufen var practicePoints []PracticePointResponse if err := c.ShouldBindJSON(&practicePoints); err != nil { respondWithError(c, http.StatusBadRequest, "Ungültige Praxispunkt-Daten: "+err.Error()) return } // Alle Fertigkeiten durchgehen und Praxispunkte zurücksetzen /* for i := range character.Fertigkeiten { character.Fertigkeiten[i].Pp = 0 } */ // Neue Praxispunkte setzen for _, pp := range practicePoints { for i := range character.Fertigkeiten { if character.Fertigkeiten[i].Name == pp.SkillName { character.Fertigkeiten[i].Pp = pp.Amount break } } } // Charakter in der Datenbank speichern if err := database.DB.Save(&character).Error; err != nil { respondWithError(c, http.StatusInternalServerError, "Fehler beim Speichern der Praxispunkte: "+err.Error()) return } // Aktualisierte Praxispunkte zurückgeben var updatedPracticePoints []PracticePointResponse for _, skill := range character.Fertigkeiten { if skill.Pp > 0 { updatedPracticePoints = append(updatedPracticePoints, PracticePointResponse{ SkillName: skill.Name, Amount: skill.Pp, }) } } c.JSON(http.StatusOK, updatedPracticePoints) } // AddPracticePoint fügt einen Praxispunkt zu einer Fertigkeit hinzu // TODO prüfe speichern der PP für Spells func AddPracticePoint(c *gin.Context) { // Charakter-ID aus der URL abrufen charID := c.Param("id") // Charakter aus der Datenbank laden var character models.Char if err := character.FirstID(charID); err != nil { respondWithError(c, http.StatusNotFound, "Charakter nicht gefunden") return } // Check ownership if !checkCharacterOwnership(c, &character) { return } // Request-Parameter abrufen type AddPPRequest struct { SkillName string `json:"skill_name" binding:"required"` SkillDescription string `json:"skill_description"` Amount int `json:"amount"` } var request AddPPRequest if err := c.ShouldBindJSON(&request); err != nil { respondWithError(c, http.StatusBadRequest, "Ungültige Anfrageparameter: "+err.Error()) return } if request.Amount <= 0 { request.Amount = 1 } // Prüfen, ob es sich um einen Zauber handelt var targetSkillName string var isSpellFlag bool if isSpellNewSystem(request.SkillName) { // Bei Zaubern: PP werden der entsprechenden Zaubergruppe zugeordnet targetSkillName = getSpellCategoryNewSystem(request.SkillName) isSpellFlag = true } else { // Bei normalen Fertigkeiten: PP werden direkt der Fertigkeit zugeordnet targetSkillName = request.SkillName isSpellFlag = false } // skillMatches prüft ob Name übereinstimmt und (wenn angegeben) auch die Beschreibung. skillMatchesAdd := func(name, beschreibung string) bool { if name != targetSkillName { return false } if request.SkillDescription != "" && beschreibung != request.SkillDescription { return false } return true } // Praxispunkt zur entsprechenden Fertigkeit hinzufügen und sofort speichern foundSkill := false for i := range character.Fertigkeiten { if skillMatchesAdd(character.Fertigkeiten[i].Name, character.Fertigkeiten[i].Beschreibung) { character.Fertigkeiten[i].Pp += request.Amount if err := database.DB.Save(&character.Fertigkeiten[i]).Error; err != nil { respondWithError(c, http.StatusInternalServerError, "Fehler beim Speichern der Fertigkeit: "+err.Error()) return } foundSkill = true break } } foundWeaponSkill := false for i := range character.Waffenfertigkeiten { if skillMatchesAdd(character.Waffenfertigkeiten[i].Name, character.Waffenfertigkeiten[i].Beschreibung) { character.Waffenfertigkeiten[i].Pp += request.Amount if err := database.DB.Save(&character.Waffenfertigkeiten[i]).Error; err != nil { respondWithError(c, http.StatusInternalServerError, "Fehler beim Speichern der Waffenfertigkeit: "+err.Error()) return } foundWeaponSkill = true break } } if !foundSkill && !foundWeaponSkill { respondWithError(c, http.StatusBadRequest, "Fertigkeit nicht gefunden: "+targetSkillName) return } // Aktualisierte Praxispunkte sammeln var practicePoints []PracticePointResponse for _, skill := range character.Fertigkeiten { if skill.Pp > 0 { practicePoints = append(practicePoints, PracticePointResponse{ SkillName: skill.Name, SkillDescription: skill.Beschreibung, Amount: skill.Pp, }) } } for _, skill := range character.Waffenfertigkeiten { if skill.Pp > 0 { practicePoints = append(practicePoints, PracticePointResponse{ SkillName: skill.Name, SkillDescription: skill.Beschreibung, Amount: skill.Pp, }) } } // Erfolgreiche Response mit Details zurückgeben var message string if isSpellFlag { message = "Praxispunkt für Zauber '" + request.SkillName + "' wurde der Zaubergruppe '" + targetSkillName + "' hinzugefügt" } else if foundSkill { message = "Praxispunkt für Fertigkeit '" + targetSkillName + "' hinzugefügt" } else if foundWeaponSkill { message = "Praxispunkt für Waffenfertigkeit '" + targetSkillName + "' hinzugefügt" } response := PracticePointActionResponse{ Success: true, Message: message, RequestedSkill: request.SkillName, TargetSkill: targetSkillName, IsSpell: isSpellFlag, PracticePoints: practicePoints, } c.JSON(http.StatusOK, response) } // UsePracticePoint verbraucht Praxispunkte für eine spezifische Fertigkeit func UsePracticePoint(c *gin.Context) { // Charakter-ID aus der URL abrufen charID := c.Param("id") // Charakter aus der Datenbank laden var character models.Char if err := character.FirstID(charID); err != nil { respondWithError(c, http.StatusNotFound, "Charakter nicht gefunden") return } // Check ownership if !checkCharacterOwnership(c, &character) { return } // Request-Parameter abrufen type UsePPRequest struct { SkillName string `json:"skill_name" binding:"required"` SkillDescription string `json:"skill_description"` Amount int `json:"amount"` } var request UsePPRequest if err := c.ShouldBindJSON(&request); err != nil { respondWithError(c, http.StatusBadRequest, "Ungültige Anfrageparameter: "+err.Error()) return } if request.Amount <= 0 { request.Amount = 1 } // Prüfen, ob es sich um einen Zauber handelt var targetSkillName string var isSpellFlag bool if isSpellNewSystem(request.SkillName) { // Bei Zaubern: PP werden von der entsprechenden Zaubergruppe abgezogen targetSkillName = getSpellCategoryNewSystem(request.SkillName) isSpellFlag = true } else { // Bei normalen Fertigkeiten: PP werden direkt von der Fertigkeit abgezogen targetSkillName = request.SkillName isSpellFlag = false } // skillMatchesUse prüft ob Name übereinstimmt und (wenn angegeben) auch die Beschreibung. skillMatchesUse := func(name, beschreibung string) bool { if name != targetSkillName { return false } if request.SkillDescription != "" && beschreibung != request.SkillDescription { return false } return true } // Praxispunkt von der entsprechenden Fertigkeit abziehen und sofort speichern foundSkill := false for i := range character.Fertigkeiten { if skillMatchesUse(character.Fertigkeiten[i].Name, character.Fertigkeiten[i].Beschreibung) { if character.Fertigkeiten[i].Pp >= request.Amount { character.Fertigkeiten[i].Pp -= request.Amount if err := database.DB.Save(&character.Fertigkeiten[i]).Error; err != nil { respondWithError(c, http.StatusInternalServerError, "Fehler beim Speichern der Fertigkeit: "+err.Error()) return } foundSkill = true } else { respondWithError(c, http.StatusBadRequest, "Nicht genügend Praxispunkte verfügbar") return } break } } foundWeaponSkill := false for i := range character.Waffenfertigkeiten { if skillMatchesUse(character.Waffenfertigkeiten[i].Name, character.Waffenfertigkeiten[i].Beschreibung) { if character.Waffenfertigkeiten[i].Pp >= request.Amount { character.Waffenfertigkeiten[i].Pp -= request.Amount if err := database.DB.Save(&character.Waffenfertigkeiten[i]).Error; err != nil { respondWithError(c, http.StatusInternalServerError, "Fehler beim Speichern der Waffenfertigkeit: "+err.Error()) return } foundWeaponSkill = true } else { respondWithError(c, http.StatusBadRequest, "Nicht genügend Praxispunkte verfügbar") return } break } } if !foundSkill && !foundWeaponSkill { respondWithError(c, http.StatusBadRequest, "Fertigkeit nicht gefunden: "+targetSkillName) return } // Erfolgreiche Antwort mit detaillierten Informationen und aktueller PP-Liste var practicePoints []PracticePointResponse for _, skill := range character.Fertigkeiten { if skill.Pp > 0 { practicePoints = append(practicePoints, PracticePointResponse{ SkillName: skill.Name, SkillDescription: skill.Beschreibung, Amount: skill.Pp, }) } } for _, skill := range character.Waffenfertigkeiten { if skill.Pp > 0 { practicePoints = append(practicePoints, PracticePointResponse{ SkillName: skill.Name, SkillDescription: skill.Beschreibung, Amount: skill.Pp, }) } } response := PracticePointActionResponse{ Success: true, Message: fmt.Sprintf("%d Praxispunkte erfolgreich von %s verwendet/reduziert", request.Amount, targetSkillName), RequestedSkill: request.SkillName, TargetSkill: targetSkillName, IsSpell: isSpellFlag, PracticePoints: practicePoints, } c.JSON(http.StatusOK, response) }