e27a0678f8ef9bb4065031563555c8afcd64b0c3
[routino] / src / profiles.c
1 /***************************************
2  $Header: /home/amb/routino/src/RCS/profiles.c,v 1.42 2010/05/29 10:37:12 amb Exp $
3
4  Load the profiles from a file and the functions for handling them.
5
6  Part of the Routino routing software.
7  ******************/ /******************
8  This file Copyright 2008-2010 Andrew M. Bishop
9
10  This program is free software: you can redistribute it and/or modify
11  it under the terms of the GNU Affero General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU Affero General Public License for more details.
19
20  You should have received a copy of the GNU Affero General Public License
21  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  ***************************************/
23
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 #include "profiles.h"
30 #include "types.h"
31 #include "ways.h"
32 #include "xmlparse.h"
33 #include "functions.h"
34
35
36 /*+ The profiles that have been loaded from file. +*/
37 static Profile **loaded_profiles=NULL;
38
39 /*+ The number of profiles that have been loaded from file. +*/
40 static int nloaded_profiles=0;
41
42
43 /* The XML tag processing function prototypes */
44
45 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding);
46 //static int RoutinoProfilesType_function(const char *_tag_,int _type_);
47 static int profileType_function(const char *_tag_,int _type_,const char *name,const char *transport);
48 //static int restrictionsType_function(const char *_tag_,int _type_);
49 static int lengthType_function(const char *_tag_,int _type_,const char *limit);
50 static int widthType_function(const char *_tag_,int _type_,const char *limit);
51 static int heightType_function(const char *_tag_,int _type_,const char *limit);
52 static int weightType_function(const char *_tag_,int _type_,const char *limit);
53 //static int propertiesType_function(const char *_tag_,int _type_);
54 static int onewayType_function(const char *_tag_,int _type_,const char *obey);
55 static int propertyType_function(const char *_tag_,int _type_,const char *type,const char *percent);
56 //static int preferencesType_function(const char *_tag_,int _type_);
57 static int preferenceType_function(const char *_tag_,int _type_,const char *highway,const char *percent);
58 //static int speedsType_function(const char *_tag_,int _type_);
59 static int speedType_function(const char *_tag_,int _type_,const char *highway,const char *kph);
60
61
62 /* The XML tag definitions */
63
64 /*+ The speedType type tag. +*/
65 static xmltag speedType_tag=
66               {"speed",
67                2, {"highway","kph"},
68                speedType_function,
69                {NULL}};
70
71 /*+ The speedsType type tag. +*/
72 static xmltag speedsType_tag=
73               {"speeds",
74                0, {NULL},
75                NULL,
76                {&speedType_tag,NULL}};
77
78 /*+ The preferenceType type tag. +*/
79 static xmltag preferenceType_tag=
80               {"preference",
81                2, {"highway","percent"},
82                preferenceType_function,
83                {NULL}};
84
85 /*+ The preferencesType type tag. +*/
86 static xmltag preferencesType_tag=
87               {"preferences",
88                0, {NULL},
89                NULL,
90                {&preferenceType_tag,NULL}};
91
92 /*+ The propertyType type tag. +*/
93 static xmltag propertyType_tag=
94               {"property",
95                2, {"type","percent"},
96                propertyType_function,
97                {NULL}};
98
99 /*+ The onewayType type tag. +*/
100 static xmltag onewayType_tag=
101               {"oneway",
102                1, {"obey"},
103                onewayType_function,
104                {NULL}};
105
106 /*+ The propertiesType type tag. +*/
107 static xmltag propertiesType_tag=
108               {"properties",
109                0, {NULL},
110                NULL,
111                {&propertyType_tag,NULL}};
112
113 /*+ The weightType type tag. +*/
114 static xmltag weightType_tag=
115               {"weight",
116                1, {"limit"},
117                weightType_function,
118                {NULL}};
119
120 /*+ The heightType type tag. +*/
121 static xmltag heightType_tag=
122               {"height",
123                1, {"limit"},
124                heightType_function,
125                {NULL}};
126
127 /*+ The widthType type tag. +*/
128 static xmltag widthType_tag=
129               {"width",
130                1, {"limit"},
131                widthType_function,
132                {NULL}};
133
134 /*+ The lengthType type tag. +*/
135 static xmltag lengthType_tag=
136               {"length",
137                1, {"limit"},
138                lengthType_function,
139                {NULL}};
140
141 /*+ The restrictionsType type tag. +*/
142 static xmltag restrictionsType_tag=
143               {"restrictions",
144                0, {NULL},
145                NULL,
146                {&onewayType_tag,&weightType_tag,&heightType_tag,&widthType_tag,&lengthType_tag,NULL}};
147
148 /*+ The profileType type tag. +*/
149 static xmltag profileType_tag=
150               {"profile",
151                2, {"name","transport"},
152                profileType_function,
153                {&speedsType_tag,&preferencesType_tag,&propertiesType_tag,&restrictionsType_tag,NULL}};
154
155 /*+ The RoutinoProfilesType type tag. +*/
156 static xmltag RoutinoProfilesType_tag=
157               {"routino-profiles",
158                0, {NULL},
159                NULL,
160                {&profileType_tag,NULL}};
161
162 /*+ The xmlDeclaration type tag. +*/
163 static xmltag xmlDeclaration_tag=
164               {"xml",
165                2, {"version","encoding"},
166                NULL,
167                {NULL}};
168
169
170 /*+ The complete set of tags at the top level. +*/
171 static xmltag *xml_toplevel_tags[]={&xmlDeclaration_tag,&RoutinoProfilesType_tag,NULL};
172
173
174 /* The XML tag processing functions */
175
176
177 /*++++++++++++++++++++++++++++++++++++++
178   The function that is called when the speedType XSD type is seen
179
180   int speedType_function Returns 0 if no error occured or something else otherwise.
181
182   const char *_tag_ Set to the name of the element tag that triggered this function call.
183
184   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
185
186   const char *highway The contents of the 'highway' attribute (or NULL if not defined).
187
188   const char *kph The contents of the 'kph' attribute (or NULL if not defined).
189   ++++++++++++++++++++++++++++++++++++++*/
190
191 static int speedType_function(const char *_tag_,int _type_,const char *highway,const char *kph)
192 {
193  if(_type_&XMLPARSE_TAG_START)
194    {
195     double speed;
196     Highway highwaytype;
197
198     XMLPARSE_ASSERT_STRING(_tag_,highway);
199
200     highwaytype=HighwayType(highway);
201
202     if(highwaytype==Way_Count)
203        XMLPARSE_INVALID(_tag_,highway);
204
205     XMLPARSE_ASSERT_FLOATING(_tag_,kph,speed);
206
207     loaded_profiles[nloaded_profiles-1]->speed[highwaytype]=kph_to_speed(speed);
208    }
209
210  return(0);
211 }
212
213
214 /*++++++++++++++++++++++++++++++++++++++
215   The function that is called when the speedsType XSD type is seen
216
217   int speedsType_function Returns 0 if no error occured or something else otherwise.
218
219   const char *_tag_ Set to the name of the element tag that triggered this function call.
220
221   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
222   ++++++++++++++++++++++++++++++++++++++*/
223
224 //static int speedsType_function(const char *_tag_,int _type_)
225 //{
226 // return(0);
227 //}
228
229
230 /*++++++++++++++++++++++++++++++++++++++
231   The function that is called when the preferenceType XSD type is seen
232
233   int preferenceType_function Returns 0 if no error occured or something else otherwise.
234
235   const char *_tag_ Set to the name of the element tag that triggered this function call.
236
237   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
238
239   const char *highway The contents of the 'highway' attribute (or NULL if not defined).
240
241   const char *percent The contents of the 'percent' attribute (or NULL if not defined).
242   ++++++++++++++++++++++++++++++++++++++*/
243
244 static int preferenceType_function(const char *_tag_,int _type_,const char *highway,const char *percent)
245 {
246  if(_type_&XMLPARSE_TAG_START)
247    {
248     Highway highwaytype;
249     double p;
250
251     XMLPARSE_ASSERT_STRING(_tag_,highway);
252
253     highwaytype=HighwayType(highway);
254
255     if(highwaytype==Way_Count)
256        XMLPARSE_INVALID(_tag_,highway);
257
258     XMLPARSE_ASSERT_FLOATING(_tag_,percent,p);
259
260     loaded_profiles[nloaded_profiles-1]->highway[highwaytype]=p;
261    }
262
263  return(0);
264 }
265
266
267 /*++++++++++++++++++++++++++++++++++++++
268   The function that is called when the preferencesType XSD type is seen
269
270   int preferencesType_function Returns 0 if no error occured or something else otherwise.
271
272   const char *_tag_ Set to the name of the element tag that triggered this function call.
273
274   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
275   ++++++++++++++++++++++++++++++++++++++*/
276
277 //static int preferencesType_function(const char *_tag_,int _type_)
278 //{
279 // return(0);
280 //}
281
282
283 /*++++++++++++++++++++++++++++++++++++++
284   The function that is called when the propertyType XSD type is seen
285
286   int propertyType_function Returns 0 if no error occured or something else otherwise.
287
288   const char *_tag_ Set to the name of the element tag that triggered this function call.
289
290   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
291
292   const char *type The contents of the 'type' attribute (or NULL if not defined).
293
294   const char *percent The contents of the 'percent' attribute (or NULL if not defined).
295   ++++++++++++++++++++++++++++++++++++++*/
296
297 static int propertyType_function(const char *_tag_,int _type_,const char *type,const char *percent)
298 {
299  if(_type_&XMLPARSE_TAG_START)
300    {
301     Property property;
302     double p;
303
304     XMLPARSE_ASSERT_STRING(_tag_,type);
305
306     property=PropertyType(type);
307
308     if(property==Property_Count)
309        XMLPARSE_INVALID(_tag_,type);
310
311     XMLPARSE_ASSERT_FLOATING(_tag_,percent,p);
312
313     loaded_profiles[nloaded_profiles-1]->props_yes[property]=p;
314    }
315
316  return(0);
317 }
318
319
320 /*++++++++++++++++++++++++++++++++++++++
321   The function that is called when the onewayType XSD type is seen
322
323   int onewayType_function Returns 0 if no error occured or something else otherwise.
324
325   const char *_tag_ Set to the name of the element tag that triggered this function call.
326
327   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
328
329   const char *obey The contents of the 'obey' attribute (or NULL if not defined).
330   ++++++++++++++++++++++++++++++++++++++*/
331
332 static int onewayType_function(const char *_tag_,int _type_,const char *obey)
333 {
334  if(_type_&XMLPARSE_TAG_START)
335    {
336     int o;
337
338     XMLPARSE_ASSERT_INTEGER(_tag_,obey,o);
339
340     loaded_profiles[nloaded_profiles-1]->oneway=!!o;
341    }
342
343  return(0);
344 }
345
346
347 /*++++++++++++++++++++++++++++++++++++++
348   The function that is called when the propertiesType XSD type is seen
349
350   int propertiesType_function Returns 0 if no error occured or something else otherwise.
351
352   const char *_tag_ Set to the name of the element tag that triggered this function call.
353
354   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
355   ++++++++++++++++++++++++++++++++++++++*/
356
357 //static int propertiesType_function(const char *_tag_,int _type_)
358 //{
359 // return(0);
360 //}
361
362
363 /*++++++++++++++++++++++++++++++++++++++
364   The function that is called when the weightType XSD type is seen
365
366   int weightType_function Returns 0 if no error occured or something else otherwise.
367
368   const char *_tag_ Set to the name of the element tag that triggered this function call.
369
370   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
371
372   const char *limit The contents of the 'limit' attribute (or NULL if not defined).
373   ++++++++++++++++++++++++++++++++++++++*/
374
375 static int weightType_function(const char *_tag_,int _type_,const char *limit)
376 {
377  if(_type_&XMLPARSE_TAG_START)
378    {
379     double l;
380
381     XMLPARSE_ASSERT_FLOATING(_tag_,limit,l);
382
383     loaded_profiles[nloaded_profiles-1]->weight=tonnes_to_weight(l);
384    }
385
386  return(0);
387 }
388
389
390 /*++++++++++++++++++++++++++++++++++++++
391   The function that is called when the heightType XSD type is seen
392
393   int heightType_function Returns 0 if no error occured or something else otherwise.
394
395   const char *_tag_ Set to the name of the element tag that triggered this function call.
396
397   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
398
399   const char *limit The contents of the 'limit' attribute (or NULL if not defined).
400   ++++++++++++++++++++++++++++++++++++++*/
401
402 static int heightType_function(const char *_tag_,int _type_,const char *limit)
403 {
404  if(_type_&XMLPARSE_TAG_START)
405    {
406     double l;
407
408     XMLPARSE_ASSERT_FLOATING(_tag_,limit,l);
409
410     loaded_profiles[nloaded_profiles-1]->height=metres_to_height(l);
411    }
412
413  return(0);
414 }
415
416
417 /*++++++++++++++++++++++++++++++++++++++
418   The function that is called when the widthType XSD type is seen
419
420   int widthType_function Returns 0 if no error occured or something else otherwise.
421
422   const char *_tag_ Set to the name of the element tag that triggered this function call.
423
424   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
425
426   const char *limit The contents of the 'limit' attribute (or NULL if not defined).
427   ++++++++++++++++++++++++++++++++++++++*/
428
429 static int widthType_function(const char *_tag_,int _type_,const char *limit)
430 {
431  if(_type_&XMLPARSE_TAG_START)
432    {
433     double l;
434
435     XMLPARSE_ASSERT_FLOATING(_tag_,limit,l);
436
437     loaded_profiles[nloaded_profiles-1]->width=metres_to_width(l);
438    }
439
440  return(0);
441 }
442
443
444 /*++++++++++++++++++++++++++++++++++++++
445   The function that is called when the lengthType XSD type is seen
446
447   int lengthType_function Returns 0 if no error occured or something else otherwise.
448
449   const char *_tag_ Set to the name of the element tag that triggered this function call.
450
451   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
452
453   const char *limit The contents of the 'limit' attribute (or NULL if not defined).
454   ++++++++++++++++++++++++++++++++++++++*/
455
456 static int lengthType_function(const char *_tag_,int _type_,const char *limit)
457 {
458  if(_type_&XMLPARSE_TAG_START)
459    {
460     double l;
461
462     XMLPARSE_ASSERT_FLOATING(_tag_,limit,l);
463
464     loaded_profiles[nloaded_profiles-1]->length=metres_to_length(l);
465    }
466
467  return(0);
468 }
469
470
471 /*++++++++++++++++++++++++++++++++++++++
472   The function that is called when the restrictionsType XSD type is seen
473
474   int restrictionsType_function Returns 0 if no error occured or something else otherwise.
475
476   const char *_tag_ Set to the name of the element tag that triggered this function call.
477
478   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
479   ++++++++++++++++++++++++++++++++++++++*/
480
481 //static int restrictionsType_function(const char *_tag_,int _type_)
482 //{
483 // return(0);
484 //}
485
486
487 /*++++++++++++++++++++++++++++++++++++++
488   The function that is called when the profileType XSD type is seen
489
490   int profileType_function Returns 0 if no error occured or something else otherwise.
491
492   const char *_tag_ Set to the name of the element tag that triggered this function call.
493
494   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
495
496   const char *name The contents of the 'name' attribute (or NULL if not defined).
497
498   const char *transport The contents of the 'transport' attribute (or NULL if not defined).
499   ++++++++++++++++++++++++++++++++++++++*/
500
501 static int profileType_function(const char *_tag_,int _type_,const char *name,const char *transport)
502 {
503  if(_type_&XMLPARSE_TAG_START)
504    {
505     Transport transporttype;
506     int i;
507
508     XMLPARSE_ASSERT_STRING(_tag_,name);
509     XMLPARSE_ASSERT_STRING(_tag_,transport);
510
511     for(i=0;i<nloaded_profiles;i++)
512        if(!strcmp(name,loaded_profiles[i]->name))
513           XMLPARSE_MESSAGE(_tag_,"profile name must be unique");
514
515     transporttype=TransportType(transport);
516
517     if(transporttype==Transport_None)
518        XMLPARSE_INVALID(_tag_,transport);
519
520     if((nloaded_profiles%16)==0)
521        loaded_profiles=(Profile**)realloc((void*)loaded_profiles,(nloaded_profiles+16)*sizeof(Profile*));
522
523     nloaded_profiles++;
524
525     loaded_profiles[nloaded_profiles-1]=(Profile*)calloc(1,sizeof(Profile));
526
527     loaded_profiles[nloaded_profiles-1]->name=strcpy(malloc(strlen(name)+1),name);
528     loaded_profiles[nloaded_profiles-1]->transport=transporttype;
529    }
530
531  return(0);
532 }
533
534
535 /*++++++++++++++++++++++++++++++++++++++
536   The function that is called when the RoutinoProfilesType XSD type is seen
537
538   int RoutinoProfilesType_function Returns 0 if no error occured or something else otherwise.
539
540   const char *_tag_ Set to the name of the element tag that triggered this function call.
541
542   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
543   ++++++++++++++++++++++++++++++++++++++*/
544
545 //static int RoutinoProfilesType_function(const char *_tag_,int _type_)
546 //{
547 // return(0);
548 //}
549
550
551 /*++++++++++++++++++++++++++++++++++++++
552   The function that is called when the XML declaration is seen
553
554   int xmlDeclaration_function Returns 0 if no error occured or something else otherwise.
555
556   const char *_tag_ Set to the name of the element tag that triggered this function call.
557
558   int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
559
560   const char *version The contents of the 'version' attribute (or NULL if not defined).
561
562   const char *encoding The contents of the 'encoding' attribute (or NULL if not defined).
563   ++++++++++++++++++++++++++++++++++++++*/
564
565 //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding)
566 //{
567 // return(0);
568 //}
569
570
571 /*++++++++++++++++++++++++++++++++++++++
572   The XML profile parser.
573
574   int ParseXMLProfiles Returns 0 if OK or something else in case of an error.
575
576   const char *filename The name of the file to read.
577   ++++++++++++++++++++++++++++++++++++++*/
578
579 int ParseXMLProfiles(const char *filename)
580 {
581  int retval;
582
583  if(!ExistsFile(filename))
584    {
585     fprintf(stderr,"Error: Specified profiles file '%s' does not exist.\n",filename);
586     return(1);
587    }
588
589  FILE *file=fopen(filename,"r");
590
591  if(!file)
592    {
593     fprintf(stderr,"Error: Cannot open profiles file '%s' for reading.\n",filename);
594     return(1);
595    }
596
597  retval=ParseXML(file,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_ERRNONAME);
598
599  fclose(file);
600
601  if(retval)
602    {
603     int i;
604
605     for(i=0;i<nloaded_profiles;i++)
606        free(loaded_profiles[i]);
607     free(loaded_profiles);
608
609     nloaded_profiles=0;
610
611     return(1);
612    }
613
614  return(0);
615 }
616
617
618 /*++++++++++++++++++++++++++++++++++++++
619   Get the profile for a type of transport.
620
621   Profile *GetProfile Returns a pointer to the profile.
622
623   const char *name The name of the profile.
624   ++++++++++++++++++++++++++++++++++++++*/
625
626 Profile *GetProfile(const char *name)
627 {
628  int i;
629
630  for(i=0;i<nloaded_profiles;i++)
631     if(!strcmp(loaded_profiles[i]->name,name))
632        return(loaded_profiles[i]);
633
634  return(NULL);
635 }
636
637
638 /*++++++++++++++++++++++++++++++++++++++
639   Update a profile with highway preference scaling factor.
640
641   int UpdateProfile Returns 1 in case of a problem.
642
643   Profile *profile The profile to be updated.
644
645   Ways *ways The set of ways to use.
646   ++++++++++++++++++++++++++++++++++++++*/
647
648 int UpdateProfile(Profile *profile,Ways *ways)
649 {
650  score_t hmax=0;
651  int i;
652
653  /* Fix up the allowed transport types. */
654
655  profile->allow=ALLOWED(profile->transport);
656
657  if(!(profile->allow & ways->allow))
658     return(1);
659
660  /* Normalise the highway preferences into the range 0 -> 1 */
661
662  for(i=1;i<Way_Count;i++)
663    {
664     if(profile->highway[i]<0)
665        profile->highway[i]=0;
666
667     if(profile->highway[i]>hmax)
668        hmax=profile->highway[i];
669    }
670
671  if(hmax==0)
672     return(1);
673
674  for(i=1;i<Way_Count;i++)
675     profile->highway[i]/=hmax;
676
677  /* Normalise the property preferences into the range 0 -> 2 */
678
679  for(i=1;i<Property_Count;i++)
680    {
681     if(profile->props_yes[i]<0)
682        profile->props_yes[i]=0;
683
684     if(profile->props_yes[i]>100)
685        profile->props_yes[i]=100;
686
687     profile->props_yes[i]/=50;
688     profile->props_no [i] =2-profile->props_yes[i];
689    }
690
691  /* Find the fastest preferred speed */
692
693  profile->max_speed=0;
694
695  for(i=1;i<Way_Count;i++)
696     if(profile->speed[i]>profile->max_speed)
697        profile->max_speed=profile->speed[i];
698
699  if(profile->max_speed==0)
700     return(1);
701
702  /* Find the most preferred property combination */
703
704  profile->max_pref=1; /* since highway prefs were normalised to 1 */
705
706  for(i=1;i<Property_Count;i++)
707     if(ways->props & PROPERTIES(i))
708       {
709        if(profile->props_yes[i]>profile->props_no[i])
710           profile->max_pref*=profile->props_yes[i];
711        else
712           profile->max_pref*=profile->props_no[i];
713       }
714
715  return(0);
716 }
717
718
719 /*++++++++++++++++++++++++++++++++++++++
720   Print out a profile.
721
722   const Profile *profile The profile to print.
723   ++++++++++++++++++++++++++++++++++++++*/
724
725 void PrintProfile(const Profile *profile)
726 {
727  unsigned int i;
728
729  printf("Profile\n=======\n");
730
731  printf("\n");
732
733  printf("Transport: %s\n",TransportName(profile->transport));
734
735  printf("\n");
736
737  for(i=1;i<Way_Count;i++)
738     printf("Highway %-12s: %3d%%\n",HighwayName(i),(int)profile->highway[i]);
739
740  printf("\n");
741
742  for(i=1;i<Way_Count;i++)
743     if(profile->highway[i])
744        printf("Speed on %-12s: %3d km/h / %2.0f mph\n",HighwayName(i),profile->speed[i],(double)profile->speed[i]/1.6);
745
746  printf("\n");
747
748  for(i=1;i<Property_Count;i++)
749     printf("Highway property %-12s: %3d%%\n",PropertyName(i),(int)profile->props_yes[i]);
750
751  printf("\n");
752
753  printf("Obey one-way  : %s\n",profile->oneway?"yes":"no");
754  printf("Minimum weight: %.1f tonnes\n",weight_to_tonnes(profile->weight));
755  printf("Minimum height: %.1f metres\n",height_to_metres(profile->height));
756  printf("Minimum width : %.1f metres\n",width_to_metres(profile->width));
757  printf("Minimum length: %.1f metres\n",length_to_metres(profile->length));
758 }
759
760
761 /*++++++++++++++++++++++++++++++++++++++
762   Print out the profiles as XML for use as program input.
763   ++++++++++++++++++++++++++++++++++++++*/
764
765 void PrintProfilesXML(void)
766 {
767  unsigned int i,j;
768  char *padding="                ";
769
770  printf("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
771  printf("\n");
772
773  printf("<routino-profiles xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"routino-profiles.xsd\">\n");
774  printf("\n");
775
776  for(j=0;j<nloaded_profiles;j++)
777    {
778     printf("  <profile name=\"%s\" transport=\"%s\">\n",loaded_profiles[j]->name,TransportName(loaded_profiles[j]->transport));
779
780     printf("    <speeds>\n");
781     for(i=1;i<Way_Count;i++)
782        printf("      <speed highway=\"%s\"%s kph=\"%d\" />\n",HighwayName(i),padding+3+strlen(HighwayName(i)),loaded_profiles[j]->speed[i]);
783     printf("    </speeds>\n");
784
785     printf("    <preferences>\n");
786     for(i=1;i<Way_Count;i++)
787        printf("      <preference highway=\"%s\"%s percent=\"%.0f\" />\n",HighwayName(i),padding+3+strlen(HighwayName(i)),loaded_profiles[j]->highway[i]);
788     printf("    </preferences>\n");
789
790     printf("    <properties>\n");
791     for(i=1;i<Property_Count;i++)
792        printf("      <property type=\"%s\"%s percent=\"%.0f\" />\n",PropertyName(i),padding+6+strlen(PropertyName(i)),loaded_profiles[j]->props_yes[i]);
793     printf("    </properties>\n");
794
795     printf("    <restrictions>\n");
796     printf("      <oneway obey=\"%d\" /> \n",loaded_profiles[j]->oneway);
797     printf("      <weight limit=\"%.1f\" />\n",weight_to_tonnes(loaded_profiles[j]->weight));
798     printf("      <height limit=\"%.1f\" />\n",height_to_metres(loaded_profiles[j]->height));
799     printf("      <width  limit=\"%.1f\" />\n",width_to_metres(loaded_profiles[j]->width));
800     printf("      <length limit=\"%.1f\" />\n",length_to_metres(loaded_profiles[j]->length));
801     printf("    </restrictions>\n");
802
803     printf("  </profile>\n");
804     printf("\n");
805    }
806
807  printf("</routino-profiles>\n");
808 }
809
810
811 /*++++++++++++++++++++++++++++++++++++++
812   Print out the profiles as JavaScript Object Notation for use in a web form.
813   ++++++++++++++++++++++++++++++++++++++*/
814
815 void PrintProfilesJSON(void)
816 {
817  unsigned int i,j;
818
819  printf("var routino={ // contains all default Routino options (generated using \"--help-profile-json\").\n");
820  printf("\n");
821
822  printf("  // Default transport type\n");
823  printf("  transport: 'motorcar',\n");
824  printf("\n");
825
826  printf("  // Transport types\n");
827  printf("  transports: {");
828  for(j=0;j<nloaded_profiles;j++)
829     printf("%s%s: %d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),j);
830  printf("},\n");
831  printf("\n");
832
833  printf("  // Highway types\n");
834  printf("  highways: {");
835  for(i=1;i<Way_Count;i++)
836     printf("%s%s: %d",i==1?"":", ",HighwayName(i),i);
837  printf("},\n");
838  printf("\n");
839
840  printf("  // Property types\n");
841  printf("  properties: {");
842  for(i=1;i<Property_Count;i++)
843     printf("%s%s: %d",i==1?"":", ",PropertyName(i),i);
844  printf("},\n");
845  printf("\n");
846
847  printf("  // Restriction types\n");
848  printf("  restrictions: {oneway: 1, weight: 2, height: 3, width: 4, length: 5},\n");
849  printf("\n");
850
851  printf("  // Allowed highways\n");
852  printf("  profile_highway: {\n");
853  for(i=1;i<Way_Count;i++)
854    {
855     printf("    %12s: {",HighwayName(i));
856     for(j=0;j<nloaded_profiles;j++)
857        printf("%s%s: %3d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->highway[i]);
858     printf("}%s\n",i==(Way_Count-1)?"":",");
859    }
860  printf("     },\n");
861  printf("\n");
862
863  printf("  // Speed limits\n");
864  printf("  profile_speed: {\n");
865  for(i=1;i<Way_Count;i++)
866    {
867     printf("    %12s: {",HighwayName(i));
868     for(j=0;j<nloaded_profiles;j++)
869        printf("%s%s: %3d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->speed[i]);
870     printf("}%s\n",i==(Way_Count-1)?"":",");
871    }
872  printf("     },\n");
873  printf("\n");
874
875  printf("  // Highway properties\n");
876  printf("  profile_property: {\n");
877  for(i=1;i<Property_Count;i++)
878    {
879     printf("    %12s: {",PropertyName(i));
880     for(j=0;j<nloaded_profiles;j++)
881        printf("%s%s: %3d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->props_yes[i]);
882     printf("}%s\n",i==(Property_Count-1)?"":",");
883    }
884  printf("     },\n");
885  printf("\n");
886
887  printf("  // Restrictions\n");
888  printf("  profile_restrictions: {\n");
889  printf("    %12s: {","oneway");
890  for(j=0;j<nloaded_profiles;j++)
891     printf("%s%s: %4d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->oneway);
892  printf("},\n");
893  printf("    %12s: {","weight");
894  for(j=0;j<nloaded_profiles;j++)
895     printf("%s%s: %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),weight_to_tonnes(loaded_profiles[j]->weight));
896  printf("},\n");
897  printf("    %12s: {","height");
898  for(j=0;j<nloaded_profiles;j++)
899     printf("%s%s: %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),height_to_metres(loaded_profiles[j]->height));
900  printf("},\n");
901  printf("    %12s: {","width");
902  for(j=0;j<nloaded_profiles;j++)
903     printf("%s%s: %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),width_to_metres(loaded_profiles[j]->width));
904  printf("},\n");
905  printf("    %12s: {","length");
906  for(j=0;j<nloaded_profiles;j++)
907     printf("%s%s: %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),length_to_metres(loaded_profiles[j]->length));
908  printf("}\n");
909  printf("     }\n");
910  printf("\n");
911
912  printf("}; // end of routino variable\n");
913 }
914
915
916 /*++++++++++++++++++++++++++++++++++++++
917   Print out the profiles as Perl for use in a web CGI.
918   ++++++++++++++++++++++++++++++++++++++*/
919
920 void PrintProfilesPerl(void)
921 {
922  unsigned int i,j;
923
924  printf("$routino={ # contains all default Routino options (generated using \"--help-profile-perl\").\n");
925  printf("\n");
926
927  printf("  # Default transport type\n");
928  printf("  transport => 'motorcar',\n");
929  printf("\n");
930
931  printf("  # Transport types\n");
932  printf("  transports => {");
933  for(j=0;j<nloaded_profiles;j++)
934     printf("%s%s => %d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),j);
935  printf("},\n");
936  printf("\n");
937
938  printf("  # Highway types\n");
939  printf("  highways => {");
940  for(i=1;i<Way_Count;i++)
941     printf("%s%s => %d",i==1?"":", ",HighwayName(i),i);
942  printf("},\n");
943  printf("\n");
944
945  printf("  # Property types\n");
946  printf("  properties => {");
947  for(i=1;i<Property_Count;i++)
948     printf("%s%s => %d",i==1?"":", ",PropertyName(i),i);
949  printf("},\n");
950  printf("\n");
951
952  printf("  # Restriction types\n");
953  printf("  restrictions => {oneway => 1, weight => 2, height => 3, width => 4, length => 5},\n");
954  printf("\n");
955
956  printf("  # Allowed highways\n");
957  printf("  profile_highway => {\n");
958  for(i=1;i<Way_Count;i++)
959    {
960     printf("  %12s => {",HighwayName(i));
961     for(j=0;j<nloaded_profiles;j++)
962        printf("%s %s => %3d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->highway[i]);
963     printf("}%s\n",i==(Way_Count-1)?"":",");
964    }
965  printf("     },\n");
966  printf("\n");
967
968  printf("  # Speed limits\n");
969  printf("  profile_speed => {\n");
970  for(i=1;i<Way_Count;i++)
971    {
972     printf("  %12s => {",HighwayName(i));
973     for(j=0;j<nloaded_profiles;j++)
974        printf("%s %s => %3d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->speed[i]);
975     printf("}%s\n",i==(Way_Count-1)?"":",");
976    }
977  printf("     },\n");
978  printf("\n");
979
980  printf("  # Highway properties\n");
981  printf("  profile_property => {\n");
982  for(i=1;i<Property_Count;i++)
983    {
984     printf("  %12s => {",PropertyName(i));
985     for(j=0;j<nloaded_profiles;j++)
986        printf("%s %s => %3d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->props_yes[i]);
987     printf("}%s\n",i==(Property_Count-1)?"":",");
988    }
989  printf("     },\n");
990  printf("\n");
991
992  printf("  # Restrictions\n");
993  printf("  profile_restrictions => {\n");
994  printf("    %12s => {","oneway");
995  for(j=0;j<nloaded_profiles;j++)
996     printf("%s %s => %4d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->oneway);
997  printf("},\n");
998  printf("    %12s => {","weight");
999  for(j=0;j<nloaded_profiles;j++)
1000     printf("%s %s => %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),weight_to_tonnes(loaded_profiles[j]->weight));
1001  printf("},\n");
1002  printf("    %12s => {","height");
1003  for(j=0;j<nloaded_profiles;j++)
1004     printf("%s %s => %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),height_to_metres(loaded_profiles[j]->height));
1005  printf("},\n");
1006  printf("    %12s => {","width");
1007  for(j=0;j<nloaded_profiles;j++)
1008     printf("%s %s => %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),width_to_metres(loaded_profiles[j]->width));
1009  printf("},\n");
1010  printf("    %12s => {","length");
1011  for(j=0;j<nloaded_profiles;j++)
1012     printf("%s %s => %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),length_to_metres(loaded_profiles[j]->length));
1013  printf("}\n");
1014  printf("     },\n");
1015  printf("\n");
1016
1017  printf("}; # end of routino variable\n");
1018 }