import re class LicenseValidator: def __init__(self, license_id: str): self.license_id = license_id.upper() # Ensure uppercase for consistency @property def stripped_license(self) -> str: # Remove leading zero if present and match only the numeric part license_without_leading_zero = self.license_id.lstrip("0") match = re.match(r"^[0-9]{6,8}", license_without_leading_zero) if match: return match.group(0) return 'licence invalide' @property def computed_licence_id(self) -> str: return f"{self.stripped_license}{self.computed_license_key}".upper() @property def computed_license_key(self) -> str: stripped = self.stripped_license key = LicenseValidator.get_computed_license_key(stripped) if key: return key return 'aucune clé de licence' @staticmethod def get_computed_license_key(stripped): if stripped and stripped.isdigit(): int_value = int(stripped) value = (int_value - 1) % 23 char_code = ord('A') + value # Adjust for letters to skip: I, O, Q if char_code >= ord('I'): char_code += 1 if char_code >= ord('O'): char_code += 1 if char_code >= ord('Q'): char_code += 1 return chr(char_code) return None def validate_license(self) -> bool: if not self.license_id or len(self.license_id) < 7: return False # Invalid length for a license ID # Separate the numeric part and the letter numeric_part = self.license_id[:-1] given_letter = self.license_id[-1] # Verify that the last character matches the computed license key return self.computed_licence_id == numeric_part + given_letter.upper()