diff --git a/README.md b/README.md
new file mode 100644
index 0000000..34428ea
--- /dev/null
+++ b/README.md
@@ -0,0 +1,12 @@
+# ddServer
+
+This is a simple Webserver, which helps zou creating monsters for a dungeons & dragons game
+
+## Installation
+Either clone the repo and build it your self.
+- You need to have go installed for that
+
+Or download the latest release and start your server with
+```bash
+./ddServer
+```
diff --git a/go.mod b/go.mod
index 7db1ebd..dfe5d47 100644
--- a/go.mod
+++ b/go.mod
@@ -2,10 +2,7 @@ module ddServer
go 1.21.4
-require (
- github.com/stretchr/testify v1.8.4
- golang.org/x/text v0.14.0
-)
+require github.com/stretchr/testify v1.8.4
require (
github.com/davecgh/go-spew v1.1.1 // indirect
diff --git a/go.sum b/go.sum
index e228b7b..fa4b6e6 100644
--- a/go.sum
+++ b/go.sum
@@ -4,8 +4,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/handlers/about_handler.go b/handlers/about_handler.go
index 5f8a1dd..1d628e0 100644
--- a/handlers/about_handler.go
+++ b/handlers/about_handler.go
@@ -25,7 +25,7 @@ func AboutHandler(content embed.FS) http.HandlerFunc {
}
// Execute the template with the provided data
- data := map[string]interface{}{
+ data := map[string]any{
"Title": "Dungeons & Dragons Monster Generator",
}
err = tmpl.ExecuteTemplate(w, "about", data)
diff --git a/handlers/add_monster_handler.go b/handlers/add_monster_handler.go
index 5174c3a..38cb1a1 100644
--- a/handlers/add_monster_handler.go
+++ b/handlers/add_monster_handler.go
@@ -2,14 +2,10 @@ package handlers
import (
"ddServer/model"
- "fmt"
"log"
"net/http"
"strconv"
"strings"
-
- "golang.org/x/text/cases"
- "golang.org/x/text/language"
)
// AddMonster is a http.HandlerFunc that adds a new monster to the Monsters slice.
@@ -98,32 +94,32 @@ func parseMonster(r *http.Request) model.Monster {
Wis: parseInt(r.FormValue("wis")),
Cha: parseInt(r.FormValue("cha")),
Save: model.Save{
- Dex: checkCheckbox("savedex", r),
- Con: checkCheckbox("savecon", r),
- Wis: checkCheckbox("savewis", r),
- Str: checkCheckbox("savestr", r),
- Cha: checkCheckbox("savecha", r),
- Int: checkCheckbox("saveint", r),
+ Dex: r.FormValue("saveDex"),
+ Con: r.FormValue("saveCon"),
+ Wis: r.FormValue("saveWis"),
+ Str: r.FormValue("saveStr"),
+ Cha: r.FormValue("saveCha"),
+ Int: r.FormValue("saveInt"),
},
Skill: model.Skill{
- Perception: checkCheckbox("perception", r),
- Stealth: checkCheckbox("stealth", r),
- Acrobatics: checkCheckbox("acrobatics", r),
- AnimalHandling: checkCheckbox("animalhandling", r),
- Arcana: checkCheckbox("arcana", r),
- Athletics: checkCheckbox("athletics", r),
- Deception: checkCheckbox("deception", r),
- History: checkCheckbox("history", r),
- Insight: checkCheckbox("insight", r),
- Intimidation: checkCheckbox("intimidation", r),
- Investigation: checkCheckbox("investigation", r),
- Medicine: checkCheckbox("medicine", r),
- Nature: checkCheckbox("nature", r),
- Performance: checkCheckbox("performance", r),
- Persuasion: checkCheckbox("persuasion", r),
- SleightOfHand: checkCheckbox("sleightofhand", r),
- Survival: checkCheckbox("survival", r),
- Religion: checkCheckbox("religion", r),
+ Perception: r.FormValue("perception"),
+ Stealth: r.FormValue("stealth"),
+ Acrobatics: r.FormValue("acrobatics"),
+ AnimalHandling: r.FormValue("animalHandling"),
+ Arcana: r.FormValue("arcana"),
+ Athletics: r.FormValue("athletics"),
+ Deception: r.FormValue("deception"),
+ History: r.FormValue("history"),
+ Insight: r.FormValue("insight"),
+ Intimidation: r.FormValue("intimidation"),
+ Investigation: r.FormValue("investigation"),
+ Medicine: r.FormValue("medicine"),
+ Nature: r.FormValue("nature"),
+ Performance: r.FormValue("performance"),
+ Persuasion: r.FormValue("persuasion"),
+ SleightOfHand: r.FormValue("sleightOfHand"),
+ Survival: r.FormValue("survival"),
+ Religion: r.FormValue("religion"),
},
Resist: []string{r.FormValue("resist")},
ConditionImmune: []string{r.FormValue("conditionImmune")},
@@ -146,10 +142,3 @@ func parseMonster(r *http.Request) model.Monster {
},
}
}
-
-func checkCheckbox(field string, r *http.Request) string {
- if r.FormValue(fmt.Sprintf("check%v", cases.Caser(cases.Title(language.Und)).String(field))) == "on" {
- return r.FormValue(field)
- }
- return ""
-}
diff --git a/handlers/contact_handler.go b/handlers/contact_handler.go
index a01cad4..611abc2 100644
--- a/handlers/contact_handler.go
+++ b/handlers/contact_handler.go
@@ -23,7 +23,7 @@ func ContactHandler(content embed.FS) http.HandlerFunc {
}
// Execute the contact template
- err = tmpl.ExecuteTemplate(w, "contact", map[string]interface{}{
+ err = tmpl.ExecuteTemplate(w, "contact", map[string]any{
"Title": "Dungeons & Dragons Monster Generator",
})
if err != nil {
diff --git a/handlers/form_handler.go b/handlers/form_handler.go
index c31cee4..1232463 100644
--- a/handlers/form_handler.go
+++ b/handlers/form_handler.go
@@ -42,7 +42,7 @@ func FormHandler(content embed.FS, monsters *[]model.Monster) http.HandlerFunc {
}
// Execute the template and render the response.
- data := map[string]interface{}{
+ data := map[string]any{
"Title": "Dungeons & Dragons Monster Generator",
"Monsters": *monsters,
}
diff --git a/handlers/load_file_handler.go b/handlers/load_file_handler.go
deleted file mode 100644
index cfaaac4..0000000
--- a/handlers/load_file_handler.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package handlers
-
-import (
- "ddServer/model"
- "encoding/json"
- "fmt"
- "log"
- "net/http"
-)
-
-func LoadFileHandler(monsters *[]model.Monster) http.HandlerFunc {
- log.Print("LoadFileHandler called")
- return func(w http.ResponseWriter, r *http.Request) {
- r.ParseMultipartForm(10 << 20) // 10 MB limit
-
- // Get the file from the request
- file, _, err := r.FormFile("uploadFile")
- if err != nil {
- http.Error(w, "Error retrieving file", http.StatusBadRequest)
- return
- }
- defer file.Close()
-
- // Parse the file content
- decoder := json.NewDecoder(file)
- var loadedChars model.Character
- err = decoder.Decode(&loadedChars)
- if err != nil {
- http.Error(w, "Error decoding file content", http.StatusInternalServerError)
- return
- }
-
- // Lock the Monsters slice and append the loaded monsters, then unlock the slice
- mu.Lock()
- defer mu.Unlock()
-
- // Assuming 'loadedChars' contains an array of Monster objects
- for _, monster := range loadedChars.Monster {
- *monsters = append(*monsters, monster)
- }
-
- fmt.Printf("%v\n", monsters)
- // Send a success response
- http.Redirect(w, r, "/monsterTable", http.StatusTemporaryRedirect)
- }
-}
diff --git a/handlers/main_handler.go b/handlers/main_handler.go
index 19d2cdf..e4b575e 100644
--- a/handlers/main_handler.go
+++ b/handlers/main_handler.go
@@ -16,7 +16,7 @@ func MainHandler(content embed.FS, monsters *[]model.Monster) http.HandlerFunc {
log.Print("MainHandler called")
// Parse the templates from the embedded file system
- tmpl, err := template.ParseFS(content, "templates/main.html", "templates/monsterForm.html", "templates/monster.html", "templates/monsterTable.html", "templates/base.html", "templates/skills.html")
+ tmpl, err := template.ParseFS(content, "templates/main.html", "templates/monsterForm.html", "templates/monster.html", "templates/monsterTable.html", "templates/base.html")
if err != nil {
log.Printf("Template parsing error: %v\n", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -28,7 +28,7 @@ func MainHandler(content embed.FS, monsters *[]model.Monster) http.HandlerFunc {
defer mu.Unlock()
// Execute the main template with the provided data
- err = tmpl.ExecuteTemplate(w, "main", map[string]interface{}{
+ err = tmpl.ExecuteTemplate(w, "main", map[string]any{
"Title": "Dungeons & Dragons Monster Generator",
"Monsters": *monsters,
})
diff --git a/handlers/monster_table_handler.go b/handlers/monster_table_handler.go
index 4755386..f227962 100644
--- a/handlers/monster_table_handler.go
+++ b/handlers/monster_table_handler.go
@@ -24,7 +24,7 @@ func MonsterTableHandler(content embed.FS, monsters *[]model.Monster) http.Handl
}
// Execute the template and pass the necessary data
- err = tmpl.ExecuteTemplate(w, "monsterTable", map[string]interface{}{
+ err = tmpl.ExecuteTemplate(w, "monsterTable", map[string]any{
"Title": "Dungeons & Dragons Monster Generator",
"Monsters": *monsters,
})
diff --git a/handlers/skill_calculation_handler.go b/handlers/skill_calculation_handler.go
index 55ce57b..48935cf 100644
--- a/handlers/skill_calculation_handler.go
+++ b/handlers/skill_calculation_handler.go
@@ -8,44 +8,40 @@ import (
"strconv"
)
-// SkillCalculationHandler is an http.HandlerFunc triggered by htmx when the user makes entries in certain fields and then populates the skill fields.
+// SkillCalculationHandler ist ein http.HandlerFunc, der von htmx getriggert wird,
+// wenn der Benutzer Einträge in bestimmten Feldern macht, und dann die Skill-Felder befüllt.
func SkillCalculationHandler(content embed.FS) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
- // Check if the request is a POST request.
+ log.Print("SkillCalculationHandler called")
+
+ // Überprüfen Sie, ob die Anfrage eine POST-Anfrage ist.
if r.Method != http.MethodPost {
+ log.Print("Method not allowed")
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
- // Parse form data.
+ // Parse Formulardaten.
err := r.ParseForm()
if err != nil {
+ log.Printf("Error parsing form data: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- // Parse template files.
- tmplFiles := []string{
- "templates/base.html",
- "templates/header.html",
- "templates/skills.html",
- "templates/main.html",
- "templates/footer.html",
- "templates/about.html",
- }
+ tmplFiles := []string{"templates/base.html", "templates/header.html", "templates/skills.html", "templates/main.html", "templates/footer.html", "templates/about.html"}
tmpl, err := template.ParseFS(content, tmplFiles...)
if err != nil {
+ log.Printf("Template parsing error: %v\n", err)
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
- // Parse form field values and calculate skill values.
str := parseFieldValue(r.FormValue("str"))
dex := parseFieldValue(r.FormValue("dex"))
int := parseFieldValue(r.FormValue("int"))
cha := parseFieldValue(r.FormValue("cha"))
wis := parseFieldValue(r.FormValue("wis"))
- con := parseFieldValue(r.FormValue("con"))
cr := parseFieldValue(r.FormValue("cr"))
crBonus := calcBonus(cr)
@@ -68,124 +64,79 @@ func SkillCalculationHandler(content embed.FS) http.HandlerFunc {
"sleightOfHand": strconv.Itoa(calcAbilityScore(dex) + crBonus),
"stealth": strconv.Itoa(calcAbilityScore(dex) + crBonus),
"survival": strconv.Itoa(calcAbilityScore(wis) + crBonus),
- "saveStr": strconv.Itoa(calcAbilityScore(str) + crBonus),
- "saveWis": strconv.Itoa(calcAbilityScore(wis) + crBonus),
- "saveCon": strconv.Itoa(calcAbilityScore(con) + crBonus),
- "saveInt": strconv.Itoa(calcAbilityScore(int) + crBonus),
- "saveCha": strconv.Itoa(calcAbilityScore(cha) + crBonus),
- "saveDex": strconv.Itoa(calcAbilityScore(dex) + crBonus),
}
- // Execute template with skill values.
err = tmpl.ExecuteTemplate(w, "skills", skillValues)
if err != nil {
+ log.Printf("Template execution error: %v\n", err)
http.Error(w, err.Error(), http.StatusBadRequest)
}
}
}
-// calcBonus calculates the bonus based on the given credit rating.
-// It returns the bonus value as an integer.
func calcBonus(cr int) int {
- switch {
- case cr >= 0 && cr < 5:
- log.Println("Bonus calculated for credit rating:", cr)
+ if cr >= 0 && cr < 5 {
return 2
- case cr >= 5 && cr < 9:
- log.Println("Bonus calculated for credit rating:", cr)
+ } else if cr >= 5 && cr < 9 {
return 3
- case cr >= 9 && cr < 14:
- log.Println("Bonus calculated for credit rating:", cr)
+ } else if cr >= 9 && cr < 14 {
return 4
- case cr >= 14 && cr < 18:
- log.Println("Bonus calculated for credit rating:", cr)
+ } else if cr >= 14 && cr < 18 {
return 5
- case cr >= 18 && cr < 21:
- log.Println("Bonus calculated for credit rating:", cr)
+ } else if cr >= 18 && cr < 21 {
return 6
- case cr >= 21 && cr < 25:
- log.Println("Bonus calculated for credit rating:", cr)
+ } else if cr >= 21 && cr < 25 {
return 7
- case cr >= 25 && cr < 28:
- log.Println("Bonus calculated for credit rating:", cr)
+ } else if cr >= 25 && cr < 28 {
return 8
- case cr >= 28 && cr < 31:
- log.Println("Bonus calculated for credit rating:", cr)
+ } else if cr >= 28 && cr < 31 {
return 9
- default:
- log.Println("Invalid credit rating:", cr)
+ } else {
return 0
}
}
-// calcAbilityScore calculates the ability score based on the given value.
func calcAbilityScore(val int) int {
- switch {
- case val < 2:
- log.Println("Ability Score: -5")
+ if val < 2 {
return -5
- case val < 4:
- log.Println("Ability Score: -4")
+ } else if val >= 2 && val < 4 {
return -4
- case val < 6:
- log.Println("Ability Score: -3")
+ } else if val >= 4 && val < 6 {
return -3
- case val < 8:
- log.Println("Ability Score: -2")
+ } else if val >= 6 && val < 8 {
return -2
- case val < 10:
- log.Println("Ability Score: -1")
+ } else if val >= 8 && val < 10 {
return -1
- case val < 12:
- log.Println("Ability Score: 0")
+ } else if val >= 10 && val < 12 {
return 0
- case val < 14:
- log.Println("Ability Score: 1")
+ } else if val >= 12 && val < 14 {
return 1
- case val < 16:
- log.Println("Ability Score: 2")
+ } else if val >= 14 && val < 16 {
return 2
- case val < 18:
- log.Println("Ability Score: 3")
+ } else if val >= 16 && val < 18 {
return 3
- case val < 20:
- log.Println("Ability Score: 4")
+ } else if val >= 18 && val < 20 {
return 4
- case val < 22:
- log.Println("Ability Score: 5")
+ } else if val >= 20 && val < 22 {
return 5
- case val < 24:
- log.Println("Ability Score: 6")
+ } else if val >= 22 && val < 24 {
return 6
- case val < 26:
- log.Println("Ability Score: 7")
+ } else if val >= 24 && val < 26 {
return 7
- case val < 28:
- log.Println("Ability Score: 8")
+ } else if val >= 26 && val < 28 {
return 8
- case val < 30:
- log.Println("Ability Score: 9")
+ } else if val >= 28 && val < 30 {
return 9
- default:
- log.Println("Ability Score: 10")
+ } else {
return 10
}
}
-// parseFieldValue takes a string value and returns an integer.
-// If the string value cannot be converted to an integer, it logs an error and returns 0.
-// The function follows these rules:
-// - No line is over 66 characters.
func parseFieldValue(value string) int {
- // Convert the string value to an integer using strconv.Atoi.
- // If an error occurs during the conversion, log the error and return 0.
val, err := strconv.Atoi(value)
if err != nil {
log.Printf("Error converting field value to integer: %v", err)
return 0
}
- // Log the converted integer value for debugging purposes.
- log.Printf("Converted field value to integer: %d", val)
- // Return the converted integer value.
return val
}
diff --git a/main.go b/main.go
index 5bbd46f..d163e79 100644
--- a/main.go
+++ b/main.go
@@ -37,7 +37,6 @@ func main() {
routes.HandleFunc("/contact", handlers.ContactHandler(content))
routes.HandleFunc("/monsterTable", handlers.MonsterTableHandler(content, &Monsters))
routes.HandleFunc("/calculate-skills", handlers.SkillCalculationHandler(content))
- routes.HandleFunc("/loadFile", handlers.LoadFileHandler(&Monsters))
// Print the message indicating that 'static' has been included.
log.Printf("Eingebunden is %v\n", static)
diff --git a/templates/contact.html b/templates/contact.html
index c8481f1..ce0085d 100644
--- a/templates/contact.html
+++ b/templates/contact.html
@@ -1,58 +1,57 @@
{{ define "contact" }}
-
-
-
-
Contact Us
-
-
+
+
+
+
Contact Us
+
+
-
-
Our Contact Information
-
You can reach us through the following channels:
-
-
Email: example@example.com
-
Phone: +123456789
-
-
-
-
-
Contact Form
-
-
-
+
+
Our Contact Information
+
You can reach us through the following channels:
+
+
Email: example@example.com
+
Phone: +123456789
+
+
+
+
Contact Form
+
+
+
+
{{ end }}
diff --git a/templates/footer.html b/templates/footer.html
index 9b0881a..cf8d261 100644
--- a/templates/footer.html
+++ b/templates/footer.html
@@ -6,4 +6,4 @@
-{{ end }}
\ No newline at end of file
+{{ end }}
diff --git a/templates/header.html b/templates/header.html
index 46c13ec..0efea19 100644
--- a/templates/header.html
+++ b/templates/header.html
@@ -78,4 +78,4 @@
});
-{{ end }}
\ No newline at end of file
+{{ end }}
diff --git a/templates/main.html b/templates/main.html
index 359f1a9..ed4581f 100644
--- a/templates/main.html
+++ b/templates/main.html
@@ -1,131 +1,109 @@
{{ define "main" }}
-
-
-
-
Monster Form
-
-
-
-
-
-
-
Existing Monsters
-
-
-
-
-
-
-
-
-
-
Name
-
Source
-
Size
-
Type
-
Alignment
-
AC
-
AC Form
-
HP Average
-
HP Formula
-
Walk
-
Swim
-
Burrow
-
Climb
-
Fly
-
Str
-
Dex
-
Con
-
Int
-
Wis
-
Cha
-
Save Dex
-
Save Con
-
Save Wis
-
Save Str
-
Save Int
-
Save Cha
-
Perception
-
Stealth
-
Acrobatics
-
AnimalHandling
-
Arcana
-
Athletics
-
Deception
-
History
-
Insight
-
Intimidation
-
Investigation
-
Medicine
-
Nature
-
Performance
-
Persuasion
-
SleightOfHand
-
Survival
-
Religion
-
Damage Resistance
-
Damage Immune
-
Vulnerable
-
Condition Immune
-
Senses
-
Languages
-
CR
-
Trait Name
-
Trait Entry
-
Action Name
-
Action Entry
-
-
- {{ template "monsterTable" }}
-
-
+
+
+
+
Existing Monsters
+
+
+
+
+
+
+
+
+
+
Name
+
Source
+
Size
+
Type
+
Alignment
+
AC
+
AC Form
+
HP Average
+
HP Formula
+
Walk
+
Swim
+
Burrow
+
Climb
+
Fly
+
Str
+
Dex
+
Con
+
Int
+
Wis
+
Cha
+
Save Dex
+
Save Con
+
Save Wis
+
Save Str
+
Save Con
+
Save Cha
+
Perception
+
Stealth
+
Acrobatics
+
AnimalHandling
+
Arcana
+
Athletics
+
Deception
+
History
+
Insight
+
Intimidation
+
Investigation
+
Medicine
+
Nature
+
Performance
+
Persuasion
+
SleightOfHand
+
Survival
+
Religion
+
Damage Resistance
+
Damage Immune
+
Vulnerable
+
Condition Immune
+
Senses
+
Languages
+
CR
+
Trait Name
+
Trait Entry
+
Action Name
+
Action Entry
+
+
+ {{ template "monsterTable" }}
+
+
+
-
-{{ end }}
\ No newline at end of file
+{{ end }}
diff --git a/templates/monster.html b/templates/monster.html
index 0053cea..d3a59d6 100644
--- a/templates/monster.html
+++ b/templates/monster.html
@@ -24,7 +24,7 @@
-{{ end }}
\ No newline at end of file
+{{ end }}
diff --git a/templates/monsterForm.html b/templates/monsterForm.html
index 5903e0d..ca69873 100644
--- a/templates/monsterForm.html
+++ b/templates/monsterForm.html
@@ -87,6 +87,61 @@
+
+
+
+ Speed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -154,14 +209,20 @@
-
-
- {{ template "skills" }}
+
+
+
+
+
+
+
+
- Speed
+ Save
@@ -169,50 +230,61 @@
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ template "skills" }}
+
@@ -303,4 +375,4 @@
-{{end}}
\ No newline at end of file
+{{end}}
diff --git a/templates/monsterTable.html b/templates/monsterTable.html
index 9eb1b75..d5aef50 100644
--- a/templates/monsterTable.html
+++ b/templates/monsterTable.html
@@ -4,4 +4,4 @@
{{ template "monster" . }}
{{ end }}
-{{ end }}
\ No newline at end of file
+{{ end }}
diff --git a/templates/skills.html b/templates/skills.html
index acd9da9..9322260 100644
--- a/templates/skills.html
+++ b/templates/skills.html
@@ -1,265 +1,185 @@
{{ define "skills" }}
-