File Coverage

blib/lib/Geo/LookupPostcode/IT.pm
Criterion Covered Total %
statement 70 77 90.9
branch 44 48 91.6
condition 111 122 90.9
subroutine 29 29 100.0
pod 1 1 100.0
total 255 277 92.0


line stmt bran cond sub pod time code
1             package Geo::LookupPostcode::IT;
2              
3 2     2   13766 use 5.012;
  2         4  
4 2     2   7 use strict;
  2         2  
  2         42  
5 2     2   7 use warnings FATAL => 'all';
  2         2  
  2         56  
6 2     2   5 use utf8;
  2         2  
  2         8  
7              
8 2     2   43 use Carp qw(croak);
  2         3  
  2         3453  
9             require Exporter;
10              
11             our @ISA = qw(Exporter);
12             our @EXPORT_OK = qw(lookup_it_postcode);
13              
14             my @geo_provinces;
15             my %lookup_table;
16              
17             =encoding utf-8
18              
19             =head1 NAME
20              
21             Geo::LookupPostcode::IT - Get province and region codes for an Italian postcode
22              
23             =head1 SUBROUTINES/METHODS
24              
25             =head2 lookup_it_postcode
26              
27             Takes one character string argument: a postcode.
28              
29             If successful, it returns a reference to a hash, with this structure:
30              
31             {
32             region_code => $region_code,
33             province_code => $province_code,
34             }
35            
36             If it cannot find the province, it returns undef.
37              
38             Note that the names may be anglicised (eg: "Vatican City", not "Città del Vaticano").
39              
40             my $rh_province = lookup_it_postcode("00118");
41              
42              
43             =cut
44              
45             sub lookup_it_postcode {
46 100002 50   100002 1 147349 croak "Expected one argument" if (@_ != 1);
47 100002         88041 my ($postcode) = @_;
48              
49             # Ensure that the UTF-8 flag is turned on, so that `lc` treats these
50             # strings as character strings.
51 100002         107743 utf8::upgrade $postcode;
52 100002         92704 $postcode = lc($postcode);
53              
54             # Do some cleanup of postcode:
55 100002         85715 utf8::upgrade $postcode;
56 100002         458735 $postcode =~ s/\s*//g;
57              
58 100002         146301 my $lookup_key = substr($postcode, 0, 3);
59              
60 100002         59423 my @results;
61 100002         62996 for my $rh_geo_entry (@{ $lookup_table{$lookup_key} }) {
  100002         157063  
62 22003         21877 local $_ = $postcode;
63 22003 100 100     46854 if (! $rh_geo_entry->{function} || $rh_geo_entry->{function}()) {
64 19269         28983 push @results, $rh_geo_entry;
65             }
66             }
67 100002 50       192798 if (@results > 1) {
    100          
68 0         0 my $provinces = join(", ", map { $_->{province} } @results);
  0         0  
69 0         0 die "Found more than one province for postcode '$postcode': $provinces ";
70             }
71             elsif (@results == 1) {
72             return {
73             region_code => $results[0]{region_code},
74             province_code => $results[0]{province_code},
75 19269         67407 };
76             }
77 80733         138050 return;
78             }
79              
80              
81             sub _build_data() {
82             # Italian data from https://en.wikipedia.org/wiki/List_of_postal_codes_in_Italy
83             @geo_provinces = (
84             {
85             'region' => 'Sicily',
86             'lookup_keys' => [ '920', '921' ],
87             'province' => 'Agrigento',
88             'province_code' => 'IT-AG'
89             },
90             {
91             'region' => 'Piedmont',
92             'lookup_keys' => [ '150', '151' ],
93             'province' => 'Alessandria',
94             'province_code' => 'IT-AL'
95             },
96             {
97             'region' => 'Marche',
98             'lookup_keys' => [ '600', '601' ],
99             'province' => 'Ancona',
100             'province_code' => 'IT-AN'
101             },
102             {
103             'region' => 'Aosta Valley',
104             'lookup_keys' => [ '110', '111' ],
105             'province' => 'Aosta',
106             'province_code' => 'IT-AO'
107             },
108             {
109             'region' => 'Marche',
110             'lookup_keys' => [ '630', '631' ],
111             'province' => 'Ascoli Piceno',
112             'province_code' => 'IT-AP'
113             },
114             {
115             'region' => 'Abruzzo',
116             'lookup_keys' => [ '670', '671' ],
117             'province' => 'L\'Aquila',
118             'province_code' => 'IT-AQ'
119             },
120             {
121             'region' => 'Tuscany',
122             'lookup_keys' => [ '520', '521' ],
123             'province' => 'Arezzo',
124             'province_code' => 'IT-AR'
125             },
126             {
127             'region' => 'Piedmont',
128             'lookup_keys' => [ '140', '141' ],
129             'province' => 'Asti',
130             'province_code' => 'IT-AT'
131             },
132             {
133             'region' => 'Campania',
134             'lookup_keys' => [ '830', '831' ],
135             'province' => 'Avellino',
136             'province_code' => 'IT-AV'
137             },
138             {
139             'region' => 'Apulia',
140             'lookup_keys' => [ '700', '701' ],
141             'province' => 'Bari',
142             'province_code' => 'IT-BA'
143             },
144             {
145             'region' => 'Lombardy',
146             'lookup_keys' => [ '240', '241' ],
147             'province' => 'Bergamo',
148             'province_code' => 'IT-BG'
149             },
150             {
151             'region' => 'Piedmont',
152             'lookup_keys' => [ '138', '139' ],
153             'province' => 'Biella',
154             'province_code' => 'IT-BI'
155             },
156             {
157             'region' => 'Veneto',
158             'lookup_keys' => [ '320', '321' ],
159             'province' => 'Belluno',
160             'province_code' => 'IT-BL'
161             },
162             {
163             'region' => 'Campania',
164             'comment' => 'Province could also be Beneventum',
165             'lookup_keys' => [ '820', '821' ],
166             'province' => 'Benevento',
167             'province_code' => 'IT-BN'
168             },
169             {
170             'region' => 'Emilia-Romagna',
171             'lookup_keys' => [ '400', '401' ],
172             'province' => 'Bologna',
173             'province_code' => 'IT-BO'
174             },
175             {
176             'region' => 'Apulia',
177             'lookup_keys' => [ '720', '721' ],
178             'province' => 'Brindisi',
179             'province_code' => 'IT-BR'
180             },
181             {
182             'region' => 'Lombardy',
183             'lookup_keys' => [ '250', '251' ],
184             'province' => 'Brescia',
185             'province_code' => 'IT-BS'
186             },
187             {
188             'region' => 'Apulia',
189             'lookup_keys' => [ '760', '761' ],
190             'province' => 'Barletta-Andria-Trani',
191             'province_code' => 'IT-BT'
192             },
193             {
194             'region' => 'Trentino-Alto Adige/Südtirol',
195             'lookup_keys' => [ '390', '391' ],
196             'province' => 'Bolzano/Bozen',
197             'province_code' => 'IT-BZ'
198             },
199             {
200             'region' => 'Sardinia',
201 300 100 100 300   4010 'function' => sub { ($_ >= 9121 && $_ <= 9134) || ($_ >= 9018 && $_ <= 9019) || ($_ >= 9042 && $_ <= 9049) || $_ == 8030 || $_ == 8033 || $_ == 8035 || $_ == 8043 },
      100        
      66        
      100        
      66        
      100        
      100        
      100        
202             'lookup_keys' => [ '080', '090', '091' ],
203             'province' => 'Cagliari',
204             'province_code' => 'IT-CA',
205             'comment' => 'Remove 09010 to 09017 because it conflicts with Carbonia-Iglesias, and 09020 to 09041 because it conflicts with Medio Campidano',
206             },
207             {
208             'region' => 'Molise',
209 200 100 100 200   1128 'function' => sub { $_ == 86100 || ($_ >= 86010 && $_ <= 86049) },
210             'lookup_keys' => [ '860', '861' ],
211             'province' => 'Campobasso',
212             'province_code' => 'IT-CB'
213             },
214             {
215             'region' => 'Campania',
216             'lookup_keys' => [ '810', '811' ],
217             'province' => 'Caserta',
218             'province_code' => 'IT-CE'
219             },
220             {
221             'region' => 'Abruzzo',
222             'lookup_keys' => [ '660', '661' ],
223             'province' => 'Chieti',
224             'province_code' => 'IT-CH'
225             },
226             {
227             'region' => 'Sardinia',
228 100 100   100   430 'function' => sub { $_ >= 9010 && $_ <= 9017 },
229             'lookup_keys' => [ '090' ],
230             'province' => 'Carbonia-Iglesias',
231             'province_code' => 'IT-CI'
232             },
233             {
234             'region' => 'Sicily',
235             'lookup_keys' => [ '930', '931' ],
236             'province' => 'Caltanissetta',
237             'province_code' => 'IT-CL'
238             },
239             {
240             'region' => 'Piedmont',
241             'lookup_keys' => [ '120', '121' ],
242             'province' => 'Cuneo',
243             'province_code' => 'IT-CN'
244             },
245             {
246             'region' => 'Lombardy',
247             'lookup_keys' => [ '220', '221' ],
248             'province' => 'Como',
249             'province_code' => 'IT-CO'
250             },
251             {
252             'region' => 'Lombardy',
253             'lookup_keys' => [ '260', '261' ],
254             'province' => 'Cremona',
255             'province_code' => 'IT-CR'
256             },
257             {
258             'region' => 'Calabria',
259             'lookup_keys' => [ '870', '871' ],
260             'province' => 'Cosenza',
261             'province_code' => 'IT-CS'
262             },
263             {
264             'region' => 'Sicily',
265             'lookup_keys' => [ '950', '951' ],
266             'province' => 'Catania',
267             'province_code' => 'IT-CT'
268             },
269             {
270             'region' => 'Calabria',
271             'lookup_keys' => [ '880', '881' ],
272             'province' => 'Catanzaro',
273             'province_code' => 'IT-CZ'
274             },
275             {
276             'region' => 'Sicily',
277             'lookup_keys' => [ '940', '941' ],
278             'province' => 'Enna',
279             'province_code' => 'IT-EN'
280             },
281             {
282             'region' => 'Emilia-Romagna',
283             'lookup_keys' => [ '470', '471' ],
284             'province' => 'Forl�-Cesena',
285             'province_code' => 'IT-FC'
286             },
287             {
288             'region' => 'Emilia-Romagna',
289             'lookup_keys' => [ '440', '441' ],
290             'province' => 'Ferrara',
291             'province_code' => 'IT-FE'
292             },
293             {
294             'region' => 'Apulia',
295             'lookup_keys' => [ '710', '711' ],
296             'province' => 'Foggia',
297             'province_code' => 'IT-FG'
298             },
299             {
300             'region' => 'Tuscany',
301             'lookup_keys' => [ '500', '501' ],
302             'province' => 'Florence',
303             'province_code' => 'IT-FI'
304             },
305             {
306             'region' => 'Marche',
307             'lookup_keys' => [ '638', '639' ],
308             'province' => 'Fermo',
309             'province_code' => 'IT-FM'
310             },
311             {
312             'region' => 'Lazio',
313             'lookup_keys' => [ '030', '031' ],
314             'province' => 'Frosinone',
315             'province_code' => 'IT-FR'
316             },
317             {
318             'region' => 'Liguria',
319             'lookup_keys' => [ '160', '161' ],
320             'province' => 'Genoa',
321             'province_code' => 'IT-GE'
322             },
323             {
324             'region' => 'Friuli-Venezia Giulia',
325 200 100 33 200   815 'function' => sub { $_ == 34170 && ($_ >= 34070 && $_ <= 34079) },
326             'lookup_keys' => [ '340', '341' ],
327             'province' => 'Gorizia',
328             'province_code' => 'IT-GO'
329             },
330             {
331             'region' => 'Tuscany',
332             'lookup_keys' => [ '580', '581' ],
333             'province' => 'Grosseto',
334             'province_code' => 'IT-GR'
335             },
336             {
337             'region' => 'Liguria',
338             'lookup_keys' => [ '180', '181' ],
339             'province' => 'Imperia',
340             'province_code' => 'IT-IM'
341             },
342             {
343             'region' => 'Molise',
344 200 100 100 200   888 'function' => sub { $_ == 86170 || ($_ >= 86070 && $_ <= 86097) },
345             'lookup_keys' => [ '860', '861' ],
346             'province' => 'Isernia',
347             'province_code' => 'IT-IS'
348             },
349             {
350             'region' => 'Calabria',
351             'lookup_keys' => [ '888', '889' ],
352             'province' => 'Crotone',
353             'province_code' => 'IT-KR'
354             },
355             {
356             'region' => 'Lombardy',
357             'lookup_keys' => [ '238', '239' ],
358             'province' => 'Lecco',
359             'province_code' => 'IT-LC'
360             },
361             {
362             'region' => 'Apulia',
363             'lookup_keys' => [ '730', '731' ],
364             'province' => 'Lecce',
365             'province_code' => 'IT-LE'
366             },
367             {
368             'region' => 'Tuscany',
369             'comment' => 'Province could also be Leghorn',
370             'lookup_keys' => [ '570', '571' ],
371             'province' => 'Livorno',
372             'province_code' => 'IT-LI'
373             },
374             {
375             'region' => 'Lombardy',
376             'lookup_keys' => [ '268', '269' ],
377             'province' => 'Lodi',
378             'province_code' => 'IT-LO'
379             },
380             {
381             'region' => 'Lazio',
382             'lookup_keys' => [ '040', '041' ],
383             'province' => 'Latina',
384             'province_code' => 'IT-LT'
385             },
386             {
387             'region' => 'Tuscany',
388             'lookup_keys' => [ '550', '551' ],
389             'province' => 'Lucca',
390             'province_code' => 'IT-LU'
391             },
392             {
393             'region' => 'Lombardy',
394             'lookup_keys' => [ '208', '209' ],
395             'province' => 'Monza & Brianza',
396             'province_code' => 'IT-MB'
397             },
398             {
399             'region' => 'Marche',
400             'lookup_keys' => [ '620', '621' ],
401             'province' => 'Macerata',
402             'province_code' => 'IT-MC'
403             },
404             {
405             'region' => 'Sardinia',
406 100 100   100   377 'function' => sub { $_ >= 9020 && $_ <= 9041 },
407             'comment' => 'Provisional code MD modified in VS from December 2006.',
408             'lookup_keys' => [ '090' ],
409             'province' => 'Medio Campidano',
410             'province_code' => 'IT-MD',
411             },
412             {
413             'region' => 'Sicily',
414             'lookup_keys' => [ '980', '981' ],
415             'province' => 'Messina',
416             'province_code' => 'IT-ME'
417             },
418             {
419             'region' => 'Lombardy',
420             'lookup_keys' => [ '200', '201' ],
421             'province' => 'Milan',
422             'province_code' => 'IT-MI'
423             },
424             {
425             'region' => 'Lombardy',
426             'lookup_keys' => [ '460', '461' ],
427             'province' => 'Mantua',
428             'province_code' => 'IT-MN'
429             },
430             {
431             'region' => 'Emilia-Romagna',
432             'lookup_keys' => [ '410', '411' ],
433             'province' => 'Modena',
434             'province_code' => 'IT-MO'
435             },
436             {
437             'region' => 'Tuscany',
438             'lookup_keys' => [ '541', '750' ],
439             'province' => 'Massa-Carrara',
440             'province_code' => 'IT-MS'
441             },
442             {
443             'region' => 'Basilicata',
444             'lookup_keys' => [ '751', '80750' ],
445             'province' => 'Matera',
446             'province_code' => 'IT-MT'
447             },
448             {
449             'region' => 'Campania',
450             'lookup_keys' => [ '800', '801' ],
451             'province' => 'Naples',
452             'province_code' => 'IT-NA'
453             },
454             {
455             'region' => 'Piedmont',
456             'lookup_keys' => [ '280', '281' ],
457             'province' => 'Novara',
458             'province_code' => 'IT-NO'
459             },
460             {
461             'region' => 'Sardinia',
462 200 100 100 200   2465 'function' => sub { $_ == 8100 || $_ == 8012 || ($_ >= 8014 && $_ <= 8018) || ($_ >= 8021 && $_ <= 8029) || ($_ >= 8031 && $_ <= 8032) || ($_ >= 8036 && $_ <= 8039) },
      100        
      100        
      66        
      100        
      66        
      100        
      66        
463             'lookup_keys' => [ '080', '081' ],
464             'province' => 'Nuoro',
465             'province_code' => 'IT-NU',
466             'comment' => 'Removed 08010, 08013, 08019, 08020 and 08034 as these conflict with Oristano, and 08030, 08033 and 08035 as these conflict with Cagliari',
467             },
468             {
469             'region' => 'Sardinia',
470 100 100 100 100   424 'function' => sub { $_ >= 8040 && $_ <= 8049 && $_ != 8043 },
471             'lookup_keys' => [ '080' ],
472             'province' => 'Ogliastra',
473             'province_code' => 'IT-OG',
474             'comment' => 'Removed 08043 because it conflicts with Cagliari',
475             },
476             {
477             'region' => 'Sardinia',
478 300 100 100 300   2976 'function' => sub { $_ == 9170 || ($_ >= 9070 && $_ <= 9099) || $_ == 8010 || $_ == 8013 || $_ == 8019 || $_ == 8034 },
      66        
      100        
      100        
      100        
479             'lookup_keys' => [ '080', '090', '091' ],
480             'province' => 'Oristano',
481             'province_code' => 'IT-OR',
482             'comment' => 'Remove 08030 because this conflicts with Cagliari',
483             },
484             {
485             'region' => 'Sardinia',
486 200 100 100 200   1543 'function' => sub { ($_ >= 7020 && $_ <= 7029) || $_ == 8020 },
487             'lookup_keys' => [ '070', '080' ],
488             'province' => 'Olbia-Tempio',
489             'province_code' => 'IT-OT'
490             },
491             {
492             'region' => 'Sicily',
493             'lookup_keys' => [ '900', '901' ],
494             'province' => 'Palermo',
495             'province_code' => 'IT-PA'
496             },
497             {
498             'region' => 'Emilia-Romagna',
499             'lookup_keys' => [ '290', '291' ],
500             'province' => 'Piacenza',
501             'province_code' => 'IT-PC'
502             },
503             {
504             'region' => 'Veneto',
505             'lookup_keys' => [ '350', '351' ],
506             'province' => 'Padua',
507             'province_code' => 'IT-PD'
508             },
509             {
510             'region' => 'Abruzzo',
511             'lookup_keys' => [ '650', '651' ],
512             'province' => 'Pescara',
513             'province_code' => 'IT-PE'
514             },
515             {
516             'region' => 'Umbria',
517             'lookup_keys' => [ '060', '061' ],
518             'province' => 'Perugia',
519             'province_code' => 'IT-PG'
520             },
521             {
522             'region' => 'Tuscany',
523             'lookup_keys' => [ '560', '561' ],
524             'province' => 'Pisa',
525             'province_code' => 'IT-PI'
526             },
527             {
528             'region' => 'Friuli-Venezia Giulia',
529 200 100 100 200   1061 'function' => sub { $_ == 33170 || ($_ >= 33070 && $_ <= 33099) },
530             'lookup_keys' => [ '330', '331' ],
531             'province' => 'Pordenone',
532             'province_code' => 'IT-PN'
533             },
534             {
535             'region' => 'Tuscany',
536             'lookup_keys' => [ '590', '591' ],
537             'province' => 'Prato',
538             'province_code' => 'IT-PO'
539             },
540             {
541             'region' => 'Emilia-Romagna',
542             'lookup_keys' => [ '430', '431' ],
543             'province' => 'Parma',
544             'province_code' => 'IT-PR'
545             },
546             {
547             'region' => 'Tuscany',
548             'lookup_keys' => [ '510', '511' ],
549             'province' => 'Pistoia',
550             'province_code' => 'IT-PT'
551             },
552             {
553             'region' => 'Marche',
554             'lookup_keys' => [ '610', '611' ],
555             'province' => 'Pesaro e Urbino',
556             'province_code' => 'IT-PU'
557             },
558             {
559             'region' => 'Lombardy',
560             'lookup_keys' => [ '270', '271' ],
561             'province' => 'Pavia',
562             'province_code' => 'IT-PV'
563             },
564             {
565             'region' => 'Basilicata',
566             'lookup_keys' => [ '850', '851' ],
567             'province' => 'Potenza',
568             'province_code' => 'IT-PZ'
569             },
570             {
571             'region' => 'Emilia-Romagna',
572             'lookup_keys' => [ '480', '481' ],
573             'province' => 'Ravenna',
574             'province_code' => 'IT-RA'
575             },
576             {
577             'region' => 'Calabria',
578             'lookup_keys' => [ '890', '891' ],
579             'province' => 'Reggio Calabria',
580             'province_code' => 'IT-RC'
581             },
582             {
583             'region' => 'Emilia-Romagna',
584             'lookup_keys' => [ '420', '421' ],
585             'province' => 'Reggio Emilia',
586             'province_code' => 'IT-RE'
587             },
588             {
589             'region' => 'Sicily',
590             'lookup_keys' => [ '970', '971' ],
591             'province' => 'Ragusa',
592             'province_code' => 'IT-RG'
593             },
594             {
595             'region' => 'Lazio',
596             'lookup_keys' => [ '020', '021' ],
597             'province' => 'Rieti',
598             'province_code' => 'IT-RI'
599             },
600             {
601             'region' => 'Lazio',
602 201 100 100 201   1565 'function' => sub { ($_ >= 118 && $_ <= 119) || ($_ >= 121 && $_ <= 199) || ($_ >= 10 && $_ <= 69) },
      100        
      66        
      66        
603             'lookup_keys' => [ '000', '001' ],
604             'province' => 'Rome',
605             'province_code' => 'IT-RM'
606             },
607             {
608             'region' => 'Emilia-Romagna',
609 200 100 100 200   1390 'function' => sub { ($_ >= 47921 && $_ <= 47924) || ($_ >= 47814 && $_ <= 47866) },
      100        
610             'lookup_keys' => [ '478', '479' ],
611             'province' => 'Rimini',
612             'province_code' => 'IT-RN'
613             },
614             {
615             'region' => 'Veneto',
616             'lookup_keys' => [ '450', '451' ],
617             'province' => 'Rovigo',
618             'province_code' => 'IT-RO'
619             },
620             {
621             'region' => '-',
622 100 100   100   373 'function' => sub { $_ >= 47890 && $_ <= 47899 },
623             'lookup_keys' => [ '478' ],
624             'province' => 'Republic of San Marino',
625             'province_code' => 'IT-RSM'
626             },
627             {
628             'region' => 'Campania',
629             'lookup_keys' => [ '840', '841' ],
630             'province' => 'Salerno',
631             'province_code' => 'IT-SA'
632             },
633             {
634             'region' => '-',
635 102     102   295 'function' => sub { $_ == 120 },
636             'lookup_keys' => [ '001' ],
637             'province' => 'Vatican City',
638             'province_code' => 'IT-SCV'
639             },
640             {
641             'region' => 'Tuscany',
642             'lookup_keys' => [ '530', '531' ],
643             'province' => 'Siena',
644             'province_code' => 'IT-SI'
645             },
646             {
647             'region' => 'Lombardy',
648             'lookup_keys' => [ '230', '231' ],
649             'province' => 'Sondrio',
650             'province_code' => 'IT-SO'
651             },
652             {
653             'region' => 'Liguria',
654             'lookup_keys' => [ '190', '191' ],
655             'province' => 'La Spezia',
656             'province_code' => 'IT-SP'
657             },
658             {
659             'region' => 'Sicily',
660             'lookup_keys' => [ '960', '961' ],
661             'province' => 'Syracuse',
662             'province_code' => 'IT-SR'
663             },
664             {
665             'region' => 'Sardinia',
666 200 100 100 200   2039 'function' => sub { $_ == 7100 || ($_ >= 7010 && $_ <= 7019) || ($_ >= 7030 && $_ <= 7049) },
      100        
      66        
667             'lookup_keys' => [ '070', '071' ],
668             'province' => 'Sassari',
669             'province_code' => 'IT-SS'
670             },
671             {
672             'region' => 'Liguria',
673             'lookup_keys' => [ '170', '171' ],
674             'province' => 'Savona',
675             'province_code' => 'IT-SV'
676             },
677             {
678             'region' => 'Apulia',
679             'lookup_keys' => [ '740', '741' ],
680             'province' => 'Taranto',
681             'province_code' => 'IT-TA'
682             },
683             {
684             'region' => 'Abruzzo',
685             'lookup_keys' => [ '640', '641' ],
686             'province' => 'Teramo',
687             'province_code' => 'IT-TE'
688             },
689             {
690             'region' => 'Trentino-Alto Adige/Südtirol',
691             'lookup_keys' => [ '380', '381' ],
692             'province' => 'Trento',
693             'province_code' => 'IT-TN'
694             },
695             {
696             'region' => 'Piedmont',
697             'lookup_keys' => [ '100', '101' ],
698             'province' => 'Turin',
699             'province_code' => 'IT-TO'
700             },
701             {
702             'region' => 'Sicily',
703             'lookup_keys' => [ '910', '911' ],
704             'province' => 'Trapani',
705             'province_code' => 'IT-TP'
706             },
707             {
708             'region' => 'Umbria',
709             'lookup_keys' => [ '050', '051' ],
710             'province' => 'Terni',
711             'province_code' => 'IT-TR'
712             },
713             {
714             'region' => 'Friuli-Venezia Giulia',
715 200 100 100 200   1027 'function' => sub { ($_ >= 34121 && $_ <= 34151) || ($_ >= 34010 && $_ <= 34018) },
      100        
716             'lookup_keys' => [ '340', '341' ],
717             'province' => 'Trieste',
718             'province_code' => 'IT-TS'
719             },
720             {
721             'region' => 'Veneto',
722             'lookup_keys' => [ '310', '311' ],
723             'province' => 'Treviso',
724             'province_code' => 'IT-TV'
725             },
726             {
727             'region' => 'Friuli-Venezia Giulia',
728 200 100 100 200   936 'function' => sub { $_ == 33100 || ($_ >= 33010 && $_ <= 33059) },
729 2     2   356 'lookup_keys' => [ '330', '331' ],
730             'province' => 'Udine',
731             'province_code' => 'IT-UD'
732             },
733             {
734             'region' => 'Lombardy',
735             'lookup_keys' => [ '210', '211' ],
736             'province' => 'Varese',
737             'province_code' => 'IT-VA'
738             },
739             {
740             'region' => 'Piedmont',
741             'lookup_keys' => [ '288', '289' ],
742             'province' => 'Verbano-Cusio-Ossola',
743             'province_code' => 'IT-VB'
744             },
745             {
746             'region' => 'Piedmont',
747             'lookup_keys' => [ '130', '131' ],
748             'province' => 'Vercelli',
749             'province_code' => 'IT-VC'
750             },
751             {
752             'region' => 'Veneto',
753             'lookup_keys' => [ '300', '301' ],
754             'province' => 'Venice',
755             'province_code' => 'IT-VE'
756             },
757             {
758             'region' => 'Veneto',
759             'lookup_keys' => [ '360', '361' ],
760             'province' => 'Vicenza',
761             'province_code' => 'IT-VI'
762             },
763             {
764             'region' => 'Veneto',
765             'lookup_keys' => [ '370', '371' ],
766             'province' => 'Verona',
767             'province_code' => 'IT-VR'
768             },
769             {
770             'region' => 'Lazio',
771             'lookup_keys' => [ '010', '011' ],
772             'province' => 'Viterbo',
773             'province_code' => 'IT-VT'
774             },
775             {
776             'region' => 'Calabria',
777             'lookup_keys' => [ '898', '899' ],
778             'province' => 'Vibo Valentia',
779             'province_code' => 'IT-VV'
780             },
781             );
782 2         36 my %geo_regions = (
783             # Take from https://en.wikipedia.org/wiki/ISO_3166-2:IT
784             'Abruzzo' => 'IT-65',
785             'Basilicata' => 'IT-77',
786             'Calabria' => 'IT-78',
787             'Campania' => 'IT-72',
788             'Emilia-Romagna' => 'IT-45',
789             'Friuli-Venezia Giulia' => 'IT-36',
790             'Lazio' => 'IT-62',
791             'Liguria' => 'IT-42',
792             'Lombardy' => 'IT-25',
793             'Marche' => 'IT-57',
794             'Molise' => 'IT-67',
795             'Piedmont' => 'IT-21',
796             'Apulia' => 'IT-75',
797             'Sardinia' => 'IT-88',
798             'Sicily' => 'IT-82',
799             'Tuscany' => 'IT-52',
800             'Trentino-Alto Adige/Südtirol' => 'IT-32',
801             'Umbria' => 'IT-55',
802             'Aosta Valley' => 'IT-23',
803             'Veneto' => 'IT-34',
804             '-' => '-', # For the Vatican and San Marino
805             );
806 2         3 %lookup_table = ();
807 2         4 for my $rh_geo_entry (@geo_provinces) {
808 224         215 $rh_geo_entry->{region_code} = $geo_regions{$rh_geo_entry->{region}};
809 224         122 for my $key (@{ $rh_geo_entry->{lookup_keys} }) {
  224         196  
810 442   100     1054 $lookup_table{$key} //= [];
811 442         251 push @{ $lookup_table{$key} }, $rh_geo_entry;
  442         511  
812             }
813             }
814              
815             }
816              
817             sub _test_check_lookup_table {
818             # This test is written here, instead of in a .t file, as only it has access
819             # to the private variable %lookup_table
820 1     1   7732 require Test::More;
821 1         91 for my $key (sort keys %lookup_table) {
822 204 100       113 if (@{ $lookup_table{$key} } >= 2) {
  204         268  
823 12 50   29   16 if (! _all(sub { $_->{function} }, @{ $lookup_table{$key} })) {
  29         55  
  12         17  
824             my $provinces_string = join(", ",
825 0         0 map { $_->{province} } @{ $lookup_table{$key} }
  0         0  
  0         0  
826             );
827 0         0 Test::More::fail("Lookup key '$key' in country IT has multiple provinces $provinces_string but missing functions to distinguish between them. ");
828             }
829             }
830             }
831             }
832              
833             sub _all {
834 12     12   10 my $rc_sub = shift;
835 12         11 for (@_) {
836 29 50       21 return 0 if ! $rc_sub->();
837             }
838 12         21 return 1;
839             }
840              
841             BEGIN {
842 2     2   5 _build_data();
843             }
844              
845             1;