jollheef / henhouse

Scoreboard for jeopardy-style CTFs
GNU Affero General Public License v3.0
9 stars 5 forks source link

Не описана формула пересчёта очков #13

Closed DEIGHD closed 7 years ago

DEIGHD commented 7 years ago

Нет описания формулы пересчёта очков для заданий.

jollheef commented 7 years ago

А что тебе из кода не понятно?

DEIGHD commented 7 years ago

Так? https://imgur.com/lo5H8CR

jollheef commented 7 years ago

Влияет этот участок конфигурационного файла:

[TaskPrice]
# use non linear function for calculate teams base
use_non_linear = false
# for correct work with small amount of teams
use_teams_base = false
teams_base = 20
# 500 if percent of solve less than value
p500 = 10
p400 = 15
p300 = 30
# 200 if percent of solve less than value
p200 = 50
# other 100

Само значения ценности таска вычисляется:

func (g *Game) taskPrice(database *sql.DB, taskID int) (price int, err error) {

    count, err := db.GetSolvedCount(database, taskID)

    fprice := float64(count) / g.TaskPrice.TeamsBase

    if fprice <= g.TaskPrice.P500 {
        price = 500
    } else if fprice <= g.TaskPrice.P400 {
        price = 400
    } else if fprice <= g.TaskPrice.P300 {
        price = 300
    } else if fprice <= g.TaskPrice.P200 {
        price = 200
    } else {
        price = 100
    }

    return
}

Базовое значение количества команд равно либо количеству команд, либо заданному значению teams_base при use_teams_base = true в конфигурационном файле, либо в случае use_non_linear = true:

func CalcTeamsBase(database *sql.DB) (z float64, err error) {

    teams, err := db.GetTeams(database)
    if err != nil {
        return
    }

    flags, err := db.GetFlags(database)
    if err != nil {
        return
    }

    k := []int{}
    for _, t := range teams {
        solvedCount := 0
        for _, f := range flags {
            if f.TeamID == t.ID {
                solvedCount++
            }
        }
        k = append(k, solvedCount)
    }

    max := 1
    for _, ki := range k {
        if ki > max {
            max = ki
        }
    }

    for _, ki := range k {
        z += math.Sqrt(float64(ki) / float64(max))
    }

    if z < 21 {
        z = 21
    }

    return
}