File size: 1,882 Bytes
569c142
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
"""Deterministic graders for the three tasks. All return a reward in [0.0, 1.0]."""
from __future__ import annotations

from typing import Dict

from disk_panic.server.vfs import VFS
from disk_panic.server.scenarios import _audit_sha


def grade_easy(vfs: VFS, targets: Dict[str, object]) -> float:
    """Reward = smoothly interpolated disk-free fraction."""
    pct = vfs.usage_pct()
    if pct <= 60:
        disk_score = 1.0
    elif pct >= 99:
        disk_score = 0.0
    else:
        disk_score = max(0.0, (99 - pct) / 39)
    audit_ok = _audit_sha(vfs) == targets["audit_sha"]
    # If audit got touched, cap score at 0.5.
    return min(disk_score, 0.5) if not audit_ok else disk_score


def grade_medium(vfs: VFS, targets: Dict[str, object]) -> float:
    pct = vfs.usage_pct()
    disk = 1.0 if pct < 80 else max(0.0, (99 - pct) / 19)
    svc = 1.0 if vfs.services.get("app") == "active" else 0.0
    audit = 1.0 if _audit_sha(vfs) == targets["audit_sha"] else 0.0
    score = 0.4 * disk + 0.4 * svc + 0.2 * audit
    return round(score, 4)


def grade_hard(vfs: VFS, targets: Dict[str, object]) -> float:
    pct = vfs.usage_pct()
    disk = 1.0 if pct < 80 else max(0.0, (99 - pct) / 19)
    svc = 1.0 if vfs.services.get("app") == "active" else 0.0
    audit = 1.0 if _audit_sha(vfs) == targets["audit_sha"] else 0.0
    lr_path = targets.get("logrotate_path", "/etc/logrotate.d/app")
    logrotate = 0.0
    if isinstance(lr_path, str) and lr_path in vfs.files:
        content = vfs.files[lr_path].content.decode("utf-8", errors="ignore")
        if "rotate" in content and "size" in content:
            logrotate = 1.0
        elif content.strip():
            logrotate = 0.5
    score = 0.3 * disk + 0.3 * svc + 0.2 * audit + 0.2 * logrotate
    return round(score, 4)


GRADERS = {
    "easy": grade_easy,
    "medium": grade_medium,
    "hard": grade_hard,
}