(FILECREATED "23-Jul-86 15:50:04" {QV}<NOTECARDS>1.2K>LIBRARY>NOTEFILESTATS.;26 29488  

      changes to:  (MACROS NFSTAT.HistPlot)
		   (VARS NOTEFILESTATSCOMS)

      previous date: "22-Jun-86 23:14:21" {QV}<NOTECARDS>1.2K>LIBRARY>NOTEFILESTATS.;24)


(* Copyright (c) 1986 by Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT NOTEFILESTATSCOMS)

(RPAQQ NOTEFILESTATSCOMS ((* * This code computes statistics for a notefile.)
			    (GLOBALVARS NFSTAT.HistSize NFSTAT.HashArraySize)
			    (VARS (NFSTAT.HistSize 100)
				  (NFSTAT.HashArraySize 100))
			    (RECORDS NOTEFILEATTRIBUTES NOTEFILEDATA ALLCARDSDATA CARDTYPEDATA 
				     FILEBOXDATA CARDHISTENTRY FILEBOXHISTENTRY CARDSTATS 
				     STATSFROMHIST)
			    (* * Top level functions.)
			    (FNS NFSTAT.AnalyzeRemoteNoteFile NFSTAT.GatherNoteFileData)
			    (* * Helper functions.)
			    (FNS NFSTAT.ProcessCards NFSTAT.ProcessFileBoxHierarchies)
			    (FNS NFSTAT.AddCardDataToHist NFSTAT.AddFileBoxDataToHist 
				 NFSTAT.AddCardSizeDataToHist NFSTAT.MakeFreshHistRecord 
				 NFSTAT.TraverseFileBoxHierarchy NFSTAT.ComputeSubstanceSize 
				 NFSTAT.IncrementHashItem NFSTAT.FetchCardTypeData 
				 NFSTAT.FillInCardStats)
			    (MACROS NFSTAT.AddFieldEntryToHist NFSTAT.AnalyzeHist)
			    (* * Miscellaneous accelerators.)
			    (FNS NFSTAT.AnalyzeSetsOfNoteFiles NFSTAT.AnalyzeListOfNoteFiles 
				 NFSTAT.MakeOutputFileName NFSTAT.InspectDataFile)
			    (* * Functions for plotting.)
			    (MACROS NFSTAT.HistPlot)
			    (DECLARE: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY COMPILERVARS
				      (ADDVARS (NLAMA)
					       (NLAML)
					       (LAMA NFSTAT.AnalyzeSetsOfNoteFiles)))))
(* * This code computes statistics for a notefile.)

(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS NFSTAT.HistSize NFSTAT.HashArraySize)
)

(RPAQQ NFSTAT.HistSize 100)

(RPAQQ NFSTAT.HashArraySize 100)
[DECLARE: EVAL@COMPILE 

(DATATYPE NOTEFILEATTRIBUTES (FULLNAME AUTHOR CREATIONDATE WRITEDATE READDATE (SIZE INTEGER)))

(DATATYPE NOTEFILEDATA (ALLCARDSDATA CARDTYPESHASHARRAY FILEBOXDATA LINKTYPESHASHARRAY
				       (NUMLINKS INTEGER)))

(DATATYPE ALLCARDSDATA (ALLCARDSSIZEHIST1 ALLCARDSSIZEHIST2 ALLCARDSHIST ALLCARDSSTATS))

(DATATYPE CARDTYPEDATA (CARDTYPESIZEHIST1 CARDTYPESIZEHIST2 CARDTYPEHIST CARDTYPESTATS))

(DATATYPE FILEBOXDATA (FILEBOXHIST FILEDCARDSTATS SUBBOXSTATS TOCDEPTHHIST TOCDEPTHSTATS 
				     TBFDEPTHHIST TBFDEPTHSTATS ORPHDEPTHHIST ORPHDEPTHSTATS))

(DATATYPE CARDHISTENTRY ((HISTENTRYPARENTS INTEGER)
			   (HISTENTRYTOLINKS INTEGER)
			   (HISTENTRYFROMLINKS INTEGER)
			   (HISTENTRYGLOBALLINKS INTEGER)))

(DATATYPE FILEBOXHISTENTRY ((HISTENTRYFILEDCARDLINKS INTEGER)
			      (HISTENTRYSUBBOXLINKS INTEGER)))

(DATATYPE CARDSTATS ((TOTAL INTEGER)
		       PARENTSSTATS TOLINKSSTATS FROMLINKSSTATS GLOBALLINKSSTATS SIZESTATS))

(DATATYPE STATSFROMHIST ((TOTAL INTEGER)
			   (MIN FLOATING)
			   (MAX FLOATING)
			   (MEAN FLOATING)
			   (MEDIAN FLOATING)
			   (MODE FLOATING)))
]
(/DECLAREDATATYPE (QUOTE NOTEFILEATTRIBUTES)
		  (QUOTE (POINTER POINTER POINTER POINTER POINTER FIXP))
		  (QUOTE ((NOTEFILEATTRIBUTES 0 POINTER)
			  (NOTEFILEATTRIBUTES 2 POINTER)
			  (NOTEFILEATTRIBUTES 4 POINTER)
			  (NOTEFILEATTRIBUTES 6 POINTER)
			  (NOTEFILEATTRIBUTES 8 POINTER)
			  (NOTEFILEATTRIBUTES 10 FIXP)))
		  (QUOTE 12))
(/DECLAREDATATYPE (QUOTE NOTEFILEDATA)
		  (QUOTE (POINTER POINTER POINTER POINTER FIXP))
		  (QUOTE ((NOTEFILEDATA 0 POINTER)
			  (NOTEFILEDATA 2 POINTER)
			  (NOTEFILEDATA 4 POINTER)
			  (NOTEFILEDATA 6 POINTER)
			  (NOTEFILEDATA 8 FIXP)))
		  (QUOTE 10))
(/DECLAREDATATYPE (QUOTE ALLCARDSDATA)
		  (QUOTE (POINTER POINTER POINTER POINTER))
		  (QUOTE ((ALLCARDSDATA 0 POINTER)
			  (ALLCARDSDATA 2 POINTER)
			  (ALLCARDSDATA 4 POINTER)
			  (ALLCARDSDATA 6 POINTER)))
		  (QUOTE 8))
(/DECLAREDATATYPE (QUOTE CARDTYPEDATA)
		  (QUOTE (POINTER POINTER POINTER POINTER))
		  (QUOTE ((CARDTYPEDATA 0 POINTER)
			  (CARDTYPEDATA 2 POINTER)
			  (CARDTYPEDATA 4 POINTER)
			  (CARDTYPEDATA 6 POINTER)))
		  (QUOTE 8))
(/DECLAREDATATYPE (QUOTE FILEBOXDATA)
		  (QUOTE (POINTER POINTER POINTER POINTER POINTER POINTER POINTER POINTER POINTER))
		  (QUOTE ((FILEBOXDATA 0 POINTER)
			  (FILEBOXDATA 2 POINTER)
			  (FILEBOXDATA 4 POINTER)
			  (FILEBOXDATA 6 POINTER)
			  (FILEBOXDATA 8 POINTER)
			  (FILEBOXDATA 10 POINTER)
			  (FILEBOXDATA 12 POINTER)
			  (FILEBOXDATA 14 POINTER)
			  (FILEBOXDATA 16 POINTER)))
		  (QUOTE 18))
(/DECLAREDATATYPE (QUOTE CARDHISTENTRY)
		  (QUOTE (FIXP FIXP FIXP FIXP))
		  (QUOTE ((CARDHISTENTRY 0 FIXP)
			  (CARDHISTENTRY 2 FIXP)
			  (CARDHISTENTRY 4 FIXP)
			  (CARDHISTENTRY 6 FIXP)))
		  (QUOTE 8))
(/DECLAREDATATYPE (QUOTE FILEBOXHISTENTRY)
		  (QUOTE (FIXP FIXP))
		  (QUOTE ((FILEBOXHISTENTRY 0 FIXP)
			  (FILEBOXHISTENTRY 2 FIXP)))
		  (QUOTE 4))
(/DECLAREDATATYPE (QUOTE CARDSTATS)
		  (QUOTE (FIXP POINTER POINTER POINTER POINTER POINTER))
		  (QUOTE ((CARDSTATS 0 FIXP)
			  (CARDSTATS 2 POINTER)
			  (CARDSTATS 4 POINTER)
			  (CARDSTATS 6 POINTER)
			  (CARDSTATS 8 POINTER)
			  (CARDSTATS 10 POINTER)))
		  (QUOTE 12))
(/DECLAREDATATYPE (QUOTE STATSFROMHIST)
		  (QUOTE (FIXP FLOATP FLOATP FLOATP FLOATP FLOATP))
		  (QUOTE ((STATSFROMHIST 0 FIXP)
			  (STATSFROMHIST 2 FLOATP)
			  (STATSFROMHIST 4 FLOATP)
			  (STATSFROMHIST 6 FLOATP)
			  (STATSFROMHIST 8 FLOATP)
			  (STATSFROMHIST 10 FLOATP)))
		  (QUOTE 12))
(* * Top level functions.)

(DEFINEQ

(NFSTAT.AnalyzeRemoteNoteFile
  (LAMBDA (NoteFileName LocalHostAndDirectory OutputFile Don'tDeleteLocalCopyFlg QuietFlg)
                                                             (* rht: "19-Jun-86 18:22")

          (* * First get attributes from remote file. Then copy to local disk, open notefile, gather data, close, and write 
	  out data to OutputFile. Delete local copy of notefile unless Don'tDeleteLocalCopyFlg non-nil.)


    (if (NCP.CurrentNoteFile)
	then (NCP.PrintMsg NIL T "Must close current open notefile first!")
	       (FLASHW PROMPTWINDOW)
      else (LET ((FullFileName (FULLNAME NoteFileName))
		   LocalFileName NoteFileAttributes NoteFileData ResultOfOper)

          (* * Fill in fresh NOTEFILEATTRIBUTES record.)


	          (SETQ NoteFileAttributes (create NOTEFILEATTRIBUTES
						       FULLNAME ← FullFileName
						       AUTHOR ←(GETFILEINFO FullFileName
									      (QUOTE AUTHOR))
						       CREATIONDATE ←(GETFILEINFO FullFileName
										    (QUOTE 
										     CREATIONDATE))
						       WRITEDATE ←(GETFILEINFO FullFileName
										 (QUOTE WRITEDATE))
						       READDATE ←(GETFILEINFO FullFileName
										(QUOTE READDATE))
						       SIZE ←(GETFILEINFO FullFileName
									    (QUOTE SIZE))))

          (* * Copy notefile to local disk.)


	          (SETQ LocalFileName (PACKFILENAME (QUOTE NAME)
							(FILENAMEFIELD FullFileName (QUOTE NAME))
							(QUOTE EXTENSION)
							(QUOTE NOTEFILE)
							(QUOTE BODY)
							LocalHostAndDirectory))
	          (OR QuietFlg (NCP.PrintMsg NIL T "Copying " FullFileName " to " LocalFileName 
						 " ..."))
	          (if (NULL (ERSETQ (COPYFILE FullFileName LocalFileName)))
		      then (ERROR "Trouble copying from " (CONCAT FullFileName " to " 
									LocalFileName)))

          (* * Open, process, and close.)


	          (SETQ ResultOfOper (ERSETQ (NCP.OpenNoteFile LocalFileName T T)))
	          (if (OR (NULL ResultOfOper)
			      (NULL (CAR ResultOfOper)))
		      then (ERROR "Trouble opening " LocalFileName))
	          (if (NULL (ERSETQ (SETQ NoteFileData (NFSTAT.GatherNoteFileData QuietFlg))
					  ))
		      then (ERROR "Trouble gathering data for " LocalFileName))
	          (if (NULL (ERSETQ (NCP.CloseNoteFile)))
		      then (ERROR "Trouble closing " LocalFileName))

          (* * Write results out to OutputFile.)


	          (if (NULL (ERSETQ (OPENFILE OutputFile (QUOTE OUTPUT))))
		      then (ERROR "Trouble opening " OutputFile))
	          (OR QuietFlg (NCP.PrintMsg NIL T "Writing out results to " OutputFile " ..."))
	          (HPRINT (CONS NoteFileAttributes NoteFileData)
			    OutputFile T)
	          (CLOSEF OutputFile)

          (* * Delete local notefile if desired.)


	          (OR Don'tDeleteLocalCopyFlg (DELFILE LocalFileName))
	          (OR QuietFlg (NCP.PrintMsg NIL T "Done."))))))

(NFSTAT.GatherNoteFileData
  (LAMBDA (QuietFlg)                                         (* rht: "19-Jun-86 11:11")

          (* * Accumulate data on this notefile into a fresh NOTEFILEDATA record.)


    (LET ((FileName (NCP.CurrentNoteFile))
	  NoteFileDataRecord)

          (* * Initialize a fresh data record.)


         (SETQ NoteFileDataRecord (create NOTEFILEDATA
					      ALLCARDSDATA ←(create ALLCARDSDATA
								      ALLCARDSSIZEHIST1 ←(ARRAY
									NFSTAT.HistSize
									(QUOTE FIXP)
									0 0)
								      ALLCARDSSIZEHIST2 ←(ARRAY
									NFSTAT.HistSize
									(QUOTE FIXP)
									0 0)
								      ALLCARDSHIST ←(ARRAY 
										  NFSTAT.HistSize NIL 
											     NIL 0)
								      ALLCARDSSTATS ←(create 
											CARDSTATS
											       TOTAL 
											       ← 0))
					      CARDTYPESHASHARRAY ←(HASHARRAY NFSTAT.HashArraySize)
					      LINKTYPESHASHARRAY ←(HASHARRAY NFSTAT.HashArraySize)
					      FILEBOXDATA ←(create FILEBOXDATA
								     FILEBOXHIST ←(ARRAY 
										  NFSTAT.HistSize NIL 
											   NIL 0)
								     TOCDEPTHHIST ←(ARRAY
								       NFSTAT.HistSize
								       (QUOTE FIXP)
								       0 0)
								     TBFDEPTHHIST ←(ARRAY
								       NFSTAT.HistSize
								       (QUOTE FIXP)
								       0 0)
								     ORPHDEPTHHIST ←(ARRAY
								       NFSTAT.HistSize
								       (QUOTE FIXP)
								       0 0))
					      NUMLINKS ← 0))

          (* * Fill in the ALLCARDSHIST, FILEBOXHIST, CARDTYPESHASHARRAY, LINKTYPESHASHARRAY fields.)


         (NFSTAT.ProcessCards NoteFileDataRecord QuietFlg)

          (* * Fill in the TOCDEPTHHIST, TBFDEPTHHIST, ORPHDEPTHHIST fields.)


         (NFSTAT.ProcessFileBoxHierarchies (fetch (NOTEFILEDATA FILEBOXDATA) of 
									       NoteFileDataRecord)
					     QuietFlg)
         (OR QuietFlg (NCP.PrintMsg NIL T "Done."))
     NoteFileDataRecord)))
)
(* * Helper functions.)

(DEFINEQ

(NFSTAT.ProcessCards
  (LAMBDA (NoteFileDataRecord QuietFlg)                      (* rht: "19-Jun-86 15:18")

          (* * Run through all the cards in the currently open notefile, computing vital data for each and storing in the 
	  proper histograms in NoteFileDataRecord.)


    (LET ((CardNum 0)
	  (CardTotal (SUB1 (STREAMPROP (NCP.CurrentNoteFileStream)
					   (QUOTE NCNEXTIDNUM))))
	  (RealCardTotal 0)
	  (TotalFileBoxes 0))
         (OR QuietFlg (NCP.PrintMsg NIL T "Processing card number " 1 " out of " CardTotal))
         (with
	   NOTEFILEDATA NoteFileDataRecord
	   (with ALLCARDSDATA ALLCARDSDATA
		   (with FILEBOXDATA FILEBOXDATA
			   (NCP.MapCards
			     (FUNCTION (LAMBDA (Card)
				 (BLOCK)
				 (SETQ CardNum (ADD1 CardNum))
				 (AND (NULL QuietFlg)
					(ZEROP (REMAINDER CardNum 100))
					(NCP.PrintMsg NIL T "Processing card number " CardNum 
							" out of "
							CardTotal))
				 (LET ((CardType (NCP.CardType Card))
				       (ToLinks (NCP.GetLinks Card))
				       (FromLinks (NCP.GetLinks NIL Card))
				       SubstanceSize NumParents NumToLinks NumFromLinks 
				       NumGlobalLinks)
				      (with CARDTYPEDATA (NFSTAT.FetchCardTypeData CardType 
									       CARDTYPESHASHARRAY)
					      (with CARDSTATS CARDTYPESTATS 

          (* * Keep track of total # of cards and by card type.)


						      (add RealCardTotal 1)
						      (add TOTAL 1)

          (* * Keep running total of substance size and by card type.)


						      (NFSTAT.AddCardSizeDataToHist 
										ALLCARDSSIZEHIST1 
										ALLCARDSSIZEHIST2
										      (SETQ 
										    SubstanceSize
											(
								      NFSTAT.ComputeSubstanceSize
											  Card)))
						      (NFSTAT.AddCardSizeDataToHist 
										CARDTYPESIZEHIST1 
										CARDTYPESIZEHIST2 
										    SubstanceSize)

          (* * Keep track of vital links info in allcards histograms and by card type.)


						      (SETQ NumParents
							(for Link in FromLinks
							   count (FMEMB (NCP.LinkLabel Link)
									    (QUOTE (SubBox 
											FiledCard)))))
						      (SETQ NumToLinks (LENGTH ToLinks))
						      (SETQ NumFromLinks (LENGTH FromLinks))
						      (SETQ NumGlobalLinks
							(for Link in ToLinks
							   count (EQ (fetch (NOTECARDLINK
										    ANCHORMODE)
									    of Link)
									 (QUOTE GLOBAL))))
						      (NFSTAT.AddCardDataToHist ALLCARDSHIST 
										  NumParents 
										  NumToLinks 
										  NumFromLinks 
										  NumGlobalLinks)
						      (NFSTAT.AddCardDataToHist CARDTYPEHIST 
										  NumParents 
										  NumToLinks 
										  NumFromLinks 
										  NumGlobalLinks)

          (* * Keep track specially of filebox linking info.)


						      (if (EQ CardType (QUOTE FileBox))
							  then (NFSTAT.AddFileBoxDataToHist
								   FILEBOXHIST
								   (for Link in ToLinks
								      count (EQ (NCP.LinkLabel
										      Link)
										    (QUOTE 
											FiledCard)))
								   (for Link in ToLinks
								      count (EQ (NCP.LinkLabel
										      Link)
										    (QUOTE SubBox)))
								   )
								 (add TotalFileBoxes 1))

          (* * Keep track of total number of links of each type.)


						      (for Link in ToLinks
							 do (NFSTAT.IncrementHashItem
								(NCP.LinkLabel Link)
								LINKTYPESHASHARRAY)
							      (add NUMLINKS 1))))))))

          (* * Turn size totals for all cards and in each CARDTYPEDATA into averages. Also analyze the histograms to obtain 
	  vital stats.)


			   (OR QuietFlg (NCP.PrintMsg NIL T 
				      "Computing statistics from card and filebox histograms ..."))
			   (replace (CARDSTATS TOTAL) of ALLCARDSSTATS with RealCardTotal)
			   (NFSTAT.FillInCardStats ALLCARDSHIST ALLCARDSSTATS)
			   (replace (CARDSTATS SIZESTATS) of ALLCARDSSTATS
			      with (NFSTAT.AnalyzeHist (LIST ALLCARDSSIZEHIST1 ALLCARDSSIZEHIST2)
							 (QUOTE (100 1000))
							 RealCardTotal NIL NIL))
			   (MAPHASH CARDTYPESHASHARRAY
				      (FUNCTION (LAMBDA (Item Key)
					  (BLOCK)
					  (with CARDTYPEDATA Item (NFSTAT.FillInCardStats 
										     CARDTYPEHIST 
										    CARDTYPESTATS)
						  (replace (CARDSTATS SIZESTATS) of CARDTYPESTATS
						     with (NFSTAT.AnalyzeHist (LIST 
										CARDTYPESIZEHIST1 
										CARDTYPESIZEHIST2)
										(QUOTE
										  (100 1000))
										(fetch
										  (CARDSTATS TOTAL)
										   of CARDTYPESTATS)
										NIL NIL))))))

          (* * Analyze the FileBox histogram for stats on SubBox and FiledCard links.)


			   (SETQ FILEDCARDSTATS (NFSTAT.AnalyzeHist FILEBOXHIST 1 TotalFileBoxes 
								      FILEBOXHISTENTRY 
								      HISTENTRYFILEDCARDLINKS))
			   (SETQ SUBBOXSTATS (NFSTAT.AnalyzeHist FILEBOXHIST 1 TotalFileBoxes 
								   FILEBOXHISTENTRY 
								   HISTENTRYSUBBOXLINKS))))))))

(NFSTAT.ProcessFileBoxHierarchies
  (LAMBDA (FileBoxDataRecord QuietFlg)                       (* rht: "19-Jun-86 01:04")

          (* * Run down each of the three main filebox hierarchies to make and analyze a histogram of depths.)


    (with FILEBOXDATA FileBoxDataRecord (OR QuietFlg (NCP.PrintMsg NIL T 
					"Traversing filebox hierarchy under Contents FileBox ..."))
	    (SETQ TOCDEPTHSTATS (NFSTAT.AnalyzeHist TOCDEPTHHIST 1 (
							NFSTAT.TraverseFileBoxHierarchy (
									   NCP.GetContentsFileBox)
											  
										     TOCDEPTHHIST 0)
						      NIL NIL))
	    (OR QuietFlg (NCP.PrintMsg NIL T 
				       "Traversing filebox hierarchy under ToBeFiled FileBox ..."))
	    (SETQ TBFDEPTHSTATS (NFSTAT.AnalyzeHist TBFDEPTHHIST 1 (
							NFSTAT.TraverseFileBoxHierarchy (
									  NCP.GetToBeFiledFileBox)
											  
										     TBFDEPTHHIST 0)
						      NIL NIL))
	    (OR QuietFlg (NCP.PrintMsg NIL T 
					 "Traversing filebox hierarchy under Orphans FileBox ..."))
	    (SETQ ORPHDEPTHSTATS (NFSTAT.AnalyzeHist ORPHDEPTHHIST 1 (
							 NFSTAT.TraverseFileBoxHierarchy (
									    NCP.GetOrphansFileBox)
											   
										    ORPHDEPTHHIST 0)
						       NIL NIL)))))
)
(DEFINEQ

(NFSTAT.AddCardDataToHist
  (LAMBDA (Hist NumParents NumToLinks NumFromLinks NumGlobalLinks)
                                                             (* rht: "15-Jun-86 20:40")

          (* * Insert the data for this card into given histogram)


    (NFSTAT.AddFieldEntryToHist CARDHISTENTRY Hist HISTENTRYPARENTS NumParents)
    (NFSTAT.AddFieldEntryToHist CARDHISTENTRY Hist HISTENTRYTOLINKS NumToLinks)
    (NFSTAT.AddFieldEntryToHist CARDHISTENTRY Hist HISTENTRYFROMLINKS NumFromLinks)
    (NFSTAT.AddFieldEntryToHist CARDHISTENTRY Hist HISTENTRYGLOBALLINKS NumGlobalLinks)))

(NFSTAT.AddFileBoxDataToHist
  (LAMBDA (FileBoxHist FiledCardLinks SubBoxLinks)           (* rht: "15-Jun-86 18:05")

          (* * Insert the data for this FileBox into the FileBox histogram.)


    (NFSTAT.AddFieldEntryToHist FILEBOXHISTENTRY FileBoxHist HISTENTRYFILEDCARDLINKS FiledCardLinks)
    (NFSTAT.AddFieldEntryToHist FILEBOXHISTENTRY FileBoxHist HISTENTRYSUBBOXLINKS SubBoxLinks)))

(NFSTAT.AddCardSizeDataToHist
  (LAMBDA (Hist1 Hist2 Size)                                 (* rht: "22-Jun-86 20:59")

          (* * Insert the size of this card into given histograms. The two 100 box histograms have different box widths.
	  The first runs from 0 to 9999 by 100's while the second runs from 10000 to 999999 by 1000's.)


    (OR (LESSP Size 109999)
	  (SETQ Size 109999))
    (LET (BoxNum)
         (if (LESSP Size 10000)
	     then (SETQ BoxNum (QUOTIENT Size 100))
		    (SETA Hist1 BoxNum (ADD1 (ELT Hist1 BoxNum)))
	   else (SETQ BoxNum (QUOTIENT (DIFFERENCE Size 10000)
					     1000))
		  (SETA Hist2 BoxNum (ADD1 (ELT Hist2 BoxNum)))))))

(NFSTAT.MakeFreshHistRecord
  (LAMBDA (HistRecordType)                                   (* rht: "15-Jun-86 20:49")

          (* * Make a zero-filled instance of HistRecordType.)


    (if (EQ HistRecordType (QUOTE CARDHISTENTRY))
	then (create CARDHISTENTRY
			 HISTENTRYPARENTS ← 0
			 HISTENTRYTOLINKS ← 0
			 HISTENTRYFROMLINKS ← 0
			 HISTENTRYGLOBALLINKS ← 0)
      elseif (EQ HistRecordType (QUOTE FILEBOXHISTENTRY))
	then (create FILEBOXHISTENTRY
			 HISTENTRYFILEDCARDLINKS ← 0
			 HISTENTRYSUBBOXLINKS ← 0))))

(NFSTAT.TraverseFileBoxHierarchy
  (LAMBDA (RootCard Hist CurrentDepth)                       (* rht: "15-Jun-86 21:03")

          (* * Walk down the filebox hierarchy till a non-filebox or empty filebox is found. Register its depth in Hist.
	  Return total number of terminals.)


    (LET (Children)
         (BLOCK)
         (if (AND (NCP.FileBoxP RootCard)
		      (SETQ Children (NCP.FileBoxChildren RootCard)))
	     then (for Child in Children sum (NFSTAT.TraverseFileBoxHierarchy Child Hist
											(ADD1
											  
										     CurrentDepth)))
	   else (SETA Hist CurrentDepth (ADD1 (ELT Hist CurrentDepth)))
		  1))))

(NFSTAT.ComputeSubstanceSize
  (LAMBDA (Card)                                             (* rht: "15-Jun-86 13:57")

          (* * Compute the size of this card's substance.)


    (LET ((Stream (NCP.CurrentNoteFileStream)))
         (WITH.MONITOR (NC.FetchMonitor Stream "NFSTAT.ComputeSubstanceSize")
		       (LET ((EndPtr (GETEOFPTR Stream))
			     IdentifierAndVersionNum)
			    (SETFILEPTR Stream (CADR (NC.GetPtrsFromIndex Stream Card)))
			    (AND (SETQ IdentifierAndVersionNum (NC.RobustReadItemIdentifier
				       Stream))
				   (if (GEQ (CDR IdentifierAndVersionNum)
						1)
				       then (NC.RobustReadDate Stream)
				     else T)
				   (EQ (CAR IdentifierAndVersionNum)
					 NC.ItemIdentifier)
				   (EQ Card (NC.RobustReadID Stream))
				   (CAR (NC.RobustReadAtom Stream))
				   (NC.RobustReadRegion Stream EndPtr)
				   (NC.CheckForValidSubstance Stream EndPtr Card)))))))

(NFSTAT.IncrementHashItem
  (LAMBDA (Item HashArray)                                   (* rht: "13-Jun-86 15:19")

          (* * Increment the value of Item in HashArray)


    (PUTHASH Item (ADD1 (OR (NUMBERP (GETHASH Item HashArray))
				  0))
	       HashArray)))

(NFSTAT.FetchCardTypeData
  (LAMBDA (CardType CardTypesHashArray)                      (* rht: "19-Jun-86 11:11")

          (* * Returns the data record for given card type.)


    (OR (GETHASH CardType CardTypesHashArray)
	  (PUTHASH CardType (create CARDTYPEDATA
					CARDTYPESIZEHIST1 ←(ARRAY NFSTAT.HistSize (QUOTE FIXP)
								    0 0)
					CARDTYPESIZEHIST2 ←(ARRAY NFSTAT.HistSize (QUOTE FIXP)
								    0 0)
					CARDTYPEHIST ←(ARRAY NFSTAT.HistSize NIL NIL 0)
					CARDTYPESTATS ←(create CARDSTATS
								 TOTAL ← 0))
		     CardTypesHashArray))))

(NFSTAT.FillInCardStats
  (LAMBDA (Hist CardStats)                                   (* rht: "19-Jun-86 01:03")

          (* * Fill in the various CardStats by analyzing Hist.)


    (with CARDSTATS CardStats (SETQ PARENTSSTATS (NFSTAT.AnalyzeHist Hist 1 TOTAL CARDHISTENTRY 
									 HISTENTRYPARENTS))
	    (SETQ TOLINKSSTATS (NFSTAT.AnalyzeHist Hist 1 TOTAL CARDHISTENTRY HISTENTRYTOLINKS))
	    (SETQ FROMLINKSSTATS (NFSTAT.AnalyzeHist Hist 1 TOTAL CARDHISTENTRY HISTENTRYFROMLINKS))
	    (SETQ GLOBALLINKSSTATS (NFSTAT.AnalyzeHist Hist 1 TOTAL CARDHISTENTRY 
							 HISTENTRYGLOBALLINKS)))))
)
(DECLARE: EVAL@COMPILE 
(DEFMACRO NFSTAT.AddFieldEntryToHist (HistType Hist FieldName Num)
	  (* * First make sure that Hist has a non-nil Num entry. Then increment FieldName field of 
	     the record in that entry. This is a macro so as to avoid call to RECORDACCESS.)
	  (BQUOTE (LET* ((Index (if (GEQ , Num NFSTAT.HistSize)
				    then
				    (SUB1 NFSTAT.HistSize)
				    else , Num))
			 (Val (ELT , Hist Index)))
			(if (NULL Val)
			    then
			    (SETQ Val (SETA , Hist Index (NFSTAT.MakeFreshHistRecord (QUOTE , 
											 HistType)))))
			(replace (, HistType , FieldName)
				 of Val with (ADD1 (fetch (, HistType , FieldName)
							  of Val))))))
(DEFMACRO
  NFSTAT.AnalyzeHist
  (Hists BoxWidths Total RecordType Field)
  (* * Compute statistics on the data in Hist into a STATSFROMHIST record. If Field is non-nil, then 
     hist entries are records of type RecordType and we're interested in Field of that record. 
     Otherwise, hist entries are numbers. This is a macro to avoid doing RECORDACCESS.)
  (* * Hists can be a list of histograms which should be the same length as IntervalWidths. The 
     latter gives the width of a histogram entry or box, one for each histogram.)
  (BQUOTE
    (LET ((StatsFromHist (create STATSFROMHIST TOTAL ← , Total MIN ← 99999.0 MAX ← 0.0 MEAN ← 0.0 
				 MEDIAN ← -1.0 MODE ← 0)))
	 (with STATSFROMHIST StatsFromHist
	       (for Hist in (MKLIST , Hists)
		    as BoxWidth in (MKLIST , BoxWidths)
		    bind TotalDivBy2 ← (FQUOTIENT TOTAL 2)
		    NumSeen ← 0 LastNonEmptyEndBox ← -1 StartBox ← 0 ModeVal ← 0 HalfBox do
		    (SETQ HalfBox (FQUOTIENT (SUB1 BoxWidth)
					     2))
		    (for i from 0 to (SUB1 NFSTAT.HistSize)
			 eachtime
			 (BLOCK)
			 bind MidBox EndBox do
			 (LET* ((Entry (ELT Hist i))
				(Val , (if (OR (NULL RecordType)
					       (NULL Field))
					   then
					   (BQUOTE (OR Entry 0))
					   else
					   (BQUOTE (OR (AND (type? , RecordType Entry)
							    (fetch (, RecordType , Field)
								   of Entry))
						       0)))))
			       (SETQ EndBox (PLUS StartBox BoxWidth -1))
			       (SETQ MidBox (PLUS StartBox HalfBox))
			       (* Update MAX and MIN.)
			       (if (GREATERP Val 0)
				   then
				   (if (LESSP MidBox MIN)
				       then
				       (SETQ MIN MidBox))
				   (if (GREATERP MidBox MAX)
				       then
				       (SETQ MAX MidBox)))
			       (* Keep running total in MEAN.)
			       (add MEAN (TIMES Val MidBox))
			       (* Update MODE.)
			       (if (GREATERP Val ModeVal)
				   then
				   (SETQ ModeVal Val)
				   (SETQ MODE MidBox))
			       (* Compute MEDIAN if not already done.)
			       (if (AND (LESSP MEDIAN 0.0)
					(GREATERP Val 0))
				   then
				   (if (EQUAL NumSeen TotalDivBy2)
				       then
				       (SETQ MEDIAN (FQUOTIENT (PLUS LastNonEmptyEndBox StartBox)
							       2))
				       elseif
				       (LESSP TotalDivBy2 (add NumSeen Val))
				       then
				       (SETQ MEDIAN (FPLUS StartBox (FQUOTIENT (TIMES (DIFFERENCE
											NumSeen 
										      TotalDivBy2)
										      (SUB1 BoxWidth))
									       Val)))
				       else
				       (SETQ LastNonEmptyEndBox EndBox)))
			       (* Set up StartBox for next iteration.)
			       (add StartBox BoxWidth))))
	       (* Divide total in MEAN by num cards.)
	       (SETQ MEAN (FQUOTIENT MEAN TOTAL))
	       StatsFromHist))))
)
(* * Miscellaneous accelerators.)

(DEFINEQ

(NFSTAT.AnalyzeSetsOfNoteFiles
  (LAMBDA NumArgs                                            (* rht: "22-Jun-86 21:43")

          (* * Analyze sets of notefiles, each set having the same prefix for their OutputFileName. Args should be a proplist
	  of pairs, the first of which is a list of file names and the second of which is an OutputFilename prefix.)


    (for ArgNum from 1 to NumArgs by 2 do (LET ((FileNames (ARG NumArgs ArgNum))
							  (Prefix (ARG NumArgs (ADD1 ArgNum))))
						         (NFSTAT.AnalyzeListOfNoteFiles FileNames 
											  Prefix)))))

(NFSTAT.AnalyzeListOfNoteFiles
  (LAMBDA (NoteFiles OutputNamePrefix)                       (* rht: "22-Jun-86 18:46")

          (* * Analyze a whole list of notefiles.)


    (for NoteFile in NoteFiles do (NFSTAT.AnalyzeRemoteNoteFile NoteFile (QUOTE {dsk1})
									(NFSTAT.MakeOutputFileName
									  NoteFile OutputNamePrefix)))
    ))

(NFSTAT.MakeOutputFileName
  (LAMBDA (NoteFileName Owner)                               (* rht: "22-Jun-86 17:11")

          (* * Create a file name for the output file.)


    (PACKFILENAME (QUOTE HOST)
		    (QUOTE {dsk2})
		    (QUOTE DIRECTORY)
		    NIL
		    (QUOTE EXTENSION)
		    (QUOTE data)
		    (QUOTE VERSION)
		    NIL
		    (QUOTE NAME)
		    (CONCAT Owner "-" (FILENAMEFIELD NoteFileName (QUOTE NAME))))))

(NFSTAT.InspectDataFile
  (LAMBDA (FileName)                                         (* rht: "22-Jun-86 23:02")

          (* * Open, read and inspect a data file.)


    (LET ((File (OPENFILE FileName (QUOTE INPUT))))
         (if File
	     then (INSPECT (PROG1 (HREAD File T)
					(CLOSEF File)))))))
)
(* * Functions for plotting.)

(DECLARE: EVAL@COMPILE 
(DEFMACRO NFSTAT.HistPlot (Hist Label &OPTIONAL RecordName &OPTIONAL FieldName)
	  (* * Create a histogram plot using HISTPLOT from the PLOTEXAMPLES package of that field of 
	     Hist given by FieldName. If FieldName is nil, then Hist is assumed to contain integers 
	     rather than datatype entries.)
	  (if RecordName then
	      (BQUOTE (HISTPLOT (for i from 0 to (SUB1 NFSTAT.HistSize)
				     collect
				     (LET ((HistEntry (ELT , Hist i)))
					  (CONS i (OR (AND (type? , RecordName HistEntry)
							   (fetch (, RecordName , FieldName)
								  of HistEntry))
						      0))))
				(OR , Label (CONCAT (QUOTE , FieldName)
						    " of "
						    (QUOTE , RecordName)))))
	      else
	      (BQUOTE (HISTPLOT (for i from 0 to (SUB1 NFSTAT.HistSize)
				     collect
				     (LET ((HistEntry (ELT , Hist i)))
					  (CONS i (OR (NUMBERP HistEntry)
						      0))))
				, Label))))
)
(DECLARE: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY COMPILERVARS 

(ADDTOVAR NLAMA )

(ADDTOVAR NLAML )

(ADDTOVAR LAMA NFSTAT.AnalyzeSetsOfNoteFiles)
)
(PUTPROPS NOTEFILESTATS COPYRIGHT ("Xerox Corporation" 1986))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (5511 10751 (NFSTAT.AnalyzeRemoteNoteFile 5521 . 8711) (NFSTAT.GatherNoteFileData 8713
 . 10749)) (10782 17410 (NFSTAT.ProcessCards 10792 . 16091) (NFSTAT.ProcessFileBoxHierarchies 16093 . 
17408)) (17411 23032 (NFSTAT.AddCardDataToHist 17421 . 18017) (NFSTAT.AddFileBoxDataToHist 18019 . 
18425) (NFSTAT.AddCardSizeDataToHist 18427 . 19178) (NFSTAT.MakeFreshHistRecord 19180 . 19752) (
NFSTAT.TraverseFileBoxHierarchy 19754 . 20470) (NFSTAT.ComputeSubstanceSize 20472 . 21481) (
NFSTAT.IncrementHashItem 21483 . 21782) (NFSTAT.FetchCardTypeData 21784 . 22397) (
NFSTAT.FillInCardStats 22399 . 23030)) (26437 28279 (NFSTAT.AnalyzeSetsOfNoteFiles 26447 . 27066) (
NFSTAT.AnalyzeListOfNoteFiles 27068 . 27447) (NFSTAT.MakeOutputFileName 27449 . 27928) (
NFSTAT.InspectDataFile 27930 . 28277)))))
STOP