You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
1.9 KiB

6 months ago
import re
from string import ascii_uppercase
from .. import BaseProvider, ElementsType
localized = True
def calculate_vin_str_weight(s: str, weight_factor: list) -> int:
"""
multiply s(str) by weight_factor char by char
e.g.
input: s="ABCDE", weight_factor=[1, 2, 3, 4, 5]
return: A*1 + B*2 + C*3 + D*4 + E*5
will multiply 0 when len(weight_factor) less than len(s)
"""
def _get_char_weight(c: str) -> int:
"""A=1, B=2, ...., I=9,
J=1, K=2, ..., R=9,
S=2, T=3, ..., Z=9
"""
if ord(c) <= 64: # 0-9
return int(c)
if ord(c) <= 73: # A-I
return ord(c) - 64
if ord(c) <= 82: # J-R
return ord(c) - 73
# S-Z
return ord(c) - 81
res = 0
for i, c in enumerate(s):
res += _get_char_weight(c) * weight_factor[i] if i < len(weight_factor) else 0
return res
class Provider(BaseProvider):
"""Implement default automotive provider for Faker."""
license_formats: ElementsType = ()
def license_plate(self) -> str:
"""Generate a license plate."""
temp = re.sub(
r"\?",
lambda x: self.random_element(ascii_uppercase),
self.random_element(self.license_formats),
)
return self.numerify(temp)
def vin(self) -> str:
"""Generate vin number."""
vin_chars = "1234567890ABCDEFGHJKLMNPRSTUVWXYZ" # I, O, Q are restricted
front_part = self.bothify("????????", letters=vin_chars)
rear_part = self.bothify("????????", letters=vin_chars)
front_part_weight = calculate_vin_str_weight(front_part, [8, 7, 6, 5, 4, 3, 2, 10])
rear_part_weight = calculate_vin_str_weight(rear_part, [9, 8, 7, 6, 5, 4, 3, 2])
checksum = (front_part_weight + rear_part_weight) % 11
checksum_char = "X" if checksum == 10 else str(checksum)
return front_part + checksum_char + rear_part