Handle optionnal flags
This commit is contained in:
parent
e581630d5e
commit
a414cd22c8
18 changed files with 68 additions and 22 deletions
|
@ -735,7 +735,8 @@ type uploadedFlag struct {
|
|||
SortReGroups bool `json:"sort_re_grps"`
|
||||
Flag string
|
||||
Value []byte
|
||||
ChoicesCost int64 `json:"choices_cost"`
|
||||
ChoicesCost int32 `json:"choices_cost"`
|
||||
BonusGain int32 `json:"bonus_gain"`
|
||||
}
|
||||
|
||||
func createExerciceFlag(c *gin.Context) {
|
||||
|
@ -758,7 +759,7 @@ func createExerciceFlag(c *gin.Context) {
|
|||
|
||||
exercice := c.MustGet("exercice").(*fic.Exercice)
|
||||
|
||||
flag, err := exercice.AddRawFlagKey(uk.Label, uk.Type, uk.Placeholder, uk.IgnoreCase, uk.NoTrim, uk.Multiline, vre, uk.SortReGroups, []byte(uk.Flag), uk.ChoicesCost)
|
||||
flag, err := exercice.AddRawFlagKey(uk.Label, uk.Type, uk.Placeholder, uk.IgnoreCase, uk.NoTrim, uk.Multiline, vre, uk.SortReGroups, []byte(uk.Flag), uk.ChoicesCost, uk.BonusGain)
|
||||
if err != nil {
|
||||
log.Println("Unable to createExerciceFlag:", err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs when trying to create flag."})
|
||||
|
@ -839,6 +840,7 @@ func updateExerciceFlag(c *gin.Context) {
|
|||
flag.Checksum = uk.Value
|
||||
}
|
||||
flag.ChoicesCost = uk.ChoicesCost
|
||||
flag.BonusGain = uk.BonusGain
|
||||
|
||||
if uk.ValidatorRe != nil && len(*uk.ValidatorRe) > 0 {
|
||||
flag.ValidatorRegexp = uk.ValidatorRe
|
||||
|
|
|
@ -62,6 +62,9 @@
|
|||
<div class="col-2">
|
||||
<input type="text" id="kccost{{flag.id}}" ng-model="flag.choices_cost" class="form-control form-control-sm" placeholder="Choices cost" title="Choices cost" integer>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<input type="text" id="kbgain{{flag.id}}" ng-model="flag.bonus_gain" class="form-control form-control-sm" placeholder="Bonus gain" title="Bonus gain" integer>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<input type="text" id="korder{{flag.id}}" ng-model="flag.order" class="form-control form-control-sm" placeholder="Order" title="Order" integer>
|
||||
</div>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<th>Date</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="row in scores | filter: query | orderBy:'time'" ng-class="{'bg-ffound': row.reason == 'First blood', 'bg-wchoices': row.reason == 'Display choices', 'bg-success': row.reason == 'Validation', 'bg-info': row.reason == 'Hint', 'bg-warning': row.reason == 'Tries'}">
|
||||
<tr ng-repeat="row in scores | filter: query | orderBy:'time'" ng-class="{'bg-danger': row.reason == 'Bonus flag', 'bg-ffound': row.reason == 'First blood', 'bg-wchoices': row.reason == 'Display choices', 'bg-success': row.reason == 'Validation', 'bg-info': row.reason == 'Hint', 'bg-warning': row.reason == 'Tries'}">
|
||||
<td>
|
||||
<a ng-repeat="exercice in exercices" ng-if="exercice.id == row.id_exercice" href="exercices/{{ row.id_exercice }}">{{ exercice.title }}</a>
|
||||
</td>
|
||||
|
|
|
@ -43,7 +43,8 @@ type ExerciceFlag struct {
|
|||
SortReGroups bool `toml:"sort_validator_regexp_groups,omitempty"`
|
||||
Placeholder string `toml:",omitempty"`
|
||||
Help string `toml:",omitempty"`
|
||||
ChoicesCost int64 `toml:"choices_cost,omitempty"`
|
||||
BonusGain int32 `toml:"bonus_gain,omitempty"`
|
||||
ChoicesCost int32 `toml:"choices_cost,omitempty"`
|
||||
Choice []ExerciceFlagChoice
|
||||
LockedFile []ExerciceUnlockFile `toml:"unlock_file,omitempty"`
|
||||
NeedFlag []ExerciceDependency `toml:"need_flag,omitempty"`
|
||||
|
|
|
@ -170,6 +170,7 @@ func buildKeyFlag(exercice *fic.Exercice, flag ExerciceFlag, flagline int, defau
|
|||
SortReGroups: flag.SortReGroups,
|
||||
Checksum: hashedFlag[:],
|
||||
ChoicesCost: flag.ChoicesCost,
|
||||
BonusGain: flag.BonusGain,
|
||||
})
|
||||
f = &fl
|
||||
|
||||
|
|
|
@ -82,8 +82,7 @@ func treatSubmission(pathname string, team *fic.Team, exercice_id string) {
|
|||
// Ensure the team didn't already solve this exercice
|
||||
tm := team.HasSolved(exercice)
|
||||
if tm != nil {
|
||||
log.Printf("%s [WRN] Team %d ALREADY solved exercice %d (%s : %s)\n", id, team.Id, exercice.Id, theme.Name, exercice.Title)
|
||||
return
|
||||
log.Printf("%s [WRN] Team %d ALREADY solved exercice %d (%s : %s), continuing for eventual bonus flags\n", id, team.Id, exercice.Id, theme.Name, exercice.Title)
|
||||
}
|
||||
|
||||
// Handle MCQ justifications: convert to expected keyid
|
||||
|
@ -119,7 +118,9 @@ func treatSubmission(pathname string, team *fic.Team, exercice_id string) {
|
|||
log.Println(id, "[ERR] Can't remove file:", err)
|
||||
}
|
||||
|
||||
if solved {
|
||||
if tm != nil {
|
||||
genTeamQueue <- team
|
||||
} else if solved {
|
||||
log.Printf("%s Team %d SOLVED exercice %d (%s : %s)\n", id, team.Id, exercice.Id, theme.Name, exercice.Title)
|
||||
if err := exercice.Solved(team); err != nil {
|
||||
log.Println(id, "[ERR] Unable to mark the challenge as solved:", err)
|
||||
|
|
|
@ -100,6 +100,11 @@
|
|||
</script>
|
||||
|
||||
<div class="form-group mb-3">
|
||||
{#if flag.bonus_gain}
|
||||
<div class={'float-end badge bg-' + (flag.found?'success':'danger')} title={'Ce flag est optionnel, si vous le complétez il vous rapportera ' + flag.bonus_gain + ' points supplémentaires'}>
|
||||
optionnel | {#if flag.bonus_gain > 0}+{/if}{flag.bonus_gain} pts
|
||||
</div>
|
||||
{/if}
|
||||
<label for="sol_{flag.type}{flag.id}_0">{flag.label} :</label>
|
||||
{#if flag.found && flag.value}
|
||||
<span>{flag.value}</span>
|
||||
|
|
|
@ -161,7 +161,7 @@
|
|||
{/if}
|
||||
</Col>
|
||||
<Col lg="6" class="mb-5">
|
||||
{#if !$my.exercices[exercice.id].solved_rank && !solved[exercice.id]}
|
||||
{#if $my.exercices[exercice.id].flags && $my.exercices[exercice.id].non_found_flags > 0 && !solved[exercice.id]}
|
||||
<ExerciceFlags
|
||||
{refresh_my}
|
||||
{refresh_teams}
|
||||
|
@ -169,7 +169,8 @@
|
|||
bind:forcesolved={solved[exercice.id]}
|
||||
flags={$my.exercices[exercice.id].flags}
|
||||
/>
|
||||
{:else}
|
||||
{/if}
|
||||
{#if $my.exercices[exercice.id].solved_rank || solved[exercice.id]}
|
||||
<ExerciceSolved
|
||||
{theme}
|
||||
exercice={$my.exercices[exercice.id]}
|
||||
|
|
|
@ -11,6 +11,15 @@ function createMyStore() {
|
|||
for (let k in my.exercices) {
|
||||
my.exercices[k].id = k;
|
||||
|
||||
if (my.exercices[k].flags) {
|
||||
let nb = 0;
|
||||
for (let j in my.exercices[k].flags) {
|
||||
if (!my.exercices[k].flags[j].found)
|
||||
nb += 1;
|
||||
}
|
||||
my.exercices[k].non_found_flags = nb;
|
||||
}
|
||||
|
||||
if (my.team_id === 0 && my.exercices[k].hints) {
|
||||
for (let j in my.exercices[k].hints) {
|
||||
my.exercices[k].hints[j].hidden = true;
|
||||
|
|
|
@ -195,7 +195,8 @@ CREATE TABLE IF NOT EXISTS exercice_flags(
|
|||
validator_regexp VARCHAR(255) NULL,
|
||||
sort_re_grps BOOLEAN NOT NULL DEFAULT 0,
|
||||
cksum BINARY(64) NOT NULL,
|
||||
choices_cost INTEGER NOT NULL,
|
||||
choices_cost MEDIUMINT NOT NULL,
|
||||
bonus_gain MEDIUMINT NOT NULL,
|
||||
FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice)
|
||||
) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
|
||||
`); err != nil {
|
||||
|
|
|
@ -471,10 +471,10 @@ func (e *Exercice) CheckResponse(cksum []byte, respflags map[int]string, respmcq
|
|||
// Check flags
|
||||
for _, flag := range flags {
|
||||
if res, ok := respflags[flag.Id]; !ok && (!PartialValidation || t.HasPartiallySolved(flag) == nil) {
|
||||
valid = false
|
||||
valid = valid && flag.IsOptionnal()
|
||||
} else if flag.Check([]byte(res)) != 0 {
|
||||
if !PartialValidation || t.HasPartiallySolved(flag) == nil {
|
||||
valid = false
|
||||
valid = valid && flag.IsOptionnal()
|
||||
}
|
||||
} else {
|
||||
flag.FoundBy(t)
|
||||
|
|
|
@ -338,7 +338,7 @@ func (f *EFile) GetDepends() ([]Flag, error) {
|
|||
if err := rows.Scan(&d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deps = append(deps, &FlagKey{d, f.IdExercice, 0, "", "", "", "", "", false, false, false, nil, false, []byte{}, 0})
|
||||
deps = append(deps, &FlagKey{d, f.IdExercice, 0, "", "", "", "", "", false, false, false, nil, false, []byte{}, 0, 0})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -12,6 +12,7 @@ type Flag interface {
|
|||
GetDepends() ([]Flag, error)
|
||||
GetOrder() int8
|
||||
Check(val interface{}) int
|
||||
IsOptionnal() bool
|
||||
FoundBy(t *Team)
|
||||
}
|
||||
|
||||
|
|
|
@ -42,12 +42,14 @@ type FlagKey struct {
|
|||
// Checksum is the expected hashed flag
|
||||
Checksum []byte `json:"value"`
|
||||
// ChoicesCost is the number of points lost to display choices.
|
||||
ChoicesCost int64 `json:"choices_cost"`
|
||||
ChoicesCost int32 `json:"choices_cost"`
|
||||
// BonusGain makes the flag completion optionnal. If it is filled and correct, it gives some points.
|
||||
BonusGain int32 `json:"bonus_gain"`
|
||||
}
|
||||
|
||||
// GetFlagKeys returns a list of key's flags comming with the challenge.
|
||||
func (e *Exercice) GetFlagKeys() ([]*FlagKey, error) {
|
||||
if rows, err := DBQuery("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, sort_re_grps, cksum, choices_cost FROM exercice_flags WHERE id_exercice = ?", e.Id); err != nil {
|
||||
if rows, err := DBQuery("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, sort_re_grps, cksum, choices_cost, bonus_gain FROM exercice_flags WHERE id_exercice = ?", e.Id); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
@ -57,7 +59,7 @@ func (e *Exercice) GetFlagKeys() ([]*FlagKey, error) {
|
|||
k := &FlagKey{}
|
||||
k.IdExercice = e.Id
|
||||
|
||||
if err := rows.Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.NoTrim, &k.Multiline, &k.ValidatorRegexp, &k.SortReGroups, &k.Checksum, &k.ChoicesCost); err != nil {
|
||||
if err := rows.Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.NoTrim, &k.Multiline, &k.ValidatorRegexp, &k.SortReGroups, &k.Checksum, &k.ChoicesCost, &k.BonusGain); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -74,21 +76,21 @@ func (e *Exercice) GetFlagKeys() ([]*FlagKey, error) {
|
|||
// GetFlagKey returns a list of flags comming with the challenge.
|
||||
func GetFlagKey(id int) (k *FlagKey, err error) {
|
||||
k = &FlagKey{}
|
||||
err = DBQueryRow("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, sort_re_grps, cksum, choices_cost FROM exercice_flags WHERE id_flag = ?", id).Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.Multiline, &k.NoTrim, &k.ValidatorRegexp, &k.SortReGroups, &k.Checksum, &k.ChoicesCost)
|
||||
err = DBQueryRow("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, sort_re_grps, cksum, choices_cost, bonus_gain FROM exercice_flags WHERE id_flag = ?", id).Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.Multiline, &k.NoTrim, &k.ValidatorRegexp, &k.SortReGroups, &k.Checksum, &k.ChoicesCost, &k.BonusGain)
|
||||
return
|
||||
}
|
||||
|
||||
// GetFlagKey returns a flag.
|
||||
func (e *Exercice) GetFlagKey(id int) (k *FlagKey, err error) {
|
||||
k = &FlagKey{}
|
||||
err = DBQueryRow("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, sort_re_grps, cksum, choices_cost FROM exercice_flags WHERE id_flag = ? AND id_exercice = ?", id, e.Id).Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.NoTrim, &k.Multiline, &k.ValidatorRegexp, &k.SortReGroups, &k.Checksum, &k.ChoicesCost)
|
||||
err = DBQueryRow("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, sort_re_grps, cksum, choices_cost, bonus_gain FROM exercice_flags WHERE id_flag = ? AND id_exercice = ?", id, e.Id).Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.NoTrim, &k.Multiline, &k.ValidatorRegexp, &k.SortReGroups, &k.Checksum, &k.ChoicesCost, &k.BonusGain)
|
||||
return
|
||||
}
|
||||
|
||||
// GetFlagKeyByLabel returns a flag matching the given label.
|
||||
func (e *Exercice) GetFlagKeyByLabel(label string) (k *FlagKey, err error) {
|
||||
k = &FlagKey{}
|
||||
err = DBQueryRow("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, sort_re_grps, cksum, choices_cost FROM exercice_flags WHERE type LIKE ? AND id_exercice = ?", label, e.Id).Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.NoTrim, &k.Multiline, &k.ValidatorRegexp, &k.SortReGroups, &k.Checksum, &k.ChoicesCost)
|
||||
err = DBQueryRow("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, sort_re_grps, cksum, choices_cost, bonus_gain FROM exercice_flags WHERE type LIKE ? AND id_exercice = ?", label, e.Id).Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.NoTrim, &k.Multiline, &k.ValidatorRegexp, &k.SortReGroups, &k.Checksum, &k.ChoicesCost, &k.BonusGain)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -139,7 +141,7 @@ func ExecValidatorRegexp(vre string, val []byte, ignorecase bool, sortregroups b
|
|||
}
|
||||
|
||||
// AddRawFlagKey creates and fills a new struct FlagKey, from a non-hashed flag, and registers it into the database.
|
||||
func (e *Exercice) AddRawFlagKey(name string, t string, placeholder string, ignorecase bool, multiline bool, notrim bool, validator_regexp *string, sortregroups bool, raw_value []byte, choicescost int64) (*FlagKey, error) {
|
||||
func (e *Exercice) AddRawFlagKey(name string, t string, placeholder string, ignorecase bool, multiline bool, notrim bool, validator_regexp *string, sortregroups bool, raw_value []byte, choicescost int32, bonusgain int32) (*FlagKey, error) {
|
||||
hash, err := ComputeHashedFlag(raw_value, ignorecase, notrim, validator_regexp, sortregroups)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -156,6 +158,7 @@ func (e *Exercice) AddRawFlagKey(name string, t string, placeholder string, igno
|
|||
SortReGroups: sortregroups,
|
||||
Checksum: hash[:],
|
||||
ChoicesCost: choicescost,
|
||||
BonusGain: bonusgain,
|
||||
}
|
||||
|
||||
_, err = f.Create(e)
|
||||
|
@ -185,7 +188,7 @@ func (k *FlagKey) Create(e *Exercice) (Flag, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if res, err := DBExec("INSERT INTO exercice_flags (id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, sort_re_grps, cksum, choices_cost) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", e.Id, k.Order, k.Label, k.Type, k.Placeholder, k.Help, k.Unit, k.IgnoreCase, k.NoTrim, k.Multiline, k.ValidatorRegexp, k.SortReGroups, k.Checksum, k.ChoicesCost); err != nil {
|
||||
if res, err := DBExec("INSERT INTO exercice_flags (id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, sort_re_grps, cksum, choices_cost, bonus_gain) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", e.Id, k.Order, k.Label, k.Type, k.Placeholder, k.Help, k.Unit, k.IgnoreCase, k.NoTrim, k.Multiline, k.ValidatorRegexp, k.SortReGroups, k.Checksum, k.ChoicesCost, k.BonusGain); err != nil {
|
||||
return k, err
|
||||
} else if kid, err := res.LastInsertId(); err != nil {
|
||||
return k, err
|
||||
|
@ -210,7 +213,7 @@ func (k *FlagKey) Update() (int64, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if res, err := DBExec("UPDATE exercice_flags SET id_exercice = ?, ordre = ?, label = ?, type = ?, placeholder = ?, help = ?, unit = ?, ignorecase = ?, notrim = ?, multiline = ?, validator_regexp = ?, sort_re_grps = ?, cksum = ?, choices_cost = ? WHERE id_flag = ?", k.IdExercice, k.Order, k.Label, k.Type, k.Placeholder, k.Help, k.Unit, k.IgnoreCase, k.NoTrim, k.Multiline, k.ValidatorRegexp, k.SortReGroups, k.Checksum, k.ChoicesCost, k.Id); err != nil {
|
||||
if res, err := DBExec("UPDATE exercice_flags SET id_exercice = ?, ordre = ?, label = ?, type = ?, placeholder = ?, help = ?, unit = ?, ignorecase = ?, notrim = ?, multiline = ?, validator_regexp = ?, sort_re_grps = ?, cksum = ?, choices_cost = ?, bonus_gain = ? WHERE id_flag = ?", k.IdExercice, k.Order, k.Label, k.Type, k.Placeholder, k.Help, k.Unit, k.IgnoreCase, k.NoTrim, k.Multiline, k.ValidatorRegexp, k.SortReGroups, k.Checksum, k.ChoicesCost, k.BonusGain, k.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
return 0, err
|
||||
|
@ -299,6 +302,11 @@ func (k *FlagKey) GetDepends() ([]Flag, error) {
|
|||
return deps, nil
|
||||
}
|
||||
|
||||
// IsOptionnal to know if the flag can be omitted when validating the step.
|
||||
func (k *FlagKey) IsOptionnal() bool {
|
||||
return k.BonusGain != 0
|
||||
}
|
||||
|
||||
// Check if the given val is the expected one for this flag.
|
||||
func (k *FlagKey) Check(v interface{}) int {
|
||||
var val []byte
|
||||
|
|
|
@ -167,6 +167,11 @@ func (k *FlagLabel) GetDepends() ([]Flag, error) {
|
|||
return deps, nil
|
||||
}
|
||||
|
||||
// IsOptionnal to know if the flag can be omitted when validating the step.
|
||||
func (k *FlagLabel) IsOptionnal() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if the given val is the expected one for this flag.
|
||||
func (k *FlagLabel) Check(v interface{}) int {
|
||||
return 0
|
||||
|
|
|
@ -314,6 +314,11 @@ func (c *MCQ_entry) GetJustifiedFlag(e *Exercice) (*FlagKey, error) {
|
|||
return e.GetFlagKeyByLabel(fmt.Sprintf("\\%%%d\\%%%%", c.Id))
|
||||
}
|
||||
|
||||
// IsOptionnal to know if the flag can be omitted when validating the step.
|
||||
func (m *MCQ) IsOptionnal() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if the given vals are the expected ones to validate this flag.
|
||||
func (m *MCQ) Check(v interface{}) int {
|
||||
var vals map[int]bool
|
||||
|
|
|
@ -32,6 +32,7 @@ func exoptsQuery(whereExo string) string {
|
|||
SELECT id_team, id_exercice, MIN(time) AS time, ` + fmt.Sprintf("%f", FirstBlood) + ` AS coeff, "First blood" AS reason FROM exercice_solved GROUP BY id_exercice UNION
|
||||
SELECT id_team, id_exercice, time, coefficient AS coeff, "Validation" AS reason FROM exercice_solved
|
||||
) S INNER JOIN exercices E ON S.id_exercice = E.id_exercice ` + whereExo + ` UNION ALL
|
||||
SELECT B.id_team, B.time, F.bonus_gain AS points, 1 AS coeff, "Bonus flag" AS reason, F.id_exercice FROM flag_found B INNER JOIN exercice_flags F ON F.id_flag = B.id_flag WHERE F.bonus_gain != 0 HAVING points != 0 UNION ALL
|
||||
SELECT id_team, MAX(time) AS time, (FLOOR(COUNT(*)/10 - 1) * (FLOOR(COUNT(*)/10)))/0.2 + (FLOOR(COUNT(*)/10) * (COUNT(*)%10)) AS points, ` + fmt.Sprintf("%f", SubmissionCostBase*-1) + ` AS coeff, "Tries" AS reason, id_exercice FROM ` + tries_table + ` S ` + whereExo + ` GROUP BY id_exercice, id_team`
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ type myTeamFlag struct {
|
|||
PSolved *time.Time `json:"part_solved,omitempty"`
|
||||
Soluce string `json:"soluce,omitempty"`
|
||||
Justify bool `json:"justify,omitempty"`
|
||||
BonusGain int64 `json:"bonus_gain,omitempty"`
|
||||
Choices map[string]interface{} `json:"choices,omitempty"`
|
||||
ChoicesCost int64 `json:"choices_cost,omitempty"`
|
||||
Variant string `json:"variant,omitempty"`
|
||||
|
@ -275,6 +276,7 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
|
|||
}
|
||||
|
||||
flag.Multiline = k.Multiline
|
||||
flag.BonusGain = int64(float64(k.BonusGain) * GlobalScoreCoefficient)
|
||||
|
||||
var fl FlagMCQLabel
|
||||
if fl, err = k.GetMCQJustification(); err == nil {
|
||||
|
|
Reference in a new issue