2020-09-13 14:37:15 +00:00
package main
import (
2022-07-09 17:42:00 +00:00
"log"
"net/http"
2020-09-13 14:37:15 +00:00
"strconv"
"strings"
2022-07-09 17:42:00 +00:00
"github.com/gin-gonic/gin"
2020-09-13 14:37:15 +00:00
)
2022-07-09 17:42:00 +00:00
func declareAPIAdminCorrectionsRoutes ( router * gin . RouterGroup ) {
router . GET ( "/corrections" , func ( c * gin . Context ) {
q := c . MustGet ( "question" ) . ( * Question )
cts , err := q . GetCorrectionTemplates ( )
if err != nil {
log . Println ( "Unable to GetCorrectionTemplates:" , err )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to retrive correction's templates" } )
return
2020-09-13 14:37:15 +00:00
}
2022-07-09 17:42:00 +00:00
c . JSON ( http . StatusOK , cts )
} )
router . POST ( "/corrections" , func ( c * gin . Context ) {
q := c . MustGet ( "question" ) . ( * Question )
2020-09-13 14:37:15 +00:00
var new CorrectionTemplate
2022-07-09 17:42:00 +00:00
if err := c . ShouldBindJSON ( & new ) ; err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2020-09-13 14:37:15 +00:00
}
2022-07-09 17:42:00 +00:00
ct , err := q . NewCorrectionTemplate ( new . Label , new . RegExp , new . Score , new . ScoreExplaination )
if err != nil {
log . Println ( "Unable to NewCorrectionTemplate:" , err )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to insert new correction template." } )
return
2020-09-13 14:37:15 +00:00
}
2022-07-09 17:42:00 +00:00
c . JSON ( http . StatusOK , ct )
} )
correctionsRoutes := router . Group ( "/corrections/:cid" )
correctionsRoutes . Use ( correctionHandler )
correctionsRoutes . GET ( "" , func ( c * gin . Context ) {
ct := c . MustGet ( "correctiontemplate" ) . ( * CorrectionTemplate )
users , err := ct . GetUserCorrected ( )
if err != nil {
log . Println ( "Unable to GetUserCorrected:" , err )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to retrieve users' corrections" } )
return
2022-02-28 09:52:27 +00:00
}
2022-07-09 17:42:00 +00:00
c . JSON ( http . StatusOK , users )
} )
correctionsRoutes . PUT ( "" , func ( c * gin . Context ) {
current := c . MustGet ( "correctiontemplate" ) . ( * CorrectionTemplate )
2022-02-28 09:52:27 +00:00
var new CorrectionTemplate
2022-07-09 17:42:00 +00:00
if err := c . ShouldBindJSON ( & new ) ; err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2022-02-28 09:52:27 +00:00
}
new . Id = current . Id
2022-07-09 17:42:00 +00:00
2022-02-28 09:52:27 +00:00
if err := new . Update ( ) ; err != nil {
2022-07-09 17:42:00 +00:00
log . Println ( "Unable to Update correctionTemplate:" , err )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to update the correction template" } )
return
2022-02-28 09:52:27 +00:00
}
2022-07-09 17:42:00 +00:00
c . JSON ( http . StatusOK , new )
} )
correctionsRoutes . DELETE ( "" , func ( c * gin . Context ) {
ct := c . MustGet ( "correctiontemplate" ) . ( * CorrectionTemplate )
if _ , err := ct . Delete ( ) ; err != nil {
log . Println ( "Unable to Delete correctionTemplate:" , err )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to delete the correction template." } )
return
}
c . JSON ( http . StatusOK , nil )
} )
}
func declareAPIAdminUserCorrectionsRoutes ( router * gin . RouterGroup ) {
router . GET ( "/corrections" , func ( c * gin . Context ) {
user := c . MustGet ( "user" ) . ( * User )
corrections , err := user . GetCorrections ( )
if err != nil {
log . Printf ( "Unable to GetCorrections(uid=%d): %s" , user . Id , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "Unable to retrieve corrections." } )
return
}
c . JSON ( http . StatusOK , corrections )
} )
router . POST ( "/corrections" , func ( c * gin . Context ) {
user := c . MustGet ( "user" ) . ( * User )
2020-09-13 14:37:15 +00:00
var new UserCorrection
2022-07-09 17:42:00 +00:00
if err := c . ShouldBindJSON ( & new ) ; err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
}
correction , err := user . NewCorrection ( new . IdTemplate )
if err != nil {
log . Printf ( "Unable to NewCorrection(uid=%d): %s" , user . Id , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "Unable to insert the new correction." } )
return
2020-09-13 14:37:15 +00:00
}
2022-07-09 17:42:00 +00:00
c . JSON ( http . StatusOK , correction )
} )
router . PUT ( "/corrections" , func ( c * gin . Context ) {
user := c . MustGet ( "user" ) . ( * User )
2022-02-28 09:52:27 +00:00
var new map [ int64 ] bool
2022-07-09 17:42:00 +00:00
if err := c . ShouldBindJSON ( & new ) ; err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2022-02-28 09:52:27 +00:00
}
2022-07-09 17:42:00 +00:00
correction , err := user . EraseCorrections ( new )
if err != nil {
log . Printf ( "Unable to EraseCorrections(uid=%d): %s" , user . Id , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "Unable to erase the correction." } )
return
}
2020-09-13 14:37:15 +00:00
2022-07-09 17:42:00 +00:00
c . JSON ( http . StatusOK , correction )
} )
correctionsRoutes := router . Group ( "/corrections/:cid" )
correctionsRoutes . Use ( userCorrectionHandler )
correctionsRoutes . DELETE ( "" , func ( c * gin . Context ) {
user := c . MustGet ( "user" ) . ( * User )
uc := c . MustGet ( "correction" ) . ( * UserCorrection )
if _ , err := uc . Delete ( user ) ; err != nil {
log . Printf ( "Unable to Delete(uid=%d, cid=%d) user correction: %s" , user . Id , uc . Id , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "Unable to delete this correction." } )
return
}
c . JSON ( http . StatusOK , nil )
} )
2020-09-13 14:37:15 +00:00
}
2022-07-09 17:42:00 +00:00
func correctionHandler ( c * gin . Context ) {
q := c . MustGet ( "question" ) . ( * Question )
if cid , err := strconv . Atoi ( string ( c . Param ( "cid" ) ) ) ; err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "Invalid correction id" } )
return
} else if correction , err := q . GetCorrectionTemplate ( cid ) ; err != nil {
c . AbortWithStatusJSON ( http . StatusNotFound , gin . H { "errmsg" : "Correction not found" } )
return
} else {
c . Set ( "correctiontemplate" , correction )
c . Next ( )
2020-09-13 14:37:15 +00:00
}
}
type CorrectionTemplate struct {
Id int64 ` json:"id" `
IdQuestion int64 ` json:"id_question" `
Label string ` json:"label" `
2022-02-28 09:52:27 +00:00
RegExp string ` json:"regexp" `
2020-09-13 14:37:15 +00:00
Score int ` json:"score" `
ScoreExplaination string ` json:"score_explaination,omitempty" `
}
2022-07-09 17:42:00 +00:00
func ( q * Question ) GetCorrectionTemplates ( ) ( ct [ ] * CorrectionTemplate , err error ) {
2022-02-28 09:52:27 +00:00
if rows , errr := DBQuery ( "SELECT id_template, id_question, label, re, score, score_explanation FROM correction_templates WHERE id_question=?" , q . Id ) ; errr != nil {
2020-09-13 14:37:15 +00:00
return nil , errr
} else {
defer rows . Close ( )
for rows . Next ( ) {
var c CorrectionTemplate
2022-02-28 09:52:27 +00:00
if err = rows . Scan ( & c . Id , & c . IdQuestion , & c . Label , & c . RegExp , & c . Score , & c . ScoreExplaination ) ; err != nil {
2020-09-13 14:37:15 +00:00
return
}
2022-07-09 17:42:00 +00:00
ct = append ( ct , & c )
2020-09-13 14:37:15 +00:00
}
if err = rows . Err ( ) ; err != nil {
return
}
return
}
}
2022-07-09 17:42:00 +00:00
func ( q * Question ) GetCorrectionTemplate ( id int ) ( c * CorrectionTemplate , err error ) {
c = new ( CorrectionTemplate )
2022-02-28 09:52:27 +00:00
err = DBQueryRow ( "SELECT id_template, id_question, label, re, score, score_explanation FROM correction_templates WHERE id_question=? AND id_template=?" , q . Id , id ) . Scan ( & c . Id , & c . IdQuestion , & c . Label , & c . RegExp , & c . Score , & c . ScoreExplaination )
2020-09-13 14:37:15 +00:00
return
}
2022-07-09 17:42:00 +00:00
func GetCorrectionTemplate ( id int64 ) ( c * CorrectionTemplate , err error ) {
c = new ( CorrectionTemplate )
2022-02-28 09:52:27 +00:00
err = DBQueryRow ( "SELECT id_template, id_question, label, re, score, score_explanation FROM correction_templates WHERE id_template=?" , id ) . Scan ( & c . Id , & c . IdQuestion , & c . Label , & c . RegExp , & c . Score , & c . ScoreExplaination )
2020-09-13 14:37:15 +00:00
return
}
2022-07-09 17:42:00 +00:00
func ( q * Question ) NewCorrectionTemplate ( label string , regexp string , score int , score_explaination string ) ( * CorrectionTemplate , error ) {
2022-02-28 09:52:27 +00:00
if res , err := DBExec ( "INSERT INTO correction_templates (id_question, label, re, score, score_explanation) VALUES (?, ?, ?, ?, ?)" , q . Id , label , regexp , score , score_explaination ) ; err != nil {
2022-07-09 17:42:00 +00:00
return nil , err
2020-09-13 14:37:15 +00:00
} else if cid , err := res . LastInsertId ( ) ; err != nil {
2022-07-09 17:42:00 +00:00
return nil , err
2020-09-13 14:37:15 +00:00
} else {
2022-07-09 17:42:00 +00:00
return & CorrectionTemplate { cid , q . Id , label , regexp , score , score_explaination } , nil
2020-09-13 14:37:15 +00:00
}
}
func ( t * CorrectionTemplate ) Update ( ) error {
2022-02-28 09:52:27 +00:00
_ , err := DBExec ( "UPDATE correction_templates SET id_question = ?, label = ?, re = ?, score = ?, score_explanation = ? WHERE id_template = ?" , t . IdQuestion , t . Label , t . RegExp , t . Score , t . ScoreExplaination , t . Id )
2020-09-13 14:37:15 +00:00
return err
}
func ( t * CorrectionTemplate ) Delete ( ) ( int64 , error ) {
if res , err := DBExec ( "DELETE FROM correction_templates WHERE id_template = ?" , t . Id ) ; err != nil {
return 0 , err
} else if nb , err := res . RowsAffected ( ) ; err != nil {
return 0 , err
} else {
return nb , err
}
}
2022-07-09 17:42:00 +00:00
func ( t * CorrectionTemplate ) GetUserCorrected ( ) ( ucs [ ] * UserCorrection , err error ) {
2020-09-13 14:37:15 +00:00
if rows , errr := DBQuery ( "SELECT id_correction, id_user, id_template FROM student_corrected WHERE id_template=?" , t . Id ) ; errr != nil {
return nil , errr
} else {
defer rows . Close ( )
for rows . Next ( ) {
var c UserCorrection
if err = rows . Scan ( & c . Id , & c . IdUser , & c . IdTemplate ) ; err != nil {
return
}
2022-07-09 17:42:00 +00:00
ucs = append ( ucs , & c )
2020-09-13 14:37:15 +00:00
}
if err = rows . Err ( ) ; err != nil {
return
}
return
}
}
func ClearTemplates ( ) ( int64 , error ) {
if res , err := DBExec ( "DELETE FROM correction_templates" ) ; err != nil {
return 0 , err
} else if nb , err := res . RowsAffected ( ) ; err != nil {
return 0 , err
} else {
return nb , err
}
}
type UserCorrection struct {
Id int64 ` json:"id" `
IdUser int64 ` json:"id_user,omitempty" `
IdTemplate int64 ` json:"id_template" `
}
2022-07-09 17:42:00 +00:00
func userCorrectionHandler ( c * gin . Context ) {
u := c . MustGet ( "user" ) . ( * User )
if cid , err := strconv . Atoi ( string ( c . Param ( "cid" ) ) ) ; err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "Invalid correction id" } )
return
} else if correction , err := u . GetCorrection ( cid ) ; err != nil {
c . AbortWithStatusJSON ( http . StatusNotFound , gin . H { "errmsg" : "Correction not found" } )
return
} else {
c . Set ( "correction" , correction )
c . Next ( )
}
}
2020-09-13 14:37:15 +00:00
func ( u * User ) GetCorrections ( ) ( uc [ ] UserCorrection , err error ) {
if rows , errr := DBQuery ( "SELECT id_correction, id_template FROM student_corrected WHERE id_user=?" , u . Id ) ; errr != nil {
return nil , errr
} else {
defer rows . Close ( )
for rows . Next ( ) {
var c UserCorrection
if err = rows . Scan ( & c . Id , & c . IdTemplate ) ; err != nil {
return
}
uc = append ( uc , c )
}
if err = rows . Err ( ) ; err != nil {
return
}
return
}
}
func ( u * User ) GetCorrectionsTemplate ( ) ( tpls [ ] int64 , err error ) {
if rows , errr := DBQuery ( "SELECT id_template FROM student_corrected WHERE id_user=?" , u . Id ) ; errr != nil {
return nil , errr
} else {
defer rows . Close ( )
for rows . Next ( ) {
var tpl int64
if err = rows . Scan ( & tpl ) ; err != nil {
return
}
tpls = append ( tpls , tpl )
}
if err = rows . Err ( ) ; err != nil {
return
}
return
}
}
2022-07-09 17:42:00 +00:00
func ( u * User ) GetCorrection ( id int ) ( c * UserCorrection , err error ) {
c = new ( UserCorrection )
2020-09-13 14:37:15 +00:00
err = DBQueryRow ( "SELECT id_correction, id_template FROM student_corrected WHERE id_user=? AND id_correction=?" , u . Id , id ) . Scan ( & c . Id , & c . IdTemplate )
return
}
func ( u * User ) NewCorrection ( id int64 ) ( * UserCorrectionSummary , error ) {
if res , err := DBExec ( "INSERT INTO student_corrected (id_user, id_template) VALUES (?, ?)" , u . Id , id ) ; err != nil {
return nil , err
} else if cid , err := res . LastInsertId ( ) ; err != nil {
return nil , err
} else if ucs , err := u . ComputeScoreQuestion ( id ) ; err != nil {
return nil , err
} else {
ucs . LastId = cid
return ucs , nil
}
}
2022-02-28 09:52:27 +00:00
func ( u * User ) EraseCorrections ( ids map [ int64 ] bool ) ( * UserCorrectionSummary , error ) {
var lastid int64
for id , st := range ids {
lastid = id
if st {
DBExec ( "INSERT INTO student_corrected (id_user, id_template) VALUES (?, ?)" , u . Id , id )
} else {
DBExec ( "DELETE FROM student_corrected WHERE id_user = ? AND id_template = ?" , u . Id , id )
}
}
if ucs , err := u . ComputeScoreQuestion ( lastid ) ; err != nil {
return nil , err
} else {
return ucs , nil
}
}
2022-07-09 17:42:00 +00:00
func ( c * UserCorrection ) Delete ( u * User ) ( * UserCorrectionSummary , error ) {
2020-09-13 14:37:15 +00:00
if res , err := DBExec ( "DELETE FROM student_corrected WHERE id_correction = ?" , c . Id ) ; err != nil {
return nil , err
} else if _ , err := res . RowsAffected ( ) ; err != nil {
return nil , err
} else if ucs , err := u . ComputeScoreQuestion ( c . IdTemplate ) ; err != nil {
return nil , err
} else {
return ucs , nil
}
}
type UserCorrectionSummary struct {
LastId int64 ` json:"last_id,omitempty" `
Score int ` json:"score" `
ScoreExplaination string ` json:"score_explaination" `
}
func ( u * User ) ComputeScoreQuestion ( idtpl int64 ) ( * UserCorrectionSummary , error ) {
if tpl , err := GetCorrectionTemplate ( idtpl ) ; err != nil {
return nil , err
} else if question , err := getQuestion ( int ( tpl . IdQuestion ) ) ; err != nil {
return nil , err
} else {
return question . ComputeScoreQuestion ( u )
}
}
func ( q * Question ) ComputeScoreQuestion ( u * User ) ( * UserCorrectionSummary , error ) {
if templates , err := q . GetCorrectionTemplates ( ) ; err != nil {
return nil , err
} else if corrections , err := u . GetCorrectionsTemplate ( ) ; err != nil {
return nil , err
} else {
2022-07-09 17:42:00 +00:00
tpls := map [ int64 ] * CorrectionTemplate { }
2020-09-13 14:37:15 +00:00
for _ , tpl := range templates {
tpls [ tpl . Id ] = tpl
}
score := 100
var expl [ ] string
for _ , correction := range corrections {
if _ , ok := tpls [ correction ] ; ok {
score += tpls [ correction ] . Score
if tpls [ correction ] . ScoreExplaination != "" {
expl = append ( expl , tpls [ correction ] . ScoreExplaination )
}
delete ( tpls , correction )
}
}
return & UserCorrectionSummary { Score : score , ScoreExplaination : strings . Join ( expl , ". " ) } , nil
}
}