probo/server/main.go

209 lines
4.2 KiB
Go
Raw Normal View History

2023-12-05 22:11:08 +01:00
package main
import (
"encoding/json"
2023-12-11 09:32:50 +01:00
"log"
2023-12-05 22:11:08 +01:00
"math/rand"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"text/template"
"git.andreafazzi.eu/andrea/probo/models"
2023-12-11 09:32:50 +01:00
"git.andreafazzi.eu/andrea/probo/store/file"
2023-12-05 22:11:08 +01:00
)
2023-12-11 09:32:50 +01:00
var (
DefaultDataDir = "data"
DefaultSessionDir = "sessions"
DefaultTemplateDir = "templates"
DefaultStaticDir = "static"
)
type Config struct {
SessionDir string
TemplateDir string
StaticDir string
}
2023-12-05 22:11:08 +01:00
type ExamSession []*models.Exam
2023-12-11 09:32:50 +01:00
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
2023-12-05 22:11:08 +01:00
}
2023-12-11 09:32:50 +01:00
_, 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(),
})
2023-12-05 22:11:08 +01:00
}
2023-12-11 09:32:50 +01:00
func (s *Server) createExamSessionHandler(w http.ResponseWriter, r *http.Request) {
2023-12-05 22:11:08 +01:00
var p ExamSession
err := json.NewDecoder(r.Body).Decode(&p)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
id := generateRandomID()
2023-12-11 09:32:50 +01:00
path := filepath.Join(s.config.SessionDir, id)
2023-12-05 22:11:08 +01:00
err = os.MkdirAll(path, os.ModePerm)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
for _, exam := range p {
file, err := os.Create(filepath.Join(path, strconv.Itoa(exam.Participant.Token)) + ".json")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer file.Close()
err = json.NewEncoder(file).Encode(exam)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
response := map[string]string{"id": id}
json.NewEncoder(w).Encode(response)
}
2023-12-11 09:32:50 +01:00
func (s *Server) getExamHandler(w http.ResponseWriter, r *http.Request) {
2023-12-05 22:11:08 +01:00
urlParts := strings.Split(r.URL.Path, "/")
examID := urlParts[1]
token := urlParts[2]
2023-12-11 09:32:50 +01:00
filePath := filepath.Join(s.config.SessionDir, examID, token+".json")
2023-12-05 22:11:08 +01:00
data, err := os.ReadFile(filePath)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
exam := new(models.Exam)
err = json.Unmarshal(data, &exam)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
2023-12-11 09:32:50 +01:00
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>"))
2023-12-05 22:11:08 +01:00
return
}
}
2023-12-11 09:32:50 +01:00
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
}
2023-12-05 22:11:08 +01:00
func main() {
2023-12-11 09:32:50 +01:00
server, err := NewDefaultServer()
if err != nil {
panic(err)
}
2023-12-05 22:11:08 +01:00
2023-12-11 09:32:50 +01:00
log.Println("Probo server started.", "Config", server.config)
http.ListenAndServe(":8080", server)
2023-12-05 22:11:08 +01:00
}