This repository has been archived on 2024-03-28. You can view files and clone it, but cannot push or open issues or pull requests.
atsebay.t/grades.go

166 lines
4.0 KiB
Go

package main
import (
"fmt"
"log"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
func declareAPIAuthGradesRoutes(router *gin.RouterGroup) {
router.GET("/grades", func(c *gin.Context) {
uauth := c.MustGet("LoggedUser").(*User)
if survey, ok := c.Get("survey"); !ok {
if uauth == nil || !uauth.IsAdmin {
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Not authorized"})
return
}
grades, err := GetAllGrades()
if err != nil {
log.Println("Unable to GetAllGrades:", err)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs when trying to retrieve grades."})
return
}
c.JSON(http.StatusOK, grades)
} else {
s := survey.(*Survey)
if user, ok := c.Get("user"); ok {
u := user.(*User)
if uauth == nil || !((s.Shown && u.Id == uauth.Id) || uauth.IsAdmin) {
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Not accessible"})
return
}
score, err := s.GetUserGrades(u)
if err != nil {
log.Printf("Unable to GetUserGrades(sid=%d; uid=%d): %s", s.Id, u.Id, err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to retrive user grade. Please try again later."})
return
}
if score == nil {
c.JSON(http.StatusOK, "N/A")
} else {
c.JSON(http.StatusOK, score)
}
} else if uauth.IsAdmin {
scores, err := s.GetGrades()
if err != nil {
log.Printf("Unable to GetGrades(sid=%d): %s", s.Id, err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to retrive grades."})
return
}
c.JSON(http.StatusOK, scores)
} else {
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Not authorized"})
return
}
}
})
}
func gradeHandler(c *gin.Context) {
work := c.MustGet("work").(*Work)
if gid, err := strconv.Atoi(string(c.Param("gid"))); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Bad grade identifier."})
return
} else if grade, err := work.GetGrade(int64(gid)); err != nil {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Grade not found."})
return
} else {
c.Set("grade", grade)
c.Next()
}
}
func GetAllGrades() (scores map[int64]map[string]*float64, err error) {
if rows, errr := DBQuery("SELECT id_user, kind, id, SUM(score)/COUNT(*) FROM student_scores GROUP BY id_user, kind, id"); errr != nil {
return nil, errr
} else {
defer rows.Close()
scores = map[int64]map[string]*float64{}
for rows.Next() {
var id_user int64
var kind string
var id int64
var score *float64
if err = rows.Scan(&id_user, &kind, &id, &score); err != nil {
return
}
if scores[id_user] == nil {
scores[id_user] = map[string]*float64{}
}
scores[id_user][fmt.Sprintf("%c.%d", kind[0], id)] = score
}
if err = rows.Err(); err != nil {
return
}
}
return
}
func (s Survey) GetGrades() (scores map[int64]*float64, err error) {
if rows, errr := DBQuery("SELECT id_question, SUM(score)/COUNT(*) FROM student_scores WHERE kind = 'survey' AND id=? GROUP BY id_question", s.Id); errr != nil {
return nil, errr
} else {
defer rows.Close()
scores = map[int64]*float64{}
for rows.Next() {
var id_question int64
var score *float64
if err = rows.Scan(&id_question, &score); err != nil {
return
}
scores[id_question] = score
}
if err = rows.Err(); err != nil {
return
}
}
return
}
func (s Survey) GetUserGrades(u *User) (scores map[int64]*float64, err error) {
if rows, errr := DBQuery("SELECT id_question, MAX(score) FROM student_scores WHERE kind = 'survey' AND id=? AND id_user = ? GROUP BY id_question", s.Id, u.Id); errr != nil {
return nil, errr
} else {
defer rows.Close()
scores = map[int64]*float64{}
for rows.Next() {
var id_question int64
var score *float64
if err = rows.Scan(&id_question, &score); err != nil {
return
}
scores[id_question] = score
}
if err = rows.Err(); err != nil {
return
}
}
return
}