45 lines
1.8 KiB
Python
45 lines
1.8 KiB
Python
from typing import ClassVar
|
|
from pydantic import BaseModel, model_validator
|
|
from src.models import KeypadSize
|
|
from src.utils import generate_random_nonrepeating_list
|
|
|
|
|
|
class CustomerAttributes(BaseModel):
|
|
attr_vals: list[int]
|
|
set_vals: list[int]
|
|
keypad_size: KeypadSize
|
|
MAX_KEYS: ClassVar[int] = 256
|
|
MAX_ATTRS_PER_KEY: ClassVar[int] = 256
|
|
|
|
@model_validator(mode='after')
|
|
def check_keys_vs_attrs(self) -> 'CustomerAttributes':
|
|
if self.keypad_size.is_dispersable:
|
|
raise ValueError("number of keys must be less than the number of "
|
|
"attributes per key to be dispersion resistant")
|
|
return self
|
|
|
|
@classmethod
|
|
def create(cls, keypad_size: KeypadSize) -> 'CustomerAttributes':
|
|
if keypad_size.numb_of_keys > cls.MAX_KEYS or keypad_size.attrs_per_key > cls.MAX_ATTRS_PER_KEY:
|
|
raise ValueError(f"Keys and attributes per key must not exceed {cls.MAX_KEYS}")
|
|
return cls(
|
|
attr_vals=generate_random_nonrepeating_list(keypad_size.numb_of_attrs),
|
|
set_vals=generate_random_nonrepeating_list(keypad_size.attrs_per_key),
|
|
keypad_size=keypad_size,
|
|
)
|
|
|
|
def renew(self):
|
|
self.attr_vals = generate_random_nonrepeating_list(self.keypad_size.numb_of_attrs)
|
|
self.set_vals = generate_random_nonrepeating_list(self.keypad_size.attrs_per_key)
|
|
|
|
def get_attr_set_val(self, attr: int) -> int:
|
|
assert (attr in self.attr_vals)
|
|
attr_idx = self.attr_vals.index(attr)
|
|
set_idx = attr_idx % self.keypad_size.attrs_per_key
|
|
return self.set_vals[set_idx]
|
|
|
|
def get_set_index(self, set_val: int) -> int:
|
|
if set_val not in self.set_vals:
|
|
raise ValueError(f"Set value {set_val} not found in set values")
|
|
return self.set_vals.index(set_val)
|