initComplete = false;
var lineSplitRegex = new RegExp("\s*[\r\n]+\s*", "m");
var onePixelImg = "http://i.cdn.turner.com/nascar/.e/img/2.0/global/util/pixel.gif"
var flagImgBase = "http://i.cdn.turner.com/nascar/.e/img/2.0/sect/races/apps/flags/";
var flagImgMap = {
	"green": "green.png",
	"yellow": "yellow.png",
	"white": "white.png",
	"checkered": "checkered.png",
	"black": "black.png",
	"red": "red.png"
};
var seriesId = "U";
var seriesDirMap = {
	"C": "cup",
	"B": "bg",
	"T": "ct",
	"U": ""
};
var normalDriverColor = "black";
var fastestCurrentLapColor = "#003399";
var driverCloseUpMap = {};
var trackImgPattern = "http://i.cdn.turner.com/nascar/.element/img/2.0/sect/races/tracks/shape/__trackAbbreviation__.png";
var badgeImgPattern = "http://i.cdn.turner.com/nascar/.element/img/2.0/global/badges/cup/25x20/__carNumber__.png";
var bigBadgeImgPattern = "http://i.cdn.turner.com/nascar/.element/img/2.0/global/badges/cup/50x35/__carNumber__.png";
var carImgPattern = "http://i.cdn.turner.com/nascar/.element/img/2.0/global/cars/cup/165x65/__carNumber__.png";
var headshotImgPattern = "http://i.cdn.turner.com/nascar/.element/img/2.0/global/headshots/cup/75x100/__carNumber__.png";
var driverLinkPattern = "/drivers/dps/__driverId__/__seriesDir__/index.html";
var cautionSummaryUrlPattern = "/races/leaderboard/data/event/__seriesId__/__eventType__/__eventId__cautions.dat";
var registrationMap = {};
var driverDropdown;
var protoTBody;
var protoCloseUp;
var registrationTBody;
var tableWrapper;
var leaderboardTable;
var dataLoadingDiv;
var lapByLapDiv;
var cautionSummaryDiv;
var currentEventId;
var eventType;
var seriesId;
var appletDataAvailable = false;
var dataReloadFrequency = 15000;
var lapByLapReloadFrequency = 30000;
var lapByLapLastModifiedDate = null;
var cautionSummaryReloadFrequency = 45000;
var cautionSummaryLastModifiedDate = null;
var fastestCurrentLapRegId = null;
var xhrInProgress = false;
var ingestorApplet;
var intervalId = null;
var lapByLapIntervalId = null;
var cautionSummaryIntervalId = null;
var ELEMENT_NODE_TYPE = 1;

function setupLeaderboard() {
	protoTBody = el("driverRowProtos");
	registrationTBody = el("cnnTableBody");
	tableWrapper = el("tableWrapper");
	leaderboardTable = el("cnnDataTable");
	dataLoadingDiv = el("dataLoading");
	ingestorApplet = el("ingestor");
	driverDropdown = el("cnnDriverDropdown");
	protoCloseUp = el("driverCloseUpProto");
	lapByLapDiv = el("lapByLapContent");
	cautionSummaryDiv = el("cautionSummaryContent");
	currentEventId = null;
	loadEventData();
	loadLapByLapData();
}

function unloadLeaderboard() {
	// force-stop the applet
	ingestorApplet.stopStream();
}

function loadEventData() {
	if (eventDataFileURL) {
		if (!xhrInProgress) { // skip this if we get asked to do it while another request is doing its thing
			var req = newXHR();
			if (req != null) {
				req.onreadystatechange = function () {
					if (req.readyState == 4) {
						if (req.status == 200) {
							initializeEvent(req.responseText);
							xhrInProgress = false;
						} else {
							//alert("Error fetching init: " + req.status + " " + req.statusText);
						}
					}
				};
				xhrInProgress = true;
				req.open("GET", eventDataFileURL, true);
				req.send("");
			} else {
				//alert("req is null");
			}
		}
	} else {
		//alert("eventDataFileURL unknown");
	}
}

function reloadEventData() {
	if (!appletDataAvailable) {
		loadEventData();
	}
}

function loadLapByLapData() {
	if (lapByLapDataFileURL) {
		var req = newXHR();
		if (req != null) {
			req.onreadystatechange = function () {
				if (req.readyState == 4) {
					if (req.status == 200) {
						var lastModified = req.getResponseHeader("Last-Modified");
						if (lapByLapLastModifiedDate != lastModified) {
							lapByLapLastModifiedDate = lastModified;
							updateLapByLap(req.responseText);
						} // ignore the content if the file hasn't changed
					} else if (req.status == 404) {
						lapByLapDiv.innerHTML = "<h5>Lap By Lap data file not found.</h5>";
					} else {
						//alert("Error fetching lap by lap: " + req.status + " " + req.statusText);
					}
					if (lapByLapIntervalId == null) lapByLapIntervalId = 
						window.setInterval("loadLapByLapData();", lapByLapReloadFrequency);
				}
			};
			req.open("GET", lapByLapDataFileURL, true);
			req.send("");
		} else {
			//alert("req is null");
		}
	} else {
		//alert("lapByLapDataFileURL unknown");
	}
}

function loadCautionSummaryData() {
	var cautionSummaryDataFileURL = cautionSummaryUrlPattern.replace("__seriesId__", seriesId).replace("__eventType__", eventType).replace("__eventId__", currentEventId);
	var req = newXHR();
	if (req != null) {
		req.onreadystatechange = function () {
			if (req.readyState == 4) {
				if (req.status == 200) {
					var lastModified = req.getResponseHeader("Last-Modified");
					if (cautionSummaryLastModifiedDate != lastModified) {
						cautionSummaryLastModifiedDate = lastModified;
						updateCautionSummary(req.responseText);
					} // ignore the content if the file hasn't changed
				} else if (req.status == 404) {
					cautionSummaryDiv.innerHTML = "";
				} else {
					//alert("Error fetching caution summary: " + req.status + " " + req.statusText);
				}
				if (cautionSummaryIntervalId == null) cautionSummaryIntervalId = 
					window.setInterval("loadCautionSummaryData();", cautionSummaryReloadFrequency);
			}
		};
		req.open("GET", cautionSummaryDataFileURL, true);
		req.send("");
	} else {
		//alert("req is null");
	}
}

function extReceiveInfo(code, info) {
	
}

function extReceiveWarning(code, warning) {
	
}

function extReceiveData(length, data) {
	if (initComplete) processDataPayload(data + "");
}

function extDataAvailable(isAvailable) {
	if (isAvailable instanceof Object) {
		appletDataAvailable = isAvailable.booleanValue();
	} else {
		appletDataAvailable = isAvailable;
	}
}

function initializeEvent(data) {
	var initWasComplete = initComplete;
	processDataPayload(data);
	if (initComplete && !initWasComplete) loadCautionSummaryData();
	if (intervalId == null) intervalId = window.setInterval("reloadEventData();", dataReloadFrequency);
}

function processDataPayload(data) {
	var lines = data.split(lineSplitRegex);
	var registrationFound = false;
	for (var i=0; i < lines.length; i++) {
		var line = lines[i];
		if (line.match(/^E\|/)) {
			processEventData(line);
		} else if (line.match(/^R\|/)) {
			registrationFound = true;
			processRegistrationData(line);
		}
	}
	if (registrationFound && !initComplete) {
		dataLoadingDiv.style.display = "none";
		tableWrapper.style.display = "block";
		initComplete = true;
		if (ingestorApplet && ingestorApplet.startStream) ingestorApplet.startStream();
	}		
}

function updateLapByLap(data) {
	var lines = data.split(lineSplitRegex);
	var lapsProcessed = 0;
	for (var i = 0; i < lines.length && lapsProcessed < 10; i++) {
		var line = lines[i];
		var matches = line.match(/^L\|(.*?)\s+--\s+(.*)/);
		if (matches && matches.length > 2) {
			if (lapsProcessed == 0) lapByLapDiv.innerHTML = "";
			lapByLapDiv.innerHTML += "<h5>" + matches[1] + "</h5><p>" + matches[2] + "</p>";
			lapsProcessed++;
		}
	}
}

function updateCautionSummary(data) {
	var lines = data.split(lineSplitRegex);
	var cautionsProcessed = 0;
	for (var i = 0; i < lines.length; i++) {
		var line = lines[i];
		var matches = line.match(/^C\|/);
		if (matches) {
			var values = line.split("|");
			// "C", eventId, raceId, number, lapNumber, time, restartLap, restartTime, carsInvolved
			// 0,   1,       2,      3,      4,         5,    6,          7,           8
			// description, carNumbers, duration
			// 9,           10,         11
			if (cautionsProcessed == 0) cautionSummaryDiv.innerHTML = "";
			cautionSummaryDiv.innerHTML += '<div class="cnnCautionInfo"><b>' + values[3] +
				'. Lap ' + values[4] + '</b> (Restart Lap ' + values[6] + '), ' + values[11] + '</div>';
			cautionsProcessed++;
		}
	}
	if (cautionsProcessed == 0) cautionSummaryDiv.innerHTML = "<h5>No caution data available.</h5>";
}

function resetEvent() {
	// set all fields to defaults
	el('raceName').innerHTML = "";
	el('location').innerHTML = "Loading...";
	el('flagImg').setAttribute('src', onePixelImg);
	dashedFields = ['lapsCompleted', 'totalLaps', 'elapsedTime', 'cautions', 'cautionLaps', 'leaders', 'leadChanges',
		'carsStarted', 'carsRunning', 'carsOnLeadLap', 'averageEventSpeed', 'fullLocation', 'trackType', 'trackLength',
		'trackShape', 'trackTemp', 'airTemp', 'windDirection', 'windSpeed'/*, 'weatherForecast'*/];
	for (var i = 0; i < dashedFields.length; i++) {
		el(dashedFields[i]).innerHTML = "--";
	}
	el('trackImg').setAttribute('src', onePixelImg);
	// lap by lap to loading
	lapByLapDiv.innerHTML = "<h5>Loading Lap By Lap data...</h5>";
	lapByLapLastModifiedDate = null;
	// caution summary to loading
	cautionSummaryDiv.innerHTML = "<h5>Loading caution data...</h5>";
	cautionSummaryLastModifiedDate = null;
	// hide the leaderboardTable
	tableWrapper.style.display = "none";
	// show the loading div
	dataLoadingDiv.style.display = "";
	// remove all registration TBODYs from the table
	while (leaderboardTable.tBodies.length > 1) {
		// this should never happen because it should always be last in the list, but just to be sure
		if (leaderboardTable.tBodies[0] == protoTBody) break;
		leaderboardTable.removeChild(leaderboardTable.tBodies[0]);
	}
	// remove all regs from map
	registrationMap = {};
	updateDriverDropdownOptions();
	initComplete = false;
}

function processEventData(data) {
	var values = data.split("|");
	// id, raceId, type, league, totalLaps, lapsCompleted, lapsLeft, trackLength, raceName, sponsor, location
	// 1,  2,      3,    4,      5,         6,             7,        8,           9,        10,       11
	// flag, startTime, elapsedTime, averageSpeed, carsRunning, carsOnLeadLap, leaders, leadChanges
	// 12,   13,        14,          15,           16,          17,            18,      19,
	// numberLapsUnderCaution, numberCautions, airTemperature, trackTemperature, windSpeed, windDirection
	// 20,                     21,             22,             23,               24,        25,
	// weather, forecast, trackAbbreviation, trackShape, trackShortName, trackType, carsStarted
	// 26,      27,       28,                29,         30,             31,        32
	if (currentEventId != values[1]) {
		if (currentEventId != null) resetEvent();
		currentEventId = values[1];
	}
	eventType = values[3];
	seriesId = values[4];
	el('raceName').innerHTML = convertNullToDefault(values[9]);
	el('location').innerHTML = convertNullToDefault(values[30]);
	if (flagImgMap[values[12]]) {
		el('flagImg').setAttribute('src', flagImgBase + flagImgMap[values[12]]);
		convertPNG(el('flagImg'));
	}
	el('lapsCompleted').innerHTML = convertNullToDefault(values[6]);
	el('totalLaps').innerHTML = convertNullToDefault(values[5]);
	el('elapsedTime').innerHTML = convertNullToDefault(values[14]);
	el('cautions').innerHTML = convertNullToDefault(values[21]);
	el('cautionLaps').innerHTML = convertNullToDefault(values[20]);
	el('leaders').innerHTML = convertNullToDefault(values[18]);
	el('leadChanges').innerHTML = convertNullToDefault(values[19]);
	el('carsStarted').innerHTML = convertNullToDefault(values[32]);
	el('carsRunning').innerHTML = convertNullToDefault(values[16]);
	el('carsOnLeadLap').innerHTML = convertNullToDefault(values[17]);
	el('averageEventSpeed').innerHTML = convertNullToDefault(values[15]);
	el('trackImg').setAttribute('src', trackImgPattern.replace("__trackAbbreviation__", values[28]));
	convertPNG(el('trackImg'));
	el('fullLocation').innerHTML = convertNullToDefault(values[11]);
	el('trackType').innerHTML = convertNullToDefault(values[31]);
	if (!isNull(values[8])) el('trackLength').innerHTML = values[8] + " Mile" + (values[8] != 1 ? "s" : "");
	el('trackShape').innerHTML = convertNullToDefault(values[29]);
	el('trackTemp').innerHTML = convertNullToDefault(values[23]);
	el('airTemp').innerHTML = convertNullToDefault(values[22]);
	el('windDirection').innerHTML = convertNullToDefault(values[25]);
	el('windSpeed').innerHTML = convertNullToDefault(values[24]);
	//el('weatherForecast').innerHTML = convertNullToDefault(values[27]);
}

function processRegistrationData(data) {
	var values = data.split("|");
	// id, carNumber, startingPosition, currentPosition, isPositionOfficial, timeBehind, lapsBehind,
	// 1,  2,         3,                4,               5,                  6,          7,
	// firstName, lastName, currentLap, currentLapTime, lapsLed, fastestLap, seasonPoints, racePoints,
	// 8,         9,        10,         11,             12,      13,         14,           15,
	// status, extendedStatus, manufacturer, sponsor, bestPosition, worstPosition, averagePosition,
	// 16,     17,             18,           19,      20,           21,            22,
	// fastestSpeed, slowestSpeed, averageSpeed, fastestLapTime, slowestLapTime, averageLapTime
	// 23,           24,           25,           26,             27,             28
	// currentSpeed, driverId, isFastestCurrentLap, isInChase
	// 29,           30,       31,                  32
	var r, newReg = false;
	// if the registration has an entry in the registration map
	var regId = values[1];
	if (registrationMap[regId]) {
		r = registrationMap[regId];
	} else {
		// create a new TR for the regular row and the details row from the prototype rows
		var newTBody = protoTBody.cloneNode(true);
		newTBody.setAttribute("id", "driverTBody" + regId);
		// modify the ids of all the children
		replaceStringInIds(newTBody, "Proto", regId);
		var normalRow = newTBody.getElementsByTagName("tr")[0];
		var detailsRow = newTBody.getElementsByTagName("tr")[1];
		normalRow.style.display = "";
		detailsRow.style.display = "none";
		// insert the new tbody as the last one (before the prototypes)
		leaderboardTable.insertBefore(newTBody, protoTBody);
		// set event handlers for details on click
		el('expand' + regId).style.cursor = 'pointer';
		normalRow.onclick = function() { 
			detailsRow.style.display = ""; 
			el('expand' + regId).innerHTML = '';
			var expandCloseLink = d.createElement('a');
			expandCloseLink.style.textDecoration = 'none';
			expandCloseLink.style.padding = '0';
			expandCloseLink.onclick = function() {
				el('driverDetailsRow' + regId).style.display = "none";
				el('expand' + regId).innerHTML = '[+]';
			}
			expandCloseLink.appendChild(d.createTextNode('[-]'));
			el('expand' + regId).appendChild(expandCloseLink);
			el('expand' + regId).style.cursor = 'pointer';
		}
		
		el("closeLink" + regId).onclick = function() { 
			detailsRow.style.display = "none";
			el('expand' + regId).innerHTML = '[+]';
		}
		// create a registration object
		r = new Registration(regId, newTBody);
		newReg = true;
		registrationMap[regId] = r;
	}
	r.setPosition(values[4]);
	r.setCarNumber(values[2]);
	r.setStartingPosition(values[3]);
	r.setPositionOfficial("true"); // ignoring this from the feed for now
	//r.setDriverName(values[8] + " " + values[9]); //Removed 06/25/08
	r.setDriverName(values[8] + " " + values[9], values[9] + "_" + values[8]); //Added 06/25/08 - passing 2nd variable to use for pulling headshots by driver name instead of car number
	r.setCurrentLap(values[10]);
	r.setCurrentSpeed(values[29]);
	r.setCurrentTime(values[11]);
	r.setBehindLeader((values[7] && values[7] > 0) ? values[7] + " Lap" + (values[7] > 1 ? "s" : "") : values[6]);
	r.setLapsLed(values[12]);
	r.setPoints((values[14].match(/^\d+/) ? parseInt(values[14]) : 0) + (values[15].match(/^\d+/) ? parseInt(values[15]) : 0));
	r.setStatus(values[16]);
	r.setExtendedStatus(values[17]);
	r.setMake(values[18]);
	r.setSponsor(values[19]);
	r.setLowPosition(values[20]);
	r.setHighPosition(values[21]);
	r.setBestSpeed(values[23]);
	r.setAverageSpeed(values[25]);
	r.setBestTime(values[26]);
	r.setAverageTime(values[28]);
	r.setDriverId(values[30]);
	r.setFastestCurrentLap(values[31] == "1" ? true : false);
	r.setInChase(values[32] == "1" ? true : false);
	if (newReg) updateDriverDropdownOptions();
}

function updateDriverDropdownOptions() {
	if (registrationMap) {
		var regs = [];
		for (var r in registrationMap) {
			regs.push(registrationMap[r]);
		}
		regs.sort(function (a, b) {
			if (parseInt(a.getCarNumber(), 10) < parseInt(b.getCarNumber(), 10)) return -1;
			if (parseInt(a.getCarNumber(), 10) > parseInt(b.getCarNumber(), 10)) return 1;
			if (parseInt(a.getCarNumber(), 10) == parseInt(b.getCarNumber(), 10)) return 0;
		});
		driverDropdown.options.length = 1;
		for (var i = 0; i < regs.length; i++) {
			driverDropdown.options[driverDropdown.options.length] = new Option(regs[i].getCarNumber() + " " + regs[i].getDriverName(), regs[i].getId());
		}
	}
}

function cnnShowBlurbs(tab, name) {
	blurbs = new Array('LapByLap','CautionSummary');
	for (i = 0; i < blurbs.length; i++) {
		el('cnn' + blurbs[i]).className = '';
    	el(blurbs[i]).style.display = (name == blurbs[i]) ? 'block':'none';
		el('cnn' + name).className = 'cnnSelected';
		if (name == 'CautionSummary') {	
			el('cnnEventBlurbsHdr').style.background = 'url("http://i2.cdn.turner.com/nascar/.e/img/2.0/sect/races/apps/leaderboard/bg_eventBlurbs_hdr.gif") 0 -24px no-repeat';
		} else if (name == 'LapByLap') {	
			el('cnnEventBlurbsHdr').style.background = 'url("http://i2.cdn.turner.com/nascar/.e/img/2.0/sect/races/apps/leaderboard/bg_eventBlurbs_hdr.gif") 0 0 no-repeat';
		}
  	}
}


function cnnLoadDriver() {
	var driverId = driverDropdown.options[driverDropdown.selectedIndex].value;
	if (driverId != '' && !driverCloseUpMap[driverId]) {
		// create a new close up and stuff it in the map and the corresponding registration
		var newCloseUp = protoCloseUp.cloneNode(true);
		newCloseUp.setAttribute("id", "driverCloseUp" + driverId);
		replaceStringInIds(newCloseUp, "Proto", driverId);
		protoCloseUp.parentNode.insertBefore(newCloseUp, protoCloseUp);
		driverCloseUpMap[driverId] = newCloseUp;
		registrationMap[driverId].setCloseUpElem(newCloseUp);
		var closeBtnLink = el("closeBtnLink" + driverId);
		if (closeBtnLink) closeBtnLink.onclick = createCloseUpCloseClosure(driverId, newCloseUp);
		newCloseUp.style.display = "block";
	}
}

function createCloseUpCloseClosure(driverId, closeUpElem) {
	return function () {
		driverCloseUpMap[driverId] = null;
		registrationMap[driverId].setCloseUpElem(null);
		closeUpElem.parentNode.removeChild(closeUpElem);
	}
}

// registration object holds info about the car/driver
function Registration(id, tBody) {
	this._id = id;
	var _position, _carNumber, _driverName, _currentLap, _currentSpeed, _currentTime, _behindLeader, _lapsLed, _points;
	var _sponsor, _make, _status, _extendedStatus, _startingPosition, _highPosition, _lowPosition, _bestSpeed, _averageSpeed;
	var _bestTime, _averageTime, _pitStops, _lastPitLap, _lastPitTime, _lastPitEntryPosition, _lastPitExitPosition, _isPositionOfficial;
	var _driverId, _isInChase;
	
	// find elements for each of our fields
	this._tBody = tBody;
	this._carImgElem = el("carImg" + id); this._headshotImgElem = el("headshotImg" + id);
	this._positionElem = el("pos" + id); this._badgeImgElem = el("badgeImg" + id); this._driverLinkElem = null;
	this._currentLapElem = el("lap" + id); this._currentSpeedElem = el("speed" + id); this._currentTimeElem = el("time" + id);
	this._timeBehindElem = el("timeBehind" + id); this._lapsLedElem = el("lapsLed" + id); this._pointsElem = el("points" + id);
	this._carNumberElem = el("carNumber" + id); this._sponsorElem = el("sponsor" + id); this._makeElem = el("make" + id);
	this._statusElem = el("status" + id); this._positionDetailElem = el("positionDetail" + id); this._startingPositionElem = el("startingPosition" + id);
	this._highPositionElem = el("bestPosition" + id); this._lowPositionElem = el("worstPosition" + id); this._speedDetailElem = el("speedDetail" + id);
	this._bestSpeedElem = el("bestSpeed" + id); this._avgSpeedElem = el("avgSpeed" + id); this._timeDetailElem = el("timeDetail" + id);
	this._bestTimeElem = el("bestTime" + id); this._avgTimeElem = el("avgTime" + id); this._pitStopsElem = el("pitStops" + id);
	this._lastPitLapElem = el("lastPitLap" + id); this._lastPitTimeElem = el("lastPitTime" + id); this._lastPitEntryElem = el("lastPitEntryPos" + id);
	this._lastPitExitPosElem = el("lastPitExitPos" + id); this._driverNameElem = el("driverName" + id); this._driverNameLinkElem = el("driverNameLink" + id);
	// fields for driver close up are null by default
	this._closeUpElem = null;
	this._closeUpDriverNameElem = null;
	this._bigBadgeImgElem = null;
	this._closeUpPositionElem = null;
	this._closeUpBehindLeaderElem = null;
	this._closeUpCurrentLapElem = null;
	this._closeUpRacePointsElem = null;
	
	this.getTBody = function() {
		return this._tBody;
	}
	
	this.getId = function() {
		return this._id;
	}
	
	this.getPosition = function() {
		return this._position;
	}
	this.setPosition = function(position) {
		// don't set anything for an invalid position
		if (position.match(/^\s*\d+\s*$/)) {
			var oldPosition = this._position;
			if (position != oldPosition) {
				this._position = position;
				this._positionElem.innerHTML = this._position;
				this._positionDetailElem.innerHTML = this._position;
				if (this._closeUpPositionElem) this._closeUpPositionElem.innerHTML = this._position;
				// if our tBody element has a parent
				if (this._tBody.parentNode) leaderboardTable.removeChild(this._tBody);

				// this assumes there will be a TBODY (prototypes) in the table regardless
				var tBodies = leaderboardTable.tBodies;
				var newNextSibling = protoTBody;
				for (var i = 0; i < tBodies.length; i++) {
					if (tBodies[i] == protoTBody) {
						break;
					}
					var matches = tBodies[i].getAttribute("id").match(/^driverTBody(\d+)$/);
					if (matches && matches.length > 1) {
						var driver = registrationMap[matches[1]];
						if (driver && parseInt(driver.getPosition()) >= parseInt(position)) {
							newNextSibling = tBodies[i];
							break;
						}
					}
				}
				leaderboardTable.insertBefore(this._tBody, newNextSibling);
				// restripe the table
				for (var i = 0; i < tBodies.length; i++) {
					var tbodyTRs = tBodies[i].getElementsByTagName("tr")[0];
					var tbodyTDs = tbodyTRs.getElementsByTagName('td');
					for (var j = 0; j < tbodyTDs.length; j++) {
						tbodyTDs[j].style.backgroundColor = i % 2 == 0 ? "#efefef" : "#ffffff";
					}
				}
			}
			if (position - 0 == 1) { // implicit numeric conversion
				// set everyone else's positionOfficial to false
				for (var i = 1; i < leaderboardTable.tBodies.length; i++) {
					if (leaderboardTable.tBodies[i] == protoTBody) {
						break;
					}
					var matches = leaderboardTable.tBodies[i].getAttribute("id").match(/^driverTBody(\d+)$/);
					if (matches && matches.length > 1) {
						var driver = registrationMap[matches[1]];
						if (driver) {
							driver.setPositionOfficial("false");
						}
					}
				}
			}
		}
	}
	
	this.getCarNumber = function() {
		return this._carNumber;
	}
	this.setCarNumber = function(carNumber) {
		if (this._carNumber != convertNullToDefault(carNumber)) {
			this._carNumber = convertNullToDefault(carNumber);
			this._badgeImgElem.setAttribute("src", badgeImgPattern.replace("__carNumber__", this._carNumber));
			convertPNG(this._badgeImgElem);
			this._carImgElem.setAttribute("src", carImgPattern.replace("__carNumber__", this._carNumber));
			convertPNG(this._carImgElem);
			//Removed 06/25/08
			//this._headshotImgElem.setAttribute("src", headshotImgPattern.replace("__carNumber__", this._carNumber));
			//convertPNG(this._headshotImgElem);
			this._carNumberElem.innerHTML = this._carNumber;
			if (this._bigBadgeImgElem) {
				this._bigBadgeImgElem.setAttribute("src", bigBadgeImgPattern.replace("__carNumber__", this._carNumber));
				convertPNG(this._bigBadgeImgElem);
			}
		}
	}
	
	this.getDriverName = function() {
		return this._driverName;
	}
	this.setDriverName = function(driverName,driverNameHS) {
		if (this._driverName != convertNullToDefault(driverName)) {
			this._driverName = convertNullToDefault(driverName);
			if (this._driverLinkElem != null) {
				this._driverLinkElem.innerHTML = this._driverName;
			} else {
				this._driverNameLinkElem.innerHTML = '<span class="driverName">' + this._driverName + '</span>';
			}
			this._driverNameElem.innerHTML = this._driverName;
			if (this._closeUpDriverNameElem) this._closeUpDriverNameElem.innerHTML = this._driverName;
			//Added 06/25/08: Pull headshots by driver name instead of car name
			var driverHeadshot = driverNameHS.toUpperCase().split(" ").join("_").split(".").join(""); //convert to uppercase, strip out blanks, periods
			this._headshotImgElem.setAttribute("src", headshotImgPattern.replace("__carNumber__", driverHeadshot));
			convertPNG(this._headshotImgElem);
			/////////////////////
		}
	}
	
	this.getDriverId = function() {
		return this._driverId;
	}
	this.setDriverId = function(driverId) {
		if (this._driverId != driverId) {
			this._driverId = driverId;
			if (!isNull(this._driverId)) {
				if (this._driverLinkElem == null) {
					// create a driver link
					var driverLink = document.createElement("a");
					if (this._driverNameLinkElem.firstChild) {
						driverLink.innerHTML = this._driverNameLinkElem.firstChild.innerHTML;
						this._driverNameLinkElem.replaceChild(driverLink, this._driverNameLinkElem.firstChild);
					} else {
						this._driverNameLinkElem.appendChild(driverLink);
					}
					this._driverLinkElem = driverLink;
				}
				this._driverLinkElem.setAttribute("href", driverLinkPattern.replace("__driverId__", this._driverId).replace("__seriesDir__", seriesDirMap[seriesId]));
			}
		}
	}
	
	this.getCurrentLap = function() {
		return this._currentLap;
	}
	this.setCurrentLap = function(currentLap) {
		this._currentLap = convertNullToDefault(currentLap);
		this._currentLapElem.innerHTML = this._currentLap;
		if (this._closeUpCurrentLapElem) this._closeUpCurrentLapElem.innerHTML = this._currentLap;
	}
	
	this.getCurrentSpeed = function() {
		return this._currentSpeed;
	}
	this.setCurrentSpeed = function(currentSpeed) {
		this._currentSpeed = convertNullToDefault(currentSpeed);
		this._currentSpeedElem.innerHTML = this._currentSpeed;
		this._speedDetailElem.innerHTML = this._currentSpeed;
	}
	
	this.getCurrentTime = function() {
		return this._currentTime;
	}
	this.setCurrentTime = function(currentTime) {
		this._currentTime = convertNullToDefault(currentTime);
		this._currentTimeElem.innerHTML = this._currentTime;
		this._timeDetailElem.innerHTML = this._currentTime;
	}
	
	this.getBehindLeader = function() {
		return this._behindLeader;
	}
	this.setBehindLeader = function(behindLeader) {
		this._behindLeader = convertNullToDefault(behindLeader);
		this._timeBehindElem.innerHTML = this._behindLeader;
		if (this._closeUpBehindLeaderElem) this._closeUpBehindLeaderElem.innerHTML = this._behindLeader;
	}
	
	this.getLapsLed = function() {
		return this._lapsLed;
	}
	this.setLapsLed = function(lapsLed) {
		this._lapsLed = convertNullToDefault(lapsLed);
		this._lapsLedElem.innerHTML = this._lapsLed;
	}
	
	this.getPoints = function() {
		return this._points;
	}
	this.setPoints = function(points) {
		this._points = convertNullToDefault(points);
		this._pointsElem.innerHTML = this._points;
		if (this._closeUpRacePointsElem) this._closeUpRacePointsElem.innerHTML = this._points;
	}
	
	this.getSponsor = function() {
		return this._sponsor;
	}
	this.setSponsor = function(sponsor) {
		this._sponsor = sponsor.toLowerCase() == "none" ? "" : convertNullToDefault(sponsor, "");
		this._sponsorElem.innerHTML = this._sponsor;
	}
	
	this.getMake = function() {
		return this._make;
	}
	this.setMake = function(make) {
		this._make = convertNullToDefault(make, "");
		this._makeElem.innerHTML = this._make;
	}
	
	this.getStatus = function() {
		return this._status;
	}
	this.setStatus = function(status) {
		this._status = convertNullToDefault(status);
		this._statusElem.innerHTML = this._status;
	}
	
	this.getExtendedStatus = function() {
		return this._extendedStatus;
	}
	this.setExtendedStatus = function(extendedStatus) {
		this._extendedStatus = convertNullToDefault(extendedStatus);
	}
	
	this.getStartingPosition = function() {
		return this._startingPosition;
	}
	this.setStartingPosition = function(startingPosition) {
		this._startingPosition = convertNullToDefault(startingPosition);
		this._startingPositionElem.innerHTML = this._startingPosition;
	}
	
	this.getHighPosition = function() {
		return this._highPosition;
	}
	this.setHighPosition = function(highPosition) {
		this._highPosition = convertNullToDefault(highPosition);
		this._highPositionElem.innerHTML = this._highPosition;
	}
	
	this.getLowPosition = function() {
		return this._lowPosition;
	}
	this.setLowPosition = function(lowPosition) {
		this._lowPosition = convertNullToDefault(lowPosition);
		this._lowPositionElem.innerHTML = this._lowPosition;
	}
	
	this.getBestSpeed = function() {
		return this._bestSpeed;
	}
	this.setBestSpeed = function(bestSpeed) {
		this._bestSpeed = convertNullToDefault(bestSpeed);
		this._bestSpeedElem.innerHTML = this._bestSpeed;
	}
	
	this.getAverageSpeed = function() {
		return this._averageSpeed;
	}
	this.setAverageSpeed = function(averageSpeed) {
		this._averageSpeed = convertNullToDefault(averageSpeed);
		this._avgSpeedElem.innerHTML = this._averageSpeed;
	}
	
	this.getBestTime = function() {
		return this._bestTime;
	}
	this.setBestTime = function(bestTime) {
		this._bestTime = convertNullToDefault(bestTime);
		this._bestTimeElem.innerHTML = this._bestTime;
	}
	
	this.getAverageTime = function() {
		return this._averageTime;
	}
	this.setAverageTime = function(averageTime) {
		this._averageTime = convertNullToDefault(averageTime);
		this._avgTimeElem.innerHTML = this._averageTime;
	}
	
	this.getPitStops = function() {
		return this._pitStops;
	}
	this.setPitStops = function(pitStops) {
		this._pitStops = convertNullToDefault(pitStops);
		this._pitStopsElem.innerHTML = this._pitStops;
	}
	
	this.getLastPitLap = function() {
		return this._lastPitLap;
	}
	this.setLastPitLap = function(lastPitLap) {
		this._lastPitLap = convertNullToDefault(lastPitLap);
		this._lastPitLapElem.innerHTML = this._lastPitLap;
	}
	
	this.getLastPitTime = function() {
		return this._lastPitTime;
	}
	this.setLastPitTime = function(lastPitTime) {
		this._lastPitTime = convertNullToDefault(lastPitTime);
		this._lastPitTimeElem.innerHTML = this._lastPitTime;
	}
	
	this.getLastPitEntryPosition = function() {
		return this._lastPitEntryPosition;
	}
	this.setLastPitEntryPosition = function(lastPitEntryPosition) {
		this._lastPitEntryPosition = convertNullToDefault(lastPitEntryPosition);
		this._lastPitEntryPosElem.innerHTML = this._lastPitEntryPosition;
	}
	
	this.getLastPitExitPosition = function() {
		return this._lastPitExitPosition;
	}
	this.setLastPitExitPosition = function(lastPitExitPosition) {
		this._lastPitExitPosition = convertNullToDefault(lastPitExitPosition);
		this._lastPitExitPosElem.innerHTML = this._lastPitExitPosition;
	}
	
	this.getPositionOfficial = function() {
		return this._isPositionOfficial;
	}
	this.setPositionOfficial = function(isPositionOfficial) {
		this._isPositionOfficial = isPositionOfficial == "true" ? true : false;
		var driverRow = this._tBody.getElementsByTagName("tr")[0];
		if (this._isPositionOfficial) {
			driverRow.style.color = normalDriverColor;
			if (this._driverLinkElem)
				this._driverLinkElem.style.color = normalDriverColor;
		} else {
			driverRow.style.color = "#999999";
			if  (this._driverLinkElem)
				this._driverLinkElem.style.color = "#999999";
		}
	}
	
	this.setFastestCurrentLap = function(isFastestCurrentLap) {
		var driverRow = this._tBody.getElementsByTagName("tr")[0];
		if (isFastestCurrentLap) {
			if (fastestCurrentLapRegId != null) {
				// set the old fastest driver to normal color
				var driver = registrationMap[fastestCurrentLapRegId];
				if (driver) driver.setFastestCurrentLap(false);
			}
			fastestCurrentLapRegId = this._id;
			driverRow.style.color = fastestCurrentLapColor;
			if (this._driverLinkElem)
				this._driverLinkElem.style.color = fastestCurrentLapColor;
		} else {
			driverRow.style.color = normalDriverColor;
			if (this._driverLinkElem)
				this._driverLinkElem.style.color = normalDriverColor;
		}
	}
	
	this.setInChase = function(isInChase) {
		if (isInChase != this._isInChase) {
			this._isInChase = isInChase;
			if (this._driverLinkElem) {
				if (isInChase) {
					this._driverLinkElem.className = "cnnChaseDriver";
				} else {
					this._driverLinkElem.className = "";
				}
			}
		}
	}
	
	this.setCloseUpElem = function(closeUpElem) {
		this._closeUpElem = closeUpElem;
		if (this._closeUpElem) {
			this._closeUpDriverNameElem = el("closeUpDriverName" + this._id);
			this._closeUpDriverNameElem.innerHTML = this.getDriverName();
			this._bigBadgeImgElem = el("bigBadgeImg" + this._id);
			this._bigBadgeImgElem.setAttribute("src", bigBadgeImgPattern.replace("__carNumber__", this.getCarNumber()));
			convertPNG(this._bigBadgeImgElem);
			this._closeUpPositionElem = el("closeUpPosition" + this._id);
			this._closeUpPositionElem.innerHTML = this.getPosition();
			this._closeUpBehindLeaderElem = el("closeUpBehindLeader" + this._id);
			this._closeUpBehindLeaderElem.innerHTML = this.getBehindLeader();
			this._closeUpCurrentLapElem = el("closeUpCurrentLap" + this._id);
			this._closeUpCurrentLapElem.innerHTML = this.getCurrentLap();
			this._closeUpRacePointsElem = el("closeUpRacePoints" + this._id);
			this._closeUpRacePointsElem.innerHTML = this.getPoints();
		}
	}
}

