<!--
// Handles value sorting and tri-gram matching

// ============== Sort Routines

// Should these 2 values be swapped based on the tri-gram Score, sortOrder & name properties
function DoSwap ( v1 , v2 , doneTrigram )
{
  if ( doneTrigram )
  {
    if ( v1.score < v2.score )
      return ( true ) ;
    else if ( v1.score > v2.score )
      return ( false ) ;
    else
      return ( v1.text > v2.text ) ;
  }
  else
  {    
    if ( v1.sortOrder != -1 )
    {
      if ( v1.sortOrder > v2.sortOrder )
        return ( true ) ;
      else if ( v1.sortOrder == v2.sortOrder )
      {
        if ( v1.text > v2.text )
          return ( true ) ;
      }
    }
  }
  return ( false ) ;
}

// Quicksort routine (does what it says on the tin)
function Quicksort ( values , loBound , hiBound , doneTri )
{
  var pivot, loSwap, hiSwap, temp;
  if (hiBound - loBound == 1)
  {
    if ( DoSwap ( values[loBound] , values[hiBound] , doneTri ) )
    {
      temp = values[loBound];
      values[loBound] = values[hiBound];
      values[hiBound] = temp;
    }
    return;
  }
  pivot = values[parseInt((loBound + hiBound) / 2)];
  values[parseInt((loBound + hiBound) / 2)] = values[loBound];
  values[loBound] = pivot;
  loSwap = loBound + 1;
  hiSwap = hiBound;
  do {
    while ( ( loSwap <= hiSwap ) && ! DoSwap ( values [ loSwap ] , pivot , doneTri ) )
      loSwap++;
    while ( ( hiSwap >= loSwap ) && DoSwap ( values [ hiSwap ] , pivot , doneTri ) )
      hiSwap--;
    if (loSwap < hiSwap)
    {
      temp = values[loSwap];
      values[loSwap] = values[hiSwap];
      values[hiSwap] = temp;
    }
  } while (loSwap < hiSwap);
  values[loBound] = values[hiSwap];
  values[hiSwap] = pivot;
  if (loBound < hiSwap - 1)
    Quicksort(values, loBound, hiSwap - 1, doneTri);
  if (hiSwap + 1 < hiBound)
    Quicksort(values, hiSwap + 1, hiBound, doneTri);
}

// Sort an array of value objects
function SortValues ( values , doneTrigram )
{
  if ( ( ( values.length > 100 ) && ( ! doneTrigram ) ) || ( values.length == 0 ) )
    return ;
  Quicksort ( values , 0 , values.length - 1 , doneTrigram ) ;
}

// Nico punctuation Fix 06-May-05
function ClenseString( searchStr )
{
  var ripThese = "!?,.()/:" ;
  var aResult = "" ;
  var found = new Boolean(false) ;
  
    for ( i = 0; i < searchStr.length ; i++ )
  	{
  		PunctTemp = searchStr.charAt(i)
    	found = false ;
    	
    	for ( j = 0; j < ripThese.length; j++ )
    	{
    	
      		if ( PunctTemp == ripThese.charAt(j) )
      		{
        		found = true ;
        		aResult += " " + PunctTemp + " ";
      		}
    	}
    	
    	if ( found == false )
    	{
      		aResult += PunctTemp ;
      	}
  	}
  return ( aResult ) ;
}
//

// ============== Tri-Gram Searcher

function GetTris ( searchStr ) //will return the different trigrams for a string
{
  var aResult = new Array ;
  searchStr = " " + searchStr.toLowerCase() + " " ;
  if ( searchStr.length >= 3 )
  {
    searchStr = searchStr.replace(/  /," "); // Compress multiple spaces into single spaces
    var i , j , iTemp ;
    for ( i = 0 ; i < searchStr.length - 2 ; i++ )
    {
      iTemp = searchStr.charCodeAt(i)*65536 + searchStr.charCodeAt(i+1)*256 + searchStr.charCodeAt(i+2) ;
      for ( j = 0 ; j < aResult.length ; j++ )
        if ( aResult[j] == iTemp )
          break;
      if ( j == aResult.length )
        aResult[j] = iTemp ;
    }
  }
  return ( aResult ) ;
}

function CalcScore ( tris , value )
{
//Nico: adding space before and after punctiations.
	CleanValue = ClenseString( value.text );
//
  if ( tris.length == 0 )
    return ( -1 ) ;
  var comp ;
  if ( value.trigrams != null )
    comp = value.trigrams ;
  else
  {
    comp = GetTris ( CleanValue ) ;
    value.trigrams = comp ;
  }
  var nMatches = 0 ;
  var i , c ;
  for ( i = 0 ; i < comp.length ; i++ )
  {
    for ( c = 0 ; c < tris.length ; c++ )
      if ( tris[c] == comp[i] )
        break ;
    if ( c != tris.length )
      nMatches++ ;
  }
  return ( Math.round ( ( nMatches / tris.length ) * 100 ) ) ;
}

function CalcValueTriGrams ( searchStr )
{
  var strTri = GetTris ( searchStr ) ;
  if ( strTri.length > 0 )
  {
    question.doneTrigram = true ;
    var sSplit = searchStr.split(" ");
    var c ;
    var ss = "" ;
    for ( c = 0 ; c < sSplit.length ; c++ )
    {
      if ( ss.length > 0 )
        ss += "|" ;
      ss += sSplit [ c ] ;
    }
    var rTest = new RegExp ( "(" + ss + ")" , "i" ) ;
    for ( c = 0 ; c < question.values.length ; c++ )
    {
    if ( question.values[c].alwaysShow )
        	question.values[c].score = -1 ;
      else {
        question.values[c].score = CalcScore ( strTri , question.values[c] ) ;
        }
	    if ( question.values[c].score == 100 ) {
//if the search score is 100%, then the search string will appear in bold in the displayed value
			question.values[c].display = question.values[c].text.toLowerCase(rTest);
			boldVal = searchStr.toLowerCase()
	  		question.values[c].display = question.values[c].display.replace ( boldVal , "<B>"+searchStr+"</B>" );
	  	} else {
	  		question.values[c].display = question.values[c].text ;
 		}
    }
  }
  else
  {
    question.doneTrigram = false ;
    for ( c = 0 ; c < question.values.length ; c++ )
    {
      question.values[c].score = -1 ;
      question.values[c].display = question.values[c].text ;
	}
  }
  SortValues ( question.values , question.doneTrigram ) ;
  }

-->