<!-- Random Index Generation (History Controlled)  04/21/1998-10/14/2003 -->
<!-- -------------------------------------------------------- 10/14/2003 -->
<!-- www.davar.net/RANDOM.JS                                             -->
<!-- Copyright (C) 1998-2003 by Vladimir Veytsel                         -->
<!--

// Generates and returns a random integer number in the range of [1-Max_Ind]
// that serves as an index for random selection of an array element.

// In order to provide a facility for selection of the specified index (handy
// for individual adjustment of items to be selected) RANDOM has the ability
// to be referenced with a SINGLE numeric argument, which indicates that it
// is the index to be returned as RANDOM value.

// The history of previous selections (comma-delimited index list) is passed
// as an argument and serves for generation a random index which is not present
// in the index history.

// A predefined history depth is maintained by placing a new index in front of
// the list and truncating list from the right to the specified length.

// The returned value is the modified history list, containing newly generated
// random index as its FIRST element.

// NOTE: Ideally a cycle of purely random attempts should work until a new
// index is generated (which is not present in the history of the previously
// generated indexes).  However, with this approach the response time tends
// to be more than what is acceptable.  To keep the response time always
// within the reasonable limits following method was chosen as a result of
// the experiments:
// - Total maximum number of attempts to generate a random index is limited
//   by total number of items in the item list (passed to RANDOM as Max_Ind).
// - Up to 3/4 of it can be used for attempts to generate index at random.
// - Remaining 1/4 of it can be used to generate index by "+1" incrementing.
// - If none of the above worked, returned value is index next to previous.

   function RANDOM(Ind_Hist,Hist_Depth,Max_Ind)
            {// Ind_Hist    - History of generated indexes (i1,i2,...,iN)
             // Hist_Depth  - History depth (limited by Max_Ind+1)
             // Max_Ind     - Maximum value of index range (minimum: 1)

             if ((Ind_Hist!="")&&              // Not empty AND
                 (Ind_Hist.indexOf(",")==-1))  // Is not the history list
                {if ((Ind_Hist<1)||
                     (Ind_Hist>Max_Ind))
                    document.write("<BR>Specified index <FONT COLOR=Red><BLINK><B>",
                                   Ind_Hist,"</B></BLINK></FONT> is out of item array range [<B>1</B>,<B>"
                                   ,Max_Ind,"</B>]<BR><BR>",
                                   "Please select index within the valid range of [<B>1</B>,<B>"
                                   ,Max_Ind,"</B>]<BR>",
                                   "or drop <B>?<FONT COLOR=Red>",Ind_Hist,"</FONT></B> altogether to select ",
                                   "item at random.<BR>")
                 else
                    return Ind_Hist+","  // Index for specific item selection
                }
             else
                {if (Hist_Depth>Max_Ind)  // Limit history depth by maximum index
                     Hist_Depth=Max_Ind

                 H=Ind_Hist.split(",",Hist_Depth)  // Split history list into index array

                 // document.write("Input_History=",H,"     ")  // Debugging

                 // Generate next index (non-repeatable for prev of specif depth)
                 // (logic below is necessary to minimize the response time)

                 Cnt=Max_Ind            // Attempts reverse counter
                 K=Math.round(Cnt/4*3)  // Number of purely random attempts
                 L=Cnt-K                // Number of "+1" incremental attempts
                 Valid=false            // Index valid (non-repeatable) flag

                 while (!Valid)      // Repeat until valid index is generated
                       {if (Cnt>=K)  // Attempts counter is within "random" range
                           i=Math.floor(Math.random()*Max_Ind)%Max_Ind+1
                        if (Cnt<L)   // Attempts counter is within "incremental" range
                           i=((i+1)%Max_Ind)+1       // Get "+1" incremental after previous
                        Found=false
                        for (j=0;j<Hist_Depth;j++)  // Compare new index with all previously saved
                            if (Number(H[j])==i)
                               Found=true            // Index is found among previously saved
                        Valid=!Found   // New valid is not not found among previously saved
                        Cnt=Cnt-1      // Decrement the attempts reverse counter
                        if (Cnt<=0)    // Limit number of attempts to number of taglines
                           {i=Max_Ind/2
                            if (H[0]!="")
                               i=((Number(H[0])+1)%Max_Ind)+1  // Get next seq index to prev displayed
                            Valid=true
                           }
                       }

                 for (j=Hist_Depth-1;j>0;j--)  // Push history array down to make room
                     H[j]=H[j-1]               // for the newly generated index

                 H[0]=i                        // Put new index at the top of history array

                 // document.write("     Output_History=",H,"<BR>")  // Debugging

                 return H.join()             // Join index history array into a comma-delimited list
                                             // and return it as a function value
                }
            }
//-->
  

