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.
 
 
 
 

119 lines
3.3 KiB

package level
import (
"encoding/json"
"fmt"
"os"
"strings"
)
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"`
InterviewerRequirements []string `json:"interviewerRequirements,omitempty"`
FunctionalRequirements []string `json:"functionalRequirements,omitempty"`
NonFunctionalRequirements []string `json:"nonFunctionalRequirements,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
normalized := strings.ToLower(lvl.Name)
if _, ok := Registry[normalized]; !ok {
Registry[normalized] = make(map[string]Level)
}
// populate it
Registry[normalized][string(lvl.Difficulty)] = lvl
}
}
func GetLevel(name string, difficulty Difficulty) (*Level, error) {
name = strings.ToLower(name)
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)
}
}
func AllLevels() []Level {
var levels []Level
for _, diffMap := range Registry {
for _, lvl := range diffMap {
levels = append(levels, lvl)
}
}
return levels
}