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