module FFaker::Vehicle::VIN
def vin
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