1 OPTION TYPE=EXPLICIT ! ! BASIC_ZILL_MOST_REPORT.BAS ! ! Stand alone program to report the top 10 ! drawing and mega numbers by hit count. ! %INCLUDE "MEGA_INC:MEGA_RECS.INC" ! our record definitions %INCLUDE "LIB$ROUTINES" %FROM %LIBRARY !;;;;;;;;;; ! Constants !;;;;;;;;;; DECLARE BYTE CONSTANT dstat_chan% = 7% DECLARE BYTE CONSTANT mstat_chan% = 8% DECLARE BYTE CONSTANT rpt_chan% = 11% DECLARE BYTE CONSTANT elm_count% = 52% DECLARE STRING CONSTANT drawing_stats$ = "DRAWING_STATS", & mega_stats$ = "MEGA_STATS", & report_name$ = "ZILL_MOST.RPT" !;;;;;;;;;; ! Maps !;;;;;;;;;; MAP (LOCAL_MAP) STRING TRANSLATED_NAME$ = 255% MAP (D_STAT_MAP) ZILLIONARE_STATS_RECORD D_STAT MAP (M_STAT_MAP) ZILLIONARE_STATS_RECORD M_STAT !;;;;;;;;;; ! Local Variables !;;;;;;;;;; DECLARE BYTE B_DONE% DECLARE WORD W_X% DECLARE LONG L_X%, L_ERR%, L_END% DECLARE STRING WORK_STR$, LOG_TXT$ DECLARE ZILLIONARE_STATS_RECORD SCRATCH_STAT DIM ZILLIONARE_STATS_RECORD D_STATS( elm_count%) DIM ZILLIONARE_STATS_RECORD M_STATS( elm_count%) !;;;;;;;;;; ! Main Logic !;;;;;;;;;; 100 L_ERR% = 0% GOSUB A900_FILL_IN_LOGICALS GOSUB A910_OPEN_FILES IF L_ERR% = 0% THEN GOSUB A930_READ_TO_EOF GOSUB A960_SORT_ARRAYS GOSUB A940_GENERATE_REPORT END IF GOTO PROGRAM_EXIT 900 !;;;;;;;;;; ! Subroutine to fill in logical values ! Ordinarily developers simply "assume" that either ! logicals have been defined or do so in a job stream ! but this will allow the demonstration of service calls. !;;;;;;;;;; A900_FILL_IN_LOGICALS: WORK_STR$ = drawing_stats$ TRANSLATED_NAME$ = " " ! destination has to be pre-allocated W_X% = 0% L_X% = LIB$GET_LOGICAL( WORK_STR$, TRANSLATED_NAME$, W_X%,,,,) IF LEN( TRM$( TRANSLATED_NAME$)) < 1 THEN LOG_TXT$ = drawing_stats$ + ".IDX" L_X% = LIB$SET_LOGICAL( WORK_STR$, LOG_TXT$,,,) END IF WORK_STR$ = mega_stats$ TRANSLATED_NAME$ = " " ! destination has to be pre-allocated W_X% = 0% L_X% = LIB$GET_LOGICAL( WORK_STR$, TRANSLATED_NAME$, W_X%,,,,) IF LEN( TRM$( TRANSLATED_NAME$)) < 1 THEN LOG_TXT$ = mega_stats$ + ".IDX" L_X% = LIB$SET_LOGICAL( WORK_STR$, LOG_TXT$,,,) END IF RETURN 910 !;;;;;;;;;; ! Subroutine to open indexed files !;;;;;;;;;; A910_OPEN_FILES: WHEN ERROR IN L_ERR% = 0% OPEN drawing_stats$ FOR INPUT AS FILE #dstat_chan%, & ORGANIZATION INDEXED FIXED, & ALLOW MODIFY, & RECORDTYPE FORTRAN, & RECORDSIZE zillionare_stats_record_size, & PRIMARY KEY D_STAT::ELM_NO, & MAP D_STAT_MAP USE L_ERR% = ERR PRINT "Unable to open drawing stat input file"; drawing_stats$ PRINT "Error: ";L_ERR%;" ";ERT$( L_ERR%) END WHEN RETURN IF L_ERR% <> 0% WHEN ERROR IN L_ERR% = 0% OPEN mega_stats$ FOR INPUT AS FILE #mstat_chan%, & ORGANIZATION INDEXED FIXED, & ALLOW MODIFY, & RECORDTYPE FORTRAN, & RECORDSIZE zillionare_stats_record_size, & PRIMARY KEY M_STAT::ELM_NO, & MAP M_STAT_MAP USE L_ERR% = ERR PRINT "Unable to open mega stat input file"; mega_stats$ PRINT "Error: ";L_ERR%;" ";ERT$( L_ERR%) END WHEN RETURN IF L_ERR% <> 0% WHEN ERROR IN L_ERR% = 0% OPEN report_name$ FOR OUTPUT AS FILE # rpt_chan%, & RECORDTYPE LIST, & ACCESS WRITE USE L_ERR% = ERR PRINT "Error opening report file for output" PRINT "Error: ";L_ERR%;" ";ERT$( L_ERR%) END WHEN RETURN 930 !;;;;;;;;;; ! Subroutine to load up the basic stats of hit counts !;;;;;;;;;; A930_READ_TO_EOF: ! ! We don't care about the order or initial load ! just read sequentially ! L_ERR% = 0% L_X% = 0% WHILE L_ERR% = 0% WHEN ERROR IN GET #mstat_chan% L_X% = L_X% + 1% M_STATS( L_X%) = M_STAT USE L_ERR% = ERR END WHEN NEXT IF L_X% <> elm_count% THEN PRINT "Only ";L_X%;" records out of ";elm_count%;" loaded" END IF L_ERR% = 0% L_X% = 0% WHILE L_ERR% = 0% WHEN ERROR IN GET #dstat_chan% L_X% = L_X% + 1% D_STATS( L_X%) = D_STAT USE L_ERR% = ERR END WHEN NEXT IF L_X% <> elm_count% THEN PRINT "Only ";L_X%;" records out of ";elm_count%;" loaded" END IF RETURN 940 !;;;;;;;;;; ! Subroutine to generate the report ! No need for page breaks when will will have less ! than the number of lines a page can hold. !;;;;;;;;;; A940_GENERATE_REPORT: WORK_STR$ = "Most Hits Report" L_X% = 40% - (LEN( WORK_STR$) / 2%) ! size needed to center !;;;;; ! First Heading line !;;;;; PRINT #rpt_chan%, "DATE: ";DATE$(0%); PRINT #rpt_chan%, TAB( L_X%);WORK_STR$;TAB( 71%);"PAGE: "; PRINT #rpt_chan%, FORMAT$( 1%, "###") PRINT #rpt_chan%, " " WORK_STR$ = "Regular Drawing Numbers" L_X% = 40% - (LEN( WORK_STR$) / 2%) ! size needed to center PRINT #rpt_chan%, TAB( L_X%);WORK_STR$ PRINT #rpt_chan%, " " PRINT #rpt_chan%, " " !;;;;; ! Column headings !;;;;; PRINT #rpt_chan%, "No Hits Since Pct_hits Ave_btwn" PRINT #rpt_chan%, "-- ---- ----- -------- --------" FOR L_X% = 1% TO 10% PRINT #rpt_chan% USING "## #### #### ##.### ##.###", & D_STATS( L_X%)::ELM_NO, & D_STATS( L_X%)::HIT_COUNT, & D_STATS( L_X%)::SINCE_LAST, & D_STATS( L_X%)::PCT_HITS, & D_STATS( L_X%)::AVE_BTWN NEXT L_X% PRINT #rpt_chan%, " " PRINT #rpt_chan%, " " PRINT #rpt_chan%, " " WORK_STR$ = "Mega Numbers" L_X% = 40% - (LEN( WORK_STR$) / 2%) ! size needed to center PRINT #rpt_chan%, TAB( L_X%);WORK_STR$ PRINT #rpt_chan%, " " PRINT #rpt_chan%, " " !;;;;; ! Column headings !;;;;; PRINT #rpt_chan%, "No Hits Since Pct_hits Ave_btwn" PRINT #rpt_chan%, "-- ---- ----- -------- --------" FOR L_X% = 1% TO 10% PRINT #rpt_chan% USING "## #### #### ##.### ##.###", & M_STATS( L_X%)::ELM_NO, & M_STATS( L_X%)::HIT_COUNT, & M_STATS( L_X%)::SINCE_LAST, & M_STATS( L_X%)::PCT_HITS, & M_STATS( L_X%)::AVE_BTWN NEXT L_X% RETURN 960 !;;;;;;;;;; ! Subroutine to sort arrays so they are descending ! by SINCE_LAST. !;;;;;;;;;; A960_SORT_ARRAYS: B_DONE% = 0% L_END% = elm_count% WHILE B_DONE% = 0% L_X% = 1% B_DONE% = 1% ! assume each pass will be our last WHILE L_X% < L_END% IF M_STATS( L_X%)::HIT_COUNT < M_STATS( L_X%+1%)::HIT_COUNT THEN B_DONE% = 0% ! made a swap, have to look again SCRATCH_STAT = M_STATS( L_X%) M_STATS( L_X%) = M_STATS( L_X% + 1%) M_STATS( L_X%+1%) = SCRATCH_STAT END IF L_X% = L_X% + 1% NEXT ! ! At the end of each pass through this loop ! the smallest SINCE_LAST value will be at the ! bottom of the array. No since looking at it again. ! L_END% = L_END% - 1% NEXT L_END% = elm_count% ! reset the end B_DONE% = 0% ! reset done flag WHILE B_DONE% = 0% L_X% = 1% B_DONE% = 1% ! assume each pass will be our last WHILE L_X% < L_END% IF D_STATS( L_X%)::HIT_COUNT < D_STATS( L_X%+1%)::HIT_COUNT THEN B_DONE% = 0% ! made a swap, have to look again SCRATCH_STAT = D_STATS( L_X%) D_STATS( L_X%) = D_STATS( L_X% + 1%) D_STATS( L_X%+1%) = SCRATCH_STAT END IF L_X% = L_X% + 1% NEXT ! ! At the end of each pass through this loop ! the smallest SINCE_LAST value will be at the ! bottom of the array. No since looking at it again. ! L_END% = L_END% - 1% NEXT RETURN 32767 ! End of module PROGRAM_EXIT: WHEN ERROR IN CLOSE #mstat_chan% USE ! ignore error on close END WHEN WHEN ERROR IN CLOSE #dstat_chan% USE ! ignore error on close END WHEN WHEN ERROR IN CLOSE #rpt_chan% USE END WHEN WORK_STR$ = "EDIT/READ " + report_name$ L_X% = LIB$DO_COMMAND( WORK_STR$) END