Multiple hints
This commit is contained in:
parent
d54bc80a59
commit
3525cd610b
@ -115,3 +115,22 @@ func createExerciceKey(theme fic.Theme, exercice fic.Exercice, args map[string]s
|
|||||||
|
|
||||||
return exercice.AddRawKey(uk.Name, uk.Key)
|
return exercice.AddRawKey(uk.Name, uk.Key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type uploadedHint struct {
|
||||||
|
Title string
|
||||||
|
Content string
|
||||||
|
Cost int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func createExerciceHint(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) {
|
||||||
|
var uh uploadedHint
|
||||||
|
if err := json.Unmarshal(body, &uh); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(uh.Content) == 0 {
|
||||||
|
return nil, errors.New("Hint's content not filled")
|
||||||
|
}
|
||||||
|
|
||||||
|
return exercice.AddHint(uh.Title, uh.Content, uh.Cost)
|
||||||
|
}
|
||||||
|
@ -33,6 +33,10 @@ func init() {
|
|||||||
rtef.Methods("GET").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(listThemedExerciceFiles))))
|
rtef.Methods("GET").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(listThemedExerciceFiles))))
|
||||||
rtef.Methods("POST").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(createExerciceFile))))
|
rtef.Methods("POST").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(createExerciceFile))))
|
||||||
|
|
||||||
|
rteh := rte.Path("/hints").Subrouter()
|
||||||
|
rteh.Methods("GET").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(listThemedExerciceHints))))
|
||||||
|
rteh.Methods("POST").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(createExerciceHint))))
|
||||||
|
|
||||||
rtek := rte.Path("/keys").Subrouter()
|
rtek := rte.Path("/keys").Subrouter()
|
||||||
rtek.Methods("GET").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(listThemedExerciceKeys))))
|
rtek.Methods("GET").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(listThemedExerciceKeys))))
|
||||||
rtek.Methods("POST").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(createExerciceKey))))
|
rtek.Methods("POST").HandlerFunc(apiHandler(themeHandler(themedExerciceHandler(createExerciceKey))))
|
||||||
@ -86,6 +90,10 @@ func listThemedExerciceFiles(theme fic.Theme, exercice fic.Exercice, args map[st
|
|||||||
return exercice.GetFiles()
|
return exercice.GetFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func listThemedExerciceHints(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) {
|
||||||
|
return exercice.GetHints()
|
||||||
|
}
|
||||||
|
|
||||||
func listThemedExerciceKeys(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) {
|
func listThemedExerciceKeys(theme fic.Theme, exercice fic.Exercice, args map[string]string, body []byte) (interface{}, error) {
|
||||||
return exercice.GetKeys()
|
return exercice.GetKeys()
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,11 @@ new_exercice() {
|
|||||||
THEME="$1"
|
THEME="$1"
|
||||||
TITLE=`echo "$2" | sed 's/"/\\\\"/g'`
|
TITLE=`echo "$2" | sed 's/"/\\\\"/g'`
|
||||||
STATEMENT=`echo "$3" | sed 's/"/\\\\"/g' | sed ':a;N;$!ba;s/\n/<br>/g'`
|
STATEMENT=`echo "$3" | sed 's/"/\\\\"/g' | sed ':a;N;$!ba;s/\n/<br>/g'`
|
||||||
HINT=`echo "$4" | sed 's/"/\\\\"/g' | sed ':a;N;$!ba;s/\n/<br>/g'`
|
DEPEND="$4"
|
||||||
DEPEND="$5"
|
GAIN="$5"
|
||||||
GAIN="$6"
|
VIDEO="$6"
|
||||||
VIDEO="$7"
|
|
||||||
|
|
||||||
curl -f -s -d "{\"title\": \"$TITLE\", \"statement\": \"$STATEMENT\", \"hint\": \"$HINT\", \"depend\": $DEPEND, \"gain\": $GAIN, \"videoURI\": \"$VIDEO\"}" "${BASEURL}/api/themes/$THEME" |
|
curl -f -s -d "{\"title\": \"$TITLE\", \"statement\": \"$STATEMENT\", \"depend\": $DEPEND, \"gain\": $GAIN, \"videoURI\": \"$VIDEO\"}" "${BASEURL}/api/themes/$THEME" |
|
||||||
grep -Eo '"id":[0-9]+,' | grep -Eo "[0-9]+"
|
grep -Eo '"id":[0-9]+,' | grep -Eo "[0-9]+"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,6 +34,17 @@ new_file() {
|
|||||||
grep -Eo '"id":[0-9]+,' | grep -Eo "[0-9]+"
|
grep -Eo '"id":[0-9]+,' | grep -Eo "[0-9]+"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new_hint() {
|
||||||
|
THEME="$1"
|
||||||
|
EXERCICE="$2"
|
||||||
|
TITLE=`echo "$3" | sed 's/"/\\\\"/g'`
|
||||||
|
CONTENT=`echo "$4" | sed 's/"/\\\\"/g' | sed ':a;N;$!ba;s/\n/<br>/g'`
|
||||||
|
COST="$5"
|
||||||
|
|
||||||
|
curl -f -s -d "{\"title\": \"$TITLE\", \"content\": \"$CONTENT\", \"cost\": \"$COST\"}" "${BASEURL}/api/themes/$THEME/$EXERCICE/hints" |
|
||||||
|
grep -Eo '"id":[0-9]+,' | grep -Eo "[0-9]+"
|
||||||
|
}
|
||||||
|
|
||||||
new_key() {
|
new_key() {
|
||||||
THEME="$1"
|
THEME="$1"
|
||||||
EXERCICE="$2"
|
EXERCICE="$2"
|
||||||
@ -110,9 +120,8 @@ do
|
|||||||
echo ">>> Using default gain: ${EXO_GAIN} points"
|
echo ">>> Using default gain: ${EXO_GAIN} points"
|
||||||
|
|
||||||
EXO_SCENARIO=$(get_file "${THM_BASEURI}${EXO_BASEURI}/scenario.txt")
|
EXO_SCENARIO=$(get_file "${THM_BASEURI}${EXO_BASEURI}/scenario.txt")
|
||||||
EXO_HINT=$(get_file "${THM_BASEURI}${EXO_BASEURI}/hint.txt")
|
|
||||||
|
|
||||||
EXO_ID=`new_exercice "${THEME_ID}" "${EXO_NAME}" "${EXO_SCENARIO}" "${EXO_HINT}" "${LAST}" "${EXO_GAIN}" "/resolution${THM_BASEURI}${EXO_BASEURI}resolution/${EXO_VIDEO}"`
|
EXO_ID=`new_exercice "${THEME_ID}" "${EXO_NAME}" "${EXO_SCENARIO}" "${LAST}" "${EXO_GAIN}" "/resolution${THM_BASEURI}${EXO_BASEURI}resolution/${EXO_VIDEO}"`
|
||||||
if [ -z "$EXO_ID" ]; then
|
if [ -z "$EXO_ID" ]; then
|
||||||
echo -e "\e[31;01m!!! An error occured during exercice add.\e[00m"
|
echo -e "\e[31;01m!!! An error occured during exercice add.\e[00m"
|
||||||
continue
|
continue
|
||||||
@ -140,6 +149,16 @@ do
|
|||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
|
# Hints
|
||||||
|
EXO_HINT=$(get_file "${THM_BASEURI}${EXO_BASEURI}/hint.txt")
|
||||||
|
HINT_ID=`new_hint "${THEME_ID}" "${EXO_ID}" "Astuce #1" "${EXO_HINT}" "1"`
|
||||||
|
if [ -z "$HINT_ID" ]; then
|
||||||
|
echo -e "\e[31;01m!!! An error occured during hint import!\e[00m (title=Astuce #1;content=${EXO_HINT};cost=1)"
|
||||||
|
else
|
||||||
|
echo -e "\e[32m>>> New hint added:\e[00m $HINT_ID - Astuce #1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Files
|
# Files
|
||||||
get_dir "${THM_BASEURI}${EXO_BASEURI}files/" | grep -v DIGESTS.txt | while read f; do basename "$f"; done | while read FILE_URI
|
get_dir "${THM_BASEURI}${EXO_BASEURI}files/" | grep -v DIGESTS.txt | while read f; do basename "$f"; done | while read FILE_URI
|
||||||
do
|
do
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div style="margin-top: 15px" class="well well-lg" ng-show="(my.exercices[current_exercice])">
|
<div style="margin-top: 15px" class="well well-lg" ng-show="(my.exercices[current_exercice])">
|
||||||
<p ng-bind-html="my.exercices[current_exercice].statement"></p>
|
<p ng-bind-html="my.exercices[current_exercice].statement"></p>
|
||||||
<blockquote ng-show="(my.exercices[current_exercice].hint)" ng-bind-html="my.exercices[current_exercice].hint"></blockquote>
|
|
||||||
<hr ng-show="!(my.exercices[current_exercice].hint)">
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Gain :</strong> {{ themes[current_theme].exercices[current_exercice].gain }} points</li>
|
<li><strong>Gain :</strong> {{ themes[current_theme].exercices[current_exercice].gain }} points</li>
|
||||||
<li><strong>Résolu par :</strong> {{ themes[current_theme].exercices[current_exercice].solved }} équipes</li>
|
<li><strong>Résolu par :</strong> {{ themes[current_theme].exercices[current_exercice].solved }} équipes</li>
|
||||||
@ -28,6 +26,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="panel panel-info" ng-show="(my.exercices[current_exercice] && my.exercices[current_exercice].hints.length)">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<div class="panel-title"><span class="glyphicon glyphicon-lamp" aria-hidden="true"></span> Indices</div>
|
||||||
|
</div>
|
||||||
|
<ul class="list-group">
|
||||||
|
<li class="list-group-item" ng-repeat="hint in my.exercices[current_exercice].hints">
|
||||||
|
<form class="pull-right" ng-show="!hint.unlocked">
|
||||||
|
<button type="submit" class="btn btn-info"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span> Débloquer</button>
|
||||||
|
</form>
|
||||||
|
<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">Cet indice vous coûtera {{ hint.cost }}% des points de l'exercice</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="panel panel-danger" ng-show="my.team_id && my.exercices[current_exercice] && !(my.exercices[current_exercice].solved)">
|
<div class="panel panel-danger" ng-show="my.team_id && my.exercices[current_exercice] && !(my.exercices[current_exercice].solved)">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<div class="panel-title"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> Soumettre une solution</div>
|
<div class="panel-title"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> Soumettre une solution</div>
|
||||||
|
24
libfic/db.go
24
libfic/db.go
@ -64,7 +64,6 @@ CREATE TABLE IF NOT EXISTS exercices(
|
|||||||
id_theme INTEGER NOT NULL,
|
id_theme INTEGER NOT NULL,
|
||||||
title VARCHAR(255) NOT NULL,
|
title VARCHAR(255) NOT NULL,
|
||||||
statement TEXT NOT NULL,
|
statement TEXT NOT NULL,
|
||||||
hint TEXT NOT NULL,
|
|
||||||
depend INTEGER,
|
depend INTEGER,
|
||||||
gain INTEGER NOT NULL,
|
gain INTEGER NOT NULL,
|
||||||
video_uri VARCHAR(255) NOT NULL,
|
video_uri VARCHAR(255) NOT NULL,
|
||||||
@ -85,6 +84,18 @@ CREATE TABLE IF NOT EXISTS exercice_files(
|
|||||||
size INTEGER NOT NULL,
|
size INTEGER NOT NULL,
|
||||||
FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice)
|
FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice)
|
||||||
);
|
);
|
||||||
|
`); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := db.Exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS exercice_hints(
|
||||||
|
id_hint INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
id_exercice INTEGER NOT NULL,
|
||||||
|
title VARCHAR(255) NOT NULL,
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
cost INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice)
|
||||||
|
);
|
||||||
`); err != nil {
|
`); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -118,6 +129,17 @@ CREATE TABLE IF NOT EXISTS exercice_tries(
|
|||||||
FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice),
|
FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice),
|
||||||
FOREIGN KEY(id_team) REFERENCES teams(id_team)
|
FOREIGN KEY(id_team) REFERENCES teams(id_team)
|
||||||
);
|
);
|
||||||
|
`); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := db.Exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS team_hints(
|
||||||
|
id_team INTEGER,
|
||||||
|
id_hint INTEGER,
|
||||||
|
time TIMESTAMP NOT NULL,
|
||||||
|
FOREIGN KEY(id_hint) REFERENCES exercice_hints(id_hint),
|
||||||
|
FOREIGN KEY(id_team) REFERENCES teams(id_team)
|
||||||
|
);
|
||||||
`); err != nil {
|
`); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ type Exercice struct {
|
|||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Statement string `json:"statement"`
|
Statement string `json:"statement"`
|
||||||
Hint string `json:"hint"`
|
|
||||||
Depend *int64 `json:"depend"`
|
Depend *int64 `json:"depend"`
|
||||||
Gain int64 `json:"gain"`
|
Gain int64 `json:"gain"`
|
||||||
VideoURI string `json:"videoURI"`
|
VideoURI string `json:"videoURI"`
|
||||||
@ -17,7 +16,7 @@ type Exercice struct {
|
|||||||
|
|
||||||
func GetExercice(id int64) (Exercice, error) {
|
func GetExercice(id int64) (Exercice, error) {
|
||||||
var e Exercice
|
var e Exercice
|
||||||
if err := DBQueryRow("SELECT id_exercice, title, statement, hint, depend, gain, video_uri FROM exercices WHERE id_exercice = ?", id).Scan(&e.Id, &e.Title, &e.Statement, &e.Hint, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
|
if err := DBQueryRow("SELECT id_exercice, title, statement, depend, gain, video_uri FROM exercices WHERE id_exercice = ?", id).Scan(&e.Id, &e.Title, &e.Statement, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
|
||||||
return Exercice{}, err
|
return Exercice{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +25,7 @@ func GetExercice(id int64) (Exercice, error) {
|
|||||||
|
|
||||||
func (t Theme) GetExercice(id int) (Exercice, error) {
|
func (t Theme) GetExercice(id int) (Exercice, error) {
|
||||||
var e Exercice
|
var e Exercice
|
||||||
if err := DBQueryRow("SELECT id_exercice, title, statement, hint, depend, gain, video_uri FROM exercices WHERE id_theme = ? AND id_exercice = ?", t.Id, id).Scan(&e.Id, &e.Title, &e.Statement, &e.Hint, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
|
if err := DBQueryRow("SELECT id_exercice, title, statement, depend, gain, video_uri FROM exercices WHERE id_theme = ? AND id_exercice = ?", t.Id, id).Scan(&e.Id, &e.Title, &e.Statement, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
|
||||||
return Exercice{}, err
|
return Exercice{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ func (t Theme) GetExercice(id int) (Exercice, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetExercices() ([]Exercice, error) {
|
func GetExercices() ([]Exercice, error) {
|
||||||
if rows, err := DBQuery("SELECT id_exercice, title, statement, hint, depend, gain, video_uri FROM exercices"); err != nil {
|
if rows, err := DBQuery("SELECT id_exercice, title, statement, depend, gain, video_uri FROM exercices"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
@ -42,7 +41,7 @@ func GetExercices() ([]Exercice, error) {
|
|||||||
var exos = make([]Exercice, 0)
|
var exos = make([]Exercice, 0)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var e Exercice
|
var e Exercice
|
||||||
if err := rows.Scan(&e.Id, &e.Title, &e.Statement, &e.Hint, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
|
if err := rows.Scan(&e.Id, &e.Title, &e.Statement, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
exos = append(exos, e)
|
exos = append(exos, e)
|
||||||
@ -56,7 +55,7 @@ func GetExercices() ([]Exercice, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t Theme) GetExercices() ([]Exercice, error) {
|
func (t Theme) GetExercices() ([]Exercice, error) {
|
||||||
if rows, err := DBQuery("SELECT id_exercice, title, statement, hint, depend, gain, video_uri FROM exercices WHERE id_theme = ?", t.Id); err != nil {
|
if rows, err := DBQuery("SELECT id_exercice, title, statement, depend, gain, video_uri FROM exercices WHERE id_theme = ?", t.Id); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
@ -64,7 +63,7 @@ func (t Theme) GetExercices() ([]Exercice, error) {
|
|||||||
var exos = make([]Exercice, 0)
|
var exos = make([]Exercice, 0)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var e Exercice
|
var e Exercice
|
||||||
if err := rows.Scan(&e.Id, &e.Title, &e.Statement, &e.Hint, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
|
if err := rows.Scan(&e.Id, &e.Title, &e.Statement, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
exos = append(exos, e)
|
exos = append(exos, e)
|
||||||
@ -77,28 +76,28 @@ func (t Theme) GetExercices() ([]Exercice, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Theme) AddExercice(title string, statement string, hint string, depend *Exercice, gain int, videoURI string) (Exercice, error) {
|
func (t Theme) AddExercice(title string, statement string, depend *Exercice, gain int, videoURI string) (Exercice, error) {
|
||||||
var dpd interface{}
|
var dpd interface{}
|
||||||
if depend == nil {
|
if depend == nil {
|
||||||
dpd = nil
|
dpd = nil
|
||||||
} else {
|
} else {
|
||||||
dpd = depend.Id
|
dpd = depend.Id
|
||||||
}
|
}
|
||||||
if res, err := DBExec("INSERT INTO exercices (id_theme, title, statement, hint, depend, gain, video_uri) VALUES (?, ?, ?, ?, ?, ?, ?)", t.Id, title, statement, hint, dpd, gain, videoURI); err != nil {
|
if res, err := DBExec("INSERT INTO exercices (id_theme, title, statement, depend, gain, video_uri) VALUES (?, ?, ?, ?, ?, ?)", t.Id, title, statement, dpd, gain, videoURI); err != nil {
|
||||||
return Exercice{}, err
|
return Exercice{}, err
|
||||||
} else if eid, err := res.LastInsertId(); err != nil {
|
} else if eid, err := res.LastInsertId(); err != nil {
|
||||||
return Exercice{}, err
|
return Exercice{}, err
|
||||||
} else {
|
} else {
|
||||||
if depend == nil {
|
if depend == nil {
|
||||||
return Exercice{eid, title, statement, hint, nil, int64(gain), videoURI}, nil
|
return Exercice{eid, title, statement, nil, int64(gain), videoURI}, nil
|
||||||
} else {
|
} else {
|
||||||
return Exercice{eid, title, statement, hint, &depend.Id, int64(gain), videoURI}, nil
|
return Exercice{eid, title, statement, &depend.Id, int64(gain), videoURI}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Exercice) Update() (int64, error) {
|
func (e Exercice) Update() (int64, error) {
|
||||||
if res, err := DBExec("UPDATE exercices SET title = ?, statement = ?, hint = ?, depend = ?, gain = ?, video_uri = ? WHERE id_exercice = ?", e.Title, e.Statement, e.Hint, e.Depend, e.Gain, e.VideoURI, e.Id); err != nil {
|
if res, err := DBExec("UPDATE exercices SET title = ?, statement = ?, depend = ?, gain = ?, video_uri = ? WHERE id_exercice = ?", e.Title, e.Statement, e.Depend, e.Gain, e.VideoURI, e.Id); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
} else if nb, err := res.RowsAffected(); err != nil {
|
} else if nb, err := res.RowsAffected(); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
65
libfic/hint.go
Normal file
65
libfic/hint.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package fic
|
||||||
|
|
||||||
|
import (
|
||||||
|
)
|
||||||
|
|
||||||
|
type EHint struct {
|
||||||
|
Id int64 `json:"id"`
|
||||||
|
IdExercice int64 `json:"idExercice"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Content string `json:"content"`
|
||||||
|
Cost int64 `json:"cost"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Exercice) GetHints() ([]EHint, error) {
|
||||||
|
if rows, err := DBQuery("SELECT id_hint, title, content, cost FROM exercice_hints WHERE id_exercice = ?", e.Id); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var hints = make([]EHint, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
var h EHint
|
||||||
|
h.IdExercice = e.Id
|
||||||
|
if err := rows.Scan(&h.Id, &h.Title, &h.Content, &h.Cost); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hints = append(hints, h)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return hints, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Exercice) AddHint(title string, content string, cost int64) (EHint, error) {
|
||||||
|
if res, err := DBExec("INSERT INTO exercice_hints (id_exercice, title, content, cost) VALUES (?, ?, ?, ?)", e.Id, title, content, cost); err != nil {
|
||||||
|
return EHint{}, err
|
||||||
|
} else if hid, err := res.LastInsertId(); err != nil {
|
||||||
|
return EHint{}, err
|
||||||
|
} else {
|
||||||
|
return EHint{hid, e.Id, title, content, cost}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h EHint) Update() (int64, error) {
|
||||||
|
if res, err := DBExec("UPDATE exercice_hints SET id_exercice = ?, title = ?, content = ?, cost = ? WHERE id_hint = ?", h.IdExercice, h.Title, h.Content, h.Cost, h.Id); err != nil {
|
||||||
|
return 0, err
|
||||||
|
} else if nb, err := res.RowsAffected(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
} else {
|
||||||
|
return nb, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h EHint) Delete() (int64, error) {
|
||||||
|
if res, err := DBExec("DELETE FROM exercice_hints WHERE id_hint = ?", h.Id); err != nil {
|
||||||
|
return 0, err
|
||||||
|
} else if nb, err := res.RowsAffected(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
} else {
|
||||||
|
return nb, err
|
||||||
|
}
|
||||||
|
}
|
@ -210,6 +210,12 @@ func GetTries(t *Team, e *Exercice) ([]time.Time, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t Team) HasHint(h EHint) (bool) {
|
||||||
|
var tm *time.Time
|
||||||
|
DBQueryRow("SELECT MIN(time) FROM team_hints WHERE id_team = ? AND id_hint = ?", t.Id, h.Id).Scan(&tm)
|
||||||
|
return tm != nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t Team) HasSolved(e Exercice) (bool, time.Time, int64) {
|
func (t Team) HasSolved(e Exercice) (bool, time.Time, int64) {
|
||||||
var nb *int64
|
var nb *int64
|
||||||
var tm *time.Time
|
var tm *time.Time
|
||||||
|
@ -13,10 +13,17 @@ type myTeamFile struct {
|
|||||||
Checksum string `json:"checksum"`
|
Checksum string `json:"checksum"`
|
||||||
Size int64 `json:"size"`
|
Size int64 `json:"size"`
|
||||||
}
|
}
|
||||||
|
type myTeamHint struct {
|
||||||
|
HintId int64 `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Content string `json:"content"`
|
||||||
|
Cost int64 `json:"cost"`
|
||||||
|
Unlocked bool `json:"unlocked"`
|
||||||
|
}
|
||||||
type myTeamExercice struct {
|
type myTeamExercice struct {
|
||||||
ThemeId int `json:"theme_id"`
|
ThemeId int `json:"theme_id"`
|
||||||
Statement string `json:"statement"`
|
Statement string `json:"statement"`
|
||||||
Hint string `json:"hint"`
|
Hints []myTeamHint `json:"hints"`
|
||||||
Gain int64 `json:"gain"`
|
Gain int64 `json:"gain"`
|
||||||
Files []myTeamFile `json:"files"`
|
Files []myTeamFile `json:"files"`
|
||||||
Keys []string `json:"keys"`
|
Keys []string `json:"keys"`
|
||||||
@ -35,6 +42,8 @@ type myTeam struct {
|
|||||||
|
|
||||||
func MyJSONTeam(t *Team, started bool) (interface{}, error) {
|
func MyJSONTeam(t *Team, started bool) (interface{}, error) {
|
||||||
ret := myTeam{}
|
ret := myTeam{}
|
||||||
|
|
||||||
|
// Fill information about the team
|
||||||
if t == nil {
|
if t == nil {
|
||||||
ret.Id = 0
|
ret.Id = 0
|
||||||
} else {
|
} else {
|
||||||
@ -46,8 +55,9 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
ret.Exercices = map[string]myTeamExercice{}
|
|
||||||
|
|
||||||
|
// Fill exercices, only if the challenge is started
|
||||||
|
ret.Exercices = map[string]myTeamExercice{}
|
||||||
if exos, err := GetExercices(); err != nil {
|
if exos, err := GetExercices(); err != nil {
|
||||||
return ret, err
|
return ret, err
|
||||||
} else if started {
|
} else if started {
|
||||||
@ -58,7 +68,6 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
|
|||||||
exercice.ThemeId = tid
|
exercice.ThemeId = tid
|
||||||
}
|
}
|
||||||
exercice.Statement = e.Statement
|
exercice.Statement = e.Statement
|
||||||
exercice.Hint = e.Hint
|
|
||||||
if t == nil {
|
if t == nil {
|
||||||
exercice.VideoURI = e.VideoURI
|
exercice.VideoURI = e.VideoURI
|
||||||
exercice.Solved = true
|
exercice.Solved = true
|
||||||
@ -67,6 +76,36 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
|
|||||||
exercice.Solved, exercice.SolvedTime, exercice.SolvedNumber = t.HasSolved(e)
|
exercice.Solved, exercice.SolvedTime, exercice.SolvedNumber = t.HasSolved(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expose exercice files
|
||||||
|
|
||||||
|
exercice.Files = []myTeamFile{}
|
||||||
|
|
||||||
|
if files, err := e.GetFiles(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
for _, f := range files {
|
||||||
|
exercice.Files = append(exercice.Files, myTeamFile{path.Join(FilesDir, f.Path), f.Name, hex.EncodeToString(f.Checksum), f.Size})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expose exercice hints
|
||||||
|
|
||||||
|
exercice.Hints = []myTeamHint{}
|
||||||
|
|
||||||
|
if hints, err := e.GetHints(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
for _, h := range hints {
|
||||||
|
if t == nil || t.HasHint(h) {
|
||||||
|
exercice.Hints = append(exercice.Hints, myTeamHint{h.Id, h.Title, h.Content, h.Cost, true})
|
||||||
|
} else {
|
||||||
|
exercice.Hints = append(exercice.Hints, myTeamHint{h.Id, h.Title, "", h.Cost, false})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expose exercice keys
|
||||||
|
|
||||||
exercice.Keys = []string{}
|
exercice.Keys = []string{}
|
||||||
|
|
||||||
if keys, err := e.GetKeys(); err != nil {
|
if keys, err := e.GetKeys(); err != nil {
|
||||||
@ -81,16 +120,7 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exercice.Files = []myTeamFile{}
|
// Hash table ordered by exercice Id
|
||||||
|
|
||||||
if files, err := e.GetFiles(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else {
|
|
||||||
for _, f := range files {
|
|
||||||
exercice.Files = append(exercice.Files, myTeamFile{path.Join(FilesDir, f.Path), f.Name, hex.EncodeToString(f.Checksum), f.Size})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.Exercices[fmt.Sprintf("%d", e.Id)] = exercice
|
ret.Exercices[fmt.Sprintf("%d", e.Id)] = exercice
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user