module FFaker::Vehicle::VIN

def vin

I, O and Q are NOT allowed. VIN_VALID_ALPHA has valid alpha characters.

12-17 Serial number (digits only)
11 Plant of manufacture (alpha and digits)
10 Year (see VIN_VALID_YEARS)
9 Check Digit (0-9 or "X")
4-8 Vehicle Description ("For passenger cars ..[position 7].. shall be alphabetic")
1-3 Manufacturer ID aka WMI (alpha and digits)
Position Meaning

https://www.govinfo.gov/content/pkg/CFR-2019-title49-vol6/xml/CFR-2019-title49-vol6-part565.xml#seqnum565.15
Generate a VIN that is compliant with specifications of US Title 49 Section 565.15
def vin
  generated_vin = [
    # Manufacturer ID / WMI
    fetch_sample(VALID_WMI_REGIONS),
    fetch_sample(VALID_ALPHANUMERIC, count: 2),
    # Vehicle Description
    fetch_sample(VALID_ALPHANUMERIC, count: 3),
    fetch_sample(VALID_ALPHA),
    fetch_sample(VALID_ALPHANUMERIC),
    '0', # check digit placeholder
    fetch_sample(VALID_YEAR_CHARS), # Year of Manufacture
    fetch_sample(VALID_ALPHANUMERIC), # Plant ID
    FFaker.numerify('######') # Serial Number
  ].join
  # Calculate the Check Digit
  weighted_sum = generated_vin.chars.each_with_index.sum do |char, idx|
    (TRANSLITERATION_VALUES[char.to_sym] || char).to_i * POSITION_WEIGHTS[idx]
  end
  check_digit = weighted_sum % 11
  check_digit = 'X' if check_digit == 10
  generated_vin[8] = check_digit.to_s
  generated_vin
end