Advertisement
Hellerick_Ferlibay

New Russian vehicle registration plate generator

Nov 24th, 2016
303
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.69 KB | None | 0 0
  1. from xml.etree import ElementTree
  2. import os, re
  3.  
  4. # Kept here: http://pastebin.com/TRCR5Y1k
  5.  
  6. template_path = '/home/hellerick/Dropbox/License plates/Template.svg'
  7. letters = 'ABEKMHOPCTYX'
  8. digits = '0123456789'
  9.  
  10. total = 12*12*9999*12*12 # =207339264
  11. offset = 128142713
  12. magic = 43514825
  13.  
  14. regions = {
  15.     'резервная серия'       : {'code': 0, 'zones':range(  0,100)},
  16.     'Республика Адыгея'     : {'code': 1, 'zones':range(100,103)},
  17.     'Республика Алтай'      : {'code': 4, 'zones':range(103,105)},
  18.     'Республика '
  19.         'Башкортостан'      : {'code': 2, 'zones':range(105,129)},
  20.     'Республика Бурятия'    : {'code': 3, 'zones':range(129,135)},
  21.     'Республика Дагестан'   : {'code': 5, 'zones':range(135,153)},
  22.     'Республика Ингушетия'  : {'code': 6, 'zones':range(153,156)},
  23.     'Кабардино-Балкарская '
  24.         'Республика'        : {'code': 7, 'zones':range(156,162)},
  25.     'Республика Калмыкия'   : {'code': 8, 'zones':range(162,164)},
  26.     'Республика Карачаево-'
  27.         'Черкесия'          : {'code': 9, 'zones':range(164,167)},
  28.     'Республика Карелия'    : {'code':10, 'zones':range(167,171)},
  29.     'Республика Коми'       : {'code':11, 'zones':range(171,177)},
  30.     'Республика Крым'       : {'code':82, 'zones':range(177,189)},
  31.     'Республика Марий Эл'   : {'code':12, 'zones':range(189,194)},
  32.     'Республика Мордовия'   : {'code':13, 'zones':range(194,199)},
  33.     'Республика Саха '
  34.         '(Якутия)'          : {'code':14, 'zones':range(199,205)},
  35.     'Республика Северная '
  36.     'Осетия — Алания'       : {'code':15, 'zones':range(205,210)},
  37.     'Республика Татарстан'  : {'code':16, 'zones':range(210,233)},
  38.     'Республика Тыва'       : {'code':17, 'zones':range(233,235)},
  39.     'Удмуртская Республика' : {'code':18, 'zones':range(235,244)},
  40.     'Республика Хакасия'    : {'code':19, 'zones':range(244,248)},
  41.     'Чеченская республика'  : {'code':20, 'zones':range(248,256)},
  42.     'Чувашская Республика'  : {'code':21, 'zones':range(256,264)},
  43.     'Алтайский край'        : {'code':22, 'zones':range(264,279)},
  44.     'Забайкальский край'    : {'code':75, 'zones':range(279,286)},
  45.     'Камчатский край'       : {'code':41, 'zones':range(286,288)},
  46.     'Краснодарский край'    : {'code':23, 'zones':range(288,320)},
  47.     'Красноярский край'     : {'code':24, 'zones':range(320,337)},
  48.     'Пермский край'         : {'code':59, 'zones':range(337,353)},
  49.     'Приморский край'       : {'code':25, 'zones':range(353,365)},
  50.     'Ставропольский край'   : {'code':26, 'zones':range(365,382)},
  51.     'Хабаровский край'      : {'code':27, 'zones':range(382,390)},
  52.     'Амурская область'      : {'code':28, 'zones':range(390,395)},
  53.     'Архангельская область' : {'code':29, 'zones':range(395,402)},
  54.     'Астраханская область'  : {'code':30, 'zones':range(402,408)},
  55.     'Белгородская область'  : {'code':31, 'zones':range(408,418)},
  56.     'Брянская область'      : {'code':32, 'zones':range(418,426)},
  57.     'Владимирская область'  : {'code':33, 'zones':range(426,435)},
  58.     'Волгоградская область' : {'code':34, 'zones':range(435,451)},
  59.     'Вологодская область'   : {'code':35, 'zones':range(451,459)},
  60.     'Воронежская область'   : {'code':36, 'zones':range(459,473)},
  61.     'Ивановская область'    : {'code':37, 'zones':range(473,480)},
  62.     'Иркутская область'     : {'code':38, 'zones':range(480,495)},
  63.     'Калининградская '
  64.         'область'           : {'code':39, 'zones':range(495,501)},
  65.     'Калужская область'     : {'code':40, 'zones':range(501,507)},
  66.     'Кемеровская область'   : {'code':42, 'zones':range(507,524)},
  67.     'Кировская область'     : {'code':43, 'zones':range(524,532)},
  68.     'Костромская область'   : {'code':44, 'zones':range(532,536)},
  69.     'Курганская область'    : {'code':45, 'zones':range(536,542)},
  70.     'Курская область'       : {'code':46, 'zones':range(542,549)},
  71.     'Ленинградская область' : {'code':47, 'zones':range(549,560)},
  72.     'Липецкая область'      : {'code':48, 'zones':range(560,567)},
  73.     'Магаданская область'   : {'code':49, 'zones':range(567,568)},
  74.     'Московская область'    : {'code':50, 'zones':range(568,610)},
  75.     'Мурманская область'    : {'code':51, 'zones':range(610,615)},
  76.     'Нижегородская область' : {'code':52, 'zones':range(615,635)},
  77.     'Новгородская область'  : {'code':53, 'zones':range(635,639)},
  78.     'Новосибирская область' : {'code':54, 'zones':range(639,656)},
  79.     'Омская область'        : {'code':55, 'zones':range(656,668)},
  80.     'Оренбургская область'  : {'code':56, 'zones':range(668,680)},
  81.     'Орловская область'     : {'code':57, 'zones':range(680,685)},
  82.     'Пензенская область'    : {'code':58, 'zones':range(685,694)},
  83.     'Псковская область'     : {'code':60, 'zones':range(694,698)},
  84.     'Ростовская область'    : {'code':61, 'zones':range(698,724)},
  85.     'Рязанская область'     : {'code':62, 'zones':range(724,731)},
  86.     'Самарская область'     : {'code':63, 'zones':range(731,750)},
  87.     'Саратовская область'   : {'code':64, 'zones':range(750,765)},
  88.     'Сахалинская область'   : {'code':65, 'zones':range(765,768)},
  89.     'Свердловская область'  : {'code':66, 'zones':range(768,794)},
  90.     'Смоленская область'    : {'code':67, 'zones':range(794,800)},
  91.     'Тамбовская область'    : {'code':68, 'zones':range(800,807)},
  92.     'Тверская область'      : {'code':69, 'zones':range(807,815)},
  93.     'Томская область'       : {'code':70, 'zones':range(815,822)},
  94.     'Тульская область'      : {'code':71, 'zones':range(822,832)},
  95.     'Тюменская область'     : {'code':72, 'zones':range(832,841)},
  96.     'Ульяновская область'   : {'code':73, 'zones':range(841,849)},
  97.     'Челябинская область'   : {'code':74, 'zones':range(849,870)},
  98.     'Ярославская область'   : {'code':76, 'zones':range(870,878)},
  99.     'Москва'                : {'code':77, 'zones':range(878,949)},
  100.     'Санкт-Петербург'       : {'code':78, 'zones':range(949,979)},
  101.     'Севастополь'           : {'code':92, 'zones':range(979,982)},
  102.     'Еврейская автономная '
  103.         'область'           : {'code':79, 'zones':range(982,984)},
  104.     'Ненецкий автономный '
  105.         'округ'             : {'code':83, 'zones':range(984,985)},
  106.     'Ханты-Мансийский '
  107.         'автономный округ '
  108.         '— Югра'            : {'code':86, 'zones':range(985,995)},
  109.     'Чукотский автономный '
  110.         'округ'             : {'code':87, 'zones':range(995,996)},
  111.     'Ямало-Ненецкий '
  112.         'автономный округ'  : {'code':89, 'zones':range(996,1000)},
  113.     }
  114.  
  115. colors = {
  116.     'W':'#ffffff',
  117.     'Y':'#ffcc00',
  118.     'K':'#000000',
  119.     'R':'#d40000',
  120.     'G':'#008000',
  121.     'B':'#0000d4',
  122.     }
  123.  
  124.  
  125. def generate_plate(plate_code):
  126.    
  127.     print('Generating the plate', plate_code)
  128.     inner_id, zone = unpack(plate_code)
  129.     print('Inner ID:', inner_id)
  130.     print('Zone:', zone)
  131.     region = [regions[r]['code'] for r in regions if zone in regions[r]['zones']][0]
  132.     region_name = [r for r in regions if region==regions[r]['code']][0]
  133.     print('Region code:', region, '('+region_name+')')
  134.     colorscheme = get_colorscheme(region)
  135.     print('Color scheme: {}/{} {}/{}'.format(*colorscheme)) # RPFONT, RPBG, IPFONT, IPBG
  136.  
  137.     ## https://docs.python.org/3/library/xml.etree.elementtree.html
  138.     ElementTree.register_namespace('dc','http://purl.org/dc/elements/1.1/')
  139.     ElementTree.register_namespace('cc','http://creativecommons.org/ns#')
  140.     ElementTree.register_namespace('rdf','http://www.w3.org/1999/02/22-rdf-syntax-ns#')
  141.     ElementTree.register_namespace('svg','http://www.w3.org/2000/svg')
  142.     ElementTree.register_namespace('','http://www.w3.org/2000/svg')
  143.     ElementTree.register_namespace('xlink','http://www.w3.org/1999/xlink')
  144.     ElementTree.register_namespace('sodipodi','http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd')
  145.     ElementTree.register_namespace('inkscape','http://www.inkscape.org/namespaces/inkscape')
  146.     doc = ElementTree.parse(template_path)
  147.     RPFONT = doc.find('.//*[@id="RPFONT"]')
  148.     RPBG = doc.find('.//*[@id="RPBG"]')
  149.     IPFONT = doc.find('.//*[@id="IPFONT"]')
  150.     IPBG = doc.find('.//*[@id="IPBG"]')
  151.  
  152.     RPFONT.attrib['style']=re.sub(r'fill:#[0-9a-f]{6}', r'fill:'+colors[colorscheme[0]], RPFONT.attrib['style'])
  153.     RPBG.attrib['style']=re.sub(r'fill:#[0-9a-f]{6}', r'fill:'+colors[colorscheme[1]], RPBG.attrib['style'])
  154.     IPFONT.attrib['style']=re.sub(r'fill:#[0-9a-f]{6}', r'fill:'+colors[colorscheme[2]], IPFONT.attrib['style'])
  155.     IPBG.attrib['style']=re.sub(r'fill:#[0-9a-f]{6}', r'fill:'+colors[colorscheme[3]], IPBG.attrib['style'])
  156.  
  157.     RP1 = doc.find('.//*[@id="RP1"]')
  158.     RP2 = doc.find('.//*[@id="RP2"]')
  159.  
  160.     for n,e in enumerate([RP1, RP2]):
  161.         e.attrib['{http://www.w3.org/1999/xlink}href'] = '#smallDigit'+'{:02d}'.format(region)[n]
  162.  
  163.     IP1 = doc.find('.//*[@id="IP1"]')
  164.     IP2 = doc.find('.//*[@id="IP2"]')
  165.     IP3 = doc.find('.//*[@id="IP3"]')
  166.     IP4 = doc.find('.//*[@id="IP4"]')
  167.     IP5 = doc.find('.//*[@id="IP5"]')
  168.     IP6 = doc.find('.//*[@id="IP6"]')
  169.     IP7 = doc.find('.//*[@id="IP7"]')
  170.     IP8 = doc.find('.//*[@id="IP8"]')
  171.  
  172.     for n,e in enumerate([IP1, IP2]):
  173.         e.attrib['{http://www.w3.org/1999/xlink}href'] = '#letter'+plate_code[n]
  174.     for n,e in enumerate([IP3, IP4, IP5, IP6]):
  175.         e.attrib['{http://www.w3.org/1999/xlink}href'] = '#digit'+plate_code[n+2]
  176.     for n,e in enumerate([IP7, IP8]):
  177.         e.attrib['{http://www.w3.org/1999/xlink}href'] = '#letter'+plate_code[n+6]
  178.  
  179.     folder = os.path.dirname(template_path)
  180.     svg_path = os.path.join(folder, 'Plate ({:02d}) {}.svg'.format(region, plate_code))
  181.     png_path = os.path.join(folder, 'Plate ({:02d}) {}.png'.format(region, plate_code))
  182.     print('Saving as:', svg_path)
  183.     doc.write(svg_path, default_namespace=None)
  184.     print('Converting as:', png_path)
  185.     os.system('inkscape "{}" -e "{}"'.format(svg_path, png_path))
  186.  
  187.  
  188. def pack(inner_id, zone): # inner_id 0..207339; zone 100..999
  189.     plainnum = inner_id * 1000 + zone
  190.     n = plainnum*offset % total
  191.     code = ''
  192.     for p in [12,12,9999,12,12]:
  193.         c = n%p
  194.         n = n//p
  195.         if p==12:
  196.             code = letters[c] + code
  197.         else:
  198.             code = '{:04d}'.format(c+1) + code
  199.     return code
  200.  
  201.  
  202. def unpack(alphanumcode):
  203.     alphanumcode = [
  204.             alphanumcode[0],
  205.             alphanumcode[1],
  206.             alphanumcode[2:6],
  207.             alphanumcode[6],
  208.             alphanumcode[7],
  209.         ]
  210.     num = 0
  211.     for c in alphanumcode:
  212.         if c in letters:
  213.             val = [i for i in range(len(letters)) if letters[i]==c][0]
  214.             num = num * len(letters) + val
  215.         else:
  216.             val = int(c)-1
  217.             num = num * 9999 + val
  218.     num = round(num * magic % total)
  219.     inner_id, zone = num // 1000, num % 1000
  220.     return inner_id, zone
  221.  
  222.  
  223. def get_colorscheme(regioncode):
  224.     ipcol = 'KRGB'[regioncode%4]
  225.     rpcol = 'KRGB'[regioncode//4%4]
  226.     ipmet = 'WY'[regioncode//16%2]
  227.     rpmet = 'WY'[regioncode//32%2]
  228.     scheme = [ipcol,ipmet,rpcol,rpmet]
  229.     if regioncode in range(0,64):
  230.         scheme[0], scheme[1] = scheme[1], scheme[0]
  231.     if regioncode in range(64,128):
  232.         scheme[2], scheme[3] = scheme[3], scheme[2]
  233.     return scheme
  234.  
  235.  
  236. if __name__ == '__main__':
  237. ##    print(pack(6024,336))
  238. ##    print(unpack('XM7145MA'))
  239. ##    generate_plate(pack(1,949))
  240.     for r in regions:
  241.         generate_plate(pack(1,regions[r]['zones'][0]))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement