/***** UTILITIES *****/ // get an HTML element for a given mktId function getEl(name, mktId) { return document.getElementById(name + '_' + mktId); } // rnd a number for a given mkt (use mkt.decimals, default to 1.) function round(num, mkt) { var res = num; var dec = mkt.decimals; if(!isNaN(num)) res = (dec > 1) ? (Math.round(num * dec) / dec) : Math.round(num); return res; } // cross ref mkts and mktsById var mktsById = new Object(); function fixUpMkts() { for(var i = mkts.length ; i-- > 0 ; ) { var mkt = mkts[i]; mktsById[mkts[i].id] = mkt; mkt.hasFcst = mkt.fcst && mkt.fcst.valid && mkt.fcst.active; } } // return a two digit representation of val (leading 0 if needed) function twoDigits(val) { return (val < 10) ? ("0" + val) : val; } // the fixed height used to build fcstBoxes and other table elements var rowHeight=20; /***** DISPLAY FUNCTIONS *****/ // clear and then fill the mktsTbl with each of the mkt. function redisplayAllMkts() { var t = document.getElementById('mktsTbl'); var r, c; // delete all rows while(t.rows.length > 2) t.deleteRow(1); // redisplay each bin var questNum =1; for(var i = 0 ; i < mkts.length ; i++) { var mkt = mkts[i]; redisplayMkt(mkt, t.insertRow(t.rows.length), questNum++); r = t.insertRow(t.rows.length); c = r.insertCell(0); c.colSpan = 3; c.className = "account-lite"; c.innerHTML = ""; } // the global submit forecasts button r = t.insertRow(t.rows.length); r.insertCell(0); var c = r.insertCell(1); c.align="center"; c.innerHTML = "
" + "
"; r.insertCell(2); } // display market 'mkt' in table row 'r' function redisplayMkt(mkt, r, questNum) { var z = 0; var editLink = userIsEditor ? ("[Edit Market]") : ""; var transLink = "[List of your forecasts]"; // describe Mkt var c = r.insertCell(z++); c.vAlign="top"; c.bgColor = "#FFFFFF"; c.innerHTML = "
" + mkt.name + "
" + mkt.info + "
" + "full info>>" + editLink; // fcst box switch(mkt.state) { case 'active': c = r.insertCell(z++); c.vAlign="top"; c.className="data"; c.bgColor = "#FFFFFF"; var sb = new StringBuffer(); // your forecast or message if(accountId > 0) { sb.append(genFcstBox(mkt)); sb.append("

"); } // aggregate fcst (mkt.hasFcst ? sb.append("

" + genAggrHTML(mkt) + "
") : sb.append("



")); //sb.append("
" + genAggrHTML(mkt) + "
"); c.innerHTML = sb.toString(); break; case 'halted': c = r.insertCell(z++); c.colspan = 2; c.bgColor = "#FFFFFF"; c.innerHTML = "
" + mkt.ruling + "
" + editLink; break; case 'closed': c = r.insertCell(z++); c.colspan = 2; c.bgColor = "#FFFFFF"; c.innerHTML = "
" + mkt.ruling + "
OUTCOME: " + mkt.outcomeStr + "
" + editLink; break; } // display graph (or msg) c = r.insertCell(z++); c.vAlign="top"; c.align="center"; c.bgColor = "#FFFFFF"; if (mkt.hasFcst || (accountId == 0)) { c.innerHTML = "
Forecasts: " + " Old  " + " Current  " + " Yours" + "

" + "" + ""; } else { c.innerHTML = "

 

" + ""; } } function genAggrHTML(mkt) { var high; var low; var range; var fcst; var stdDev; if(mkt.isTimer) { high = valToDate(mkt.avgFcst + (mkt.avgRange / 2)); low = valToDate(mkt.avgFcst - (mkt.avgRange / 2)); range = Math.round(mkt.avgRange/daySecs) + " days"; fcst = valToDate(mkt.avgFcst); stdDev = Math.round(mkt.stdDev/daySecs) + "days"; } else { high = round(mkt.avgFcst + (mkt.avgRange / 2), mkt); low = round(mkt.avgFcst - (mkt.avgRange / 2), mkt); range = round(mkt.avgRange, mkt); fcst = mkt.avgFcstStr; stdDev = round(mkt.stdDev, mkt); } var res = "" + "" + "" + "" + "" + "" + "
Average Forecast
Mean:" + fcst + "StdDev:" + stdDev + "
Lo/Hi:" + low + " / " + high + "Spread:" + range + "
" return res; } function genFcstBox(mkt) { var low; var high; if(mkt.fcst && mkt.fcst.valid && mkt.fcst.active) { low = mkt.fcst.low; high = mkt.fcst.high; } return genHSlider(mkt.id, 200, 20, mkt.low, mkt.high, 0, mkt.maxRange, low, high, sliderCB, mkt.decimals, mkt.isTimer) + "

" + "   " + "" + "
"; } function dateToVal(str) { str = trim(str); if(str == '') return 0; var d = isoDateToTs(str); if(d == null) return "false"; return d.getTime() / 1000; } /***** INPUT HANDLERS ******/ // slider call back function sliderCB(info, what) { var mktId = info.name; var mkt = mktsById[mktId]; switch(what) { case "start": case "move": getEl("msg", mktId).innerHTML = "spread: " + (mkt.isTimer ? (Math.round((info.high - info.low)/daySecs) + " days") : round(info.high - info.low, mkt)); break; case "done": mkt.modified = true; enableButtons(mktId, true); getEl("msg", mktId).innerHTML = ""; break; } } function sendFcst(mktId) { enableButtons(mktId, false); var info = __hsldr.infoTbl[mktId]; var args = { cmd: "CFMgr.submitHLForecast", marketId: mktId, low: info.low, high: info.high }; var req = getAjaxRequestor(); makeAjaxRequest(req, "cfSubmitFcst.html", args, function() { hdlSendFcstResponse(req, args, mktId); }); } function hdlSendFcstResponse(req, args, mktId) { var el = getEl("msg", mktId); el.className = "label"; switch(req.readyState) { case 2: el.innerHTML = "Forecast sent."; break; case 3: el.innerHTML = "Receiving confirmation."; break; case 4: try { var resp = req.responseText; if(resp.charAt(0) != '{') throw "Unexpected response from server:
" + resp.substring(0,100) + "
"; var mkt = mktsById[mktId]; var data; eval("data=" + resp); mkt.avgFcstStr = data.avgFcstStr; mkt.avgRange = data.avgRange; mkt.stdDev = data.stdDev; getEl("aggr", mktId).value = genAggrHTML(mkt); el.innerHTML = "Forecast saved."; mkt.fcst = { low: args.low, high: args.high, valid: true, active: true }; highlight("msg_" + mktId); mkt.modified = false; updateSbmAllBut(); // if not mkt.hasFcst, now we can display a fcst if(!mkt.hasFcst) { getEl("graph", mktId).src = "/elab/graphs/cfl.acc=" + accountId + ",show=bl." + mktId + ".png?" + Math.random(0,10000); mkt.hasFcst = true; } } catch(err) { el.className = "warning"; el.innerHTML = "****Forecast NOT updated!****
" + err; } } } // this is called when the submit all fcsts button is click function submitAllForecasts() { for(var i in mkts) { var mkt = mkts[i]; if(mkt.modified) { var info = __hsldr.infoTbl[mkt.id]; var mEl = getEl("sbMkt", mkt.id); mEl.disabled = false; var hEl = getEl("sbHigh", mkt.id); hEl.disabled = false; var lEl = getEl("sbLow", mkt.id); lEl.disabled = false; hEl.value = info.high; lEl.value = info.low; } } window.onbeforeunload = null; document.getElementById("submitForm").submit(); } // reset the slider to current mkt.fcst.high/low function resetFcst(mktId) { var mkt = mktsById[mktId]; if(mkt.fcst && mkt.fcst.valid && mkt.fcst.active) setHSlider(mktId, mkt.fcst.low, mkt.fcst.high); else setHSlider(mktId); mkt.modified = false; enableButtons(mktId, false); getEl("msg", mktId).innerHTML = ""; } // enable or disable buttons for a mkt function enableButtons(mktId, trueFalse) { var el = getEl("sbmBut", mktId); el.disabled = !trueFalse; el.className = trueFalse ? "sbmBut-enabled" : "but-disabled"; el = getEl("rstBut", mktId); el.disabled = !trueFalse; el.className = trueFalse ? "rstBut-enabled" : "but-disabled"; updateSbmAllBut(); } // update the status of submit all forecasts button function updateSbmAllBut() { var activate = anyModified(); var el = document.getElementById("sbmAllBut"); el.disabled = !activate; el.className = activate ? "sbmBut-enabled" : "but-disabled"; } // check if we need to submit the form as the page is being unloaded. function hdlBeforeUnload(ev) { if(anyModified()) { if(ev == undefined) ev = window.event; ev.returnValue = "You haven't pressed the SUBMIT button for all the forecasts you created or modified."; } } // return true iff there is at least one mkt whose fcst has been modified function anyModified() { for(var i in mkts) if(mkts[i].modified) return true; return false; } /////////////////////// Top Right Box //////////////////////// // various box contents var topRightBoxHelp; var topRightBoxHelpButton; function fillTopRightBoxHelp() { if(accountId > 0) { topRightBoxHelp = "" + "" + "" + "" + "
" + "
Forecasting to win:

" + " You win points if the real outcome falls somewhere within your High-Low range, otherwise you lose points.

" + " You can revise or refine your forecast as often as you like.

" + " Each of your successive forecasts will be scored for its accuracy and precision.

" + " Learn more about the scoring rule...
 " + "

" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "
" + "
"; } else if(loggedIn) { topRightBoxHelp = "
You do not have the account required to make forecasts in this tournament." + " Please contact the system administrator.
"; } else { topRightBoxHelp = "
In order to make forecasts, you must first

" + " " + "or " + "
"; } topRightBoxHelpButton = ""; } var topRightBoxForum; var topRightBoxForumButton; function fillTopRightBoxForum() { sb = new StringBuffer(); sb2 = new StringBuffer(); if(forumMsgs.length==0) { sb.append("
Message Board

No one has posted to the forum yet.
" + "Be the first!"); } else { sb.append("" + "" + ""); for(var n = 0 ; n < 4 && n < forumMsgs.length ; n++) { var msg = forumMsgs[n]; sb.append("" + ""); } sb.append("
Message Board" + "New Message | " + "All Messages" + "

" + "" + msg.author + " : "); sb.append("" + msg.subject + ""); /* if(msg.body.length == 0) { sb.append(msg.subject + "(no text)"); } else { sb.append("" + msg.subject + ""); } */ sb.append("
" + msg.date + "
" + "
 
"); } topRightBoxForum = sb.toString(); topRightBoxForumButton = ""; } function setTopRightBox(html,bhtml) { document.getElementById("topRightBox").innerHTML = html; //document.getElementById("topRightButton").innerHTML = bhtml; } // make sure we check that form is submitted if any changes were made window.onbeforeunload = hdlBeforeUnload;