# Stateless hierarchical scopes, with explicitly local random streams.
import hashlib
import json
import random
from dataclasses import dataclass


@dataclass(frozen=True)
class Scope:
    seed: int
    key: tuple[str, ...] = ()

    def child(self, key: str, override: int | None = None):
        return Scope(self.seed, self.key + (key,)) if override is None else Scope(override, (key,))

    def stream(self, purpose: str = 'plan') -> random.Random:
        payload = json.dumps([self.seed, self.key, purpose], separators=(',', ':')).encode()
        return random.Random(int.from_bytes(hashlib.sha256(payload).digest(), 'big'))

    def choose(self, values, purpose='plan'):
        return self.stream(purpose).choice(tuple(values))
