You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
2.8 KiB
103 lines
2.8 KiB
package level |
|
|
|
import ( |
|
"encoding/json" |
|
"fmt" |
|
"os" |
|
) |
|
|
|
type Level struct { |
|
ID string `json:"id"` |
|
Name string `json:"name"` |
|
Description string `json:"description"` |
|
Difficulty Difficulty `json:"difficulty"` |
|
|
|
TargetRPS int `json:"targetRps"` |
|
DurationSec int `json:"durationSec"` |
|
MaxMonthlyUSD int `json:"maxMonthlyUsd"` |
|
MaxP95LatencyMs int `json:"maxP95LatencyMs"` |
|
RequiredAvailabilityPct float64 `json:"requiredAvailabilityPct"` |
|
|
|
MustInclude []string `json:"mustInclude,omitempty"` |
|
MustNotInclude []string `json:"mustNotInclude,omitempty"` |
|
EncouragedComponents []string `json:"encouragedComponents,omitempty"` |
|
DiscouragedComponents []string `json:"discouragedComponents,omitempty"` |
|
MinReplicas map[string]int `json:"minReplicas,omitempty"` |
|
MaxLatencyPerNodeType map[string]int `json:"maxLatencyPerNodeType,omitempty"` |
|
CustomValidators []string `json:"customValidators,omitempty"` |
|
|
|
FailureEvents []FailureEvent `json:"failureEvents,omitempty"` |
|
ScoringWeights map[string]float64 `json:"scoringWeights,omitempty"` |
|
|
|
Hints []string `json:"hints,omitempty"` |
|
} |
|
|
|
type Difficulty string |
|
|
|
const ( |
|
DifficultyEasy Difficulty = "easy" |
|
DifficultyMedium Difficulty = "medium" |
|
DifficultyHard Difficulty = "hard" |
|
) |
|
|
|
var Registry map[string]map[string]Level |
|
|
|
type FailureEvent struct { |
|
Type string `json:"type"` |
|
TimeSec int `json:"timeSec"` |
|
TargetID string `json:"targetId,omitempty"` |
|
} |
|
|
|
func LoadLevels(path string) ([]Level, error) { |
|
data, err := os.ReadFile(path) |
|
if err != nil { |
|
return nil, fmt.Errorf("Error opening levels.json: %w", err) |
|
} |
|
|
|
var levels []Level |
|
if err := json.Unmarshal(data, &levels); err != nil { |
|
return nil, fmt.Errorf("Error parsing levels.json: %w", err) |
|
} |
|
|
|
return levels, nil |
|
} |
|
|
|
func InitRegistry(levels []Level) { |
|
Registry = make(map[string]map[string]Level) |
|
for _, lvl := range levels { |
|
// check if level already exists here |
|
if _, ok := Registry[lvl.Name]; !ok { |
|
Registry[lvl.Name] = make(map[string]Level) |
|
} |
|
// populate it |
|
Registry[lvl.Name][string(lvl.Difficulty)] = lvl |
|
} |
|
} |
|
|
|
func GetLevel(name string, difficulty Difficulty) (*Level, error) { |
|
diffMap, ok := Registry[name] |
|
if !ok { |
|
return nil, fmt.Errorf("level name %s not found", name) |
|
} |
|
|
|
lvl, ok := diffMap[string(difficulty)] |
|
if !ok { |
|
return nil, fmt.Errorf("difficulty %s not available for level '%s'", difficulty, name) |
|
} |
|
return &lvl, nil |
|
} |
|
|
|
func (d *Difficulty) UnmarshalJSON(b []byte) error { |
|
var s string |
|
if err := json.Unmarshal(b, &s); err != nil { |
|
return err |
|
} |
|
|
|
switch s { |
|
case string(DifficultyEasy), string(DifficultyMedium), string(DifficultyHard): |
|
*d = Difficulty(s) |
|
return nil |
|
default: |
|
return fmt.Errorf("invalid difficulty: %q", s) |
|
} |
|
}
|
|
|