2020-09-13 14:37:15 +00:00
package main
import (
"encoding/json"
"strconv"
"strings"
"github.com/julienschmidt/httprouter"
)
func init ( ) {
router . GET ( "/api/surveys/:sid/questions/:qid/corrections" , apiHandler ( questionHandler (
func ( q Question , _ [ ] byte ) HTTPResponse {
if cts , err := q . GetCorrectionTemplates ( ) ; err != nil {
return APIErrorResponse { err : err }
} else {
return APIResponse { cts }
}
} ) , adminRestricted ) )
router . POST ( "/api/surveys/:sid/questions/:qid/corrections" , apiHandler ( questionHandler ( func ( q Question , body [ ] byte ) HTTPResponse {
var new CorrectionTemplate
if err := json . Unmarshal ( body , & new ) ; err != nil {
return APIErrorResponse { err : err }
}
2022-02-28 09:52:27 +00:00
return formatApiResponse ( q . NewCorrectionTemplate ( new . Label , new . RegExp , new . Score , new . ScoreExplaination ) )
2020-09-13 14:37:15 +00:00
} ) , adminRestricted ) )
router . GET ( "/api/surveys/:sid/questions/:qid/corrections/:cid" , apiHandler ( correctionHandler (
func ( ct CorrectionTemplate , _ [ ] byte ) HTTPResponse {
if users , err := ct . GetUserCorrected ( ) ; err != nil {
return APIErrorResponse { err : err }
} else {
return APIResponse { users }
}
} ) , adminRestricted ) )
router . PUT ( "/api/surveys/:sid/questions/:qid/corrections/:cid" , apiHandler ( correctionHandler ( func ( current CorrectionTemplate , body [ ] byte ) HTTPResponse {
var new CorrectionTemplate
if err := json . Unmarshal ( body , & new ) ; err != nil {
return APIErrorResponse { err : err }
}
new . Id = current . Id
if err := new . Update ( ) ; err != nil {
return APIErrorResponse { err : err }
} else {
return APIResponse { new }
}
} ) , adminRestricted ) )
router . DELETE ( "/api/surveys/:sid/questions/:qid/corrections/:cid" , apiHandler ( correctionHandler ( func ( ct CorrectionTemplate , body [ ] byte ) HTTPResponse {
return formatApiResponse ( ct . Delete ( ) )
} ) , adminRestricted ) )
2022-02-28 09:52:27 +00:00
router . GET ( "/api/questions/:qid/corrections" , apiHandler ( questionHandler (
func ( q Question , _ [ ] byte ) HTTPResponse {
if cts , err := q . GetCorrectionTemplates ( ) ; err != nil {
return APIErrorResponse { err : err }
} else {
return APIResponse { cts }
}
} ) , adminRestricted ) )
router . POST ( "/api/questions/:qid/corrections" , apiHandler ( questionHandler ( func ( q Question , body [ ] byte ) HTTPResponse {
var new CorrectionTemplate
if err := json . Unmarshal ( body , & new ) ; err != nil {
return APIErrorResponse { err : err }
}
return formatApiResponse ( q . NewCorrectionTemplate ( new . Label , new . RegExp , new . Score , new . ScoreExplaination ) )
} ) , adminRestricted ) )
router . GET ( "/api/questions/:qid/corrections/:cid" , apiHandler ( correctionHandler (
func ( ct CorrectionTemplate , _ [ ] byte ) HTTPResponse {
if users , err := ct . GetUserCorrected ( ) ; err != nil {
return APIErrorResponse { err : err }
} else {
return APIResponse { users }
}
} ) , adminRestricted ) )
router . PUT ( "/api/questions/:qid/corrections/:cid" , apiHandler ( correctionHandler ( func ( current CorrectionTemplate , body [ ] byte ) HTTPResponse {
var new CorrectionTemplate
if err := json . Unmarshal ( body , & new ) ; err != nil {
return APIErrorResponse { err : err }
}
new . Id = current . Id
if err := new . Update ( ) ; err != nil {
return APIErrorResponse { err : err }
} else {
return APIResponse { new }
}
} ) , adminRestricted ) )
router . DELETE ( "/api/questions/:qid/corrections/:cid" , apiHandler ( correctionHandler ( func ( ct CorrectionTemplate , body [ ] byte ) HTTPResponse {
return formatApiResponse ( ct . Delete ( ) )
} ) , adminRestricted ) )
2020-09-13 14:37:15 +00:00
router . GET ( "/api/users/:uid/questions/:qid" , apiAuthHandler ( func ( u * User , ps httprouter . Params , body [ ] byte ) HTTPResponse {
return userHandler ( func ( u User , _ [ ] byte ) HTTPResponse {
if qid , err := strconv . Atoi ( string ( ps . ByName ( "qid" ) ) ) ; err != nil {
return APIErrorResponse { err : err }
} else if question , err := getQuestion ( qid ) ; err != nil {
return APIErrorResponse { err : err }
} else {
return formatApiResponse ( question . ComputeScoreQuestion ( & u ) )
}
} ) ( ps , body )
} , adminRestricted ) )
router . GET ( "/api/users/:uid/corrections" , apiHandler ( userHandler (
func ( u User , _ [ ] byte ) HTTPResponse {
return formatApiResponse ( u . GetCorrections ( ) )
} ) , adminRestricted ) )
router . POST ( "/api/users/:uid/corrections" , apiHandler ( userHandler ( func ( u User , body [ ] byte ) HTTPResponse {
var new UserCorrection
if err := json . Unmarshal ( body , & new ) ; err != nil {
return APIErrorResponse { err : err }
}
return formatApiResponse ( u . NewCorrection ( new . IdTemplate ) )
} ) , adminRestricted ) )
2022-02-28 09:52:27 +00:00
router . PUT ( "/api/users/:uid/corrections" , apiHandler ( userHandler ( func ( u User , body [ ] byte ) HTTPResponse {
var new map [ int64 ] bool
if err := json . Unmarshal ( body , & new ) ; err != nil {
return APIErrorResponse { err : err }
}
return formatApiResponse ( u . EraseCorrections ( new ) )
} ) , adminRestricted ) )
2020-09-13 14:37:15 +00:00
router . DELETE ( "/api/users/:uid/corrections/:cid" , apiHandler ( userCorrectionHandler ( func ( u User , uc UserCorrection , body [ ] byte ) HTTPResponse {
return formatApiResponse ( uc . Delete ( u ) )
} ) , adminRestricted ) )
}
func correctionHandler ( f func ( CorrectionTemplate , [ ] byte ) HTTPResponse ) func ( httprouter . Params , [ ] byte ) HTTPResponse {
return func ( ps httprouter . Params , body [ ] byte ) HTTPResponse {
return questionHandler ( func ( q Question , body [ ] byte ) HTTPResponse {
if cid , err := strconv . Atoi ( string ( ps . ByName ( "cid" ) ) ) ; err != nil {
return APIErrorResponse { err : err }
} else if correction , err := q . GetCorrectionTemplate ( cid ) ; err != nil {
return APIErrorResponse { err : err }
} else {
return f ( correction , body )
}
} ) ( ps , body )
}
}
func userCorrectionHandler ( f func ( User , UserCorrection , [ ] byte ) HTTPResponse ) func ( httprouter . Params , [ ] byte ) HTTPResponse {
return func ( ps httprouter . Params , body [ ] byte ) HTTPResponse {
return userHandler ( func ( u User , body [ ] byte ) HTTPResponse {
if cid , err := strconv . Atoi ( string ( ps . ByName ( "cid" ) ) ) ; err != nil {
return APIErrorResponse { err : err }
} else if correction , err := u . GetCorrection ( cid ) ; err != nil {
return APIErrorResponse { err : err }
} else {
return f ( u , correction , body )
}
} ) ( ps , body )
}
}
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" `
}
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
}
ct = append ( ct , c )
}
if err = rows . Err ( ) ; err != nil {
return
}
return
}
}
func ( q * Question ) GetCorrectionTemplate ( id int ) ( c CorrectionTemplate , err error ) {
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
}
func GetCorrectionTemplate ( id int64 ) ( c CorrectionTemplate , err error ) {
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-02-28 09:52:27 +00:00
func ( q * Question ) NewCorrectionTemplate ( label string , regexp string , score int , score_explaination string ) ( CorrectionTemplate , error ) {
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 {
2020-09-13 14:37:15 +00:00
return CorrectionTemplate { } , err
} else if cid , err := res . LastInsertId ( ) ; err != nil {
return CorrectionTemplate { } , err
} else {
2022-02-28 09:52:27 +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
}
}
func ( t * CorrectionTemplate ) GetUserCorrected ( ) ( ucs [ ] UserCorrection , err error ) {
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
}
ucs = append ( ucs , c )
}
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" `
}
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
}
}
func ( u * User ) GetCorrection ( id int ) ( c UserCorrection , err error ) {
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
}
}
2020-09-13 14:37:15 +00:00
func ( c * UserCorrection ) Delete ( u User ) ( * UserCorrectionSummary , error ) {
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 {
tpls := map [ int64 ] CorrectionTemplate { }
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
}
}