LimmeDev's picture
Initial MANIFOLD upload - CS2 cheat detection training
454ecdd verified
from __future__ import annotations
import numpy as np
from dataclasses import dataclass, field
from typing import Optional, Dict, Any, Tuple
from enum import Enum
# Skill correlation matrix - represents realistic correlations between player skills
# Rows/cols: raw_aim, spray_control, crosshair_placement, reaction_speed, game_sense, movement, consistency, mental_resilience
SKILL_CORRELATION_MATRIX = np.array([
# aim spray cross react sense move cons mental
[1.00, 0.70, 0.50, 0.30, 0.20, 0.40, 0.30, 0.10], # raw_aim
[0.70, 1.00, 0.40, 0.20, 0.30, 0.30, 0.40, 0.10], # spray_control
[0.50, 0.40, 1.00, 0.20, 0.60, 0.50, 0.50, 0.20], # crosshair_placement
[0.30, 0.20, 0.20, 1.00, 0.30, 0.40, 0.20, 0.30], # reaction_speed
[0.20, 0.30, 0.60, 0.30, 1.00, 0.50, 0.40, 0.40], # game_sense
[0.40, 0.30, 0.50, 0.40, 0.50, 1.00, 0.30, 0.20], # movement
[0.30, 0.40, 0.50, 0.20, 0.40, 0.30, 1.00, 0.50], # consistency
[0.10, 0.10, 0.20, 0.30, 0.40, 0.20, 0.50, 1.00], # mental_resilience
])
SKILL_STD = np.array([15.0, 15.0, 15.0, 12.0, 15.0, 12.0, 18.0, 20.0])
SKILL_NAMES = ["raw_aim", "spray_control", "crosshair_placement", "reaction_speed",
"game_sense", "movement", "consistency", "mental_resilience"]
class Rank(Enum):
SILVER = "silver"
GOLD_NOVA = "gold_nova"
MASTER_GUARDIAN = "master_guardian"
LEGENDARY_EAGLE = "legendary_eagle"
SUPREME_GLOBAL = "supreme_global"
PRO = "pro"
RANK_STATISTICS = {
Rank.SILVER: {
"skill_mean": 25.0,
"hs_percent": (0.25, 0.35),
"accuracy": (0.06, 0.08),
"reaction_time_ms": (280.0, 350.0),
"kd_ratio": (0.5, 0.85),
"adr": (35.0, 55.0),
"edpi": (1200, 2400),
"hours_played": (0, 300),
},
Rank.GOLD_NOVA: {
"skill_mean": 40.0,
"hs_percent": (0.35, 0.42),
"accuracy": (0.08, 0.10),
"reaction_time_ms": (250.0, 290.0),
"kd_ratio": (0.85, 1.1),
"adr": (50.0, 70.0),
"edpi": (1000, 1800),
"hours_played": (200, 600),
},
Rank.MASTER_GUARDIAN: {
"skill_mean": 55.0,
"hs_percent": (0.40, 0.48),
"accuracy": (0.10, 0.12),
"reaction_time_ms": (220.0, 260.0),
"kd_ratio": (1.0, 1.2),
"adr": (60.0, 80.0),
"edpi": (800, 1400),
"hours_played": (400, 1200),
},
Rank.LEGENDARY_EAGLE: {
"skill_mean": 70.0,
"hs_percent": (0.45, 0.52),
"accuracy": (0.12, 0.14),
"reaction_time_ms": (200.0, 240.0),
"kd_ratio": (1.15, 1.35),
"adr": (70.0, 90.0),
"edpi": (700, 1200),
"hours_played": (800, 2000),
},
Rank.SUPREME_GLOBAL: {
"skill_mean": 82.0,
"hs_percent": (0.48, 0.55),
"accuracy": (0.14, 0.16),
"reaction_time_ms": (180.0, 220.0),
"kd_ratio": (1.25, 1.5),
"adr": (75.0, 95.0),
"edpi": (600, 1100),
"hours_played": (1200, 3500),
},
Rank.PRO: {
"skill_mean": 92.0,
"hs_percent": (0.55, 0.66),
"accuracy": (0.17, 0.20),
"reaction_time_ms": (140.0, 180.0),
"kd_ratio": (1.3, 2.0),
"adr": (85.0, 110.0),
"edpi": (550, 1000),
"hours_played": (3000, 10000),
},
}
@dataclass
class SkillVector:
"""8-dimensional skill vector with realistic correlations."""
raw_aim: float
spray_control: float
crosshair_placement: float
reaction_speed: float
game_sense: float
movement: float
consistency: float
mental_resilience: float
def to_array(self) -> np.ndarray:
return np.array([
self.raw_aim, self.spray_control, self.crosshair_placement,
self.reaction_speed, self.game_sense, self.movement,
self.consistency, self.mental_resilience
])
@classmethod
def from_array(cls, arr: np.ndarray) -> SkillVector:
return cls(*arr.tolist())
@property
def mean_skill(self) -> float:
return float(self.to_array().mean())
def generate_correlated_skills(
rank: Rank,
rng: Optional[np.random.Generator] = None
) -> np.ndarray:
"""Generate correlated skill vector using Cholesky decomposition."""
if rng is None:
rng = np.random.default_rng()
stats = RANK_STATISTICS[rank]
skill_mean = stats["skill_mean"]
# Create covariance matrix from correlation and std
cov = np.outer(SKILL_STD, SKILL_STD) * SKILL_CORRELATION_MATRIX
# Cholesky decomposition for correlated sampling
L = np.linalg.cholesky(cov)
# Generate uncorrelated standard normal
z = rng.standard_normal(8)
# Transform to correlated with correct mean/cov
skills = skill_mean + L @ z
# Clip to valid range [0, 100]
skills = np.clip(skills, 0.0, 100.0)
return skills
@dataclass
class PlayerProfile:
"""Complete player profile with skill and metadata."""
profile_id: str
rank: Rank
skill_vector: SkillVector
hours_played: int
is_cheater: bool = False
@classmethod
def generate(
cls,
rank: str | Rank,
seed: Optional[int] = None,
profile_id: Optional[str] = None,
) -> PlayerProfile:
"""Generate a random player profile for given rank."""
if isinstance(rank, str):
rank = Rank(rank)
rng = np.random.default_rng(seed)
# Generate correlated skills
skills = generate_correlated_skills(rank, rng)
skill_vector = SkillVector.from_array(skills)
# Generate hours played
stats = RANK_STATISTICS[rank]
hours_low, hours_high = stats["hours_played"]
hours_played = int(rng.uniform(hours_low, hours_high))
# Generate profile ID if not provided
if profile_id is None:
profile_id = f"player_{rng.integers(0, 2**32):08x}"
return cls(
profile_id=profile_id,
rank=rank,
skill_vector=skill_vector,
hours_played=hours_played,
is_cheater=False,
)
def get_expected_stats(self) -> Dict[str, Tuple[float, float]]:
"""Get expected stat ranges based on rank and skill."""
return RANK_STATISTICS[self.rank].copy()