var oOddsConv = {

    // This multiplier is used
    // for converting decimal to fractional
    // and represents the order of magnitude
    // we are able to convert
    iMultiplier: 1000000,

    // Finds the greatest common factor between
    // two numbers, a and b
    greatest_common_factor: function(a, b) {
      while (b != 0) {
        remainder = a % b;
        a = b; b = remainder;
      }
      return Math.abs(a);
    },

    // Converts decimal odds into
    // fractional format
    decfrac: function(nDec) {

        // If this isn't a number, do nothing
        if (isNaN(nDec)) return;

        // Set up a denominator
        iDen = oOddsConv.iMultiplier;

        // Multiply up the numerator
        iNum = Math.round((nDec - 1) * oOddsConv.iMultiplier);

        // Divide down by common factors
        iFactor = oOddsConv.greatest_common_factor(iNum, iDen);
        while (iFactor > 1) {
            iNum /= iFactor; iDen /= iFactor;
            iFactor = oOddsConv.greatest_common_factor(iNum, iDen);
        }

        // Return a string
        return oOddsConv.formatFrac(iNum + '-' + iDen);
    },

    // Converts fractional odds into
    // decimal format
    fracdec: function(sFrac) {
        aFrac = sFrac.split(/[\/\-\:]/,2);
        if (aFrac[1] == '') return 0;
        return oOddsConv.formatDec((aFrac[0] / aFrac[1]) + 1, 2);
    },

    // Converts decimal odds into US format
    decus: function(nDec) {
        sUSA = (nDec - 1) * 100;
        if (nDec < 2) {
            sUSA = Math.round(100 / (1 - nDec));
        } else {
            sUSA = '+' + Math.round(sUSA);
        }
        return oOddsConv.formatUSA(sUSA);
    },

    // Converts US odds into Decimal format
    usdec: function(sUSA) {
        if (sUSA.substring(0, 1) == '+') {
            sDec = (parseInt(sUSA) + 100) / 100;
            if (sDec < 2) return '';
        } else if (sUSA.substring(0, 1) == '-') {
            iUSA = Math.abs(parseInt(sUSA));
            if (isNaN(iUSA)) return '';
            sDec = (iUSA + 100) / iUSA;
            if (sDec >= 2) return '';
        } else {
            return '';
        }
        return oOddsConv.formatDec(sDec, 2);
    },

    // Formats a decimal number
    formatDec: function(mNum, iPlaces, sThouSep) {

        // Validate params
        if (isNaN(iPlaces)) {
            iPlaces = 0;
        }

        if (typeof(sThouSep) == 'undefined') {
            sThouSep = ',';
        }

        // Round to the appropriate decimal places
        mNum = (Math.round(mNum * Math.pow(10, iPlaces)) / Math.pow(10, iPlaces)).toFixed(iPlaces);

        // Split out the decimal - we'll add it back later
        aBroken = mNum.toString().split(".");

        // If there is a decimal to add, format a string
        aBroken[1] = aBroken[1] ? "." + aBroken[1] : "";

        // Search for a group of 3 nums
    	var sRegex = /(\d+)(\d{3})/;
    	while (sRegex.test(aBroken[0])) {
    		aBroken[0] = aBroken[0].replace(sRegex, '$1' + sThouSep + '$2');
    	}

    	// Cat the strings back together
    	return aBroken[0] + aBroken[1];
    },

    // Formats a fraction
    formatFrac: function(sFrac) {
        sFrac = sFrac.split(/[\/\-\:]/);
        iNum = Math.round(sFrac[0]);
        iDen = Math.round(sFrac[1]);
        if (iDen > 0) {
            return iNum + '-' + iDen;
        }
        return '';
    },

    // Formats US odds
    formatUSA: function(sUSA) {
        return sUSA.toString().substring(0,1) + parseInt(Math.abs(sUSA));
    },

    // Detects and converts the passed value
    // into the three different odds formats
    convertMe: function(sValue, oOutput) {

        // Strip away number formatting
        // We'll add this back in later
        sValue = sValue.replace(/[ \,]/, '');

        // Special case
        if (sValue.toUpperCase() == 'EVENS') sValue = '1-1';

        // Initialise some vars
        sFrac = '';
        sDec  = '';
        sUSA  = '';

        // Make sure we have valid stuff
        if (!sValue.match(/^[\d\+\-\/\.\:]+$/)) {
            return;

        // Check if this is fractional odds
        } else if (sValue.match(/\d[\/\-\:]/)) {
            sFrac = oOddsConv.formatFrac(sValue);
            sDec  = oOddsConv.fracdec(sFrac);
            sUSA  = oOddsConv.decus(sDec);

        // Test if this is American odds
        } else if (sValue.match(/^[\+\-]/)) {
            sUSA  = oOddsConv.formatUSA(sValue);
            sDec  = oOddsConv.usdec(sValue);
            sFrac = oOddsConv.decfrac(sDec);

        // Assume this is decimal odds
        } else {
            sFrac = oOddsConv.decfrac(sValue);
            sDec  = oOddsConv.formatDec(sValue, 2);
            sUSA  = oOddsConv.decus(sValue);
        }

        // Init error state
        bError = false;

        // Cap at a big value
        if (sDec.length > 15) {
            bError = true;
        }

        // Check the format of each element
        if (!sFrac.toString().match(/^\d+[\/\-]\d+$/)) {
            sFrac = '';
            bError = true;
        }
        if (!sDec.toString().match(/^[\d\,]+\.\d{2}$/)) {
            sDec = '';
            bError = true;
        }
        if (!sUSA.toString().match(/^[\+\-]\d{3,}$/) || (parseInt(sUSA) < 100 && parseInt(sUSA) >= -100)) {
            sUSA = '';
            bError = true;
        }

        // Init HTML to write
        sHTML = '';

        // Create the HTML to write
        if (!bError) {
            sHTML += '<b class="black">FRACTIONAL:</b> ' + (sFrac == '1-1' ? 'Evens' : sFrac) + '<br />';
            sHTML += '<b class="black">DECIMAL:</b> ' + sDec + '<br />';
            sHTML += '<b class="black">AMERICAN:</b> ' + sUSA + '';
        }

        // Write the HTML
        oOutput.html(sHTML);
    }
}