package mining import ( "context" "math/rand" "sync" "time" ) // MockMiner simulates hashrate when real miner binaries are unavailable. type MockMiner struct { mu sync.Mutex baseHps float64 running bool cancel context.CancelFunc lastHps float64 tierLabel string } func NewMockMiner(tierLabel string, baseHps float64) *MockMiner { if baseHps <= 0 { baseHps = 1500 + rand.Float64()*500 } return &MockMiner{tierLabel: tierLabel, baseHps: baseHps} } func (m *MockMiner) Start(ctx context.Context) error { m.mu.Lock() defer m.mu.Unlock() if m.running { return nil } runCtx, cancel := context.WithCancel(ctx) m.cancel = cancel m.running = true m.lastHps = m.baseHps go m.loop(runCtx) return nil } func (m *MockMiner) loop(ctx context.Context) { ticker := time.NewTicker(2 * time.Second) defer ticker.Stop() for { select { case <-ctx.Done(): m.mu.Lock() m.running = false m.lastHps = 0 m.mu.Unlock() return case <-ticker.C: jitter := 0.85 + rand.Float64()*0.3 m.mu.Lock() m.lastHps = m.baseHps * jitter m.mu.Unlock() } } } func (m *MockMiner) Stop() { m.mu.Lock() cancel := m.cancel m.mu.Unlock() if cancel != nil { cancel() } } func (m *MockMiner) HashrateHps() float64 { m.mu.Lock() defer m.mu.Unlock() return m.lastHps } func (m *MockMiner) Simulated() bool { return true }