/***** 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("
" +
"";
}
}
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.
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("
");
}
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;