home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / comm / Fido / Spot / Rexx / EchoStat.spot < prev    next >
Text File  |  1994-09-10  |  28KB  |  788 lines

  1. /***************************************************************************/
  2. /* EchoStat.spot (C) Phil O'Malley 1994, Fidonet: 2:250/107.96             */
  3. /*                                                                         */
  4. /* $VER: EchoStat [15.02.94]                                               */
  5. /***************************************************************************/
  6. /*                                                                         */
  7. /* Desc : A script which analyzes the messages held in an area and then    */
  8. /*        produces traffic report.                                         */
  9. /*                                                                         */
  10. /***************************************************************************/
  11. /*                                                                         */
  12. /* Usage: (1) Invoke from the CLI with Spot as a background task.          */
  13. /*                                                                         */
  14. /*              ie. rx >nil: rexx:EchoStat.spot                            */
  15. /*                                                                         */
  16. /*        (2) Or specify the desired syntax from the Spot ARexx menu.      */
  17. /*                                                                         */
  18. /***************************************************************************/
  19. /*                                                                         */
  20. /* Ctrl : By CLI parameters. These are:                                    */
  21. /*                                                                         */
  22. /*   NONODE      = Don't append the table concerning non-point origins.    */
  23. /*   NOSUBJECT   = Don't append the table concerning echomail subjects.    */
  24. /*   NOTRAFFIC   = Don't append the table concerning echomail traffic.     */
  25. /*                                                                         */
  26. /*   NOFLAG      = Don't display the flags in the output tables.           */
  27. /*   NOPOST      = Don't post the final output into the current area.      */
  28. /*                                                                         */
  29. /*   NTC <%>     = Alter the wasting bandwidth flag threshold to <%>.      */
  30. /*   XSQUOTE <%> = Alter the excessive quoting flag threshold to <%>.      */
  31. /*   TABLE <len> = Alter the table length (0 = no limits).                 */
  32. /*                                                                         */
  33. /*   OUT <file>  = Specify an output path for the ASCII report.            */
  34. /*                                                                         */
  35. /***************************************************************************/
  36.  
  37. address spot 
  38. options results
  39.  
  40. /***************************************************************************/
  41. /* Check for, and install if necessary, any libraries we need.             */
  42. /***************************************************************************/
  43.  
  44. if ~show(l, "traplist.library") then do
  45.   if ~addlib("traplist.library", 0, -30) then do
  46.     say "Please install the traplist.library in your libs: directory"
  47.   end
  48. end
  49.  
  50. /***************************************************************************/
  51. /* Define global variables                                                 */
  52. /***************************************************************************/
  53.  
  54. version = 'EchoStat 1.1'
  55.  
  56. /* Logical assigns */
  57.  
  58. true    = 1
  59. false   = 0
  60.  
  61. blank   = ''
  62. newline = '0a'x
  63.  
  64. /* File names. */
  65.  
  66. temp_file   = 'T:EchoStat.tmp'
  67. output_file = 'T:EchoStat.tmp'
  68.  
  69. /* Defaults. Can be overriden from the CLI. */
  70.  
  71. xsquoting_level  = 57.5
  72. newtopic_content = 37.5
  73. table_size       = 10
  74.  
  75. /***************************************************************************/
  76. /* Grab the command line and check to see if (crudely) valid.              */
  77. /***************************************************************************/
  78.  
  79. parse arg command_line
  80.  
  81. if command_line = "?" then do
  82.   say "Usage: rx EchoStat.spot [NOFLAG] [NONODE] [NOPOST] [NOSUBJECT] [NOTRAFFIC] [NTC %] [OUT <file>] [TABLE <length>] [XSQUOTE %]" ; exit
  83. end
  84.  
  85. /***************************************************************************/
  86. /* Main program. All procedures are called from here.                      */
  87. /***************************************************************************/
  88.  
  89. /* Make sure that any other requesters are closed. */
  90.  
  91. 'progressclose 1'
  92.  
  93. /* Parse the CLI. */
  94.  
  95. call parsecli()
  96.  
  97. /* Review the messagebase. */
  98.  
  99. call parse_statistics()
  100.  
  101. /* Now sort the report. All output from the procedures is sent back in
  102.    the form of a variable which is organised into the report later. */
  103.  
  104. if notraffic ~= true then do
  105.   report.1 = produce_traffic_statistics(table_size)
  106. end
  107.  
  108. if nosubject ~= true then do
  109.   report.2 = produce_subject_statistics(table_size)
  110. end
  111.  
  112. if nonode ~= true then do
  113.   report.3 = produce_node_statistics(table_size)
  114. end
  115.  
  116. /* Sort out the outputfile. */
  117.  
  118. call produce_report()
  119.  
  120. /* Now, if not overridden from the CLI, post the output as a message in the
  121.    current area. */
  122.  
  123. if nopost ~= true then do
  124.   'write TO "All" SUBJECT "Echo Stats: 'date(e)'" FILE "'output_file'" NOEDIT NOGUI REFLOW=OFF'
  125. end
  126.  
  127. exit
  128.  
  129. /***************************************************************************/
  130. /* ParseCLI(). Parse the command line.                                     */
  131. /***************************************************************************/
  132.  
  133. parsecli: procedure expose command_line noflag nonode nopost nosubject nosubject newtopic_content output_file table_size true xsquoting_level 
  134.  
  135.   /* Each element is separated by a space, thus we can parse them
  136.      with as if it was a simple sentence. */
  137.  
  138.   do i = 1 to words(command_line)
  139.  
  140.     if upper(word(command_line,i)) = "NOFLAG" then do
  141.       noflag = true
  142.     end
  143.  
  144.     if upper(word(command_line,i)) = "NONODE" then do
  145.       nonode = true
  146.     end
  147.  
  148.     if upper(word(command_line,i)) = "NOPOST" then do
  149.       nopost = true 
  150.     end
  151.  
  152.     if upper(word(command_line,i)) = "NOSUBJECT" then do
  153.       nosubject = true
  154.     end
  155.  
  156.     if upper(word(command_line,i)) = "NOTRAFFIC" then do
  157.       notraffic = true 
  158.     end
  159.  
  160.     if upper(word(command_line,i)) = "NTC" then do
  161.       newtopic_content = word(command_line,(i+1)) ; i = i +1
  162.     end
  163.  
  164.     if upper(word(command_line,i)) = "OUT" then do
  165.       output_file = word(command_line,(i+1)) ; i = i +1
  166.     end
  167.  
  168.     if upper(word(command_line,i)) = "TABLE" then do
  169.       table_size = word(command_line,(i+1)) ; i = i +1
  170.     end
  171.  
  172.     if upper(word(command_line,i)) = "XSQUOTE" then do
  173.       xsquoting_level = word(command_line,(i+1)) ; i = i +1
  174.     end
  175.  
  176.   end
  177.  
  178. return
  179.  
  180. /***************************************************************************/
  181. /* Produce_Report(). Create/append the output file.                        */
  182. /***************************************************************************/
  183.  
  184. produce_report: procedure expose report. newline output_file version
  185.  
  186.   /* This holds the organisational data for the report file. The report.x
  187.      variables are spooled into the file in the order designated allowing
  188.      greater flexibility than if just dumped into a log file. */
  189.  
  190.   report_format = "1 2 3"
  191.  
  192.   /* Find the number of valid reports. */
  193.  
  194.   reports_remaining = 0
  195.  
  196.   do i = 1 to words(report_format)
  197.     number = word(report_format,i)
  198.  
  199.     if report.number ~= upper("report."number) then do
  200.       reports_remaining = reports_remaining +1
  201.     end 
  202.   end
  203.  
  204.   if reports_remaining ~= 0 then do
  205.  
  206.     /* Grab the area name and number of messages. */
  207.  
  208.     'getareaname' ; area_name = result
  209.     'getnummsgs' ; number_messages = result
  210.  
  211.     call open(report,output_file,'w')
  212.     call writeln(report,'Report for 'area_name' ('number_messages') on 'date(e)':')
  213.  
  214.     /* And now we parse the report format to create the report. */
  215.  
  216.     do i = 1 to words(report_format)
  217.       number = word(report_format,i)
  218.  
  219.       if report.number ~= upper("report."number) then do
  220.         call writeln(report,report.number) ; reports_remaining = reports_remaining -1
  221.       end 
  222.     end
  223.  
  224.     /* Close the report. */
  225.  
  226.     call writech(report,newline'Created by 'version' (C)1994 Phil O''Malley (FIDONET#2:250/107.96)')
  227.     call close(report)
  228.  
  229.   end
  230.  
  231. return
  232.  
  233. /* ----------------------------------------------------------------------- */
  234.  
  235. /***************************************************************************/
  236. /* Parse_Statistics(). Grab all statistics from the current area.          */
  237. /***************************************************************************/
  238.  
  239. parse_statistics: procedure expose true false temp_file subjecttotal. nodetotal. address. nodelist. subjectlist. userlist. receiver. writer. writer_q. writer_nq. subject_q. subject_nq. version
  240.  
  241.   /* Grab the current messgae and then mark all unread messages so that we
  242.      can restore the area to how me found it later.  */
  243.  
  244.   'getmessagenum'
  245.    current_message =  result
  246.  
  247.   'messagelist' ; 'includeflag unread'
  248.   'gotomessage 1' ; 'messages'
  249.  
  250.   /* Grab the preq values and pop open the progress requester. */
  251.  
  252.   'progressopen title "'version'" prompt "Assessing Echomail Information..."'
  253.    preq = result ; 'getnummsgs' ; ptotal = result ; pcurrent = 1 
  254.  
  255.   /* The userlist. stem variable is used to store firstly the total number
  256.      of users (both as writers and receivers) in the area in branch .0 with
  257.      subsequent branches holding the names themselves. All other variables
  258.      are branched from these names which is the quickest option. */
  259.  
  260.   userlist.0 = 0 ; subjectlist.0 = 0 ; nodelist.0 = 0
  261.  
  262.   /* Scan all messages in the area... */
  263.  
  264.   do loop = 1 to ptotal
  265.  
  266.   /* Obtain the user name, and address. As with all entries, first we
  267.      check to see if one is already present for the person concerned, and
  268.      if not we make on and initialise all the variables. */
  269.  
  270.     'getfrom' ; getfrom_result = result
  271.     'getfromaddress' ; getfromaddress_result = result
  272.  
  273.     if writer.getfrom_result = 'WRITER.'getfrom_result & receiver.getfrom_result = 'RECEIVER.'getfrom_result then
  274.       do
  275.         userlist.0 = userlist.0 + 1 ; usertotal = userlist.0
  276.         userlist.usertotal = getfrom_result
  277.  
  278.         /* For each user entry, we must initialise all the variables which
  279.            could be needed. One of the more dubious features of ARexx. */
  280.  
  281.         writer.getfrom_result = 1 ; writer_nq.getfrom_result = 0 ; writer_q.getfrom_result = 0
  282.         receiver.getfrom_result = 0 ; address.getfrom_result = getfromaddress_result
  283.       end
  284.     else
  285.       do  
  286.         writer.getfrom_result = writer.getfrom_result + 1
  287.         address.getfrom_result = getfromaddress_result
  288.       end
  289.  
  290.     /* Find out where the message is going. */
  291.  
  292.     'getto' ; getto_result = result
  293.  
  294.     if receiver.getto_result = 'RECEIVER.'getto_result & writer.getto_result = 'WRITER.'getto_result then
  295.       do
  296.         userlist.0 = userlist.0 + 1 ; usertotal = userlist.0
  297.         userlist.usertotal = getto_result
  298.  
  299.         receiver.getto_result = 1 ; address.getto_result = "?"
  300.         writer.getto_result = 0 ; writer_nq.getto_result = 0 ; writer_q.getto_result = 0
  301.       end
  302.     else 
  303.       receiver.getto_result = receiver.getto_result + 1
  304.  
  305.     /* Now grab the subject information and append it to its own series
  306.        of variable stems. Quoting stats will also be included so we can run
  307.        and waste-of-bandwidth check later on. */
  308.  
  309.     'getsubject' ; getsubject_result = result 
  310.  
  311.     /* Strip out RE:s */
  312.  
  313.     if index(upper(getsubject_result),"RE: ") ~= 0 then do
  314.       getsubject_result = right(getsubject_result,(length(getsubject_result)-4))
  315.     end
  316.  
  317.     if subjecttotal.getsubject_result = 'SUBJECTTOTAL.'getsubject_result then
  318.       do
  319.         subjectlist.0 = subjectlist.0 + 1 ; subjecttotal = subjectlist.0
  320.         subjectlist.subjecttotal = getsubject_result
  321.  
  322.         subjecttotal.getsubject_result = 1 ; subject_nq.getsubject_result = 0 ; subject_q.getsubject_result = 0
  323.       end
  324.     else 
  325.       subjecttotal.getsubject_result = subjecttotal.getsubject_result + 1
  326.  
  327.     /* Now things will slow down. Unfortunately, we have to access all
  328.        messages in the message window which adds to the time taken to dump
  329.        out the message as an ASCII file for analysis purposes. */
  330.  
  331.     'saveascii 'temp_file' overwrite noheader nokludges notearline noorigin'
  332.  
  333.     call open(file,temp_file,"r")
  334.  
  335.       do until eof(file) = 1
  336.         line = readln(file)
  337.  
  338.         if index(line,">")>1 & index(line,">")<6 then
  339.           do
  340.             writer_q.getfrom_result = writer_q.getfrom_result + length(line)
  341.             subject_q.getsubject_result = subject_q.getsubject_result + length(line)
  342.           end
  343.         else
  344.           if line ~= "" then do 
  345.             writer_nq.getfrom_result = writer_nq.getfrom_result + length(line)
  346.             subject_nq.getsubject_result = subject_nq.getsubject_result + length(line)
  347.           end
  348.  
  349.       end
  350.  
  351.     call close(file)    
  352.  
  353.     /* Update the progress requester... */
  354.  
  355.     'progressupdate 'preq' current 'pcurrent' total 'ptotal
  356.  
  357.     if rc = 5 then do
  358.       'progressclose 'preq ; exit
  359.     end
  360.  
  361.     /* We must see if we are at the last message in the area as if we try
  362.        to grab the next message then the script fails with an error. */
  363.  
  364.     if loop ~= ptotal then do
  365.       pcurrent = pcurrent +1 ; 'nextmessage'
  366.     end
  367.  
  368.   end
  369.  
  370.   'progressclose 'preq
  371.  
  372.   /* Restore any unread flags. */
  373.  
  374.   'messagelist' ; 'setflags unread' ; 'excludeflag all'
  375.  
  376. return
  377.  
  378. /***************************************************************************/
  379. /* Produce_Traffic_Statistics(). Total users, mail from/to, quoting %      */
  380. /***************************************************************************/
  381.  
  382. produce_traffic_statistics: procedure expose true blank newline noflag address. receiver. userlist. writer. writer_nq. writer_q. version xsquoting_level
  383.  
  384.   parse arg table_limit ; if table_limit = "" then table_limit = 0 ; total_entries = 0 ; total_writers = 0 ; total_receivers = 0
  385.  
  386.   do entry = 1 to userlist.0
  387.  
  388.     username = userlist.entry
  389.  
  390.     select
  391.       when writer_q.username = 0 then writer_qs.username = 0
  392.       when writer_nq.username = 0 then writer_qs.username = 100
  393.  
  394.       otherwise writer_qs.username = (writer_q.username/(writer_nq.username+writer_q.username))*100
  395.     end
  396.   end
  397.  
  398.   /* Write the message header. */
  399.  
  400.   if userlist.0 ~= 0 then do
  401.  
  402.     /* Initialise the report. The header will be appended later when we've
  403.        found how many writers and recievers there were. */
  404.  
  405.     report = blank
  406.  
  407.     /* Sort according to amount of mail posted. */
  408.  
  409.     'progressopen title "'version'" prompt "Sorting Echomail Traffic..."'
  410.      preq = result ; current_entry = 1
  411.  
  412.     do loop = 1 to userlist.0
  413.       writer = 0 ; highest = 0
  414.  
  415.         do u = 1 to userlist.0
  416.           username = userlist.u
  417.  
  418.           if writer.username ~< highest & writer_used.username ~= "Null" then do
  419.             writer = username ; highest = writer.username
  420.           end
  421.         end
  422.  
  423.       /* Update the total number of senders and receivers. */
  424.  
  425.       if writer.writer ~= 0 then total_writers = total_writers +1
  426.       if receiver.writer = ~0 then total_receivers = total_receivers +1
  427.  
  428.       /* Work out any flags to be displayed. Notice that the flags are
  429.          entered in order of dominance as only one is displayed. */
  430.  
  431.       select
  432.         when noflag = true then flag = " "
  433.         when address.writer = "?" then flag = " "
  434.         when display_traplist_info(left((address.writer),((index((address.writer),".",1))-1))) = "?" then flag = "#"
  435.         when writer_qs.writer > xsquoting_level then flag = "!"
  436.  
  437.         otherwise flag = " "
  438.       end
  439.  
  440.       /* Keep tabs on any flags used so that we can append a key to the
  441.          bottom of the table. */
  442.  
  443.       if flag = "!" then flag_! = true
  444.       if flag = "#" then flag_# = true
  445.  
  446.       if (loop > table_limit) & table_limit ~= 0 & flag = " " then
  447.         do 
  448.           /* Do nothing */
  449.         end
  450.       else
  451.         if (loop > table_limit) & table_limit ~= 0 then
  452.           do 
  453.             report = report||newline"  | "||right(loop,3," ")||". "||flag||" "||left(writer||" ",22,".")||" "||left(address.writer||" ",14,".")||right(" "||writer.writer||" ",7,".")||right(" "||receiver.writer||" ",7,".")||right(left((" "||writer_qs.writer||".0"),((index((" "||writer_qs.writer||".0"),".",1))+1)),8,".")||"%"||"  |"
  454.             extra_entries = true
  455.           end
  456.         else
  457.           report = report||newline"  | "||right(loop,3," ")||". "||flag||" "||left(writer||" ",22,".")||" "||left(address.writer||" ",14,".")||right(" "||writer.writer||" ",7,".")||right(" "||receiver.writer||" ",7,".")||right(left((" "||writer_qs.writer||".0"),((index((" "||writer_qs.writer||".0"),".",1))+1)),8,".")||"%"||"  |"
  458.  
  459.       /* This "Null" business is for convience during sorting. Notice that
  460.          it uses it's own variable and so is completely forgotten about when
  461.          we leave the procedure. */
  462.  
  463.       writer_used.writer = "Null"
  464.  
  465.       /* Check to see if we've reached the desired table size. */
  466.  
  467.       if (loop = table_limit) & table_limit ~= 0 then do
  468.         report = report||newline'  +----------------------------------------------------------------------+'
  469.         table_limit_seperator = true
  470.       end
  471.  
  472.       /* Update the progress requester. */
  473.  
  474.       'progressupdate 'preq' current 'loop' total 'userlist.0
  475.  
  476.        if rc = 5 then do
  477.          'progressclose 'preq ; exit
  478.        end
  479.  
  480.     end
  481.  
  482.     if table_limit_seperator ~= true | extra_entries = true then do
  483.       report = report||newline'  +----------------------------------------------------------------------+'
  484.     end
  485.  
  486.     if flag_! = true | flag_# = true then do
  487.  
  488.       footnote = "NB."
  489.  
  490.       if flag_! = true then do
  491.         report = report||newline'  |  'footnote' ! = Quoting level is considered excessive.                      |' ; footnote = "   "
  492.       end
  493.  
  494.       if flag_# = true then do
  495.         report = report||newline'  |  'footnote' # = Address is not present in the current nodelist.             |' ; footnote = "   "
  496.       end
  497.  
  498.       report = report||newline'  +----------------------------------------------------------------------+'
  499.  
  500.     end
  501.  
  502.     /* Create the header, taking into account the total number of people in
  503.        in echo and the total number of writers and receivers. */
  504.  
  505.     header_title = '       | Echomail Traffic (T:'userlist.0', W:'total_writers', R:'total_receivers') |'    
  506.  
  507.     header =  blank||newline'       +'||right(blank,(length(header_title)-9),"-")||'+'
  508.     header = header||newline||header_title
  509.     header = header||newline'  +----+'||right(blank,(length(header_title)-9),"-")||'+'||right(blank,(73-length(header_title)),"-")||'+'
  510.     header = header||newline'  |  No.   Name                   Address         From     To    Quoted  |'
  511.     header = header||newline'  +----------------------------------------------------------------------+'
  512.  
  513.     'progressclose 'preq
  514.  
  515.   end
  516.  
  517. return header||report
  518.  
  519. /***************************************************************************/
  520. /* Procduce_Subject_Statistics(). Subject popularity and debate.           */
  521. /***************************************************************************/
  522.  
  523. produce_subject_statistics: procedure expose newtopic_content true noflag blank newline subjectlist. subjecttotal. subject_q. subject_nq. version
  524.  
  525.   parse arg table_limit ; if table_limit = "" then table_limit = 0 ; total_entries = 0
  526.  
  527.   do i = 1 to subjectlist.0
  528.     subjectname = subjectlist.i
  529.  
  530.     select
  531.       when subject_q.subjectname  = 0 then subject_qs.subjectname = 100
  532.       when subject_nq.subjectname = 0 then subject_qs.subjectname = 0
  533.  
  534.       otherwise subject_qs.subjectname = (subject_nq.subjectname/(subject_nq.subjectname+subject_q.subjectname))*100
  535.     end
  536.  
  537.   end
  538.  
  539.   /* Write the message header. */
  540.  
  541.   if subjectlist.0 ~= 0 then do
  542.     report_header = '       | Echomail Content (T:'subjectlist.0') |'
  543.  
  544.     report =  blank||newline'       +'||right(blank,(length(report_header)-9),"-")||'+'
  545.     report = report||newline||report_header
  546.     report = report||newline'  +----+'||right(blank,(length(report_header)-9),"-")||'+'||right(blank,(73-length(report_header)),"-")||'+'
  547.     report = report||newline'  |  No.   Subject                                      Total       New  |'
  548.     report = report||newline'  +----------------------------------------------------------------------+'
  549.  
  550.     /* Sort entries according to naughtiness in quoting. */
  551.  
  552.     'progressopen title "'version'" prompt "Sorting Subject Statistics..."'
  553.      preq = result ; current_entry = 1
  554.  
  555.     do loop = 1 to subjectlist.0
  556.       subject = 0 ; highest = 0
  557.  
  558.       do u = 1 to subjectlist.0
  559.         subjectname = subjectlist.u
  560.  
  561.         if subjecttotal.subjectname ~< highest & subject_used.subjectname ~= "Null" then do
  562.           subject = subjectname ; highest = subjecttotal.subjectname
  563.         end
  564.       end
  565.  
  566.       /* Work out the dominant flag, if there is one. */
  567.  
  568.       select
  569.         when noflag = true then flag = " "
  570.         when subject_qs.subject < newtopic_content then flag = "!"
  571.  
  572.         otherwise flag = " "
  573.       end
  574.  
  575.       if flag = "!" then flag_! = true
  576.  
  577.       if (loop > table_limit) & table_limit ~= 0 & flag = " " then
  578.         do 
  579.           /* Do nothing */
  580.         end
  581.       else
  582.         if (loop > table_limit) & table_limit ~= 0 then
  583.           do 
  584.             report = report||newline"  | "||right(loop,3," ")||". "||flag||" "||left(subject||" ",44,".")||right(" "||subjecttotal.subject||" ",7,".")||right(left((" "||subject_qs.subject||".0"),((index((" "||subject_qs.subject||".0"),".",1))+1)),8,".")||"%"||"  |"
  585.             extra_entries = true
  586.           end
  587.         else
  588.             report = report||newline"  | "||right(loop,3," ")||". "||flag||" "||left(subject||" ",44,".")||right(" "||subjecttotal.subject||" ",7,".")||right(left((" "||subject_qs.subject||".0"),((index((" "||subject_qs.subject||".0"),".",1))+1)),8,".")||"%"||"  |"
  589.  
  590.       subject_used.subject = "Null"
  591.  
  592.       /* Check to see if we've reached the desired table size. */
  593.  
  594.       if (loop = table_limit) & table_limit ~= 0 then do
  595.         report = report||newline'  +----------------------------------------------------------------------+'
  596.         table_limit_seperator = true
  597.       end
  598.  
  599.       /* Update the progress requester. */
  600.  
  601.       'progressupdate 'preq' current 'loop' total 'subjectlist.0
  602.  
  603.       if rc = 5 then do
  604.         'progressclose 'preq ; exit
  605.       end
  606.  
  607.     end
  608.  
  609.     if table_limit_seperator ~= true | extra_entries = true then do
  610.       report = report||newline'  +----------------------------------------------------------------------+'
  611.     end
  612.  
  613.     if flag_! = true then do
  614.       report = report||newline'  |  NB. ! = Thread is currently wasting bandwidth.                      |'
  615.       report = report||newline'  +----------------------------------------------------------------------+'
  616.     end
  617.  
  618.     'progressclose ' preq
  619.  
  620.   end
  621.  
  622. return report
  623.  
  624. /***************************************************************************/
  625. /* Produce_Node_Statistics(). List originating nodes, with names.          */
  626. /***************************************************************************/
  627.  
  628. produce_node_statistics: procedure expose true blank newline noflag address. userlist. writer. version
  629.  
  630.   parse arg table_limit ; if table_limit = "" then table_limit = 0 ; nodelist.0 = 0
  631.  
  632.   /* Grab the node information from the address. list. */
  633.  
  634.   if userlist.0 ~= 0 then do
  635.  
  636.     'progressopen title "'version'" prompt "Sorting Node Traffic..."'
  637.      preq = result ; current_entry = 1
  638.  
  639.     do u = 1 to userlist.0
  640.       username = userlist.u
  641.  
  642.       if address.username ~= "?" then do
  643.         nodeaddress_result = left((address.username),((index((address.username),".",1))-1))
  644.  
  645.         if nodetotal.nodeaddress_result = 'NODETOTAL.'nodeaddress_result then
  646.           do
  647.             nodelist.0 = nodelist.0 + 1 ; nodetotal = nodelist.0
  648.             nodelist.nodetotal = nodeaddress_result ; nodetotal.nodeaddress_result = writer.username
  649.           end
  650.         else 
  651.           nodetotal.nodeaddress_result = nodetotal.nodeaddress_result + writer.username
  652.       end
  653.  
  654.       /* Update the progress requester. */
  655.  
  656.        total = ((userlist.0)*2)
  657.       'progressupdate 'preq' current 'u' total 'total
  658.  
  659.        if rc = 5 then do
  660.          'progressclose 'preq ; exit
  661.        end
  662.  
  663.     end  
  664.   end
  665.  
  666.   if nodelist.0 ~= 0 then do
  667.     report_header ='       | Echomail Origins (T:'nodelist.0') |'
  668.  
  669.     report =  blank||newline'       +'||right(blank,(length(report_header)-9),"-")||'+'
  670.     report = report||newline||report_header
  671.     report = report||newline'  +----+'||right(blank,(length(report_header)-9),"-")||'+'||right(blank,(73-length(report_header)),"-")||'+'
  672.     report = report||newline'  |  No.   Name                          Address                  Total  |'
  673.     report = report||newline'  +----------------------------------------------------------------------+'
  674.  
  675.     /* Sort according to amount of mail originating. */
  676.  
  677.     do loop = 1 to nodelist.0
  678.       node = 0 ; highest = 0
  679.  
  680.       do u = 1 to nodelist.0
  681.         nodename = nodelist.u
  682.  
  683.         if nodetotal.nodename ~< highest & node_used.nodename ~= "Null" then do
  684.           node = nodename ; highest = nodetotal.nodename
  685.         end
  686.       end
  687.  
  688.       /* Check to see if the node is listed in the nodelist. */
  689.  
  690.       system_name = display_traplist_info(node)
  691.  
  692.       /* Work out the flags. */
  693.  
  694.       select
  695.         when noflag = true then flag = " "
  696.         when system_name = "?" then flag = "#"
  697.  
  698.         otherwise flag = " "
  699.       end
  700.  
  701.       if flag = "#" then flag_# = true
  702.  
  703.       if (loop > table_limit) & table_limit ~= 0 & flag = " " then
  704.         do 
  705.           /* Do nothing */
  706.         end
  707.       else
  708.         if (loop > table_limit) & table_limit ~= 0 then
  709.           do 
  710.             report = report||newline"  | "||right(loop,3," ")||". "||flag||" "||left(system_name||" ",29,".")||left(" "||node||" ",19,".")||right(" "||nodetotal.node,12,".")||"  |"
  711.             extra_entries = true
  712.           end
  713.         else
  714.           report = report||newline"  | "||right(loop,3," ")||". "||flag||" "||left(system_name||" ",29,".")||left(" "||node||" ",19,".")||right(" "||nodetotal.node,12,".")||"  |"
  715.  
  716.       node_used.node = "Null"
  717.  
  718.       /* Check to see if we've reached the desired table size. */
  719.  
  720.       if (loop = table_limit) & table_limit ~= 0 then do
  721.         report = report||newline'  +----------------------------------------------------------------------+'
  722.         table_limit_seperator = true
  723.       end
  724.  
  725.       /* Update the progress requester. */
  726.  
  727.        current = int(((nodelist.0)/2)+(loop/2))
  728.       'progressupdate 'preq' current 'current' total 'nodelist.0
  729.  
  730.        if rc = 5 then do
  731.          'progressclose 'preq ; exit
  732.        end
  733.  
  734.     end
  735.  
  736.     if table_limit_seperator ~= true | extra_entries = true then do
  737.       report = report||newline'  +----------------------------------------------------------------------+'
  738.     end
  739.  
  740.     if flag_# = true then do
  741.       report = report||newline'  |  NB. # = Address is not present in the current nodelist.             |'
  742.       report = report||newline'  +----------------------------------------------------------------------+'
  743.     end
  744.  
  745.     'progressclose 'preq
  746.  
  747.   end
  748.  
  749. return report
  750.  
  751. /* ----------------------------------------------------------------------- */
  752.  
  753. /***************************************************************************/
  754. /* Display_TrapList_Info(). Does what it says...                           */
  755. /***************************************************************************/
  756.  
  757. display_traplist_info:
  758.  
  759.   parse arg nodenumber
  760.  
  761.   /* Get the info. */
  762.  
  763.   result = findnode(nodenumber,'System')
  764.   parse var result success " " name
  765.  
  766.   /* Check if the address was present. */
  767.  
  768.   if success ~= 1 then do
  769.     name = "?"
  770.   end
  771.  
  772. return name
  773.  
  774. /***************************************************************************/
  775. /* Int(). Returns an an interger from a specified number.                  */
  776. /***************************************************************************/
  777.  
  778. int: procedure
  779.  
  780.   parse arg number
  781.  
  782.   if index(number,".") ~= 0 then
  783.     result = left(number,(index(number,".")-1))
  784.   else
  785.     result = number
  786.  
  787. return result
  788.