vehicles 0.4.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +164 -0
  3. data/CHANGELOG.md +321 -0
  4. data/README.md +88 -15
  5. data/data/PROVENANCE-vehicles.md +12 -0
  6. data/data/plates/PROVENANCE.md +10 -0
  7. data/data/plates/_decode/at-districts.yml +287 -0
  8. data/data/plates/_decode/ch-cantons.yml +110 -0
  9. data/data/plates/_decode/cn-issuing-offices.yml +463 -0
  10. data/data/plates/_decode/cn-provinces.yml +614 -0
  11. data/data/plates/_decode/cz-kraj.yml +159 -0
  12. data/data/plates/_decode/dk-serial-blocks.yml +327 -0
  13. data/data/plates/_decode/es-provinces.yml +116 -0
  14. data/data/plates/_decode/fr-departements.yml +191 -0
  15. data/data/plates/_decode/gb-age-identifiers.yml +170 -0
  16. data/data/plates/_decode/gb-memory-tags.yml +202 -0
  17. data/data/plates/_decode/gr-prefectures.yml +1408 -0
  18. data/data/plates/_decode/hr-cities.yml +315 -0
  19. data/data/plates/_decode/ie-counties.yml +227 -0
  20. data/data/plates/_decode/in-state-codes.yml +169 -0
  21. data/data/plates/_decode/is-districts-1938.yml +116 -0
  22. data/data/plates/_decode/it-provinces.yml +348 -0
  23. data/data/plates/_decode/jp-office-marks.yml +960 -0
  24. data/data/plates/_decode/jp-use-marks.yml +205 -0
  25. data/data/plates/_decode/kr-authority-marks.yml +146 -0
  26. data/data/plates/_decode/kr-use-syllables.yml +194 -0
  27. data/data/plates/_decode/lu-series-order.yml +638 -0
  28. data/data/plates/_decode/mx-entity-series.yml +380 -0
  29. data/data/plates/_decode/my-index-marks.yml +271 -0
  30. data/data/plates/_decode/no-counties-1913.yml +148 -0
  31. data/data/plates/_decode/no-districts.yml +901 -0
  32. data/data/plates/_decode/pl-powiats.yml +567 -0
  33. data/data/plates/_decode/pt-trailer-services.yml +96 -0
  34. data/data/plates/_decode/ro-counties.yml +213 -0
  35. data/data/plates/_decode/se-diplomatic.yml +220 -0
  36. data/data/plates/_decode/si-regions.yml +123 -0
  37. data/data/plates/_decode/sk-districts.yml +314 -0
  38. data/data/plates/_decode/th-registration-elements.yml +208 -0
  39. data/data/plates/_decode/ua-regions.yml +393 -0
  40. data/data/plates/_decode/za-licence-marks.yml +215 -0
  41. data/data/plates/_meta/classes.yml +26 -0
  42. data/data/plates/_meta/separators.yml +102 -0
  43. data/data/plates/ad.yml +961 -0
  44. data/data/plates/ar.yml +762 -0
  45. data/data/plates/at.yml +1424 -0
  46. data/data/plates/au-act.yml +472 -0
  47. data/data/plates/au-nsw.yml +282 -0
  48. data/data/plates/au-nt.yml +431 -0
  49. data/data/plates/au-qld.yml +272 -0
  50. data/data/plates/au-sa.yml +248 -0
  51. data/data/plates/au-tas.yml +302 -0
  52. data/data/plates/au-vic.yml +215 -0
  53. data/data/plates/au-wa.yml +309 -0
  54. data/data/plates/be.yml +1840 -0
  55. data/data/plates/br.yml +1152 -0
  56. data/data/plates/ca-ab.yml +430 -0
  57. data/data/plates/ca-bc.yml +697 -0
  58. data/data/plates/ca-mb.yml +499 -0
  59. data/data/plates/ca-nb.yml +537 -0
  60. data/data/plates/ca-nl.yml +743 -0
  61. data/data/plates/ca-ns.yml +808 -0
  62. data/data/plates/ca-nt.yml +610 -0
  63. data/data/plates/ca-nu.yml +280 -0
  64. data/data/plates/ca-on.yml +881 -0
  65. data/data/plates/ca-pe.yml +592 -0
  66. data/data/plates/ca-qc.yml +1036 -0
  67. data/data/plates/ca-sk.yml +256 -0
  68. data/data/plates/ca-yt.yml +656 -0
  69. data/data/plates/ch.yml +1273 -0
  70. data/data/plates/cn.yml +1431 -0
  71. data/data/plates/cy.yml +688 -0
  72. data/data/plates/cz.yml +1179 -0
  73. data/data/plates/de.yml +1107 -0
  74. data/data/plates/dk.yml +1647 -0
  75. data/data/plates/ee.yml +1275 -0
  76. data/data/plates/es.yml +888 -0
  77. data/data/plates/fi.yml +1271 -0
  78. data/data/plates/fr.yml +1265 -0
  79. data/data/plates/gb.yml +1188 -0
  80. data/data/plates/gr.yml +721 -0
  81. data/data/plates/hr.yml +860 -0
  82. data/data/plates/hu.yml +959 -0
  83. data/data/plates/ie.yml +775 -0
  84. data/data/plates/in.yml +1172 -0
  85. data/data/plates/is.yml +667 -0
  86. data/data/plates/it.yml +1317 -0
  87. data/data/plates/jp.yml +3650 -0
  88. data/data/plates/kr.yml +1375 -0
  89. data/data/plates/li.yml +1010 -0
  90. data/data/plates/lt.yml +879 -0
  91. data/data/plates/lu.yml +842 -0
  92. data/data/plates/lv.yml +924 -0
  93. data/data/plates/mc.yml +1024 -0
  94. data/data/plates/mt.yml +854 -0
  95. data/data/plates/mx.yml +1372 -0
  96. data/data/plates/my.yml +685 -0
  97. data/data/plates/nl.yml +1016 -0
  98. data/data/plates/no.yml +1018 -0
  99. data/data/plates/nz.yml +1699 -0
  100. data/data/plates/pl.yml +1296 -0
  101. data/data/plates/pt.yml +847 -0
  102. data/data/plates/ro.yml +785 -0
  103. data/data/plates/se.yml +1091 -0
  104. data/data/plates/si.yml +1105 -0
  105. data/data/plates/sk.yml +1439 -0
  106. data/data/plates/sm.yml +1119 -0
  107. data/data/plates/th.yml +1150 -0
  108. data/data/plates/ua.yml +1672 -0
  109. data/data/plates/us-ak.yml +763 -0
  110. data/data/plates/us-al.yml +457 -0
  111. data/data/plates/us-ar.yml +427 -0
  112. data/data/plates/us-as.yml +454 -0
  113. data/data/plates/us-az.yml +430 -0
  114. data/data/plates/us-ca.yml +892 -0
  115. data/data/plates/us-co.yml +452 -0
  116. data/data/plates/us-ct.yml +427 -0
  117. data/data/plates/us-dc.yml +614 -0
  118. data/data/plates/us-de.yml +551 -0
  119. data/data/plates/us-fl.yml +741 -0
  120. data/data/plates/us-ga.yml +644 -0
  121. data/data/plates/us-gu.yml +658 -0
  122. data/data/plates/us-hi.yml +585 -0
  123. data/data/plates/us-ia.yml +438 -0
  124. data/data/plates/us-id.yml +531 -0
  125. data/data/plates/us-il.yml +516 -0
  126. data/data/plates/us-in.yml +324 -0
  127. data/data/plates/us-ks.yml +351 -0
  128. data/data/plates/us-ky.yml +770 -0
  129. data/data/plates/us-la.yml +568 -0
  130. data/data/plates/us-ma.yml +379 -0
  131. data/data/plates/us-md.yml +536 -0
  132. data/data/plates/us-me.yml +445 -0
  133. data/data/plates/us-mi.yml +408 -0
  134. data/data/plates/us-mn.yml +411 -0
  135. data/data/plates/us-mo.yml +356 -0
  136. data/data/plates/us-mp.yml +402 -0
  137. data/data/plates/us-ms.yml +432 -0
  138. data/data/plates/us-mt.yml +619 -0
  139. data/data/plates/us-nc.yml +602 -0
  140. data/data/plates/us-nd.yml +419 -0
  141. data/data/plates/us-ne.yml +483 -0
  142. data/data/plates/us-nh.yml +394 -0
  143. data/data/plates/us-nj.yml +547 -0
  144. data/data/plates/us-nm.yml +574 -0
  145. data/data/plates/us-nv.yml +655 -0
  146. data/data/plates/us-ny.yml +592 -0
  147. data/data/plates/us-oh.yml +404 -0
  148. data/data/plates/us-ok.yml +513 -0
  149. data/data/plates/us-or.yml +392 -0
  150. data/data/plates/us-pa.yml +506 -0
  151. data/data/plates/us-pr.yml +507 -0
  152. data/data/plates/us-ri.yml +445 -0
  153. data/data/plates/us-sc.yml +605 -0
  154. data/data/plates/us-sd.yml +428 -0
  155. data/data/plates/us-tn.yml +471 -0
  156. data/data/plates/us-tx.yml +535 -0
  157. data/data/plates/us-ut.yml +384 -0
  158. data/data/plates/us-va.yml +567 -0
  159. data/data/plates/us-vi.yml +489 -0
  160. data/data/plates/us-vt.yml +458 -0
  161. data/data/plates/us-wa.yml +484 -0
  162. data/data/plates/us-wi.yml +509 -0
  163. data/data/plates/us-wv.yml +446 -0
  164. data/data/plates/us-wy.yml +523 -0
  165. data/data/plates/va.yml +604 -0
  166. data/data/plates/za.yml +1141 -0
  167. data/data/vehicles.json +160653 -105090
  168. data/lib/vehicles/configuration.rb +18 -2
  169. data/lib/vehicles/dataset.rb +73 -18
  170. data/lib/vehicles/fuzzy.rb +115 -0
  171. data/lib/vehicles/http.rb +48 -0
  172. data/lib/vehicles/make.rb +36 -6
  173. data/lib/vehicles/mcp_server.rb +5 -5
  174. data/lib/vehicles/model.rb +42 -6
  175. data/lib/vehicles/plates/jurisdiction.rb +32 -0
  176. data/lib/vehicles/plates/series.rb +291 -0
  177. data/lib/vehicles/plates/template_fill.rb +188 -0
  178. data/lib/vehicles/plates/templates.rb +162 -0
  179. data/lib/vehicles/plates.rb +122 -0
  180. data/lib/vehicles/providers/hosted_provider.rb +49 -58
  181. data/lib/vehicles/providers/local_provider.rb +4 -3
  182. data/lib/vehicles/validators/vehicle_make_validator.rb +3 -1
  183. data/lib/vehicles/validators/vehicle_model_validator.rb +1 -1
  184. data/lib/vehicles/version.rb +1 -1
  185. data/lib/vehicles.rb +53 -16
  186. data/rakelib/data_refresh.rake +109 -0
  187. data/rakelib/plates_refresh.rake +29 -0
  188. data/sig/vehicles.rbs +18 -0
  189. metadata +174 -2
@@ -0,0 +1,314 @@
1
+ # plates/_decode/sk-districts.yml — the Slovak okres codes carried by the first
2
+ # letter pair of an evidenčné číslo.
3
+ #
4
+ # THE SOURCE IS A STATUTORY BODY PROVISION, NOT A TABLE ON THE WEB. Every row
5
+ # below is transcribed mechanically (a script, not a human retype) from § 36
6
+ # ods. 2 of vyhláška Ministerstva vnútra Slovenskej republiky č. 9/2009 Z. z.,
7
+ # ktorou sa vykonáva zákon o cestnej premávke, in the CONSOLIDATED VERSION IN
8
+ # FORCE ON 1 AUGUST 2022 — the last version of that section before it was
9
+ # repealed. Its opening words, verbatim: "Pre potreby evidenčného čísla sa
10
+ # označenie okresov ustanovuje takto:". 72 district rows, 93 codes.
11
+ #
12
+ # THE ONE FACT A CONSUMER MUST NOT MISS — AND IT IS WHY THIS FILE OPENS WITH IT
13
+ # RATHER THAN BURYING IT IN PROSE:
14
+ #
15
+ # ON 1 JANUARY 2023 THE DISTRICT MEANING WAS ABOLISHED PROSPECTIVELY.
16
+ # Three dated primary acts, all quoted below in `decoupling_2023`:
17
+ # * zákon č. 128/2021 Z. z. Čl. I bod 32 DELETED the second sentence of
18
+ # § 124 ods. 1 zákona č. 8/2009 Z. z. — the sentence that said "Prvá
19
+ # dvojica písmen evidenčného čísla označuje okres, v ktorom je vozidlo
20
+ # evidované" (the first letter pair designates the district in which the
21
+ # vehicle is registered). Čl. IV: "Tento zákon nadobúda účinnosť
22
+ # 1. januára 2023."
23
+ # * the same act, bod 31, replaced the word "okresov" with "údajov" in the
24
+ # delegation in § 123 ods. 20 — the ministry no longer has power to
25
+ # prescribe DISTRICT markings on plates at all.
26
+ # * vyhláška č. 480/2022 Z. z. Čl. I bod 7, in force 1 January 2023:
27
+ # "§ 36 sa vypúšťa." — the table reproduced in this file was struck out
28
+ # of the regulation on that date.
29
+ #
30
+ # CONSEQUENCE FOR A PARSE API, stated as a rule rather than a caution:
31
+ # a decode of the leading letter pair is a claim about WHERE AND WHEN THE
32
+ # PLATE WAS ISSUED, never about where the vehicle is registered now, and for
33
+ # a plate first issued on or after 1 January 2023 it is not a geographic
34
+ # claim at all. Two separate 2023 changes make it wrong:
35
+ # (a) NEW ISSUES are allocated from a single national sequence with no
36
+ # district input (§ 124 ods. 1 in its post-2023 wording gives only the
37
+ # SHAPE: "Za prvou dvojicou písmen sa za štátnym znakom Slovenskej
38
+ # republiky uvádzajú tri číslice a dvojica písmen").
39
+ # (b) EXISTING plates stay with the vehicle when it changes hands and
40
+ # crosses a district boundary — § 116 ods. 14, inserted by the same
41
+ # act, verbatim: "Pri zmene držby vozidla sa ponechávajú tabuľky
42
+ # s evidenčným číslom na vozidle a to aj v tom prípade, ak má nový
43
+ # držiteľ adresu pobytu, sídla, prevádzkarne alebo organizačnej zložky
44
+ # v pôsobnosti iného orgánu Policajného zboru." Before that date the
45
+ # opposite rule applied — § 116 ods. 13 in the version in force on
46
+ # 1 August 2022: "ak orgán Policajného zboru eviduje zmenu z iného
47
+ # okresu pobytu, sídla alebo prevádzkarne, pridelí vozidlu evidenčné
48
+ # číslo a vydá tabuľku s evidenčným číslom".
49
+ # A plate carrying BA therefore means "issued in Bratislava before 2023",
50
+ # and the vehicle may lawfully have lived in Košice ever since.
51
+ #
52
+ # The rows remain live data, not history: vyhláška č. 480/2022 Z. z. Čl. I
53
+ # bod 10 inserted § 41e into vyhláška 9/2009, verbatim: "(1) Tabuľky
54
+ # s evidenčným číslom ... podľa predpisov účinných do 31. decembra 2022
55
+ # zostávajú v platnosti. (2) Tabuľky s evidenčným číslom ... podľa predpisov
56
+ # účinných do 31. decembra 2022 sa vydávajú do vyčerpania ich skladových
57
+ # zásob." District plates stay lawful indefinitely and were still being issued
58
+ # from stock after the reform date, so the reform has NO end date on the road.
59
+ #
60
+ # Referenced by plates/sk.yml via region_encoding on the pre-2023 district
61
+ # series; the current series (sk-standard-2023) deliberately carries
62
+ # `region_encoding: none`.
63
+ jurisdiction: sk
64
+ topic: districts
65
+ authority:
66
+ name: "Vyhláška Ministerstva vnútra Slovenskej republiky č. 9/2009 Z. z., § 36 ods. 2 (repealed 1 January 2023)"
67
+ url: "https://www.slov-lex.sk/static/pdf/2009/9/ZZ_2009_9_20220801.pdf"
68
+ sources:
69
+ - "https://www.slov-lex.sk/static/pdf/2009/9/ZZ_2009_9_20220801.pdf # vyhláška MV SR č. 9/2009 Z. z., consolidated version in force 01.08.2022 - 29.12.2022, § 36 ods. 2 'Pre potreby evidenčného čísla sa označenie okresov ustanovuje takto' — all 72 rows below, extracted by script from the official PDF. Accessed 2026-08-02"
70
+ - "https://www.slov-lex.sk/static/pdf/1997/90/ZZ_1997_90_19970401.pdf # vyhláška MV SR č. 90/1997 Z. z., § 44 ods. 4 'Označenie okresov pre potreby evidenčného čísla sa ustanovuje takto' — the FIRST enactment of this table, in force 1 April 1997, with fewer codes per district (e.g. 'BB, BC' where 2022 has 'BB, BC, BK'; 'ZA, ZI' where 2022 has 'ZA, ZI, ZL'). Per-code first-issue dates are a recorded gap. Accessed 2026-08-02"
71
+ - "https://www.slov-lex.sk/static/pdf/2022/480/ZZ_2022_480.pdf # vyhláška č. 480/2022 Z. z. Čl. I bod 7 '§ 36 sa vypúšťa.'; Čl. II commences that item on 1 January 2023; Čl. I bod 10 inserts § 41e (existing plates remain valid, stock is issued out). Accessed 2026-08-02"
72
+ - "https://www.slov-lex.sk/static/pdf/2021/128/ZZ_2021_128_20211201.pdf # zákon č. 128/2021 Z. z. Čl. I body 31, 32 and 11 (§ 116 ods. 14); Čl. IV 'Tento zákon nadobúda účinnosť 1. januára 2023.' Accessed 2026-08-02"
73
+ - "https://www.slov-lex.sk/static/pdf/2009/8/ZZ_2009_8_20220801.pdf # zákon č. 8/2009 Z. z. as in force 01.08.2022 — § 124 ods. 1 second sentence (the district rule, pre-repeal) and § 116 ods. 13 (new number on a cross-district change). Accessed 2026-08-02"
74
+ - "https://www.slov-lex.sk/static/pdf/2009/8/ZZ_2009_8_20230101.pdf # zákon č. 8/2009 Z. z. as in force 01.01.2023 — the same two provisions AFTER the reform. Diffing the pair IS the evidence for this file's central caveat. Accessed 2026-08-02"
75
+ period: { start: 1997, end: 2022 }
76
+ period_evidence: instrument-dated-both-ends
77
+ period_note: >-
78
+ 1997 is the commencement of vyhláška MV SR č. 90/1997 Z. z. (1 April 1997),
79
+ which first enacted this table; 2022 is the last full year of § 36 ods. 2
80
+ vyhlášky 9/2009, repealed with effect from 1 January 2023. NEITHER bound is
81
+ the validity of the plates: they remain lawful indefinitely (§ 41e) and were
82
+ issued from stock past the end date. The period is the period of the CODE
83
+ SYSTEM, and per-row periods are a recorded gap — Slovak district reform added
84
+ codes over time (see the 90/1997 comparison in `sources`) and the instruments
85
+ never dated the additions.
86
+ decode_direction: "code -> district of ISSUE (pre-2023). NEVER code -> district of current registration."
87
+ maximal_munch: false
88
+ split_note: >-
89
+ Unlike Austria and Germany, the Slovak prefix is FIXED-WIDTH: § 124 ods. 1
90
+ makes it exactly two letters, so the split point is unambiguous and no
91
+ longest-match rule is needed. The residual ambiguity is semantic, not
92
+ lexical, and it is the 2023 one described in `decoupling_2023`.
93
+
94
+ decoupling_2023:
95
+ effective: "2023-01-01"
96
+ applies_to: "every evidenčné číslo FIRST ISSUED on or after this date, and every pre-2023 plate that has since changed hands"
97
+ district_meaning_after: none
98
+ instruments:
99
+ - citation: "zákon č. 128/2021 Z. z., Čl. I bod 32"
100
+ text: "V § 124 ods. 1 sa vypúšťa druhá veta."
101
+ effect: >-
102
+ The deleted sentence is the whole district claim: "Prvá dvojica písmen
103
+ evidenčného čísla označuje okres, v ktorom je vozidlo evidované." After
104
+ 1 January 2023 § 124 ods. 1 reads only "Evidenčné číslo tvoria písmená
105
+ a číslice. Za prvou dvojicou písmen sa za štátnym znakom Slovenskej
106
+ republiky uvádzajú tri číslice a dvojica písmen." — a SHAPE with no
107
+ geography in it.
108
+ commencement: "Čl. IV: 'Tento zákon nadobúda účinnosť 1. januára 2023.'"
109
+ - citation: "zákon č. 128/2021 Z. z., Čl. I bod 31"
110
+ text: "V § 123 ods. 20 sa slovo „okresov“ nahrádza slovom „údajov“."
111
+ effect: >-
112
+ The delegation to the ministry stops mentioning districts, so the
113
+ regulation lost its power to prescribe a district marking at all. This
114
+ is why the table below could be, and was, struck out wholesale.
115
+ - citation: "zákon č. 128/2021 Z. z., Čl. I bod 11 (new § 116 ods. 14)"
116
+ text: >-
117
+ "Pri zmene držby vozidla sa ponechávajú tabuľky s evidenčným číslom na
118
+ vozidle a to aj v tom prípade, ak má nový držiteľ adresu pobytu, sídla,
119
+ prevádzkarne alebo organizačnej zložky v pôsobnosti iného orgánu
120
+ Policajného zboru."
121
+ effect: >-
122
+ PLATE FOLLOWS THE VEHICLE across a district boundary. This is what
123
+ breaks the decode for EXISTING plates, not just new ones — a BA plate on
124
+ the road today may be on a vehicle registered anywhere in Slovakia.
125
+ - citation: "zákon č. 128/2021 Z. z., Čl. I bod 29 (§ 123 ods. 8)"
126
+ text: >-
127
+ "Orgán Policajného zboru pridelí vozidlu evidenčné číslo, ku ktorému už
128
+ má držiteľ vozidla ponechané tabuľky s evidenčným číslom z iného
129
+ vozidla, ak o to držiteľ vozidla požiada."
130
+ effect: >-
131
+ PLATE FOLLOWS THE OWNER: a holder may keep the plates off one vehicle
132
+ (§ 116 ods. 17) and have them assigned to another. Slovakia is therefore
133
+ NOT a `binding: owner` jurisdiction in the Swiss sense — the binding
134
+ stays with the vehicle by default (§ 116 ods. 14) and moves to the owner
135
+ only on request. plates/sk.yml records `binding: vehicle` with that
136
+ qualification stated on the series.
137
+ - citation: "vyhláška č. 480/2022 Z. z., Čl. I bod 7"
138
+ text: "§ 36 sa vypúšťa."
139
+ effect: "Struck the table below out of vyhláška 9/2009 with effect from 1 January 2023 (Čl. II)."
140
+ what_did_not_change: >-
141
+ THE STRING SHAPE. Both before and after the reform an ordinary Slovak plate
142
+ is two letters, the state arms, three digits, two letters. A parse API
143
+ cannot tell a 2022 district plate from a 2024 national-sequence plate by
144
+ shape alone; only the letter pair against this table plus the knowledge that
145
+ post-reform pairs are allocated alphabetically from AA distinguishes them,
146
+ and the two sets OVERLAP. Record the ambiguity; do not resolve it by guess.
147
+ allocation_after_2023:
148
+ claim: "new pairs are allocated nationally in alphabetical sequence from AA"
149
+ evidence: secondary-wikipedia
150
+ source: "https://en.wikipedia.org/wiki/Vehicle_registration_plates_of_Slovakia # 'arbitrary letters of the alphabet (assigned alphabetically, starting with AA)'. Accessed 2026-08-02"
151
+ note: >-
152
+ NOT FOUND IN ANY INSTRUMENT. § 124 ods. 1 prescribes the shape and is
153
+ silent on allocation order; neither the zákon nor vyhláška 9/2009 in its
154
+ post-2023 wording publishes an allocation rule. Tagged secondary-wikipedia
155
+ and NOT relied on by any regex in plates/sk.yml. Recorded gap.
156
+
157
+ collisions:
158
+ - "SK — Svidník (a district code) AND the international distinguishing sign of Slovakia itself, which appears on the same plate in the blue EU field (§ 35 ods. 9 vyhlášky 9/2009: 'Rozlišovací znak Slovenskej republiky sa skladá z písmen SK'). A parse API reading the band and the serial must not conflate them."
159
+ - "PS — Prešov (a district code) AND, in the same vyhláška, a VEHICLE CATEGORY letter pair used throughout § 35 ('vozidlu kategórie ... PS a LS'). Textual collision only; the plate positions differ."
160
+ - "EE / ZZ — NOT district codes. § 125 ods. 1 and 2 zákona 8/2009 reserve them for foreign missions and for mission administrative/technical staff. A leading EE or ZZ must be routed to the diplomatic series, never to this table."
161
+ - "EL / EV — NOT district codes since 1 January 2023. § 35 ods. 7 vyhlášky 9/2009, as replaced by vyhláška 480/2022: 'Písmená na tabuľke s evidenčným číslom vozidla podľa § 123 ods. 18 zákona začínajú písmenami EL alebo EV' — the electric/plug-in-hybrid prefix. Neither pair appears in the district table below, so there is no historical clash, but a parse API must know them."
162
+ - "Y — never a district code, and reserved in the TRAILING pair: § 35 ods. 3 vyhlášky 9/2009 puts Y first in the letter pair after the state arms for category O and R vehicles (trailers). This is the one piece of structure that survived 2023 intact."
163
+
164
+ # ---------------------------------------------------------------------------
165
+ # THE TABLE. Rows are the 72 district entries of § 36 ods. 2 in the annex's own
166
+ # alphabetical-by-district order; `codes` lists the pairs the annex assigns to
167
+ # each, in the annex's own order within the row. Extracted by script from the
168
+ # official slov-lex PDF, not retyped.
169
+ # ---------------------------------------------------------------------------
170
+ districts:
171
+ - district: "Banská Bystrica"
172
+ codes: [BB, BC, BK]
173
+ - district: "Banská Štiavnica"
174
+ codes: [BS]
175
+ - district: "Bardejov"
176
+ codes: [BJ]
177
+ - district: "Bánovce nad Bebravou"
178
+ codes: [BN]
179
+ - district: "Brezno"
180
+ codes: [BR]
181
+ - district: "Bratislava"
182
+ codes: [BA, BD, BE, BI, BL, BT]
183
+ - district: "Bytča"
184
+ codes: [BY]
185
+ - district: "Čadca"
186
+ codes: [CA]
187
+ - district: "Detva"
188
+ codes: [DT]
189
+ - district: "Dolný Kubín"
190
+ codes: [DK]
191
+ - district: "Dunajská Streda"
192
+ codes: [DS]
193
+ - district: "Galanta"
194
+ codes: [GA]
195
+ - district: "Gelnica"
196
+ codes: [GL]
197
+ - district: "Hlohovec"
198
+ codes: [HC]
199
+ - district: "Humenné"
200
+ codes: [HE]
201
+ - district: "Ilava"
202
+ codes: [IL]
203
+ - district: "Kežmarok"
204
+ codes: [KK]
205
+ - district: "Komárno"
206
+ codes: [KN]
207
+ - district: "Košice"
208
+ codes: [KE, KC, KI]
209
+ - district: "Košice-okolie"
210
+ codes: [KS]
211
+ - district: "Krupina"
212
+ codes: [KA]
213
+ - district: "Kysucké Nové Mesto"
214
+ codes: [KM]
215
+ - district: "Levice"
216
+ codes: [LV, LL]
217
+ - district: "Levoča"
218
+ codes: [LE]
219
+ - district: "Liptovský Mikuláš"
220
+ codes: [LM]
221
+ - district: "Lučenec"
222
+ codes: [LC]
223
+ - district: "Malacky"
224
+ codes: [MA]
225
+ - district: "Martin"
226
+ codes: [MT]
227
+ - district: "Medzilaborce"
228
+ codes: [ML]
229
+ - district: "Michalovce"
230
+ codes: [MI]
231
+ - district: "Myjava"
232
+ codes: [MY]
233
+ - district: "Námestovo"
234
+ codes: [NO]
235
+ - district: "Nitra"
236
+ codes: [NR, NI, NT]
237
+ - district: "Nové Mesto nad Váhom"
238
+ codes: [NM]
239
+ - district: "Nové Zámky"
240
+ codes: [NZ, NC]
241
+ - district: "Partizánske"
242
+ codes: [PE]
243
+ - district: "Pezinok"
244
+ codes: [PK]
245
+ - district: "Piešťany"
246
+ codes: [PN]
247
+ - district: "Poltár"
248
+ codes: [PT]
249
+ - district: "Poprad"
250
+ codes: [PP]
251
+ - district: "Považská Bystrica"
252
+ codes: [PB]
253
+ - district: "Prešov"
254
+ codes: [PO, PV, PS]
255
+ - district: "Prievidza"
256
+ codes: [PD]
257
+ - district: "Púchov"
258
+ codes: [PU]
259
+ - district: "Revúca"
260
+ codes: [RA]
261
+ - district: "Rimavská Sobota"
262
+ codes: [RS]
263
+ - district: "Rožňava"
264
+ codes: [RV]
265
+ - district: "Ružomberok"
266
+ codes: [RK]
267
+ - district: "Sabinov"
268
+ codes: [SB]
269
+ - district: "Senec"
270
+ codes: [SC]
271
+ - district: "Senica"
272
+ codes: [SE]
273
+ - district: "Skalica"
274
+ codes: [SI]
275
+ - district: "Snina"
276
+ codes: [SV]
277
+ - district: "Sobrance"
278
+ codes: [SO]
279
+ - district: "Spišská Nová Ves"
280
+ codes: [SN]
281
+ - district: "Stará Ľubovňa"
282
+ codes: [SL]
283
+ - district: "Stropkov"
284
+ codes: [SP]
285
+ - district: "Svidník"
286
+ codes: [SK]
287
+ - district: "Šaľa"
288
+ codes: [SA]
289
+ - district: "Topoľčany"
290
+ codes: [TO]
291
+ - district: "Trebišov"
292
+ codes: [TV]
293
+ - district: "Trenčín"
294
+ codes: [TN, TC, TE]
295
+ - district: "Trnava"
296
+ codes: [TT, TA, TB]
297
+ - district: "Turčianske Teplice"
298
+ codes: [TR]
299
+ - district: "Tvrdošín"
300
+ codes: [TS]
301
+ - district: "Veľký Krtíš"
302
+ codes: [VK]
303
+ - district: "Vranov nad Topľou"
304
+ codes: [VT]
305
+ - district: "Zlaté Moravce"
306
+ codes: [ZM]
307
+ - district: "Zvolen"
308
+ codes: [ZV]
309
+ - district: "Žarnovica"
310
+ codes: [ZC]
311
+ - district: "Žiar nad Hronom"
312
+ codes: [ZH]
313
+ - district: "Žilina"
314
+ codes: [ZA, ZI, ZL]
@@ -0,0 +1,208 @@
1
+ # plates/_decode/th-registration-elements.yml — the decodable elements of a
2
+ # Thai registration mark. DRAFT for verification.
3
+ #
4
+ # WHY THIS FILE IS SHAPED LIKE THIS, stated up front because it is unusual:
5
+ # Thailand has NO region letter-code table to decode. The Motor-Vehicle-Act
6
+ # plate SPELLS THE PROVINCE OUT in Thai on its own line (กฎกระทรวง พ.ศ. ๒๕๕๔
7
+ # ข้อ ๓ (๑) (ก) ๒)), so a parse API needs a NAME list, not a code table, and
8
+ # that name list is ordinary Thai geography rather than plate law. What Thailand
9
+ # does have that is closed, primary and genuinely decodable is smaller and it is
10
+ # all here: the four diplomatic corps letters, the six commercial vehicle-type
11
+ # code bands, and the one sub-provincial registration place named in the
12
+ # regulation. Everything else is a MECHANISM, and each mechanism below says
13
+ # plainly what is delegated and to whom.
14
+ #
15
+ # Referenced by plates/th.yml from every series' `region_encoding`.
16
+ jurisdiction: th
17
+ topic: registration-elements
18
+ authority:
19
+ name: กรมการขนส่งทางบก (Department of Land Transport, DLT), Ministry of Transport
20
+ url: "https://www.dlt.go.th"
21
+ sources:
22
+ - "https://web.archive.org/web/20171113165614/http://www.ratchakitcha.soc.go.th/DATA/PDF/2554/A/045/6.PDF # กฎกระทรวง กำหนดขนาด ลักษณะ และสีของแผ่นป้ายทะเบียนรถ ฯ พ.ศ. ๒๕๕๔, ราชกิจจานุเบกษา เล่ม ๑๒๘ ตอนที่ ๔๕ ก หน้า ๖, 8 June 2011 — ข้อ ๓ (๑) (ก) ๒) the province line and the Betong exception; ข้อ ๓ (๑) (ก) ๓) the leading numeral; ข้อ ๓ (๑) (ก) ๕) the delegation of the alphabet; ข้อ ๓ (๑) (ค) ๓) the four corps letters"
23
+ - "https://web.archive.org/web/20160304073451/http://www.ratchakitcha.soc.go.th/DATA/PDF/2554/E/044/52.PDF # ประกาศกรมการขนส่งทางบก ฯ พ.ศ. ๒๕๕๔, ราชกิจจานุเบกษา เล่ม ๑๒๘ ตอนพิเศษ ๔๔ ง หน้า ๕๒, 19 April 2011 — ข้อ ๒ (๑) the numeric province code on line 1; ข้อ ๒ (๓) the six vehicle-type code bands and the 0001-9999 serial rule"
24
+ accessed: "2026-08-02"
25
+ period: { start: 2011 }
26
+ period_evidence: instrument-in-force
27
+ period_note: >-
28
+ 2011 is the year of BOTH instruments (the ministerial regulation published
29
+ 8 June 2011 and in force on the expiry of 180 days; the DLT announcement
30
+ published 19 April 2011). Neither created the elements below — the diplomatic
31
+ corps letters and the commercial type codes both carry over from revoked
32
+ predecessors (the B.E. 2547/2550 regulations and the B.E. 2549 announcement,
33
+ which itself replaced one of 14 April B.E. 2530). Their own start years are
34
+ recorded gaps and no year is invented for them.
35
+
36
+ # ---------------------------------------------------------------------------
37
+ # 1. THE PROVINCE LINE — a NAME, not a code. This is the decode dimension a
38
+ # consumer will reach for first, and it is the one Thailand does not encode.
39
+ # ---------------------------------------------------------------------------
40
+ province_line:
41
+ mechanism: spelled-out-name
42
+ rule: >-
43
+ กฎกระทรวง พ.ศ. ๒๕๕๔ ข้อ ๓ (๑) (ก) ๒), verbatim: "บรรทัดที่สองเป็นตัวอักษร
44
+ แสดงชื่อกรุงเทพมหานครหรือจังหวัดที่จดทะเบียน เว้นแต่กรณีจดทะเบียนที่อำเภอ
45
+ เบตง จังหวัดยะลา ให้ใช้คำว่า เบตง ทั้งนี้ ตัวอักษรให้ใช้ตัวอักษรไทย" — line
46
+ two carries the letters showing the name of Bangkok or of the province of
47
+ registration, except where the vehicle is registered at Betong District,
48
+ Yala Province, where the word เบตง is used; the letters shall be Thai
49
+ letters. The identical rule is repeated for motorcycles at ข้อ ๓ (๑) (ข) ๒),
50
+ where the province name is on line TWO of a three-line plate.
51
+ script: Thai
52
+ exceptions:
53
+ - name_on_plate: "เบตง"
54
+ romanised: Betong
55
+ covers: "อำเภอเบตง จังหวัดยะลา (Betong District, Yala Province)"
56
+ note: >-
57
+ The ONLY sub-provincial registration place in Thai plate law, and it is
58
+ in the regulation itself rather than in an administrative announcement.
59
+ A parse API that maps plate text to provinces must special-case it: a
60
+ Betong plate reads เบตง, never ยะลา.
61
+ gap: >-
62
+ A full Thai-name-to-province table (77 changwat plus Bangkok, with romanised
63
+ forms and ISO 3166-2:TH codes) is what a parse API actually needs and is NOT
64
+ supplied here: it was not secured from a primary in this pass and is
65
+ geography rather than plate law. It is the single highest-value follow-up
66
+ for Thailand and is deliberately left empty rather than filled from an
67
+ encyclopaedic source.
68
+
69
+ # ---------------------------------------------------------------------------
70
+ # 2. THE CATEGORY LETTERS — delegated, unpinned, and the reason Thai plates
71
+ # cannot yet be validated strictly by this dataset.
72
+ # ---------------------------------------------------------------------------
73
+ category_letters:
74
+ mechanism: delegated-to-director-general
75
+ rule: >-
76
+ กฎกระทรวง พ.ศ. ๒๕๕๔ ข้อ ๓ (๑) (ก) ๕), verbatim: "การใช้ตัวเลขนำหน้าตัวอักษร
77
+ ประจำหมวด ตัวอักษรประจำหมวด และหมายเลขทะเบียน ให้เป็นไปตามที่อธิบดีประกาศ
78
+ กำหนด" — the use of the numeral preceding the category letters, the category
79
+ letters themselves, and the registration number are as the Director-General
80
+ publicly prescribes. Repeated verbatim for motorcycles at ข้อ ๓ (๑) (ข) ๔).
81
+ count: 2
82
+ script: Thai
83
+ unicode_range: "U+0E01–U+0E2E (Thai consonants ก through ฮ)"
84
+ leading_numeral:
85
+ values: "1–9"
86
+ cars_rule: >-
87
+ ข้อ ๓ (๑) (ก) ๓): added in front of the first category letter ONLY once
88
+ every combination of the first and second category letters has been used.
89
+ motorcycles_rule: >-
90
+ ข้อ ๓ (๑) (ข) ๒) states the numeral as part of the base composition of
91
+ line 1, with no exhaustion condition — a real difference between the car
92
+ and motorcycle rules that a parse API must not smooth over.
93
+ partial_list_from_metrics:
94
+ values: ["ข", "ง", "ช", "ซ", "ฌ", "ญ", "ฎ", "ฏ", "ฐ", "ฒ", "ณ", "ป", "ฝ", "ฟ", "ศ", "ษ", "ส", "ฬ", "ฮ"]
95
+ rule: >-
96
+ ข้อ ๓ (๑) (ก) ๔) sets minimum letter heights and widths and then excepts
97
+ "ตัวอักษร ข ง ช ซ ฌ ญ ฎ ฏ ฐ ฒ ณ ป ฝ ฟ ศ ษ ส ฬ ฮ สระ วรรณยุกต์ และหมายเลข ๑",
98
+ whose dimensions the Director-General fixes instead. These nineteen
99
+ consonants therefore appear on Thai plates as a matter of primary law.
100
+ warning: >-
101
+ This is NOT the alphabet and must never be used as one. It is a side-door
102
+ list of the letters whose SHAPES need special metrics; the letters with
103
+ ordinary metrics (ก, ค, จ, ท, ม, ย, ร, ล, ว, อ and others) are absent from
104
+ it precisely because they are unexceptional.
105
+ gap: >-
106
+ No Director-General announcement fixing the category-letter alphabet, the
107
+ order in which letter pairs open, or the mapping of letter families to
108
+ vehicle classes was retrieved. Consequently plates/th.yml asserts no letter
109
+ set, offers no age inference from a letter pair, and marks every
110
+ Thai-script series `matching: recall-only`.
111
+
112
+ # ---------------------------------------------------------------------------
113
+ # 3. DIPLOMATIC CORPS LETTERS — closed, primary, four rows. The one Thai decode
114
+ # table that is complete on its face.
115
+ # ---------------------------------------------------------------------------
116
+ diplomatic_corps_letters:
117
+ mechanism: closed-list-in-instrument
118
+ rule: "กฎกระทรวง พ.ศ. ๒๕๕๔ ข้อ ๓ (๑) (ค) ๓) — 'การใช้ตัวอักษรในบรรทัดที่หนึ่งของตอนซ้ายของแผ่นป้ายให้เป็นดังต่อไปนี้' followed by exactly these four rows"
119
+ codes:
120
+ - letter: "ท"
121
+ thai: "รถยนต์ของบุคคลในคณะผู้แทนทางการทูต"
122
+ en: "vehicles of persons in the diplomatic corps"
123
+ ground_colour: "retroreflective white, black characters (ข้อ ๓ (๒) (ช))"
124
+ - letter: "พ"
125
+ thai: "รถยนต์ของบุคคลในหน่วยงานพิเศษของสถานทูต"
126
+ en: "vehicles of persons in a special agency of an embassy"
127
+ ground_colour: "retroreflective light blue, white characters (ข้อ ๓ (๒) (ซ))"
128
+ - letter: "ก"
129
+ thai: "รถยนต์ของบุคคลในคณะผู้แทนทางกงสุล"
130
+ en: "vehicles of persons in the consular corps"
131
+ ground_colour: "retroreflective light blue, white characters; retroreflective GREY with black characters for an honorary consul (เจ้าพนักงานกงสุลกิตติมศักดิ์), by the proviso to ข้อ ๓ (๒) (ซ)"
132
+ - letter: "อ"
133
+ thai: "รถยนต์ของบุคคลในองค์การระหว่างประเทศหรือทบวงการชำนัญพิเศษแห่งสหประชาชาติซึ่งประจำอยู่ในประเทศไทย"
134
+ en: "vehicles of persons in an international organisation or a UN specialised agency stationed in Thailand"
135
+ ground_colour: "retroreflective light blue, white characters"
136
+ collisions:
137
+ - "ก is BOTH the consular corps letter here and the first consonant of the Thai alphabet, which is also an ordinary category letter on civilian plates. The two are told apart by LAYOUT, not by the letter: a diplomatic plate is a single line of 11 x 38.7 cm with a two-line left block and a bar, while a civilian plate is two lines of 15 x 34 cm. A parser that looks only at the letter will get this wrong."
138
+ - "ท is the diplomatic letter here and is also reported as the first letter of Bangkok metered-taxi series. Same caution: the discriminator is the layout and the ground colour, not the consonant."
139
+ country_code:
140
+ mechanism: delegated
141
+ note: >-
142
+ ข้อ ๓ (๑) (ค) ๒) requires line 2 of the left block to be "ตัวเลขอารบิค
143
+ เป็นรหัสแทนชื่อประเทศหรือองค์การระหว่างประเทศหรือทบวงการชำนัญพิเศษแห่ง
144
+ สหประชาชาติซึ่งประจำอยู่ในประเทศไทย" — Arabic numerals coding the country
145
+ or the organisation. The regulation prescribes the FIELD and not the
146
+ CODES; no code list was secured. Recorded gap.
147
+
148
+ # ---------------------------------------------------------------------------
149
+ # 4. LAND TRANSPORT ACT VEHICLE-TYPE CODES — closed, primary, six rows, and the
150
+ # only Thai decode that a machine can apply to a purely numeric string.
151
+ # ---------------------------------------------------------------------------
152
+ lta_vehicle_type_codes:
153
+ mechanism: closed-list-in-instrument
154
+ rule: "ประกาศกรมการขนส่งทางบก พ.ศ. ๒๕๕๔ ข้อ ๒ (๓): 'เลขรหัสแสดงประเภทรถแบ่งตามประเภทการขนส่งดังนี้' followed by exactly these six rows"
155
+ ground_colour_rule: >-
156
+ ข้อ ๒ (๑) puts scheduled, non-scheduled and small-vehicle transport on a
157
+ retroreflective YELLOW ground; ข้อ ๒ (๒) puts private transport on a
158
+ retroreflective WHITE ground, otherwise identical. The type code therefore
159
+ PREDICTS the plate colour exactly, which is the useful inference.
160
+ codes:
161
+ - { code_range: "10-19", thai: "รถโดยสารประจำทาง", en: "scheduled passenger transport", ground: yellow }
162
+ - { code_range: "20-29", thai: "รถขนาดเล็ก", en: "small-vehicle transport", ground: yellow }
163
+ - { code_range: "30-39", thai: "รถโดยสารไม่ประจำทาง", en: "non-scheduled passenger transport", ground: yellow }
164
+ - { code_range: "40-49", thai: "รถโดยสารส่วนบุคคล", en: "private passenger transport", ground: white }
165
+ - { code_range: "60-69", thai: "รถบรรทุกไม่ประจำทาง", en: "non-scheduled goods transport", ground: yellow }
166
+ - { code_range: "70-79", thai: "รถบรรทุกไม่ประจำทาง", en: "non-scheduled goods transport — the band ADDED by the 2554 announcement because 60-69 was nearly exhausted, which the preamble states as the operative reason for the instrument", ground: yellow }
167
+ - { code_range: "50-59", thai: "รถบรรทุกส่วนบุคคล", en: "private goods transport", ground: white }
168
+ - { code_range: "80-99", thai: "รถบรรทุกส่วนบุคคล", en: "private goods transport, second band", ground: white }
169
+ serial_rule: >-
170
+ "หมายเลขทะเบียนรถใช้เลข ๔ หลัก ตั้งแต่ลำดับหมายเลข ๐๐๐๑ ถึงหมายเลข ๙๙๙๙
171
+ แล้วเริ่มต้นโดยใช้เลขรหัสแสดงประเภทรถเดิมลำดับถัดไป" — four digits, 0001 to
172
+ 9999, then the next code within the same band. Leading zeros are REQUIRED,
173
+ which inverts the usual no-leading-zero convention and is why
174
+ plates/th.yml's `regex_strict` twins forbid only 0000.
175
+ unused_band:
176
+ note: >-
177
+ The six paragraphs of ข้อ ๒ (๓) leave 00-09 unallocated and the instrument
178
+ says nothing about it. Recorded as an observation about the instrument's
179
+ face, not as a claim that no such code exists.
180
+ province_code:
181
+ mechanism: delegated
182
+ note: >-
183
+ ข้อ ๒ (๑) puts "เลขรหัสจังหวัด" (a numeric province code) on line 1 beside
184
+ the word THAILAND, at a minimum height of 2.4 cm, and does not enumerate
185
+ the codes. No code list was secured. Recorded gap — and note that this is
186
+ the ONE place Thai plate law does encode the province numerically, so the
187
+ list is worth chasing.
188
+
189
+ # ---------------------------------------------------------------------------
190
+ # 5. WHAT A CONSUMER MUST NOT DO WITH THIS FILE.
191
+ # ---------------------------------------------------------------------------
192
+ decode_semantics: >-
193
+ The province on a Thai plate is the province of REGISTRATION, and Thai plates
194
+ are not re-issued on a change of the keeper's address, so a decoded province
195
+ is a fact about where the vehicle was first put on the register — not about
196
+ where it is, where its owner lives, or where it was built. The category
197
+ letters encode a VEHICLE CLASS FAMILY and a position in an issuing sequence,
198
+ not a place: there is no geographic information in a Thai category letter at
199
+ all, and any parser that treats the two consonants as a region code is wrong.
200
+ maximal_munch: false
201
+ maximal_munch_note: >-
202
+ Not applicable to the letters: the Motor-Vehicle-Act mark has exactly two
203
+ category letters (กฎกระทรวง ข้อ ๓ (๑) (ก) ๒) names ตัวอักษรประจำหมวดตัวที่หนึ่ง
204
+ and ตัวที่สอง and no more), so the letter/number boundary is fixed. It IS a
205
+ live hazard on the commercial plate, where a bare "701234" could be read as
206
+ type code 70 + serial 1234 or as 7 + 01234; the instrument settles it by
207
+ prescribing the printed bar between the two groups and a four-digit serial,
208
+ which is why plates/th.yml writes the separator into the pattern.