// Code and display of Cat Breed Selector program, Copyright (c) 2006, Telemark Productions. 
//May not be duplicated in whole or in part. All rights reserved.
var browserOS;
var browserName;
var browserVersion;

function getBrowserID() {
    var appVersion = navigator.appVersion;
    if (appVersion.indexOf("Win") > 0) {
        browserOS = "WIN";
    } else if (appVersion.indexOf("Mac") > 0) {
        browserOS = "MAC";
    } else if (appVersion.indexOf("X11") > 0) {
        browserOS = "UNX";
    } else {
        browserOS = "UNK";
    }

    var browser = navigator.appName;
    if (browser.substring(0, 8) == "Netscape") {
        browserName = "NN";
    } else if (browser.substring(0, 9) == "Microsoft") {
        browserName = "IE";
    } else {
        browserName = browser;
    }

    var msidx = appVersion.indexOf("MSIE");
    if (msidx > 0) {
       browserVersion = parseFloat(appVersion.substring(msidx+5)) * 1000;
    } else {
       browserVersion = parseFloat(appVersion) * 1000;
    }
}

// --------------------------------------------
var debugWin;
function debugwrite(str) {
    if (debugWin == null || debugWin.closed) {
        debugWin = window.open("", "debugWin", "width=450,height=600,scrollbars,resizable");
    }
    debugWin.document.write(str + "<BR>");
}

// --------------------------------------------
function islower(c) {
    if (c >= 'a' && c <= 'z')
        return true;
    else
        return false;
}

// --------------------------------------------
var catData;

function OneCat(n, d, f) {
    this.name = n;
    this.data = d;
    this.file = f;
    this.score = 0;
}

function CatData() {

}

function initCatData() {

catData = new CatData();
catData.cat0 = new OneCat("Abyssinian",                             "2S0S5220452N31", "abyssini");
catData.cat1 = new OneCat("American Bobtail (medium and long coat)","4MLM4334532Y33", "amerbobt");
catData.cat2 = new OneCat("American Curl (short and long coat)",    "2SLM4324451Y33", "amercurl");
catData.cat3 = new OneCat("American Shorthair",                     "4S0B2220331Y53", "amershor");
catData.cat4 = new OneCat("American Wirehair",                      "4M0M3310532Y53", "amerwire");
catData.cat5 = new OneCat("Balinese",                               "2M0V5520552Y11", "balinese");
catData.cat6 = new OneCat("Bengal",                                 "4S0M5220453N31", "bengal__");
catData.cat7 = new OneCat("Birman",                                 "4L0M2240531Y35", "birman__");
catData.cat8 = new OneCat("Bombay",                                 "3S0M4410452Y33", "bombay__");
catData.cat9 = new OneCat("British Shorthair",  "4M0B2230312Y55", "britshor");
catData.cat10 = new OneCat("Burmese",           "3S0M4420552Y31", "burmese_");
catData.cat11 = new OneCat("Chartreux",         "4M0B3130432Y35", "chartreu");
catData.cat12 = new OneCat("Colorpoint Shorthair", "2S0V5510552Y11", "coloshor");
catData.cat13 = new OneCat("Cornish Rex",       "2S0S5210552N11", "cornrex_");
catData.cat14 = new OneCat("Cymric (longhaired Manx)", "4L0B3340531Y55", "cymric__");
catData.cat15 = new OneCat("Devon Rex",         "2S0S4210552Y33", "devorex_");
catData.cat16 = new OneCat("Egyptian Mau",      "3S0M5320552N31", "egypmau_");
catData.cat17 = new OneCat("European Burmese",  "3S0M4420552Y31", "euroburm");
catData.cat18 = new OneCat("Exotic Shorthair",  "4S0C1240431Y35", "exotshor");
catData.cat19 = new OneCat("Havana Brown",      "3S0M3210551Y33", "havabrow");
catData.cat20 = new OneCat("Himalayan",         "4L0C1250451Y35", "himalaya");
catData.cat21 = new OneCat("Japanese Bobtail (short and long coat)","3SLS4424552Y33", "japabobt");
catData.cat22 = new OneCat("Javanese",          "2M0V5520552Y11", "javanese");
catData.cat23 = new OneCat("Korat",             "3S0B4310552Y31", "korat___");
catData.cat24 = new OneCat("LaPerm (short and long coat)",          "3SLM3223432Y35", "laperm__");
catData.cat25 = new OneCat("Maine Coon",        "5L0M3240531Y55", "maincoon");
catData.cat26 = new OneCat("Manx",              "4S0B3330531Y55", "manx____");
catData.cat27 = new OneCat("Munchkin (short and long coat)",        "2SLM3324432Y53", "munchkin");
catData.cat28 = new OneCat("Nebelung",          "2M0M3240433Y53", "nebelung");
catData.cat29 = new OneCat("Norwegian Forest Cat", "5L0M3230531Y35", "norforca");
catData.cat30 = new OneCat("Ocicat",            "4S0M5410432N31", "ocicat__");
catData.cat31 = new OneCat("Oriental (Longhair)", "2M0V5520552Y11", "orielong");
catData.cat32 = new OneCat("Persian",           "4L0C1250451Y35", "persian_");
catData.cat33 = new OneCat("Peterbald",         "2S0V4440552Y33", "peterbal");
catData.cat34 = new OneCat("Pixiebob (short and medium coat)",      "4SMB4223532Y33", "pixiebob");
catData.cat35 = new OneCat("RagaMuffin",        "4L0M2230531Y35", "ragamuff");
catData.cat36 = new OneCat("Ragdoll",           "4L0M2230531Y35", "ragdoll_");
catData.cat37 = new OneCat("Russian Blue",      "2S0S3220433Y53", "russblue");
catData.cat38 = new OneCat("Scottish Fold (short and long coat)",   "3SLM3234432Y33", "scotfold");
catData.cat39 = new OneCat("Selkirk Rex (medium and long coat)",    "4MLB2334432Y35", "selkrex_");
catData.cat40 = new OneCat("Siamese",           "3S0V5510552Y11", "siamese_");
catData.cat41 = new OneCat("Siberian",          "5L0M3230431Y35", "siberian");
catData.cat42 = new OneCat("Singapura",         "1S0M4210552Y31", "singapur");
catData.cat43 = new OneCat("Snowshoe",          "4S0M4420532Y33", "snowshoe");
catData.cat44 = new OneCat("Somali (longhaired Abyssinian)", "4L0S5240452N31", "somali__");
catData.cat45 = new OneCat("Sphynx",            "3S0M4440551Y35", "sphynx__");
catData.cat46 = new OneCat("Tonkinese",         "3S0M5420552Y13", "tonkines");
catData.cat47 = new OneCat("Turkish Angora",    "3L0S4330552Y33", "turkango");
catData.cat48 = new OneCat("Turkish Van",       "4L0M5440553N33", "turkvan_");
catData.cat49 = new OneCat("Oriental (Shorthair)", "2S0V5520552Y11", "orieshor");
catData.numCats = 50;
}

// --------------------------------------------
function Const() {

}

    Const.Size   = 0;
    Const.Coat1  = 1;
    Const.Coat2  = 2;
    Const.Body   = 3;
    Const.Active = 4;
    Const.Vocal  = 5;
    Const.Grooming1    = 6;
    Const.Grooming2    = 7;
    Const.Affectionate = 8;
    Const.Demanding    = 9;
    Const.Children     = 10;
    Const.Seniors      = 11;
    Const.Independence = 12;

    Const.EXACTMATCH = 50;
    Const.OFFBYONE = Const.EXACTMATCH/2;
    Const.OFFBYTWO = Const.EXACTMATCH/4;
    Const.IMPORTANTMATCH = Const.EXACTMATCH*2;
    Const.REALLYIMPORTANTMATCH = Const.IMPORTANTMATCH*2;

// --------------------------------------------

var userSizeM="";
var userCoatM="";
var userTypesM="";
var userActiveM="";
var userVocal = 0;
var userGrooming = 0;
var userAffection = 0;
var userDemanding = 0;
var userChildrenM;
var userChildren;
var userSeniors;
var userAdults;
var userIndependence = 1;

// --------------------------------------------
function quickSortSwap(idx, odx, theList) {
    temp = theList["cat"+idx];
    theList["cat"+idx] = theList["cat"+odx];
    theList["cat"+odx] = temp;
}

function quickSort(lower, upper, theList) {
    var pivot;
    var isLess;

   if (lower < upper) {
      quickSortSwap(lower, Math.floor((upper+lower)/2), theList);
      pivot = theList["cat"+lower];
      m = lower;
      for (var idx = lower + 1; idx <= upper; idx++) {
          isLess = false;
          if (theList["cat"+idx].score < pivot.score) {
              isLess = true;
          } else if (theList["cat"+idx].score == pivot.score) {
              if (theList["cat"+idx].name > pivot.name) {
                  isLess = true;
              }
          }

          if (isLess) {
             m++;
             quickSortSwap(m, idx, theList);
         }
      }
      quickSortSwap(lower, m, theList);
      quickSort(lower, m - 1, theList);
      quickSort(m + 1, upper, theList);
   }
}

// ------------------------------
function DoTheSort(theList) {
    quickSort(0, theList.numCats-1, theList);
}

// ------------------------------
function getVarsFromCookie() {
    var allCookies = "" + document.cookie;
    var start = allCookies.indexOf("catSelectorData=");
//    alert("allCookies=" + allCookies);
    //debugwrite("allCookies=" + allCookies);

    if (start == -1) {
        //alert("Cookie data not found.");
    } else {
        start += "catSelectorData=".length;
        var end = allCookies.indexOf(':', start);
        if (end == -1) {
            end = allCookies.length;
        }

        var cookieString = unescape(allCookies.substring(start, end));
  //      alert("jamal checking cookieString "+cookieString);
        var tokens = cookieString.split("&");
        userSizeM = tokens[0];
        userCoatM = tokens[1];
        userTypesM = tokens[2];
        userActiveM = tokens[3];
        userVocal = tokens[4];
        userGrooming = tokens[5];
        userAffection = tokens[6];
        userDemanding = tokens[7];
        userChildrenM = tokens[8];
        userSeniors = tokens[9];
        userAdults = tokens[10];
        userIndependence = tokens[11];

        // The token in the cookie has all the boxes the user checked.
        // But here we want the userChildren variable to contain just
        // the value of the youngest person the user has. So we go
        // through in reverse order so we'll end up with the youngest.
        userChildren = 0;
        if (userChildrenM.indexOf("3") > -1) {
            userChildren = "3";
        }
        if (userChildrenM.indexOf("2") > -1) {
            userChildren = "2";
        }
        if (userChildrenM.indexOf("1") > -1) {
            userChildren = "1";
        }

        /*
        debugwrite("userSizeM=" + userSizeM);
        debugwrite("userCoatM=" + userCoatM);
        debugwrite("userTypesM=" + userTypesM);
        debugwrite("userActiveM=" + userActiveM);
        debugwrite("userVocal=" + userVocal);
        debugwrite("userGrooming=" + userGrooming);
        debugwrite("userAffection=" + userAffection);
        debugwrite("userDemanding=" + userDemanding);
        debugwrite("userChildren=" + userChildren);
        debugwrite("userSeniors=" + userSeniors);
        debugwrite("userAdults=" + userAdults);
        debugwrite("userIndependence=" + userIndependence);
        */
    }
}

// --------------------------------------------
// Figure out what the maximum possible score is that
// any cat could get.  This is not a constant because any zero answers
// from the user, meaning that he has no preference, means that that
// attribute won't contribute to the maximum score.
// It's important that everything that contributes to the scores be
// reflected in maxScore or the normalization at the end won't come out right.
function getMaxPossibleScore() {
    var maxScore;

    maxScore = 0;

    // 1. size
    if (userSizeM != null && userSizeM.length > 0) {
        maxScore += Const.EXACTMATCH;
        //debugwrite("maxScore incr for size=" + maxScore);
    }

    // 2. coat
    if (userCoatM != null && userCoatM.length > 0) {
        maxScore += Const.EXACTMATCH;
        //debugwrite("maxScore incr for coat=" + maxScore);
    }

    // 3. looks / body type
    if (userTypesM != null && userTypesM.length > 0) {
        maxScore += Const.REALLYIMPORTANTMATCH;
        //debugwrite("maxScore incr for looks=" + maxScore);
    }

    // 4. active
    if (userActiveM != null && userActiveM.length > 0) {
        maxScore += Const.EXACTMATCH;
        //debugwrite("maxScore incr for active=" + maxScore);
    }

    // 5. vocal
    if (userVocal != 0) {
        maxScore += Const.EXACTMATCH;
        //debugwrite("maxScore incr for vocal=" + maxScore);
    }

    // 6. grooming
    if (userGrooming != 0) {
        maxScore += Const.EXACTMATCH;
        //debugwrite("maxScore incr for grooming=" + maxScore);
    }

    // 7. affectionate
    if (userAffection != 0) {
        maxScore += Const.EXACTMATCH;
        //debugwrite("maxScore incr for affection=" + maxScore);
    }

    // 8. demanding
    if (userDemanding != 0) {
        maxScore += Const.EXACTMATCH;
        //debugwrite("maxScore incr for demanding=" + maxScore);
    }

    // 9. children
    if (userChildren > 0) {
        maxScore += Const.EXACTMATCH;
        //debugwrite("maxScore incr for children=" + maxScore);
    }

    // 9a. Seniors
    if (userSeniors == "Y") {
        maxScore += Const.EXACTMATCH;
        //debugwrite("maxScore incr for seniors=" + maxScore);
    }

    // 10. independence - there's no "no preference" choice here.
    maxScore += Const.EXACTMATCH;
    //debugwrite("maxScore incr for independence=" + maxScore);

    //debugwrite("maxScore=" + maxScore);

    return maxScore;
}

// --------------------------------------------
function doTheRankings() {
var idx, catIdx, catAttr, usrAttr, catAttr2;
var maxScore, oneCatData;

    // Bizarre bug that sometimes catData doesn't get properly initialized, even though intCatData()
    // is called by the onload handler.
    if (catData == null) {
        initCatData();
    }
    if (catData.numCats == null) {
        initCatData();
    }

    maxScore = getMaxPossibleScore();

    // --------------------------------------------
    // The main loop: for each cat, compare its data to the
    // user's choices, keeping score along the way.

    //debugwrite("numCats =" + catData.numCats);

    for (catIdx=0; catIdx < catData.numCats; catIdx++) {
        oneCatData = catData["cat" + catIdx].data;
        var thisScore = 0;

        /* The type, size and coat attributes allow the user to select multiple answers.
         * So if any of the user's choices match the cat's attribute, we give the
         * maximum points.
         * For cat type, we don't give any off-by-one points since
         * it's not a range where adjacent attributes are closely related.
         */

        // 1. size

        catAttr = null;
        catAttr = oneCatData.charAt(Const.Size);
        for (idx=0; idx < userSizeM.length; idx++) {
            if (userSizeM.charAt(idx) == catAttr) {
                thisScore += Const.EXACTMATCH;
                break;
            } else if (Math.abs(catAttr - userSizeM.charAt(idx)) == 1) {
                thisScore += Const.EXACTMATCH;
                break;
            } else if (Math.abs(catAttr - userSizeM.charAt(idx)) == 2) {
                thisScore += Const.OFFBYTWO;
                break;
            }
        }

        // 2. coat

        catAttr = oneCatData.charAt(Const.Coat1);
        catAttr2 = oneCatData.charAt(Const.Coat2);
        // Used under grooming to know which one to match against.
        var userCoatPrefMatchedCat2 = false;
        if (userCoatM.length > 0) {

            // We don't want to give double points to two-type cats that happen to match
            // two of the user's choices. So as soon as we find a match, we break out
            // of the loop.
            for (idx=0; idx < userCoatM.length; idx++) {
                if (userCoatM.charAt(idx) == catAttr) {
                    thisScore += Const.EXACTMATCH;
                    break;
                }
                if (userCoatM.charAt(idx) == catAttr2) {
                    thisScore += Const.EXACTMATCH;
                    userCoatPrefMatchedCat2 = true;
                    break;
                }
            }
        }

        // 3. cat body type

        catAttr = oneCatData.charAt(Const.Body);
        if (catAttr == 'C') {           // cobby
            if (userTypesM.indexOf('C') > -1) {
                thisScore += Const.REALLYIMPORTANTMATCH;
            } else if (userTypesM.indexOf('B') > -1) {
                thisScore += Const.IMPORTANTMATCH;
            } else if (userTypesM.indexOf('M') > -1) {
                thisScore += Const.EXACTMATCH;
            }
        } else if (catAttr == 'B') {    // semi-cobby
            if (userTypesM.indexOf('B') > -1) {
                thisScore += Const.REALLYIMPORTANTMATCH;
            } else if (userTypesM.indexOf('C') > -1) {
                thisScore += Const.IMPORTANTMATCH;
            } else if (userTypesM.indexOf('M') > -1) {
                thisScore += Const.IMPORTANTMATCH;
            }
        } else if (catAttr == 'M') {    // moderate
            if (userTypesM.indexOf('M') > -1) {
                thisScore += Const.REALLYIMPORTANTMATCH;
            } else if (userTypesM.indexOf('B') > -1) {
                thisScore += Const.IMPORTANTMATCH;
            } else if (userTypesM.indexOf('S') > -1) {
                thisScore += Const.IMPORTANTMATCH;
            }
        } else if (catAttr == 'S') {    // slender
            if (userTypesM.indexOf('S') > -1) {
                thisScore += Const.REALLYIMPORTANTMATCH;
            } else if (userTypesM.indexOf('M') > -1) {
                thisScore += Const.IMPORTANTMATCH;
            } else if (userTypesM.indexOf('V') > -1) {
                thisScore += Const.IMPORTANTMATCH;
            }
        } else if (catAttr == 'V') {    // svelte
            if (userTypesM.indexOf('V') > -1) {
                thisScore += Const.REALLYIMPORTANTMATCH;
            } else if (userTypesM.indexOf('S') > -1) {
                thisScore += Const.IMPORTANTMATCH;
            } else if (userTypesM.indexOf('M') > -1) {
                thisScore += Const.EXACTMATCH;
            }
        }

        /*
        var foundExactMatch = false;
        for (idx=0; idx < userTypesM.length; idx++) {
            if (userTypesM.charAt(idx) == catAttr) {
                thisScore += Const.REALLYIMPORTANTMATCH;
                foundExactMatch = true;
                break;
            }
        }
        if ( ! foundExactMatch) {

        }
        */

        // 4. active

        catAttr = oneCatData.charAt(Const.Active);
        for (idx=0; idx < userActiveM.length; idx++) {
            if (userActiveM.charAt(idx) == catAttr) {
                thisScore += Const.EXACTMATCH;
                break;
            } else if (userActiveM.charAt(idx) != 3 && Math.abs(catAttr - userActiveM.charAt(idx)) == 1) {
                thisScore += Const.EXACTMATCH;
                break;
            } else if (Math.abs(catAttr - userActiveM.charAt(idx)) == 2) {
                thisScore += Const.OFFBYONE;
                break;
            }
        }

        // 5. vocal

        catAttr = oneCatData.charAt(Const.Vocal);
        if (catAttr != 0 && userVocal != 0) {
            if (catAttr == userVocal) {
                thisScore += Const.EXACTMATCH;
            } else if (userVocal != 3 && Math.abs(catAttr - userVocal) == 1) {
                thisScore += Const.EXACTMATCH;
            } else if (Math.abs(catAttr - userVocal) == 2) {
                thisScore += Const.OFFBYONE;
            }
        }

        // 6. grooming

        if (userGrooming != 0) {
            if (userCoatPrefMatchedCat2) {
                catAttr = oneCatData.charAt(Const.Grooming2);
            } else {
                catAttr = oneCatData.charAt(Const.Grooming1);
            }
            if (catAttr <= userGrooming) {
                thisScore += Const.EXACTMATCH;
            } else if (catAttr - userGrooming == 1) {
                thisScore += Const.OFFBYONE;
            }
        }

        // 7. affectionate

        catAttr = oneCatData.charAt(Const.Affectionate);
        if (catAttr != 0 && userAffection != 0) {
            if (catAttr == userAffection) {
                thisScore += Const.EXACTMATCH;
            } else if (Math.abs(catAttr - userAffection) == 1) {
                thisScore += Const.OFFBYONE;
            } else if (Math.abs(catAttr - userAffection) == 2) {
                thisScore += Const.OFFBYTWO;
            }
        }

        // 8. demanding

        catAttr = oneCatData.charAt(Const. Demanding);
        if (userDemanding != 0) {
            if (userDemanding == catAttr) {
                thisScore += Const.EXACTMATCH;
            } else if (Math.abs(catAttr - userDemanding) == 1) {
                thisScore += Const.OFFBYONE;
            } else if (Math.abs(catAttr - userDemanding) == 2) {
                thisScore += Const.OFFBYTWO;
            }
        }

        // 9. children

        catAttr = oneCatData.charAt(Const.Children);
        if (catAttr != 0 && userChildren != 0) {
            if (catAttr <= userChildren) {
                thisScore += Const.EXACTMATCH;
            }
        }

        // 9a. seniors

        catAttr = oneCatData.charAt(Const.Seniors);
        if (userSeniors == "Y" && catAttr == "Y") {
            thisScore += Const.EXACTMATCH;
        }

        // 10. Independence: if the cat's needs are less than what the user can
        // provide (e.g. the cat does fine left alone all day, but the user will
        // be around most of the time), it should get full points.
        // (The comparison is greater than because a low number means more dependent.)

        catAttr = oneCatData.charAt(Const.Independence);
        if (catAttr != 0) {
            if (catAttr >= userIndependence) {
                thisScore += Const.EXACTMATCH;
            } else if (Math.abs(catAttr - userIndependence) == 1) {
                thisScore += Const.OFFBYONE;
            } else if (Math.abs(catAttr - userIndependence) == 2) {
                thisScore += Const.OFFBYTWO;
            }
        }

        // Demote cats bad with small children if the user has them.
        catAttr = oneCatData.charAt(Const.Children);
        if (catAttr == 3 && userChildren == 1) {
            thisScore = 0;
        }

        //---------------------------------------------
        // Normalize the scores to a scale of 0 to 100

        //debugwrite(catIdx + ") " + thisScore);

        if (thisScore < 0) {        // Just in case.
            thisScore = 0;
        }

        thisScore = (((thisScore) * 100) / maxScore);

        catData["cat" + catIdx].score = Math.round(thisScore);

    }    // mainloop

    DoTheSort(catData);
}

// --------------------------------------------
function showResults() {
    var doc = document;
    for (var catIdx=catData.numCats-1; catIdx >= catData.numCats-25; catIdx--) {
        doc.write('<tr><td>');
		var filename=catData["cat" + catIdx].file
		
		var values=filename.indexOf('_');
		
		if(values>0)
		{
			var breedFile= filename.substring(0, values);
		}
		else
		{
			var breedFile= filename;
		}
        doc.write('<A HREF="IAMS_Page.jsp?pageID=CBD&breedPage=');
        doc.write(breedFile + '.html');
		doc.write('">');
        doc.write("<img src='../data_root/image/cat_breed/" + catData["cat" + catIdx].file + "_sm.jpg' align=middle border=0>");
        doc.write('</A>');
        doc.write("&nbsp;");
        doc.write('<A HREF="IAMS_Page.jsp?pageID=CBD&breedPage=');
      	doc.write(breedFile + '.html');
        doc.write('">');
        doc.write(catData["cat" + catIdx].name);
        doc.write('</A>');
        doc.write('</td><td align="center">');
        doc.write(catData["cat" + catIdx].score);
        doc.write('%</td></tr>');
    }
}



