/* Prino's hitchhike statistics extraction program */
/**********************************************************************
* (C) Copyright Robert AH Prins, 1993-2022 *
***********************************************************************
* LIFT is a program to produce statistics for a dataset containing *
* hitchhike data. *
* *
* The program produces seven output datasets: *
* *
* 1. A summary dataset (DD: SUMMOUT) containing the following tables: *
* *
* 1) two tables of totals for every trip *
* - per individual trip *
* ------------------------------------------------------------- *
* - as a running cumulative total *
* ---------------------------------------------------------------- *
* 2) a table of totals for all distances *
* 3) a table of totals for all types *
* 4) a table of totals for all countries *
* ---------------------------------------------------------------- *
* 5) a table of totals for all nationalities *
* 6) a table of totals for all speeds *
* ---------------------------------------------------------------- *
* 7) four tables of totals for all waits *
* - waits split up in waiting time intervals *
* - a statistical analysis of waiting times *
* - distribution of short and long rides after waits *
* ------------------------------------------------------------- *
* - waits split up in reason per wait (*) *
* ---------------------------------------------------------------- *
* 8) two tables of ferry related waits (*) *
* - waits after ferry crossings *
* - time spent on ferries *
* ---------------------------------------------------------------- *
* 9) three tables of pick-ups *
* - per nationality per country *
* ------------------------------------------------------------- *
* - per country per type *
* ------------------------------------------------------------- *
* - per nationality per type *
* ----------------------------------------------------------------- *
* 10) a table of hourly departure times per weekday *
* ----------------------------------------------------------------- *
* 11) a table with the first and last ride for all distances *
* 12) a table with the first and last ride for all types *
* 13) a table with the first and last ride for all countries *
* ----------------------------------------------------------------- *
* 14) a table with the first and last ride for all nationalities *
* 15) a table with the first and last ride for all speeds *
**********************************************************************/
1/**********************************************************************
* 16) two tables of waits per trip, split in short and long waits *
* - per individual trip *
* ------------------------------------------------------------- *
* - as a running cumulative total *
* ----------------------------------------------------------------- *
* 17) a table of waits per country, split in short and long waits *
* ----------------------------------------------------------------- *
* 18) a table of waits per 24-hour, split in short and long waits *
* 19) a table of waits per weekday, split in short and long waits *
* 20) a table of waits per month, split in short and long waits *
* 21) a table of waits per year, split in short and long waits *
* ----------------------------------------------------------------- *
* 22) a max/min/average summary for all rides *
* ----------------------------------------------------------------- *
* 23) a max/min/average summary for all days *
* ----------------------------------------------------------------- *
* 24) a max/min/average summary for all types *
* ----------------------------------------------------------------- *
* 25) a max/min/average summary for all nationalities *
* ----------------------------------------------------------------- *
* 26) a max/min/average summary for all countries *
* ----------------------------------------------------------------- *
* 27) a table of rides per country, split in internal and border *
* crossing rides *
* ----------------------------------------------------------------- *
* 28) a table of rides per country, split in native and "foreign" *
* drivers *
* ----------------------------------------------------------------- *
* 29) two tables of longest (km/#r) consecutive distance per *
* country *
* - the longest run of consecutive rides inside a country *
* - the longest run of consecutive rides outside a country *
* ----------------------------------------------------------------- *
* 30) four tables for the max/min speed & max/min rides for a given *
* number of distances *
* ----------------------------------------------------------------- *
* 31) four tables for the max/min speed & max/min distance for a *
* given number of rides *
* ----------------------------------------------------------------- *
* 32) four tables for the maximum number of rides exceeding a *
* number of selected velocities, maximized for the number of *
* rides and the distance, *
* - one set of two tables for absolute speed *
* - one set of two tables for average speed *
* ----------------------------------------------------------------- *
* 33) four tables for the maximum number of rides exceeding a *
* number of selected lengths, maximized for the number of *
* rides and the distance, *
* - one set of two tables for absolute distance *
* - one set of two tables for average distance *
**********************************************************************/
1/**********************************************************************
* 34) a max/min/average summary for all weekdays *
* 35) a max/min/average summary for all months *
* ----------------------------------------------------------------- *
* 36) a max/min/average summary for all rides per year *
* 37) a max/min/average summary for all days per year *
* ----------------------------------------------------------------- *
* 38) a table of totals for all distances per day *
* 39) a table of totals for all speeds per day *
* ----------------------------------------------------------------- *
* 40) a table with the first and last day for all distances *
* 41) a table with the first and last day for all speeds *
* ----------------------------------------------------------------- *
* 42) four tables for the max/min speed & max/min days for a given *
* number of distances *
* ----------------------------------------------------------------- *
* 43) four tables for the max/min speed & max/min distance for a *
* given number of days *
* ----------------------------------------------------------------- *
* 44) four tables for the maximum number of days exceeding a *
* number of selected lengths, maximized for the number of *
* days and the distance, *
* - one set of two tables for absolute distance *
* - one set of two tables for average distance *
* ----------------------------------------------------------------- *
* 45) four tables for the maximum number of days exceeding a *
* number of selected velocities, maximized for the number of *
* days and the distance, *
* - one set of two tables for absolute speed *
* - one set of two tables for average speed *
* ----------------------------------------------------------------- *
* 46) a table of distribution of distances per trip *
* 47) a table of distribution of velocities per trip *
* ----------------------------------------------------------------- *
* 48) four tables for the max/min speed & max/min trips for a given *
* number of distances *
* ----------------------------------------------------------------- *
* 49) four tables for the max/min speed & max/min distance for a *
* given number of trips *
* ----------------------------------------------------------------- *
* 50) four tables for the maximum number of trips exceeding a *
* number of selected velocities, maximized for the number of *
* trips and the distance, *
* - one set of two tables for absolute speed *
* - one set of two tables for average speed *
* ----------------------------------------------------------------- *
* 51) four tables for the maximum number of trips exceeding a *
* number of selected lengths, maximized for the number of *
* trips and the distance, *
* - one set of two tables for absolute distance *
* - one set of two tables for average distance *
**********************************************************************/
1/**********************************************************************
* 52) a table with totals per weekday *
* 53) a table with totals per month *
* 54) a table of general totals per year *
* ----------------------------------------------------------------- *
* 55) a table with first/last ride/trip per year *
* ----------------------------------------------------------------- *
* 56) a table with usage of days per year *
* 57) a table with pickups per day per year *
* ----------------------------------------------------------------- *
* 58) a table with pickups per weekday per month *
* 59) a table of totals for consecutive days *
* ----------------------------------------------------------------- *
* 60) two tables of totals for 24 hour periods *
* - maximum distance per 24-hour period per year *
* - consecutive longer 24-hour period distances *
* 61) a table of totals for 365 day periods *
* ----------------------------------------------------------------- *
* 62) a table of minimum number of rides needed for selected *
* numbers of nationalities *
* ----------------------------------------------------------------- *
* 63) two tables (trip/year) with the number of calendar days, *
* types, countries and nationalities of drivers met during the *
* trip/year, split in total and 'new' *
* ----------------------------------------------------------------- *
* 64) four tables (two per type, two per nationality) with *
* - the longest run of consecutive rides for a single type *
* or nationality *
* - the longest run of consecutive rides without a type or *
* nationality *
* ----------------------------------------------------------------- *
* 65) a table of pickup times per 6-hour interval per country *
* ----------------------------------------------------------------- *
* 66) two (ride + day) sets of three tables with 10% information *
* about rides/days, distances, and times *
* ----------------------------------------------------------------- *
* 67) a table of DTV (+ L=) per type of pickup *
* 68) a table of short and long waits per type of pickup *
* 69) a summary table for per type of pickup split into internal *
* and external rides *
* ----------------------------------------------------------------- *
* 70) six tables (three per country, three per year) for each type *
* of pickup, split into internal and external rides *
* ----------------------------------------------------------------- *
* 71) a table with indicators which countries have been hitched-in *
* or hitched through and with locals or foreigners *
* ----------------------------------------------------------------- *
* 72) three tables showing the progressive maxima for distance, *
* time, and velocity *
**********************************************************************/
1/**********************************************************************
* 73) four tables (two for foreigners, two for natives) showing the *
* progressive longer numbers and distances covered by both *
* ----------------------------------------------------------------- *
* 74) two tables (per type & nationality) for the longest non-stop *
* ride and the distribution of number of stops *
* ----------------------------------------------------------------- *
* 75) a table of counts of borders from a start in each country *
* *
* 76) a table of DV+ for each number of borders crossed *
**********************************************************************/
1/**********************************************************************
* 2. A dataset (DD: LIFTOUT) with non-summarized data, containing *
* six sections: *
* *
* - per trip data, containing the following tables for every trip *
* *
* 1) a table of totals for all days *
* 2) a table of totals for all distances *
* 3) a table of totals for all types *
* 4) a table of totals for all countries *
* 5) a table of totals for all nationalities *
* 6) a table of totals for all speeds *
* 7) a max/min/average summary for all rides & days *
* -------------------------------------------------------------- *
* 8) three tables of totals for all waits *
* - waits split up in waiting time intervals *
* - a statistical analysis of waiting times *
* - waits split up in reason per wait (*) *
* *
* 9) a table of waits per country, split in short and long waits *
* 10) a table of totals for 24 hour periods *
* --------------------------------------------------------------- *
* 11) three tables of pick-ups *
* - per nationality per country *
* - per country per type *
* - per nationality per type *
* --------------------------------------------------------------- *
* 12) a max/min/average summary for all types *
* 13) a max/min/average summary for all nationalities *
* 14) a max/min/average summary for all countries *
* *
* 15) two tables of rides per country, split in internal and *
* border crossing rides *
* - for each country in the order they were passed *
* - as a summary per country *
* *
* - per type data, containing the following tables for every type *
* *
* 1) a table of totals for all distances *
* 2) a table of totals for all countries *
* 3) a table of totals for all nationalities *
* 4) a table of totals for all speeds *
* -------------------------------------------------------------- *
* 5) a table of progressively longer rides *
* 6) a table of progressively faster rides *
* 7) a max/min/average summary for all rides *
**********************************************************************/
1/**********************************************************************
* - per country data, containing the following tables for every *
* country *
* *
* 1) two tables of totals for all waits *
* - waits split up in waiting time intervals *
* - a statistical analysis of waiting times *
* 2) a table with the distribution of departure times per *
* weekday *
* 3) a table of DTV (+ L=) per type of pickup *
* 4) a table of short and long waits per type of pickup *
* 5) a table of DTV+ for each number of borders crossed *
* 6) a max/min/average summary for all rides *
* *
* - per nationality data, containing the following tables for *
* every nationality *
* *
* 1) a table of totals for all distances *
* 2) a table of totals for all types *
* 3) a table of totals for all countries *
* 4) a table of totals for all speeds *
* 5) a table of progressively longer rides *
* 6) a table of progressively faster rides *
* 7) a max/min/average summary for all rides *
**********************************************************************/
1/**********************************************************************
* - per year data, containing the following tables for every year *
* *
* 1) a table of totals for all distances *
* 2) a table of totals for all types *
* 3) a table of totals for all countries *
* 4) a table of totals for all speeds *
* 5) a max/min/average summary for all rides & days *
* -------------------------------------------------------------- *
* 6) three tables of totals for all waits *
* - waits split up in waiting time intervals *
* - a statistical analysis of waiting times *
* - waits split up in reason per wait (*) *
* *
* 7) a table of waits per country, split in short and long *
* waits *
* -------------------------------------------------------------- *
* 8) three tables of pick-ups *
* - per nationality per country *
* - per country per type *
* - per nationality per type *
* -------------------------------------------------------------- *
* 9) a max/min/average summary for all types *
* 10) a max/min/average summary for all nationalities *
* 11) a max/min/average summary for all countries *
* *
* 12) a table of rides per country, split in internal and border *
* crossing rides *
* --------------------------------------------------------------- *
* 13) a table with the longest consecutive distance inside each *
* country passed during the year *
* 14) a table of all per-country sections for the entire year *
* --------------------------------------------------------------- *
* 15) a table of totals for all distances per day *
* 16) a table of totals for all speeds per day *
* *
* 17) a table with totals per weekday *
* 18) a table with totals per month *
* 19) a table of totals for 24 hour periods *
* 20) a table of totals for 365 day periods *
**********************************************************************/
1/**********************************************************************
* 3. A dataset (DD: DAYSOUT) with totals for all days *
* *
* 4. A dataset (DD: TRIPOUT) with a formatted print-out of the input *
* data *
* *
* 5. A dataset (DD: WEEKOUT) with data per weekday, containing the *
* following tables: *
* *
* 1) a table of DTV's per weekday per year *
* 2) a table of DTV's per weekday per day of the month + totals *
* *
* 6. A dataset (DD: MNTHOUT) with monthly data, containing the *
* following tables: *
* *
* 1) distance per month per year *
* 2) cumulative distance per month per year *
* *
* 3) rides and distances for calendar days per month *
* 4) first use of calendar day (ride/trip/year) *
* *
* 7. A dataset (DD: NTOPOUT) with Top-nn tables for longest (distance *
* and time) and fastest rides, with *
* *
* - a top-50 table for all rides *
* - top-10 tables for each trip, type, country, nationality, and *
* year *
* *
* 8. A dataset (DD: XTRAOUT) with milestone data, containing at the *
* moment two tables: *
* *
* 1) Rides at which a selected number of rides was reached *
* 2) Rides at which a selected distance was reaced *
**********************************************************************/
1/**********************************************************************
* Called *
* by - z/OS *
* *
* Modules *
* called - None *
* *
* Datasets *
* input - LIFTIN *
* - INSUMM (Alias of SUMMOUT, for reordering process) *
* - INLIFT (Alias of LIFTOUT, for reordering process) *
* *
* output - SUMMOUT (Overall summary data) *
* - LIFTOUT (Prints per trip/type/country/nationality) *
* - TRIPOUT (Formatted print of input data) *
* - DAYSOUT (Summary for all days) *
* - WEEKOUT (Totals (#d, km) per weekday per year) *
* - MNTHOUT (Totals (#d, km) per month per year) *
* - NTOPOUT (Top-NN (summary/trip/type/cnty/nat/year)) *
* - XTRAOUT (Milestones) *
* - SYSPRINT *
***********************************************************************
* Send questions, suggestions and/or bug reports to: *
* *
* robert@prino.org / robert.ah.prins@gmail.com *
* *
* Robert AH Prins *
* Ozkiniu gatve 48 *
* Vilnius 08405 *
* Lithuania *
***********************************************************************
* This program is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY, without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/> *
**********************************************************************/
1/*--------------------------------------------------------------------+
| Date | TR | Major changes |
+------------+-----+--------------------------------------------------+
| | | |
+<035>-------+-----+--------------------------------------------------+
| 2022-12-31 | 286 | General: |
| | | - add '-*' and 'V*' types |
| | | - move 'VPor' after 'Por' |
| | | - merge "Invite" and "Other" pickup types |
| | | - split pickups into internal and external rides |
| | | - add "E-Charge" in-ride wait |
| | | - add 6-hour night/morning/afternoon/evening) |
| | | separator lines to hours table |
| | | |
| | | SUMMOUT: |
| | | - add summary pickup table per type of pickup |
| | | for internal and border-crossing rides |
| | | - add summary per-country and per-year tables |
| | | for internal and external rides, for each |
| | | type of pickup |
| | | |
| | | LIFTOUT: |
| | | - add a table of DTV (+ L=) per type of pickup |
| | | for each year |
| | | - add a table of short and long waits per type |
| | | of pickup for each year |
| | | |
| | | WEEKOUT: |
| | | - add weekdays hitched per month tables if there |
| | | are more than 1,000 rides |
| | | |
| | | XTRAOUT: |
| | | - new dataset - ride and distance milestones |
+------------+-----+--------------------------------------------------+
1+<034>-------+-----+--------------------------------------------------+
| 2021-12-31 | 262 | General: |
| | | - rename some variables |
| | | - "period_of_365_days" updated to handle periods |
| | | of 366 days for leapyears |
| | | |
| | | SUMMOUT: |
| | | - remove time and velocity from INEX_TCN table |
| | | - remove time and velocity from HHCOPA table |
| | | - process post-eol "foreigner" slots, will |
| | | only affect single-trip processing |
| | | - reduce the per-interval pickup table to four |
| | | intervals, i.e. "Night", "Morning', |
| | | "Afternoon", and "Evening" |
| | | - add a table of DTV (+ L=) per type of pickup |
| | | - add a table of short and long waits per type |
| | | of pickup |
| | | |
| | | LIFTOUT: |
| | | - add a table of DTV (+ L=) per type of pickup |
| | | - add a table of short and long waits per type |
| | | of pickup |
| | | |
| | | WEEKOUT: |
| | | - add table of pickups + DTV per weekday per |
| | | per day of the month + totals |
+------------+-----+--------------------------------------------------+
1+<033>-------+-----+--------------------------------------------------+
| 2020-12-31 | 252 | General: |
| | | - equalise the top of the lift_list, day_list, |
| | | and trip_list structures to allow merging the |
| | | code of most of the fast_* routines |
| | | - merge the various fast* routines, using |
| | | parameters to pass per ride/day/trip data |
| | | - correct buggy code in "fast_distance" with |
| | | equivalent correct Pascal code |
| | | |
| | | SUMMOUT: |
| | | - mark used days without starting ride |
| | | (@ <033>: 1988-07-14 & 2000-03-02) |
| | | - add table with pickups per day per year |
| | | - add time and velocity to INEX_TCN table |
| | | - add HHCOPA exclusion table |
| | | - add border cross counts per country |
| | | - add DV+ border crossing rides |
| | | - add initial country to progressive maxima DTV |
| | | tables for split-country rides |
| | | - add the "four sets of four tables" for trips |
| | | |
| | | LIFTOUT: |
| | | - add DV+ border crossing rides in the per- |
| | | country section |
| | | - add maximum consecutive distance per country |
| | | table to the per-year section |
| | | - add all-country segment table to the per-year |
| | | section |
| | | - add initial country to progressive maxima DV |
| | | tables in the per-type and per-nat sections |
| | | for split-country rides |
| | | |
| | | NTOPOUT: |
| | | - add initial country to Top-N tables for split- |
| | | country rides |
+<032>-------+-----+--------------------------------------------------+
| 2020-03-07 | 235 | General: |
| | | - finally solve the problem of 24-hour periods |
| | | crossing timezone boundaries |
| | | - use non-hitching time of previous ride for |
| | | ferry-crossing time if ride was obtained on |
| | | ferry |
| | | |
| | | SUMMOUT: |
| | | - correct separator line placement in FiLa table |
| | | for days distance |
+------------+-----+--------------------------------------------------+
1+<031>-------+-----+--------------------------------------------------+
| 2020-01-11 | 233 | General: *S* |
| | | - on-the-fly suppression of "!^" 706 idle-time |
| | | records (out of 710, left are T108R17, T152R6, |
| | | T208R6, and T224R26, where idle time crosses |
| | | midnight) |
| | | - add name of country to the totals per |
| | | nationality table |
| | | - use ":" in headings of wait tables |
| | | - add NMK for North Macedonia to plates |
| | | - add third dimension to "m_dtv" in "year_wm" to |
| | | allow day-of-week granularity summation of per |
| | | day dtv-data |
| | | - split nationalities in the non-stop table in |
| | | the usual (N=C / N^=C) way |
| | | - suppress period of 24 hour from extending into |
| | | the next trip (225->226) |
| | | |
| | | SUMMOUT: |
| | | - correct entries in FiLa-table for types, |
| | | countries, and nationalities for rides that |
| | | span multiple days |
| | | - add separator in the INEX "Nat" table for |
| | | internal and external nationalities |
| | | - remove name of country per nationality table |
| | | - add tables with longest no-wait rides per type |
| | | and nationality, and distribution of #waits |
| | | - Added 42, "The Answer to the Ultimate Question |
| | | of Life, the Universe, and Everything" from |
| | | Douglas Adams' "The Hitchhiker's Guide to the |
| | | Galaxy" to the interval values for the |
| | | V/L(+/-) Ride/Day tables (At long last...) |
| | | - add 384,402 ("Hitch me to the Moon") to the |
| | | distances for the "Fastest/Slowest/Min Ride/ |
| | | Max Ride" (and same for Days) table |
| | | |
| | | LIFTOUT: |
| | | - add two tables with progessively longer and |
| | | progressively faster rides to the per-type and |
| | | per-nationality sections |
| | | |
| | | MNTHOUT: |
| | | - create uniform headings for the per-month and |
| | | cumulative per-month tables |
| | | - add table with distance per month for calendar |
| | | days (See *^01* markers for possible change) |
| | | - add "DAYSOUT" like table of months |
| | | |
| | | WEEKOUT: |
| | | - print full DTV weekday tables |
| | | |
| | | NTOPOUT: |
| | | - add lift_list.id as tie-breaker in sort |
+------------+-----+--------------------------------------------------+
1+<030>-------+-----+--------------------------------------------------+
| 2018-10-01 | 209 | General: |
| | | - add native and foreign drivers to the totals |
| | | per country tables |
| | | - remove "to" trip in "Period of 24 hour" tables |
| | | - build full Top-nn tables rather than caching |
| | | only top (statement count -97.4%!) |
| | | - direct access to top_x_ptr via overlay |
| | | - postpone rounding to just before print |
| | | - correct rounding for distance in 10% tables |
| | | - add ISO 3166-1 country codes |
| | | - allow for ISO 3166-1 code in {U metadata |
| | | |
| | | SUMMOUT: |
| | | - only invoke "nat_scan" if there are at least |
| | | 3 nationalities (reversal of <014>) |
| | | - always print ride in "foreign_writer" if trips |
| | | are different |
| | | - add table with distribution of short and long |
| | | rides after various waiting times |
| | | - add +/-/= table for weekdays |
| | | - add +/-/= table for months |
| | | - add HHCOPA table |
| | | - add consecutive foreigners & natives tables |
| | | - reorder to match output of PC version |
| | | |
| | | LIFTOUT: |
| | | - add table with distribution of short and long |
| | | rides after various waiting times for per-trip |
| | | and per-year sections (f '*?*') |
| | | - reorder to match output of PC version |
| | | |
| | | NTOPOUT: |
| | | - Top-nn per country up to 10 not total "#cnty" |
+------------+-----+--------------------------------------------------+
1+<029>-------+-----+--------------------------------------------------+
| 2017-09-22 | 191 | General: |
| | | - add odo, deptyp, deploc, and arrloc to inrec |
| | | - add more comments |
| | | - correct generation of splits for multi-day/ |
| | | country rides (Invalid data for T107 & T163, |
| | | did not affect output) |
| | | - eliminate zero-km splits (Currently eliminates |
| | | spurious 24-hour period for T74) |
| | | - reduce calls to srch_cnty by ~70% by caching |
| | | the results outside the "post_process_ride" |
| | | procedure |
| | | - substantially restructure "process_times" and |
| | | move results directly into day_list, removing |
| | | the need for intermediate d_arr |
| | | |
| | | SUMMOUT: |
| | | - add table of progress for distance, time, and |
| | | velocity, with a last row showing the current |
| | | maximum values since the absolute maximum |
| | | |
| | | MNTHOUT: |
| | | - suppress same trip/ride/year when they are the |
| | | same on first day of next month |
| | | |
| | | NTOPOUT: |
| | | - output Top-nn tables for the summary (Top-50), |
| | | and per trip, type, country, nationality, and |
| | | year (Top-10), for the longest (time/distance) |
| | | and fastest rides |
+------------+-----+--------------------------------------------------+
1+<028>-------+-----+--------------------------------------------------+
| 2017-05-19 | 187 | General: |
| | | - add GPL statement & contact details |
| | | - allocate *tot_list items in AREA (*=tcn) |
| | | - merge LL and wait tab |
| | | |
| | | SUMMOUT: |
| | | - add 10% tables (#R/KM/Time + #D/KM/Time) |
| | | - add name of country to country tables |
| | | - add country & nationality name tables |
+<027>-------+-----+--------------------------------------------------+
| 2017-01-01 | 180 | General: |
| | | - reduce statement count of "inex_tcn" by about |
| | | 88% using new sum_xxxx fields in lift_list and |
| | | the information in the type_list and nat_list |
| | | - add 40,075.2 (equator) to "fast_dist" array |
| | | - double separator line in various "nat" tables |
| | | after N=C countries (use '$ds' pre-processor |
| | | variable to disable) |
| | | - reduce inex_tcn CPU consumption by moving most |
| | | compares out of the loops |
| | | - improve generation of split_list by skipping |
| | | intervals > 2 days |
| | | - pre-calculate #sp at read-in (lift) or while |
| | | processing (day) so as not to have to |
| | | recalculate them multiple times |
| | | |
| | | SUMMOUT: |
| | | - added calendar days usage to "tycona" table |
| | | - added wait before departure table |
| | | |
| | | MNTHOUT: |
| | | - add cumulative totals per month per year |
| | | - add print of first use of calendar days |
+------------+-----+--------------------------------------------------+
1+<026>-------+-----+--------------------------------------------------+
| 2016-05-23 | 175 | General: |
| | | - correct serious bug in GET_TZ_INFO for {Z+ |
| | | records due to double use of #tz |
| | | - moved some in-line processing at read-in to |
| | | "post_process_ride" routine allowing a number |
| | | of significant optimizations |
| | | - replaced 4-nested "if" in "build_24_hour_list" |
| | | with "select-when-other-end" |
| | | - moved most code from "build_24_hour_list" to |
| | | "post_process_ride" allowing periods to be |
| | | built on a per-ride basis |
| | | - use '+' or '-' in arrival time for border- |
| | | crossings to indicate timezone change |
| | | - removed code to handle the original six non- |
| | | day split days (added approximate splits to |
| | | input dataset) |
| | | - classify "No hitching" under "real" type for |
| | | "In-ride wait" table |
| | | - some more local variables |
| | | - round-2-even for R/D (T008, cumulative) |
| | | |
| | | SUMMOUT: |
| | | - paginate nationalities table |
| | | |
| | | WEEKOUT: |
| | | - new dataset - totals per weekday per year |
| | | |
| | | MNTHOUT: |
| | | - new dataset - totals per month per year |
+<025>-------+-----+--------------------------------------------------+
| 2016-01-01 | 167 | General: |
| | | - correct processing of "fast_x_speed_abs/avg" |
| | | "fast_x_length_abs/avg" routines to use '>' |
| | | rather than ">=". |
| | | |
| | | SUMMOUT: |
| | | - pre-calculate #sd and #ld at read-in so as not |
| | | to have to recalculate them for the summary, |
| | | trip and per year processing |
+------------+-----+--------------------------------------------------+
1+<024>-------+-----+--------------------------------------------------+
| 2015-09-14 | 164 | General: |
| | | |
| | | SUMMOUT: |
| | | - new table of #rides/distance/time per country |
| | | for natives and "foreigners" |
| | | |
| | | LIFTOUT: |
| | | - new table of progressive periods of 24 hours |
| | | per trip |
+<023>-------+-----+--------------------------------------------------+
| 2015-07-27 | 161 | General: |
| | | - introduction of 'crossed' departure indicator |
| | | - save monthly and weekday totals per year into |
| | | the year list (future use) |
| | | - times (with the exception of those in TRIPOUT) |
| | | are now in ISO8601 (hh:mm) format |
| | | - cnty_list now records border-crossing and non- |
| | | border-crossing rides separately |
| | | - merge wait_list into lift_list |
| | | |
| | | SUMMOUT: |
| | | - trip_total.trip should start with number of |
| | | first trip in input dataset |
| | | - number of days for "next" year of split-year |
| | | trip was incorrect and would lead to S0C4 in |
| | | "process_times" (Trip 61, 2002/3) |
| | | - add missing separator line in FiLa table for |
| | | per-ride distances > 1000 km |
| | | |
| | | TRIPOUT: |
| | | - print new 'crossed' departure indicator |
+<022>-------+-----+--------------------------------------------------+
| 2014-06-23 | 140 | Ad-hoc bugfix: |
| + backport | | - reduce next day threshold ('tht') to 660 for |
| | | ride split over multiple countries (T139R4 and |
| | | T142R2) |
| | | |
| | | General: |
| | | - remove some redundant code |
| | | - km / time changed to fixed (9,1) / fixed (9) |
| | | - update liftlog after split of trip 53 |
| | | |
| | | SUMMOUT: |
| | | - add distribution of lengths per trip table |
| | | - add distribution of velocities per trip table |
+------------+-----+--------------------------------------------------+
1+<021>-------+-----+--------------------------------------------------+
| 2013-04-12 | 122 | General: |
| | | - optimize "process_pickups" (discrete loop is |
| | | much more efficient than "index") and process |
| | | all pickup types in a single pass |
| | | - optimize access to "type_list" and "nat_list" |
| | | for non-summary data and access to "cnty_list" |
| | | for per-type, per-country and per-nationality |
| | | processing using extra pointers in "lift_list" |
| | | - delete "process_trip" and "process_day" and |
| | | create trip_list and day_list while reading in |
| | | the input dataset, like what was already done |
| | | for year_list |
| | | |
| | | SUMMOUT: |
| | | - enable the use of 'PERIOD_OF_24_HOUR' to print |
| | | a table of maximum distances per 24 hour per |
| | | year |
+<020>-------+-----+--------------------------------------------------+
| 2013-02-10 | 120 | General: |
| | | - alter precision of prequal (2012@T114) |
| | | - use preprocessor to generate inline code in |
| | | sortwait |
| | | - many additional optimizations of LRU type |
| | | |
| | | SUMMOUT: |
| | | - suppress output of empty tables from |
| | | fast_[rd]_length_[abs avg] due to trip only |
| | | containing only short rides and/or days (T100) |
| | | - change "process_mini_wait('PY ')" to cater |
| | | for trips containing only "No Wait" waiting |
| | | times (T049 & T100) |
| | | - new table containing pickup times per 4-hour |
| | | interval per country |
| | | |
| | | LIFTOUT: |
| | | - move non-hitching ('!^') time to Idle in the |
| | | totals-per-day table |
+<019>-------+-----+--------------------------------------------------+
| 2012-06-05 | 112 | General - maintenance/optimization release |
| | | - use more local variables |
| | | - convert more variables to fixed bin (31) |
| | | - remove in-loop pic<->fixed dec compares |
| | | - zap reliance on minmax from many procedures |
| | | - optimize "fast_?_s/l_avg" significantly |
| | | - optimize "process_ty/co/na" (Using LRU) |
| | | - change the layout of the lift_list, day_list |
| | | and min_max strutures to enable further |
| | | optimizations |
| | | - optimize "print_waitsd" (Using LRU) |
| | | - optimize "tycona_count" (discrete loop is |
| | | much more efficient than "index") |
+------------+-----+--------------------------------------------------+
1+<018>-------+-----+--------------------------------------------------+
| 2011-10-31 | 106 | General: |
| | | - add first wait count to wait -1/+1/Tot tables |
| | | - change some values in iminmax to prevent |
| | | potential errors when the (SIZE): prefix is |
| | | used |
| | | - correct wait processing for multi-split rides |
| | | - add 'No wait' column to wait tables |
+<017>-------+-----+--------------------------------------------------+
| 2011-08-31 | 102 | General: |
| | | - allow non-integral timezones in "{Z" metadata |
| | | (commented out, look for '*TZ*') |
| | | - localize many fixed bin (31)'s |
| | | - many (significant) optimisations |
| | | - replace some fixed with fixed bin (Windows!) |
| | | |
| | | SUMMOUT: |
| | | - correct rounding of SDEV (T97 Cumulative) |
| | | - correct rounding of QUAL (T88 Cumulative) |
| | | |
| | | LIFTOUT: |
| | | - rewrite process_times to use arrays |
| | | - correct missing timezone in process_times for |
| | | the case where the TZ changes between |
| | | days n/n+1 and rides p/p+1 and there is a wait |
| | | before ride p+1 (T61D5-6R23-24) |
+<016>-------+-----+--------------------------------------------------+
| 2010-06-03 | 88 | General: |
| + backport | | - Input dates are now YYYY-MM-DD. |
| | | |
| | | SUMMOUT: |
| | | - correct bug in NAT_SCAN, introduced in LIFT010 |
| | | - add "C" as a distance :) |
+<015>-------+-----+--------------------------------------------------+
| 2009-08-17 | 83 | General: |
| | | - add lift_list.aitime for follow-on idle time |
| | | - some "WHEN" reordering to put most selected |
| | | options first |
| | | |
| | | SUMMOUT: |
| | | - correct processing of hours for rides that are |
| | | the first of the day and span multiple days |
| | | (T23T22, T28R16, T40R15, T45R22 and T71R12) |
| | | |
| | | LIFTOUT: |
| | | - enable the use of 'PRINT_COPA' in the 'Totals |
| | | per year' section (f '*?*') |
+------------+-----+--------------------------------------------------+
1+<014>-------+-----+--------------------------------------------------+
| 2007-09-25 | 73 | General: |
| | | - cater for total distance >= 1,000,000 km and |
| | | total time >= 10,000 hour |
| | | - output all dates in ISO8601 (yyyy-mm-dd) |
| | | format |
| | | - set save_xxx_ptr back to sysnull after use |
| | | - decrease description column in cnty_line |
| | | - replace heapsort with Shellsort in sortwait |
| | | - remove empty line after In-ride wait table |
| | | - reformat Cnty +/-/= table |
| | | |
| | | SUMMOUT: |
| | | - improve speed of fast_X_Y_avg by skipping all |
| | | subsequent entries that have an average |
| | | length/speed above the currently select one. |
| | | |
| | | LIFTOUT: |
| | | - add 'PRINT_COPA' procedure for countries |
| | | passed |
+<013>-------+-----+--------------------------------------------------+
| 2006-10-27 | 73 | General: |
| | | - remove 'Mile' specific variables |
| | | - remove (Enterprise PL/I) inefficiencies |
| | | - recode 'FAST_?_SPEED' & 'FAST_?_LENGTH' procs, |
| | | splitting them into 'ABS' and 'AVG' variants, |
| | | significantly reducing their running times. |
| | | |
| | | SUMMOUT: |
| | | - don't invoke nat_scan if just one nationality |
| | | is present and reduce series threshold to two |
| | | if only two nationalities are present |
| | | - update V(!/=) (R/L/D/L+) table processing to |
| | | include additional speed intervals |
| | | - suppress INEX table ('EX' part) if there is |
| | | only one type or nationality present |
| | | - correct timezone roll-over (T059R041/T069R007) |
| | | |
| | | LIFTOUT: |
| | | - add split line in nat table for trip & year |
| | | sections |
+------------+-----+--------------------------------------------------+
1+<012>-------+-----+--------------------------------------------------+
| 2005-06-23 | 66 | General: |
| | | |
| | | LIFTOUT: |
| | | - add 24x7 hours table to the totals per country |
| | | section |
+<011>-------+-----+--------------------------------------------------+
| 2005-04-25 | 66 | General: |
| | | - remove pre-processor code to process distances |
| | | as miles |
| | | |
| | | SUMMOUT: |
| | | - add tables per type & nationality for longest |
| | | in- and exclusive series for selected type & |
| | | nationality |
| | | - add 'dashed' waiting times for countries |
| | | without waiting times to complete table |
| | | |
| | | LIFTOUT: |
| | | - add 'dashed' waiting times for countries |
| | | without waiting times to complete table |
+<010>-------+-----+--------------------------------------------------+
| 2003-05-12 | 62 | General: |
| | | - remove hardcoded timezone table and get |
| | | timezone information from meta-comments in |
| | | input dataset |
| | | |
| | | SUMMOUT: |
| | | - keep only first and last occurance if ten or |
| | | more nationalities in the same number of rides |
| | | - add waiting time per weekday table |
| | | - add waiting time per calender month table |
| | | - correct output of +/-/= table for one-char |
| | | nationalities where this char is the last of a |
| | | two-char nationality ('H'/'CH') |
+------------+-----+--------------------------------------------------+
1+<009>-------+-----+--------------------------------------------------+
| 2001-07-24 | 49 | General: |
| | | - split 'period_of_24_hour_and_365_days' and use |
| | | split data to produce real 24 hour data |
| | | |
| | | SUMMOUT: |
| | | - suppress duplicates in Fastest/Slowest/ |
| | | Min Ride/Max Ride tables |
| | | - convert totals per year table to same format |
| | | as totals per trip table |
| | | - add table with first/last trip/ride per year |
| | | - delete combined period table |
| | | - add 'real' 24 hour table |
| | | - add 365 day table |
| | | - add 'TyCoNa' tables per trip and year |
| | | |
| | | LIFTOUT: |
| | | - delete combined period table |
| | | - add 'real' 24 hour table |
| | | - add 365 day table |
| | | |
| | | TRIPOUT: |
| | | - start new page of formatted output on new day |
+<008>-------+-----+--------------------------------------------------+
| 1999-09-07 | 40 | General: |
| | | |
| | | SUMMOUT: |
| | | - correct processing of multi-day rides when |
| | | they are the first ride of the day |
+<007>-------+-----+--------------------------------------------------+
| 1999-07-26 | 39 | General: |
| | | - use round-to-even for average times |
| | | - calculate rides per day fraction (unused) |
| | | |
| | | SUMMOUT: |
| | | - add waiting time statistical distribution |
| | | |
| | | LIFTOUT: |
| | | - add waiting time statistical distribution to |
| | | Trip & Year sections |
+<006>-------+-----+--------------------------------------------------+
| 1998-10-30 | 38 | General: |
| | | |
| | | SUMMOUT: |
| | | - add table of in-ride waits |
| | | |
| | | LIFTOUT: |
| | | - add table of in-ride waits to the Trip & Year |
| | | sections |
| | | - add waiting times to Country section |
| | | - add +/-/= Int/Ext table to Country section |
+------------+-----+--------------------------------------------------+
1+<005>-------+-----+--------------------------------------------------+
| 1998-05-24 | 37 | General: |
| | | - replace code in 'nat_scan' by extremely fast |
| | | code by Paul Green |
+<004>-------+-----+--------------------------------------------------+
| 1998-05-04 | 36 | General: |
| | | - replace original slow code in 'nat_scan' by |
| | | faster code from Brent B. Beach |
| | | - add timezone processing (Europe only) |
| | | |
| | | SUMMOUT: |
| | | - add in-ride ferry crossings table |
| | | |
| | | LIFTOUT: |
| | | - add stoppage time output to daily data |
| | | |
| | | TRIPOUT: |
| | | - paginate formatted input on new day |
| | | - suppress zero distance & time for splits |
+<003>-------+-----+--------------------------------------------------+
| 1997-07-12 | 35 | General: |
| | | - add departure & arrival times to input |
| | | - add stop splits to input |
| | | - alter rounding of times to PC version |
| | | - remove rounding errors when converting input |
| | | to miles |
| | | |
| | | SUMMOUT: |
| | | - add hourly departure times per weekday |
| | | - add nationalities table |
| | | - screw up departure countries for ferries |
| | | because of added splits... |
| | | - remove single line summary table |
| | | |
| | | TRIPOUT: |
| | | - add new input data to formatted output |
+<002>-------+-----+--------------------------------------------------+
| 1995-01-26 | 28 | General: |
| | | - replace first item in 'trip_list' with |
| | | separate 'trip_total' record |
| | | |
| | | LIFTOUT: |
| | | - add period (24h/365d) to the Year section |
+<001>-------+-----+--------------------------------------------------+
| 1994-10-22 | 28 | First saved PL/I version |
+------------+-----+-------------------------------------------------*/
%dcl $ds char; %$ds = '''=''';
%dcl $irw char; %$irw = '-13:18';
%dcl $bc_max char; %$bc_max = '6';
%dcl filler entry;
%filler: proc returns(char);
dcl str char;
dcl compiletime builtin;
dcl counter builtin;
if substr(compiletime, 3, 1) = ' ' then
str = 'Z' || counter;
else
if sysparm = 'TEST' then
str = 'z' || counter;
else
str = '* ';
return(str);
%end filler;
%dcl $$ entry;
%$$: proc($$line) statement returns(char);
dcl $$line char;
dcl length builtin;
dcl $$i fixed;
dcl blank char;
blank = ' ' ||
' ';
if ^parmset($$line) then
$$line = ' ';
$$i = ((length($$line) + 70) / 71) * 71 - length($$line);
return($$line || substr(blank, 1, $$i));
%end $$;
1lift: proc(param) options (main) reorder;
dcl param char (100) var;
dcl plixopt char (100) var ext
init ('ISASIZE(128K) HEAP(32768K,256K)');
/**********************************************************************
* LIFT - Entry's, builtins & files *
**********************************************************************/
dcl (abs,
addr,
allocn,
dec,
divide,
empty,
floor,
hbound,
index,
lbound,
length,
max,
min,
mod,
multiply,
plidump,
repeat,
round,
sqrt,
stg,
string,
substr,
sum,
sysnull,
translate,
trunc,
unspec) builtin;
dcl liftin file record input env(vb recsize(1028) total);
dcl summout file record output env(fb recsize(121) total ctlasa);
dcl liftout file record output env(fb recsize(121) total ctlasa);
dcl tripout file record output env(fb recsize(121) total ctlasa);
dcl daysout file record output env(fb recsize(121) total ctlasa);
dcl weekout file record output env(fb recsize(121) total ctlasa);
dcl mnthout file record output env(fb recsize(121) total ctlasa);
dcl ntopout file record output env(fb recsize(121) total ctlasa);
dcl xtraout file record output env(fb recsize(121) total ctlasa);
dcl insumm file record input env(fb recsize(121) total);
dcl inlift file record input env(fb recsize(121) total);
dcl sysprint file;
1dcl 1 plitabs ext,
2 offset fixed bin (15) init (14),
2 pagesize fixed bin (15) init (32765), /* 60 */
2 linesize fixed bin (15) init (511), /* 120 */
2 pagelength fixed bin (15) init (32767),
2 reserved1 fixed bin (15) init (0),
2 reserved2 fixed bin (15) init (0),
2 reserved3 fixed bin (15) init (0),
2 no_of_tabs fixed bin (15) init (0), /* 5 */
2 tab(10) fixed bin (15) init (25, 49, 73, 97, 121,
145, 169, 193, 217, 241);
1/**********************************************************************
* LIFT - Working storage *
**********************************************************************/
dcl 1 lift_static static,
2 filler char (32)
init ('LIFT STATIC INITIAL DATA'),
2 idata,
3 #c fixed bin (31) init (0),
3 km fixed (9,1) init (0),
3 time fixed (9) init (0),
3 filler char (2) init ((2)'00'x),
2 filler char (16) init ('IMINI '),
2 imini,
3 #mima fixed bin (31) init (0),
3 l_max fixed (9,1) init (0),
3 t_max fixed (9) init (0),
3 filler char (10) init ((10)'00'x),
3 fptr(2) ptr init ((2)sysnull()),
2 filler char (16) init ('IMINMAX '),
2 iminmax,
3 #mima fixed bin (31) init (0),
3 v_max fixed (13,9) init (0),
3 v_min fixed (13,9) init (9999.999999999),
3 v_avg fixed (5,1) init (0),
3 l_tot fixed (9,1) init (0),
3 l_max fixed (9,1) init (0),
3 l_min fixed (9,1) init (9999.9),
3 l_avg fixed (15,9) init (0),
3 t_tot fixed (9) init (0),
3 t_max fixed (9) init (0),
3 t_min fixed (9) init (5999),
3 #rc fixed (13,8) init (0),
3 f_max fixed (15,10) init (0),
3 filler char (46) init ((46)'00'x),
3 fptr(2) ptr init ((2)sysnull()),
2 filler char (16) init ('INITIAL WAIT '),
2 iwait,
3 #w fixed bin (31) init (0),
3 wtime fixed bin (31) init (0),
2 filler char (16) init ('PLATE DATA '),
2 iplates,
3 visit bit (1) init ('0'b) aligned,
3 hitch char (1) init (' '),
3 local char (1) init (' '),
3 filler char (1) init (' '),
1 2 filler char (16) init ('WAIT INTERVALS '),
2 wa_time(-2:33) fixed bin (31)
init (-2, -1, 0,
5, 10, 15, 20, 25, 30,
35, 40, 45, 50, 55, 60,
75, 90, 105, 120, 135, 150, 165, 180,
210, 240, 270, 300, 330, 360,
420, 480, 540, 600, 660, 720,
99999),
2 wa_idx(-2:33) fixed bin (31)
init (8, 1, 2,
3, 3, 3, 3, 3, 3, /* 1 - 30 */
3, 3, 3, 3, 3, 3, /* 31 - 60 */
4, 4, 4, 4, 4, 4, 4, 4, /* 61 - 180 */
5, 5, 5, 5, 5, 5, /* 181 - 360 */
6, 6, 6, 6, 6, 6, /* 361 - 720 */
7), /* 721+ */
2 wa_hdx(0:120) fixed bin (31)
init (0,
1, 1, 1, 1, 1, 2, 2, 2, 2, 2, /* 1 - 10 */
3, 3, 3, 3, 3, 4, 4, 4, 4, 4, /* 11 - 20 */
5, 5, 5, 5, 5, 6, 6, 6, 6, 6, /* 21 - 30 */
7, 7, 7, 7, 7, 8, 8, 8, 8, 8, /* 31 - 40 */
9, 9, 9, 9, 9, 10, 10, 10, 10, 10, /* 41 - 50 */
11, 11, 11, 11, 11, 12, 12, 12, 12, 12, /* 51 - 60 */
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, /* 61 - */
13, 13, 13, 13, 13, /* 75 */
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, /* 76 - */
14, 14, 14, 14, 14, /* 90 */
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, /* 91 - */
15, 15, 15, 15, 15, /* 105 */
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, /* 106 - */
16, 16, 16, 16, 16), /* 120 */
1 2 filler char (16) init ('FASTEST DISTANCE'),
2 fast_dist(20) fixed (9,1)
init (100.0, 250.0, 500.0,
1000.0, 2500.0, 5000.0,
10000.0, 25000.0, 40075.2, 50000.0, /* Equator */
100000.0, 160934.4, /* 100,000 mile */
250000.0, 299792.5, /* Lightsecond */
384402.0, 500000.0, /* The Moon */
1000000.0, 2500000.0, 5000000.0,
10000000.0),
2 filler char (16) init ('HIGHEST SPEED '),
2 highest_s(31) fixed (15,10)
init (10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
105, 110, 115, 120, 125, 130, 135, 140, 145, 150,
155, 160, 165, 170, 175, 180, 185, 190, 195, 200,
999),
2 filler char (16) init ('FASTEST RIDES '),
2 fastest_r(13) fixed bin (31)
init (1, 5,
10, 25, 42, 50,
100, 250, 500,
1000, 2500, 5000,
10000),
2 filler char (16) init ('FASTEST DAYS '),
2 fastest_d(18) fixed bin (31)
init (1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
25, 42, 50, 100,
250, 365, 500, 1000),
2 filler char (16) init ('LONGEST RIDE '),
2 longest_r(13) fixed (15,10)
init (25, 50, 75,
100, 200, 300, 400, 500, 600, 700, 800, 900, 1000),
2 filler char (16) init ('LONGEST DAYS '),
2 longest_d(10) fixed (15,10)
init (100, 200, 300, 400, 500, 600, 700, 800, 900, 1000),
2 filler char (16) init ('LONGEST TRIPS '),
2 longest_t(8) fixed (15,10)
init (100, 250, 500, 1000, 2500, 5000, 10000, 25000),
1 /*--------------------------------------------------------------+
| Current set of in-ride waits. If another is added, both array |
| bounds must be increased by 1 (currently to -13:18) and the |
| id and description of the new in-ride wait must be added |
| *BEFORE* the '&'/'Smiespel' id/description, and one |
| ' '/'*** Oops ***' pair must be removed. |
| |
| Note the change must also be made to 'irwait' in 'lift_work'! |
+--------------------------------------------------------------*/
2 filler char (16) init ('IN-RIDE WAITS '),
2 irw_id char (18) init ('BPWDMRSCTLVNFJE&^ '),
2 filler char (14), /* ----+----1----+--- */
2 irw($irw),
3 irw_desc char (12)
init ('*** Oops ***', /* -13 */
'*** Oops ***', /* -12 */
'*** Oops ***', /* -11 */
'*** Oops ***', /* -10 */
'*** Oops ***', /* -9 */
'*** Oops ***', /* -8 */
'*** Oops ***', /* -7 */
'*** Oops ***', /* -6 */
'*** Oops ***', /* -5 */
'*** Oops ***', /* -4 */
'*** Oops ***', /* -3 */
'*** Oops ***', /* -2 */
'*** Oops ***', /* -2 */
/* @ T286 *S*/ '*** Oops ***', /* 0 */
/* 216 */ 'Border ', /* B 1 */
/* 499 */ 'Fuel ', /* P 2 */
/* 166 */ 'Toilet ', /* W 3 */
/* 298 */ 'Drink ', /* D 4 */
/* 206 */ 'Meal ', /* M 5 */
/* 182 */ 'Rest ', /* R 6 */
/* 59 */ 'Sleep ', /* S 7 */
/* 155 */ 'Business ', /* C 8 */
/* 87 */ 'Toll ', /* T 9 */
/* 30 */ 'Police ', /* L 10 */
/* 80 */ 'Car ', /* V 11 */
/* 4 */ 'No fuel ', /* N 12 */
/* 7 */ 'Tacho fiddle', /* F 13 */
/* 335 */ 'Traffic jam ', /* J 14 */
/* 2 */ 'E-Charge ', /* E 15 */
/* 17 */ 'Smiespel ', /* & 16 */
/* 513 */ 'No hitching ', /* ^ 17 */
/* 307 */ 'Other '), /* 18 */
1 2 filler char (16) init ('PRINT STRUCTURES'),
2 iline char (121) init (' '),
2 pline char (121) init ('1'),
2 filler char (16) init ('LIFT LINES '),
2 lift_sep char (121)
init ((' +------+------+-----+-------' ||
'-+-------+-------+-----+------+-----+' ||
'-------+---+-------+-------+------------+')),
2 lift_init char (121)
init ((' | | | | ' ||
' | : | | | | |' ||
' | | | | - - |')),
2 lift_head char (121)
init ((' | Trip | Ride | Day | KM' ||
' | Time | V= | Nat | Type | Cty |' ||
' Wait | S | From | To | Date |')),
2 filler char (16) init ('TRYR LINES '),
2 tryr_sep char (121)
init ((' +------+------+------+----------+--------' ||
'-+-------+--------+--------+--------+-------+')),
2 tryr_init char (121)
init ((' | | | | | : ' ||
' | | | | | |')),
2 tryr_head char (121)
init ((' | Trip | #D | #R | KM | Time' ||
' | V= | Qual | D= | R= | R/D |')),
2 filler char (16) init ('DTCNS LINES '),
2 dtcns_sep char (121)
init ((' +--------+------+----------+---------+-------+')),
2 dtcns_init char (121)
init ((' | | | | : | |')),
2 dtcns_initx char (121)
init ((' | | - | - | : - | - |')),
2 dtcns_head char (121)
init ((' | | # | KM | Time | V= |')),
2 filler char (16) init ('TD LINES '),
2 td_sep char (121)
init ((' +------+-----+-------' ||
'-+-------+-------+------------+')),
2 td_head char (121)
init ((' | Trip | Day | KM' ||
' | Time | V= | Date |')),
2 td_init char (121)
init ((' | | | ' ||
' | : | | - - |')),
1 2 filler char (16) init ('MIN_MAX LINES '),
2 min_max_sep char (121)
init ((' +------+------+-------+-------+-------+--------' ||
'+--------+--------+-------+-------+-------+')),
2 min_max_init char (121)
init ((' | | | | | | ' ||
'| | | : | : | : |')),
2 min_max_head char (121)
init ((' | | # | V+ | V- | V= | L+ ' ||
'| L- | L= | T+ | T- | T= |')),
2 min_max_csep char (121)
init ((' +------+---------+-------+-------+-------+--------' ||
'+--------+--------+-------+-------+-------+')),
2 min_max_chead char (121)
init ((' | | # | V+ | V- | V= | L+ ' ||
'| L- | L= | T+ | T- | T= |')),
2 filler char (16) init ('FAST LINES '),
2 fast_sep char (121)
init ((' +----------+------+---------' ||
'-+---------+-------+-----+-----+-----+-----+')),
2 fast_init char (121)
init ((' | - | - | -' ||
' | : - | - | - | - | - | - |')),
2 fast_head char (121)
init ((' | Fastest | #R | KM' ||
' | Time | V= | T | R | T | R |')),
2 fast_head_d char (121)
init ((' | Fastest | #D | KM' ||
' | Time | V= | T | D | T | D |')),
2 filler char (16) init ('FAST LINES '),
2 fast_sep_t char (121)
init ((' +----------+------+---------' ||
'-+---------+-------+-----+-----+')),
2 fast_init_t char (121)
init ((' | - | - | -' ||
' | : - | - | - | - |')),
2 fast_head_t char (121)
init ((' | Fastest | #T | KM' ||
' | Time | V= | T | T |')),
2 filler char (16) init ('RIDE LINES '),
2 ride_sep char (121)
init ((' +--------+---------' ||
'-+---------+-------+-----+-----+-----+-----+')),
2 ride_init char (121)
init ((' | - | ' ||
' | : | | | | | |')),
2 ride_head_r char (121)
init ((' | V+ #R | KM' ||
' | Time | V= | T | R | T | R |')),
2 ride_head_d char (121)
init ((' | V+ #R | KM' ||
' | Time | V= | T | D | T | D |')),
1 2 filler char (16) init ('RIDE LINES '),
2 ride_sep_t char (121)
init (' +--------+----------+---------+-------+-----+-----+'),
2 ride_init_t char (121)
init (' | - | | : | | | |'),
2 ride_head_t char (121)
init (' | V+ #T | KM | Time | V= | T | T |'),
2 filler char (16) init ('FILA LINES '),
2 fila_init char (121)
init ((' | |' || (2)' | | - - |')),
2 fila_sep char (121)
init ((' +--------+' || (2)'------+------+------------+')),
2 fila_head(4) char (121)
init ((' +--------+' || (2)'--------------------------+'),
(' | | First |' ||
' Last |'),
(' | +' || (2)'------+------+------------+'),
(' | |' || (2)' Trip | Ride | Date |')),
2 filler char (16) init ('SWAIT LINES '),
2 swait_sep char (121)
init ((' +------+------+' ||
(3)'------+---------+----------+')),
2 swait_init char (121)
init ((' | | - |' ||
(3)' - | - | - |')),
2 swait_head(4) char (121)
init ((' +------+------+' ||
(3)'---------------------------+'),
(' | | |' ||
' - 1:00 |' ||
' 1:00 + |' ||
' Total |'),
(' | | No +' ||
(3)'------+---------+----------+'),
(' | | wait |' ||
(3)' # | Time | W= |')),
2 filler char (16) init ('INTERVAL LINES '),
2 iv_sep char (121)
init ((' +-----+------+------+------+------+------+')),
2 iv_init char (121)
init ((' | Tot | - | - | - | - | - |')),
2 iv_head char (121)
init ((' | Cty | < 6 | < 12 | < 18 | < 24 | Tot |')),
1 2 filler char (16) init ('BOCRO DTV LINES '),
2 bocro_dtv_sep char (121)
init ((' +----+------+------+--------+-------+-------+' ||
'-------------------------+')),
2 bocro_dtv_init char (121)
init ((' | | - | - | - | - | - |' ||
' |')),
2 bocro_dtv_head char (121)
init ((' | #B | Trip | Ride | KM | Time | V= |' ||
' Countries |')),
2 filler char (16) init ('DEPLOCS_S LINES '),
2 dep_s_init char (121)
init ((' | Tot ' ||
'| - | - | - | - | - | - ' ||
'| - | - | - | - | - | - |')),
2 filler char (16) init ('VARIOUS CHAR '),
2 day(0:6) char (3)
init ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'),
2 month(12) char (3)
init ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
2 monthl(12) char (9)
init ('January ', 'February ', 'March ',
'April ', 'May ', 'June ',
'July ', 'August ', 'September',
'October ', 'November ', 'December '),
2 filler char (16) init ('FAST R HEADINGS '),
2 f_ride_d(4) char (8)
init ('Fastest ',
'Slowest ',
'Min Ride',
'Max Ride'),
2 filler char (16) init ('FAST D HEADINGS '),
2 f_day_d(4) char (8)
init ('Fastest ',
'Slowest ',
'Min Day ',
'Max Day '),
2 filler char (16) init ('FAST T HEADINGS '),
2 f_trip_d(4) char (8)
init ('Fastest ',
'Slowest ',
'Min Trip',
'Max Trip'),
1 2 filler char (16) init ('VL +/- R HEADING'),
2 f_ride(4) char (8)
init ('V+ #R |',
'V- #R |',
'L+ #R |',
'L- #R |'),
2 filler char (16) init ('VL +/- D HEADING'),
2 f_day(4) char (8)
init ('V+ #D |',
'V- #D |',
'L+ #D |',
'L- #D |'),
2 filler char (16) init ('VL +/- T HEADING'),
2 f_trip(4) char (8)
init ('V+ #T |',
'V- #T |',
'L+ #T |',
'L- #T |'),
1 /*--------------------------------------------------------------+
| List of all countries |
| |
| - plate: license plate sign |
| - iso : ISO 3166-1 code |
| - stat : status |
| ' ': official |
| '*': unofficial |
| - name : name of the country |
+--------------------------------------------------------------*/
2 cplates(235),
3 plate char (4)
init ('A ', /* Austria */
'AFG ', /* Afghanistan */
'AG ', /* * Antigua and Barbuda */
'AL ', /* Albania */
'AM ', /* Armenia */
'AND ', /* Andorra */
'ANG ', /* * Angola */
'ARK ', /* * Antarctica */
'ARU ', /* * Aruba */
'AS ', /* * Asturias */
'AUA ', /* * Aruba */
'AUS ', /* Australia */
'AX ', /* * Åland Islands */
'AXA ', /* * Anguilla */
'AZ ', /* Azerbaijan */
'B ', /* Belgium */
'BD ', /* Bangladesh */
'BDS ', /* Barbados */
'BF ', /* Burkina Faso */
'BG ', /* Bulgaria */
'BH ', /* Belize */
'BHT ', /* * Bhutan */
'BIH ', /* Bosnia and Herzegovina */
'BOL ', /* Bolivia */
'BR ', /* Brazil */
'BRN ', /* Bahrain */
'BRU ', /* Brunei */
'BS ', /* Bahamas */
'BUR ', /* Myanmar */
'BVI ', /* British Virgin Islands */
'BW ', /* Botswana */
'BY ', /* Belarus */
'BZ ', /* * Belize */
'C ', /* Cuba */
'CAM ', /* Cameroon */
'CDN ', /* Canada */
'CGO ', /* Democratic Republic of the Congo */
'CH ', /* Switzerland */
'CHN ', /* * People's Republic of China */
'CI ', /* Ivory Coast (Côte d'Ivoire) */
'CL ', /* Sri Lanka */
'CO ', /* Colombia */
1 'COM ', /* * Comoros */
'CR ', /* Costa Rica */
'CV ', /* * Cape Verde */
'CY ', /* Cyprus */
'CYM ', /* * Wales */
'CZ ', /* Czech Republic */
'D ', /* Germany */
'DJI ', /* * Djibouti */
'DK ', /* Denmark */
'DOM ', /* Dominican Republic */
'DY ', /* Benin */
'DZ ', /* Algeria */
'E ', /* Spain */
'EAK ', /* Kenya */
'EAT ', /* Tanzania */
'EAU ', /* Uganda */
'EAZ ', /* Zanzibar */
'EC ', /* Ecuador */
'ENG ', /* * England */
'ER ', /* Eritrea */
'ES ', /* El Salvador */
'EST ', /* Estonia */
'ET ', /* Egypt */
'ETH ', /* Ethiopia */
'F ', /* France */
'FIN ', /* Finland */
'FJI ', /* Fiji */
'FL ', /* Liechtenstein */
'FO ', /* Faroe Islands */
'FSM ', /* * Federated States of Micronesia */
'G ', /* Gabon */
'GB ', /* United Kingdom (UK) */
'GBA ', /* Alderney */
'GBG ', /* Guernsey */
'GBJ ', /* Jersey */
'GBM ', /* Isle of Man */
'GBZ ', /* Gibraltar */
'GCA ', /* Guatemala */
'GE ', /* Georgia */
'GH ', /* Ghana */
'GQ ', /* * Equatorial Guinea */
'GR ', /* Greece */
'GUY ', /* Guyana */
'GW ', /* * Guinea-Bissau */
'H ', /* Hungary */
'HK ', /* * Hong Kong */
'HKJ ', /* Jordan */
'HN ', /* * Honduras */
'HR ', /* Croatia */
'I ', /* Italy */
'IL ', /* Israel */
'IND ', /* India */
'IR ', /* Iran */
1 'IRL ', /* Ireland */
'IRQ ', /* Iraq */
'IS ', /* Iceland */
'J ', /* Japan */
'JA ', /* Jamaica */
'K ', /* Cambodia */
'KAN ', /* * Saint Kitts and Nevis */
'KGZ ', /* Kyrgyzstan */
'KIR ', /* * Kiribati */
'KN ', /* * Greenland */
'KP ', /* * Democratic People's Republic of Korea */
'KS ', /* Kyrgyzstan */
'KSA ', /* Saudi Arabia */
'KWT ', /* Kuwait */
'KZ ', /* Kazakhstan */
'L ', /* Luxembourg */
'LAO ', /* Laos */
'LAR ', /* Libya */
'LB ', /* Liberia */
'LS ', /* Lesotho */
'LT ', /* Lithuania */
'LV ', /* Latvia */
'M ', /* Malta */
'MA ', /* Morocco */
'MAL ', /* Malaysia */
'MC ', /* Monaco */
'MD ', /* Moldova */
'MEX ', /* Mexico */
'MGL ', /* Mongolia */
'MH ', /* * Marshall Islands */
'MK ', /* Macedonia (NMK) */
'MNE ', /* Montenegro */
'MO ', /* * Macau */
'MOC ', /* Mozambique */
'MS ', /* Mauritius */
'MV ', /* * Maldives */
'MW ', /* Malawi */
'N ', /* Norway */
'NA ', /* Netherlands Antilles */
'NAM ', /* Namibia */
'NAU ', /* Nauru */
'NC ', /* * New Caledonia */
'NEP ', /* Nepal */
'NI ', /* * Northern Ireland */
'NIC ', /* Nicaragua */
'NL ', /* Netherlands */
'NMK ', /* North Macedonia */
'NZ ', /* New Zealand */
'OM ', /* * Oman */
'P ', /* Portugal */
'PA ', /* Panama */
'PAL ', /* * Palau */
'PE ', /* Peru */
'PK ', /* Pakistan */
1 'PL ', /* Poland */
'PMR ', /* * Transnistria */
'PNG ', /* Papua New Guinea */
'PR ', /* * Puerto Rico */
'PS ', /* * Palestine */
'PY ', /* Paraguay */
'Q ', /* Qatar */
'RA ', /* Argentina */
'RB ', /* Botswana */
'RC ', /* Republic of China (Taiwan) */
'RCA ', /* Central African Republic */
'RCB ', /* Republic of the Congo */
'RCH ', /* Chile */
'RG ', /* Guinea */
'RGB ', /* * Guinea-Bissau */
'RH ', /* Haiti */
'RI ', /* Indonesia */
'RIM ', /* Mauritania */
'RKS ', /* * Kosovo */
'RL ', /* Lebanon */
'RM ', /* Madagascar */
'RMM ', /* Mali */
'RN ', /* Niger */
'RO ', /* Romania */
'ROK ', /* Republic of Korea */
'ROU ', /* Uruguay (UY) */
'RP ', /* Philippines */
'RSM ', /* San Marino */
'RU ', /* Burundi */
'RUS ', /* Russia */
'RWA ', /* Rwanda */
'S ', /* Sweden */
'SCO ', /* * Scotland */
'SCV ', /* * Vatican City */
'SD ', /* Swaziland */
'SF ', /* Finland (FIN) */
'SGP ', /* Singapore */
'SK ', /* Slovakia */
'SLE ', /* * Sierra Leone */
'SLO ', /* Slovenia */
'SME ', /* Suriname */
'SMO ', /* * Sovereign Military Order of Malta */
'SN ', /* Senegal */
'SO ', /* Somalia */
'SOL ', /* * Solomon Islands */
'SRB ', /* Serbia */
'STP ', /* * Sáo Tomé and Príncipe */
'SUD ', /* Sudan */
'SY ', /* Seychelles */
'SYR ', /* Syria */
'T ', /* Thailand */
'TCH ', /* Chad */
'TD ', /* Chad */
1 'TG ', /* Togo */
'TJ ', /* Tajikistan */
'TL ', /* * Timor-Leste */
'TM ', /* Turkmenistan */
'TN ', /* Tunisia */
'TO ', /* * Tonga */
'TR ', /* Turkey */
'TT ', /* Trinidad and Tobago */
'TUV ', /* * Tuvalu */
'UA ', /* Ukraine */
'UAE ', /* United Arab Emirates */
'USA ', /* United States */
'UY ', /* Uruguay */
'UZ ', /* Uzbekistan */
'V ', /* Vatican City */
'VN ', /* Vietnam */
'VU ', /* * Vanuatu */
'WAG ', /* Gambia */
'WAL ', /* Sierra Leone */
'WAN ', /* Nigeria */
'WD ', /* Dominica */
'WG ', /* Grenada */
'WL ', /* Saint Lucia */
'WS ', /* Samoa */
'WSA ', /* * Western Sahara */
'WV ', /* Saint Vincent and the Grenadines */
'YAR ', /* Yemen */
'YU ', /* Yugoslavia */
'YV ', /* Venezuela */
'Z ', /* Zambia */
'ZA ', /* South Africa */
'ZW ', /* Zimbabwe */
'ZZZZ'), /* Dummy for initial value */
1 3 iso char (2)
init ('AT', /* Austria */
'AF', /* Afghanistan */
'AG', /* * Antigua and Barbuda */
'AL', /* Albania */
'AM', /* Armenia */
'AD', /* Andorra */
'AO', /* * Angola */
'AQ', /* * Antarctica */
'AW', /* * Aruba */
'ES', /* * Asturias */
'AW', /* * Aruba */
'AU', /* Australia */
'AX', /* * Åland Islands */
'AI', /* * Anguilla */
'AZ', /* Azerbaijan */
'BE', /* Belgium */
'BD', /* Bangladesh */
'BB', /* Barbados */
'BF', /* Burkina Faso */
'BG', /* Bulgaria */
'BZ', /* Belize */
'BT', /* * Bhutan */
'BA', /* Bosnia and Herzegovina */
'BO', /* Bolivia */
'BR', /* Brazil */
'BH', /* Bahrain */
'BN', /* Brunei */
'BS', /* Bahamas */
'MM', /* Myanmar */
'VG', /* British Virgin Islands */
'BW', /* Botswana */
'BY', /* Belarus */
'BZ', /* * Belize */
'CU', /* Cuba */
'CM', /* Cameroon */
'CA', /* Canada */
'CD', /* Democratic Republic of the Congo */
'CH', /* Switzerland */
'CN', /* * People's Republic of China */
'CI', /* Ivory Coast (Côte d'Ivoire) */
'LK', /* Sri Lanka */
'CO', /* Colombia */
1 'KM', /* * Comoros */
'CR', /* Costa Rica */
'CV', /* * Cape Verde */
'CY', /* Cyprus */
'??', /* * Wales */
'CZ', /* Czech Republic */
'DE', /* Germany */
'DJ', /* * Djibouti */
'DK', /* Denmark */
'DO', /* Dominican Republic */
'BJ', /* Benin */
'DZ', /* Algeria */
'ES', /* Spain */
'KE', /* Kenya */
'TZ', /* Tanzania */
'UG', /* Uganda */
'TZ', /* Zanzibar */
'EC', /* Ecuador */
'UK', /* * England */
'ER', /* Eritrea */
'SV', /* El Salvador */
'EE', /* Estonia */
'EG', /* Egypt */
'ET', /* Ethiopia */
'FR', /* France */
'FI', /* Finland */
'FJ', /* Fiji */
'LI', /* Liechtenstein */
'FO', /* Faroe Islands */
'FM', /* * Federated States of Micronesia */
'GA', /* Gabon */
'UK', /* United Kingdom */
'GG', /* Alderney */
'GG', /* Guernsey */
'JE', /* Jersey */
'IM', /* Isle of Man */
'GI', /* Gibraltar */
'GT', /* Guatemala */
'GE', /* Georgia */
'GH', /* Ghana */
'GQ', /* * Equatorial Guinea */
'GR', /* Greece */
'GY', /* Guyana */
'GW', /* * Guinea-Bissau */
'HU', /* Hungary */
'HK', /* * Hong Kong */
'JO', /* Jordan */
'HN', /* * Honduras */
'HR', /* Croatia */
'IT', /* Italy */
'IL', /* Israel */
'IN', /* India */
'IR', /* Iran */
1 'IE', /* Ireland */
'IQ', /* Iraq */
'IS', /* Iceland */
'JP', /* Japan */
'JM', /* Jamaica */
'KH', /* Cambodia */
'KN', /* * Saint Kitts and Nevis */
'KG', /* Kyrgyzstan */
'KI', /* * Kiribati */
'GL', /* * Greenland */
'KP', /* * Democratic People's Republic of Korea */
'KG', /* Kyrgyzstan */
'SA', /* Saudi Arabia */
'KW', /* Kuwait */
'KZ', /* Kazakhstan */
'LU', /* Luxembourg */
'LA', /* Laos */
'LY', /* Libya */
'LR', /* Liberia */
'LS', /* Lesotho */
'LT', /* Lithuania */
'LV', /* Latvia */
'MT', /* Malta */
'MA', /* Morocco */
'MY', /* Malaysia */
'MC', /* Monaco */
'MD', /* Moldova */
'MX', /* Mexico */
'MN', /* Mongolia */
'MH', /* * Marshall Islands */
'MK', /* Macedonia (NMK) */
'ME', /* Montenegro */
'MO', /* * Macau */
'MZ', /* Mozambique */
'MU', /* Mauritius */
'MV', /* * Maldives */
'MW', /* Malawi */
'NO', /* Norway */
'AN', /* Netherlands Antilles */
'NA', /* Namibia */
'NR', /* Nauru */
'NC', /* * New Caledonia */
'NP', /* Nepal */
'UK', /* * Northern Ireland */
'NI', /* Nicaragua */
'NL', /* Netherlands */
'MK', /* North Macedonia */
'NZ', /* New Zealand */
'OM', /* * Oman */
'PT', /* Portugal */
'PA', /* Panama */
'PW', /* * Palau */
'PE', /* Peru */
'PK', /* Pakistan */
1 'PL', /* Poland */
'MD', /* * Transnistria */
'PG', /* Papua New Guinea */
'PR', /* * Puerto Rico */
'PS', /* * Palestine */
'PY', /* Paraguay */
'QA', /* Qatar */
'AR', /* Argentina */
'BW', /* Botswana */
'TW', /* Republic of China (Taiwan) */
'CF', /* Central African Republic */
'CG', /* Republic of the Congo */
'CL', /* Chile */
'GN', /* Guinea */
'GW', /* * Guinea-Bissau */
'HT', /* Haiti */
'ID', /* Indonesia */
'MR', /* Mauritania */
'XK', /* * Kosovo */
'LB', /* Lebanon */
'MG', /* Madagascar */
'ML', /* Mali */
'NE', /* Niger */
'RO', /* Romania */
'KR', /* Republic of Korea */
'UY', /* Uruguay (UY) */
'PH', /* Philippines */
'SM', /* San Marino */
'BI', /* Burundi */
'RU', /* Russia */
'RW', /* Rwanda */
'SE', /* Sweden */
'UK', /* * Scotland */
'VA', /* * Vatican City */
'SZ', /* Swaziland */
'FI', /* Finland (FIN) */
'SG', /* Singapore */
'SK', /* Slovakia */
'SL', /* * Sierra Leone */
'SI', /* Slovenia */
'SR', /* Suriname */
'??', /* * Sovereign Military Order of Malta */
'SN', /* Senegal */
'SO', /* Somalia */
'SB', /* * Solomon Islands */
'RS', /* Serbia */
'ST', /* * Sáo Tomé and Príncipe */
'SD', /* Sudan */
'SC', /* Seychelles */
'SY', /* Syria */
'TH', /* Thailand */
'TD', /* Chad */
'TD', /* Chad */
1 'TG', /* Togo */
'TJ', /* Tajikistan */
'TL', /* * Timor-Leste */
'TM', /* Turkmenistan */
'TN', /* Tunisia */
'TO', /* * Tonga */
'TR', /* Turkey */
'TT', /* Trinidad and Tobago */
'TV', /* * Tuvalu */
'UA', /* Ukraine */
'AE', /* United Arab Emirates */
'US', /* United States */
'UY', /* Uruguay */
'UZ', /* Uzbekistan */
'VA', /* Vatican City */
'VN', /* Vietnam */
'VU', /* * Vanuatu */
'GM', /* Gambia */
'SL', /* Sierra Leone */
'NG', /* Nigeria */
'DM', /* Dominica */
'GD', /* Grenada */
'LC', /* Saint Lucia */
'WS', /* Samoa */
'EH', /* * Western Sahara */
'VC', /* Saint Vincent and the Grenadines */
'YE', /* Yemen */
'YU', /* Yugoslavia */
'VE', /* Venezuela */
'ZM', /* Zambia */
'ZA', /* South Africa */
'ZW', /* Zimbabwe */
'ZZ'), /* Dummy for initial value */
1 3 name char (56) var
init (/* A */ 'Austria',
/* AFG */ 'Afghanistan',
/* AG * */ 'Antigua and Barbuda',
/* AL */ 'Albania',
/* AM */ 'Armenia',
/* AND */ 'Andorra',
/* ANG * */ 'Angola',
/* ARK * */ 'Antarctica',
/* ARU * */ 'Aruba',
/* AS * */ 'Asturias',
/* AUA * */ 'Aruba',
/* AUS */ 'Australia',
/* AX * */ 'Åland Islands',
/* AXA * */ 'Anguilla',
/* AZ */ 'Azerbaijan',
/* B */ 'Belgium',
/* BD */ 'Bangladesh',
/* BDS */ 'Barbados',
/* BF */ 'Burkina Faso',
/* BG */ 'Bulgaria',
/* BH */ 'Belize',
/* BHT * */ 'Bhutan',
/* BIH */ 'Bosnia and Herzegovina',
/* BOL */ 'Bolivia',
/* BR */ 'Brazil',
/* BRN */ 'Bahrain',
/* BRU */ 'Brunei',
/* BS */ 'Bahamas',
/* BUR */ 'Myanmar',
/* BVI */ 'British Virgin Islands',
/* BW */ 'Botswana',
/* BY */ 'Belarus',
/* BZ * */ 'Belize',
/* C */ 'Cuba',
/* CAM */ 'Cameroon',
/* CDN */ 'Canada',
/* CGO */ 'Democratic Republic of the Congo',
/* CH */ 'Switzerland',
/* CHN * */ 'People''s Republic of China',
/* CI */ 'Ivory Coast (Côte d''Ivoire)',
/* CL */ 'Sri Lanka',
/* CO */ 'Colombia',
1 /* COM * */ 'Comoros',
/* CR */ 'Costa Rica',
/* CV * */ 'Cape Verde',
/* CY */ 'Cyprus',
/* CYM * */ 'Wales',
/* CZ */ 'Czech Republic',
/* D */ 'Germany',
/* DJI * */ 'Djibouti',
/* DK */ 'Denmark',
/* DOM */ 'Dominican Republic',
/* DY */ 'Benin',
/* DZ */ 'Algeria',
/* E */ 'Spain',
/* EAK */ 'Kenya',
/* EAT */ 'Tanzania',
/* EAU */ 'Uganda',
/* EAZ */ 'Zanzibar',
/* EC */ 'Ecuador',
/* ENG * */ 'England',
/* ER */ 'Eritrea',
/* ES */ 'El Salvador',
/* EST */ 'Estonia',
/* ET */ 'Egypt',
/* ETH */ 'Ethiopia',
/* F */ 'France',
/* FIN */ 'Finland',
/* FJI */ 'Fiji',
/* FL */ 'Liechtenstein',
/* FO */ 'Faroe Islands',
/* FSM * */ 'Federated States of Micronesia',
/* G */ 'Gabon',
/* GB */ 'United Kingdom (UK)',
/* GBA */ 'Alderney',
/* GBG */ 'Guernsey',
/* GBJ */ 'Jersey',
/* GBM */ 'Isle of Man',
/* GBZ */ 'Gibraltar',
/* GCA */ 'Guatemala',
/* GE */ 'Georgia',
/* GH */ 'Ghana',
/* GQ * */ 'Equatorial Guinea',
/* GR */ 'Greece',
/* GUY */ 'Guyana',
/* GW * */ 'Guinea-Bissau',
/* H */ 'Hungary',
/* HK * */ 'Hong Kong',
/* HKJ */ 'Jordan',
/* HN * */ 'Honduras',
/* HR */ 'Croatia',
/* I */ 'Italy',
/* IL */ 'Israel',
/* IND */ 'India',
/* IR */ 'Iran',
1 /* IRL */ 'Ireland',
/* IRQ */ 'Iraq',
/* IS */ 'Iceland',
/* J */ 'Japan',
/* JA */ 'Jamaica',
/* K */ 'Cambodia',
/* KAN * */ 'Saint Kitts and Nevis',
/* KGZ */ 'Kyrgyzstan',
/* KIR * */ 'Kiribati',
/* KN * */ 'Greenland',
/* KP * */ 'Democratic People''s Republic of Korea',
/* KS */ 'Kyrgyzstan',
/* KSA */ 'Saudi Arabia',
/* KWT */ 'Kuwait',
/* KZ */ 'Kazakhstan',
/* L */ 'Luxembourg',
/* LAO */ 'Laos',
/* LAR */ 'Libya',
/* LB */ 'Liberia',
/* LS */ 'Lesotho',
/* LT */ 'Lithuania',
/* LV */ 'Latvia',
/* M */ 'Malta',
/* MA */ 'Morocco',
/* MAL */ 'Malaysia',
/* MC */ 'Monaco',
/* MD */ 'Moldova',
/* MEX */ 'Mexico',
/* MGL */ 'Mongolia',
/* MH * */ 'Marshall Islands',
/* MK */ 'Macedonia (NMK)',
/* MNE */ 'Montenegro',
/* MO * */ 'Macau',
/* MOC */ 'Mozambique',
/* MS */ 'Mauritius',
/* MV * */ 'Maldives',
/* MW */ 'Malawi',
/* N */ 'Norway',
/* NA */ 'Netherlands Antilles',
/* NAM */ 'Namibia',
/* NAU */ 'Nauru',
/* NC * */ 'New Caledonia',
/* NEP */ 'Nepal',
/* NI * */ 'Northern Ireland',
/* NIC */ 'Nicaragua',
/* NL */ 'Netherlands',
/* NMK */ 'North Macedonia',
/* NZ */ 'New Zealand',
/* OM * */ 'Oman',
/* P */ 'Portugal',
/* PA */ 'Panama',
/* PAL * */ 'Palau',
/* PE */ 'Peru',
/* PK */ 'Pakistan',
1 /* PL */ 'Poland',
/* PMR * */ 'Transnistria',
/* PNG */ 'Papua New Guinea',
/* PR * */ 'Puerto Rico',
/* PS * */ 'Palestine',
/* PY */ 'Paraguay',
/* Q */ 'Qatar',
/* RA */ 'Argentina',
/* RB */ 'Botswana',
/* RC */ 'Republic of China (Taiwan)',
/* RCA */ 'Central African Republic',
/* RCB */ 'Republic of the Congo',
/* RCH */ 'Chile',
/* RG */ 'Guinea',
/* RGB * */ 'Guinea-Bissau',
/* RH */ 'Haiti',
/* RI */ 'Indonesia',
/* RIM */ 'Mauritania',
/* RKS * */ 'Kosovo',
/* RL */ 'Lebanon',
/* RM */ 'Madagascar',
/* RMM */ 'Mali',
/* RN */ 'Niger',
/* RO */ 'Romania',
/* ROK */ 'Republic of Korea',
/* ROU */ 'Uruguay (UY)',
/* RP */ 'Philippines',
/* RSM */ 'San Marino',
/* RU */ 'Burundi',
/* RUS */ 'Russia',
/* RWA */ 'Rwanda',
/* S */ 'Sweden',
/* SCO * */ 'Scotland',
/* SCV * */ 'Vatican City',
/* SD */ 'Swaziland',
/* SF */ 'Finland (FIN)',
/* SGP */ 'Singapore',
/* SK */ 'Slovakia',
/* SLE * */ 'Sierra Leone',
/* SLO */ 'Slovenia',
/* SME */ 'Suriname',
/* SMO * */ 'Sovereign Military Order of Malta',
/* SN */ 'Senegal',
/* SO */ 'Somalia',
/* SOL * */ 'Solomon Islands',
/* SRB */ 'Serbia',
/* STP * */ 'Sáo Tomé and Príncipe',
/* SUD */ 'Sudan',
/* SY */ 'Seychelles',
/* SYR */ 'Syria',
/* T */ 'Thailand',
/* TCH */ 'Chad',
/* TD */ 'Chad',
1 /* TG */ 'Togo',
/* TJ */ 'Tajikistan',
/* TL * */ 'Timor-Leste',
/* TM */ 'Turkmenistan',
/* TN */ 'Tunisia',
/* TO * */ 'Tonga',
/* TR */ 'Turkey',
/* TT */ 'Trinidad and Tobago',
/* TUV * */ 'Tuvalu',
/* UA */ 'Ukraine',
/* UAE */ 'United Arab Emirates',
/* USA */ 'United States',
/* UY */ 'Uruguay',
/* UZ */ 'Uzbekistan',
/* V */ 'Vatican City',
/* VN */ 'Vietnam',
/* VU * */ 'Vanuatu',
/* WAG */ 'Gambia',
/* WAL */ 'Sierra Leone',
/* WAN */ 'Nigeria',
/* WD */ 'Dominica',
/* WG */ 'Grenada',
/* WL */ 'Saint Lucia',
/* WS */ 'Samoa',
/* WSA * */ 'Western Sahara',
/* WV */ 'Saint Vincent and the Grenadines',
/* YAR */ 'Yemen',
/* YU */ 'Yugoslavia',
/* YV */ 'Venezuela',
/* Z */ 'Zambia',
/* ZA */ 'South Africa',
/* ZW */ 'Zimbabwe',
/* ZZZZ */ 'ZZZZ'),
2 filler char (16) init ('UTF-8 LENGTHS '),
2 utf8 char (224)
init (('1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c'x ||
'1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c'x ||
'1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c'x ||
'1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c'x ||
'1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c'x ||
'1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c'x ||
'0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c'x ||
'0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c'x ||
'0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c'x ||
'0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c'x ||
'0c0c1c1c1c1c1c1c1c1c1c1c1c1c1c1c'x ||
'1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c'x ||
'1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c'x ||
'1c1c1c1c1c0c0c0c0c0c0c0c0c0c0c0c'x)),
1 2 filler char (16) init ('DEPARTURE MODES '),
2 depmode(0:2) char (6) init ('Thumb ',
'Ask ',
/* 'Invite', */ /*tao*/
'Other '),
2 eor_lift_static char (32)
init ('XXXXXX END OF LIFT STATIC XXXXXX');
1/**********************************************************************
* LIFT - Overlays for print lines *
**********************************************************************/
dcl 1 lift_line based(line_ptr),
2 filler char (3),
2 trip pic 'zzz9',
2 filler char (3),
2 ride pic 'zzz9',
2 filler char (3),
2 cday char (3),
2 filler char (3),
2 km pic '(3)z9v.9',
2 filler char (3),
2 hhmm,
3 hh pic 'z9',
3 hs char (1),
3 mm pic '99',
2 filler char (3),
2 v pic 'zz9v.9',
2 filler char (3),
2 nat char (4),
2 filler char (2),
2 type char (4),
2 filler char (3),
2 cnty char (4),
2 filler char (2),
2 wait,
3 whh pic 'z9.',
3 wmm pic '99',
2 filler char (3),
2 split char (1),
2 filler char (3),
2 dep,
3 dhh pic 'z9',
3 dt char (1),
3 dmm pic '99',
2 filler char (3),
2 arr,
3 ahh pic 'z9',
3 atz char (1),
3 amm pic '99',
2 filler char (3),
2 date,
3 year pic '9999',
3 filler char (1),
3 mnth pic '99',
3 filler char (1),
3 day pic '99';
1dcl 1 tryr_line based(line_ptr),
2 filler char (3),
2 trip pic 'zzz9',
2 filler char (3),
2 #d pic 'zzz9',
2 filler char (3),
2 #r pic 'zzz9',
2 filler char (3),
2 km pic '(5)z9v.9',
2 filler char (3),
2 hh pic 'zzz9',
2 filler char (1),
2 mm pic '99',
2 filler char (3),
2 v pic 'zz9v.9',
2 filler char (3),
2 qual pic 'zzzzz9',
2 filler char (3),
2 d pic 'zzz9v.9',
2 filler char (3),
2 r pic 'zzz9v.9',
2 filler char (3),
2 rd pic 'z9v.99';
dcl 1 dtcns_line based(line_ptr),
2 filler char (3),
2 head char (6),
2 filler char (3),
2 data,
3 #c pic 'zzz9',
3 filler char (3),
3 km pic '(5)z9v.9',
3 filler char (3),
3 hh pic 'zzz9',
3 hs char (1),
3 mm pic '99',
3 filler char (3),
3 v pic 'zz9v.9';
1dcl 1 min_max_line based(line_ptr),
2 filler char (3),
2 mode char (4),
2 filler char (3),
2 #mima pic 'zzz9',
2 filler char (3),
2 v_maxr pic 'zz9v.9',
2 filler char (3),
2 v_minr pic 'zz9v.9',
2 filler char (3),
2 v_avg pic 'zz9v.9',
2 filler char (3),
2 l_max pic 'zzz9v.9',
2 filler char (3),
2 l_min pic 'zzz9v.9',
2 filler char (3),
2 l_avg pic 'zzz9v.9',
2 filler char (3),
2 t_max_hh pic 'z9',
2 filler char (1),
2 t_max_mm pic '99',
2 filler char (3),
2 t_min_hh pic 'z9',
2 filler char (1),
2 t_min_mm pic '99',
2 filler char (3),
2 t_avg_hh pic 'z9',
2 filler char (1),
2 t_avg_mm pic '99';
dcl 1 fast_line based(line_ptr),
2 filler char (4),
2 fastest pic '(6)z9',
2 filler char (3),
2 #mima pic 'zzz9',
2 filler char (3),
2 l_max pic '(5)z9v.9',
2 filler char (3),
2 t_max_hh pic 'zzz9',
2 hs char (1),
2 t_max_mm pic '99',
2 filler char (3),
2 f_max pic 'zz9v.9',
2 filler char (3),
2 fasts(2),
3 trip pic 'zz9',
3 filler char (3),
3 ride pic 'zz9',
3 filler char (3);
1dcl 1 ride_line based(line_ptr),
2 filler char (4),
2 #mima pic 'zzzz9',
2 filler char (3),
2 l_max pic '(5)z9v.9',
2 filler char (3),
2 t_max_hh pic 'zzz9',
2 hs char (1),
2 t_max_mm pic '99',
2 filler char (3),
2 f_max pic 'zz9v.9',
2 filler char (3),
2 fasts(2),
3 trip pic 'zz9',
3 filler char (3),
3 ride pic 'zz9',
3 filler char (3);
dcl 1 td_line based(line_ptr),
2 filler char (3),
2 trip pic 'zzz9',
2 filler char (3),
2 day pic 'zz9',
2 filler char (3),
2 km pic 'zzz9v.9',
2 filler char (3),
2 hh pic 'z9',
2 hs char (1),
2 mm pic '99',
2 filler char (3),
2 v pic 'zz9v.9',
2 filler char (3),
2 date,
3 year pic '9999',
3 filler char (1),
3 mnth pic '99',
3 filler char (1),
3 day pic '99';
1dcl 1 swait_line based(line_ptr),
2 filler char (3),
2 head char (4),
2 filler char (3),
2 none pic 'zzz9',
2 filler char (3),
2 wait(3),
3 #w pic 'zzz9',
3 filler char (3),
3 whh pic 'zzz9',
3 hs char (1),
3 wmm pic '99',
3 filler char (3),
3 w_avg,
4 whh_avg pic 'z9',
4 col1 char (1),
4 wmm_avg pic '99',
4 col2 char (1),
4 wss_avg pic '99',
3 filler char (3);
dcl 1 iv_line based(line_ptr),
2 filler char (3),
2 cnty char (4),
2 filler char (2),
2 iv(5),
3 #c pic 'zzz9',
3 filler char (3);
1/**********************************************************************
* LIFT - Main working storage *
**********************************************************************/
dcl 1 lift_work,
2 filler char (32)
init ('LIFT WORKAREA JCL PARAMETER'),
2 parm,
3 filler char (100) init ((100)' '),
2 filler char (16) init ('TYPE STRING '),
2 a_typ char (1022) var
init (('- -* V V* T ' ||
'B E F P Bus ' ||
'M Taxi PW C Tr ' ||
'Por VPor Cab VT MB ' ||
'Fer Elec V-El ')),
2 filler char (16) init ('COUNTRY STRING '),
2 a_cnty char (1022) init ('') var,
2 filler char (16) init ('NAT STRING '),
2 a_nat char (1022) init ('') var,
2 filler char (16) init ('CNAT STRING '),
2 cnat char (994) init ((994)' ') var,
2 filler char (16) init ('TYPE PICKUP '),
2 pickup_t char (1022) init ('') var,
2 filler char (16) init ('COUNTRY PICKUP '),
2 pickup_c char (1022) init ('') var,
2 filler char (16) init ('NAT PICKUP '),
2 pickup_n char (1022) init ('') var,
2 filler char (16) init ('TRIP TOTAL '),
2 trip_total,
3 filler(2) ptr init ((2)sysnull()),
3 trip fixed bin (31) init (-1),
3 #d fixed bin (31) init (0),
3 km fixed (9,1) init (0),
3 time fixed (9) init (0),
3 vx fixed (13,9) init (0),
3 qual fixed (7) init (0),
3 #r fixed (5) init (0),
3 filler char (48) init ((48)' '),
3 #trips fixed bin (31) init (0),
3 filler char (36) init ((36)' '),
1 2 filler char (16) init ('VARIOUS PICTURE '),
2 day pic 'zz9' init (0),
2 trip_pic pic 'zzz9' init (0),
2 year_pic pic '9999' init (0),
2 filler char (1),
2 filler char (16) init ('EBCDIC-2-UTF8 '),
2 b47(47) fixed (1),
2 filler char (1),
/*--------------------------------------------------------------+
| Pointer triplets |
| |
| - xxxx_top: pointer to current item in the list |
| - xxxx_top: pointer to first item in the list |
| - xxxx_end: pointer to last item in the list |
+--------------------------------------------------------------*/
2 filler char (16) init ('LIFT PTR TOP END'),
2 lift_ptr ptr init (sysnull()),
2 lift_top ptr init (sysnull()),
2 lift_end ptr init (addr(lift_top)),
2 filler char (16) init ('TRIP PTR TOP END'),
2 trip_ptr ptr init (sysnull()),
2 trip_top ptr init (sysnull()),
2 trip_end ptr init (addr(trip_top)),
2 filler char (16) init ('TYPE PTR TOP END'),
2 type_ptr ptr init (sysnull()),
2 type_top ptr init (sysnull()),
2 type_end ptr init (addr(type_top)),
2 filler char (16) init ('CNTY PTR TOP END'),
2 cnty_ptr ptr init (sysnull()),
2 cnty_top ptr init (sysnull()),
2 cnty_end ptr init (addr(cnty_top)),
2 filler char (16) init ('NAT PTR TOP END'),
2 nat_ptr ptr init (sysnull()),
2 nat_top ptr init (sysnull()),
2 nat_end ptr init (addr(nat_top)),
2 filler char (16) init ('YEAR PTR TOP END'),
2 year_ptr ptr init (sysnull()),
2 year_top ptr init (sysnull()),
2 year_end ptr init (addr(year_top)),
2 filler char (16) init ('RTOT PTR TOP END'),
2 rtot_ptr ptr init (sysnull()),
2 rtot_top ptr init (sysnull()),
2 rtot_end ptr init (addr(rtot_top)),
1 2 filler char (16) init ('DTOT PTR TOP END'),
2 dtot_ptr ptr init (sysnull()),
2 dtot_top ptr init (sysnull()),
2 dtot_end ptr init (addr(dtot_top)),
2 filler char (16) init ('TTOT PTR TOP END'),
2 ttot_ptr ptr init (sysnull()),
2 ttot_top ptr init (sysnull()),
2 ttot_end ptr init (addr(ttot_top)),
2 filler char (16) init ('CTOT PTR TOP END'),
2 ctot_ptr ptr init (sysnull()),
2 ctot_top ptr init (sysnull()),
2 ctot_end ptr init (addr(ctot_top)),
2 filler char (16) init ('NTOT PTR TOP END'),
2 ntot_ptr ptr init (sysnull()),
2 ntot_top ptr init (sysnull()),
2 ntot_end ptr init (addr(ntot_top)),
2 filler char (16) init ('YTOT PTR TOP END'),
2 ytot_ptr ptr init (sysnull()),
2 ytot_top ptr init (sysnull()),
2 ytot_end ptr init (addr(ytot_top)),
2 filler char (16) init ('VTOT PTR TOP END'),
2 vtot_ptr ptr init (sysnull()),
2 vtot_top ptr init (sysnull()),
2 vtot_end ptr init (addr(vtot_top)),
2 filler char (16) init ('FAST PTR TOP END'),
2 fast_ptr ptr init (sysnull()),
2 fast_top ptr init (sysnull()),
2 fast_end ptr init (addr(fast_top)),
2 filler char (16) init ('WAIT PTR TOP END'),
2 wift_ptr ptr init (sysnull()),
2 wift_top ptr init (sysnull()),
2 wift_end ptr init (sysnull()),
2 filler char (16) init ('SPLI PTR TOP END'),
2 split_ptr ptr init (sysnull()),
2 split_top ptr init (sysnull()),
2 split_end ptr init (addr(split_top)),
2 filler char (16) init ('P24H PTR TOP END'),
2 p24h_ptr ptr init (sysnull()),
2 p24h_top ptr init (sysnull()),
2 p24h_end ptr init (addr(p24h_top)),
1 2 filler char (16) init ('KTV PTR TOP END'),
2 ktv_ptr ptr init (sysnull()),
2 ktv_top ptr init (sysnull()),
2 ktv_end ptr init (addr(ktv_top)),
2 filler char (16) init ('DEP PTR TOP END'),
2 dep_ptr ptr init (sysnull()),
2 dep_top ptr init (sysnull()),
2 dep_end ptr init (addr(dep_top)),
1 /*--------------------------------------------------------------+
| Various pointers |
| |
| - nxt_ptr General purpose |
| - prv_lift Pointer to initialise previous pointers |
| - prv_day Pointer to initialise previous pointers |
| - pp_ptr Short lift |
| - day_ptr Current DAY_LIST |
| - ll_top First unsplit LIFT_LIST |
| - ll_end Last unsplit LIFT_LIST |
| - ctot_toq Current ctot_top |
| - pu_naco_ptr Table to process pickup data |
| - pu_coty_ptr Table to process pickup data |
| - pu_naty_ptr Table to process pickup data |
| - td_top First day in combined DAY_LIST |
| - run_ptr Current item in nationalites scan |
| - s_ty_ptr Least recently used type_list |
| - s_co_ptr Least recently used cnty_list |
| - s_na_ptr Least recently used nat_list |
+--------------------------------------------------------------*/
2 filler char (16) init ('VARIOUS PTRS 1 '),
2 nxt_ptr ptr init (sysnull()),
2 prv_lift ptr init (sysnull()),
2 prv_day ptr init (sysnull()),
2 pp_ptr ptr init (sysnull()),
2 day_ptr ptr init (sysnull()),
2 ll_top ptr init (sysnull()),
2 ll_end ptr init (sysnull()),
2 ctot_toq ptr init (sysnull()),
2 pu_naco_ptr ptr init (sysnull()),
2 pu_coty_ptr ptr init (sysnull()),
2 pu_naty_ptr ptr init (sysnull()),
2 td_top ptr init (sysnull()),
2 run_ptr ptr init (sysnull()),
2 s_ty_ptr ptr init (sysnull()),
2 s_co_ptr ptr init (sysnull()),
2 s_na_ptr ptr init (sysnull()),
1 /*--------------------------------------------------------------+
| More various pointers |
| |
| - nat_mptr Middle of nat_list |
| - lift_own First lift_list for a ride |
| - p24h_topw Working top of p24h_list |
| - p24h_topz First id=0 item of p24h_list |
| - tarea_ptr Area to hold TTOT_LIST items |
| - carea_ptr Area to hold CTOT_LIST items |
| - narea_ptr Area to hold NTOT_LIST items |
| - ltd_ptr Common head of lift/trip/day list |
| - depy_ptr Departure types per year |
| - depy_top Departure types per year - first year |
+--------------------------------------------------------------*/
2 filler char (16) init ('VARIOUS PTRS 2 '),
2 nat_mptr ptr init (sysnull()),
2 lift_own ptr init (sysnull()),
2 p24h_topw ptr init (sysnull()),
2 p24h_topz ptr init (sysnull()),
2 tarea_ptr ptr init (sysnull()),
2 carea_ptr ptr init (sysnull()),
2 narea_ptr ptr init (sysnull()),
2 ltd_ptr ptr init (sysnull()),
2 depy_ptr ptr init (sysnull()),
2 depy_top ptr init (sysnull()),
1 /*--------------------------------------------------------------+
| Initialised pointers |
| |
| - total_ptr Address of trip_total record |
| - liftrec_ptr Input record |
| - line_ptr Print line |
| - static_ptr Address of static storage |
+--------------------------------------------------------------*/
2 filler char (16) init ('INIT POINTERS '),
2 total_ptr ptr init (addr(trip_total)),
2 liftrec_ptr ptr init (addr(liftrec)),
2 line_ptr ptr init (addr(line)),
2 static_ptr ptr init (addr(lift_static)),
/*--------------------------------------------------------------+
| Other pointers |
| |
| - save_lift_ptr -+- Save pointers |
| - save_cnty_top | |
| - save_cnty_end | |
| - save_fast_top | |
| - save_fast_end -+ |
| - lws_tab_ptr Table of pointers to clean lift_list's/waits |
+--------------------------------------------------------------*/
2 filler char (16) init ('OTHER POINTERS '),
2 save_lift_ptr ptr init (sysnull()),
2 save_cnty_top ptr init (sysnull()),
2 save_cnty_end ptr init (sysnull()),
2 save_fast_top ptr init (sysnull()),
2 save_fast_end ptr init (sysnull()),
2 lws_tab_ptr ptr init (sysnull()),
/*--------------------------------------------------------------+
| - visit: |
| '1': visited |
| '0': unvisited |
| - hitch: |
| 'H': hitched-in |
| '*': hitched through only |
| - local: |
| '+': in-country ride with local |
| '-': only out-of-country ride with nationality |
+--------------------------------------------------------------*/
2 filler char (16) init ('PLATE DATA '),
2 plates(233),
3 visit bit (1) init ((233)((1)'0'b)) aligned,
3 hitch char (1) init ((233)((1)' ')),
3 local char (1) init ((233)((1)' ')),
3 filler char (1),
2 filler char (16) init ('OUTFILE '),
2 outfile file,
1 2 filler char (16) init ('CALENDAR DAYS '),
2 cdays(12,0:31) fixed bin (31) init ((384)0),
2 filler char (16) init ('PICKUP DAYS '),
2 pdays(12,0:31) fixed bin (31) init ((384)0),
2 filler char (16) init ('PICKUP WEEKDAYS '),
2 wdays(0:7,0:31),
3 #pw fixed bin (31) init ((256)0),
3 km fixed (9,1) init ((256)0),
3 time fixed (9) init ((256)0),
3 filler char (2),
2 filler char (16) init ('CALENDAR RTYS '),
2 crty(12,0:31,4) fixed bin (31) init ((1536)0),
/*---------------------------------------------------------------
2 filler char (16) init ('CALENDAR TRIPS '),
2 ct_mm(12,0:1) fixed bin (31) init ((12)(9999,0)),
2 filler char (16) init ('CALENDAR YEARS '),
2 cy_mm(12,0:1) fixed bin (31) init ((12)(9999,0)),
---------------------------------------------------------------*/
2 filler char (16) init ('HOURLY TOTALS '),
2 hours(0:7,0:24) fixed bin (31) init ((200)0),
2 filler char (16) init ('VARIOUS CHAR '),
2 heading char (4) init ((4)' '),
2 nat_mid char (4) init ((4)' '),
2 tzc_cnty char (4) init ((4)' '),
2 tcn_t char (5) init ((5)' '),
2 tcn_c char (5) init ((5)' '),
2 tcn_n char (5) init ((5)' '),
2 line char (121) init ((121)' '),
2 filler char (0),
2 filler char (16) init ('BIT SWITCHES '),
2 bits aligned,
3 @eof bit (1) init ('0'b),
3 @first bit (1) init ('0'b),
3 @summary bit (1) init ('0'b),
3 @trip bit (1) init ('0'b),
3 @type bit (1) init ('0'b),
3 @cnty bit (1) init ('0'b),
3 @nat bit (1) init ('0'b),
3 @day bit (1) init ('0'b),
3 @year bit (1) init ('0'b),
3 @nested bit (1) init ('0'b),
3 @irwait bit (1) init ('0'b),
3 @in_cnty bit (1) init ('0'b),
3 @hash bit (1) init ('0'b),
3 @tsum bit (1) init ('0'b),
3 @next bit (1) init ('0'b),
3 @ftrip bit (1) init ('0'b),
3 filler char (0),
1 2 filler char (16) init ('ASCII '),
2 ascii char (224) init ('') var,
2 filler char (2),
2 filler char (16) init ('KTV MAX - CUR '),
2 ktv,
3 maxk,
4 km fixed (9,1) init (0),
4 vx fixed (13,9) init (0),
3 maxt,
4 time fixed (9) init (0),
4 vx fixed (13,9) init (0),
3 maxv,
4 vx fixed (13,9) init (0),
4 km fixed (9,1) init (0),
3 curk,
4 km fixed (9,1) init (0),
4 vx fixed (13,9) init (0),
4 kptr ptr init (sysnull()),
3 curt,
4 time fixed (9) init (0),
4 vx fixed (13,9) init (0),
4 tptr ptr init (sysnull()),
3 curv,
4 vx fixed (13,9) init (0),
4 km fixed (9,1) init (0),
4 vptr ptr init (sysnull()),
2 filler char (16) init ('VARIOUS FIXED '),
2 wt_avg,
3 w_hh fixed (3) init (0),
3 filler char (1) init (':'),
3 w_mm fixed (3) init (0),
3 filler char (1) init (':'),
3 w_ss fixed (3) init (0),
2 dtot,
3 l_max fixed (9,1) init (0),
3 l_min fixed (9,1) init (9999.9),
3 t_max fixed (9) init (0),
3 t_min fixed (9) init (5999),
3 v_max fixed (13,9) init (0),
3 v_min fixed (13,9) init (9999.999999999),
3 filler char (2),
2 filler char (16) init ('GLOBAL BORDERS '),
2 gborders(8),
3 #c fixed bin (31) init ((8)0),
3 p_d ptr init ((8)sysnull()),
3 p_t ptr init ((8)sysnull()),
3 p_v ptr init ((8)sysnull()),
1 2 filler char (16) init ('VARIOUS FIXED '),
2 dtime fixed (5) init (0),
2 atime fixed (5) init (0),
2 etime fixed (5) init (0),
2 s_wavg fixed (5) init (-1),
2 s_sdev fixed (5) init (-1),
2 jdn_save fixed (7) init (0),
2 t_avg fixed (9) init (0),
2 sum_km fixed (9,1) init (0),
2 sum_time fixed (9) init (0),
2 vx_max_r fixed (13,9) init (-1),
2 vx_max_d fixed (13,9) init (-1),
2 vx_max_t fixed (13,9) init (-1),
2 filler char (1),
2 filler char (16) init ('TIMEZONE DATA '),
2 timezone(0:255),
3 tzc char (4) init ((256)((4)' ')),
3 tzt fixed (3) init ((256)0),
/*--------------------------------------------------------------+
| Structures for nationalities scan |
+--------------------------------------------------------------*/
2 filler char (16) init ('RUN ARRAY '),
2 run_arr(0:255),
3 run_top ptr init ((256)sysnull()),
3 run_end ptr,
3 run_cnt fixed bin (31) init ((256)0),
3 filler char (4),
2 filler char (16) init ('SPOT ARRAY '),
2 spot_arr(0:255),
3 nat char (4) init ((256)((4)' ')),
3 atl fixed bin (31) init ((256)0),
3 trip fixed bin (31) init ((256)0),
3 ride fixed bin (31) init ((256)0),
2 filler char (16) init ('DAILY TOTALS '),
2 days,
3 data(0:6),
4 #c fixed bin (31),
4 km fixed (9,1),
4 time fixed (9),
4 filler char (2),
2 filler char (16) init ('MONTHLY TOTALS '),
2 months,
3 data(12),
4 #c fixed bin (31),
4 km fixed (9,1),
4 time fixed (9),
4 filler char (2),
1 2 filler char (16) init ('IN-RIDE WAITS '),
2 irwait($irw),
3 #w fixed bin (31),
3 wtime fixed bin (31),
2 filler char (16) init ('WAIT SUMMARY '),
2 swaits(0:3),
3 #w fixed bin (31),
3 wtime fixed bin (31),
2 filler char (16) init ('WAIT TOTALS '),
2 waits(8),
3 #w fixed bin (31),
3 wtime fixed bin (31),
2 w8wtimesq fixed bin (31) init (0),
2 filler char (16) init ('WAIT TIMES '),
2 wwait(-2:33),
3 #w fixed bin (31),
3 wtime fixed bin (31),
2 filler char (16) init ('MINMAX ARRAY '),
2 minmax(0:4),
3 #mima fixed bin (31),
3 v_max fixed (13,9),
3 v_min fixed (13,9),
3 v_avg fixed (5,1),
3 l_tot fixed (9,1),
3 l_max fixed (9,1),
3 l_min fixed (9,1),
3 l_avg fixed (15,9),
3 t_tot fixed (9),
3 t_max fixed (9),
3 t_min fixed (9),
3 #rc fixed (13,8),
3 f_max fixed (15,10),
3 filler char (46),
3 fptr(2) ptr,
2 filler char (16) init ('INTERVAL DATA '),
2 g_iv,
3 #c(5) fixed bin (31) init ((5)0),
2 filler char (16) init ('SHORT DISTANCE 4'),
2 sd,
3 data(4),
4 #c fixed bin (31),
4 km fixed (9,1),
4 time fixed (9),
4 filler char (2),
3 fila(4,2) ptr init ((8)sysnull()),
1 2 filler char (16) init ('LONG DISTANCE 18'),
2 ld,
3 data(0:17),
4 #c fixed bin (31),
4 km fixed (9,1),
4 time fixed (9),
4 filler char (2),
3 fila(0:17,2) ptr init ((36)sysnull()),
2 filler char (16) init ('SPEED 21 '),
2 sp,
3 data(21),
4 #c fixed bin (31),
4 km fixed (9,1),
4 time fixed (9),
4 filler char (2),
3 fila(21,2) ptr init ((42)sysnull()),
1 2 filler char (16) init ('FIXED BIN 31 '),
2 #i fixed bin (31) init (0),
2 #j fixed bin (31) init (0),
2 #s fixed bin (31) init (0),
2 #atline fixed bin (31) init (0),
2 #lnls fixed bin (31) init (0),
2 #lnls0 fixed bin (31) init (0),
2 #lsat fixed bin (31) init (0),
2 #natscan fixed bin (31) init (3),
2 #nct fixed bin (31) init (0),
2 #pu_sep fixed bin (31) init (0),
2 #save_dow fixed bin (31) init (-1),
2 #save_day fixed bin (31) init (-1),
2 #save_mth fixed bin (31) init (-1),
2 #save_trip fixed bin (31) init (0),
2 #save_year fixed bin (31) init (0),
2 #type fixed bin (31) init (23),
2 #cnty fixed bin (31) init (0),
2 #nat fixed bin (31) init (0),
2 #trip fixed bin (31) init (-1),
2 #day fixed bin (31) init (-1),
2 #year fixed bin (31) init (0),
2 #ride fixed bin (31) init (0),
2 #tz fixed bin (31) init (0),
2 #tzc fixed bin (31) init (0),
2 #tzp fixed bin (31) init (1),
2 #wait fixed bin (31) init (0),
2 #wait_dow fixed bin (31) init (-1),
2 #wait_mth fixed bin (31) init (-1),
2 #wait_prv fixed bin (31) init (-2),
2 #ferry fixed bin (31) init (0),
2 #wferry fixed bin (31) init (0),
2 #ms fixed bin (31) init (1),
2 #id fixed bin (31) init (0),
2 #cl fixed bin (31) init (7),
2 #cll fixed bin (31) init (7),
2 #nl fixed bin (31) init (7),
2 #nll fixed bin (31) init (7),
2 #ci fixed bin (31) init (hbound(cplates.name, 1)),
2 #pi fixed bin (31) init (hbound(cplates.name, 1)),
2 #mist_r fixed bin (31) init (1),
2 #utf8_r fixed bin (31) init (1),
2 #mist_l fixed bin (31) init (1),
2 #utf8_l fixed bin (31) init (1),
2 eor_lift_work char (32)
init ('XXXXX END OF LIFT WORKAREA XXXXX');
1/**********************************************************************
* Clean lifts array & waits array *
**********************************************************************/
dcl 1 lws_tab(#ride) ctl,
2 ll_ptr ptr,
2 wait_ptr ptr,
2 top_k_ptr ptr,
2 top_t_ptr ptr,
2 top_v_ptr ptr,
2 filler char (12);
/**********************************************************************
* Top-nn arrays *
**********************************************************************/
dcl 1 t10_summ(1) ctl,
2 su_ix(3) fixed bin (31),
2 su_ktv(3,50) ptr;
dcl 1 t10_trip(trip_total.trip) ctl,
2 tr_ix(3) fixed bin (31),
2 tr_ktv(3,10) ptr;
dcl 1 t10_type(lift_work.#type) ctl,
2 ty_ix(3) fixed bin (31),
2 ty_ktv(3,10) ptr;
dcl 1 t10_cnty(0:lift_work.#cnty) ctl,
2 co_ix(3) fixed bin (31),
2 co_ktv(3,10) ptr;
dcl 1 t10_nat(lift_work.#nat) ctl,
2 na_ix(3) fixed bin (31),
2 na_ktv(3,10) ptr;
dcl 1 t10_year(year_top -> year_list.year:
year_end -> year_list.year) ctl,
2 yr_ix(3) fixed bin (31) init ((3)0),
2 yr_ktv(3,10) ptr;
/**********************************************************************
* xtot area's *
**********************************************************************/
dcl ttot_area area (((stg(ttot_list) + 8) * #type)) ctl;
dcl ctot_area area (((stg(ctot_list) + 8) * #cnty * 2)) ctl;
dcl ntot_area area (((stg(ntot_list) + 8) * #nat)) ctl;
dcl b47_c char (47) based(addr(b47));
1/**********************************************************************
* Input record *
**********************************************************************/
dcl sliftrec char (1024) var based(liftrec_ptr);
dcl 1 liftrec,
2 filler char (2),
2 trip pic 'zz9',
2 filler char (3),
2 ride pic 'zz9',
2 filler char (3),
2 cday char (3),
2 filler char (2),
2 km pic '(4)z9v.9',
2 filler char (2),
2 hh pic 'zz9',
2 filler char (1),
2 mm pic '99',
2 filler char (2),
2 v pic 'zzz9v.9',
2 filler char (2),
2 nat char (3),
2 filler char (2),
2 type char (4),
2 filler char (2),
2 cnty char (3),
2 filler char (2),
2 wait,
3 whh pic 'z9',
3 ferry char (1),
3 wmm pic '99',
2 filler char (2),
2 split char (1),
2 filler char (2),
2 dtime,
3 dhh pic 'z9',
3 dt char (1),
3 dmm pic '99',
2 filler char (2),
2 atime,
3 ahh pic 'z9',
3 atz char (1),
3 amm pic '99',
2 filler char (2),
2 date,
3 year pic '9999',
3 filler char (1),
3 mnth pic '99',
3 filler char (1),
3 day pic '99',
1 2 filler char (2),
2 odo pic '(5)z9v.9',
2 filler char (2),
2 dep_mode char (1),
2 dep_typ char (1),
2 filler char (2),
2 deploc char (47),
2 filler char (3),
2 arrloc char (47),
2 filler char (821),
2 eor_liftrec char (0);
/**********************************************************************
* Input record overlay for timezone information *
**********************************************************************/
dcl 1 tzrec based(liftrec_ptr),
2 filler char (4),
2 id char (1),
2 tzinfo(32),
3 tzc char (4),
3 tzt pic 's99',
3 tzt_c char (1);
1/**********************************************************************
* LIFT - Lift list *
* *
* The pointers in LIFT_LIST serve the following purposes: *
* *
* - lift_nxt : the address of the next item in the list of ALL lifts *
* - lift_prv : the address of the previous item in the list of ALL *
* lifts *
* - wift_nxt : the address of the next item in the list of waits *
* - wift_skip: the address of the next item in the list of waits for *
* a specific type of wait (all/trip/country/year) *
* - owner : the address of first item for this ride *
* - ll_nxt : the address of the next item in the list of ALL *
* lifts, skipping any records containing data relating *
* to day or country splits *
* - tr_nxt : the address of the next lift for the same trip *
* - tl_nxt : the address of the next lift for the same type of *
* driver or vehicle *
* - xty_ptr : the address of the type_list for the type of this *
* ride *
* - cl_nxt : the address of the next lift for the same country, *
* skipping any records containing data relating to day *
* splits and records containing multiple country totals *
* - xco_ptr : the address of the cnty_list for the country of this *
* ride *
* - nl_nxt : the address of the next lift for the same nationality *
* of the driver *
* - xna_ptr : the address of the nat_list for the nationality of *
* this ride *
* - yr_nxt : the address of the next lift for the same year *
**********************************************************************/
dcl 1 lift_list based(lift_ptr),
2 lift_nxt ptr init (sysnull()), /* pp */
2 ll_nxt ptr init (sysnull()),
2 trip fixed bin (31) init (liftrec.trip),
2 ride fixed bin (31) init (liftrec.ride), /* pp */
2 km fixed (9,1) init (liftrec.km),
2 time fixed (9) init (0),
2 vx fixed (13,9) init (0),
2 nat char (4)
init (translate(liftrec.nat, ' ', ',')),
2 type char (4)
init (translate(liftrec.type, ' ', ',')),
2 cnty char (4)
init (translate(liftrec.cnty, ' ', ',')),
2 ferry bit (1)
init ((liftrec.ferry = ':')) aligned,
2 wferry bit (1)
init ((liftrec.dt = ':')) aligned,
2 atz char (1) init (liftrec.atz),
1 2 date,
3 year fixed bin (31) init (liftrec.date.year),
3 mnth fixed bin (31) init (liftrec.date.mnth),
3 day fixed bin (31) init (liftrec.date.day),
2 dow fixed bin (31) init (-1),
2 jdn fixed (7) init (-1), /* pp */
2 day fixed (3) init (-1), /* pp */
2 cday char (3) init (liftrec.cday),
2 dtime fixed (5) init (-1),
2 atime fixed (5) init (-1),
2 utc_cnty fixed (5) init (-9999),
2 utc_dtime fixed (5) init (-9999),
2 utc_atime fixed (5) init (-9999),
2 split char (1) init (liftrec.split),
2 spl_day fixed (3) init (-1),
2 cross char (1) init (liftrec.dt),
2 etime fixed (5) init (0),
2 itime fixed (5) init (0),
2 aitime fixed (5) init (-1),
2 odo fixed (7,1) init (liftrec.odo),
2 dep_mode char (1) init (liftrec.dep_mode),
2 dep_typ char (1)
init (translate(liftrec.dep_typ, ' ', ',')),
2 deploc char (47) init (liftrec.deploc),
2 arrloc char (47) init (liftrec.arrloc),
2 sum_km fixed (9,1) init (0),
2 sum_time fixed (9) init (0),
2 ds_type char (1) init (' '),
2 vs_type char (1) init (' '),
2 ds_nat char (1) init (' '),
2 vs_nat char (1) init (' '),
2 mstone char (1) init ('00'x),
2 padding char (176) init ((176)' '),
2 id fixed bin (31) init (0),
2 wtime fixed bin (31) init (-1),
2 #wa fixed bin (31) init (-1),
2 #wx fixed bin (31) init (-1),
2 watime fixed bin (31) init (-2),
2 wid fixed bin (31) init (0),
2 #sd fixed bin (31) init (0),
2 #ld_l fixed bin (31) init (0),
2 #sp_l fixed bin (31) init (0),
2 #spl fixed bin (31) init (0),
2 #cspl fixed bin (31) init (0),
2 #n fixed bin (31) init (0),
2 #ud fixed bin (31) init (0),
2 #ud8 fixed bin (31) init (0),
2 #ua fixed bin (31) init (0),
2 #ua8 fixed bin (31) init (0),
1 2 filler char (8) init ('LIFTPTRS'),
2 owner ptr init (sysnull()),
2 lift_prv ptr init (prv_lift),
2 wift_nxt ptr init (sysnull()),
2 wift_skip ptr init (sysnull()),
2 tr_nxt ptr init (sysnull()),
2 tl_nxt ptr init (sysnull()),
2 xty_ptr ptr init (sysnull()),
2 cl_nxt ptr init (sysnull()),
2 xco_ptr ptr init (sysnull()),
2 nl_nxt ptr init (sysnull()),
2 xna_ptr ptr init (sysnull()),
2 yr_nxt ptr init (sysnull()),
2 eor_lift_list char (0);
1/**********************************************************************
* LIFT - Trip list *
* *
* The pointers in TRIP_LIST serve the following purposes: *
* *
* - trip_nxt: the address of the next item in the list of trips *
* - tr_top : the address of the first item in the LIFT LIST for *
* this trip *
* - tr_end : the address of the last item in the LIFT LIST for this *
* trip *
* - day_top : the address of the first day item for this trip *
* - day_end : the address of the last day item for this trip *
* *
* Note: The TR_NXT pointers are in the LIFT_LIST items. *
**********************************************************************/
dcl 1 trip_list based(trip_ptr),
2 trip_nxt ptr init (sysnull()),
2 nxt_trip ptr init (sysnull()),
2 trip fixed bin (31) init (lift_list.trip),
2 #d fixed bin (31) init (0),
2 km fixed (9,1) init (lift_list.km),
2 time fixed (9) init (lift_list.time),
2 vx fixed (13,9) init (0),
2 qual fixed (7) init (0),
2 #r fixed (5) init (1),
2 d fixed (5,1) init (0),
2 r fixed (5,1) init (0),
2 rd fixed (5,2) init (0),
2 t_wavg fixed (5) init (-1),
2 t_sdev fixed (5) init (-1),
2 padding char (41) init ((41)' '),
2 #trips fixed bin (31) init (0),
2 #ms fixed bin (31) init (1),
2 wait,
3 #w fixed bin (31) init (0),
3 wtime fixed bin (31) init (0),
2 tr_top ptr init (lift_ptr),
2 tr_end ptr init (lift_ptr),
2 day_top ptr init (sysnull()),
2 day_end ptr init (sysnull()),
2 eor_trip_list char (0);
1/**********************************************************************
* LIFT - Day list *
* *
* The pointers in DAY_LIST serve the following purposes: *
* *
* - day_nxt: the address of the next item in the list of days for *
* the current trip *
* - day_prv: the address of the previous item in the list of days *
* for the current trip *
* - td_nxt : the address of the next item in the list of all days *
* - yd_end : the address of the next item in the list of days for *
* the current year *
* *
* The times structure contains the following times: *
* *
* w1time : total waiting time on this day *
* d1time : time of start of first ride on the day *
* a1time : time of end of last ride on this day *
* i1time : total in-ride waitng time for this day *
* s1time : total sleep time during this day *
* z1time : time gained/lost over timezone crossings during this day *
* n1time : non-hitching time (Sleep etc) during this day *
* *
* The following times are used on days that include a period of sleep *
* immediately before or after midnight (or both) *
* *
* bms1time: sleep time before midnight *
* ams1time: sleep time after midnight *
**********************************************************************/
1dcl 1 day_list based(day_ptr),
2 day_nxt ptr init (sysnull()),
2 td_nxt ptr init (sysnull()),
2 trip fixed bin (31) init (trip_list.trip),
2 day fixed bin (31) init (lift_list.day),
2 km fixed (9,1) init (0),
2 time fixed (9) init (0),
2 vx fixed (13,9) init (0),
2 jdn fixed (7) init (lift_list.jdn),
2 times,
3 w1time fixed (7) init (-1),
3 d1time fixed (5) init (-1),
3 a1time fixed (5) init (-1),
3 i1time fixed (5) init (0),
3 s1time fixed (5) init (0),
3 z1time fixed (5) init (0),
3 n1time fixed (5) init (0),
3 bms1time fixed (5) init (0),
3 ams1time fixed (5) init (0),
2 #r fixed (13,8) init (0),
2 padding char (24) init ((24)' '),
2 #ld_d fixed bin (31) init (0),
2 #sp_d fixed bin (31) init (0),
2 dow fixed bin (31) init (-1),
2 date,
3 year fixed bin (31) init (lift_list.date.year),
3 mnth fixed bin (31) init (lift_list.date.mnth),
3 day fixed bin (31) init (lift_list.date.day),
2 day_prv ptr init (prv_day),
2 yd_nxt ptr init (sysnull()),
2 eor_day_list char (0);
1/**********************************************************************
* LIFT - Type list *
* *
* The pointers in TYPE_LIST serve the following purposes: *
* *
* - type_nxt: the address of the next item in the list of types *
* - tl_top : the address of the first item in the LIFT LIST for *
* this type *
* - tl_end : the address of the last item in the LIFT LIST for this *
* type *
* *
* Note: The TL_NXT pointers are in the LIFT_LIST items. *
**********************************************************************/
dcl 1 type_list based(type_ptr),
2 type_nxt ptr init (sysnull()),
2 type char (4) init (substr(a_typ, #i, 4)),
2 data,
3 #c fixed bin (31) init (0),
3 km fixed (9,1) init (0),
3 time fixed (9) init (0),
3 filler char (2) init ((2)'00'x),
2 padding char (20) init ((20)' '),
2 #tt fixed bin (31) init (0),
2 dmax_lift ptr init (sysnull()),
2 vmax_lift ptr init (sysnull()),
2 tl_top ptr init (sysnull()),
2 tl_end ptr init (sysnull()),
2 eor_type_list char (0);
1/**********************************************************************
* LIFT - Country list *
* *
* The pointers in CNTY_LIST serve the following purposes: *
* *
* - cnty_nxt: the address of the next item in the list of countries *
* - cd_ptr : the address of the dep_list for this country *
* - cl_top : the address of the first item in the LIFT LIST for *
* this country *
* - cl_end : the address of the last item in the LIFT LIST for *
* this country *
* - cn_ptr : the address of the item in the NAT LIST where the *
* nationality is the same as the country in the *
* COUNTRY LIST *
* *
* Notes: *
* *
* - The CL_NXT pointers are in the LIFT_LIST items. *
* - The CN_PTR's are used to print (when processing the results for *
* a single trip) the nationalities of the drivers in the same *
* order as the countries being passed. *
**********************************************************************/
1dcl 1 cnty_list based(cnty_ptr),
2 cnty_nxt ptr init (sysnull()),
2 cnty char (4) init (' '),
2 int,
3 #c fixed bin (31) init (0),
3 km fixed (9,1) init (0),
3 time fixed (9) init (0),
3 filler char (2) init ((2)'00'x),
2 ext,
3 #c fixed bin (31) init (0),
3 km fixed (9,1) init (0),
3 time fixed (9) init (0),
3 filler char (2) init ((2)'00'x),
2 pick_up bit (1) init ('0'b) aligned,
2 @copa bit (1) init ('0'b) aligned,
2 #ir fixed (13,8) init (0),
2 #er fixed (13,8) init (0),
2 padding char (28) init ((28)' '),
2 borders(8),
3 #c fixed bin (31) init ((8)0),
3 p_d ptr init ((8)sysnull()),
3 p_t ptr init ((8)sysnull()),
3 p_v ptr init ((8)sysnull()),
2 wait,
3 #w fixed bin (31) init (0),
3 wtime fixed bin (31) init (0),
2 #p fixed bin (31) init (-1),
2 #cc fixed bin (31) init (0),
2 #i_nat fixed bin (31) init (0),
2 #e_nat fixed bin (31) init (0),
2 cd_ptr ptr init (sysnull()),
2 clift_ptr ptr init (sysnull()),
2 cl_top ptr init (sysnull()),
2 cl_end ptr init (sysnull()),
2 cn_ptr ptr init (sysnull()),
2 eor_cnty_list char (0);
1/**********************************************************************
* LIFT - Nationality list *
* *
* The pointers in NAT_LIST serve the following purposes: *
* *
* - nat_nxt : the address of the next item in the list of *
* nationalities *
* - nl_top : the address of the first item in the LIFT LIST for *
* this nationality *
* - nl_end : the address of the last item in the LIFT LIST for this *
* nationality *
* *
* Note: The NL_NXT pointers are in the LIFT_LIST items. *
**********************************************************************/
dcl 1 nat_list based(nat_ptr),
2 nat_nxt ptr init (sysnull()),
2 nat char (4) init (substr(a_nat, #i, 4)),
2 data,
3 #c fixed bin (31) init (0),
3 km fixed (9,1) init (0),
3 time fixed (9) init (0),
3 filler char (2) init ((2)'00'x),
2 padding char (16) init ((16)' '),
2 #p fixed bin (31) init (-1),
2 #nn fixed bin (31) init (0),
2 dmax_lift ptr init (sysnull()),
2 vmax_lift ptr init (sysnull()),
2 nl_top ptr init (sysnull()),
2 nl_end ptr init (sysnull()),
2 eor_nat_list char (0);
1/**********************************************************************
* LIFT - Year list *
* *
* The pointers in YEAR_LIST serve the following purposes: *
* *
* - year_nxt: the address of the next item in the list of years *
* - yr_top : the address of the first item in the LIFT list for *
* this year *
* - yr_end : the address of the last item in the LIFT list for this *
* year *
* - yd_top : the address of the first item in the DAY list for this *
* year *
* *
* Note: The YR_NXT pointers are in the LIFT_LIST items. *
**********************************************************************/
dcl 1 year_list based(year_ptr),
2 year_nxt ptr init (sysnull()),
2 year fixed bin (31) init (lift_list.year),
2 #d fixed (5) init (1),
2 #r fixed (5) init (1),
2 km fixed (9,1) init (lift_list.km),
2 time fixed (9) init (lift_list.time),
2 v fixed (5,1) init (0),
2 qual fixed (7) init (0),
2 y_wavg fixed (5) init (-1),
2 y_sdev fixed (5) init (-1),
2 padding char (135) init ((135)' '),
2 trip_ride(2),
3 trip fixed bin (31) init ((2)lift_list.trip),
3 ride fixed bin (31) init ((2)lift_list.ride),
2 wait,
3 #w fixed bin (31) init (0),
3 wtime fixed bin (31) init (0),
2 ydays,
3 data(0:6),
4 #c fixed bin (31), /* init ((7)0), */
4 km fixed (9,1), /* init ((7)0), */
4 time fixed (9), /* init ((7)0), */
4 filler char (2), /* init ((7)((2)'00'x)), */
2 ymonths,
3 data(12),
4 #c fixed bin (31), /* init ((12)0), */
4 km fixed (9,1), /* init ((12)0), */
4 time fixed (9), /* init ((12)0), */
4 filler char (2), /* init ((12)((2)'00'x)), */
2 yr_top ptr init (lift_ptr),
2 yr_end ptr init (lift_ptr),
2 yd_top ptr init (sysnull()),
2 yd_ptr ptr init (sysnull()),
2 eor_year_list char (0);
1/**********************************************************************
* LIFT - Print fast/slow lists *
* *
* The following list is used to store the sets of lines generated by *
* the various 'FAST_...' procedures. *
**********************************************************************/
dcl 1 fast_list based(fast_ptr),
2 fast_nxt ptr init (sysnull()),
2 fline char (121) init (line),
2 visit char (1) init (' '),
2 ftype fixed bin (15) init (-32768);
1/**********************************************************************
* LIFT - Print summary lists *
* *
* The following four lists are used to store the min/max/avg lines in *
* order to print seven final summary tables. *
**********************************************************************/
dcl 1 rtot_list based(rtot_ptr),
2 rtot_nxt ptr init (sysnull()),
2 rline char (121) init (line),
2 filler char (3) init ('RRR');
dcl 1 dtot_list based(dtot_ptr),
2 dtot_nxt ptr init (sysnull()),
2 dline char (121) init (line),
2 filler char (3) init ('DDD');
dcl 1 ttot_list based(ttot_ptr),
2 ttot_nxt ptr init (sysnull()),
2 tline char (121) init (line),
2 tid char (3) init ('TTT');
dcl 1 ctot_list based(ctot_ptr),
2 ctot_nxt ptr init (sysnull()),
2 cline char (121) init (line),
2 cid char (3) init ('Int');
dcl 1 ntot_list based(ntot_ptr),
2 ntot_nxt ptr init (sysnull()),
2 nline char (121) init (line),
2 nid char (1) init ('1'),
2 nfiller char (2) init ('NN');
dcl 1 ytot_list based(ytot_ptr),
2 ytot_nxt ptr init (sysnull()),
2 yline char (121) init (line),
2 id char (1) init (' '),
2 filler char (2) init ('YY');
dcl 1 vtot_list based(vtot_ptr),
2 vtot_nxt ptr init (sysnull()),
2 vline char (121) init (line),
2 filler char (3) init ('VVV');
1/**********************************************************************
* LIFT - 24 hour split processing lists *
**********************************************************************/
dcl 1 split_list based(split_ptr),
2 split_nxt ptr init (sysnull()),
2 trip fixed bin (31) init (lift_list.trip),
2 ride fixed bin (31) init (lift_list.ride),
2 sect fixed (3) init (0),
2 km fixed (9,1) init (0),
2 time fixed (9) init (0),
2 day fixed (3) init (0),
2 dtime fixed (5) init (0),
2 dtime_utc fixed (5) init (0),
2 atime fixed (5) init (0),
2 atime_utc fixed (5) init (0),
2 jdn fixed (7) init (0),
2 stamp fixed (11) init (0),
2 cnty char (4) init (0),
2 s_y fixed (5) init (-1),
2 s_m fixed (3) init (0),
2 s_d fixed (3) init (0),
2 padding char (5) init ((5)' ');
dcl 1 p24h_list based(p24h_ptr),
2 p24h_nxt ptr init (sysnull()),
2 split_id fixed bin (31),
2 elaps fixed (5),
2 km fixed (9,1),
2 time fixed (9),
2 dday fixed (3),
2 dmnth fixed (3),
2 dyear fixed (5),
2 dtime fixed (5),
2 padding char (1) init ((1)' '),
2 data(2),
3 trip fixed bin (31),
3 ride fixed bin (31),
3 sect fixed (3),
3 cnty char (4),
3 day fixed (3);
/**********************************************************************
* Common top for lift_list, trip_list, and day_list *
**********************************************************************/
dcl 1 ltd_list based(ltd_ptr), /* lift day trip */
2 filler ptr,
2 ltd_nxt ptr, /* ll_nxt td_nxt nxt_trip */
2 trip fixed bin (31), /* trip trip trip */
2 #2 fixed bin (31), /* ride day #d */
2 km fixed (9,1),
2 time fixed (9),
2 vx fixed (13,9);
1/**********************************************************************
* Overflow list for nationalities scan when more than one interval *
**********************************************************************/
dcl 1 run_list based(run_ptr),
2 run_nxt ptr init (sysnull()),
2 run_prv ptr init (sysnull()),
2 rlen fixed bin (31) init (0),
2 strip fixed bin (31) init (0),
2 sride fixed bin (31) init (0),
2 etrip fixed bin (31) init (0),
2 eride fixed bin (31) init (0),
2 run char (994) init ('') var;
/**********************************************************************
* Progressive max distance, time, and velocity list *
**********************************************************************/
dcl 1 ktv_list based(ktv_ptr),
2 ktv_nxt ptr init (sysnull()),
2 ktv_lift ptr init (lift_ptr),
2 ktype fixed bin (31),
2 filler char (4);
/**********************************************************************
* LIFT - Departure mode distance/wait list *
* *
* data/v: *
* - Int / Ext *
* - Thumb / Ask / Other / TBA *
* *
* dep_waits: *
* - Int / Ext *
* - Thumb / Ask / Other / TBA *
* - No / <= 1:00 / > 1:00 / Total *
* *
* lines: *
* - Thumb / Ask / Other / TBA *
**********************************************************************/
dcl 1 dep_list based(dep_ptr),
2 dep_nxt ptr init (sysnull()),
2 cnty char (4) init (' '),
2 year fixed bin (31) init (-1),
2 data(0:1, 0:3),
3 #c fixed bin (31) init ((8)0),
3 km fixed (9,1) init ((8)0),
3 time fixed (9) init ((8)0),
3 filler char (2) init ((8)((2)'00'x)),
2 vx(0:1, 0:3) fixed (13,9) init ((8)0),
2 v_eff(0:1, 0:3) fixed (13,9) init ((8)0),
2 dep_waits(0:1, 0:3, 0:3),
3 #w fixed bin (31) init ((32)0),
3 wtime fixed bin (31) init ((32)0),
2 lines(0:3) char (121) init ((4)((121)' '));
1/**********************************************************************
* LIFT - On Units *
**********************************************************************/
on error snap
begin;
on error snap system;
if lift_ptr ^= sysnull() then
put skip edit('lift_list.trip=') (a)
(lift_list.trip) (p'zzz9b')
('lift_list.ride=') (a)
(lift_list.ride) (p'zzz9b');
else
put skip list('Oops, time to start using Debug Tool...');
call plidump('HB');
end;
on endfile(liftin) @eof = '1'b;
on endfile(insumm) @eof = '1'b;
on endfile(inlift) @eof = '1'b;
/**********************************************************************
* LIFT - Mainline initialisations *
**********************************************************************/
string(parm) = param;
open file(liftin),
file(summout),
file(liftout),
file(tripout),
file(daysout),
file(weekout),
file(mnthout),
file(ntopout),
file(xtraout);
1/**********************************************************************
* LIFT - Process input dataset *
**********************************************************************/
sliftrec = repeat(' ', stg(sliftrec) - 3);
read file(liftin) into(sliftrec);
do while(^@eof);
select;
when (substr(liftrec.trip, 1, 1) ^= '{' &
liftrec.trip ^= 0)
call process_inrec();
/*----------------------------------------------------------------+
| Time zone information |
+----------------------------------------------------------------*/
when (substr(liftrec.trip, 1, 2) = '{Z')
do;
/*------------------------------------------------------------+
| Need to post-process the last processed ride when the time |
| zone changes. (Mid-ride change? Ouch...) |
+------------------------------------------------------------*/
if lift_own ^= sysnull() then
do;
call post_process_ride();
lift_own = sysnull();
end;
call get_tz_info();
end;
/*----------------------------------------------------------------+
| ASCII (to cater for UTF-8) |
+----------------------------------------------------------------*/
when (substr(sliftrec, 1, 7) = '{ascii ')
ascii = ascii || substr(sliftrec, 8, 32);
1 /*----------------------------------------------------------------+
| Special UTF-8 (Greece, Japan) Currently unused |
+----------------------------------------------------------------*.
when (substr(sliftrec, 1, 2) = '{U')
select\
when (substr(sliftrec, 4, 1) = 'd')
lift_list.deploc = substr(sliftrec, 9, 47)\
when (substr(sliftrec, 4, 1) = 'a')
lift_list.arrloc = substr(sliftrec, 9, 47)\
other\
end\
/*----------------------------------------------------------------+
| Interruption info Currently unused |
+----------------------------------------------------------------*.
when (substr(sliftrec, 1, 2) = '{I')
/*----------------------------------------------------------------+
| Partner (Start) Currently unused |
+----------------------------------------------------------------*.
when (substr(sliftrec, 1, 2) = '{<')
/*----------------------------------------------------------------+
| Partner (End) Currently unused |
+----------------------------------------------------------------*.
when (substr(sliftrec, 1, 2) = '{>')
+----------------------------------------------------------------*/
/*----------------------------------------------------------------+
| Google Maps (Short) URL Currently unused |
+----------------------------------------------------------------*.
when (substr(sliftrec, 1, 2) = '{H')
+----------------------------------------------------------------*/
/*----------------------------------------------------------------+
| Pseudo-version for in-trip year end Currently unused |
+----------------------------------------------------------------*.
when (substr(sliftrec, 1, 2) = '{V')
+----------------------------------------------------------------*/
other;
end;
sliftrec = repeat(' ', stg(sliftrec) - 3);
read file(liftin) into(sliftrec);
end;
call post_process_ride();
1/**********************************************************************
* Allocate list of all types and area for the ttot_list items *
**********************************************************************/
alloc ttot_area;
tarea_ptr = addr(ttot_area);
do #i = 1 to length(a_typ) by 5;
alloc type_list;
type_end -> type_nxt,
type_end = type_ptr;
end;
s_ty_ptr = type_top;
/**********************************************************************
* Allocate list of all countries and area for the ctot_list items *
**********************************************************************/
alloc ctot_area;
carea_ptr = addr(ctot_area);
do #i = 1 to length(a_cnty) by 5;
alloc cnty_list;
cnty_end -> cnty_nxt,
cnty_end = cnty_ptr;
cnty_list.cnty = substr(a_cnty, #i, 4);
cnty_list.#p = srch_cnty(cnty_list.cnty);
#cl = max(#cl, length(cplates(cnty_list.#p).name));
end;
#cll = #cl;
/**********************************************************************
* Allocate list of all nationalities and area for the ntot_list items *
**********************************************************************/
alloc ntot_area;
narea_ptr = addr(ntot_area);
do #i = 1 to length(a_nat) by 5;
alloc nat_list;
nat_end -> nat_nxt,
nat_end = nat_ptr;
nat_list.#p = srch_cnty(nat_list.nat);
#nl = max(#nl, length(cplates(nat_list.#p).name));
if #i <= length(a_nat) / 2 then
do;
nat_mptr = nat_ptr;
nat_mid = substr(a_nat, #i, 4);
end;
end;
#nll = #nl;
s_na_ptr = nat_top;
1/**********************************************************************
* Allocate array of pointers to *
* - clean rides *
* - waits *
* - clean rides (to be sorted in distance order) *
* - clean rides (to be sorted in time order) *
* - clean rides (to be sorted in velocoty order) *
**********************************************************************/
alloc lws_tab;
lws_tab_ptr = addr(lws_tab);
#i = 0;
lift_work.#id = ll_end -> lift_list.id + 1;
do lift_ptr = lift_top repeat owner -> lift_list.ll_nxt
while(lift_ptr ^= sysnull());
#i = #i + 1;
ll_ptr(#i) = lift_ptr;
top_k_ptr(#i) = lift_ptr;
top_t_ptr(#i) = lift_ptr;
top_v_ptr(#i) = lift_ptr;
/*------------------------------------------------------------------+
| Calculate the number of UTF-8 multi-byte characters in the |
| departure and arrival locations and the UTF-8 length
+------------------------------------------------------------------*/
if lift_prv ^= sysnull() &
lift_list.deploc = lift_prv -> owner -> lift_list.arrloc then
do;
#ud8 = lift_prv -> owner -> #ua8;
#ud = lift_prv -> owner -> #ua;
end;
else
do;
b47_c = translate(lift_list.deploc, utf8, ascii);
#ud8 = 47 - sum(b47);
do #ud = stg(lift_list.deploc) by -1
while(substr(lift_list.deploc, #ud, 1) = ' ');
end;
end;
b47_c = translate(lift_list.arrloc, utf8, ascii);
#ua8 = 47 - sum(b47);
do #ua = stg(lift_list.arrloc) by -1
while(substr(lift_list.arrloc, #ua, 1) = ' ');
end;
/*------------------------------------------------------------------+
| Keep track of milestone ride numbers (1/5/10/25/42/etc) |
+------------------------------------------------------------------*/
if #i = fastest_r(#mist_r) then
do;
unspec(lift_list.mstone) = unspec(lift_list.mstone) | '01'bx;
#mist_r = #mist_r + 1;
#utf8_r = max(#utf8_r, #ud - #ud8, #ua - #ua8);
end;
1 /*------------------------------------------------------------------+
| Record the progressively longer distances |
+------------------------------------------------------------------*/
if lift_list.km > ktv.maxk.km |
lift_list.km = ktv.maxk.km & lift_list.vx > ktv.maxk.vx then
do;
ktv.maxk.km = lift_list.km;
ktv.maxk.vx = lift_list.vx;
ktv.curk.km = 0;
ktv.curk.vx = 0;
ktv.curk.kptr = sysnull();
alloc ktv_list;
ktv_end -> ktv_nxt,
ktv_end = ktv_ptr;
ktv_list.ktype = 1;
end;
else
if lift_list.km > ktv.curk.km |
lift_list.km = ktv.curk.km & lift_list.vx > ktv.curk.vx then
do;
ktv.curk.km = lift_list.km;
ktv.curk.vx = lift_list.vx;
ktv.curk.kptr = lift_ptr;
end;
/*------------------------------------------------------------------+
| Record the progressively longer times |
+------------------------------------------------------------------*/
if lift_list.time > ktv.maxt.time |
lift_list.time = ktv.maxt.time & lift_list.vx > ktv.maxt.vx then
do;
ktv.maxt.time = lift_list.time;
ktv.maxt.vx = lift_list.vx;
ktv.curt.time = 0;
ktv.curt.vx = 0;
ktv.curt.tptr = sysnull();
alloc ktv_list;
ktv_end -> ktv_nxt,
ktv_end = ktv_ptr;
ktv_list.ktype = 2;
end;
else
if lift_list.time > ktv.curt.time |
lift_list.time = ktv.curt.time & lift_list.vx > ktv.curt.vx then
do;
ktv.curt.time = lift_list.time;
ktv.curt.vx = lift_list.vx;
ktv.curt.tptr = lift_ptr;
end;
1 /*------------------------------------------------------------------+
| Record the progressively higher velocities |
+------------------------------------------------------------------*/
if lift_list.vx > ktv.maxv.vx |
lift_list.vx = ktv.maxv.vx & lift_list.km > ktv.maxv.km then
do;
ktv.maxv.vx = lift_list.vx;
ktv.maxv.km = lift_list.km;
ktv.curv.vx = 0;
ktv.curv.km = 0;
ktv.curv.vptr = sysnull();
alloc ktv_list;
ktv_end -> ktv_nxt,
ktv_end = ktv_ptr;
ktv_list.ktype = 3;
end;
else
if lift_list.vx > ktv.curv.vx |
lift_list.vx = ktv.curv.vx & lift_list.km > ktv.curv.km then
do;
ktv.curv.vx = lift_list.vx;
ktv.curv.km = lift_list.km;
ktv.curv.vptr = lift_ptr;
end;
/*------------------------------------------------------------------+
| Add an alternative arrival time for those rides where the ride |
| is followed by non-hitching time, and mark split days by adding |
| an extra 10,000 to the aitime in the owner. |
+------------------------------------------------------------------*/
if ll_nxt ^= sysnull() &
substr(ll_nxt -> lift_prv -> lift_list.type, 1, 2) = '!^' then
do;
lift_work.atime = ll_nxt -> lift_prv -> lift_list.dtime;
save_lift_ptr = lift_ptr;
do lift_ptr = lift_ptr repeat lift_nxt
while(lift_list.atime = -1);
end;
lift_list.aitime = lift_work.atime;
if lift_list.split = '#' then
owner -> lift_list.aitime = lift_work.atime + 10000;
lift_ptr = save_lift_ptr;
end;
1 /*------------------------------------------------------------------+
| Update cumulative distance and time, to reduce the statement |
| count in "inex_tcn" by about 88% |
+------------------------------------------------------------------*/
lift_list.sum_km = lift_work.sum_km;
lift_list.sum_time = lift_work.sum_time;
if substr(lift_list.cnty, 1, 1) ^= '*' then
do;
lift_work.sum_km = lift_work.sum_km + lift_list.km;
lift_work.sum_time = lift_work.sum_time + lift_list.time;
end;
else
do;
do lift_ptr = lift_nxt repeat lift_nxt
until(lift_list.split = '*');
end;
do lift_ptr = lift_ptr repeat lift_nxt
while(lift_list.split = '*');
lift_list.sum_km = lift_work.sum_km;
lift_list.sum_time = lift_work.sum_time;
lift_work.sum_km = lift_work.sum_km + lift_list.km;
lift_work.sum_time = lift_work.sum_time + lift_list.time;
end;
end;
/*------------------------------------------------------------------+
| Keep track of milestone distances (100/250/500/1000/etc) |
+------------------------------------------------------------------*/
lift_ptr = owner;
do while(lift_work.sum_km >= fast_dist(#mist_l));
#mist_l = #mist_l + 1;
unspec(lift_list.mstone) = unspec(lift_list.mstone) | '02'bx;
if lift_work.sum_km < fast_dist(#mist_l) then
#utf8_l = max(#utf8_l, #ud - #ud8, #ua - #ua8);
end;
end;
1/**********************************************************************
* Allocate and initialise array of pointers to waiting times *
**********************************************************************/
#i = 0;
do lift_ptr = wift_top repeat wift_nxt
while(lift_ptr ^= sysnull());
#i = #i + 1;
wait_ptr(#i) = lift_ptr;
end;
/**********************************************************************
* Initialise array for nationalities scan *
**********************************************************************/
do #i = lbound(run_arr.run_top, 1) to hbound(run_arr.run_top, 1);
run_arr(#i).run_end = addr(run_arr(#i).run_top);
end;
/**********************************************************************
* Build table of 24 hour splits *
**********************************************************************/
call build_24_hour_list();
/**********************************************************************
* Count simple waiting times for the summary *
**********************************************************************/
call process_mini_wait('CPER');
/**********************************************************************
* Build list of departure information *
**********************************************************************/
call process_deplocs();
1/**********************************************************************
* Summary results *
* *
* The summary consists of the tables described at main comment box at *
* the top of the program, although some of the tables mentioned are *
* not printed until much later in the program. *
* *
* During this first pass through the data, *
* *
* - the rides are added to a dynamically build list of trips *
* *
* - the rides are added to the earlier created lists of types, *
* countries and nationalities, creating a structure like the one *
* depicted below for the types: *
* *
* -> TYPA -> TYPB -> TYPC *
* | | | *
* | | +-------+ *
* | | | *
* | | +------------>--+ *
* v v | | | *
* -> LIFT -> LIFT -> LIFT -> LIFT -> LIFT -> LIFT *
* | | | | *
* +------------>--+ +------------>--+ *
* *
* Obviously the list for countries and nationalities are similar. *
**********************************************************************/
@summary = '1'b;
outfile = summout;
minmax = iminmax;
sd.data = idata;
ld.data = idata;
sp.data = idata;
irwait = iwait;
wwait = iwait;
waits = iwait;
w8wtimesq = 0;
hours = 0;
@irwait = '0'b;
trip_ptr = trip_top;
1do lift_ptr = lift_top repeat lift_nxt
while(lift_ptr ^= sysnull());
/*------------------------------------------------------------------+
| Find trip_list for this ride |
+------------------------------------------------------------------*/
if lift_list.split = ' ' then
do trip_ptr = trip_ptr repeat trip_list.trip_nxt
while(trip_ptr ^= sysnull())
until(trip_list.trip = lift_list.trip);
end;
call process_list();
/*------------------------------------------------------------------+
| Don't process type, country or nationality for wait records |
| |
| Loops have been removed as "process_ty/co/na" in "process_list" |
| has already established currency on the correct ty/co/na_list |
| item! |
+------------------------------------------------------------------*/
if lift_list.split ^= '!' then
do;
/*--------------------------------------------------------------+
| Add current lift to list of types and add a direct link to |
| type_list for the type of the current ride |
+--------------------------------------------------------------*/
if tl_top = sysnull() then
tl_top = lift_ptr;
else
tl_end -> tl_nxt = lift_ptr;
tl_end = lift_ptr;
lift_list.xty_ptr = type_ptr;
/*--------------------------------------------------------------+
| Add current lift to list of countries and add a direct link |
| link to the cnty_list for the country of the current ride |
+--------------------------------------------------------------*/
if lift_list.cnty ^= ' ' &
lift_list.cnty ^= '* ' then
do;
if cl_top = sysnull() then
cl_top = lift_ptr;
else
cl_end -> cl_nxt = lift_ptr;
cl_end = lift_ptr;
lift_list.xco_ptr = cnty_ptr;
end;
1 /*--------------------------------------------------------------+
| Add current lift to list of nationalities and add a direct |
| link to the nat_list for the nationality of the current ride |
+--------------------------------------------------------------*/
if nl_top = sysnull() then
nl_top = lift_ptr;
else
nl_end -> nl_nxt = lift_ptr;
nl_end = lift_ptr;
lift_list.xna_ptr = nat_ptr;
end;
end;
call sortwait(' ');
call print_list();
call print_fila();
@summary = '0'b;
/**********************************************************************
* Logically delete the current alphabetical list of countries by *
* saving its pointers and resettting them subsequently. This is *
* needed because the results per country per trip are required in the *
* order in which the countries were passed. *
**********************************************************************/
save_cnty_top = cnty_top;
save_cnty_end = cnty_end;
s_co_ptr = sysnull();
1/**********************************************************************
* Results per trip *
**********************************************************************/
@trip = '1'b;
outfile = liftout;
swaits = iwait;
call sortwait('T');
do trip_ptr = trip_top repeat trip_list.trip_nxt
while(trip_ptr ^= sysnull());
cnty_top = sysnull();
cnty_end = addr(cnty_top);
/*------------------------------------------------------------------+
| Perform the necessary per-trip initialisations |
+------------------------------------------------------------------*/
minmax = iminmax;
sd.data = idata;
ld.data = idata;
sp.data = idata;
irwait = iwait;
wwait = iwait;
waits = iwait;
w8wtimesq = 0;
@irwait = '0'b;
lift_ptr = tr_top;
#save_trip = lift_list.trip;
trip_pic = lift_list.trip;
do lift_ptr = tr_top repeat tr_nxt
while(lift_ptr ^= sysnull());
call process_list();
end;
1 /*------------------------------------------------------------------+
| Min max processing for day totals |
+------------------------------------------------------------------*/
do day_ptr = trip_list.day_top repeat day_nxt
while(day_ptr ^= sysnull());
day_list.vx = divide(
multiply(day_list.km, 60, 15, 0),
day_list.time, 13, 9);
call process_min_max(2,
day_list.km,
day_list.time,
day_list.vx);
end;
/*------------------------------------------------------------------+
| Accumulate the various times for each ride into the day_list |
+------------------------------------------------------------------*/
call process_times();
call print_list();
call create_wait_summary(string(trip_pic));
trip_list.wait = waits(8);
/*------------------------------------------------------------------+
| Process minima/maxima/averages per type, nationality and country |
+------------------------------------------------------------------*/
@nested = '1'b;
call trip_year_type();
call trip_year_nat();
call trip_year_cnty();
@nested = '0'b;
1 /*------------------------------------------------------------------+
| Delete the list of countries for the just processed trip |
+------------------------------------------------------------------*/
do cnty_ptr = cnty_top repeat nxt_ptr
while(cnty_ptr ^= sysnull());
nxt_ptr = cnty_nxt;
free cnty_list;
end;
s_co_ptr = sysnull();
end;
outfile = summout;
call print_wait_summary('0'b);
@trip = '0'b;
1/**********************************************************************
* Interconnect the various day lists into one list *
**********************************************************************/
do trip_ptr = trip_top repeat trip_list.trip_nxt
while(trip_list.trip_nxt ^= sysnull());
trip_list.day_end -> td_nxt =
trip_list.trip_nxt -> trip_list.day_top;
end;
td_top = trip_top -> trip_list.day_top;
day_ptr = td_top;
/**********************************************************************
* Connect the various day lists to the appropriate year list *
**********************************************************************/
do year_ptr = year_top repeat year_nxt
while(year_ptr ^= sysnull());
yd_top = day_ptr;
do day_ptr = day_ptr repeat td_nxt
while(day_ptr ^= sysnull() &
td_nxt ^= sysnull() &
td_nxt -> day_list.year = year_list.year);
yd_nxt = td_nxt;
end;
day_ptr = td_nxt;
end;
/**********************************************************************
* Restore the list of countries in alphabetical order, by setting the *
* pointers to the saved values. *
**********************************************************************/
cnty_top = save_cnty_top;
cnty_end = save_cnty_end;
save_cnty_top = sysnull();
save_cnty_end = sysnull();
s_co_ptr = sysnull();
1/**********************************************************************
* Results per type *
**********************************************************************/
@type = '1'b;
outfile = liftout;
write file(outfile) from(pline);
line = ' Totals per type (035)';
write file(outfile) from(line);
do type_ptr = type_top repeat type_nxt
while(type_ptr ^= sysnull());
/*------------------------------------------------------------------+
| Perform the necessary per-type initialisations |
+------------------------------------------------------------------*/
minmax = iminmax;
sd.data = idata;
ld.data = idata;
sp.data = idata;
/*------------------------------------------------------------------+
| Only process those types for which there are rides. |
+------------------------------------------------------------------*/
if tl_top ^= sysnull() then
do;
heading = type_list.type;
do lift_ptr = tl_top repeat tl_nxt
while(lift_ptr ^= sysnull());
call process_list();
end;
call print_list();
end;
end;
@type = '0'b;
1/**********************************************************************
* Results per country *
**********************************************************************/
@cnty = '1'b;
@in_cnty = '1'b;
outfile = liftout;
write file(outfile) from(pline);
line = ' Totals per country (035)';
write file(outfile) from(line);
call sortwait('C');
call cnty_sub();
@in_cnty = '0'b;
@cnty = '0'b;
1/**********************************************************************
* Results per nationality *
**********************************************************************/
@nat = '1'b;
outfile = liftout;
write file(outfile) from(pline);
line = ' Totals per nationality (035)';
write file(outfile) from(line);
do nat_ptr = nat_top repeat nat_nxt
while(nat_ptr ^= sysnull());
/*------------------------------------------------------------------+
| Perform the necessary per-nationality initialisations |
+------------------------------------------------------------------*/
minmax = iminmax;
sd.data = idata;
ld.data = idata;
sp.data = idata;
/*------------------------------------------------------------------+
| Only process those nationalities for which there are rides |
+------------------------------------------------------------------*/
if nl_top ^= sysnull() then
do;
heading = nat_list.nat;
do lift_ptr = nl_top repeat nl_nxt
while(lift_ptr ^= sysnull());
call process_list();
end;
call print_list();
end;
end;
@nat = '0'b;
1/**********************************************************************
* Print final min/max/avg tables per ride *
**********************************************************************/
outfile = summout;
write file(outfile) from(pline);
call print_min_max_box('Trip | #R');
do rtot_ptr = rtot_top -> rtot_nxt repeat rtot_nxt
while(rtot_ptr ^= sysnull()),
rtot_top;
if rtot_ptr = rtot_top then
call print_min_max_box('B');
write file(outfile) from(rtot_list.rline);
end;
call print_min_max_box('B');
1/**********************************************************************
* Print final min/max/avg tables per day *
**********************************************************************/
write file(outfile) from(iline);
call print_min_max_box('Trip | #D');
do dtot_ptr = dtot_top repeat dtot_nxt
while(dtot_ptr ^= sysnull());
write file(outfile) from(dtot_list.dline);
end;
call print_min_max_box('B');
line = min_max_init;
min_max_line.mode = 'Tot ';
min_max_line.#mima = trip_total.#d;
min_max_line.v_maxr = round(dtot.v_max, 1);
min_max_line.v_minr = round(dtot.v_min, 1);
min_max_line.v_avg = round(trip_total.vx, 1);
min_max_line.l_max = dtot.l_max;
min_max_line.l_min = dtot.l_min;
min_max_line.l_avg = round(
divide(trip_total.km,
dec(trip_total.#d, 5), 15, 2), 1);
min_max_line.t_max_hh = dtot.t_max / 60;
min_max_line.t_max_mm = mod(dtot.t_max, 60);
min_max_line.t_min_hh = dtot.t_min / 60;
min_max_line.t_min_mm = mod(dtot.t_min, 60);
lift_work.t_avg = round(
divide(trip_total.time,
dec(trip_total.#d, 5), 15, 11), 0);
min_max_line.t_avg_hh = lift_work.t_avg / 60;
min_max_line.t_avg_mm = mod(lift_work.t_avg, 60);
write file(outfile) from(line);
call print_min_max_box('B');
/**********************************************************************
* Print final min/max/avg tables per type, nationality & country *
**********************************************************************/
write file(outfile) from(pline);
call print_and_delete_ttot_list();
write file(outfile) from(pline);
call print_and_delete_ntot_list();
write file(outfile) from(pline);
call print_and_delete_ctot_list();
call process_nacodi();
call process_hhcopa();
1/**********************************************************************
* Print summary tables for *
* *
* - the highest/lowest speed & min/max rides over a number of *
* distances *
* - the highest/lowest average speed & greatest/smallest distance *
* over a number of rides *
* - the number of consecutive rides with an absolute/average *
* distance over a number of distances *
* - the number of consecutive rides with an absolute/average speed *
* over a number of speeds *
**********************************************************************/
@summary = '1'b;
call fast_distance(lift_top,
f_ride_d,
fast_head,
fast_sep,
fast_init);
call fast_ltd(lift_top,
#ride,
fastest_r,
f_ride,
ride_head_r,
ride_sep,
ride_init);
call fast_speed(lift_top,
vx_max_r,
fast_init);
call fast_length(lift_top,
longest_r,
fast_init);
@summary = '0'b;
1/**********************************************************************
* Print formatted tables of all trips *
**********************************************************************/
do trip_ptr = trip_top repeat trip_list.trip_nxt
while(trip_ptr ^= sysnull());
@first = '1'b;
#j = 0;
do lift_ptr = tr_top repeat tr_nxt
while(lift_ptr ^= sysnull());
line = lift_init;
lift_line = lift_list, by name;
lift_line.hh = lift_list.time / 60;
lift_line.mm = mod(lift_list.time, 60);
select(lift_list.split);
when (' ') lift_line.v = round(lift_list.vx, 1);
when ('#',
'*');
/*?* Add speed for splits -------------------------------------
if lift_list.time ^= 0 then
lift_line.v = round(
divide(
multiply(lift_list.km, 60, 15, 0),
lift_list.time, 13, 9), 1)\
-------------------------------------------------------------*/
when ('!')
do;
string(lift_line.km) = '';
string(lift_line.hhmm) = '';
end;
other;
end;
if lift_list.wtime >= 0 then
do;
lift_line.whh = lift_list.wtime / 60;
lift_line.wmm = mod(lift_list.wtime, 60);
end;
if lift_list.dtime >= 0 then
do;
lift_line.dhh = lift_list.dtime / 60;
lift_line.dmm = mod(lift_list.dtime, 60);
lift_line.dt = lift_list.cross;
end;
1 if lift_list.atime >= 0 then
do;
lift_line.ahh = lift_list.atime / 60;
lift_line.atz = lift_list.atz;
lift_line.amm = mod(lift_list.atime, 60);
end;
if lift_list.ferry then
substr(line, 70, 1) = ':';
if lift_list.wferry then
substr(line, 82, 1) = ':';
if lift_list.jdn < 0 then
string(lift_line.date) = '';
alloc fast_list;
fast_end -> fast_nxt,
fast_end = fast_ptr;
fast_list.ftype = #j;
if #j > 115 |
lift_list.split = ' ' &
(lift_list.jdn ^= -1 |
(lift_list.cday = ' #' &
lift_list.tr_nxt -> lift_list.jdn ^= -1)) then
do;
if #j > 115 then
do;
save_fast_top -> fast_list.ftype = 0;
#j = 0;
end;
save_fast_top = fast_ptr;
end;
#j = #j + 1;
end;
1 do fast_ptr = fast_top repeat fast_nxt
while(fast_ptr ^= sysnull());
if fast_list.ftype = 0 then
do;
if ^@first then
write file(tripout) from(lift_sep);
@first = '0'b;
write file(tripout) from(pline);
write file(tripout) from(lift_sep);
write file(tripout) from(lift_head);
write file(tripout) from(lift_sep);
end;
write file(tripout) from(fast_list.fline);
end;
call free_fast_list();
write file(tripout) from(lift_sep);
end;
1/**********************************************************************
* Results per year *
**********************************************************************/
@year = '1'b;
outfile = liftout;
write file(outfile) from(pline);
line = ' Totals per year (035)';
write file(outfile) from(line);
/**********************************************************************
* Logically delete the current alphabetical list of countries by *
* saving its pointers and resettting them subsequently. This is *
* needed because the results per country per year are required in the *
* order in which the countries were passed. *
**********************************************************************/
save_cnty_top = cnty_top;
save_cnty_end = cnty_end;
s_co_ptr = sysnull();
swaits = iwait;
call sortwait('Y');
do year_ptr = year_top repeat year_nxt
while(year_ptr ^= sysnull());
cnty_top = sysnull();
cnty_end = addr(cnty_top);
/*------------------------------------------------------------------+
| Perform the necessary per-year initialisations |
+------------------------------------------------------------------*/
minmax = iminmax;
sd.data = idata;
ld.data = idata;
sp.data = idata;
irwait = iwait;
wwait = iwait;
waits = iwait;
w8wtimesq = 0;
@irwait = '0'b;
#save_year = year_list.year;
year_pic = year_list.year;
heading = year_pic;
1 do lift_ptr = yr_top repeat yr_nxt
while(lift_ptr ^= sysnull());
call process_list();
end;
do day_ptr = yd_top repeat yd_nxt
while(day_ptr ^= sysnull());
call process_min_max(2,
day_list.km,
day_list.time,
day_list.vx);
end;
call create_wait_summary(string(year_pic));
year_list.wait = waits(8);
call print_list();
/*------------------------------------------------------------------+
| Process minima/maxima/averages per type, nationality and country |
+------------------------------------------------------------------*/
@nested = '1'b;
call trip_year_type();
call trip_year_nat();
call trip_year_cnty();
@nested = '0'b;
/*------------------------------------------------------------------+
| Print full list of country sections passed |
+------------------------------------------------------------------*/
call print_copa();
/*------------------------------------------------------------------+
| Delete the list of countries for the just processed year |
+------------------------------------------------------------------*/
do cnty_ptr = cnty_top repeat nxt_ptr
while(cnty_ptr ^= sysnull());
nxt_ptr = cnty_nxt;
free cnty_list;
end;
s_co_ptr = sysnull();
/*------------------------------------------------------------------+
| Print the two types of pickup tables |
+------------------------------------------------------------------*/
call print_deplocs_d(year_list.yd_ptr);
call print_deplocs_w(year_list.yd_ptr);
1 /*------------------------------------------------------------------+
| Process distance, speed, weekday and calendar month for the year |
+------------------------------------------------------------------*/
ld.data = idata;
ld.fila = sysnull();
sp.data = idata;
sp.fila = sysnull();
days.data = idata;
months.data = idata;
@day = '1'b;
do day_ptr = yd_top repeat yd_nxt
while(day_ptr ^= sysnull());
call process_day_list();
end;
year_list.ydays = lift_work.days;
year_list.ymonths = lift_work.months;
write file(outfile) from(pline);
call print_distance();
call print_speed();
call print_daily_totals();
call print_monthly_totals();
call period_of_24_hour((year_pic));
call period_of_365_days();
@day = '0'b;
end;
1outfile = summout;
call process_mini_wait('PY ');
call free_fast_list();
/**********************************************************************
* Print final min/max/avg tables per year *
**********************************************************************/
call mima_7x12();
write file(outfile) from(pline);
call print_min_max_box('Year | #R');
do ytot_ptr = ytot_top repeat ytot_nxt
while(ytot_ptr ^= sysnull());
if ytot_list.id = 'R' then
write file(outfile) from(ytot_list.yline);
end;
call print_min_max_box('B');
write file(outfile) from(iline);
call print_min_max_box('Year | #D');
do ytot_ptr = ytot_top repeat ytot_nxt
while(ytot_ptr ^= sysnull());
if ytot_list.id = 'D' then
write file(outfile) from(ytot_list.yline);
end;
call print_min_max_box('B');
/**********************************************************************
* Restore the list of countries in alphabetical order, by setting the *
* pointers to the saved values. *
**********************************************************************/
cnty_top = save_cnty_top;
cnty_end = save_cnty_end;
save_cnty_top = sysnull();
save_cnty_end = sysnull();
s_co_ptr = sysnull();
@year = '0'b;
1/**********************************************************************
* Print a final table of all days *
**********************************************************************/
@day = '1'b;
ld.data = idata;
ld.fila = sysnull();
sp.data = idata;
sp.fila = sysnull();
days.data = idata;
months.data = idata;
write file(daysout) from(pline);
write file(daysout) from(td_sep);
write file(daysout) from(td_head);
write file(daysout) from(td_sep);
line = td_init;
do day_ptr = td_top repeat td_nxt
while(day_ptr ^= sysnull());
/*------------------------------------------------------------------+
| Collect monthly per day data here, allowing general use? *^01*|
+------------------------------------------------------------------*/
call process_day_list();
td_line = day_list, by name;
td_line.hh = day_list.time / 60;
td_line.mm = mod(day_list.time, 60);
td_line.v = round(day_list.vx, 1);
write file(daysout) from(line);
end;
write file(daysout) from(td_sep);
call print_list();
call print_fila();
1/**********************************************************************
* Print summary tables for *
* *
* - the highest/lowest speed & min/max days over a number of *
* distances *
* - the highest/lowest average speed & greatest/smallest distance *
* over a number of days *
* - the number of consecutive days with an absolute/average distance *
* over a number of distances *
* - the number of consecutive days with an absolute/average speed *
* over a number of speeds *
**********************************************************************/
@summary = '1'b;
call fast_distance(td_top,
f_day_d,
fast_head_d,
fast_sep,
fast_init);
call fast_ltd(td_top,
trip_total.#d,
fastest_d,
f_day,
ride_head_d,
ride_sep,
ride_init);
call fast_speed(td_top,
vx_max_d,
fast_init);
call fast_length(td_top,
longest_d,
fast_init);
@summary = '0'b;
@day = '0'b;
1/**********************************************************************
* Distribution of distance and velocity per trip *
**********************************************************************/
call process_trip_list();
/**********************************************************************
* Print summary tables for *
* *
* - the highest/lowest speed & min/max trips over a number of *
* distances *
* - the highest/lowest average speed & greatest/smallest distance *
* over a number of trips *
* - the number of consecutive trips with an absolute/average *
* distance over a number of distances *
* - the number of consecutive trips with an absolute/average speed *
* over a number of speeds *
**********************************************************************/
@ftrip = '1'b;
call fast_distance(trip_top,
f_trip_d,
fast_head_t,
fast_sep_t,
fast_init_t);
call fast_ltd(trip_top,
trip_total.#trips,
fastest_r,
f_trip,
ride_head_t,
ride_sep_t,
ride_init_t);
call fast_speed(trip_top,
vx_max_t,
fast_init_t);
call fast_length(trip_top,
longest_t,
fast_init_t);
@ftrip = '0'b;
1/**********************************************************************
* Print summary tables for *
* *
* - the totals per weekday *
* - the totals per calendar month *
* - the totals per calendar year *
* - the total numer of times a calendar day has been used *
* - the maximum distance over a number of consecutive calendar days *
* - the maximum distance over 24 hour and 365 day periods *
* - the occurences of series of nationalities *
**********************************************************************/
call print_daily_totals();
call print_monthly_totals();
call print_yearly_totals();
call print_days_used('C');
call print_days_used('P');
call print_weekday_pickups();
call distance_over_consecutive_days();
call period_of_24_hour(-1); /* Maximums per year */
call period_of_24_hour(0); /* Sucessive maximums */
call period_of_365_days();
if #nat > 2 then
call nat_scan();
1/**********************************************************************
* Print summary tables for *
* *
* - the number of types, countries and nationalities of drivers met *
* during each trip/year *
* *
* - the longest runs of inclusive/exclusive types and nationalites *
**********************************************************************/
call tycona_count('T');
call tycona_count('Y');
call inex_tcn((type_top), 'Type');
call inex_tcn((nat_top), 'Nat ');
/*--------------------------------------------------------------------+
| Pickup times per 6-hour interval per country |
+--------------------------------------------------------------------*/
outfile = summout;
write file(outfile) from(pline);
write file(outfile) from(iv_sep);
write file(outfile) from(iv_head);
write file(outfile) from(iv_sep);
do vtot_ptr = vtot_top repeat vtot_nxt
while(vtot_ptr ^= sysnull());
write file(outfile) from(vtot_list.vline);
end;
write file(outfile) from(iv_sep);
line = iv_init;
do #i = 1 to hbound(g_iv.#c, 1);
if g_iv.#c(#i) ^= 0 then
iv_line.#c(#i) = g_iv.#c(#i);
end;
write file(outfile) from(line);
write file(outfile) from(iv_sep);
/*--------------------------------------------------------------------+
| 10% intervals for rides/days, distance, and time |
+--------------------------------------------------------------------*/
if #ride >= 1000 then
call print_percent();
1/*--------------------------------------------------------------------+
| Print summary departure location information |
+--------------------------------------------------------------------*/
call print_deplocs_d(dep_end);
call print_deplocs_w(dep_end);
call print_deplocs_s('S');
/*--------------------------------------------------------------------+
| Print the per-country and per-year per deploc summaries |
+--------------------------------------------------------------------*/
call print_deplocs_s('F');
/*--------------------------------------------------------------------+
| Print "hitched-in" tables with names of countries |
+--------------------------------------------------------------------*/
call print_plates();
/*--------------------------------------------------------------------+
| Progessively longer (distance/time) and faster rides |
+--------------------------------------------------------------------*/
call ktv_progress();
/*--------------------------------------------------------------------+
| Progessively longer series of foreigners & natives |
+--------------------------------------------------------------------*/
call foreigners();
/*--------------------------------------------------------------------+
| Non-stop tables per type and nationality |
+--------------------------------------------------------------------*/
call nonstop((type_top), 'Type');
call nonstop((nat_top), 'Nat ');
/*--------------------------------------------------------------------+
| Border crossing tables |
+--------------------------------------------------------------------*/
call print_bocro();
call print_bocro_dtv();
/*--------------------------------------------------------------------+
| Print distances per weekday and calendar month |
+--------------------------------------------------------------------*/
call year_wm();
/*--------------------------------------------------------------------+
| Sort the list in km, time, and velocity orders |
+--------------------------------------------------------------------*/
call sort_top_nn('K');
call sort_top_nn('T');
call sort_top_nn('V');
1/*--------------------------------------------------------------------+
| Top-NN tables: |
| |
| - top-50 tables for the summary |
| - top-10 tables per |
| + trip |
| + type |
| + country |
| + nationality |
| + year |
+--------------------------------------------------------------------*/
alloc t10_summ;
t10_summ.su_ix = 0;
alloc t10_trip;
t10_trip.tr_ix = 0;
alloc t10_type;
t10_type.ty_ix = 0;
alloc t10_cnty;
t10_cnty.co_ix = 0;
alloc t10_nat;
t10_nat.na_ix = 0;
alloc t10_year;
t10_year.yr_ix = 0;
1do #i = #ride to 1 by -1;
/*------------------------------------------------------------------+
| Distance list |
+------------------------------------------------------------------*/
lift_ptr = top_k_ptr(#i);
/*------------------------------------------------------------------+
| Summary - distance |
+------------------------------------------------------------------*/
#j = t10_summ(1).su_ix(1) + 1;
if #j <= hbound(su_ktv, 3) then
do;
t10_summ(1).su_ktv(1, #j) = lift_ptr;
t10_summ(1).su_ix(1) = #j;
end;
/*------------------------------------------------------------------+
| Trip - distance |
+------------------------------------------------------------------*/
#j = t10_trip(lift_list.trip).tr_ix(1) + 1;
if #j <= hbound(tr_ktv, 3) then
do;
t10_trip(lift_list.trip).tr_ktv(1, #j) = lift_ptr;
t10_trip(lift_list.trip).tr_ix(1) = #j;
end;
/*------------------------------------------------------------------+
| Type - distance |
+------------------------------------------------------------------*/
#s = (index(a_typ, lift_list.type || ' ') + 4) / 5;
#j = t10_type(#s).ty_ix(1) + 1;
if #j <= hbound(ty_ktv, 3) then
do;
t10_type(#s).ty_ktv(1, #j) = lift_ptr;
t10_type(#s).ty_ix(1) = #j;
end;
/*------------------------------------------------------------------+
| Country - distance |
+------------------------------------------------------------------*/
#s = (index(a_cnty, lift_list.cnty || ' ') + 4) / 5;
#j = t10_cnty(#s).co_ix(1) + 1;
if #j <= hbound(co_ktv, 3) then
do;
t10_cnty(#s).co_ktv(1, #j) = lift_ptr;
t10_cnty(#s).co_ix(1) = #j;
end;
1 /*------------------------------------------------------------------+
| Nationality - distance |
+------------------------------------------------------------------*/
#s = (index(a_nat, lift_list.nat || ' ') + 4) / 5;
#j = t10_nat(#s).na_ix(1) + 1;
if #j <= hbound(na_ktv, 3) then
do;
t10_nat(#s).na_ktv(1, #j) = lift_ptr;
t10_nat(#s).na_ix(1) = #j;
end;
/*------------------------------------------------------------------+
| Year - distance |
+------------------------------------------------------------------*/
#j = t10_year(lift_list.year).yr_ix(1) + 1;
if #j <= hbound(yr_ktv, 3) then
do;
t10_year(lift_list.year).yr_ktv(1, #j) = lift_ptr;
t10_year(lift_list.year).yr_ix(1) = #j;
end;
/*------------------------------------------------------------------+
| Time list |
+------------------------------------------------------------------*/
lift_ptr = top_t_ptr(#i);
/*------------------------------------------------------------------+
| Summary - time |
+------------------------------------------------------------------*/
#j = t10_summ(1).su_ix(2) + 1;
if #j <= hbound(su_ktv, 3) then
do;
t10_summ(1).su_ktv(2, #j) = lift_ptr;
t10_summ(1).su_ix(2) = #j;
end;
/*------------------------------------------------------------------+
| Trip - time |
+------------------------------------------------------------------*/
#j = t10_trip(lift_list.trip).tr_ix(2) + 1;
if #j <= hbound(tr_ktv, 3) then
do;
t10_trip(lift_list.trip).tr_ktv(2, #j) = lift_ptr;
t10_trip(lift_list.trip).tr_ix(2) = #j;
end;
1 /*------------------------------------------------------------------+
| Type - time |
+------------------------------------------------------------------*/
#s = (index(a_typ, lift_list.type || ' ') + 4) / 5;
#j = t10_type(#s).ty_ix(2) + 1;
if #j <= hbound(ty_ktv, 3) then
do;
t10_type(#s).ty_ktv(2, #j) = lift_ptr;
t10_type(#s).ty_ix(2) = #j;
end;
/*------------------------------------------------------------------+
| Country - time |
+------------------------------------------------------------------*/
#s = (index(a_cnty, lift_list.cnty || ' ') + 4) / 5;
#j = t10_cnty(#s).co_ix(2) + 1;
if #j <= hbound(co_ktv, 3) then
do;
t10_cnty(#s).co_ktv(2, #j) = lift_ptr;
t10_cnty(#s).co_ix(2) = #j;
end;
/*------------------------------------------------------------------+
| Nationality - time |
+------------------------------------------------------------------*/
#s = (index(a_nat, lift_list.nat || ' ') + 4) / 5;
#j = t10_nat(#s).na_ix(2) + 1;
if #j <= hbound(na_ktv, 3) then
do;
t10_nat(#s).na_ktv(2, #j) = lift_ptr;
t10_nat(#s).na_ix(2) = #j;
end;
/*------------------------------------------------------------------+
| Year - time |
+------------------------------------------------------------------*/
#j = t10_year(lift_list.year).yr_ix(2) + 1;
if #j <= hbound(yr_ktv, 3) then
do;
t10_year(lift_list.year).yr_ktv(2, #j) = lift_ptr;
t10_year(lift_list.year).yr_ix(2) = #j;
end;
1 /*------------------------------------------------------------------+
| Velocity list |
+------------------------------------------------------------------*/
lift_ptr = top_v_ptr(#i);
/*------------------------------------------------------------------+
| Summary - time |
+------------------------------------------------------------------*/
#j = t10_summ(1).su_ix(3) + 1;
if #j <= hbound(su_ktv, 3) then
do;
t10_summ(1).su_ktv(3, #j) = lift_ptr;
t10_summ(1).su_ix(3) = #j;
end;
/*------------------------------------------------------------------+
| Trip - velocity |
+------------------------------------------------------------------*/
#j = t10_trip(lift_list.trip).tr_ix(3) + 1;
if #j <= hbound(tr_ktv, 3) then
do;
t10_trip(lift_list.trip).tr_ktv(3, #j) = lift_ptr;
t10_trip(lift_list.trip).tr_ix(3) = #j;
end;
/*------------------------------------------------------------------+
| Type - velocity |
+------------------------------------------------------------------*/
#s = (index(a_typ, lift_list.type || ' ') + 4) / 5;
#j = t10_type(#s).ty_ix(3) + 1;
if #j <= hbound(ty_ktv, 3) then
do;
t10_type(#s).ty_ktv(3, #j) = lift_ptr;
t10_type(#s).ty_ix(3) = #j;
end;
/*------------------------------------------------------------------+
| Country - time |
+------------------------------------------------------------------*/
#s = (index(a_cnty, lift_list.cnty || ' ') + 4) / 5;
#j = t10_cnty(#s).co_ix(3) + 1;
if #j <= hbound(co_ktv, 3) then
do;
t10_cnty(#s).co_ktv(3, #j) = lift_ptr;
t10_cnty(#s).co_ix(3) = #j;
end;
1 /*------------------------------------------------------------------+
| Nationality - velocity |
+------------------------------------------------------------------*/
#s = (index(a_nat, lift_list.nat || ' ') + 4) / 5;
#j = t10_nat(#s).na_ix(3) + 1;
if #j <= hbound(na_ktv, 3) then
do;
t10_nat(#s).na_ktv(3, #j) = lift_ptr;
t10_nat(#s).na_ix(3) = #j;
end;
/*------------------------------------------------------------------+
| Year - velocity |
+------------------------------------------------------------------*/
#j = t10_year(lift_list.year).yr_ix(3) + 1;
if #j <= hbound(yr_ktv, 3) then
do;
t10_year(lift_list.year).yr_ktv(3, #j) = lift_ptr;
t10_year(lift_list.year).yr_ix(3) = #j;
end;
end;
outfile = ntopout;
call top_nn(t10_summ, '**');
call top_nn(t10_trip, 'Tr');
call top_nn(t10_type, 'Ty');
call top_nn(t10_cnty, 'Co');
call top_nn(t10_nat, 'Na');
call top_nn(t10_year, 'Yr');
call milestones();
close file(xtraout),
file(ntopout),
file(mnthout),
file(weekout),
file(daysout),
file(tripout),
file(liftout),
file(summout),
file(liftin);
/**********************************************************************
* Reorder SUMMOUT and LIFTOUT to match PC versions *
**********************************************************************/
call reorder();
1/**********************************************************************
* PROCESS_INREC: *
* *
* This procedure processes the input records, creating one physical *
* and two logical lists of all rides. *
* *
* - the first logical list is equal to the physical list, in that *
* it simply contains an item for every record in the original *
* input dataset. *
* *
* - the second logical list only contains those records of the *
* original input dataset that do not contain information about *
* day and country splits. *
* *
* - it adds any new types to the current string of types. The string *
* is later used to print the types in the order that was *
* originally created by the paper notes. *
* *
* - it builds a string of all countries passed, in alphabetic order. *
* This string is later used to preallocate a list for the totals *
* per country. *
* *
* - it builds a string of the nationalities of all drivers, also in *
* alphabetic order. This string is later used to preallocate a *
* list for the totals per nationality. *
* *
* - it connects all lifts into a dynamically built list of years *
**********************************************************************/
process_inrec: proc;
dcl #d fixed bin (31);
dcl #m fixed bin (31);
dcl #w fixed bin (31);
dcl #wa fixed bin (31);
dcl zz9 pic 'zz9';
/*+-------------------------------------------------------------------+
| Start of executable code for process_inrec |
+-------------------------------------------------------------------+
| Do not yet link the new item into the list, as we now want to |
| post-process the previous ride! |
+------------------------------------------------------------------*/
alloc lift_list;
1 /*------------------------------------------------------------------+
| New ride always starts with a blank split indicator, which means |
| it's now time to post-process the previous ride. |
+------------------------------------------------------------------*/
if liftrec.split = ' ' then
do;
if lift_own ^= sysnull() then
call post_process_ride();
#ride = #ride + 1;
lift_list.id = #ride;
lift_own = lift_ptr;
if ll_top = sysnull() then
ll_top = lift_ptr;
else
ll_end -> ll_nxt = lift_ptr;
ll_end = lift_ptr;
#sd = max(1, (lift_list.km + 24.9) / 25.0);
select;
when (lift_list.km <= 1000.0)
#ld_l = (lift_list.km + 99.9) / 100.0;
other
#ld_l = (lift_list.km + 999.9) / 1000.0 + 9;
end;
#ld_l = min(max(1, #ld_l), hbound(ld.#c, 1));
end;
/*------------------------------------------------------------------+
| Add newly allocated itim into the list of rides |
+------------------------------------------------------------------*/
lift_end -> lift_nxt,
lift_end,
prv_lift = lift_ptr;
prv_day = day_ptr;
owner = lift_own;
if translate(liftrec.cday, ' ',
'!#abcdefghij') = liftrec.cday then
do;
string(zz9) = liftrec.cday;
lift_list.day = zz9;
end;
lift_list.time = liftrec.hh * 60 + liftrec.mm;
1 if lift_list.trip ^= #save_trip then
do;
trip_pic = lift_list.trip;
#save_trip = lift_list.trip;
#save_dow = -1;
#save_mth = -1;
end;
if lift_list.dtime ^= -1 then
lift_work.atime = lift_list.dtime;
if lift_list.date.day ^= 0 then
do;
lift_list.jdn = cj((lift_list.date.day),
(lift_list.date.mnth),
(lift_list.date.year));
lift_list.dow = mod(lift_list.jdn, 7);
#save_dow = lift_list.dow;
#save_day = lift_list.date.day;
#save_mth = lift_list.date.mnth;
/*--------------------------------------------------------------+
| Accumulate use of calendar days |
+--------------------------------------------------------------*/
#w = lift_list.dow;
#d = lift_list.date.day;
#m = lift_list.date.mnth;
lift_work.cdays(#m, #d) = lift_work.cdays(#m, #d) + 1;
if crty(#m, #d, 1) = 0 then
do;
crty(#m, #d, 1) = lift_own -> lift_list.id;
crty(#m, #d, 2) = lift_list.trip;
crty(#m, #d, 3) = lift_list.date.year;
end;
/*---------------------------------------------------------------
ct_mm(#m, 0) = min(ct_mm(#m, 0), lift_list.trip)\
ct_mm(#m, 1) = max(ct_mm(#m, 1), lift_list.trip)\
cy_mm(#m, 0) = min(cy_mm(#m, 0), lift_list.year)\
cy_mm(#m, 1) = max(cy_mm(#m, 1), lift_list.year)\
---------------------------------------------------------------*/
end;
if lift_list.split = '#' then
#s = #s + 1;
1 /*------------------------------------------------------------------+
| Keep track of pickups per weekday per day |
+------------------------------------------------------------------*/
if lift_list.split = ' ' &
lift_list.cday ^= ' #' |
lift_list.split = '#' then
do;
#w = #save_dow;
#d = #save_day;
wdays(#w, #d).km = wdays(#w, #d).km + lift_list.km;
wdays(#w, #d).time = wdays(#w, #d).time + lift_list.time;
end;
/*------------------------------------------------------------------+
| Cater for rides that are split over both days and countries. For |
| these rides the waiting time will be on the first country split, |
| but should be classified under the date of the first day split. |
+------------------------------------------------------------------*/
if #s = 1 &
lift_list.jdn ^= -1 then
do;
jdn_save = lift_list.jdn;
#wait_dow = mod(lift_list.jdn, 7);
#wait_mth = lift_list.date.mnth;
/*--------------------------------------------------------------+
| Cater for the rare situation where the first ride of the day |
| is split over more than one day, but within a single country. |
| In this case the correct date will only be known after the |
| allocation of the lift_list. (Only occurence: T23R22) |
+--------------------------------------------------------------*/
if wift_ptr -> lift_list.trip = lift_list.trip &
wift_ptr -> lift_list.ride = lift_list.ride &
(wift_ptr -> lift_list.dow ^= #wait_dow |
wift_ptr -> lift_list.mnth ^= #wait_mth) then
do;
wift_ptr -> lift_list.dow = #wait_dow;
wift_ptr -> lift_list.mnth = #wait_mth;
end;
end;
1 /*------------------------------------------------------------------+
| Calculate the average velocity with higher precision. Velocities |
| on file are rounded, which means they may be reported as 100.0, |
| whereas in reality they are 99.96... (Zero time: T74R7) |
+------------------------------------------------------------------*/
if lift_list.split ^= '!' then
do;
if lift_list.time ^= 0 then
do;
lift_list.vx = divide(
multiply(lift_list.km, 60, 15, 0),
lift_list.time, 13, 9);
#sp_l = max(1, (lift_list.vx + 9.9999) / 10.0);
#sp_l = min(#sp_l, hbound(sp.#c, 1));
end;
else
lift_list.vx = 0;
if lift_list.split = ' ' then
vx_max_r = max(vx_max_r, lift_list.vx);
end;
if string(liftrec.wait) ^= '' then
do;
lift_list.wtime = liftrec.whh * 60 + liftrec.wmm;
if lift_list.wtime <= 120 then
#wa = wa_hdx(lift_list.wtime);
else
do #wa = 17 to hbound(wa_time, 1)
until(lift_list.wtime <= wa_time(#wa));
end;
lift_list.#wa = #wa;
lift_list.#wx = wa_idx(#wa);
end;
if lift_list.ferry then
#ferry = #ferry + 1;
if lift_list.wferry then
#wferry = #wferry + 1;
1 if lift_list.split = ' ' then
do;
if substr(lift_list.cday, 3, 1) = '#' &
substr(lift_list.cnty, 1, 1) = '*' then
do;
@hash = '1'b;
#wait_dow = #save_dow;
#wait_mth = #save_mth;
end;
else
@hash = '0'b;
end;
/*------------------------------------------------------------------+
| Build list of trips and accumulate totals per trip |
+------------------------------------------------------------------*/
if lift_list.trip ^= lift_work.#trip then
do;
lift_work.#trip = lift_list.trip;
lift_work.#day = -1;
prv_day = sysnull();
alloc trip_list;
if trip_top ^= sysnull() then
trip_end -> nxt_trip = trip_ptr;
trip_end -> trip_nxt,
trip_end = trip_ptr;
trip_total.#trips = trip_total.#trips + 1;
if trip_total.trip = -1 then
trip_total.trip = lift_list.trip - 1;
#wait_prv = -2;
end;
else
do;
trip_list.tr_end -> tr_nxt = lift_ptr;
trip_list.tr_end = lift_ptr;
if lift_list.split = ' ' then
do;
trip_list.#r = trip_list.#r + 1;
trip_list.km = trip_list.km + lift_list.km;
trip_list.time = trip_list.time + lift_list.time;
end;
end;
1 /*------------------------------------------------------------------+
| Build list of days and accumulate totals per day |
+------------------------------------------------------------------*/
if (lift_list.split = ' ' &
lift_list.cday ^= ' #') |
lift_list.split = '#' then
do;
if lift_work.#day ^= lift_list.day then
do;
lift_work.#day = lift_list.day;
alloc day_list;
trip_list.#d = trip_list.#d + 1;
if trip_list.day_top = sysnull() then
trip_list.day_top = day_ptr;
else
trip_list.day_end -> day_nxt,
trip_list.day_end -> td_nxt = day_ptr;
trip_list.day_end = day_ptr;
prv_day = day_ptr;
end;
day_list.km = day_list.km + lift_list.km;
day_list.time = day_list.time + lift_list.time;
if lift_list.split ^= '#' then
day_list.#r = day_list.#r + 1;
else
day_list.#r = day_list.#r +
round(
divide(lift_list.km,
owner -> lift_list.km, 15, 10),
8);
end;
1 /*------------------------------------------------------------------+
| Build list of years and accumulate totals per year |
+------------------------------------------------------------------*/
if lift_list.year ^= 0 &
lift_list.year ^= lift_work.#year then
do;
lift_work.#year = lift_list.year;
alloc year_list;
year_end -> year_nxt,
year_end = year_ptr;
#wait_prv = -2;
end;
else
do;
if lift_list.year = 0 then
lift_list.year = lift_work.#year;
yr_end -> yr_nxt = lift_ptr;
yr_end = lift_ptr;
if lift_list.split = ' ' then
do;
year_list.#r = year_list.#r + 1;
year_list.km = year_list.km + lift_list.km;
year_list.time = year_list.time + lift_list.time;
year_list.trip(2) = lift_list.trip;
year_list.ride(2) = lift_list.ride;
end;
if lift_list.jdn ^= -1 then
year_list.#d = year_list.#d + 1;
end;
/*------------------------------------------------------------------+
| Departure and arrival times |
+------------------------------------------------------------------*/
if string(liftrec.dtime) ^= '' then
do;
lift_work.dtime = liftrec.dhh * 60 + liftrec.dmm;
lift_list.dtime = lift_work.dtime;
if lift_list.jdn ^= -1 then
jdn_save = lift_list.jdn;
end;
1 if string(liftrec.atime) ^= '' then
do;
lift_list.atime = liftrec.ahh * 60 + liftrec.amm;
lift_list.aitime = lift_list.atime;
end;
if lift_list.split = ' ' |
lift_list.split = '#' then
if lift_list.atime ^= -1 then
jdn_save = lift_list.jdn;
/*------------------------------------------------------------------+
| Add waiting time into to sub-list of lift_list |
+------------------------------------------------------------------*/
if lift_list.wtime ^= -1 |
lift_list.split = ' ' & substr(lift_list.cnty, 1, 1) ^= '*' |
lift_list.split = '*' & substr(lift_list.cday, 3, 1) = 'a' then
do;
wift_ptr = lift_ptr;
if ^@hash then
do;
lift_list.dow = lift_work.#save_dow;
lift_list.date.mnth = lift_work.#save_mth;
end;
else
do;
lift_list.dow = lift_work.#wait_dow;
lift_list.date.mnth = lift_work.#wait_mth;
end;
if wift_top = sysnull() then
wift_top = wift_ptr;
else
wift_end -> wift_nxt = wift_ptr;
wift_end = wift_ptr;
end;
lift_own -> lift_list.#n = lift_own -> lift_list.#n + 1;
end process_inrec;
1/**********************************************************************
* POST_PROCESS_RIDE: *
* *
* This procedure is invoked after processing the last input record *
* for the current ride of a trip. It is used to *
* *
* - add types, countries and nationalities to their stores *
* - update the elapsed time based on timezone data *
* - update all '!' split times based on the timezones they occur in *
**********************************************************************/
post_process_ride: proc;
dcl 1 post_work,
2 filler char (32)
init ('POST PROCESS FIXED BIN 31'),
2 #i fixed bin (31),
2 #j fixed bin (31) init (1),
2 #c fixed bin (31) init (0),
2 #cc fixed bin (31) init (1),
2 #c24 fixed bin (31) init (0),
2 #d24 fixed bin (31) init (0),
2 #r24 fixed bin (31) init (0),
2 #midnight fixed bin (31) init (1),
2 #ms fixed bin (31) init (1),
2 #day fixed bin (31),
2 #ruler fixed bin (31),
2 own_id fixed bin (31),
/*--------------------------------------------------------------+
| Various pointers |
| |
| - slift_ptr To reset lift_ptr at exit |
| - hash_ptr Position of last day split |
| - wait_ptr Position of waiting time |
| - ride_split First '!'-split record for a ride |
+--------------------------------------------------------------*/
2 filler char (16) init ('VARIOUS POINTERS'),
2 slift_ptr ptr init (lift_ptr),
2 hash_ptr ptr init (lift_own),
2 wait_ptr ptr init (sysnull()),
2 ride_split ptr init (sysnull()),
2 filler char (16) init ('BIT SWITCHES '),
2 bits aligned,
3 @go bit (1) init ('0'b),
3 filler char (3),
1 2 filler char (16) init ('FIXED DEC '),
2 day fixed (3) init (-1),
2 pp_dtime fixed (5)
init (lift_own -> lift_list.dtime),
2 pp_atime fixed (5)
init (lift_own -> lift_list.atime),
2 pp_itime fixed (5),
2 pp_ntime fixed (5) init (-9999),
2 prv_dtime fixed (5) init (-9999),
2 cur_day fixed (5)
init (lift_own -> lift_list.day),
2 filler char (3),
2 filler char (16) init ('CNTY/TZ INFO '),
2 atz(16),
3 atzc char (4) init ((16)((4)'*')),
3 atzt fixed (5) init ((16)99999),
3 filler char (1),
2 filler char (16) init ('SPLIT RULER '),
2 split_ruler(32),
3 time(0:1) fixed (5) init ((32)((2)0)),
3 cnty char (4) init ((32)((4)' ')),
3 day fixed (3) init ((32)0),
3 km fixed (9,1) init ((32)0),
3 etime fixed (9) init ((32)0),
2 filler char (16) init ('SPLIT DAYS '),
2 a_ddt(16),
3 day fixed (3),
3 km fixed (9,1) init ((16)0),
3 time fixed (9),
3 filler char (4),
2 filler char (16) init ('SPLIT COUNTRIES '),
2 a_cdt(16),
3 cnty char (4),
3 km fixed (9,1) init ((16)0),
3 time fixed (9),
3 filler char (2),
2 eor_post_work char (0);
1/*--------------------------------------------------------------------+
| Abbreviated LIFT_LIST |
+--------------------------------------------------------------------*/
dcl 1 pp_list based(pp_ptr),
2 pp_nxt ptr,
2 filler char (8),
2 ride fixed bin (31),
2 filler char (48),
2 jdn fixed (7),
2 day fixed (3),
2 eol char (0);
/*+-------------------------------------------------------------------+
| Start of executable code for post_process_ride |
+------------------------------------------------------------------*/
lift_ptr = lift_own;
own_id = lift_list.id;
if lift_list.ride = 1 then
pp_ptr = lift_own;
a_ddt(1).day = lift_list.day;
a_ddt(1).km = lift_list.km;
a_ddt(1).time = lift_list.time;
a_cdt(1).cnty = lift_list.cnty;
a_cdt(1).km = lift_list.km;
a_cdt(1).time = lift_list.time;
/*------------------------------------------------------------------+
| Add new type to range of types - only once! |
+------------------------------------------------------------------*/
if substr(tcn_t, 1, 4) ^= lift_list.type then
do;
substr(tcn_t, 1, 4) = lift_list.type;
if index(a_typ, tcn_t) = 0 then
do;
#type = #type + 1;
a_typ = a_typ || tcn_t;
end;
end;
1 /*------------------------------------------------------------------+
| Insert new nationality (in alphabetic order) |
+------------------------------------------------------------------*/
if substr(tcn_n, 1, 4) ^= lift_list.nat then
do;
substr(tcn_n, 1, 4) = lift_list.nat;
do #i = 1 to length(a_nat) by 5
while(substr(a_nat, #i, 5) < tcn_n);
end;
if substr(a_nat, #i, 5) ^= tcn_n then
do;
#nat = #nat + 1;
a_nat = substr(a_nat, 1, #i - 1) ||
tcn_n ||
substr(a_nat, #i);
end;
end;
/*------------------------------------------------------------------+
| Process this ride |
| |
| - get last (if any) day split, to allow atime-to-UTC conversion |
| - count countries |
| - add countries to range of countries |
| - collect timezones for countries in this ride |
| - convert times of splits to UTC |
+------------------------------------------------------------------*/
do lift_ptr = lift_own repeat lift_nxt
while(lift_ptr ^= sysnull());
lift_list.id = own_id;
/*----------------------------------------------------------------+
| Process "hitched-in" data |
+----------------------------------------------------------------*/
if lift_list.split ^= '#' &
lift_list.split ^= '!' &
lift_list.cnty ^= '* ' then
do;
if cplates.plate(#ci) ^= lift_list.cnty then
#ci = srch_cnty(lift_list.cnty);
if lift_list.nat = lift_list.cnty then
#pi = #ci;
else
if cplates.plate(#pi) ^= lift_list.nat then
#pi = srch_cnty(lift_list.nat);
1 if #ci > 0 then
do;
plates(#ci).visit = '1'b;
if lift_list.split = ' ' |
substr(lift_list.cday, 3, 1) = 'a' then
do;
plates(#ci).hitch = 'H';
if lift_list.cnty = lift_list.nat then
plates(#ci).local = '+';
end;
else
if plates(#ci).hitch = ' ' &
lift_list.split = '*' then
plates(#ci).hitch = '*';
end;
if #pi > 0 then
if plates(#pi).local = ' ' then
plates(#pi).local = '-';
end;
select;
/*--------------------------------------------------------------+
| Process splits |
+--------------------------------------------------------------*/
when (lift_list.split = '!')
do;
/*----------------------------------------------------------+
| Save starting position of first split |
+----------------------------------------------------------*/
if ride_split = sysnull() then
ride_split = lift_ptr;
#ms = #ms + 1;
lift_list.utc_dtime = lift_list.dtime - atzt(#cc);
if substr(lift_list.type, 2, 1) = 'B' then
#cc = #cc + 1;
/*----------------------------------------------------------+
| Save the departure time of the idle-time split |
+----------------------------------------------------------*/
if substr(lift_list.type, 2, 1) = '^' then
if substr(owner -> lift_list.cday, 3, 1) ^= '#' then
pp_ntime = lift_list.dtime;
else
if lift_list.atime > lift_list.dtime then
pp_ntime = lift_list.dtime;
1 /*----------------------------------------------------------+
| Calculate, if the stop has an arrival time, the duration |
| of the stop (and cater for over-midnight stops) |
+----------------------------------------------------------*/
if lift_list.atime ^= -1 then
do;
lift_list.utc_atime = lift_list.atime - atzt(#cc);
pp_itime = lift_list.utc_atime -
lift_list.utc_dtime;
if pp_itime < 0 then
pp_itime = pp_itime + 1440;
lift_list.itime = pp_itime;
owner -> lift_list.itime = owner -> lift_list.itime +
pp_itime;
end;
if substr(lift_list.type, 2, 1) ^= '^' &
substr(lift_list.type, 2, 1) ^= '&' & /* Smiespel */
lift_list.itime ^= 0 then
owner -> lift_list.#spl = owner -> lift_list.#spl + 1;
if substr(lift_list.type, 2, 1) = 'B' then
do;
/*------------------------------------------------------+
| Two types of midnight border crossings: |
| |
| - lift_list.type: "!B#" (midnight + timezone (atz)) |
| - lift_list.atz : "#" (midnight) |
| |
| Status at T286R04: *S* |
| |
| - T009R41 DK - D ("#") |
| - T011R15 DK - D ("#") |
| - T015R34 I - A ("#") |
| - T041R15 PL - LT ("!B# ") |
| - T052R10 D - PL ("#") |
| - T054R13 D - PL ("#") |
| - T061R19 PL - LT ("!B# ") |
| - T065R08 PL - LT ("!B# ") |
| - T143R25 PL - LT ("!B# ") |
| - T233R17 PL - LT ("!B# ") |
+------------------------------------------------------*/
if substr(lift_list.type, 3, 1) = '#' |
lift_list.atz = '#' then
#midnight = #midnight + 1;
end;
1 /*----------------------------------------------------------+
| Add starting day to splits, simplifying processing of |
| times per day. |
+----------------------------------------------------------*/
if prv_dtime = -9999 then
prv_dtime = pp_dtime - atzt(1);
if lift_list.utc_dtime < prv_dtime then
cur_day = cur_day + 1;
lift_list.spl_day = cur_day;
prv_dtime = lift_list.utc_dtime;
end;
/*--------------------------------------------------------------+
| Process countries |
+--------------------------------------------------------------*/
when (lift_list.cnty ^= ' ' &
lift_list.cnty ^= '* ')
do;
/*----------------------------------------------------------+
| Count number of countries passed through |
+----------------------------------------------------------*/
lift_own -> lift_list.#cspl =
lift_own -> lift_list.#cspl + 1;
/*----------------------------------------------------------+
| Process the country ('*') split |
+----------------------------------------------------------*/
if lift_list.split = '*' then
do;
if wait_ptr = sysnull() then
wait_ptr = lift_ptr;
/*------------------------------------------------------+
| Save the country, distance, and time for this split |
+------------------------------------------------------*/
#c24 = #c24 + 1;
a_cdt(#c24).cnty = lift_list.cnty;
a_cdt(#c24).km = lift_list.km;
a_cdt(#c24).time = lift_list.time;
end;
1 /*----------------------------------------------------------+
| Insert new country (in alphabetic order) |
+----------------------------------------------------------*/
if substr(tcn_c, 1, 4) ^= lift_list.cnty then
do;
substr(tcn_c, 1, 4) = lift_list.cnty;
do #i = 1 to length(a_cnty) by 5
while(substr(a_cnty, #i, 5) < tcn_c);
end;
if substr(a_cnty, #i, 5) ^= tcn_c then
do;
#cnty = #cnty + 1;
a_cnty = substr(a_cnty, 1, #i - 1) ||
tcn_c ||
substr(a_cnty, #i);
end;
/*------------------------------------------------------+
| Looking forward or backward first is more efficient |
+------------------------------------------------------*/
if timezone(#tzp + 1).tzc = lift_list.cnty then
#tzp = #tzp + 1;
else
if timezone(#tzp - 1).tzc = lift_list.cnty then
#tzp = #tzp - 1;
else
if timezone(#tzp).tzc ^= lift_list.cnty then
do #tzp = 1 to hbound(timezone.tzc, 1)
while(timezone(#tzp).tzc ^= lift_list.cnty);
end;
end;
lift_list.utc_cnty = timezone(#tzp).tzt;
#c = #c + 1;
atzc(#c) = lift_list.cnty;
atzt(#c) = timezone(#tzp).tzt;
end;
1 /*--------------------------------------------------------------+
| Process day splits |
| - need to locate the last for atime |
| - save the day, distance, and time for this split |
| - save the arrival time for this day split |
+--------------------------------------------------------------*/
when (lift_list.split = '#')
do;
if cur_day = -1 then
cur_day = lift_list.day;
hash_ptr = lift_ptr;
#ms = #ms + 1;
#d24 = #d24 + 1;
a_ddt(#d24).day = lift_list.day;
a_ddt(#d24).km = lift_list.km;
a_ddt(#d24).time = lift_list.time;
pp_atime = lift_list.atime;
end;
other;
end;
end;
/*------------------------------------------------------------------+
| Change the departure and arrival times to UTC, and calculate the |
| elapsed time for the ride |
+------------------------------------------------------------------*/
lift_own -> lift_list.utc_dtime = pp_dtime - atzt(1);
hash_ptr -> lift_list.utc_atime = pp_atime - atzt(#c);
lift_own -> lift_list.etime = hash_ptr -> lift_list.utc_atime -
lift_own -> lift_list.utc_dtime;
if #d24 > 1 then
lift_own -> lift_list.etime = lift_own -> lift_list.etime +
(#d24 - 1) * 1440;
/*------------------------------------------------------------------+
| Keep track of per-trip and global maximum number of timed splits |
+------------------------------------------------------------------*/
trip_list.#ms = max(trip_list.#ms, #ms);
lift_work.#ms = max(lift_work.#ms, #ms);
1 /*------------------------------------------------------------------+
| Prepare for split processing |
+------------------------------------------------------------------*/
#c24 = max(#c24, 1);
#d24 = max(#d24, 1);
#ruler = #d24 + #c24 - #midnight;
/*------------------------------------------------------------------+
| Need data from the first record of a ride |
+------------------------------------------------------------------*/
lift_ptr = lift_own;
/*------------------------------------------------------------------+
| Fill in the data for the various slots |
| |
| A new slot is required for every change of day and/or change of |
| country. (A change of both day and country will allocate only |
| one slot) |
+------------------------------------------------------------------*/
select;
when (#ruler = 1)
do;
split_ruler(1).time(0) = lift_list.dtime;
/*------------------------------------------------------------+
| Use starting time of idle-time as end-of-ride time! |
+------------------------------------------------------------*/
if pp_ntime ^= -9999 then
split_ruler(1).time(1) = pp_ntime;
else
split_ruler(1).time(1) = lift_list.atime;
split_ruler(1).cnty = lift_list.cnty;
split_ruler(1).day = lift_list.day;
split_ruler(1).km = lift_list.km;
split_ruler(1).etime = lift_list.time;
end;
other
do;
split_ruler(1) = '';
split_ruler = split_ruler(1);
/*------------------------------------------------------------+
| Ruler 1, departure slot: |
| - time : departure time for the ride |
| - country: country where ride starts |
| - day : departure day for the ride |
+------------------------------------------------------------*/
split_ruler(1).time(0) = pp_dtime;
split_ruler(1).cnty = a_cdt(1).cnty;
split_ruler(1).day = a_ddt(1).day;
1 /*------------------------------------------------------------+
| Last ruler, arrival slot: |
| - time : arrival time for the ride |
| - country: country where ride ends |
| - day : arrival day for the ride |
+-------------------------------------------------------------+
| Use starting time of idle-time as end-of-ride time! |
+------------------------------------------------------------*/
if pp_ntime ^= -9999 then
split_ruler(#ruler).time(1) = pp_ntime;
else
split_ruler(#ruler).time(1) = pp_atime;
split_ruler(#ruler).cnty = a_cdt(#c24).cnty;
split_ruler(#ruler).day = a_ddt(#d24).day;
#c24 = 1;
#d24 = 1;
#r24 = 1;
/*------------------------------------------------------------+
| No splits is only possible for a ride that goes through |
| one country over midnight, without stopping. |
+------------------------------------------------------------*/
split_ruler(1).time(1) = 1440;
do lift_ptr = ride_split repeat lift_nxt
while(lift_ptr ^= sysnull());
pp_atime = lift_list.atime;
if pp_atime = -1 then
pp_atime = lift_list.dtime;
select;
/*--------------------------------------------------------+
| Leaving a country at midnight |
+--------------------------------------------------------*/
when (substr(lift_list.type, 1, 3) = '!B#' |
lift_list.atz = '#')
do;
split_ruler(#r24).time(1) = lift_list.dtime;
split_ruler(#r24).cnty = a_cdt(#c24).cnty;
split_ruler(#r24).day = a_ddt(#d24).day;
#d24 = #d24 + 1;
#c24 = #c24 + 1;
#r24 = #r24 + 1;
split_ruler(#r24).time(0) = pp_atime;
split_ruler(#r24).cnty = a_cdt(#c24).cnty;
split_ruler(#r24).day = a_ddt(#d24).day;
end;
1 /*--------------------------------------------------------+
| Leaving a country |
+--------------------------------------------------------*/
when (substr(lift_list.type, 1, 2) = '!B')
do;
if (lift_prv -> lift_list.atime > 720 &
lift_list.dtime < 720)
|
(lift_list.cday = '! 1' &
pp_dtime > 720 &
lift_list.dtime < 720) then
do;
split_ruler(#r24).time(1) = 1440;
split_ruler(#r24).cnty = a_cdt(#c24).cnty;
split_ruler(#r24).day = a_ddt(#d24).day;
#d24 = #d24 + 1;
#r24 = #r24 + 1;
split_ruler(#r24).time(0) = 0;
end;
split_ruler(#r24).time(1) = lift_list.dtime;
split_ruler(#r24).cnty = a_cdt(#c24).cnty;
split_ruler(#r24).day = a_ddt(#d24).day;
#c24 = #c24 + 1;
#r24 = #r24 + 1;
split_ruler(#r24).time(0) = pp_atime;
split_ruler(#r24).cnty = a_cdt(#c24).cnty;
split_ruler(#r24).day = a_ddt(#d24).day;
end;
/*--------------------------------------------------------+
| A real day split, stopping across midnight |
+--------------------------------------------------------*/
when (lift_list.dtime > 720 &
lift_list.atime ^= -1 &
lift_list.atime < 720)
do;
split_ruler(#r24).time(1) = lift_list.dtime;
split_ruler(#r24).cnty = a_cdt(#c24).cnty;
split_ruler(#r24).day = a_ddt(#d24).day;
#d24 = #d24 + 1;
#r24 = #r24 + 1;
split_ruler(#r24).time(0) = pp_atime;
split_ruler(#r24).cnty = a_cdt(#c24).cnty;
split_ruler(#r24).day = a_ddt(#d24).day;
end;
1 /*--------------------------------------------------------+
| A virtual day split, driving across midnight |
+--------------------------------------------------------*/
when ((lift_prv -> lift_list.atime > 720 &
lift_list.dtime < 720)
|
(lift_list.cday = '! 1' &
pp_dtime > 720 &
lift_list.dtime < 720))
do;
split_ruler(#r24).time(1) = 1440;
split_ruler(#r24).cnty = a_cdt(#c24).cnty;
split_ruler(#r24).day = a_ddt(#d24).day;
pp_atime = 0;
#d24 = #d24 + 1;
#r24 = #r24 + 1;
split_ruler(#r24).time(0) = pp_atime;
split_ruler(#r24).cnty = a_cdt(#c24).cnty;
split_ruler(#r24).day = a_ddt(#d24).day;
end;
other;
end;
end;
1 /*------------------------------------------------------------+
| Add the distance & time data to the slots. Processing is |
| the same for every slot: |
| |
| | A | B | C | D | E | F | G | |
| +S1---+S2-----+S3-+S4-+S5-----+S6-----+S7-------+S8-------+ |
| | Day 1 | Day 2 | Day 3 | |
| |
| For the above, there are |
| |
| - 7 countries |
| - 3 days |
| - 1 midnight crossing |
| |
| so a total of 7+3-1-1 slots is required (there is always |
| one slot less than the sum of the number of countries and |
| days) |
| |
| It should be obvious that the slots can be filled in a |
| simple loop, comparing the country and day distances. In |
| other words, for the above the first slot will contain the |
| shortest of the country "A" and day "1" distance. The |
| country "A" distance is then subtracted from the day "1" |
| distance, effectively reducing the problem to: |
| |
| | B | C | D | E | F | G | |
| +S2-----------+S3-+S4-+S5-----+S6-----+S7-------+S8-------+ |
| | Day 1' | Day 2 | Day 2 | |
| |
| which is essentially the situation as before! Of course it |
| should be obvious that the roles of days and countries are |
| interchangable. |
+------------------------------------------------------------*/
1 #c24 = 1;
#d24 = 1;
do #i = 1 to #ruler;
select;
when (a_cdt(#c24).km > a_ddt(#d24).km)
do;
split_ruler(#i).km = a_ddt(#d24).km;
split_ruler(#i).etime = a_ddt(#d24).time;
a_cdt(#c24).km = a_cdt(#c24).km - a_ddt(#d24).km;
a_cdt(#c24).time = a_cdt(#c24).time - a_ddt(#d24).time;
#d24 = #d24 + 1;
end;
when (a_cdt(#c24).km < a_ddt(#d24).km)
do;
split_ruler(#i).km = a_cdt(#c24).km;
split_ruler(#i).etime = a_cdt(#c24).time;
a_ddt(#d24).km = a_ddt(#d24).km - a_cdt(#c24).km;
a_ddt(#d24).time = a_ddt(#d24).time - a_cdt(#c24).time;
#c24 = #c24 + 1;
end;
other
do;
split_ruler(#i).km = a_cdt(#c24).km;
split_ruler(#i).etime = a_cdt(#c24).time;
#c24 = #c24 + 1;
#d24 = #d24 + 1;
end;
end;
end;
end;
end;
lift_ptr = lift_own;
1 do #i = 1 to #ruler;
/*----------------------------------------------------------------+
| The distance for a split can be zero if there is an idle time |
| split that spans midnight! (T74R7, T108R17, T152R6, T208R6) *S* |
+----------------------------------------------------------------*/
if split_ruler(#i).km ^= 0 then
do;
if split_ruler(#i).time(1) = 0 then
split_ruler(#i).time(1) = 1440;
alloc split_list;
split_end -> split_nxt,
split_end = split_ptr;
split_list.trip = lift_list.trip;
split_list.ride = lift_list.ride;
split_list.sect = #i;
split_list.km = split_ruler(#i).km;
split_list.time = split_ruler(#i).etime;
split_list.day = split_ruler(#i).day;
split_list.dtime = split_ruler(#i).time(0);
split_list.atime = split_ruler(#i).time(1);
split_list.cnty = split_ruler(#i).cnty;
if split_list.cnty ^= atzc(#j) then
select;
when(split_list.cnty = atzc(#j + 1)) #j = #j + 1;
when(split_list.cnty = atzc(#j - 1)) #j = #j - 1;
other
do #j = 1 to #c while(split_list.cnty ^= atzc(#j));
end;
end;
split_list.dtime_utc = split_list.dtime - atzt(#j);
split_list.atime_utc = split_list.atime - atzt(#j);
if post_work.day ^= split_ruler(#i).day then
do;
post_work.day = split_ruler(#i).day;
do pp_ptr = pp_ptr repeat pp_nxt
while(pp_ptr ^= sysnull())
until(pp_list.jdn ^= -1 &
pp_list.day = post_work.day);
end;
end;
split_list.jdn = pp_list.jdn;
split_list.stamp = pp_list.jdn * 1440 + split_list.atime_utc;
end;
end;
1 if wait_ptr = sysnull() then
wait_ptr = lift_own;
/*------------------------------------------------------------------+
| Reset per ride variables |
+------------------------------------------------------------------*/
#s = 0;
lift_ptr = slift_ptr;
end post_process_ride;
1/**********************************************************************
* PROCESS_LIST: *
* *
* This procedure processes the current item in any of the logical *
* lists of lifts. Depending on the type of list currently being *
* processed, it invokes the following procedures: *
* *
* Summary Trip Type Country Nat Year *
* *
* - process_min_max + + + + + + *
* - process_short_distance + + + + + + *
* - process_long_distance + + + + + + *
* - process_type + + + + + *
* - process_cnty + + + + + *
* - process_nationality + + + + + *
* - process_speed + + + + + + *
* - process_wait + + + + *
* - process_irw + + + *
* *
* However, when processing a split for a country it only invokes *
* process_cnty. *
* *
* Note that day splits have already been processed while reading in *
* the input dataset in "process_inrec". *
**********************************************************************/
process_list: proc;
dcl save_lift_ptr ptr init (lift_ptr);
dcl #d fixed bin (31);
dcl #h fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for process_list |
+------------------------------------------------------------------*/
if lift_list.date.day ^= 0 then
do;
#save_dow = lift_list.dow;
#save_day = lift_list.date.day;
#save_mth = lift_list.date.mnth;
end;
select(lift_list.split);
when (' ')
do;
/*------------------------------------------------------------+
| Min max processing for ride |
+------------------------------------------------------------*/
call process_min_max(1,
lift_list.km,
lift_list.time,
lift_list.vx);
1 /*------------------------------------------------------------+
| Short distance processing |
+------------------------------------------------------------*/
if lift_list.km <= 100.0 then
call process_short_distance();
/*------------------------------------------------------------+
| Long distance processing |
+------------------------------------------------------------*/
call process_long_distance(lift_list.km,
lift_list.time,
lift_list.#ld_l);
/*------------------------------------------------------------+
| Type processing |
+------------------------------------------------------------*/
if ^@type then
call process_type();
/*------------------------------------------------------------+
| Country processing |
+------------------------------------------------------------*/
if ^@cnty &
substr(lift_list.cnty, 1, 1) ^= '*' then
call process_cnty();
/*------------------------------------------------------------+
| Nationality processing |
+------------------------------------------------------------*/
if ^@nat then
call process_nationality();
/*------------------------------------------------------------+
| Speed processing |
+------------------------------------------------------------*/
call process_speed(lift_list.km,
lift_list.time,
lift_list.#sp_l);
1 /*------------------------------------------------------------+
| Process pickups - may need to update day and month first! |
+------------------------------------------------------------*/
if @summary then
do;
if substr(lift_list.cday, 3, 1) = '#' then
if lift_ptr -> lift_nxt -> lift_list.date.day ^= 0 then
do;
#save_dow = lift_ptr -> lift_nxt -> lift_list.dow;
#save_day =
lift_ptr -> lift_nxt -> lift_list.date.day;
#save_mth =
lift_ptr -> lift_nxt -> lift_list.date.mnth;
end;
/*--------------------------------------------------------+
| Pickup days per month |
+--------------------------------------------------------*/
pdays(#save_mth, #save_day) =
pdays(#save_mth, #save_day) + 1;
/*--------------------------------------------------------+
| Weekdays per month |
+--------------------------------------------------------*/
wdays(#save_dow, #save_day).#pw =
wdays(#save_dow, #save_day).#pw + 1;
end;
/*------------------------------------------------------------+
| Wait processing |
+------------------------------------------------------------*/
if (@summary |
@trip |
@year) &
substr(lift_list.cnty, 1, 1) ^= '*' then
call process_wait();
end;
/*----------------------------------------------------------------+
| '!' - In-ride wait processing |
+----------------------------------------------------------------*/
when ('!')
do;
if @summary |
@trip |
@year then
if lift_list.atime ^= -1 then
call process_irw();
end;
1 /*----------------------------------------------------------------+
| '*' - Split country processing |
+----------------------------------------------------------------*/
when ('*')
do;
if ^@cnty then
call process_cnty();
if (@summary |
@trip |
@year) &
substr(lift_list.cday, 3, 1) = 'a' then
call process_wait();
end;
other;
end;
/*------------------------------------------------------------------+
| Process departure times |
+------------------------------------------------------------------*/
if @summary &
lift_list.split ^= '!' &
lift_list.dtime ^= -1 then
do;
/*--------------------------------------------------------------+
| Get JDN for a split ride, first looking forward |
+--------------------------------------------------------------*/
if lift_list.jdn = -1 then
if lift_list.cday = ' #' then
lift_ptr = lift_nxt;
/*--------------------------------------------------------------+
| No date found, look backwards, every ride! |
+--------------------------------------------------------------*/
do lift_ptr = lift_ptr repeat lift_prv
while(lift_list.jdn = -1);
end;
#d = mod(lift_list.jdn, 7);
lift_ptr = save_lift_ptr;
#h = (lift_list.dtime - 1) / 60;
hours(#d, #h) = hours(#d, #h) + 1;
end;
end process_list;
1/**********************************************************************
* PRINT_LIST: *
* *
* This procedure prints the results from processing a logical list of *
* lifts. Depending on the type of list that has been processed, it *
* invokes the following procedures: *
* *
* Summary Trip Type Country Nat Day Year *
* *
* - print_trip + *
* - print_day + *
* - print_distance + + + + + + + *
* - print_type + + + + + (1) *
* - print_cnty + + + + + (2) *
* - print_nationality C C A C C (3) *
* - print_speed + + + + + + + *
* - print_min_max R D R R R (4) *
* - print_wait + + + *
* - print_waitsd + + + *
* - print_irw + + + *
* - print_ferry + *
* - process_pickups + + + *
* *
* Notes: *
* *
* 1 - print_type is not used when types are being processed, as *
* this would only add a box with one line. In stead the type *
* is added to the heading of the distances box. *
* *
* 2 - print_cnty is not used when countries are processed, as *
* this would only add a box with one line. In stead the country *
* is added to the heading of the distances box. *
* *
* 3 - print_nationality is not used when nationalities are *
* processed, as this would only add a box with one line. In *
* stead the nationality is added to the heading of the *
* distances box. *
* - The 'A' and 'C' have the following meaning: *
* *
* - 'A': print in alphabetic order *
* - 'C': print in country order, for those nationalities that *
* are the same as the countries passed, and print the *
* remaining nationalities in alphabetic order. *
* *
* 4 - The 'R' and 'D' have the following meaning: *
* *
* - 'R': print only the min/max/avg totals per ride *
* - 'D': print the min/max/avg totals per ride and per day *
**********************************************************************/
1print_list: proc;
write file(outfile) from(pline);
if @summary then
call print_trip();
if @trip then
call print_day();
call print_distance();
if ^@type &
^@day then
call print_type();
/*------------------------------------------------------------------+
| Add connections between country & nationality to be able to print |
| nationalities in country order for the summary, trip and year |
| sections. |
+------------------------------------------------------------------*/
if @summary |
@trip |
@year then
do cnty_ptr = cnty_top repeat cnty_nxt
while(cnty_ptr ^= sysnull());
if cnty_list.int.#c > 0 |
cnty_list.ext.#c > 0 then
do;
if cnty_list.cnty >= nat_mid then
nat_ptr = nat_mptr;
else
nat_ptr = nat_top;
do nat_ptr = nat_ptr repeat nat_nxt
while(nat_ptr ^= sysnull())
until(nat_list.nat = cnty_list.cnty);
end;
cn_ptr = nat_ptr;
end;
end;
if ^@cnty &
^@day then
call print_cnty();
if @summary |
@trip |
@type |
@cnty |
@year then
call print_nationality();
1 call print_speed();
if @type then
do;
call long_tn((type_ptr), 'T');
call long_tn((type_ptr), 't');
end;
if @nat then
do;
call long_tn((nat_ptr), 'N');
call long_tn((nat_ptr), 'n');
end;
if ^@day then
do;
if ^@summary then
call print_min_max_box(' ');
if minmax(1).#mima ^= 0 then
call print_min_max('Ride');
if @trip |
@year then
if minmax(2).#mima ^= 0 then
call print_min_max('Day ');
if ^@summary then
call print_min_max_box('B');
end;
if @summary |
@trip |
@year then
do;
call print_wait();
call print_waitsd();
select;
when (@summary) call after_wait(s_wavg, s_sdev);
when (@trip) /* kall after_wait(t_wavg, t_sdev) *?*/;
when (@year) /* kall after_wait(y_wavg, y_sdev) *?*/;
end;
end;
if @irwait &
(@summary |
@trip |
@year) then
call print_irw();
if @trip then
call period_of_24_hour(-2);
1 if @summary &
(#ferry > 0 |
#wferry > 0) then
call print_ferry();
if @summary |
@trip |
@year then
call process_pickups(pickup_t,
pickup_c,
pickup_n,
#pu_sep);
if @summary then
do;
call print_hours();
call process_mini_wait('PH ');
call process_mini_wait('PD ');
call process_mini_wait('PM ');
end;
end print_list;
1/**********************************************************************
* PRINT_TRIP: *
* *
* Print a summary table for all trips. *
* *
* The table contains one row for every trip, and every row contains *
* the following columns: *
* *
* - Trip - the sequence number of the trip *
* - #D - the number of days for the trip *
* - #C - the number of rides for the trip *
* - KM - the total distance for the trip *
* - Time - the total time for the trip *
* - V= - the average speed for the trip *
* - Qual - the quality for the trip *
* - D= - the average distance per day *
* - R= - the average distance per ride *
* - R/D - the number of rides per day *
**********************************************************************/
print_trip: proc;
dcl save_fast_top ptr init (fast_top);
dcl save_fast_end ptr init (fast_end);
dcl #d fixed (5);
dcl rd fixed (9,5);
dcl prequal fixed (15,4);
/*+-------------------------------------------------------------------+
| Start of executable code for print_trip |
+------------------------------------------------------------------*/
fast_top = sysnull();
fast_end = addr(fast_top);
write file(outfile) from(tryr_sep);
write file(outfile) from(tryr_head);
write file(outfile) from(tryr_sep);
line = tryr_init;
do trip_ptr = trip_top repeat trip_list.trip_nxt
while(trip_ptr ^= sysnull()),
total_ptr;
if trip_ptr ^= total_ptr then
do;
trip_total.trip = trip_total.trip + 1;
trip_total.#d = trip_total.#d + trip_list.#d;
trip_total.#r = trip_total.#r + trip_list.#r;
trip_total.km = trip_total.km + trip_list.km;
trip_total.time = trip_total.time + trip_list.time;
trip_total.vx = divide(
multiply(trip_total.km, 60, 13, 0),
trip_total.time, 13, 9);
1 tryr_line = trip_total, by name;
tryr_line.hh = trip_total.time / 60;
tryr_line.mm = mod(trip_total.time, 60);
tryr_line.v = round(trip_total.vx, 1);
#d = trip_total.#d;
prequal = divide(multiply(trip_total.km,
trip_total.km, 15, 2),
multiply(#d, trip_total.#r, 15, 0),
15, 4);
prequal = multiply(prequal,
#d + trip_total.#r, 15, 4);
tryr_line.qual = round(
divide(prequal,
divide(trip_total.time, 60, 15, 10),
15, 4), 0);
tryr_line.d = round(
divide(trip_total.km, #d, 7, 2), 1);
tryr_line.r = round(
divide(trip_total.km,
trip_total.#r, 7, 2), 1);
rd = divide(trip_total.#r, #d, 9, 5);
/*------------------------------------------------------------+
| Round to even: |
| - Full : T008, cumulative, 338 / 80 |
| - Y2000: T046, cumulative, 245 / 40 *S* |
+------------------------------------------------------------*/
if (unspec(rd) & '000000fff0'bx) = '0000005000'bx then
if (unspec(rd) & '0000010000'bx) = '0000000000'bx then
rd = rd - 0.005;
tryr_line.rd = round(rd, 2);
alloc fast_list;
fast_end -> fast_nxt,
fast_end = fast_ptr;
end;
else
write file(outfile) from(tryr_sep);
trip_list.vx = divide(multiply(trip_list.km, 60, 13, 0),
trip_list.time, 13, 9);
vx_max_t = max(vx_max_t, trip_list.vx);
1 #d = trip_list.#d;
prequal = divide(multiply(trip_list.km,
trip_list.km, 15, 2),
multiply(#d, trip_list.#r, 15, 0),
15, 4);
prequal = multiply(prequal,
#d + trip_list.#r, 15, 4);
trip_list.qual = round(
divide(prequal,
divide(trip_list.time, 60, 15, 10),
15, 4), 0);
trip_list.d = round(
divide(trip_list.km, #d, 7, 2), 1);
trip_list.r = round(
divide(trip_list.km, trip_list.#r, 7, 2), 1);
trip_list.rd = round(
divide(trip_list.#r, #d, 7, 3), 2);
tryr_line = trip_list, by name;
tryr_line.hh = trip_list.time / 60;
tryr_line.mm = mod(trip_list.time, 60);
tryr_line.v = round(trip_list.vx, 1);
if trip_ptr = total_ptr then
string(tryr_line.trip) = 'Tot';
write file(outfile) from(line);
end;
write file(outfile) from(tryr_sep);
write file(outfile) from(iline);
write file(outfile) from(tryr_sep);
write file(outfile) from(tryr_head);
write file(outfile) from(tryr_sep);
do fast_ptr = fast_top repeat fast_nxt
while(fast_ptr ^= sysnull());
write file(outfile) from(fast_list.fline);
end;
write file(outfile) from(tryr_sep);
write file(outfile) from(iline);
call free_fast_list();
fast_top = save_fast_top;
fast_end = save_fast_end;
end print_trip;
1/**********************************************************************
* PRINT_DAY: *
* *
* Print a summary table for the days of the current trip. *
* *
* The table contains one row for every day, and every row contains *
* the following columns: *
* *
* - Day - the sequence number of the day *
* - KM - the total distance for the day *
* - Time - the total time for the day *
* - V= - the average speed for the day *
* - Date - the date of the day *
* - From - the starting time *
* - To - the ending time *
* - Wait - the total waiting time during the day *
* - Stop - the total in-ride stoppage time during the day *
* - Sleep - the sleeping time during the day, not around midnight *
* - S<T>S - the around-midnight sleeping time *
* - Zone - the time gained or lost due to crossing a timezone *
* - Idle - the total non-hitching time during the day *
**********************************************************************/
print_day: proc;
dcl 1 filler static,
2 filler char (16) init ('DAY LINES '),
2 day_sep char (121)
init ((' +-----+--------+-------+' ||
'-------+------------+-------+-------+-------+' ||
'-------+-------+-------+-------+-------+')),
2 day_init char (121)
init ((' | | | : |' ||
' | - - | : | : | : |' ||
' : | | | | |')),
2 day_head char (121)
init ((' | Day | KM | Time |' ||
' V= | Date | From | To | Wait |' ||
' Stop | Sleep | S<T>S | Zone | Idle |'));
1dcl 1 day_line based(line_ptr),
2 filler char (3),
2 day pic 'zz9',
2 filler char (3),
2 km pic 'zzz9v.9',
2 filler char (3),
2 hh pic 'z9',
2 hs char (1),
2 mm pic '99',
2 filler char (3),
2 v pic 'zz9v.9',
2 filler char (3),
2 date,
3 year pic '9999',
3 filler char (1),
3 mnth pic '99',
3 filler char (1),
3 day pic '99',
2 filler char (3),
2 from,
3 hh pic 'z9',
3 hs char (1),
3 mm pic '99',
2 filler char (3),
2 to like day_line.from,
2 filler char (3),
2 wait like day_line.from,
2 filler char (3),
2 stop like day_line.from,
2 filler char (3),
2 sleep like day_line.from,
2 filler char (3),
2 ams_bms like day_line.from,
2 filler char (3),
2 zone,
3 dir char (1),
3 hh pic '9',
3 hs char (1),
3 mm pic '99',
2 filler char (3),
2 idle like day_line.from;
1/*+-------------------------------------------------------------------+
| Start of executable code for print_day |
+------------------------------------------------------------------*/
write file(outfile) from(day_sep);
write file(outfile) from(day_head);
write file(outfile) from(day_sep);
do day_ptr = trip_list.day_top repeat day_nxt
while(day_ptr ^= sysnull());
/*----------------------------------------------------------------+
| Pre-calculate indices in distance and speed arrays |
+----------------------------------------------------------------*/
select;
when (day_list.km <= 1000.0)
#ld_d = (day_list.km + 99.9) / 100.0;
other
#ld_d = (day_list.km + 249.9) / 250.0 + 6;
end;
#ld_d = min(max(1, #ld_d), hbound(ld.#c, 1));
#sp_d = max(1, (day_list.vx + 9.9999) / 10.0);
#sp_d = min(#sp_d, hbound(sp.#c, 1));
/*----------------------------------------------------------------+
| Keep track of maximum day distance for fast_*_d procedures |
+----------------------------------------------------------------*/
vx_max_d = max(vx_max_d, day_list.vx);
line = day_init;
day_line = day_list, by name;
day_line.hh = day_list.time / 60;
day_line.mm = mod(day_list.time, 60);
day_line.v = round(day_list.vx, 1);
/*----------------------------------------------------------------+
| Departure time |
+----------------------------------------------------------------*/
day_line.from.hh = day_list.d1time / 60;
day_line.from.mm = mod(day_list.d1time, 60);
1 /*----------------------------------------------------------------+
| Arrival time, change 0:00 to 24:00 |
+----------------------------------------------------------------*/
if day_list.a1time = 0 then
do;
day_line.to.hh = 24;
day_line.to.mm = 0;
end;
else
do;
day_line.to.hh = day_list.a1time / 60;
day_line.to.mm = mod(day_list.a1time, 60);
end;
/*----------------------------------------------------------------+
| Waiting time |
+----------------------------------------------------------------*/
if day_list.w1time ^= -1 then
do;
day_line.wait.hh = day_list.w1time / 60;
day_line.wait.mm = mod(day_list.w1time, 60);
end;
else
day_line.wait.hs = ' ';
/*----------------------------------------------------------------+
| Stopping time |
+----------------------------------------------------------------*/
if day_list.i1time ^= 0 then
do;
day_line.stop.hh = day_list.i1time / 60;
day_line.stop.mm = mod(day_list.i1time, 60);
end;
else
day_line.stop.hs = ' ';
/*----------------------------------------------------------------+
| Possible sleeping time during the day |
+----------------------------------------------------------------*/
lift_work.etime = day_list.s1time -
day_list.ams1time -
day_list.bms1time;
if lift_work.etime ^= 0 then
do;
day_line.sleep.hh = lift_work.etime / 60;
day_line.sleep.mm = mod(lift_work.etime, 60);
day_line.sleep.hs = ':';
end;
1 /*----------------------------------------------------------------+
| Possible sleeping time around midnight |
+----------------------------------------------------------------*/
lift_work.etime = day_list.ams1time +
day_list.bms1time;
if lift_work.etime ^= 0 then
do;
day_line.ams_bms.hh = lift_work.etime / 60;
day_line.ams_bms.mm = mod(lift_work.etime, 60);
day_line.ams_bms.hs = ':';
end;
/*----------------------------------------------------------------+
| Possible time-zone corrections |
+----------------------------------------------------------------*/
if day_list.z1time ^= 0 then
do;
day_line.zone.hh = day_list.z1time / 60;
day_line.zone.mm = mod(day_list.z1time, 60);
day_line.zone.hs = ':';
if day_list.z1time > 0 then
day_line.zone.dir = '+';
else
day_line.zone.dir = '-';
end;
/*----------------------------------------------------------------+
| Possible idle-time |
+----------------------------------------------------------------*/
if day_list.n1time ^= 0 then
do;
day_line.idle.hh = day_list.n1time / 60;
day_line.idle.mm = mod(day_list.n1time, 60);
day_line.idle.hs = ':';
end;
write file(outfile) from(line);
end;
write file(outfile) from(day_sep);
write file(outfile) from(iline);
end print_day;
1/**********************************************************************
* PROCESS_DAY_LIST: *
* *
* This procedure accumulates the distance & speed per day and the *
* totals for days of the week and months of the year. *
**********************************************************************/
process_day_list: proc;
dcl #i fixed bin (31);
/*------------------------------------------------------------------+
| Distance processing |
+------------------------------------------------------------------*/
call process_long_distance(day_list.km,
day_list.time,
day_list.#ld_d);
/*------------------------------------------------------------------+
| Speed processing |
+------------------------------------------------------------------*/
call process_speed(day_list.km,
day_list.time,
day_list.#sp_d);
/*------------------------------------------------------------------+
| Accumulate use of this day |
+------------------------------------------------------------------*/
#i = mod(day_list.jdn, 7);
day_list.dow = #i;
days(#i).#c = days(#i).#c + 1;
days(#i).km = days(#i).km + day_list.km;
days(#i).time = days(#i).time + day_list.time;
/*------------------------------------------------------------------+
| Accumulate distance per month |
+------------------------------------------------------------------*/
#i = day_list.mnth;
months.#c(#i) = months.#c(#i) + 1;
months.km(#i) = months.km(#i) + day_list.km;
months.time(#i) = months.time(#i) + day_list.time;
end process_day_list;
1/**********************************************************************
* PROCESS_SHORT_DISTANCE: *
* *
* This procedure is used to split the rides up to and including 100km *
* into four 25km intervals. *
**********************************************************************/
process_short_distance: proc;
/*+-------------------------------------------------------------------+
| Start of executable code for process_short_distance |
+------------------------------------------------------------------*/
sd(#sd).#c = sd(#sd).#c + 1;
sd(#sd).km = sd(#sd).km + lift_list.km;
sd(#sd).time = sd(#sd).time + lift_list.time;
if @summary then
do;
if sd.fila(#sd, 2) ^= sysnull() &
sd.fila(#sd, 1) = sysnull() then
sd.fila(#sd, 1) = sd.fila(#sd, 2);
sd.fila(#sd, 2) = lift_ptr;
end;
end process_short_distance;
1/**********************************************************************
* PROCESS_LONG_DISTANCE: *
* *
* This procedure is used to split the rides and days in a number of *
* distance intervals. *
**********************************************************************/
process_long_distance: proc(km,
time,
#ld);
dcl km fixed (9,1);
dcl time fixed (9);
dcl #ld fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for process_long_distance |
+------------------------------------------------------------------*/
ld(#ld).#c = ld(#ld).#c + 1;
ld(#ld).km = ld(#ld).km + km;
ld(#ld).time = ld(#ld).time + time;
if @summary |
@day then
do;
if ld.fila(#ld, 2) ^= sysnull() &
ld.fila(#ld, 1) = sysnull() then
ld.fila(#ld, 1) = ld.fila(#ld, 2);
if @summary then
ld.fila(#ld, 2) = lift_ptr;
else
ld.fila(#ld, 2) = day_ptr;
end;
end process_long_distance;
1/**********************************************************************
* PRINT_DISTANCE: *
* *
* Print a summary table for the distribution of distances. The table *
* is repeated for *
* *
* - the summary, *
* - each trip, *
* - each type, *
* - each nationality, *
* - each year, *
* - the days summary (with different descriptors) *
* *
* The table contains one row for each distance interval, and each row *
* contains the following columns: *
* *
* - Dist - the upper limit for the distance interval *
* - # - the number of rides in the interval *
* - KM - the total distance for the interval *
* - Time - the total time for the interval *
* - V= - the average speed for the interval *
**********************************************************************/
print_distance: proc;
dcl 1 filler static,
2 filler char (16) init ('SHORT DISTANCE 4'),
2 sdis(4) char (6)
init ('- 25', '- 50', '- 75', '- 100'),
2 filler char (16) init ('LONG DISTANCE 18'),
2 ldis_l(0:17) char (6)
init ('Total ',
'- 100', '- 200', '- 300', '- 400', '- 500',
'- 600', '- 700', '- 800', '- 900', '- 1000',
'1000 +', '2000 +', '3000 +', '4000 +', '5000 +',
'6000 +', '7000 +'),
2 filler char (16) init ('LONG DISTANCE 18'),
2 ldis_d(0:17) char (6)
init ('Total ',
'- 100', '- 200', '- 300', '- 400', '- 500',
'- 600', '- 700', '- 800', '- 900', '- 1000',
'- 1250', '- 1500', '- 1750', '- 2000', '- 2250',
'- 2500', '2500 +');
dcl ldis_ptr ptr init (addr(ldis_l));
dcl ldis(0:17) char (6) based(ldis_ptr);
dcl #i fixed bin (31);
dcl #j fixed bin (31);
dcl #sd fixed bin (31);
dcl #ld fixed bin (31);
1/*+-------------------------------------------------------------------+
| Start of executable code for print_distance |
+------------------------------------------------------------------*/
write file(outfile) from(dtcns_sep);
line = dtcns_head;
substr(line, 4, 4) = heading;
if @day then
do;
ldis_ptr = addr(ldis_d);
substr(line, 15, 2) = '#D';
end;
else
ldis_ptr = addr(ldis_l);
write file(outfile) from(line);
if ^@day then
/*if ld.data(1).#c ^= 0 then
*/ do;
write file(outfile) from(dtcns_sep);
do #sd = 1 to hbound(sdis, 1);
line = dtcns_init;
dtcns_line.head = sdis(#sd);
if sd.data(#sd).#c ^= 0 then
do;
dtcns_line.data = sd.data(#sd), by name;
dtcns_line.data.hh = sd.data(#sd).time / 60;
dtcns_line.data.mm = mod(sd.data(#sd).time, 60);
dtcns_line.data.v = round(
divide(
multiply(sd(#sd).km, 60, 15, 0),
sd(#sd).time, 15, 11), 1);
end;
else
dtcns_line.data.hs = ' ';
write file(outfile) from(line);
if @summary then
call process_fila(addr(sd.fila(#sd, 1)), 1, sdis(#sd));
end;
end;
1 ld(0).#c = sum(ld.#c);
ld(0).km = sum(ld.km);
ld(0).time = sum(ld.time);
do #i = 10 to 1 by -1 while(ld(#i).#c = 0);
end;
do #j = hbound(ld.#c, 1) to 11 by -1 while(ld(#j).#c = 0);
end;
do #ld = 1 to #i, 11 to #j, 0;
if #ld = 0 |
#ld = 1 |
#ld = 11 then
write file(outfile) from(dtcns_sep);
line = dtcns_init;
if ld.data(#ld).#c ^= 0 then
do;
dtcns_line.data = ld.data(#ld), by name;
dtcns_line.data.hh = ld.data(#ld).time / 60;
dtcns_line.data.mm = mod(ld.data(#ld).time, 60);
dtcns_line.data.v = round(
divide(
multiply(ld(#ld).km, 60, 15, 0),
ld(#ld).time, 15, 11), 1);
end;
else
dtcns_line.data.hs = ' ';
dtcns_line.head = ldis(#ld);
write file(outfile) from(line);
if (@summary |
@day) &
#ld ^= 0 then
call process_fila(addr(ld.fila(#ld, 1)), 1, ldis(#ld));
end;
write file(outfile) from(dtcns_sep);
write file(outfile) from(iline);
end print_distance;
1/**********************************************************************
* PROCESS_TYPE: *
* *
* This procedure accumulates the distance and time for each type. *
**********************************************************************/
process_type: proc;
if ^@summary then
type_ptr = lift_list.xty_ptr;
else
if s_ty_ptr -> type_list.type ^= lift_list.type then
do;
do type_ptr = type_top repeat type_nxt
while(type_ptr ^= sysnull())
until(type_list.type = lift_list.type);
end;
s_ty_ptr = type_ptr;
end;
else
type_ptr = s_ty_ptr;
type_list.#c = type_list.#c + 1;
type_list.km = type_list.km + lift_list.km;
type_list.time = type_list.time + lift_list.time;
if @summary then
do;
if type_list.dmax_lift = sysnull() |
lift_list.km > type_list.dmax_lift -> lift_list.km then
do;
type_list.dmax_lift = lift_ptr;
lift_list.ds_type = 'T';
end;
if type_list.vmax_lift = sysnull() |
lift_list.vx > type_list.vmax_lift -> lift_list.vx then
do;
type_list.vmax_lift = lift_ptr;
lift_list.vs_type = 't';
end;
end;
end process_type;
1/**********************************************************************
* PRINT_TYPE: *
* *
* Print a summary table for the types. The table is repeated for *
* *
* - the summary, *
* - each trip and *
* - each nationality *
* *
* The table contains one row for each type and each row contains the *
* following columns: *
* *
* - Type - the type *
* - # - the number of rides for the type *
* - KM - the total distance for the type *
* - Time - the total time for the type *
* - V= - the average speed for the type *
* *
* Note: *
* *
* - this table is omitted for the per-type summaries as it would *
* only contain one entry. In stead the type is inserted as a *
* heading in the distance table. *
**********************************************************************/
1print_type: proc;
dcl save_type_ptr ptr init (type_ptr);
write file(outfile) from(dtcns_sep);
line = dtcns_head;
substr(line, 4, 4) = 'Type';
write file(outfile) from(line);
write file(outfile) from(dtcns_sep);
pickup_t = '';
do type_ptr = type_top repeat type_nxt
while(type_ptr ^= sysnull());
if type_list.#c ^= 0 then
do;
line = dtcns_init;
dtcns_line = type_list, by name;
dtcns_line.head = type_list.type;
dtcns_line.data.hh = type_list.time / 60;
dtcns_line.data.mm = mod(type_list.time, 60);
dtcns_line.data.v = round(
divide(
multiply(type_list.km, 60, 15, 0),
type_list.time, 15, 11), 1);
write file(outfile) from(line);
if @summary then
call process_fila(addr(tl_top), 2, type_list.type);
pickup_t = pickup_t || type_list.type;
if type_list.#tt = 0 then
type_list.#tt = type_list.#c;
type_list.data = idata;
end;
end;
write file(outfile) from(dtcns_sep);
write file(outfile) from(iline);
type_ptr = save_type_ptr;
end print_type;
1/**********************************************************************
* PROCESS_CNTY: *
* *
* This procedure accumulates the distance and time for each country. *
**********************************************************************/
process_cnty: proc;
dcl #c fixed bin (31);
dcl 1 l,
2 km fixed (9,1),
2 time fixed (9),
2 vx fixed (13,9);
/*+-------------------------------------------------------------------+
| Start of executable code for process_cnty |
+------------------------------------------------------------------*/
if @type |
@in_cnty |
@nat then
cnty_ptr = lift_list.xco_ptr;
else
if s_co_ptr = sysnull() |
s_co_ptr -> cnty_list.cnty ^= lift_list.cnty then
do;
do cnty_ptr = cnty_top repeat cnty_nxt
while(cnty_ptr ^= sysnull())
until(cnty_list.cnty = lift_list.cnty);
end;
if cnty_ptr = sysnull() then
do;
alloc cnty_list;
cnty_end -> cnty_nxt,
cnty_end = cnty_ptr;
cnty_list.cnty = lift_list.cnty;
cnty_list.cl_top = lift_ptr;
cnty_list.#p = srch_cnty(cnty_list.cnty);
end;
s_co_ptr = cnty_ptr;
end;
else
cnty_ptr = s_co_ptr;
1 if lift_list.split = '*' then
do;
cnty_list.ext.#c = cnty_list.ext.#c + 1;
cnty_list.ext.km = cnty_list.ext.km + lift_list.km;
cnty_list.ext.time = cnty_list.ext.time + lift_list.time;
cnty_list.#er = cnty_list.#er +
round(
divide(lift_list.km,
owner -> lift_list.km, 15, 10),
8);
end;
else
do;
cnty_list.int.#c = cnty_list.int.#c + 1;
cnty_list.int.km = cnty_list.int.km + lift_list.km;
cnty_list.int.time = cnty_list.int.time + lift_list.time;
cnty_list.#ir = cnty_list.#ir + 1;
end;
if lift_list.split = ' ' |
(lift_list.split = '*' &
substr(lift_list.cday, 3, 1) = 'a') then
do;
cnty_list.pick_up = '1'b;
if lift_list.cnty = lift_list.nat then
cnty_list.#i_nat = cnty_list.#i_nat + 1;
else
cnty_list.#e_nat = cnty_list.#e_nat + 1;
1 /*---------------------------------------------------------------+
| Process borders |
+---------------------------------------------------------------*/
if @summary then
do;
l.km = owner -> lift_list.km;
l.time = owner -> lift_list.time;
l.vx = owner -> lift_list.vx;
#c = owner -> lift_list.#cspl;
/*-----------------------------------------------------------+
| Update global data |
+-----------------------------------------------------------*/
gborders(#c).#c = gborders(#c).#c + 1;
if gborders(#c).p_d = sysnull() then
gborders(#c).p_d = owner;
else
if (l.km > gborders(#c).p_d -> lift_list.km) |
(l.km = gborders(#c).p_d -> lift_list.km) &
(l.vx > gborders(#c).p_d -> lift_list.vx) then
gborders(#c).p_d = owner;
if gborders(#c).p_t = sysnull() then
gborders(#c).p_t = owner;
else
if (l.time > gborders(#c).p_t -> lift_list.time) |
(l.time = gborders(#c).p_t -> lift_list.time) &
(l.km > gborders(#c).p_t -> lift_list.km) then
gborders(#c).p_t = owner;
if gborders(#c).p_v = sysnull() then
gborders(#c).p_v = owner;
else
if (l.vx > gborders(#c).p_v -> lift_list.vx) |
(l.vx = gborders(#c).p_v -> lift_list.vx) &
(l.km > gborders(#c).p_v -> lift_list.km) then
gborders(#c).p_v = owner;
1 /*-----------------------------------------------------------+
| Update per-country data |
+-----------------------------------------------------------*/
cnty_list.borders(#c).#c = cnty_list.borders(#c).#c + 1;
if cnty_list.borders(#c).p_d = sysnull() then
cnty_list.borders(#c).p_d = owner;
else
if (l.km > cnty_list.borders(#c).p_d -> lift_list.km) |
(l.km = cnty_list.borders(#c).p_d -> lift_list.km) &
(l.vx > cnty_list.borders(#c).p_d -> lift_list.vx) then
cnty_list.borders(#c).p_d = owner;
if cnty_list.borders(#c).p_t = sysnull() then
cnty_list.borders(#c).p_t = owner;
else
if (l.time > cnty_list.borders(#c).p_t -> lift_list.time) |
(l.time = cnty_list.borders(#c).p_t -> lift_list.time) &
(l.km > cnty_list.borders(#c).p_t -> lift_list.km) then
cnty_list.borders(#c).p_t = owner;
if cnty_list.borders(#c).p_v = sysnull() then
cnty_list.borders(#c).p_v = owner;
else
if (l.vx > cnty_list.borders(#c).p_v -> lift_list.vx) |
(l.vx = cnty_list.borders(#c).p_v -> lift_list.vx) &
(l.km > cnty_list.borders(#c).p_v -> lift_list.km) then
cnty_list.borders(#c).p_v = owner;
end;
end;
#cll = max(#cll, length(cplates(cnty_list.#p).name));
end process_cnty;
1/**********************************************************************
* PRINT_CNTY: *
* *
* Print a summary table for the countries visited. The table is *
* repeated for *
* *
* - the summary, *
* - each trip, *
* - each type and *
* - each nationality *
* *
* The table contains one row for each country and each row contains *
* the following columns: *
* *
* - Cnty - the abbreviation of the country *
* - KM - the total distance for the country *
* - Time - the total time for the country *
* - V= - the average speed for the country *
* - #N=C - rides with natives *
* - #NxC - rides with foreigners *
* - Country - the full name of the country *
* *
* Note: *
* *
* - the table is printed in alphabetical order except when *
* processing trips. In this case the countries are printed in the *
* order they were passed. *
* *
*?* - use "init ((#cll + 54))" to obtain variable spaced table-widths *
**********************************************************************/
1print_cnty: proc;
dcl 1 filler static,
2 filler char (16) init ('CNTY LINES '),
2 cnty_sep char (121)
init ((' +-----+----------+---------+-------+' ||
'------+------+' ||
'---------------------------------------+')),
2 cnty_init char (121)
init ((' | | | : | |' ||
' - | - |' ||
' |')),
2 cnty_head char (121)
init ((' | | KM | Time | V= |' ||
' #N=C | #NxC |' ||
' Country |'));
dcl 1 cnty_line based(line_ptr),
2 filler char (3),
2 cnty char (4),
2 filler char (2),
2 data,
3 km pic '(5)z9v.9',
3 filler char (3),
3 hh pic 'zzz9',
3 hs char (1),
3 mm pic '99',
3 filler char (3),
3 v pic 'zz9v.9',
3 filler char (3),
2 #i_nat pic '(3)z9',
2 filler char (3),
2 #e_nat pic '(3)z9',
2 filler char (3),
2 name char (38);
dcl 1 cnty_tot,
2 #c fixed bin (31),
2 km fixed (9,1),
2 time fixed (9);
dcl #ci fixed bin (31) init ((#cl + 54)); /*?* #cll */
dcl sep char (121);
1/*+-------------------------------------------------------------------+
| Start of executable code for print_cnty |
+------------------------------------------------------------------*/
sep = substr(cnty_sep, 1, #ci);
substr(sep, #ci, 1) = '+';
line = substr(cnty_head, 1, #ci);
substr(line, #ci, 1) = '|';
write file(outfile) from(sep);
write file(outfile) from(line);
write file(outfile) from(sep);
pickup_c = '';
#cll = 7;
do cnty_ptr = cnty_top repeat cnty_nxt
while(cnty_ptr ^= sysnull());
cnty_tot.#c = cnty_list.int.#c + cnty_list.ext.#c;
if cnty_tot.#c > 0 then
do;
cnty_tot.km = cnty_list.int.km + cnty_list.ext.km;
cnty_tot.time = cnty_list.int.time + cnty_list.ext.time;
line = cnty_init;
cnty_line.cnty = cnty_list.cnty;
cnty_line.data.km = cnty_tot.km;
cnty_line.data.hh = cnty_tot.time / 60;
cnty_line.data.mm = mod(cnty_tot.time, 60);
cnty_line.data.v = round(
divide(
multiply(cnty_tot.km, 60, 15, 0),
cnty_tot.time, 15, 11), 1);
if cnty_list.#i_nat ^= 0 then
cnty_line.#i_nat = cnty_list.#i_nat;
if cnty_list.#e_nat ^= 0 then
cnty_line.#e_nat = cnty_list.#e_nat;
cnty_line.name = cplates(cnty_list.#p).name;
line = substr(line, 1, #ci);
substr(line, #ci, 1) = '|';
write file(outfile) from(line);
if @summary then
call process_fila(addr(cl_top), 3, cnty_list.cnty);
if cnty_list.#cc = 0 then
cnty_list.#cc = cnty_tot.#c;
1 if cnty_list.pick_up then
pickup_c = pickup_c || cnty_list.cnty;
cnty_list.int = idata;
cnty_list.ext = idata;
cnty_list.pick_up = '0'b;
cnty_list.#ir = 0;
cnty_list.#er = 0;
cnty_list.#i_nat = 0;
cnty_list.#e_nat = 0;
end;
end;
write file(outfile) from(sep);
write file(outfile) from(iline);
end print_cnty;
1/**********************************************************************
* PROCESS_NATIONALITY: *
* *
* This procedure accumulates the distance and time for each *
* nationality. *
**********************************************************************/
process_nationality: proc;
if ^@summary then
nat_ptr = lift_list.xna_ptr;
else
if s_na_ptr -> nat_list.nat ^= lift_list.nat then
do;
if lift_list.nat >= nat_mid then
nat_ptr = nat_mptr;
else
nat_ptr = nat_top;
do nat_ptr = nat_ptr repeat nat_nxt
while(nat_ptr ^= sysnull())
until(nat_list.nat = lift_list.nat);
end;
s_na_ptr = nat_ptr;
end;
else
nat_ptr = s_na_ptr;
nat_list.#c = nat_list.#c + 1;
nat_list.km = nat_list.km + lift_list.km;
nat_list.time = nat_list.time + lift_list.time;
#nll = max(#nll, length(cplates(nat_list.#p).name));
if @summary then
do;
if nat_list.dmax_lift = sysnull() |
lift_list.km > nat_list.dmax_lift -> lift_list.km then
do;
nat_list.dmax_lift = lift_ptr;
lift_list.ds_nat = 'N';
end;
if nat_list.vmax_lift = sysnull() |
lift_list.vx > nat_list.vmax_lift -> lift_list.vx then
do;
nat_list.vmax_lift = lift_ptr;
lift_list.vs_nat = 'n';
end;
end;
end process_nationality;
1/**********************************************************************
* PRINT_NATIONALITY: *
* *
* Print a summary table for the nationalities. The table is repeated *
* for *
* *
* - the summary, *
* - each trip and *
* - each type and *
* - each year *
* *
* The table contains one row for each nationality and each row *
* contains the following columns: *
* *
* - Nat - the nationality *
* - # - the number of rides for the nationality *
* - KM - the total distance for the nationality *
* - Time - the total time for the nationality *
* - V= - the average speed for the nationality *
* *
* Notes: *
* *
* - this table is omitted for the per-nationality summaries as it *
* would only contain one entry. In stead the nationality is *
* inserted as a heading in the distance table. *
* *
* - when processing a trip, the nationalities are printed in the *
* order of the countries passed, followed by the remaining *
* nationalities in alphabetical order. *
* *
*?* - use "init ((#nll + 50))" to obtain variable spaced table-widths *
**********************************************************************/
print_nationality: proc;
dcl 1 filler static,
2 filler char (16) init ('NAT LINES '),
2 nat_sep char (121)
init ((' +--------+------+----------+---------+-------+' ||
'---------------------------------------+')),
2 nat_init char (121)
init ((' | | | | : | |' ||
' |')),
2 nat_initx char (121)
init ((' | - | - | - | - | - |' ||
' - |')),
2 nat_head char (121)
init ((' | Nat | # | KM | Time | V= |' ||
' Country |'));
1dcl 1 nat_line based(line_ptr),
2 filler char (3),
2 head char (6),
2 filler char (3),
2 data,
3 #c pic 'zzz9',
3 filler char (3),
3 km pic '(5)z9v.9',
3 filler char (3),
3 hh pic 'zzz9',
3 hs char (1),
3 mm pic '99',
3 filler char (3),
3 v pic 'zz9v.9',
3 filler char (3),
2 name char (38);
dcl @first bit (1) init ('0'b) aligned;
dcl @none bit (1) aligned;
dcl sline char (121);
dcl sep char (121);
dcl save_nat_ptr ptr init (nat_ptr);
dcl #ni fixed bin (31) init ((#nl + 50));
/*+-------------------------------------------------------------------+
| Start of executable code for print_nationality |
+------------------------------------------------------------------*/
sep = substr(nat_sep, 1, #ni);
substr(sep, #ni, 1) = '+';
line = substr(nat_head, 1, #ni);
substr(line, #ni, 1) = '|';
write file(outfile) from(sep);
write file(outfile) from(line);
write file(outfile) from(sep);
pickup_n = '';
#nll = 7;
1 /*------------------------------------------------------------------+
| First print any nationalities in the order of their countries |
+------------------------------------------------------------------*/
if ^@type then
do;
@first = '1'b;
@none = '1'b;
do cnty_ptr = cnty_top repeat cnty_nxt
while(cnty_ptr ^= sysnull());
if cn_ptr ^= sysnull() then
do;
nat_ptr = cn_ptr;
cn_ptr = sysnull();
if nat_list.#c > 0 then
do;
@none = '0'b;
call print_nat();
end;
end;
end;
#pu_sep = length(pickup_n) / 4;
if @none then
do;
line = substr(nat_initx, 1, #ni);
substr(line, #ni, 1) = '|';
write file(outfile) from(line);
end;
end;
1 /*------------------------------------------------------------------+
| First (or remaining) nationalities in alphabetic order |
+------------------------------------------------------------------*/
do nat_ptr = nat_top repeat nat_nxt
while(nat_ptr ^= sysnull());
if nat_list.#c > 0 then
do;
if @first then
do;
@first = '0'b;
sline = translate(sep, $ds, '-');
write file(outfile) from(sline);
end;
call print_nat();
end;
end;
write file(outfile) from(sep);
write file(outfile) from(iline);
nat_ptr = save_nat_ptr;
1/**********************************************************************
* PRINT_NAT: *
* *
* This procedure writes out a nationality line *
**********************************************************************/
print_nat: proc;
line = nat_init;
nat_line.head = nat_list.nat;
nat_line.#c = nat_list.#c;
nat_line.km = nat_list.km;
nat_line.data.hh = nat_list.time / 60;
nat_line.data.mm = mod(nat_list.time, 60);
nat_line.data.v = round(
divide(
multiply(nat_list.km, 60, 15, 0),
nat_list.time, 15, 11), 1);
nat_line.name = cplates(nat_list.#p).name;
line = substr(line, 1, #ni);
substr(line, #ni, 1) = '|';
write file(outfile) from(line);
if @summary then
call process_fila(addr(nl_top), 4, nat_list.nat);
if nat_list.#nn = 0 then
nat_list.#nn = nat_list.#c;
nat_list.data = idata;
pickup_n = pickup_n || nat_list.nat;
end print_nat;
end print_nationality;
1/**********************************************************************
* PROCESS_SPEED: *
* *
* This procedure is used to split the velocity of the rides in 10km *
* intervals, accumulating the number of rides, distance and time per *
* interval. *
**********************************************************************/
process_speed: proc(km,
time,
#sp);
dcl km fixed (9,1);
dcl time fixed (9);
dcl #sp fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for process_speed |
+------------------------------------------------------------------*/
sp(#sp).#c = sp(#sp).#c + 1;
sp(#sp).km = sp(#sp).km + km;
sp(#sp).time = sp(#sp).time + time;
if @summary |
@day then
do;
if sp.fila(#sp, 2) ^= sysnull() &
sp.fila(#sp, 1) = sysnull() then
sp.fila(#sp, 1) = sp.fila(#sp, 2);
if @summary then
sp.fila(#sp, 2) = lift_ptr;
else
sp.fila(#sp, 2) = day_ptr;
end;
end process_speed;
1/**********************************************************************
* PRINT_SPEED: *
* *
* Print a summary table for the distribution of velocities. The table *
* is repeated for *
* *
* - the summary, *
* - each trip, *
* - each type and *
* - each nationality *
* *
* The table contains one row for each velocity interval, and each row *
* contains the following columns: *
* *
* - Vel - the upper limit for the velocity interval *
* - # - the number of rides in the interval *
* - KM - the total distance for the interval *
* - Time - the total time for the interval *
* - V= - the average speed for the interval *
**********************************************************************/
print_speed: proc;
dcl 1 filler static,
2 filler char (16) init ('SPEED 21 '),
2 spdis(21) char (6)
init ('- 10', '- 20', '- 30', '- 40', '- 50',
'- 60', '- 70', '- 80', '- 90', '- 100',
'- 110', '- 120', '- 130', '- 140', '- 150',
'- 160', '- 170', '- 180', '- 190', '- 200',
'200 + ');
dcl #i fixed bin (31);
dcl #sp fixed bin (31);
1/*+-------------------------------------------------------------------+
| Start of executable code for print_speed |
+------------------------------------------------------------------*/
do #i = hbound(spdis, 1) to 1 by -1 while(sp(#i).#c = 0);
end;
write file(outfile) from(dtcns_sep);
line = dtcns_head;
substr(line, 4, 5) = 'Speed';
if @day then
substr(line, 15, 2) = '#D';
else
if @tsum then
substr(line, 15, 2) = '#T';
write file(outfile) from(line);
write file(outfile) from(dtcns_sep);
do #sp = 1 to #i;
line = dtcns_init;
dtcns_line.head = spdis(#sp);
if sp.data(#sp).#c ^= 0 then
do;
dtcns_line.data = sp.data(#sp), by name;
dtcns_line.data.hh = sp.data(#sp).time / 60;
dtcns_line.data.mm = mod(sp.data(#sp).time, 60);
dtcns_line.data.v = round(
divide(
multiply(sp(#sp).km, 60, 15, 0),
sp(#sp).time, 15, 11), 1);
end;
else
dtcns_line.data.hs = ' ';
write file(outfile) from(line);
if @summary |
@day then
call process_fila(addr(sp.fila(#sp, 1)), 5, spdis(#sp));
end;
write file(outfile) from(dtcns_sep);
write file(outfile) from(iline);
end print_speed;
1/**********************************************************************
* PROCESS_FILA: *
* *
* This procedure stores the first and last occurance of a distance, *
* type, country, nationality or velocity in a list. *
**********************************************************************/
process_fila: proc(filaptr, #id, desc);
dcl filaptr ptr;
dcl fila_ptr(2) ptr based(filaptr);
dcl #id fixed bin (31);
dcl desc char (*);
dcl 1 fila_line based(line_ptr),
2 filler char (3),
2 head char (6),
2 fila(2),
3 filler char (3),
3 trip pic 'zzz9',
3 filler char (3),
3 ride pic 'zzz9',
3 filler char (3),
3 date,
4 year pic '9999',
4 filler char (1),
4 mnth pic '99',
4 filler char (1),
4 day pic '99';
dcl #i fixed bin (31);
dcl z9 pic 'z9';
dcl day fixed (3);
dcl save_lift_ptr ptr init (lift_ptr);
dcl save_day_ptr ptr init (day_ptr);
1/*+-------------------------------------------------------------------+
| Start of executable code for process_fila |
+------------------------------------------------------------------*/
line = fila_init;
fila_line.head = desc;
if @summary then
do #i = 1 to hbound(fila_ptr, 1);
if fila_ptr(#i) ^= sysnull() then
do;
lift_ptr = fila_ptr(#i);
fila_line.trip(#i) = lift_list.trip;
fila_line.ride(#i) = lift_list.ride;
day = lift_list.day;
if lift_list.jdn = -1 then
if lift_list.cday = ' #' then
do;
lift_ptr = lift_nxt;
day = lift_list.day;
end;
else
if index('abcdefghij',
substr(lift_list.cday, 3, 1)) ^= 0 then
do;
string(z9) = substr(lift_list.cday, 1, 2);
day = z9;
end;
do lift_ptr = lift_ptr repeat lift_prv
until(lift_list.jdn ^= -1 &
lift_list.day = day);
end;
fila_line.date(#i) = lift_list.date, by name;
end;
end;
lift_ptr = save_lift_ptr;
1 if @day then
do #i = 1 to hbound(fila_ptr, 1);
if fila_ptr(#i) ^= sysnull() then
do;
day_ptr = fila_ptr(#i);
fila_line.fila(#i) = day_list, by name;
fila_line.ride(#i) = day_list.day;
end;
end;
day_ptr = save_day_ptr;
if fila_line.trip(1) = fila_line.trip(2) &
fila_line.ride(1) = fila_line.ride(2) then
do;
fila_line.date(2) = fila_line.date(1);
string(fila_line.trip(1)) = (4)' ';
string(fila_line.ride(1)) = (4)' ';
string(fila_line.date(1)) = (10)' ';
end;
if string(fila_line.trip(1)) = (4)' ' then
string(fila_line.date(1)) = (10)' ';
if string(fila_line.trip(2)) = (4)' ' then
string(fila_line.date(2)) = (10)' ';
alloc fast_list;
fast_end -> fast_nxt,
fast_end = fast_ptr;
fast_list.ftype = #id;
end process_fila;
1/**********************************************************************
* PRINT_FILA: *
* *
* This procedure prints the first and last occurance of a distance, *
* type, country, nationality or velocity. *
**********************************************************************/
print_fila: proc;
dcl 1 filler static,
2 filler char (16) init ('FILA DESC '),
2 fila_desc(5) char (5)
init (' ', 'Type ', 'Cnty ', 'Nat ', 'Speed');
dcl #i fixed bin (31);
dcl #j fixed bin (31);
dcl #l fixed bin (31);
dcl @first bit (1) init ('1'b) aligned;
/*+-------------------------------------------------------------------+
| Start of executable code for print_fila |
+------------------------------------------------------------------*/
do #i = 1 to hbound(fila_desc, 1);
#l = 0;
do fast_ptr = fast_top repeat fast_nxt
while(fast_ptr ^= sysnull());
if fast_list.ftype = #i then
do;
if #l = 0 then
do;
write file(outfile) from(pline);
do #j = 1 to 3;
write file(outfile) from(fila_head(#j));
end;
line = fila_head(4);
substr(line, 4, 5) = fila_desc(#i);
if @day then
substr(line, 20, 4),
substr(line, 47, 4) = 'Day ';
write file(outfile) from(line);
end;
1 if #l = 0 |
#i = 1 &
((@summary &
(#l = hbound(sd.#c, 1) |
@first & substr(fast_list.fline, 9, 1) = '+')) |
(@day & substr(fast_list.fline, 6, 4) = '1250')) |
(#i = 4 &
#l = #pu_sep) then
do;
if substr(fast_list.fline, 9, 1) = '+' then
@first = '0'b;
line = fila_sep;
if #i = 4 &
#l = #pu_sep then
line = translate(line, $ds, '-');
write file(outfile) from(line);
end;
write file(outfile) from(fast_list.fline);
#l = #l + 1;
end;
end;
if #l ^= 0 then
write file(outfile) from(fila_sep);
end;
call free_fast_list();
end print_fila;
1/**********************************************************************
* PROCESS_MINI_WAIT: *
* *
* This procedure accumulates the waiting times for various lists. It *
* is used for those cases where a full interval table is not needed, *
* i.e. for the waits per *
* *
* - summary/country *
* - summary/hour - done *
* - summary/weekday - done *
* - summary/month - done *
* - summary/year - done *
* - trip/country *
* - year/country *
* *
* Note that all arrays are over-dimensioned to use power-of-two *
* dimensions. *
**********************************************************************/
process_mini_wait: proc(mode);
dcl mode char (4);
dcl #i fixed bin (31);
dcl #j fixed bin (31);
dcl #h fixed bin (31);
dcl #d fixed bin (31);
dcl #m fixed bin (31);
dcl #w fixed bin (31);
dcl #y fixed bin (31);
dcl #yl fixed bin (31) init ((ll_top -> lift_list.year));
dcl #yh fixed bin (31) init ((ll_end -> lift_list.year));
dcl hour pic '-z99';
dcl year pic '9999';
dcl wtime fixed bin (31);
dcl 1 h(1:32) ctl,
2 w(0:3),
3 #w fixed bin (31) init ((128)0),
3 wtime fixed bin (31) init ((128)0);
dcl 1 d(0:7) ctl,
2 w(0:3),
3 #w fixed bin (31) init ((32)0),
3 wtime fixed bin (31) init ((32)0);
dcl 1 m(16) ctl,
2 w(0:3),
3 #w fixed bin (31) init ((64)0),
3 wtime fixed bin (31) init ((64)0);
dcl 1 y(1980:2043) ctl,
2 w(0:3),
3 #w fixed bin (31) init ((256)0),
3 wtime fixed bin (31) init ((256)0);
1/*+-------------------------------------------------------------------+
| Start of executable code for process_mini_wait |
+------------------------------------------------------------------*/
select(mode);
when ('CPER')
do;
/*------------------------------------------------------------+
| Allocate the collection bins |
+------------------------------------------------------------*/
if allocn(h) = 0 then
alloc h;
if allocn(d) = 0 then
alloc d;
if allocn(m) = 0 then
alloc m;
if allocn(y) = 0 then
alloc y;
/*------------------------------------------------------------+
| Collect all waiting times per hour, weekday, month and year |
+------------------------------------------------------------*/
do lift_ptr = wift_top repeat wift_nxt
while(lift_ptr ^= sysnull());
#w = 1 + (lift_list.wtime > 60);
/*----------------------------------------------------------+
| These are waiting times before departure |
+----------------------------------------------------------*/
#h = trunc((owner -> lift_list.dtime + 59) / 60);
#h = max(1, #h);
#d = lift_list.dow;
#m = lift_list.mnth;
#y = lift_list.year;
if lift_list.wtime ^= -1 then
do;
wtime = lift_list.wtime;
/*---------- -------------------------------------------+
| Waits per hour |
+------------------------------------------------------*/
h(#h).w(#w).#w = h(#h).w(#w).#w + 1;
h(#h).w(#w).wtime = h(#h).w(#w).wtime + wtime;
/*------------------------------------------------------+
| Waits per weekday |
+------------------------------------------------------*/
d(#d).w(#w).#w = d(#d).w(#w).#w + 1;
d(#d).w(#w).wtime = d(#d).w(#w).wtime + wtime;
1 /*------------------------------------------------------+
| Waits per month |
+------------------------------------------------------*/
m(#m).w(#w).#w = m(#m).w(#w).#w + 1;
m(#m).w(#w).wtime = m(#m).w(#w).wtime + wtime;
/*------------------------------------------------------+
| Waits per year |
+------------------------------------------------------*/
y(#y).w(#w).#w = y(#y).w(#w).#w + 1;
y(#y).w(#w).wtime = y(#y).w(#w).wtime + wtime;
end;
else
do;
h(#h).w(0).#w = h(#h).w(0).#w + 1;
d(#d).w(0).#w = d(#d).w(0).#w + 1;
m(#m).w(0).#w = m(#m).w(0).#w + 1;
y(#y).w(0).#w = y(#y).w(0).#w + 1;
end;
end;
do #h = lbound(h.w.#w, 1) to hbound(h.w.#w, 1);
h(#h).w(3) = h(#h).w(1) + h(#h).w(2);
end;
do #d = lbound(d.w.#w, 1) to hbound(d.w.#w, 1);
d(#d).w(3) = d(#d).w(1) + d(#d).w(2);
end;
do #m = lbound(m.w.#w, 1) to hbound(m.w.#w, 1);
m(#m).w(3) = m(#m).w(1) + m(#m).w(2);
end;
do #y = #yl to #yh;
y(#y).w(3) = y(#y).w(1) + y(#y).w(2);
end;
wift_ptr = wift_top;
end;
1 when ('PH ')
do;
/*------------------------------------------------------------+
| Print the hourly waiting times table |
+------------------------------------------------------------*/
call print_wait_summary_box('Hour');
do #i = 1 to 24;
line = swait_init;
hour = -#i;
swait_line.head = hour;
if h(#i).w(0).#w ^= 0 then
swait_line.none = h(#i).w(0).#w;
do #j = 1 to hbound(h.w.#w, 2);
call create_swait_line(#j,
h(#i).w(#j));
end;
write file(outfile) from(line);
end;
call print_wait_summary_box('B ');
end;
when ('PD ')
do;
/*------------------------------------------------------------+
| Print the daily waiting times table |
+------------------------------------------------------------*/
call print_wait_summary_box('Day ');
do #i = lbound(lift_static.day, 1) to
hbound(lift_static.day, 1);
line = swait_init;
swait_line.head = lift_static.day(#i);
if d(#i).w(0).#w ^= 0 then
swait_line.none = d(#i).w(0).#w;
do #j = 1 to hbound(d.w.#w, 2);
call create_swait_line(#j,
d(#i).w(#j));
end;
write file(outfile) from(line);
end;
call print_wait_summary_box('B ');
end;
1 when ('PM ')
do;
/*------------------------------------------------------------+
| Print the monthly waiting times table |
+------------------------------------------------------------*/
call print_wait_summary_box('Mnth');
do #i = lbound(lift_static.month, 1) to
hbound(lift_static.month, 1);
line = swait_init;
swait_line.head = lift_static.month(#i);
if m(#i).w(0).#w ^= 0 then
swait_line.none = m(#i).w(0).#w;
do #j = 1 to hbound(m.w.#w, 2);
call create_swait_line(#j,
m(#i).w(#j));
end;
write file(outfile) from(line);
end;
call print_wait_summary_box('B ');
end;
1 when ('PY ')
do;
/*------------------------------------------------------------+
| Print the yearly waiting times table |
+------------------------------------------------------------*/
call print_wait_summary_box('Year');
do #i = #yl to #yh;
if y(#i).w(0).#w ^= 0 |
y(#i).w(3).#w ^= 0 then
do;
line = swait_init;
year = #i;
swait_line.head = year;
if y(#i).w(0).#w ^= 0 then
swait_line.none = y(#i).w(0).#w;
do #j = 1 to hbound(y.w.#w, 2);
call create_swait_line(#j,
y(#i).w(#j));
end;
write file(outfile) from(line);
end;
end;
call print_wait_summary_box('B ');
end;
other;
end;
end process_mini_wait;
1/**********************************************************************
* PROCESS_WAIT: *
* *
* This procedure accumulates the waiting times for each ride. *
**********************************************************************/
process_wait: proc;
dcl wtime fixed bin (31) init (lift_list.wtime);
dcl #wa fixed bin (31) init (lift_list.#wa);
dcl #wx fixed bin (31) init (lift_list.#wx);
/*+-------------------------------------------------------------------+
| Start of executable code for process_wait |
+------------------------------------------------------------------*/
wwait(-2).#w = wwait(-2).#w + 1;
wwait(#wa).#w = wwait(#wa).#w + 1;
if wtime ^= -1 then
do;
wwait(-2).wtime = wwait(-2).wtime + wtime;
wwait(#wa).wtime = wwait(#wa).wtime + wtime;
waits(#wx).#w = waits(#wx).#w + 1;
waits(#wx).wtime = waits(#wx).wtime + wtime;
waits(8).#w = waits(8).#w + 1;
waits(8).wtime = waits(8).wtime + wtime;
w8wtimesq = w8wtimesq + wtime * wtime;
end;
else
waits(1) = wwait(-1);
end process_wait;
1/**********************************************************************
* PRINT_WAIT: *
* *
* Print a summary table for the distribution of waiting times. *
* *
* The table contains one row for each wait interval, and each row *
* contains the following columns: *
* *
* - Wait - the upper limit for the wait interval *
* - # - the number of waits in the interval *
* - Time - the total time for the interval *
* - #C - the total number of waits up to this interval *
* - Time - the total time up to this interval *
**********************************************************************/
print_wait: proc;
dcl 1 filler static,
2 filler char (16) init ('WAIT LINES '),
2 wait_sep char (121)
init ((' +---------+------+---------+------+---------+')),
2 wait_init char (121)
init ((' | - : | | : | | |')),
2 wait_head char (121)
init ((' | Wait | # | Time | #C | CTime |'));
dcl 1 wait_line based(line_ptr),
2 filler char (3),
2 w_time,
3 filler char (2),
3 hh pic 'z9',
3 hs char (1),
3 mm pic '99',
2 filler char (3),
2 wait,
3 #w pic 'zzz9',
3 filler char (3),
3 whh pic 'zzz9',
3 hs char (1),
3 wmm pic '99',
2 filler char (3),
2 cwait,
3 #w pic 'zzz9',
3 filler char (3),
3 whh pic 'zzz9',
3 hs char (1),
3 wmm pic '99';
dcl #i fixed bin (31);
dcl #wa fixed bin (31);
dcl @first bit (1) init ('1'b) aligned;
dcl 1 cwait,
2 #w fixed bin (31) init (0),
2 wtime fixed bin (31) init (0);
1/*+-------------------------------------------------------------------+
| Start of executable code for print_wait |
+------------------------------------------------------------------*/
write file(outfile) from(pline);
write file(outfile) from(wait_sep);
line = wait_head;
if @cnty then
substr(line, 5, 7) = ' - ' || heading;
write file(outfile) from(line);
write file(outfile) from(wait_sep);
do #i = hbound(wwait.#w, 1) to 0 by -1 while(wwait(#i).#w = 0);
end;
if #i = -1 &
wwait(#i).#w = 0 then
#i = -2;
do #wa = -1 to #i, -2;
line = wait_init;
select(#wa);
when (-2)
do;
string(wait_line.w_time) = 'Total';
wait_line.wait.#w = wwait(#wa).#w;
if wwait(#wa).wtime ^= 0 then
do;
wait_line.wait.whh = wwait(#wa).wtime / 60;
wait_line.wait.wmm = mod(wwait(#wa).wtime, 60);
end;
else
wait_line.wait.hs = ' ';
wait_line.cwait.#w = cwait.#w;
if cwait.wtime ^= 0 then
do;
wait_line.cwait.whh = cwait.wtime / 60;
wait_line.cwait.wmm = mod(cwait.wtime, 60);
wait_line.cwait.hs = ':';
end;
end;
when (-1)
do;
string(wait_line.w_time) = 'First';
wait_line.wait.#w = wwait(#wa).#w;
wait_line.wait.hs = ' ';
end;
1 other
do;
if #wa = hbound(wwait.#w, 1) then
string(wait_line.w_time) = '12:00 +';
else
do;
wait_line.w_time.hh = wa_time(#wa) / 60;
wait_line.w_time.mm = mod(wa_time(#wa), 60);
end;
if wwait(#wa).#w ^= 0 then
do;
wait_line.wait.#w = wwait(#wa).#w;
if wwait(#wa).wtime ^= 0 then
do;
wait_line.wait.whh = wwait(#wa).wtime / 60;
wait_line.wait.wmm = mod(wwait(#wa).wtime, 60);
end;
else
wait_line.wait.hs = ' ';
cwait = cwait + wwait(#wa);
if ^@first &
#wa > 1 then
do;
wait_line.cwait.#w = cwait.#w;
wait_line.cwait.whh = cwait.wtime / 60;
wait_line.cwait.wmm = mod(cwait.wtime, 60);
wait_line.cwait.hs = ':';
end;
if #wa > 0 then
@first = '0'b;
end;
else
wait_line.wait.hs = ' ';
end;
end;
write file(outfile) from(line);
1 if #wa <= 0 | /* wa_time(#wa) <= 0 */
#wa = 12 | /* wa_time(#wa) = 60 */
#wa = 20 | /* wa_time(#wa) = 180 */
#wa = 26 | /* wa_time(#wa) = 360 */
#wa = 32 | /* wa_time(#wa) = 720 */
#wa >= #i then
write file(outfile) from(wait_sep);
end;
write file(outfile) from(iline);
end print_wait;
1/**********************************************************************
* PRINT_WAIT_SUMMARY_BOX: *
* *
* Print top or bottom of a summary wait box. *
**********************************************************************/
print_wait_summary_box: proc(head);
dcl head char (4);
dcl sline char (121);
dcl #i fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for print_wait_summary_box |
+------------------------------------------------------------------*/
if head ^= 'B ' then
do;
write file(outfile) from(iline);
do #i = 1 to 3;
write file(outfile) from(swait_head(#i));
end;
sline = swait_head(4);
substr(sline, 4, 4) = head;
write file(outfile) from(sline);
end;
write file(outfile) from(swait_sep);
end print_wait_summary_box;
1/**********************************************************************
* PRINT_WAIT_SUMMARY: *
* *
* Print the list of assembled summary wait lines. The procedure is *
* invoked recursively for trips, in order to print the accumulated *
* waiting times. *
**********************************************************************/
print_wait_summary: proc(@recursive) recursive;
dcl @recursive bit (1) aligned;
dcl #i fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for print_wait_summary |
+------------------------------------------------------------------*/
select;
when (@cnty) call print_wait_summary_box('Cnty');
when (@trip) call print_wait_summary_box('Trip');
end;
#i = 2 + @recursive;
do fast_ptr = fast_top repeat fast_nxt
while(fast_ptr ^= sysnull());
if fast_list.ftype = #i then
write file(outfile) from(fast_list.fline);
end;
call print_wait_summary_box('B ');
1 if (^@recursive & @trip) |
(@nested & @year) then
do;
line = swait_init;
swait_line.head = 'Tot';
if swaits(0).#w ^= 0 then
swait_line.none = swaits(0).#w;
do #i = 1 to 3;
call create_swait_line(#i,
swaits(#i));
end;
write file(outfile) from(line);
call print_wait_summary_box('B ');
if @trip &
^@nested then
call print_wait_summary('1'b);
end;
call free_fast_list();
end print_wait_summary;
1/**********************************************************************
* CREATE_WAIT_SUMMARY: *
* *
* Print a summary table for the distribution of waiting times per *
* trip, per country and per year. *
* *
* The table contains one row for each country, and each row contains *
* *
* - T/C - the trip, country or year, *
* - a group of columns, containing *
* - # - the number of waits *
* - Time - the total time for the interval *
* - W= - the average waiting time for the group *
* *
* The group is repeated three times for *
* - waits up to 1 hour *
* - waits longer than 1 hour *
* - the total waiting time for the trip/country/year *
**********************************************************************/
1create_wait_summary: proc(head);
dcl head char (4);
dcl #i fixed bin (31);
dcl 1 cwait,
2 #w fixed bin (31),
2 wtime fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for create_wait_summary |
+------------------------------------------------------------------*/
line = swait_init;
swait_line.head = head;
cwait = waits(2) +
waits(3);
swaits(1) = swaits(1) + cwait;
call create_swait_line(1,
cwait);
cwait = waits(4) +
waits(5) +
waits(6) +
waits(7);
swaits(2) = swaits(2) + cwait;
call create_swait_line(2,
cwait);
cwait = waits(8);
swaits(3) = swaits(3) + cwait;
call create_swait_line(3,
cwait);
swaits(0) = swaits(0) + waits(1);
if waits(1).#w ^= 0 then
swait_line.none = waits(1).#w;
alloc fast_list;
fast_end -> fast_nxt,
fast_end = fast_ptr;
fast_list.ftype = 2;
1 if @trip then
do;
do #i = 1 to 3;
call create_swait_line(#i,
swaits(#i));
end;
if swaits(0).#w ^= 0 then
swait_line.none = swaits(0).#w;
alloc fast_list;
fast_end -> fast_nxt,
fast_end = fast_ptr;
fast_list.ftype = 3;
end;
end create_wait_summary;
1/**********************************************************************
* CREATE_SWAIT_LINE: *
* *
* Fill in the details of an SWAIT_LINE *
**********************************************************************/
create_swait_line: proc(#p,
wait);
dcl #p fixed bin (31);
dcl 1 wait,
2 #w fixed bin (31),
2 wtime fixed bin (31);
if wait.#w ^= 0 then
do;
swait_line.wait(#p).#w = wait.#w;
swait_line.wait(#p).whh = wait.wtime / 60;
swait_line.wait(#p).wmm = mod(wait.wtime, 60);
swait_line.wait(#p).hs = ':';
call average_time((wait.wtime * 60), (wait.#w));
swait_line.wait(#p).w_avg = wt_avg;
end;
else
swait_line.wait(#p).hs = ' ';
end create_swait_line;
1/**********************************************************************
* PRINT_WAITSD: *
* *
* This procedure prints a statistical analysis of the waiting times *
**********************************************************************/
print_waitsd: proc;
dcl 1 filler static,
2 filler char (16) init ('WAIT INTERVALS '),
2 sd_desc(0:4) char (5)
init ('- W= ', '- 1SD', '- 2SD', '- 3SD', '3SD +'),
/* 50.0% 68.2% 95.5% 99.7% 0.3% */
2 filler char (16) init ('WAITSD LINES '),
2 waitsd_sep char (121)
init ((' +-------+------+---------+----------+--------+' ||
'------+---------+----------+')),
2 waitsd_init char (121)
init ((' | | | : | | |' ||
' | : | |')),
2 waitsd_head char (121)
init ((' | Wait | # | Time | W= | % |' ||
' #C | CTime | W= |'));
1dcl 1 waitsd_line based(line_ptr),
2 filler char (3),
2 head char (5),
2 filler char (3),
2 wait,
3 #w pic 'zzz9',
3 filler char (3),
3 wtime,
4 whh pic 'zzz9',
4 hs char (1),
4 wmm pic '99',
3 filler char (3),
3 w_avg,
4 whh_avg pic 'z9',
4 col1 char (1),
4 wmm_avg pic '99',
4 col2 char (1),
4 wss_avg pic '99',
3 filler char (3),
2 perc pic 'zz9v.99',
2 filler char (3),
2 cwait,
3 #w pic 'zzz9',
3 filler char (3),
3 wtime,
4 whh pic 'zzz9',
4 hs char (1),
4 wmm pic '99',
3 filler char (3),
3 w_avg,
4 whh_avg pic 'z9',
4 col1 char (1),
4 wmm_avg pic '99',
4 col2 char (1),
4 wss_avg pic '99';
dcl #i fixed bin (31);
dcl #wid fixed bin (31);
dcl @data bit (1);
dcl flw float (16) init (waits(8).#w);
dcl flwtime float (16) init (waits(8).wtime);
dcl flwtimesq float (16) init (w8wtimesq);
1dcl wavg fixed (5);
dcl sdev fixed (5);
dcl avg_sd fixed (5);
dcl 1 sdwait(0:1),
2 #w fixed bin (31),
2 wtime fixed bin (31);
dcl sline char (121);
/*+-------------------------------------------------------------------+
| Start of executable code for print_waitsd |
+------------------------------------------------------------------*/
write file(outfile) from(waitsd_sep);
write file(outfile) from(waitsd_head);
line = waitsd_init;
waitsd_line.head = 'Total';
waitsd_line.wait.#w = waits(8).#w;
waitsd_line.wait.whh = waits(8).wtime / 60;
waitsd_line.wait.wmm = mod(waits(8).wtime, 60);
call average_time((waits(8).wtime * 60), (waits(8).#w));
waitsd_line.wait.w_avg = wt_avg;
wavg = w_hh * 3600 + w_mm * 60 + w_ss;
if flw > 1 then
call average_time(sqrt((flw * flwtimesq - flwtime ** 2) /
(flw * (flw - 1))) * 60, 1);
else
do;
w_hh = 0;
w_mm = 0;
w_ss = 0;
end;
string(waitsd_line.cwait.wtime) = 'SDev';
waitsd_line.cwait.w_avg = wt_avg;
sdev = w_hh * 3600 + w_mm * 60 + w_ss;
sline = line;
lift_ptr = wift_ptr;
1 select;
when (@trip)
do;
t_wavg = wavg;
t_sdev = sdev;
if lift_ptr = sysnull() |
lift_list.trip ^= #save_trip then
do lift_ptr = wift_top repeat wift_skip
while(lift_ptr ^= sysnull())
until(lift_list.trip = #save_trip);
end;
end;
when (@cnty)
if lift_ptr = sysnull() |
lift_list.cnty ^= cnty_list.cnty then
do lift_ptr = wift_top repeat wift_skip
while(lift_ptr ^= sysnull())
until(lift_list.cnty = cnty_list.cnty);
end;
when (@year)
do;
y_wavg = wavg;
y_sdev = sdev;
if lift_ptr = sysnull() |
lift_list.year ^= #save_year then
do lift_ptr = wift_top repeat wift_skip
while(lift_ptr ^= sysnull())
until(lift_list.year = #save_year);
end;
end;
when (@summary)
do;
s_wavg = wavg;
s_sdev = sdev;
lift_ptr = wift_top;
end;
end;
/*------------------------------------------------------------------+
| Pointer is sysnull (OKish) or null (Not OK) for single ride trips |
+------------------------------------------------------------------*/
if lift_ptr ^= sysnull() then
#wid = lift_list.wid;
sdwait = iwait;
1 do #i = 0 to 3 while(sdwait(0).#w < waits(8).#w);
@data = '0'b;
avg_sd = wavg / 60;
sdwait(1) = iwait;
do lift_ptr = lift_ptr repeat wift_nxt
while(lift_ptr ^= sysnull() &
lift_list.wid = #wid &
lift_list.wtime <= avg_sd);
if lift_list.wtime ^= -1 then
do;
@data = '1'b;
sdwait(1).#w = sdwait(1).#w + 1;
sdwait(1).wtime = sdwait(1).wtime + lift_list.wtime;
end;
end;
sdwait(0) = sdwait(0) + sdwait(1);
line = waitsd_init;
waitsd_line.head = sd_desc(#i);
if @data then
do;
call average_time((sdwait(1).wtime * 60), (sdwait(1).#w));
waitsd_line.wait.#w = sdwait(1).#w;
waitsd_line.wait.whh = sdwait(1).wtime / 60;
waitsd_line.wait.wmm = mod(sdwait(1).wtime, 60);
waitsd_line.wait.w_avg = wt_avg;
if #i > 0 then
do;
call average_time((sdwait(0).wtime * 60), (sdwait(0).#w));
waitsd_line.cwait.#w = sdwait(0).#w;
waitsd_line.cwait.whh = sdwait(0).wtime / 60;
waitsd_line.cwait.wmm = mod(sdwait(0).wtime, 60);
waitsd_line.cwait.w_avg = wt_avg;
end;
else
waitsd_line.cwait.hs = ' ';
waitsd_line.perc = round(
divide(dec(sdwait(1).#w, 7) * 100,
dec(waits(8).#w, 7), 7, 3), 2);
end;
else
waitsd_line.wait.hs,
waitsd_line.cwait.hs = ' ';
1 if #i = 0 then
write file(outfile) from(waitsd_sep);
write file(outfile) from(line);
wavg = wavg + sdev;
end;
wift_ptr = lift_ptr;
if sdwait(0).#w < waits(8).#w then
do;
write file(outfile) from(waitsd_sep);
line = waitsd_init;
waitsd_line.head = sd_desc(4);
sdwait(1) = waits(8) - sdwait(0);
waitsd_line.wait.#w = sdwait(1).#w;
waitsd_line.wait.whh = sdwait(1).wtime / 60;
waitsd_line.wait.wmm = mod(sdwait(1).wtime, 60);
call average_time((sdwait(1).wtime * 60), (sdwait(1).#w));
waitsd_line.wait.w_avg = wt_avg;
string(waitsd_line.cwait) = substr(sline, 12, 25);
waitsd_line.perc = round(
divide(dec(sdwait(1).#w, 7) * 100,
dec(waits(8).#w, 7), 7, 3), 2);
write file(outfile) from(line);
end;
write file(outfile) from(waitsd_sep);
write file(outfile) from(sline);
write file(outfile) from(waitsd_sep);
write file(outfile) from(iline);
end print_waitsd;
1/**********************************************************************
* PRINT_FERRY: *
* *
* This procedure prints details of the ferry crossings and in-ride *
* waits due to ferry crossings *
**********************************************************************/
print_ferry: proc;
dcl 1 filler static,
2 filler char (16) init ('FERRY LINES '),
2 ferry_sep char (121)
init ((' +------+------+------+------+--------+')),
2 ferry_init char (121)
init ((' | | | | | : |')),
2 ferry_top char (121)
init ((' +------------------------------------+')),
2 ferry_head char (121)
init ((' | Trip | Ride | From | To | Wait |')),
2 ferry_total char (121)
init ((' | Total : |'));
dcl 1 ferry_line based(line_ptr),
2 filler char (3),
2 trip pic 'zzz9',
2 filler char (3),
2 ride pic 'zzz9',
2 filler char (3),
2 from char (4),
2 filler char (3),
2 cnty char (4),
2 filler char (3),
2 whh pic 'zz9',
2 filler char (1),
2 wmm pic '99';
dcl #i fixed bin (31);
dcl zzz9 pic 'zzz9';
dcl ftime fixed bin (31);
dcl wtime fixed bin (31);
1/*+-------------------------------------------------------------------+
| Start of executable code for print_ferry |
+------------------------------------------------------------------*/
if #ferry > 0 then
do;
write file(outfile) from(pline);
write file(outfile) from(ferry_top);
ftime = 0;
zzz9 = #ferry;
do #i = 1 to stg(zzz9) while(substr(zzz9, #i, 1) = ' ');
end;
line = ' | Ferry crossings (' || substr(zzz9, #i) || ')';
substr(line, 39) = '|';
write file(outfile) from(line);
write file(outfile) from(ferry_sep);
write file(outfile) from(ferry_head);
write file(outfile) from(ferry_sep);
line = ferry_init;
1 do lift_ptr = lift_top repeat lift_nxt
while(lift_ptr ^= sysnull());
if lift_list.cnty ^= ' ' &
lift_list.cnty ^= '* ' then
do;
if lift_list.ferry then
do;
wtime = lift_list.wtime;
if wtime = 0 then
wtime = owner -> lift_prv -> lift_list.itime;
ferry_line = lift_list, by name;
ferry_line.whh = wtime / 60;
ferry_line.wmm = mod(wtime, 60);
write file(outfile) from(line);
ftime = ftime + wtime;
end;
if lift_list.split ^= '!' then
ferry_line.from = lift_list.cnty;
end;
end;
write file(outfile) from(ferry_sep);
line = ferry_total;
ferry_line.whh = ftime / 60;
ferry_line.wmm = mod(ftime, 60);
write file(outfile) from(line);
write file(outfile) from(ferry_top);
end;
1 if #wferry > 0 then
do;
write file(outfile) from(iline);
write file(outfile) from(ferry_top);
ftime = 0;
zzz9 = #wferry;
do #i = 1 to stg(zzz9) while(substr(zzz9, #i, 1) = ' ');
end;
line = ' | In-ride ferry crossings (' || substr(zzz9, #i) || ')';
substr(line, 39) = '|';
write file(outfile) from(line);
write file(outfile) from(ferry_sep);
write file(outfile) from(ferry_head);
write file(outfile) from(ferry_sep);
line = ferry_init;
do lift_ptr = lift_top repeat lift_nxt
while(lift_ptr ^= sysnull());
if lift_list.wferry then
do;
ftime = ftime + lift_list.itime;
ferry_line.trip = lift_list.trip;
ferry_line.ride = lift_list.ride;
ferry_line.whh = lift_list.itime / 60;
ferry_line.wmm = mod(lift_list.itime, 60);
save_lift_ptr = lift_ptr;
1 if lift_list.cnty = ' ' then
do;
do lift_ptr = lift_prv repeat lift_prv
until(lift_list.cnty ^= ' ');
end;
ferry_line.from = lift_list.cnty;
ferry_line.cnty = lift_list.cnty;
end;
else
do;
ferry_line.from = lift_list.cnty;
do lift_ptr = lift_prv repeat lift_prv
until(lift_list.cnty = ferry_line.from);
end;
lift_ptr = lift_nxt;
ferry_line.cnty = lift_list.cnty;
end;
lift_ptr = save_lift_ptr;
write file(outfile) from(line);
end;
end;
write file(outfile) from(ferry_sep);
line = ferry_total;
ferry_line.whh = ftime / 60;
ferry_line.wmm = mod(ftime, 60);
write file(outfile) from(line);
write file(outfile) from(ferry_top);
end;
end print_ferry;
1/**********************************************************************
* PROCESS_PICKUPS: *
* *
* This procedure accumulates the relationships between *
* *
* - the countries being passed and the nationalities of the drivers *
* that gave a ride in each particular country *
* *
* - the types of driver that gave a ride in every country being *
* passed *
* *
* - the types of driver that gave a ride for each nationality *
**********************************************************************/
process_pickups: proc(pickup_t,
pickup_c,
pickup_n,
#sep);
dcl pickup_t char (1022) var;
dcl pickup_c char (1022) var;
dcl pickup_n char (1022) var;
dcl #sep fixed bin (31);
dcl #put fixed bin (31) init ((length(pickup_t) / 4));
dcl #puc fixed bin (31) init ((length(pickup_c) / 4));
dcl #pun fixed bin (31) init ((length(pickup_n) / 4));
dcl pu_naco(#pun, #puc) fixed bin (31) ctl;
dcl pu_coty(#puc, #put) fixed bin (31) ctl;
dcl pu_naty(#pun, #put) fixed bin (31) ctl;
dcl #t fixed bin (31) init (1);
dcl #c fixed bin (31) init (1);
dcl #n fixed bin (31) init (1);
dcl #tx fixed bin (31) init (1);
dcl #cx fixed bin (31) init (1);
dcl #nx fixed bin (31) init (1);
1/*+-------------------------------------------------------------------+
| Start of executable code for process_pickups |
+------------------------------------------------------------------*/
alloc pu_naco;
pu_naco_ptr = addr(pu_naco);
pu_naco = 0;
alloc pu_coty;
pu_coty_ptr = addr(pu_coty);
pu_coty = 0;
alloc pu_naty;
pu_naty_ptr = addr(pu_naty);
pu_naty = 0;
/*------------------------------------------------------------------+
| Accumulate the pick-ups |
+------------------------------------------------------------------*/
select;
when (@trip) lift_ptr = tr_top;
when (@year) lift_ptr = yr_top;
when (@summary) lift_ptr = lift_top;
other lift_ptr = sysnull();
end;
do lift_ptr = lift_ptr repeat nxt_ptr
while(lift_ptr ^= sysnull())
until(lift_ptr = sysnull());
if lift_list.split = ' ' then
do;
do lift_ptr = lift_ptr repeat lift_nxt
while(lift_ptr ^= sysnull() &
(lift_list.cnty = ' ' |
lift_list.cnty = '* '));
end;
if lift_list.type ^= substr(pickup_t, #t, 4) then
do;
do #t = 1 to length(pickup_t) - 3 by 4
until(lift_list.type = substr(pickup_t, #t, 4));
end;
#tx = (#t + 3) / 4;
end;
1 if lift_list.cnty ^= substr(pickup_c, #c, 4) then
do;
do #c = 1 to length(pickup_c) - 3 by 4
until(lift_list.cnty = substr(pickup_c, #c, 4));
end;
#cx = (#c + 3) / 4;
end;
if lift_list.nat ^= substr(pickup_n, #n, 4) then
do;
do #n = 1 to length(pickup_n) - 3 by 4
until(lift_list.nat = substr(pickup_n, #n, 4));
end;
#nx = (#n + 3) / 4;
end;
pu_naco(#nx, #cx) = pu_naco(#nx, #cx) + 1;
pu_coty(#cx, #tx) = pu_coty(#cx, #tx) + 1;
pu_naty(#nx, #tx) = pu_naty(#nx, #tx) + 1;
end;
select;
when (@trip) nxt_ptr = tr_nxt;
when (@year) nxt_ptr = yr_nxt;
when (@summary) nxt_ptr = lift_nxt;
end;
end;
1 write file(outfile) from(pline);
call print_pickups(pu_naco,
pickup_c,
pickup_n,
#sep,
'NaCo');
call print_pickups(pu_coty,
pickup_t,
pickup_c,
0,
'CoTy');
call print_pickups(pu_naty,
pickup_t,
pickup_n,
#sep,
'NaTy');
free pu_naco;
pu_naco_ptr = sysnull();
free pu_coty;
pu_coty_ptr = sysnull();
free pu_naty;
pu_naty_ptr = sysnull();
end process_pickups;
1/**********************************************************************
* PRINT_PICKUPS: *
* *
* This procedure prints the filled pickup tables *
**********************************************************************/
print_pickups: proc(pu_tab,
pickup_x,
pickup_y,
#sep,
tcn);
dcl pu_tab(*, *) fixed bin (31);
dcl pickup_x char (1022) var;
dcl pickup_y char (1022) var;
dcl #sep fixed bin (31);
dcl tcn char (4);
dcl sline char (121);
dcl tline char (121);
dcl 1 filler static,
2 filler char (16) init ('PU LINES '),
2 pu_sep char (121)
init ((' +' || (11)'------+')),
2 pu_init char (121)
init ((' | |' || (10)' - |'));
dcl 1 pu_line based(line_ptr),
2 filler char (3),
2 head char (4),
2 filler char (3),
2 filler(10),
3 #r pic 'zzz9',
3 filler char (3);
dcl #pu_x fixed bin (31) init ((length(pickup_x) / 4));
dcl #pu_y fixed bin (31) init ((length(pickup_y) / 4));
dcl #i fixed bin (31);
dcl #j fixed bin (31);
dcl #k fixed bin (31);
dcl #l fixed bin (31);
1/*+-------------------------------------------------------------------+
| Start of executable code for print_pickups |
+-------------------------------------------------------------------+
| Print the result in lines with a maximum width of 10 columns |
+------------------------------------------------------------------*/
do #i = 1 to (length(pickup_x) + 36) / 40;
/*----------------------------------------------------------------+
| Determine width of the last (partial) table |
+----------------------------------------------------------------*/
#l = index(pu_sep, '-+ ') + 1;
#l = min(#l, #l + 7 * #pu_x - 70 * #i);
sline = substr(pu_sep, 1, #l);
write file(outfile) from(sline);
line = pu_init;
substr(line, 4, 4) = tcn;
/*----------------------------------------------------------------+
| Insert the column headers into the header line |
+----------------------------------------------------------------*/
#j = min(10, (#l - 8) / 7);
do #k = 1 to #j;
string(pu_line.#r(#k)) =
substr(pickup_x, 40 * #i + 4 * #k - 43, 4);
end;
line = substr(line, 1, #l);
write file(outfile) from(line);
write file(outfile) from(sline);
/*----------------------------------------------------------------+
| Number of rows in the table |
+----------------------------------------------------------------*/
do #j = 1 to #pu_y;
line = pu_init;
pu_line.head = substr(pickup_y, 4 * #j - 3, 4);
1 /*--------------------------------------------------------------+
| Pick out current batch of columns |
+--------------------------------------------------------------*/
do #k = 10 * #i - 9 to min(10 * #i, #pu_x);
if pu_tab(#j, #k) ^= 0 then
pu_line.#r(#k - (#i - 1) * 10) = pu_tab(#j, #k);
end;
line = substr(line, 1, #l);
write file(outfile) from(line);
if #j = #sep &
#j ^= #pu_y then
do;
tline = translate(sline, $ds, '-');
write file(outfile) from(tline);
end;
end;
write file(outfile) from(sline);
write file(outfile) from(iline);
end;
end print_pickups;
1/**********************************************************************
* PROCESS_MIN_MAX: *
* *
* This procedure determines the minimum and maximum distance, time *
* and velocity for either *
* *
* - rides, for the full summary and the summaries per trip, type and *
* nationality or *
* - days, for the summaries per trip. *
**********************************************************************/
process_min_max: proc(#m,
km,
time,
vx);
dcl #m fixed bin (31);
dcl km fixed (9,1);
dcl time fixed (9);
dcl vx fixed (13,9);
minmax(#m).#mima = minmax(#m).#mima + 1;
if km ^= 0 & time ^= 0 then
do;
minmax(#m).l_min = min(minmax(#m).l_min, km);
minmax(#m).l_max = max(minmax(#m).l_max, km);
minmax(#m).l_tot = minmax(#m).l_tot + km;
minmax(#m).t_min = min(minmax(#m).t_min, time);
minmax(#m).t_max = max(minmax(#m).t_max, time);
minmax(#m).t_tot = minmax(#m).t_tot + time;
minmax(#m).v_min = min(minmax(#m).v_min, vx);
minmax(#m).v_max = max(minmax(#m).v_max, vx);
end;
end process_min_max;
1/**********************************************************************
* PRINT_MIN_MAX_BOX: *
* *
* Print the top or bottom lines for a min/max/avg box. *
**********************************************************************/
print_min_max_box: proc(head);
dcl head char (*);
dcl sline char (121);
select(head);
when ('B')
do;
write file(outfile) from(min_max_sep);
heading = ' ';
end;
when ('B=')
do;
sline = translate(min_max_sep, $ds, '-');
write file(outfile) from(sline);
heading = ' ';
end;
other
do;
write file(outfile) from(min_max_sep);
line = min_max_head;
substr(line, 4, stg(head)) = head;
write file(outfile) from(line);
write file(outfile) from(min_max_sep);
end;
end;
end print_min_max_box;
1/**********************************************************************
* PRINT_MIN_MAX: *
* *
* Print a summary table for the maximum, minimum and average speed, *
* distance and time for the current mode. The table is repeated for *
* *
* - the summary (only per ride), *
* - each trip (per ride and per day), *
* - each type (only per ride) and *
* - each nationality (only per ride) *
**********************************************************************/
print_min_max: proc(mode);
dcl mode char (4);
dcl #mm fixed bin (31);
dcl #div fixed (13,8);
dcl #pc pic 'zzz9v.99';
/*+-------------------------------------------------------------------+
| Start of executable code for print_min_max |
+------------------------------------------------------------------*/
select(mode);
when ('Ride') #mm = 1;
when ('Day ') #mm = 2;
other;
end;
if minmax(#mm).t_tot ^= 0 then
minmax(#mm).v_avg = round(
divide(
multiply(minmax(#mm).l_tot, 60, 15, 0),
minmax(#mm).t_tot, 15, 11), 1);
#div = minmax(#mm).#mima;
minmax(#mm).l_avg = round(
divide(minmax(#mm).l_tot, #div, 15, 2), 1);
line = min_max_init;
min_max_line = minmax(#mm), by name;
min_max_line.v_maxr = round(minmax(#mm).v_max, 1);
min_max_line.v_minr = round(minmax(#mm).v_min, 1);
min_max_line.t_max_hh = minmax(#mm).t_max / 60;
min_max_line.t_max_mm = mod(minmax(#mm).t_max, 60);
min_max_line.t_min_hh = minmax(#mm).t_min / 60;
min_max_line.t_min_mm = mod(minmax(#mm).t_min, 60);
lift_work.t_avg = round(
divide(minmax(#mm).t_tot,
#div, 15, 11), 0);
min_max_line.t_avg_hh = lift_work.t_avg / 60;
min_max_line.t_avg_mm = mod(lift_work.t_avg, 60);
min_max_line.mode = mode;
1 if ^@summary &
^@cnty &
^@nested then
write file(outfile) from(line);
/*------------------------------------------------------------------+
| Save results in lists for final tables |
+------------------------------------------------------------------*/
select;
when (@nat)
do;
min_max_line.mode = heading;
alloc ntot_list in(ntot_area);
ntot_end -> ntot_nxt,
ntot_end = ntot_ptr;
end;
when (@cnty)
do;
min_max_line.mode = heading;
#pc = round(minmax(#mm).#rc, 2);
line = substr(line, 1, 10) ||
#pc ||
substr(line, 15, 101);
alloc ctot_list in(ctot_area);
ctot_end -> ctot_nxt,
ctot_end = ctot_ptr;
if #mm = 2 then
cid = 'Ext';
end;
when (@type)
do;
min_max_line.mode = heading;
alloc ttot_list in(ttot_area);
ttot_end -> ttot_nxt,
ttot_end = ttot_ptr;
end;
1 when (@trip)
do;
min_max_line.mode = trip_pic;
if mode = 'Ride' then
do;
alloc rtot_list;
rtot_end -> rtot_nxt,
rtot_end = rtot_ptr;
end;
else
do;
dtot.l_max = max(dtot.l_max, minmax(#mm).l_max);
dtot.l_min = min(dtot.l_min, minmax(#mm).l_min);
dtot.t_max = max(dtot.t_max, minmax(#mm).t_max);
dtot.t_min = min(dtot.t_min, minmax(#mm).t_min);
dtot.v_max = max(dtot.v_max, minmax(#mm).v_max);
dtot.v_min = min(dtot.v_min, minmax(#mm).v_min);
alloc dtot_list;
dtot_end -> dtot_nxt,
dtot_end = dtot_ptr;
end;
end;
when (@year)
do;
min_max_line.mode = year_pic;
alloc ytot_list;
ytot_list.id = substr(mode, 1, 1);
ytot_end -> ytot_nxt,
ytot_end = ytot_ptr;
end;
when (@summary)
do;
min_max_line.mode = 'Tot ';
alloc rtot_list;
rtot_end -> rtot_nxt,
rtot_end = rtot_ptr;
end;
other;
end;
end print_min_max;
1/**********************************************************************
* FAST_DISTANCE: *
* *
* This procedure scans the lists of rides, days, and trips to *
* determine the highest speed over a number of selected distances and *
* for every selected distance it prints a row containing the *
* *
* - selected distance *
* - the actual distance *
* - the total time for the actual distance *
* - the average speed for the actual distance *
* - the first item for the actual distance *
* - the last item for the actual distance *
* *
* The procedure performs the summations using a sliding window over *
* the list of items. *
**********************************************************************/
fast_distance: proc(ltd_top,
ltd_type,
ltd_head,
ltd_sep,
ltd_init);
dcl ltd_top ptr;
dcl ltd_type(4) char (8) conn;
dcl ltd_head char (121);
dcl ltd_sep char (121);
dcl ltd_init char (121);
dcl window_top ptr;
dcl #i fixed bin (31);
dcl @first bit (1) aligned;
1/*+-------------------------------------------------------------------+
| Start of executable code for fast_distance |
+------------------------------------------------------------------*/
line = ltd_init;
do #i = 1 to hbound(fast_dist, 1)
while(fast_dist(#i) <= trip_total.km);
minmax = iminmax;
minmax(2).f_max = 99999.9999999999;
minmax(3).#mima = 2147483647;
ltd_ptr,
window_top = ltd_top;
do until(ltd_ptr = sysnull() &
minmax(0).l_max < fast_dist(#i));
minmax(0).fptr(1) = window_top;
do while(ltd_ptr ^= sysnull() &
minmax(0).l_max < fast_dist(#i));
minmax(0).#mima = minmax(0).#mima + 1;
minmax(0).l_max = minmax(0).l_max + ltd_list.km;
minmax(0).t_max = minmax(0).t_max + ltd_list.time;
minmax(0).fptr(2) = ltd_ptr;
ltd_ptr = ltd_nxt;
end;
if minmax(0).l_max >= fast_dist(#i) then
do;
minmax(0).f_max = divide(
multiply(minmax(0).l_max, 60, 15, 0),
minmax(0).t_max, 15, 10);
if minmax(0).f_max > minmax(1).f_max then
minmax(1) = minmax(0);
if minmax(0).f_max < minmax(2).f_max then
minmax(2) = minmax(0);
if minmax(0).#mima < minmax(3).#mima |
minmax(0).#mima = minmax(3).#mima &
(minmax(0).l_max > minmax(3).l_max |
minmax(0).l_max = minmax(3).l_max &
minmax(0).f_max > minmax(3).f_max) then
minmax(3) = minmax(0);
1 if minmax(0).#mima > minmax(4).#mima |
minmax(0).#mima = minmax(4).#mima &
(minmax(0).l_max < minmax(4).l_max |
minmax(0).l_max = minmax(4).l_max &
minmax(0).f_max < minmax(4).f_max) then
minmax(4) = minmax(0);
minmax(0).#mima = minmax(0).#mima - 1;
minmax(0).l_max = minmax(0).l_max -
window_top -> ltd_list.km;
minmax(0).t_max = minmax(0).t_max -
window_top -> ltd_list.time;
window_top = window_top -> ltd_nxt;
end;
end;
fast_line.fastest = fast_dist(#i);
call fill_fast_line();
end;
1 /*------------------------------------------------------------------+
| Print the tables from the data stored in the saved list |
+------------------------------------------------------------------*/
write file(outfile) from(pline);
do #i = 1 to 4;
@first = '1'b;
do fast_ptr = fast_top repeat fast_nxt
while(fast_ptr ^= sysnull());
if fast_list.ftype = #i then
do;
select;
when (@first)
do;
@first = '0'b;
write file(outfile) from(ltd_sep);
line = ltd_head;
substr(line, 4, 8) = ltd_type(#i);
write file(outfile) from(line);
write file(outfile) from(ltd_sep);
end;
when (substr(line, 12) ^= substr(fast_list.fline, 12))
write file(outfile) from(line);
other
do;
substr(line, 12) = substr(ltd_init, 12);
fast_line.hs = ' ';
write file(outfile) from(line);
end;
end;
line = fast_list.fline;
end;
end;
if ^@first then
do;
write file(outfile) from(line);
write file(outfile) from(ltd_sep);
write file(outfile) from(iline);
end;
end;
call free_fast_list();
end fast_distance;
1/**********************************************************************
* FAST_LTD: *
* *
* This procedure scans the lists or rides, days, and trips to *
* determine the highest speed over a number of selected rides and for *
* every selected number of rides it prints a row containing the *
* *
* - selected number of items *
* - the distance *
* - the total time for the distance *
* - the average speed for the distance *
* - the first item for the distance (trip & ride) *
* - the last item for the distance (trip & ride) *
* *
* The procedure performs the summations using a sliding window over *
* the list of items. *
**********************************************************************/
fast_ltd: proc(ltd_top,
#ltd,
ltd_fast,
ltd_desc,
ltd_head,
ltd_sep,
ltd_init);
dcl ltd_top ptr;
dcl #ltd fixed bin (31);
dcl ltd_fast(*) fixed bin (31) conn;
dcl ltd_desc(*) char (8) conn;
dcl ltd_head char (121);
dcl ltd_sep char (121);
dcl ltd_init char (121);
dcl window_top ptr;
dcl #i fixed bin (31);
dcl @first bit (1) aligned;
1/*+-------------------------------------------------------------------+
| Start of executable code for fast_ltd |
+------------------------------------------------------------------*/
line = ltd_init;
do #i = 1 to hbound(ltd_fast, 1) while(ltd_fast(#i) <= #ltd);
minmax = iminmax;
minmax(2).f_max = 99999.9999999999;
minmax(4).l_max = 99999999.9;
window_top = ltd_top;
do ltd_ptr = ltd_top repeat ltd_nxt
while(ltd_ptr ^= sysnull());
minmax(0).fptr(1) = window_top;
minmax(0).#mima = minmax(0).#mima + 1;
minmax(0).l_max = minmax(0).l_max + ltd_list.km;
minmax(0).t_max = minmax(0).t_max + ltd_list.time;
if minmax(0).#mima >= ltd_fast(#i) then
do;
minmax(0).fptr(2) = ltd_ptr;
minmax(0).f_max = divide(
multiply(minmax(0).l_max, 60, 15, 0),
minmax(0).t_max, 15, 10);
if minmax(0).f_max > minmax(1).f_max then
minmax(1) = minmax(0);
if minmax(0).f_max < minmax(2).f_max then
minmax(2) = minmax(0);
if minmax(0).l_max > minmax(3).l_max |
minmax(0).l_max = minmax(3).l_max &
(minmax(0).f_max > minmax(3).f_max |
minmax(0).f_max = minmax(3).f_max &
minmax(0).#mima < minmax(3).#mima) then
minmax(3) = minmax(0);
if minmax(0).l_max < minmax(4).l_max |
minmax(0).l_max = minmax(4).l_max &
(minmax(0).f_max < minmax(4).f_max |
minmax(0).f_max = minmax(4).f_max &
minmax(0).#mima > minmax(4).#mima) then
minmax(4) = minmax(0);
1 minmax(0).#mima = minmax(0).#mima - 1;
minmax(0).l_max = minmax(0).l_max -
window_top -> ltd_list.km;
minmax(0).t_max = minmax(0).t_max -
window_top -> ltd_list.time;
window_top = window_top -> ltd_nxt;
end;
end;
call fill_ride_line();
end;
1 /*------------------------------------------------------------------+
| Print the tables from the data stored in the saved list |
+------------------------------------------------------------------*/
write file(outfile) from(pline);
do #i = 1 to 4;
@first = '1'b;
do fast_ptr = fast_top repeat fast_nxt
while(fast_ptr ^= sysnull());
if fast_list.ftype = #i then
do;
if @first then
do;
@first = '0'b;
write file(outfile) from(ltd_sep);
line = ltd_head;
substr(line, 4, 8) = ltd_desc(#i);
write file(outfile) from(line);
write file(outfile) from(ltd_sep);
end;
write file(outfile) from(fast_list.fline);
end;
end;
if ^@first then
do;
write file(outfile) from(ltd_sep);
write file(outfile) from(iline);
end;
end;
call free_fast_list();
end fast_ltd;
1/**********************************************************************
* FAST_SPEED: *
* *
* This procedure scans the lists of rides, days, and trips to *
* determine the greatest number of consecutive items with a velocity *
* over a selected number of velocities. For every selected velocity *
* it prints a row containing the *
* *
* - selected velocity, *
* - the number of consecutive items with a velocity exceeding the *
* selected velocity, *
* - the distance for those items, *
* - the time for those items, *
* - the average speed for the group of items, *
* - the first item for the group, *
* - the last item for the group *
* *
* For the first copy of the table, every item has to exceed the *
* selected velocity. *
* *
* For the second copy of the table, the cumulative average has to *
* stay above the selected velocity. *
**********************************************************************/
fast_speed: proc(ltd_top,
vx_max_ltd,
ltd_init);
dcl ltd_top ptr;
dcl vx_max_ltd fixed (13,9);
dcl ltd_init char (121);
dcl #i fixed bin (31);
dcl window_top ptr;
1/*+-------------------------------------------------------------------+
| Start of executable code for fast_speed |
+-------------------------------------------------------------------+
| First 4 tables - every velocity needs to exceed vx_max_ltd |
+------------------------------------------------------------------*/
line = ltd_init;
do #i = 1 to hbound(highest_s, 1) while(highest_s(#i) <= vx_max_ltd);
minmax = iminmax;
do ltd_ptr = ltd_top repeat nxt_ptr
while(ltd_ptr ^= sysnull());
if ltd_list.vx > highest_s(#i) then
do;
minmax(0) = iminmax;
minmax(0).fptr(1) = ltd_ptr;
do ltd_ptr = ltd_ptr repeat nxt_ptr
while(ltd_ptr ^= sysnull() &
ltd_list.vx > highest_s(#i));
minmax(0).#mima = minmax(0).#mima + 1;
minmax(0).l_max = minmax(0).l_max + ltd_list.km;
minmax(0).t_max = minmax(0).t_max + ltd_list.time;
minmax(0).fptr(2) = ltd_ptr;
nxt_ptr = ltd_nxt;
end;
minmax(0).f_max = divide(
multiply(minmax(0).l_max, 60, 15, 0),
minmax(0).t_max, 15, 10);
1 if minmax(0).#mima > minmax(2).#mima |
minmax(0).#mima = minmax(2).#mima &
(minmax(0).f_max > minmax(2).f_max |
minmax(0).f_max = minmax(2).f_max &
minmax(0).l_max > minmax(2).l_max) then
minmax(2) = minmax(0);
if minmax(0).l_max > minmax(3).l_max |
(minmax(0).l_max = minmax(3).l_max &
minmax(0).f_max > minmax(3).f_max) then
minmax(3) = minmax(0);
end;
if ltd_ptr ^= sysnull() then
nxt_ptr = ltd_nxt;
end;
call store_fast_length_speed(highest_s(#i));
end;
call print_fast_length_speed('V');
1 /*------------------------------------------------------------------+
| Second 4 tables - average velocity needs to stay above vx_max_ltd |
+------------------------------------------------------------------*/
line = ltd_init;
do #i = 1 to hbound(highest_s, 1) while(highest_s(#i) <= vx_max_ltd);
minmax = iminmax;
do ltd_ptr = ltd_top repeat nxt_ptr
while(ltd_ptr ^= sysnull());
window_top = ltd_ptr;
if ltd_list.vx > highest_s(#i) then
do;
minmax(0) = iminmax;
minmax(0).fptr(1) = ltd_ptr;
do ltd_ptr = ltd_ptr repeat nxt_ptr
while(ltd_ptr ^= sysnull())
until(minmax(0).f_max <= highest_s(#i));
minmax(0).l_max = minmax(0).l_max + ltd_list.km;
minmax(0).t_max = minmax(0).t_max + ltd_list.time;
minmax(0).f_max = divide(
multiply(minmax(0).l_max, 60, 15, 0),
minmax(0).t_max, 15, 10);
if minmax(0).f_max <= highest_s(#i) then
window_top = ltd_ptr;
else
do;
minmax(0).#mima = minmax(0).#mima + 1;
minmax(0).fptr(2) = ltd_ptr;
minmax(1) = minmax(0);
nxt_ptr = ltd_nxt;
end;
end;
1 if minmax(1).f_max > highest_s(#i) then
do;
if minmax(1).#mima > minmax(2).#mima |
minmax(1).#mima = minmax(2).#mima &
(minmax(1).f_max > minmax(2).f_max |
minmax(1).f_max = minmax(2).f_max &
minmax(1).l_max > minmax(2).l_max) then
minmax(2) = minmax(1);
if minmax(1).l_max > minmax(3).l_max |
(minmax(1).l_max = minmax(3).l_max &
minmax(1).f_max > minmax(3).f_max) then
minmax(3) = minmax(1);
end;
end;
if ltd_ptr ^= sysnull() then
do;
ltd_ptr = window_top;
nxt_ptr = ltd_nxt;
end;
end;
call store_fast_length_speed(highest_s(#i));
end;
call print_fast_length_speed('v');
end fast_speed;
1/**********************************************************************
* FAST_LENGTH: *
* *
* This procedure scans the lists of rides, days, and trips to *
* determine the greatest number of consecutive items with a distance *
* over a selected number of distances. For every selected distance *
* it prints a row containing the *
* *
* - selected distance, *
* - the number of consecutive items with a distance exceeding the *
* selected distance, *
* - the distance for those items, *
* - the time for those items, *
* - the average speed for the group of items, *
* - the first item for the group *
* - the last item for the group *
* *
* For the first copy of the table, every item has to exceed the *
* selected distance. *
* *
* For the second copy of the table, the cumulative average has to *
* stay above the selected distance. *
**********************************************************************/
fast_length: proc(ltd_top,
ltd_longest,
ltd_init);
dcl ltd_top ptr;
dcl ltd_longest(*) fixed (15,10);
dcl ltd_init char (121);
dcl #i fixed bin (31);
dcl window_top ptr;
1/*+-------------------------------------------------------------------+
| Start of executable code for fast_length |
+-------------------------------------------------------------------+
| First 4 tables - every distance needs to exceed "the" distance |
+------------------------------------------------------------------*/
line = ltd_init;
do #i = 1 to hbound(ltd_longest, 1);
minmax = iminmax;
do ltd_ptr = ltd_top repeat nxt_ptr while(ltd_ptr ^= sysnull());
if ltd_list.km > ltd_longest(#i) then
do;
minmax(0) = iminmax;
minmax(0).fptr(1) = ltd_ptr;
do ltd_ptr = ltd_ptr repeat nxt_ptr
while(ltd_ptr ^= sysnull() &
ltd_list.km > ltd_longest(#i));
minmax(0).#mima = minmax(0).#mima + 1;
minmax(0).l_max = minmax(0).l_max + ltd_list.km;
minmax(0).t_max = minmax(0).t_max + ltd_list.time;
minmax(0).fptr(2) = ltd_ptr;
nxt_ptr = ltd_nxt;
end;
minmax(0).l_avg = divide(minmax(0).l_max,
dec(minmax(0).#mima, 7), 15, 9);
minmax(0).f_max = divide(
multiply(minmax(0).l_max, 60, 15, 0),
minmax(0).t_max, 15, 10);
1 if minmax(0).#mima > minmax(2).#mima |
minmax(0).#mima = minmax(2).#mima &
(minmax(0).l_max > minmax(2).l_max |
minmax(0).l_max = minmax(2).l_max &
minmax(0).f_max > minmax(2).f_max) then
minmax(2) = minmax(0);
if minmax(0).l_max > minmax(3).l_max |
minmax(0).l_max = minmax(3).l_max &
(minmax(0).l_avg > minmax(3).l_avg |
minmax(0).l_avg = minmax(3).l_avg &
minmax(0).f_max > minmax(3).f_max) then
minmax(3) = minmax(0);
end;
if ltd_ptr ^= sysnull() then
nxt_ptr = ltd_nxt;
end;
call store_fast_length_speed(ltd_longest(#i));
end;
if fast_top ^= sysnull() then
call print_fast_length_speed('L');
1 /*------------------------------------------------------------------+
| Second 4 tables - average distance needs to stay above "distance" |
+------------------------------------------------------------------*/
line = ltd_init;
do #i = 1 to hbound(ltd_longest, 1);
minmax = iminmax;
do ltd_ptr = ltd_top repeat nxt_ptr while(ltd_ptr ^= sysnull());
if ltd_list.km > longest_r(#i) then
do;
minmax(0) = iminmax;
minmax(0).fptr(1) = ltd_ptr;
do ltd_ptr = ltd_ptr repeat nxt_ptr
while(ltd_ptr ^= sysnull())
until(minmax(0).l_avg <= ltd_longest(#i));
minmax(0).#mima = minmax(0).#mima + 1;
minmax(0).l_max = minmax(0).l_max + ltd_list.km;
minmax(0).l_avg = divide(minmax(0).l_max,
dec(minmax(0).#mima, 7), 15, 9);
if minmax(0).l_avg <= ltd_longest(#i) then
window_top = ltd_ptr;
else
do;
minmax(0).t_max = minmax(0).t_max + ltd_list.time;
minmax(0).fptr(2) = ltd_ptr;
minmax(1) = minmax(0);
nxt_ptr = ltd_nxt;
end;
end;
if minmax(1).l_avg > ltd_longest(#i) then
do;
minmax(1).f_max = divide(
multiply(minmax(1).l_max, 60, 15, 0),
minmax(1).t_max, 15, 10);
1 if minmax(1).#mima > minmax(2).#mima |
minmax(1).#mima = minmax(2).#mima &
(minmax(1).l_max > minmax(2).l_max |
minmax(1).l_max = minmax(2).l_max &
minmax(1).f_max > minmax(2).f_max) then
minmax(2) = minmax(1);
if minmax(1).l_max > minmax(3).l_max |
minmax(1).l_max = minmax(3).l_max &
(minmax(1).l_avg > minmax(3).l_avg |
minmax(1).l_avg = minmax(3).l_avg &
minmax(1).f_max > minmax(3).f_max) then
minmax(3) = minmax(1);
end;
end;
else
window_top = ltd_ptr;
if ltd_ptr ^= sysnull() then
do;
ltd_ptr = window_top;
nxt_ptr = ltd_nxt;
end;
end;
call store_fast_length_speed(ltd_longest(#i));
end;
if fast_top ^= sysnull() then
call print_fast_length_speed('l');
end fast_length;
1/**********************************************************************
* FILL_FAST_LINE: *
* *
* Store the contents of minmax into four lines in the fast_list, for *
* later printing in the correct tables. *
**********************************************************************/
fill_fast_line: proc;
dcl #i fixed bin (31);
dcl 1 fast based,
2 nxt ptr,
2 filler char (4),
2 trip fixed bin (31),
2 ride fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for fill_fast_line |
+------------------------------------------------------------------*/
do #i = 1 to 4;
if minmax(#i).l_max ^= 0 then
do;
fast_line = minmax(#i), by name;
fast_line.t_max_hh = minmax(#i).t_max / 60;
fast_line.t_max_mm = mod(minmax(#i).t_max, 60);
fast_line.f_max = round(minmax(#i).f_max, 1);
fast_line.fasts(1) = minmax(#i).fptr(1) -> fast, by name;
if ^@ftrip then
fast_line.fasts(2) = minmax(#i).fptr(2) -> fast, by name;
else
fast_line.fasts(1).ride = minmax(#i).fptr(2) -> fast.trip;
alloc fast_list;
fast_end -> fast_nxt,
fast_end = fast_ptr;
fast_list.ftype = #i;
end;
end;
end fill_fast_line;
1/**********************************************************************
* FILL_RIDE_LINE: *
* *
* Store the contents of minmax into four lines in the fast_list, for *
* later printing in the correct tables. *
**********************************************************************/
fill_ride_line: proc;
dcl #i fixed bin (31);
dcl 1 fast based,
2 nxt ptr,
2 filler char (4),
2 trip fixed bin (31),
2 ride fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for fill_ride_line |
+------------------------------------------------------------------*/
do #i = 1 to 4;
if minmax(#i).l_max ^= 0 then
do;
ride_line = minmax(#i), by name;
ride_line.t_max_hh = minmax(#i).t_max / 60;
ride_line.t_max_mm = mod(minmax(#i).t_max, 60);
ride_line.f_max = round(minmax(#i).f_max, 1);
ride_line.fasts(1) = minmax(#i).fptr(1) -> fast, by name;
if ^@ftrip then
ride_line.fasts(2) = minmax(#i).fptr(2) -> fast, by name;
else
ride_line.fasts(1).ride = minmax(#i).fptr(2) -> fast.trip;
alloc fast_list;
fast_end -> fast_nxt,
fast_end = fast_ptr;
fast_list.ftype = #i;
end;
end;
end fill_ride_line;
1/**********************************************************************
* STORE_FAST_LENGTH_SPEED: *
* *
* Store the maximum number of rides/days and maximum distances for a *
* number of selected speeds. *
**********************************************************************/
store_fast_length_speed: proc(fastest_ls);
dcl fastest_ls fixed (15,10);
dcl #i fixed bin (31);
dcl 1 fast based,
2 nxt ptr,
2 filler char (4),
2 trip fixed bin (31),
2 ride fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for store_fast_length_speed |
+------------------------------------------------------------------*/
fast_line.fastest = fastest_ls;
do #i = 2 to 3;
if minmax(#i).l_max ^= 0 then
do;
fast_line = minmax(#i), by name;
fast_line.t_max_hh = minmax(#i).t_max / 60;
fast_line.t_max_mm = mod(minmax(#i).t_max, 60);
fast_line.f_max = round(minmax(#i).f_max, 1);
fast_line.fasts(1) = minmax(#i).fptr(1) -> fast, by name;
if ^@ftrip then
fast_line.fasts(2) = minmax(#i).fptr(2) -> fast, by name;
else
fast_line.fasts(1).ride = minmax(#i).fptr(2) -> fast.trip;
alloc fast_list;
fast_end -> fast_nxt,
fast_end = fast_ptr;
fast_list.ftype = #i;
end;
end;
end store_fast_length_speed;
1/**********************************************************************
* PRINT_FAST_LENGTH_SPEED: *
* *
* Print the maximum number of rides/days and maximum distances for a *
* number of selected speeds. *
**********************************************************************/
print_fast_length_speed: proc(mode);
dcl mode char (1);
dcl #i fixed bin (31);
dcl umode char (1);
dcl sptr ptr init (addr(fast_sep));
dcl hptr ptr init (addr(fast_head));
dcl iptr ptr init (addr(fast_init));
dcl sep_line char (121) based(sptr);
dcl head_line char (121) based(hptr);
dcl init_line char (121) based(iptr);
/*+-------------------------------------------------------------------+
| Start of executable code for print_fast_length_speed |
+------------------------------------------------------------------*/
unspec(umode) = unspec(mode) | unspec(' ');
if mode = 'L' |
mode = 'V' then
line = pline;
else
line = iline;
select;
when (@day)
hptr = addr(fast_head_d);
when (@ftrip)
do;
sptr = addr(fast_sep_t);
hptr = addr(fast_head_t);
iptr = addr(fast_init_t);
end;
other;
end;
1 do #i = 2 to 3;
write file(outfile) from(line);
write file(outfile) from(sep_line);
line = head_line;
substr(line, 4, 1) = umode;
if #i = 2 then
select;
when(@day) substr(line, 5, 7) = '= (D+)';
when(@ftrip) substr(line, 5, 7) = '= (T+)';
other substr(line, 5, 7) = '= (R+)';
end;
else
substr(line, 5, 7) = '= (L+)';
if mode = 'L' |
mode = 'V' then
substr(line, 5, 1) = '!';
write file(outfile) from(line);
write file(outfile) from(sep_line);
@first = '1'b;
1 do fast_ptr = fast_top repeat fast_nxt
while(fast_ptr ^= sysnull());
if fast_list.ftype = #i then
do;
substr(fast_list.fline, 4, 1) = '>';
if @first then
@first = '0'b;
else
if substr(line, 12) ^= substr(fast_list.fline, 12) then
write file(outfile) from(line);
else
do;
substr(line, 12) = substr(init_line, 12);
fast_line.hs = ' ';
write file(outfile) from(line);
end;
line = fast_list.fline;
end;
end;
write file(outfile) from(line);
write file(outfile) from(sep_line);
line = iline;
end;
call free_fast_list();
end print_fast_length_speed;
1/**********************************************************************
* PRINT_DAILY_TOTALS: *
* *
* Print distances per calendar day *
**********************************************************************/
print_daily_totals: proc;
dcl #i fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for print_daily_totals |
+------------------------------------------------------------------*/
if ^@year then
write file(outfile) from(pline);
write file(outfile) from(dtcns_sep);
line = dtcns_head;
substr(line, 4, 3) = 'Day';
write file(outfile) from(line);
write file(outfile) from(dtcns_sep);
do #i = lbound(lift_static.day, 1) to hbound(lift_static.day, 1);
line = dtcns_initx;
dtcns_line.head = lift_static.day(#i);
if days(#i).#c ^= 0 then
do;
dtcns_line.#c = days(#i).#c;
dtcns_line.km = days(#i).km;
dtcns_line.hh = days(#i).time / 60;
dtcns_line.mm = mod(days(#i).time, 60);
dtcns_line.v = round(
divide(
multiply(days(#i).km, 60, 15, 0),
days(#i).time, 15, 11), 1);
end;
else
dtcns_line.hs = ' ';
write file(outfile) from(line);
end;
write file(outfile) from(dtcns_sep);
end print_daily_totals;
1/**********************************************************************
* PRINT_MONTHLY_TOTALS: *
* *
* Print distances per month *
**********************************************************************/
print_monthly_totals: proc;
dcl #i fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for print_monthly_totals |
+------------------------------------------------------------------*/
write file(outfile) from(iline);
write file(outfile) from(dtcns_sep);
line = dtcns_head;
substr(line, 4, 5) = 'Month';
substr(line, 15, 2) = '#D';
write file(outfile) from(line);
write file(outfile) from(dtcns_sep);
do #i = lbound(lift_static.month, 1) to hbound(lift_static.month, 1);
line = dtcns_initx;
dtcns_line.head = lift_static.month(#i);
if months.#c(#i) ^= 0 then
do;
dtcns_line.#c = months.#c(#i);
dtcns_line.km = months.km(#i);
dtcns_line.hh = months.time(#i) / 60;
dtcns_line.mm = mod(months.time(#i), 60);
dtcns_line.v = round(
divide(
multiply(months.km(#i), 60, 15, 0),
months.time(#i),
15, 11), 1);
end;
else
dtcns_line.hs = ' ';
write file(outfile) from(line);
end;
write file(outfile) from(dtcns_sep);
end print_monthly_totals;
1/**********************************************************************
* PRINT_YEARLY_TOTALS: *
* *
* Print a summary table for all calendar years *
* *
* The table contains one row for every year, and every row contains *
* the following columns: *
* *
* - Year - the calendar year *
* - #D - the number of days hitched during the year *
* - #C - the number of rides in the year *
* - KM - the total distance for the year *
* - Time - the total time for the year *
* - V= - the average speed for the year *
* - Qual - the quality for the year *
**********************************************************************/
print_yearly_totals: proc;
dcl 1 filler static,
2 filler char (16) init ('YEAR LINES '),
2 year_sep char (121)
init ((' +------+-----+-----+-----+-----+')),
2 year_init char (121)
init ((' | | | | | |')),
2 year_head char (121)
init ((' | Year | T | R | T | R |'));
dcl 1 year_line based(line_ptr),
2 filler char (3),
2 year pic 'zzz9',
2 filler char (3),
2 trip_ride(2),
3 trip pic 'zz9',
3 filler char (3),
3 ride pic 'zz9',
3 filler char (3);
dcl prequal fixed (15,4);
/*+-------------------------------------------------------------------+
| Start of executable code for print_yearly_totals |
+------------------------------------------------------------------*/
write file(outfile) from(iline);
write file(outfile) from(tryr_sep);
line = tryr_head;
substr(line, 4, 4) = 'Year';
write file(outfile) from(line);
write file(outfile) from(tryr_sep);
line = tryr_init;
1 do year_ptr = year_top repeat year_nxt
while(year_ptr ^= sysnull());
prequal = divide(multiply(year_list.km, year_list.km, 15, 2),
multiply(year_list.#d, year_list.#r, 15, 0),
15, 4);
prequal = multiply(prequal,
year_list.#d + year_list.#r, 15, 4);
year_list.qual = round(
divide(prequal,
divide(year_list.time, 60, 15, 10),
15, 4), 0);
tryr_line = year_list, by name;
tryr_line.trip = year_list.year;
tryr_line.hh = year_list.time / 60;
tryr_line.mm = mod(year_list.time, 60);
tryr_line.v = round(
divide(
multiply(year_list.km, 60, 15, 0),
year_list.time, 15, 11), 1);
tryr_line.d = round(
divide(year_list.km, year_list.#d, 7, 2), 1);
tryr_line.r = round(
divide(year_list.km, year_list.#r, 7, 2), 1);
tryr_line.rd = round(
divide(year_list.#r, year_list.#d, 7, 3), 2);
write file(outfile) from(line);
end;
write file(outfile) from(tryr_sep);
1 /*------------------------------------------------------------------+
| Print table of trips and rides per year |
+------------------------------------------------------------------*/
write file(outfile) from(iline);
write file(outfile) from(year_sep);
write file(outfile) from(year_head);
write file(outfile) from(year_sep);
line = year_init;
do year_ptr = year_top repeat year_nxt
while(year_ptr ^= sysnull());
year_line = year_list, by name;
write file(outfile) from(line);
end;
write file(outfile) from(year_sep);
end print_yearly_totals;
1/**********************************************************************
* PRINT_DAYS_USED: *
* *
* Print use of days per calendar year *
**********************************************************************/
print_days_used: proc(mode);
dcl mode char (1);
dcl 1 filler static,
2 filler char (16) init ('DAYS LINES '),
2 days_sep char (121)
init ((' +' || (13)'-----+')),
2 days_init char (121)
init ((' | Day |' || (12)' - |'));
dcl 1 days_line based(line_ptr),
2 filler char (3),
2 day pic 'zz9',
2 filler char (3),
2 cdays(12),
3 #d pic 'zz9',
3 nohitch char (1),
3 filler char (2);
dcl pc_days(12,0:31) fixed bin (31) based(pc_ptr);
dcl #i fixed bin (31);
dcl #j fixed bin (31);
dcl pc_ptr ptr init (addr(lift_work.cdays));
/*+-------------------------------------------------------------------+
| Start of executable code for print_days_used |
+------------------------------------------------------------------*/
if mode = 'C' then
write file(outfile) from(pline);
else
do;
pc_ptr = addr(lift_work.pdays);
write file(outfile) from(iline);
end;
write file(outfile) from(days_sep);
line = days_init;
do #i = 1 to 12;
string(days_line.#d(#i)) = lift_static.month(#i);
end;
write file(outfile) from(line);
write file(outfile) from(days_sep);
1 do #i = 1 to hbound(pc_days, 2), 0;
line = days_init;
if #i ^= 0 then
days_line.day = #i;
else
if mode = 'C' then
string(days_line.day) = 'Use';
else
string(days_line.day) = 'Tot';
do #j = 1 to hbound(pc_days, 1);
if pc_days(#j, #i) ^= 0 then
do;
days_line.#d(#j) = pc_days(#j, #i);
if #i ^= 0 then
if mode = 'C' then
do;
pc_days(#j, 0) = pc_days(#j, 0) + 1;
if lift_work.pdays(#j, #i) = 0 then
days_line.nohitch(#j) = '*';
end;
else
pc_days(#j, 0) = pc_days(#j, 0) + pc_days(#j, #i);
end;
else
if #i > 29 then
select(#j);
when (4,
6,
9,
11)
if #i > 30 then
string(days_line.#d(#j)) = ' ';
when (2)
string(days_line.#d(#j)) = ' ';
other;
end;
end;
if #i = 0 then
write file(outfile) from(days_sep);
write file(outfile) from(line);
end;
write file(outfile) from(days_sep);
end print_days_used;
1/**********************************************************************
* DISTANCE_OVER_CONSECUTIVE_DAYS: *
* *
* This procedure scans the list of days to determine the maximum *
* distance over a number of consecutive calendar days. *
**********************************************************************/
distance_over_consecutive_days: proc;
dcl 1 filler static,
2 filler char (16) init ('CONSECUTIVE DAYS'),
2 consec(16) fixed bin (31)
init (1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16);
dcl 1 cons,
2 data(0:8),
3 #mima fixed bin (31),
3 l_max fixed (9,1),
3 t_max fixed (9),
3 filler char (10),
3 fptr(2) ptr,
2 jdn fixed bin (31);
dcl window_top ptr;
dcl #i fixed bin (31);
dcl #j fixed bin (31);
dcl 1 fast based,
2 nxt ptr,
2 filler char (4),
2 trip fixed bin (31),
2 ride fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for distance_over_consecutive_days |
+------------------------------------------------------------------*/
write file(outfile) from(iline);
write file(outfile) from(ride_sep);
line = ride_head_d;
substr(line, 4, 6) = 'L+ #CD';
write file(outfile) from(line);
write file(outfile) from(ride_sep);
line = ride_init;
1 do #i = 1 to hbound(consec, 1) by hbound(cons.#mima, 1);
cons.data = imini;
do day_ptr = td_top repeat td_nxt
while(day_ptr ^= sysnull());
window_top = day_ptr;
cons(0).#mima = 1;
cons(0).l_max = day_list.km;
cons(0).t_max = day_list.time;
cons(0).fptr(1),
cons(0).fptr(2) = day_ptr;
cons.jdn = day_list.jdn;
do day_ptr = td_nxt repeat td_nxt
while(day_ptr ^= sysnull() &
day_list.jdn = cons.jdn + 1)
until(day_ptr = sysnull());
window_top = day_ptr;
cons(0).#mima = cons(0).#mima + 1;
cons(0).l_max = cons(0).l_max + day_list.km;
cons(0).t_max = cons(0).t_max + day_list.time;
cons(0).fptr(2) = day_ptr;
cons.jdn = day_list.jdn;
end;
if cons(0).#mima >= consec(#i) &
cons(0).#mima <= consec(#i + hbound(cons.#mima, 1) - 1) then
do;
#j = mod(cons(0).#mima - 1, hbound(cons.#mima, 1)) + 1;
if cons(0).l_max > cons(#j).l_max |
(cons(0).l_max = cons(#j).l_max &
cons(0).t_max < cons(#j).t_max) then
cons(#j).data = cons(0).data;
end;
day_ptr = window_top;
end;
1 do #j = 1 to hbound(cons.#mima, 1);
if cons(#j).#mima ^= 0 then
do;
ride_line = cons(#j).data, by name;
ride_line.t_max_hh = cons(#j).t_max / 60;
ride_line.t_max_mm = mod(cons(#j).t_max, 60);
ride_line.f_max = round(
divide(
multiply(cons(#j).l_max, 60, 15, 0),
cons(#j).t_max, 7, 4), 1);
ride_line.fasts(1) = cons(#j).fptr(1) -> fast, by name;
ride_line.fasts(2) = cons(#j).fptr(2) -> fast, by name;
write file(outfile) from(line);
end;
end;
end;
write file(outfile) from(ride_sep);
end distance_over_consecutive_days;
1/**********************************************************************
* TRIP_YEAR_TYPE: *
* *
* This procedure collects the minima and maxima per type for a single *
* trip or year. *
**********************************************************************/
trip_year_type: proc;
dcl #i fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for trip_year_type |
+------------------------------------------------------------------*/
@type = '1'b;
outfile = liftout;
do #i = 1 to length(pickup_t) by 4;
minmax = iminmax;
heading = substr(pickup_t, #i, 4);
/*----------------------------------------------------------------+
| Start at the first ride for the trip or year |
+----------------------------------------------------------------*/
select;
when (@trip) lift_ptr = tr_top;
when (@year) lift_ptr = yr_top;
other lift_ptr = sysnull();
end;
/*----------------------------------------------------------------+
| Find the first required type for this trip or year |
+----------------------------------------------------------------*/
do lift_ptr = lift_ptr repeat ll_nxt
while(lift_ptr ^= sysnull())
until(lift_list.type = heading);
end;
1 select;
when (@trip)
do lift_ptr = lift_ptr repeat tl_nxt
while(lift_ptr ^= sysnull() &
lift_list.trip = #save_trip);
if lift_list.split = ' ' then
call process_min_max(1,
lift_list.km,
lift_list.time,
lift_list.vx);
end;
when (@year)
do lift_ptr = lift_ptr repeat tl_nxt
while(lift_ptr ^= sysnull() &
lift_list.year = #save_year);
if lift_list.split = ' ' then
call process_min_max(1,
lift_list.km,
lift_list.time,
lift_list.vx);
end;
other;
end;
if minmax(1).#mima ^= 0 then
call print_min_max('Ride');
end;
write file(outfile) from(pline);
call print_and_delete_ttot_list();
@type = '0'b;
end trip_year_type;
1/**********************************************************************
* TRIP_YEAR_CNTY: *
* *
* This procedure collects the minima and maxima per country for a *
* single trip or year. *
**********************************************************************/
trip_year_cnty: proc;
dcl save_fast_top ptr init (fast_top);
dcl save_fast_end ptr init (fast_end);
dcl 1 cwaits(0:3),
2 #w fixed bin (31),
2 wtime fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for trip_year_cnty |
+------------------------------------------------------------------*/
outfile = liftout;
fast_top = sysnull();
fast_end = addr(fast_top);
cwaits = swaits;
@cnty = '1'b;
call cnty_sub();
@cnty = '0'b;
swaits = cwaits;
fast_top = save_fast_top;
fast_end = save_fast_end;
end trip_year_cnty;
1/**********************************************************************
* CNTY_SUB: *
* *
* This procedure processes the totals per country. It is called for *
* the summary, for each individual trip and for each year. *
**********************************************************************/
cnty_sub: proc;
dcl 1 filler static,
2 filler char (16) init ('COUNTRY LINES '),
2 cnty_sep char (121)
init ((' +------+------+----------+---------+------' ||
'-+---------+------+----------+---------+-------+')),
2 cnty_init char (121)
init ((' | | - | - | : - | -' ||
' | - | - | - | : - | - |')),
2 cnty_head char (121)
init ((' | Cnty | #I | KM | Time | V=' ||
' | #E | # | KM | Time | V= |'));
dcl 1 cnty_line based(line_ptr),
2 filler char (3),
2 head char (4),
2 filler char (3),
2 int,
3 #r pic 'zzz9',
3 filler char (3),
3 km pic '(5)z9v.9',
3 filler char (3),
3 hh pic 'zzz9',
3 hs char (1),
3 mm pic '99',
3 filler char (3),
3 v pic 'zz9v.9',
2 filler char (3),
2 ext,
3 #r pic 'zzz9v.99',
3 filler char (3),
3 #c pic 'zzz9',
3 filler char (3),
3 km pic '(5)z9v.9',
3 filler char (3),
3 hh pic 'zzz9',
3 hs char (1),
3 mm pic '99',
3 filler char (3),
3 v pic 'zz9v.9';
dcl #i fixed bin (31);
dcl @done bit (1) aligned;
dcl @split bit (1) aligned;
1/*+-------------------------------------------------------------------+
| Start of executable code for cnty_sub |
+------------------------------------------------------------------*/
minmax = iminmax;
swaits = iwait;
do cnty_ptr = cnty_top repeat cnty_nxt
while(cnty_ptr ^= sysnull());
wwait = iwait;
waits = iwait;
w8wtimesq = 0;
heading = cnty_list.cnty;
line = cnty_init;
cnty_line.head = heading;
if @in_cnty then
hours = 0;
/*----------------------------------------------------------------+
| Start at the first ride for the trip or year |
+----------------------------------------------------------------*/
select;
when (@trip) lift_ptr = tr_top;
when (@year) lift_ptr = yr_top;
other lift_ptr = cl_top;
end;
/*----------------------------------------------------------------+
| Find the first required country |
+----------------------------------------------------------------*/
do lift_ptr = lift_ptr repeat lift_nxt
while(lift_ptr ^= sysnull())
until(lift_list.cnty = cnty_list.cnty);
end;
1 /*----------------------------------------------------------------+
| Process countries |
+----------------------------------------------------------------*/
@done = '0'b;
do lift_ptr = lift_ptr repeat cl_nxt
while(lift_ptr ^= sysnull())
until(@done);
@split = lift_list.split = '*';
#i = 1 + @split;
if (^@nested |
(@nested &
(@trip & lift_list.trip = #save_trip |
@year & lift_list.year = #save_year))) then
do;
call process_cnty();
call process_min_max(#i,
lift_list.km,
lift_list.time,
lift_list.vx);
if #i = 1 then
minmax(#i).#rc = cnty_list.#ir;
else
minmax(#i).#rc = cnty_list.#er;
if ^@split |
substr(lift_list.cday, 3, 1) = 'a' then
do;
call process_wait();
if @in_cnty then
call process_cnty_hours();
end;
end;
@done = (@nested &
(@trip & lift_list.trip > #save_trip |
@year & lift_list.year > #save_year));
end;
1 if cnty_list.int.#c > 0 then
do;
cnty_line.int.#r = cnty_list.#ir;
cnty_line.int.km = cnty_list.int.km;
cnty_line.int.hh = cnty_list.int.time / 60;
cnty_line.int.mm = mod(cnty_list.int.time, 60);
if cnty_list.int.time ^= 0 then
cnty_line.int.v = round(
divide(
multiply(cnty_list.int.km, 60, 15, 0),
cnty_list.int.time, 15, 11), 1);
minmax(3).l_tot = minmax(3).l_tot + cnty_list.int.km;
minmax(3).t_tot = minmax(3).t_tot + cnty_list.int.time;
minmax(3).#rc = minmax(3).#rc + cnty_list.#ir;
cnty_list.int = idata;
cnty_list.pick_up = '0'b;
end;
else
cnty_line.int.hs = ' ';
cnty_list.#ir = 0;
cnty_list.#i_nat = 0;
if cnty_list.ext.#c > 0 then
do;
cnty_line.ext.#r = round(cnty_list.#er, 2);
cnty_line.ext.#c = cnty_list.ext.#c;
cnty_line.ext.km = cnty_list.ext.km;
cnty_line.ext.hh = cnty_list.ext.time / 60;
cnty_line.ext.mm = mod(cnty_list.ext.time, 60);
if cnty_list.ext.time ^= 0 then
cnty_line.ext.v = round(
divide(
multiply(cnty_list.ext.km, 60, 15, 0),
cnty_list.ext.time, 15, 11), 1);
minmax(4).#mima = minmax(4).#mima + cnty_list.ext.#c;
minmax(4).l_tot = minmax(4).l_tot + cnty_list.ext.km;
minmax(4).t_tot = minmax(4).t_tot + cnty_list.ext.time;
minmax(4).#rc = minmax(4).#rc + cnty_list.#er;
cnty_list.ext = idata;
cnty_list.pick_up = '0'b;
end;
else
cnty_line.ext.hs = ' ';
cnty_list.#er = 0;
cnty_list.#e_nat = 0;
1 alloc fast_list;
fast_end -> fast_nxt,
fast_end = fast_ptr;
fast_list.ftype = 1;
if minmax(1).#mima ^= 0 then
call print_min_max('Ride');
if minmax(2).#mima ^= 0 then
call print_min_max('Day ');
minmax(1) = iminmax;
minmax(2) = iminmax;
if ^@nested then
do;
call print_wait();
call print_waitsd();
call print_hours();
call print_deplocs_d(cnty_list.cd_ptr);
call print_deplocs_w(cnty_list.cd_ptr);
call print_bocro_cnty();
write file(outfile) from(iline);
write file(outfile) from(min_max_csep);
write file(outfile) from(min_max_chead);
write file(outfile) from(min_max_csep);
if ctot_toq = sysnull() then
ctot_toq = ctot_top;
do ctot_ptr = ctot_toq repeat ctot_nxt
while(ctot_ptr ^= sysnull());
if substr(ctot_list.cline, 4, 4) = heading then
do;
line = ctot_list.cline;
substr(line, 4, 3) = ctot_list.cid;
ctot_toq = ctot_ptr;
write file(outfile) from(line);
end;
end;
write file(outfile) from(min_max_csep);
end;
call create_wait_summary(cnty_list.cnty);
if ^@nested then
cnty_list.wait = waits(8);
end;
1 if ^@nested then
do;
outfile = summout;
write file(outfile) from(pline);
end;
else
do;
write file(outfile) from(iline);
call print_and_delete_ctot_list();
write file(outfile) from(iline);
end;
if @trip then
call print_copa();
write file(outfile) from(cnty_sep);
write file(outfile) from(cnty_head);
write file(outfile) from(cnty_sep);
do fast_ptr = fast_top repeat fast_nxt
while(fast_ptr ^= sysnull());
if fast_list.ftype = 1 then
write file(outfile) from(fast_list.fline);
end;
write file(outfile) from(cnty_sep);
line = cnty_init;
cnty_line.head = 'Tot';
if minmax(3).l_tot ^= 0 then
do;
cnty_line.int.#r = minmax(3).#rc;
cnty_line.int.km = minmax(3).l_tot;
cnty_line.int.hh = minmax(3).t_tot / 60;
cnty_line.int.mm = mod(minmax(3).t_tot, 60);
if minmax(3).t_tot ^= 0 then
cnty_line.int.v = round(
divide(
multiply(minmax(3).l_tot, 60, 15, 0),
minmax(3).t_tot, 15, 11), 1);
end;
else
cnty_line.int.hs = ' ';
1 if minmax(4).l_tot ^= 0 then
do;
cnty_line.ext.#r = round(minmax(4).#rc, 2);
cnty_line.ext.#c = minmax(4).#mima;
cnty_line.ext.km = minmax(4).l_tot;
cnty_line.ext.hh = minmax(4).t_tot / 60;
cnty_line.ext.mm = mod(minmax(4).t_tot, 60);
if minmax(4).t_tot ^= 0 then
cnty_line.ext.v = round(
divide(
multiply(minmax(4).l_tot, 60, 15, 0),
minmax(4).t_tot, 15, 11), 1);
end;
else
cnty_line.ext.hs = ' ';
write file(outfile) from(line);
write file(outfile) from(cnty_sep);
call print_wait_summary('0'b);
heading = '';
end cnty_sub;
1/**********************************************************************
* TRIP_YEAR_NAT: *
* *
* This procedure collects the minima and maxima per nationality for a *
* single trip or year. *
**********************************************************************/
trip_year_nat: proc;
dcl #i fixed bin (31);
/*+-------------------------------------------------------------------+
| Start of executable code for trip_year_nat |
+------------------------------------------------------------------*/
@nat = '1'b;
outfile = liftout;
do #i = 1 to length(pickup_n) by 4;
minmax = iminmax;
heading = substr(pickup_n, #i, 4);
/*----------------------------------------------------------------+
| Start at the first ride for the trip or year |
+----------------------------------------------------------------*/
select;
when (@trip) lift_ptr = tr_top;
when (@year) lift_ptr = yr_top;
other lift_ptr = sysnull();
end;
/*----------------------------------------------------------------+
| Find the first required nationality for this trip or year |
+----------------------------------------------------------------*/
do lift_ptr = lift_ptr repeat ll_nxt
while(lift_ptr ^= sysnull())
until(lift_list.nat = heading);
end;
1 select;
when (@trip)
do lift_ptr = lift_ptr repeat nl_nxt
while(lift_ptr ^= sysnull() &
lift_list.trip = #save_trip);
if lift_list.split = ' ' then
call process_min_max(1,
lift_list.km,
lift_list.time,
lift_list.vx);
end;
when (@year)
do lift_ptr = lift_ptr repeat nl_nxt
while(lift_ptr ^= sysnull() &
lift_list.year = #save_year);
if lift_list.split = ' ' then
call process_min_max(1,
lift_list.km,
lift_list.time,
lift_list.vx);
end;
other;
end;
if minmax(1).#mima ^= 0 then
call print_min_max('Ride');
end;
write file(outfile) from(iline);
call print_and_delete_ntot_list();
@nat = '0'b;
end trip_year_nat;
1/**********************************************************************
* PRINT_AND_DELETE_TTOT_LIST: *
* *
* This procedure prints the list of maxima/minima/averages for the *
* types. *
**********************************************************************/
print_and_delete_ttot_list: proc;
call print_min_max_box('Type');
do ttot_ptr = ttot_top repeat ttot_nxt
while(ttot_ptr ^= sysnull());
write file(outfile) from(ttot_list.tline);
end;
call print_min_max_box('B');
ttot_area = empty();
ttot_top = sysnull();
ttot_end = addr(ttot_top);
end print_and_delete_ttot_list;
1/**********************************************************************
* PRINT_AND_DELETE_CTOT_LIST: *
* *
* This procedure prints the list of maxima/minima/averages for the *
* countries. *
**********************************************************************/
print_and_delete_ctot_list: proc;
dcl 1 filler static,
2 filler char (16) init ('MIN_MAX LINES '),
2 min_max_csep char (121)
init ((' +------+---------+-------+-------+-------+--------' ||
'+--------+--------+-------+-------+-------+')),
2 min_max_chead char (121)
init ((' | Cnty | # | V+ | V- | V= | L+ ' ||
'| L- | L= | T+ | T- | T= |'));
dcl @first bit (1) init ('1'b) aligned;
/*+-------------------------------------------------------------------+
| Start of executable code for print_and_delete_ctot_list |
+------------------------------------------------------------------*/
write file(outfile) from(min_max_csep);
write file(outfile) from(min_max_chead);
write file(outfile) from(min_max_csep);
do ctot_ptr = ctot_top repeat ctot_nxt
while(ctot_ptr ^= sysnull());
if substr(ctot_list.cid, 1, 1) = 'I' then
write file(outfile) from(ctot_list.cline);
end;
do ctot_ptr = ctot_top repeat ctot_nxt
while(ctot_ptr ^= sysnull());
if substr(ctot_list.cid, 1, 1) = 'E' then
do;
if @first then
do;
@first = '0'b;
write file(outfile) from(min_max_csep);
end;
write file(outfile) from(ctot_list.cline);
end;
end;
write file(outfile) from(min_max_csep);
ctot_area = empty();
ctot_top = sysnull();
ctot_end = addr(ctot_top);
ctot_toq = sysnull();
end print_and_delete_ctot_list;
1/**********************************************************************
* PRINT_AND_DELETE_NTOT_LIST: *
* *
* This procedure prints the list of maxima/minima/averages for the *
* nationalities. *
**********************************************************************/
print_and_delete_ntot_list: proc;
dcl #i fixed bin (31) init (0);
dcl @ty bit (1) init ((@trip | @year)) aligned;
dcl @first bit (1) init ('1'b) aligned;
dcl @none bit (1) init ('1'b) aligned;
dcl ntot_init char (121) static
init ((' | - | - | - | - | - | - ' ||
'| - | - | - | - | - |'));
/*+-------------------------------------------------------------------+
| Start of executable code for print_and_delete_ntot_list |
+------------------------------------------------------------------*/
call print_min_max_box('Nat ');
do ntot_ptr = ntot_top repeat ntot_nxt
while(ntot_ptr ^= sysnull());
if (^@ty & index(a_cnty, substr(nline, 4, 4) || ' ') ^= 0) |
(@ty & #i < #pu_sep) then
do;
@none = '0'b;
write file(outfile) from(ntot_list.nline);
end;
else
ntot_list.nid = '2';
#i = #i + 1;
end;
if @none then
write file(outfile) from(ntot_init);
1 do ntot_ptr = ntot_top repeat ntot_nxt
while(ntot_ptr ^= sysnull());
if ntot_list.nid = '2' then
do;
if @first then
do;
@first = '0'b;
call print_min_max_box('B=');
end;
write file(outfile) from(ntot_list.nline);
end;
end;
call print_min_max_box('B');
ntot_area = empty();
ntot_top = sysnull();
ntot_end = addr(ntot_top);
end print_and_delete_ntot_list;
1/**********************************************************************
* FREE_FAST_LIST: *
* *
* Free the list of fast_list items *
**********************************************************************/
free_fast_list: proc;
do fast_ptr = fast_top repeat nxt_ptr
while(fast_ptr ^= sysnull());
nxt_ptr = fast_nxt;
free fast_list;
end;
fast_top = sysnull();
fast_end = addr(fast_top);
end free_fast_list;
1/**********************************************************************
* CJ: *
* *
* Convert a date to a Julian Day Number *
**********************************************************************/
cj: proc(fld, flm, fly) returns(fixed (7));
dcl fld float (16);
dcl flm float (16);
dcl fly float (16);
/*+-------------------------------------------------------------------+
| Start of executable code for cj |
+------------------------------------------------------------------*/
fly = fly + (flm - 2.85) / 12;
return(floor(
floor(
floor(367 * fly) - 1.75 * floor(fly) + fld) -
0.75 * floor(fly / 100)) + 1721115);
end cj;
1/**********************************************************************
* JC: *
* *
* Convert a Julian Day Number to a date *
**********************************************************************/
jc: proc(jdn, dd, mm, yyyy);
dcl jdn fixed (7);
dcl dd fixed (3);
dcl mm fixed (3);
dcl yyyy fixed (5);
dcl flc float (16);
dcl fln float (16);
/*+-------------------------------------------------------------------+
| Start of executable code for jc |
+------------------------------------------------------------------*/
fln = jdn - 1721119.2;
flc = trunc(fln / 36524.25);
fln = fln + flc - trunc(flc / 4);
yyyy = trunc(fln / 365.25);
fln = fln - trunc(365.25 * yyyy) - 0.3;
mm = trunc(fln / 30.6);
dd = trunc(fln - 30.6 * mm + 1);
if mm > 9 then
do;
mm = mm - 9;
yyyy = yyyy + 1;
end;
else
mm = mm + 3;
end jc;
1/**********************************************************************
* PRINT_HOURS: *
* *
* This procedure prints the distrubution of departure times per day *
**********************************************************************/
print_hours: proc;
dcl 1 filler static,
2 filler char (16) init ('HOUR LINES '),
2 hour_sep char (121)
init ((' +---------+------+------+------+------+------+' ||
'------+------+------+')),
2 hour_init char (121)
init ((' | - 0:00 | - | - | - | - | - |' ||
' - | - | - |')),
2 hour_head char (121)
init ((' | | Mon | Tue | Wed | Thu | Fri |' ||
' Sat | Sun | Tot |'));
dcl 1 hour_line based(line_ptr),
2 filler char (3),
2 hour,
3 filler char (2),
3 hh pic 'z9',
3 filler char (3),
2 filler char (3),
2 day(0:7),
3 #c pic 'zzz9',
3 filler char (3);
dcl 1 l_iv,
2 cnty char (4) init (cnty_list.cnty),
2 #c(5) fixed bin (31) init ((5)0);
dcl #i fixed bin (31);
dcl #j fixed bin (31);
dcl #s fixed bin (31);
1/*+-------------------------------------------------------------------+
| Start of executable code for print_hours |
+------------------------------------------------------------------*/
if ^@in_cnty then
write file(outfile) from(pline);
write file(outfile) from(hour_sep);
write file(outfile) from(hour_head);
/*------------------------------------------------------------------+
| Sum departure times per day |
+------------------------------------------------------------------*/
do #i = lbound(hours, 1) to hbound(hours, 1);
hours(#i, 24) = sum(hours(#i, *));
end;
/*------------------------------------------------------------------+
| Sum departure times per hour |
+------------------------------------------------------------------*/
do #i = lbound(hours, 2) to hbound(hours, 2);
#s = sum(hours(*, #i));
hours(7, #i) = #s;
#j = #i / 6 + 1;
l_iv.#c(#j) = l_iv.#c(#j) + #s;
if @in_cnty then
g_iv.#c(#j) = g_iv.#c(#j) + #s;
end;
if @in_cnty then
do;
line = iv_init;
iv_line.cnty = l_iv.cnty;
do #i = 1 to hbound(l_iv.#c, 1);
if l_iv.#c(#i) ^= 0 then
iv_line.#c(#i) = l_iv.#c(#i);
end;
alloc vtot_list;
vtot_end -> vtot_nxt,
vtot_end = vtot_ptr;
end;
1 do #i = lbound(hours, 2) to hbound(hours, 2);
line = hour_init;
hour_line.hh = #i + 1;
if #i = hbound(hours, 2) then
string(hour_line.hour) = 'Total';
do #j = lbound(hours, 1) to hbound(hours, 1);
if hours(#j, #i) ^= 0 then
hour_line.#c(#j) = hours(#j, #i);
end;
if #i = 0 |
#i = 6 |
#i = 12 |
#i = 18 |
#i = 24 then
write file(outfile) from(hour_sep);
write file(outfile) from(line);
end;
write file(outfile) from(hour_sep);
end print_hours;
1/**********************************************************************
* PROCESS_TIMES: *
* *
* This procedure accumulates the different times per ride into a *
* temporary list. At the end of each trip the temporary list, with *
* the times per ride is consolidated into a single item per day, and *
* this is then transferred to the day list. *
**********************************************************************/
process_times: proc;
dcl #s fixed bin (31) init (0);
dcl delta fixed bin (31) init (0);
dcl @split bit (1) aligned;
dcl day_prv ptr init (sysnull());
dcl ld_ptr ptr;
dcl slift_ptr ptr;
dcl #tza fixed bin (31);
dcl #tzd fixed bin (31);
dcl 1 filler static,
2 init_s_arr,
3 type char (4) init ('00000000'x),
3 dtime fixed bin (31) init (0),
3 atime fixed bin (31) init (-1),
3 wtime fixed bin (31) init (