|
@@ -2,7 +2,7 @@ package main
|
|
|
|
|
|
import (
|
|
|
"encoding/json"
|
|
|
- "log/slog"
|
|
|
+ "log"
|
|
|
"math/rand"
|
|
|
"net/http"
|
|
|
"os"
|
|
@@ -10,24 +10,89 @@ import (
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
"text/template"
|
|
|
- "time"
|
|
|
|
|
|
"git.andreafazzi.eu/andrea/probo/models"
|
|
|
+ "git.andreafazzi.eu/andrea/probo/store/file"
|
|
|
)
|
|
|
|
|
|
-var Dir = "data"
|
|
|
+var (
|
|
|
+ DefaultDataDir = "data"
|
|
|
+ DefaultSessionDir = "sessions"
|
|
|
+ DefaultTemplateDir = "templates"
|
|
|
+ DefaultStaticDir = "static"
|
|
|
+)
|
|
|
+
|
|
|
+type Config struct {
|
|
|
+ SessionDir string
|
|
|
+ TemplateDir string
|
|
|
+ StaticDir string
|
|
|
+}
|
|
|
|
|
|
type ExamSession []*models.Exam
|
|
|
|
|
|
-func generateRandomID() string {
|
|
|
- id := ""
|
|
|
- for i := 0; i < 6; i++ {
|
|
|
- id += strconv.Itoa(rand.Intn(9) + 1)
|
|
|
+type ExamTemplateData struct {
|
|
|
+ *models.Exam
|
|
|
+
|
|
|
+ SessionID string
|
|
|
+}
|
|
|
+
|
|
|
+type Server struct {
|
|
|
+ config *Config
|
|
|
+ mux *http.ServeMux
|
|
|
+ responseStore *file.ResponseFileStore
|
|
|
+}
|
|
|
+
|
|
|
+func GetDefaultSessionDir() string {
|
|
|
+ return filepath.Join(DefaultDataDir, DefaultSessionDir)
|
|
|
+}
|
|
|
+
|
|
|
+func GetDefaultTemplateDir() string {
|
|
|
+ return DefaultTemplateDir
|
|
|
+}
|
|
|
+
|
|
|
+func GetDefaultStaticDir() string {
|
|
|
+ return DefaultStaticDir
|
|
|
+}
|
|
|
+
|
|
|
+func NewServer(config *Config) (*Server, error) {
|
|
|
+
|
|
|
+ _, err := os.Stat(config.SessionDir)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
}
|
|
|
- return id
|
|
|
+
|
|
|
+ _, err = os.Stat(config.TemplateDir)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ _, err = os.Stat(config.StaticDir)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ s := &Server{
|
|
|
+ config,
|
|
|
+ http.NewServeMux(),
|
|
|
+ nil,
|
|
|
+ }
|
|
|
+
|
|
|
+ s.mux.Handle("/static/", http.StripPrefix("/static", http.FileServer(http.Dir(config.StaticDir))))
|
|
|
+ s.mux.HandleFunc("/create", s.createExamSessionHandler)
|
|
|
+ s.mux.HandleFunc("/", s.getExamHandler)
|
|
|
+
|
|
|
+ return s, nil
|
|
|
+}
|
|
|
+
|
|
|
+func NewDefaultServer() (*Server, error) {
|
|
|
+ return NewServer(&Config{
|
|
|
+ SessionDir: GetDefaultSessionDir(),
|
|
|
+ TemplateDir: GetDefaultTemplateDir(),
|
|
|
+ StaticDir: GetDefaultStaticDir(),
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
-func createExamSessionHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
+func (s *Server) createExamSessionHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
var p ExamSession
|
|
|
err := json.NewDecoder(r.Body).Decode(&p)
|
|
|
if err != nil {
|
|
@@ -36,7 +101,7 @@ func createExamSessionHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
}
|
|
|
|
|
|
id := generateRandomID()
|
|
|
- path := filepath.Join(Dir, id)
|
|
|
+ path := filepath.Join(s.config.SessionDir, id)
|
|
|
|
|
|
err = os.MkdirAll(path, os.ModePerm)
|
|
|
if err != nil {
|
|
@@ -62,13 +127,13 @@ func createExamSessionHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
json.NewEncoder(w).Encode(response)
|
|
|
}
|
|
|
|
|
|
-func getExamHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
+func (s *Server) getExamHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
urlParts := strings.Split(r.URL.Path, "/")
|
|
|
|
|
|
examID := urlParts[1]
|
|
|
token := urlParts[2]
|
|
|
|
|
|
- filePath := filepath.Join(Dir, examID, token+".json")
|
|
|
+ filePath := filepath.Join(s.config.SessionDir, examID, token+".json")
|
|
|
|
|
|
data, err := os.ReadFile(filePath)
|
|
|
if err != nil {
|
|
@@ -83,48 +148,61 @@ func getExamHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- w.Header().Set("Content-Type", "text/html")
|
|
|
- tmpl := template.Must(template.New("exam").Parse(`
|
|
|
- <!DOCTYPE html>
|
|
|
- <html>
|
|
|
- <head>
|
|
|
- <title>{{.Name}}</title>
|
|
|
- </head>
|
|
|
- <body>
|
|
|
- <h1>{{.Name}}</h1>
|
|
|
- <h2>{{.Participant.Firstname}} {{.Participant.Lastname}}</h2>
|
|
|
- <form>
|
|
|
- {{range $index, $quiz := .Quizzes}}
|
|
|
- <h3>Question {{$index}}:</h3>
|
|
|
- <p>{{$quiz.Question.Text}}</p>
|
|
|
- {{range $answer := $quiz.Answers}}
|
|
|
- <input type="radio"
|
|
|
- id="{{$answer.ID}}" name="$answer.ID"
|
|
|
- value="{{$answer.Text}}">
|
|
|
- <label
|
|
|
- for="{{$answer.ID}}">{{$answer.Text}}</label><br>
|
|
|
- {{end}}
|
|
|
- <br>
|
|
|
- {{end}}
|
|
|
- <input type="submit" value="Invia">
|
|
|
- </form>
|
|
|
- </body>
|
|
|
- </html>
|
|
|
- `))
|
|
|
-
|
|
|
- err = tmpl.Execute(w, exam)
|
|
|
- if err != nil {
|
|
|
- http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
+ if r.Method == "GET" {
|
|
|
+
|
|
|
+ w.Header().Set("Content-Type", "text/html")
|
|
|
+
|
|
|
+ tplData, err := os.ReadFile(filepath.Join(GetDefaultTemplateDir(), "exam.tpl"))
|
|
|
+ if err != nil {
|
|
|
+ http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
+ return
|
|
|
+
|
|
|
+ }
|
|
|
+ tmpl := template.Must(template.New("exam").Parse(string(tplData)))
|
|
|
+
|
|
|
+ err = tmpl.Execute(w, ExamTemplateData{exam, examID})
|
|
|
+ if err != nil {
|
|
|
+ http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if r.Method == "POST" {
|
|
|
+ err := r.ParseForm()
|
|
|
+ if err != nil {
|
|
|
+ http.Error(w, err.Error(), http.StatusBadRequest)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ w.Header().Set("Content-Type", "text/html")
|
|
|
+ if r.FormValue("answer") == exam.Quizzes[0].Correct.ID {
|
|
|
+ w.Write([]byte("<p>Corretto!</p>"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ w.Write([]byte("<p>Errato!</p>"))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
+func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
|
+ s.mux.ServeHTTP(w, r)
|
|
|
+}
|
|
|
+
|
|
|
+func generateRandomID() string {
|
|
|
+ id := ""
|
|
|
+ for i := 0; i < 6; i++ {
|
|
|
+ id += strconv.Itoa(rand.Intn(9) + 1)
|
|
|
+ }
|
|
|
+ return id
|
|
|
+}
|
|
|
+
|
|
|
func main() {
|
|
|
- mux := http.NewServeMux()
|
|
|
- mux.HandleFunc("/create", createExamSessionHandler)
|
|
|
- mux.HandleFunc("/", getExamHandler)
|
|
|
+ server, err := NewDefaultServer()
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
|
|
|
- slog.Info("Probo server started", "at", time.Now())
|
|
|
- http.ListenAndServe(":8080", mux)
|
|
|
+ log.Println("Probo server started.", "Config", server.config)
|
|
|
+ http.ListenAndServe(":8080", server)
|
|
|
}
|