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