Class: Vehicles::Plates::Series
- Inherits:
-
Object
- Object
- Vehicles::Plates::Series
- Defined in:
- lib/vehicles/plates/series.rb
Overview
One registration series: a pattern identity with a period, a class
(standard/taxi/diplomatic/…), categories, sourced design facts, and the
two regexes of the dataset's regex policy — regex (recall: the
pattern's own alphabet) and regex_strict (validation: the alphabet
the authority actually issues). Validation prefers strict.
Constant Summary collapse
- SEPARATOR_TOKENS =
Tokens that read as "a separator" when they make up a whole character class —
[- ]in the ES consular series is dash-or-space, i.e. a separator spelled as a class. [ " ", "-", "·", ".", '\s', '\-', '\.', '\ ' ].freeze
Instance Attribute Summary collapse
-
#categories ⇒ Object
readonly
Returns the value of attribute categories.
-
#design ⇒ Object
readonly
Returns the value of attribute design.
-
#id ⇒ Object
readonly
Returns the value of attribute id.
-
#klass ⇒ Object
readonly
Returns the value of attribute klass.
-
#lenient_regexp ⇒ Object
readonly
Returns the value of attribute lenient_regexp.
-
#notes ⇒ Object
readonly
Returns the value of attribute notes.
-
#pattern ⇒ Object
readonly
Returns the value of attribute pattern.
-
#period ⇒ Object
readonly
Returns the value of attribute period.
-
#regex ⇒ Object
readonly
Returns the value of attribute regex.
-
#regex_strict ⇒ Object
readonly
Returns the value of attribute regex_strict.
-
#sources ⇒ Object
readonly
Returns the value of attribute sources.
-
#validation_regexp ⇒ Object
readonly
Returns the value of attribute validation_regexp.
-
#variants ⇒ Object
readonly
Returns the value of attribute variants.
Class Method Summary collapse
-
.strip_separators(src) ⇒ Object
Remove separator LITERALS from a regex source, respecting character classes (the "-" inside [A-Z] is a range, not a separator; a class composed ONLY of separators, like
[- ], is a separator and goes).
Instance Method Summary collapse
-
#format_serial(serial) ⇒ Object
Re-print a separator-less serial the way this series formats it: walk the pattern; 9/L and literal serial characters consume one input character, separator characters re-emerge from the pattern itself.
-
#initialize(entry) ⇒ Series
constructor
A new instance of Series.
- #inspect ⇒ Object
-
#period_label ⇒ Object
"2000 →" (open, runs until exhausted) or "1971–2000".
-
#strict? ⇒ Boolean
A strict-validated series has an authority-alphabet regex twin; a recall-only series (export/dark-blue catch-alls that accept any current shape) matches loosely by design.
Constructor Details
#initialize(entry) ⇒ Series
Returns a new instance of Series.
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/vehicles/plates/series.rb', line 15 def initialize(entry) @id = entry["id"] @klass = entry["class"] || "standard" @categories = Array(entry["categories"]).freeze @period = (entry["period"] || {}).freeze @pattern = entry.dig("format", "pattern") @regex = entry.dig("format", "regex") @regex_strict = entry.dig("format", "regex_strict") @design = (entry["design"] || {}).freeze @variants = Array(entry["variants"]).freeze @sources = Array(entry["sources"]).freeze @notes = entry["notes"] # Compiled eagerly — the object is frozen, so no lazy memoization. @validation_regexp = compile(@regex_strict || @regex) @lenient_regexp = compile(self.class.strip_separators(@regex_strict || @regex)) freeze end |
Instance Attribute Details
#categories ⇒ Object (readonly)
Returns the value of attribute categories.
11 12 13 |
# File 'lib/vehicles/plates/series.rb', line 11 def categories @categories end |
#design ⇒ Object (readonly)
Returns the value of attribute design.
11 12 13 |
# File 'lib/vehicles/plates/series.rb', line 11 def design @design end |
#id ⇒ Object (readonly)
Returns the value of attribute id.
11 12 13 |
# File 'lib/vehicles/plates/series.rb', line 11 def id @id end |
#klass ⇒ Object (readonly)
Returns the value of attribute klass.
11 12 13 |
# File 'lib/vehicles/plates/series.rb', line 11 def klass @klass end |
#lenient_regexp ⇒ Object (readonly)
Returns the value of attribute lenient_regexp.
11 12 13 |
# File 'lib/vehicles/plates/series.rb', line 11 def lenient_regexp @lenient_regexp end |
#notes ⇒ Object (readonly)
Returns the value of attribute notes.
11 12 13 |
# File 'lib/vehicles/plates/series.rb', line 11 def notes @notes end |
#pattern ⇒ Object (readonly)
Returns the value of attribute pattern.
11 12 13 |
# File 'lib/vehicles/plates/series.rb', line 11 def pattern @pattern end |
#period ⇒ Object (readonly)
Returns the value of attribute period.
11 12 13 |
# File 'lib/vehicles/plates/series.rb', line 11 def period @period end |
#regex ⇒ Object (readonly)
Returns the value of attribute regex.
11 12 13 |
# File 'lib/vehicles/plates/series.rb', line 11 def regex @regex end |
#regex_strict ⇒ Object (readonly)
Returns the value of attribute regex_strict.
11 12 13 |
# File 'lib/vehicles/plates/series.rb', line 11 def regex_strict @regex_strict end |
#sources ⇒ Object (readonly)
Returns the value of attribute sources.
11 12 13 |
# File 'lib/vehicles/plates/series.rb', line 11 def sources @sources end |
#validation_regexp ⇒ Object (readonly)
Returns the value of attribute validation_regexp.
11 12 13 |
# File 'lib/vehicles/plates/series.rb', line 11 def validation_regexp @validation_regexp end |
#variants ⇒ Object (readonly)
Returns the value of attribute variants.
11 12 13 |
# File 'lib/vehicles/plates/series.rb', line 11 def variants @variants end |
Class Method Details
.strip_separators(src) ⇒ Object
Remove separator LITERALS from a regex source, respecting character
classes (the "-" inside [A-Z] is a range, not a separator; a class
composed ONLY of separators, like [- ], is a separator and goes).
A quantifier left dangling by a removed separator ("-?", "[- ]?") is
swallowed with it. Linear scan — regexes in this dataset are simple.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/vehicles/plates/series.rb', line 75 def self.strip_separators(src) return nil if src.nil? out = +"" chars = src.chars i = 0 while i < chars.size ch = chars[i] if ch == "\\" && i + 1 < chars.size nxt = chars[i + 1] if [ "s", "-", ".", " " ].include?(nxt) i += 2 i += 1 if [ "?", "*" ].include?(chars[i]) # optional separator: drop its quantifier too else out << ch << nxt i += 2 end next end if ch == "[" # Copy or drop the WHOLE class span in one decision. closing = i + 1 closing += 1 while closing < chars.size && chars[closing] != "]" content = chars[(i + 1)...closing].join tokens = content.scan(/\\.|./m) if tokens.any? && tokens.all? { |t| SEPARATOR_TOKENS.include?(t) } i = closing + 1 i += 1 if [ "?", "*" ].include?(chars[i]) else out << chars[i..closing].join i = closing + 1 end next end if [ "-", " ", "·" ].include?(ch) i += 1 i += 1 if [ "?", "*" ].include?(chars[i]) else out << ch i += 1 end end out end |
Instance Method Details
#format_serial(serial) ⇒ Object
Re-print a separator-less serial the way this series formats it: walk the pattern; 9/L and literal serial characters consume one input character, separator characters re-emerge from the pattern itself.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/vehicles/plates/series.rb', line 50 def format_serial(serial) return nil if serial.nil? || pattern.nil? idx = 0 out = pattern.each_char.with_object(+"") do |ch, str| if [ "-", " ", "·", "." ].include?(ch) str << ch else str << (serial[idx] || "") idx += 1 end end out.freeze end |
#inspect ⇒ Object
123 |
# File 'lib/vehicles/plates/series.rb', line 123 def inspect = %(#<Vehicles::Plates::Series #{id} "#{pattern}">) |
#period_label ⇒ Object
"2000 →" (open, runs until exhausted) or "1971–2000".
42 43 44 45 |
# File 'lib/vehicles/plates/series.rb', line 42 def period_label finish = period["end"] finish ? "#{period["start"]}–#{finish}" : "#{period["start"]} →" end |
#strict? ⇒ Boolean
A strict-validated series has an authority-alphabet regex twin; a recall-only series (export/dark-blue catch-alls that accept any current shape) matches loosely by design. Consumers validating user input should weight strict hits above recall-only ones — Match does.
37 38 39 |
# File 'lib/vehicles/plates/series.rb', line 37 def strict? !regex_strict.nil? end |