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
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
|