/* 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 (