Hints can something else than text
This commit is contained in:
parent
8c2e8a19d1
commit
b772a22705
@ -3,6 +3,7 @@ package api
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"srs.epita.fr/fic-server/libfic"
|
"srs.epita.fr/fic-server/libfic"
|
||||||
|
|
||||||
@ -119,17 +120,29 @@ func createExerciceKey(exercice fic.Exercice, body []byte) (interface{}, error)
|
|||||||
return exercice.AddRawKey(uk.Type, uk.Key)
|
return exercice.AddRawKey(uk.Type, uk.Key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type uploadedHint struct {
|
||||||
|
Title string
|
||||||
|
Content string
|
||||||
|
Cost int64
|
||||||
|
Path string
|
||||||
|
}
|
||||||
|
|
||||||
func createExerciceHint(exercice fic.Exercice, body []byte) (interface{}, error) {
|
func createExerciceHint(exercice fic.Exercice, body []byte) (interface{}, error) {
|
||||||
var uh fic.EHint
|
var uh uploadedHint
|
||||||
if err := json.Unmarshal(body, &uh); err != nil {
|
if err := json.Unmarshal(body, &uh); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(uh.Content) == 0 {
|
if len(uh.Content) != 0 {
|
||||||
|
return exercice.AddHint(uh.Title, uh.Content, uh.Cost)
|
||||||
|
} else if len(uh.Path) != 0 {
|
||||||
|
return importFile(uploadedFile{Path: uh.Path},
|
||||||
|
func(filePath string, origin string, digest []byte) (interface{}, error) {
|
||||||
|
return exercice.AddHint(uh.Title, "$FILES" + strings.TrimPrefix(filePath, fic.FilesDir), uh.Cost)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
return nil, errors.New("Hint's content not filled")
|
return nil, errors.New("Hint's content not filled")
|
||||||
}
|
}
|
||||||
|
|
||||||
return exercice.AddHint(uh.Title, uh.Content, uh.Cost)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func showExerciceHint(hint fic.EHint, body []byte) (interface{}, error) {
|
func showExerciceHint(hint fic.EHint, body []byte) (interface{}, error) {
|
||||||
@ -189,6 +202,15 @@ func deleteExerciceKey(key fic.Key, _ fic.Exercice, _ []byte) (interface{}, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func createExerciceFile(exercice fic.Exercice, body []byte) (interface{}, error) {
|
||||||
|
var uf uploadedFile
|
||||||
|
if err := json.Unmarshal(body, &uf); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return importFile(uf, exercice.ImportFile)
|
||||||
|
}
|
||||||
|
|
||||||
func showExerciceFile(file fic.EFile, body []byte) (interface{}, error) {
|
func showExerciceFile(file fic.EFile, body []byte) (interface{}, error) {
|
||||||
return file, nil
|
return file, nil
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
"encoding/base32"
|
"encoding/base32"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
@ -29,12 +28,7 @@ type uploadedFile struct {
|
|||||||
Parts []string
|
Parts []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func createExerciceFile(exercice fic.Exercice, body []byte) (interface{}, error) {
|
func importFile(uf uploadedFile, next func(string, string, []byte) (interface{}, error)) (interface{}, error) {
|
||||||
var uf uploadedFile
|
|
||||||
if err := json.Unmarshal(body, &uf); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var hash [sha512.Size]byte
|
var hash [sha512.Size]byte
|
||||||
var logStr string
|
var logStr string
|
||||||
var fromURI string
|
var fromURI string
|
||||||
@ -80,7 +74,7 @@ func createExerciceFile(exercice fic.Exercice, body []byte) (interface{}, error)
|
|||||||
pathname := path.Join(fic.FilesDir, strings.ToLower(base32.StdEncoding.EncodeToString(hash[:])), path.Base(fromURI))
|
pathname := path.Join(fic.FilesDir, strings.ToLower(base32.StdEncoding.EncodeToString(hash[:])), path.Base(fromURI))
|
||||||
|
|
||||||
// Remove the file if it exists
|
// Remove the file if it exists
|
||||||
if _, err := os.Stat(pathname); os.IsExist(err) && !RapidImport {
|
if _, err := os.Stat(pathname); !os.IsNotExist(err) && !RapidImport {
|
||||||
if err := os.Remove(pathname); err != nil {
|
if err := os.Remove(pathname); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -98,7 +92,7 @@ func createExerciceFile(exercice fic.Exercice, body []byte) (interface{}, error)
|
|||||||
if digest, err := hex.DecodeString(uf.Digest); err != nil {
|
if digest, err := hex.DecodeString(uf.Digest); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
return exercice.ImportFile(pathname, fromURI, digest)
|
return next(pathname, fromURI, digest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +59,12 @@ new_hint() {
|
|||||||
TITLE=`echo "$3" | sed 's/"/\\\\"/g'`
|
TITLE=`echo "$3" | sed 's/"/\\\\"/g'`
|
||||||
CONTENT=`echo "$4" | sed 's/"/\\\\"/g' | sed ':a;N;$!ba;s/\n/<br>/g'`
|
CONTENT=`echo "$4" | sed 's/"/\\\\"/g' | sed ':a;N;$!ba;s/\n/<br>/g'`
|
||||||
COST="$5"
|
COST="$5"
|
||||||
|
URI="$6"
|
||||||
|
|
||||||
curl -f -s -d "{\"title\": \"$TITLE\", \"content\": \"$CONTENT\", \"cost\": $COST}" "${BASEURL}/api/themes/$THEME/exercices/$EXERCICE/hints" |
|
[ -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]+"
|
grep -Eo '"id":[0-9]+,' | grep -Eo "[0-9]+"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,15 +195,28 @@ do
|
|||||||
|
|
||||||
|
|
||||||
# Hints
|
# Hints
|
||||||
EXO_HINT=$(get_file "${THM_BASEURI}${EXO_BASEURI}/hint.txt")
|
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
|
if [ -n "$EXO_HINT" ]; then
|
||||||
HINT_ID=`new_hint "${THEME_ID}" "${EXO_ID}" "Astuce #1" "${EXO_HINT}" "${HINT_COST}"`
|
if echo "${EXO_HINT}" | file --mime-type -b - | grep text/ && [ $(echo "${EXO_HINT}" | wc -l) -lt 25 ]; then
|
||||||
if [ -z "$HINT_ID" ]; then
|
HINT_ID=`new_hint "${THEME_ID}" "${EXO_ID}" "Astuce #${HINT_COUNT}" "${EXO_HINT}" "${HINT_COST}"`
|
||||||
echo -e "\e[31;01m!!! An error occured during hint import!\e[00m (title=Astuce #1;content=${EXO_HINT};cost=${HINT_COST})"
|
|
||||||
else
|
else
|
||||||
echo -e "\e[32m>>> New hint added:\e[00m $HINT_ID - Astuce #1"
|
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};cost=${HINT_COST})"
|
||||||
|
else
|
||||||
|
echo -e "\e[32m>>> New hint added:\e[00m $HINT_ID - Astuce #${HINT_COUNT}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
HINT_COUNT=$(($HINT_COUNT + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
# Files: splited
|
# Files: splited
|
||||||
|
@ -35,8 +35,10 @@
|
|||||||
<form class="pull-right" ng-show="!hint.unlocked" ng-submit="hsubmit(hint)">
|
<form class="pull-right" ng-show="!hint.unlocked" ng-submit="hsubmit(hint)">
|
||||||
<button type="submit" class="btn btn-info" ng-class="{disabled: hint.submitted}"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span> Débloquer</button>
|
<button type="submit" class="btn btn-info" ng-class="{disabled: hint.submitted}"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span> Débloquer</button>
|
||||||
</form>
|
</form>
|
||||||
|
<a class="btn btn-info pull-right" href="{{ hint.content | limitTo:999:6 }}" target="_self" ng-show="hint.content[0] == '$' && hint.content[1] == 'F' && hint.content[4] == 'E' && hint.content[5] == 'S'"><span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span> Télécharger</a>
|
||||||
<h4 class="list-group-item-heading">{{ hint.title }}</h4>
|
<h4 class="list-group-item-heading">{{ hint.title }}</h4>
|
||||||
<p class="list-group-item-text" ng-show="hint.unlocked" ng-bind-html="hint.content"></p>
|
<p class="list-group-item-text" ng-show="hint.unlocked && !(hint.content[0] == '$' && hint.content[1] == 'F' && hint.content[4] == 'E' && hint.content[5] == 'S')" ng-bind-html="hint.content"></p>
|
||||||
|
<p class="list-group-item-text" ng-show="hint.unlocked && (hint.content[0] == '$' && hint.content[1] == 'F' && hint.content[4] == 'E' && hint.content[5] == 'S')">Utilisez le bouton pour télécharger l'indice.</p>
|
||||||
<p class="list-group-item-text" ng-show="!hint.unlocked">Débloquer cet indice vous coûtera <ng-pluralize count="hint.cost" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize>.</p>
|
<p class="list-group-item-text" ng-show="!hint.unlocked">Débloquer cet indice vous coûtera <ng-pluralize count="hint.cost" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize>.</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -69,7 +69,7 @@ func (e Exercice) GetFiles() ([]EFile, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Exercice) ImportFile(filePath string, origin string, digest []byte) (EFile, error) {
|
func (e Exercice) ImportFile(filePath string, origin string, digest []byte) (interface{}, error) {
|
||||||
if digest == nil && !OptionalDigest {
|
if digest == nil && !OptionalDigest {
|
||||||
return EFile{}, errors.New("No digest given.")
|
return EFile{}, errors.New("No digest given.")
|
||||||
} else if fi, err := os.Stat(filePath); err != nil {
|
} else if fi, err := os.Stat(filePath); err != nil {
|
||||||
@ -84,7 +84,6 @@ func (e Exercice) ImportFile(filePath string, origin string, digest []byte) (EFi
|
|||||||
if _, err := io.Copy(hash, reader); err != nil {
|
if _, err := io.Copy(hash, reader); err != nil {
|
||||||
return EFile{}, err
|
return EFile{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result := hash.Sum(nil)
|
result := hash.Sum(nil)
|
||||||
|
|
||||||
if len(digest) != len(result) {
|
if len(digest) != len(result) {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package fic
|
package fic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EHint struct {
|
type EHint struct {
|
||||||
@ -11,11 +13,18 @@ type EHint struct {
|
|||||||
Cost int64 `json:"cost"`
|
Cost int64 `json:"cost"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func treatHintContent(content *string) {
|
||||||
|
if strings.HasPrefix(*content, "$FILES") {
|
||||||
|
*content = "$FILES" + path.Join(FilesDir, strings.TrimPrefix(*content, "$FILES"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func GetHint(id int64) (EHint, error) {
|
func GetHint(id int64) (EHint, error) {
|
||||||
var h EHint
|
var h EHint
|
||||||
if err := DBQueryRow("SELECT id_hint, id_exercice, title, content, cost FROM exercice_hints WHERE id_hint = ?", id).Scan(&h.Id, &h.IdExercice, &h.Title, &h.Content, &h.Cost); err != nil {
|
if err := DBQueryRow("SELECT id_hint, id_exercice, title, content, cost FROM exercice_hints WHERE id_hint = ?", id).Scan(&h.Id, &h.IdExercice, &h.Title, &h.Content, &h.Cost); err != nil {
|
||||||
return h, err
|
return h, err
|
||||||
}
|
}
|
||||||
|
treatHintContent(&h.Content)
|
||||||
|
|
||||||
return h, nil
|
return h, nil
|
||||||
}
|
}
|
||||||
@ -33,6 +42,7 @@ func (e Exercice) GetHints() ([]EHint, error) {
|
|||||||
if err := rows.Scan(&h.Id, &h.Title, &h.Content, &h.Cost); err != nil {
|
if err := rows.Scan(&h.Id, &h.Title, &h.Content, &h.Cost); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
treatHintContent(&h.Content)
|
||||||
hints = append(hints, h)
|
hints = append(hints, h)
|
||||||
}
|
}
|
||||||
if err := rows.Err(); err != nil {
|
if err := rows.Err(); err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user