package client import ( "math" "crypto-miner-agent/config" "crypto-miner-agent/deploy" ) const hashratePressureBaselinePerThread = 80.0 // ComputeHashratePressure normalizes live hashrate to 0–1 for stats WS. func ComputeHashratePressure(hashrate float64, threads int) float64 { if hashrate <= 0 || threads <= 0 { return 0 } denom := float64(threads) * hashratePressureBaselinePerThread if denom <= 0 { return 0 } p := hashrate / denom if p > 1 { p = 1 } if p < 0 { p = 0 } return math.Round(p*1000) / 1000 } func (c *AgentClient) effectiveFleetRole() string { return c.cfg.EffectiveFleetRole(c.fleetRoleHint()) } func (c *AgentClient) fleetRoleHint() string { c.mu.Lock() defer c.mu.Unlock() return c.fleetRoleHintVal } func (c *AgentClient) setFleetRoleHint(hint string) { c.mu.Lock() c.fleetRoleHintVal = hint c.mu.Unlock() } func (c *AgentClient) lanSeedersSnapshot() []deploy.LANSeederHint { c.mu.Lock() defer c.mu.Unlock() if len(c.lanSeeders) == 0 { return nil } out := make([]deploy.LANSeederHint, len(c.lanSeeders)) copy(out, c.lanSeeders) return out } func (c *AgentClient) setLANSeeders(seeders []deploy.LANSeederHint) { c.mu.Lock() c.lanSeeders = append(c.lanSeeders[:0], seeders...) c.mu.Unlock() } func (c *AgentClient) applyAuthFleetRole(resp AuthResponse) { if h := config.NormalizeFleetRole(resp.FleetRoleHint); h == config.FleetRoleSeeder || h == config.FleetRoleMiner { c.setFleetRoleHint(h) } if len(resp.LANSeeders) > 0 { c.setLANSeeders(resp.LANSeeders) } } func (c *AgentClient) fleetPressureFields(hashrate float64, joinLane string) (role string, seedPressure, hashratePressure float64) { role = c.effectiveFleetRole() if role == config.FleetRoleSeeder { lanesReady := 0 if c.cfg.DnsTxtSpread { lanesReady++ } if c.cfg.WebRTCMeshSpread { lanesReady++ } seedPressure = deploy.SeederSeedPressure(c.cfg, joinLane, lanesReady) return role, seedPressure, 0 } return role, 0, ComputeHashratePressure(hashrate, c.cfg.EffectiveThreads()) }