#!/usr/bin/env python from dataclasses import dataclass, field from typing import ClassVar @dataclass class Counter(): top: int value: int @dataclass class Minter(): legalstring: ClassVar[str] = "0123456789bcdfghjkmnpqrstvwxz" alphacount: ClassVar[int] = len(legalstring) digitcount: ClassVar[int] = 10 oacounter: int = 0 oatop: int = 0 template: str = "" prefix: str = "" mask: str = "" active_counters: list[Counter] = field(default_factory=list) inactive_counters: list[Counter] = field(default_factory=list) def parse_template(self, template: str) -> int: """ >>> m = Minter() >>> m.parse_template("test") -1 >>> m.template 'test' >>> m.prefix '' >>> m.mask 'test' >>> m.parse_template("testkktest") -1 >>> m.parse_template("rtesk") -1 >>> m.parse_template("rteksk") -1 >>> m.parse_template("rtkkes") -1 >>> m.parse_template("reded") 84100 >>> m.parse_template("ed") -1 >>> m.parse_template("red") 290 >>> m.parse_template("redk") 290 """ self.template = template template = template.strip().removesuffix('/').strip() try: self.prefix, *_, self.mask = template.split(".") except ValueError: self.prefix = "" self.mask = template if self.mask[0] not in ("r", "s", "z"): return -1 # mask must begin with of the letters: r, s or z if "k" in self.mask and (self.mask.count("k") > 1 or self.mask[-1] != "k"): return -1 if not all(char in ("d", "e") for char in self.mask.rstrip("k")[1:]): return -1 self.oatop = 1 for chr in self.mask: match chr: case "e": self.oatop *= self.alphacount case "d": self.oatop *= self.digitcount return self.oatop def genid(self) -> str: # 1. Check if the oacounter >= oatop # -> noid are exhausted # -> At this time, all our noid are considered as longterm # -> At this tile, all our noid are not sequential, thus random # 2. Get the size of saclist (active counters list) # 3. if that size is less than 1 then no more active counters then no noid # 4. pick at random an active counter # - rand → int (index to use) # 5. get its value # 6. increment its value # 7. increment oacounter # 8. deal with an exhausted subcounter # - if new value is more more or equal to the top value of this counter # - remove this counter from the saclist # - add this counter to the siclist # 9. Generate the noid with a call to n2xdig() # - Arguments # - value + (index * percounter) # - mask # 10. return the noid return "" def initcounters() -> None: # 1. Initialize oacounter to 0 # 2. Set up a maxcounters variable to 293 # 3. Set up a percounter variable to int(total / maxcounters + 1) # 4. Divides $total into sub-counters of size $pctr, stores this # distribution in $noid, and prepares the structure to generate # IDs in a balanced manner. # - copy the value of total to the variable t # - copy the value of percounter to pctr # - initialize saclist as an empty string (list) # - while t is more than zero # - set up the top value for the counter # `$t >= $pctr ? $pctr : $t` # - set value of this counter to 0 # - add the counter to saclist # - substract pctr from t pass if __name__ == "__main__": import doctest doctest.testmod()