<!-- Random Index Generation (History Controlled) 04/21/1998-05/09/2006 --> <!-- -------------------------------------------------------- 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 item. // 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 item. // 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 // multiple 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 found among previously saved Cnt=Cnt-1 // Decrement the attempts reverse counter if (Cnt<=0) // Limit number of attempts to number of array items {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 } } //-->