diff --git a/admin/api/exercice.go b/admin/api/exercice.go
index a1ab5153..d7c7ebd6 100644
--- a/admin/api/exercice.go
+++ b/admin/api/exercice.go
@@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"strings"
+ "time"
"srs.epita.fr/fic-server/admin/sync"
"srs.epita.fr/fic-server/libfic"
@@ -14,12 +15,17 @@ import (
func init() {
router.GET("/api/exercices/", apiHandler(listExercices))
+ router.GET("/api/resolutions.json", apiHandler(exportResolutionMovies))
router.GET("/api/exercices/:eid", apiHandler(exerciceHandler(showExercice)))
router.PUT("/api/exercices/:eid", apiHandler(exerciceHandler(updateExercice)))
router.PATCH("/api/exercices/:eid", apiHandler(exerciceHandler(partUpdateExercice)))
router.DELETE("/api/exercices/:eid", apiHandler(exerciceHandler(deleteExercice)))
+ router.GET("/api/exercices/:eid/stats", apiHandler(exerciceHandler(getExerciceStats)))
+ router.GET("/api/exercices/:eid/history.json", apiHandler(exerciceHandler(getExerciceHistory)))
+ router.DELETE("/api/exercices/:eid/history.json", apiHandler(exerciceHandler(delExerciceHistory)))
+
router.GET("/api/exercices/:eid/files", apiHandler(exerciceHandler(listExerciceFiles)))
router.POST("/api/exercices/:eid/files", apiHandler(exerciceHandler(createExerciceFile)))
router.GET("/api/exercices/:eid/files/:fid", apiHandler(exerciceFileHandler(showExerciceFile)))
@@ -85,6 +91,28 @@ func listExercices(_ httprouter.Params, body []byte) (interface{}, error) {
return fic.GetExercices()
}
+// Generate the csv to export with:
+// curl -s http://127.0.0.1:8081/api/resolutions.json | jq -r ".[] | [ .theme,.title, @uri \"https://fic.srs.epita.fr/resolution/\\(.videoURI)\" ] | join(\";\")"
+func exportResolutionMovies(_ httprouter.Params, body []byte) (interface{}, error) {
+ if exercices, err := fic.GetExercices(); err != nil {
+ return nil, err
+ } else {
+ export := []map[string]string{}
+ for _, exercice := range exercices {
+ if theme, err := fic.GetTheme(exercice.IdTheme); err != nil {
+ return nil, err
+ } else {
+ export = append(export, map[string]string{
+ "videoURI": exercice.VideoURI,
+ "theme": theme.Name,
+ "title": exercice.Title,
+ })
+ }
+ }
+ return export, nil
+ }
+}
+
func listExerciceFiles(exercice fic.Exercice, body []byte) (interface{}, error) {
return exercice.GetFiles()
}
@@ -109,6 +137,35 @@ func showExercice(exercice fic.Exercice, body []byte) (interface{}, error) {
return exercice, nil
}
+func getExerciceStats(exercice fic.Exercice, body []byte) (interface{}, error) {
+ team_tries, tries := exercice.TriesByTeam()
+ return map[string]interface{}{
+ "solved": exercice.SolvedTeams(),
+ "total_tried": tries,
+ "team_tries": team_tries,
+ }, nil
+}
+
+func getExerciceHistory(exercice fic.Exercice, body []byte) (interface{}, error) {
+ return exercice.GetHistory()
+}
+
+type uploadedExerciceHistory struct {
+ IdTeam int64 `json:"team_id"`
+ Kind string
+ Time time.Time
+ Secondary *int64
+}
+
+func delExerciceHistory(exercice fic.Exercice, body []byte) (interface{}, error) {
+ var uh uploadedExerciceHistory
+ if err := json.Unmarshal(body, &uh); err != nil {
+ return nil, err
+ }
+
+ return exercice.DelHistoryItem(uh.IdTeam, uh.Kind, uh.Time, uh.Secondary)
+}
+
func deleteExercice(exercice fic.Exercice, _ []byte) (interface{}, error) {
return exercice.Delete()
}
diff --git a/admin/api/team.go b/admin/api/team.go
index dcffb055..8c32692d 100644
--- a/admin/api/team.go
+++ b/admin/api/team.go
@@ -238,10 +238,27 @@ func setTeamMember(team fic.Team, body []byte) (interface{}, error) {
}
type uploadedHistory struct {
- Kind string
- Time time.Time
- Primary *int64
- Secondary *int64
+ Kind string
+ Time time.Time
+ Primary *int64
+ Secondary *int64
+ Coefficient float32
+}
+
+func updateHistory(team *fic.Team, body []byte) (interface{}, error) {
+ var uh uploadedHistory
+ if err := json.Unmarshal(body, &uh); err != nil {
+ return nil, err
+ }
+
+ var givenId int64
+ if uh.Secondary != nil {
+ givenId = *uh.Secondary
+ } else if uh.Primary != nil {
+ givenId = *uh.Primary
+ }
+
+ return team.UpdateHistoryCoeff(uh.Kind, uh.Time, givenId, uh.Coefficient)
}
func delHistory(team *fic.Team, body []byte) (interface{}, error) {
diff --git a/admin/fill_exercices.sh b/admin/fill_exercices.sh
deleted file mode 100755
index e2ce2141..00000000
--- a/admin/fill_exercices.sh
+++ /dev/null
@@ -1,262 +0,0 @@
-#!/bin/bash
-
-BASEURL="http://localhost:8081"
-BASEURI="https://owncloud.srs.epita.fr/remote.php/webdav/FIC 2018"
-BASEFILE="/mnt/fic/"
-CLOUDPASS="$CLOUD_USER:$CLOUD_PASS"
-
-new_theme() {
- NAME=`echo $1 | sed 's/"/\\\\"/g'`
- AUTHORS=`echo $2 | sed 's/"/\\\\"/g'`
- curl -f -s -d "{\"name\": \"$NAME\", \"authors\": \"$AUTHORS\"}" "${BASEURL}/api/themes" |
- grep -Eo '"id":[0-9]+,' | grep -Eo "[0-9]+"
-}
-
-new_exercice() {
- THEME="$1"
- TITLE=`echo "$2" | sed 's/"/\\\\"/g'`
- STATEMENT=`echo "$3" | sed 's/"/\\\\"/g' | sed ':a;N;$!ba;s/\n/
/g'`
- DEPEND="$4"
- GAIN="$5"
- VIDEO="$6"
-
- curl -f -s -d "{\"title\": \"$TITLE\", \"statement\": \"$STATEMENT\", \"depend\": $DEPEND, \"gain\": $GAIN, \"videoURI\": \"$VIDEO\"}" "${BASEURL}/api/themes/$THEME/exercices" |
- grep -Eo '"id":[0-9]+,' | grep -Eo "[0-9]+"
-}
-
-new_file() (
- THEME="$1"
- EXERCICE="$2"
- URI="$3"
- DIGEST="$4"
- ARGS="$5"
-
- FIRST=
- PARTS=$(echo "$ARGS" | while read arg
- do
- [ -n "$arg" ] && {
- [ -z "${FIRST}" ] || echo -n ","
- echo "\"$arg\""
- }
- FIRST=1
- done)
-
- [ -n "${DIGEST}" ] && DIGEST=", \"digest\": \"${DIGEST}\""
-
- cat <&2
-{"path": "${BASEFILE}${URI}"${DIGEST}, "parts": [${PARTS}]}
-EOF
-
-# curl -f -s -d "{\"URI\": \"${BASEFILE}${URI}\"}" "${BASEURL}/api/themes/$THEME/$EXERCICE/files" |
- curl -f -s -d @- "${BASEURL}/api/themes/$THEME/exercices/$EXERCICE/files" </g'`
- COST="$5"
- URI="$6"
-
- [ -n "${CONTENT}" ] && CONTENT=", \"content\": \"${CONTENT}\""
- [ -n "${URI}" ] && URI=", \"path\": \"${BASEFILE}${URI}\""
-
- curl -f -s -d "{\"title\": \"$TITLE\"$CONTENT$URI, \"cost\": $COST}" "${BASEURL}/api/themes/$THEME/exercices/$EXERCICE/hints" |
- grep -Eo '"id":[0-9]+,' | grep -Eo "[0-9]+"
-}
-
-new_key() {
- THEME="$1"
- EXERCICE="$2"
- TYPE="$3"
- KEY=`echo $4 | sed 's#\\\\#\\\\\\\\#g' | sed 's/"/\\\\"/g'`
-
- curl -f -s -d "{\"type\": \"$TYPE\", \"key\": \"$KEY\"}" "${BASEURL}/api/themes/$THEME/exercices/$EXERCICE/keys" |
- grep -Eo '"id":[0-9]+,' | grep -Eo "[0-9]+"
-}
-
-get_dir_from_cloud() {
- curl -f -s -X PROPFIND -u "${CLOUDPASS}" "${BASEURI}$1" | xmllint --format - | grep 'd:href' | sed -E 's/^.*>(.*)<.*$/\1/'
-}
-get_dir() {
- ls "${BASEFILE}$1" 2> /dev/null
-}
-#alias get_dir=get_dir_from_cloud
-
-get_file_from_cloud() {
- curl -f -s -u "${CLOUDPASS}" "${BASEURI}$1" | tr -d '\r'
-}
-get_file() {
- cat "${BASEFILE}$1" 2> /dev/null | tr -d '\r'
- echo
-}
-#alias get_file=get_file_from_cloud
-
-unhtmlentities() {
- cat | sed -E 's/%20/ /g' | sed -E "s/%27/'/g" | sed -E 's/%c3%a9/é/g' | sed -E 's/%c3%a8/è/g'
-}
-
-# Theme
-{
- if [ $# -ge 1 ]; then
- echo $1
- else
- get_dir ""
- fi
-} | while read f; do basename "$f"; done | while read THEME_URI
-do
- THM_BASEURI="/${THEME_URI}/"
- THEME_NAME=$(echo "${THEME_URI#*-}" | unhtmlentities)
- THEME_AUTHORS=$(get_file "${THM_BASEURI}/AUTHORS.txt" | sed '/^$/d;s/$/, /' | tr -d '\n' | sed 's/, $//')
- THEME_ID=`new_theme "$THEME_NAME" "$THEME_AUTHORS"`
- if [ -z "$THEME_ID" ]; then
- echo -e "\e[31;01m!!! An error occured during theme add\e[00m"
- continue
- else
- echo -e "\e[33m>>> New theme created:\e[00m $THEME_ID - $THEME_NAME"
- fi
-
- LAST=null
- EXO_NUM=0
- {
- if [ $# -ge 2 ]; then
- echo "$2"
- else
- get_dir "${THM_BASEURI}"
- fi
- } | while read f; do basename "$f"; done | while read EXO_URI
- do
- case ${EXO_URI} in
- [0-9]-*)
- ;;
- *)
- continue;;
- esac
-
- #EXO_NUM=$((EXO_NUM + 1))
- EXO_NUM=${EXO_URI%-*}
- EXO_NAME=$(echo "${EXO_URI#*-}" | unhtmlentities)
- echo
- echo -e "\e[36m--- Filling exercice ${EXO_NUM} in theme ${THEME_NAME}\e[00m"
-
- EXO_BASEURI="${EXO_URI}/"
-
- EXO_VIDEO=$(get_dir "${THM_BASEURI}${EXO_BASEURI}/resolution/" | grep -E "\.(mov|mkv|mp4|avi|flv|ogv|webm)$" | while read f; do basename "$f"; done | tail -1)
- [ -n "$EXO_VIDEO" ] && EXO_VIDEO="/resolution${THM_BASEURI}${EXO_BASEURI}resolution/${EXO_VIDEO}"
-
- if [ "${LAST}" = "null" ]; then
- echo ">>> Assuming this exercice has no dependency"
- else
- echo ">>> Assuming this exercice depends on the last entry (id=${LAST})"
- fi
-
- EXO_GAIN=$((3 * (2 ** $EXO_NUM) - 1))
- HINT_COST=$(($EXO_GAIN / 4))
- echo ">>> Using default gain: ${EXO_GAIN} points"
-
- EXO_SCENARIO=$(get_file "${THM_BASEURI}${EXO_BASEURI}/scenario.txt")
-
- EXO_ID=`new_exercice "${THEME_ID}" "${EXO_NAME}" "${EXO_SCENARIO}" "${LAST}" "${EXO_GAIN}" "${EXO_VIDEO}"`
- if [ -z "$EXO_ID" ]; then
- echo -e "\e[31;01m!!! An error occured during exercice add.\e[00m"
- continue
- else
- echo -e "\e[32m>>> New exercice created:\e[00m $EXO_ID - $EXO_NAME"
- fi
-
-
- # Keys
- get_file "${THM_BASEURI}${EXO_BASEURI}/flags.txt" | while read KEYLINE
- do
- [ -z "${KEYLINE}" ] && continue
-
- KEY_NAME=$(echo "$KEYLINE" | cut -d$'\t' -f 1)
- KEY_RAW=$(echo "$KEYLINE" | cut -d$'\t' -f 2-)
-
- if [ -z "${KEY_RAW}" ] || [ "${KEY_NAME}" = "${KEY_RAW}" ]; then
- KEY_NAME=$(echo "$KEYLINE" | cut -d : -f 1)
- KEY_RAW=$(echo "$KEYLINE" | cut -d : -f 2-)
- fi
-
- if [ -z "${KEY_NAME}" ]; then
- KEY_NAME="Flag"
- fi
-
- KEY_ID=`new_key "${THEME_ID}" "${EXO_ID}" "${KEY_NAME}" "${KEY_RAW}"`
- if [ -z "$KEY_ID" ]; then
- echo -e "\e[31;01m!!! An error occured during key import!\e[00m (name=${KEYNAME};raw=${KEY_RAW})"
- else
- echo -e "\e[32m>>> New key added:\e[00m $KEY_ID - $KEY_NAME"
- fi
- done
-
-
- # Hints
- HINTS=$(get_dir "${THM_BASEURI}${EXO_BASEURI}/hints/" | sed -E 's#(.*)#hints/\1#')
- [ -z "${HINTS}" ] && HINTS=$(get_dir "${THM_BASEURI}${EXO_BASEURI}/" | grep ^hint.)
- [ -z "${HINTS}" ] && HINTS="hint.txt"
- HINT_COUNT=1
- echo "${HINTS}" | while read HINT
- do
- EXO_HINT=$(get_file "${THM_BASEURI}${EXO_BASEURI}/${HINT}")
- if [ -n "$EXO_HINT" ]; then
- EXO_HINT_TYPE=$(echo "${EXO_HINT}" | file --mime-type -b -)
- if echo "${EXO_HINT_TYPE}" | grep text/ && [ $(echo "${EXO_HINT}" | wc -l) -lt 25 ]; then
- HINT_ID=`new_hint "${THEME_ID}" "${EXO_ID}" "Astuce #${HINT_COUNT}" "${EXO_HINT}" "${HINT_COST}"`
- else
- HINT_ID=`new_hint "${THEME_ID}" "${EXO_ID}" "Astuce #${HINT_COUNT}" "" "${HINT_COST}" "${THM_BASEURI}${EXO_BASEURI}/${HINT}"`
- fi
-
- if [ -z "$HINT_ID" ]; then
- echo -e "\e[31;01m!!! An error occured during hint import!\e[00m (title=Astuce #${HINT_COUNT};content::${EXO_HINT_TYPE};cost=${HINT_COST})"
- else
- echo -e "\e[32m>>> New hint added:\e[00m $HINT_ID - Astuce #${HINT_COUNT}"
- fi
- fi
- HINT_COUNT=$(($HINT_COUNT + 1))
- done
-
-
- # Files: splited
- get_dir "${THM_BASEURI}${EXO_BASEURI}files/" | grep -v DIGESTS.txt | grep '[0-9][0-9]$' | sed -E 's/\.?([0-9][0-9])$//' | sort | uniq | while read f; do basename "$f"; done | while read FILE_URI
- do
- DIGEST=$(get_file "${THM_BASEURI}${EXO_BASEURI}files/DIGESTS.txt" | grep "${FILE_URI}\$" | awk '{ print $1; }')
-
- PARTS=
- for part in $(get_dir "${THM_BASEURI}${EXO_BASEURI}files/" | grep "${FILE_URI}" | sort)
- do
- PARTS="${PARTS}${BASEFILE}${THM_BASEURI}${EXO_BASEURI}files/${part}
-"
- done
- echo -e "\e[35mImport splited file ${THM_BASEURI}${EXO_BASEURI}files/${FILE_URI} from\e[00m `echo ${PARTS} | tr '\n' ' '`"
-
- FILE_ID=`new_file "${THEME_ID}" "${EXO_ID}" "${THM_BASEURI}${EXO_BASEURI}files/${FILE_URI}" "${DIGEST}" "${PARTS}"`
- if [ -z "$FILE_ID" ]; then
- echo -e "\e[31;01m!!! An error occured during file import! Please check path.\e[00m"
- else
- echo -e "\e[32m>>> New file added:\e[00m $FILE_ID - $FILE_URI"
- fi
- done
-
- # Files: entire
- get_dir "${THM_BASEURI}${EXO_BASEURI}files/" | grep -v DIGESTS.txt | grep -v '[0-9][0-9]$' | while read f; do basename "$f"; done | while read FILE_URI
- do
- DIGEST=$(get_file "${THM_BASEURI}${EXO_BASEURI}files/DIGESTS.txt" | grep "${FILE_URI}\$" | awk '{ print $1; }')
-
- echo "Import file ${THM_BASEURI}${EXO_BASEURI}files/${FILE_URI}"
- FILE_ID=`new_file "${THEME_ID}" "${EXO_ID}" "${THM_BASEURI}${EXO_BASEURI}files/${FILE_URI}" "${DIGEST}"`
- if [ -z "$FILE_ID" ]; then
- echo -e "\e[31;01m!!! An error occured during file import! Please check path.\e[00m"
- else
- echo -e "\e[32m>>> New file added:\e[00m $FILE_ID - $FILE_URI"
- fi
- done
-
-
- LAST=$EXO_ID
- done
- echo
-done
diff --git a/admin/get_files.sh b/admin/get_files.sh
deleted file mode 100755
index 68c032cb..00000000
--- a/admin/get_files.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-
-BASEURL="http://localhost:8081"
-BASEURI="https://srs.epita.fr/owncloud/remote.php/webdav/FIC 2016"
-CLOUDUSER='fic'
-CLOUDPASS='f>t\nV33R|(+?$i*'
-
-if [ $# -gt 0 ]
-then
- WHERE=$1
-else
- WHERE="files"
-fi
-
-curl -q -f ${BASEURL}/api/themes/files-bindings | while read l
-do
- FROM=$(echo "$l" | cut -d ";" -f 1)
- DEST=$(echo "$l" | cut -d ";" -f 2)
-
- mkdir -p $(dirname "${WHERE}${DEST}")
-
- wget -O "${WHERE}${DEST}" --user "${CLOUDUSER}" --password "${CLOUDPASS}" "${BASEURI}${FROM}"
-done
diff --git a/admin/index.go b/admin/index.go
index 0461becf..595d0b2f 100644
--- a/admin/index.go
+++ b/admin/index.go
@@ -32,8 +32,8 @@ const indextpl = `