/**
===============================================================
NEWSFUTURES JS <-> PS BRIDGE OBJECTS
Copyright (c) 2008,2009 Jason Fries,
Iowa Electronic health Markets,
http://iehm.uiowa.edu/iehm/index.html
University of Iowa
description:
revisions: 2008.06.11 first release
===============================================================
**/
//index order corresponds to int id for each state
//active = 2, halted = 3, closed = 4
var stateNames = [ "NOT_USED", "suspended", "active", "halted", "closed" ];
var altStateNames = [ "NOT_USED", "suspended", "open", "waiting for decision", "completed" ];
/**
===============================================================
* Newsfutures USER
* @description
* Newsfutures User
===============================================================
*/
function User()
{
this.login = "unknown_login";
this.id = -1;
this.incept = -1;
this.flags = [];
this.attributes = new Object();
this.props = new Object();
this.profile = new Object();
this.webservice = new HttpService();
this.updateCallback = null;
//default auto-logout for inactivity (10 minutes)
this.timeout = 1000 * 60 * 10;
}
/**
* Is a User Logged In?
* @descripition
*/
User.prototype.isLoggedIn = function()
{
return !(this.id == -1 && this.login == "unknown_login");
}
/**
* Init Event Handlers
* @descripition Setup webservice listeners (for setting attributes)
*/
User.prototype.init = function()
{
this.webservice.url = NFSiteConfig.USER_XML_FEED;
//setup params to pass to event handler methods
var parent = this;
var success = this.resultHandler;
var fault = this.faultHandler;
this.webservice.addEventListener( HttpService.RESULT, function(response) { success(response, parent); } );
this.webservice.addEventListener( HttpService.FAULT, function(response) { fault(response, parent); } );
this.webservice.send();
}
/**
* Refresh State Data
*/
User.prototype.refresh = function()
{
this.webservice.send();
}
/**
* Result OK Handler
* @description Ajax response returns correcty
*/
User.prototype.resultHandler = function( response, parent )
{
parent.updateFromXML( response );
if(parent.updateCallback) parent.updateCallback();
}
/**
* Result OK Handler
* @description Ajax response returns correcty
*/
User.prototype.faultHandler = function( response )
{
alert("NF User Ajax ERROR! " + response);
}
/**
* Get Flag
* @description
* @param Flag name String
* @return boolean Flag is checked on this object?
*/
User.prototype.hasFlag = function( flag )
{
return (this.flags.indexOf(flag) != -1);
}
/**
* Get Attribute
* @description Attributes are custom fields
* POST to /feeds/user.xml?attribute=XXX&value=XXX will dynamically set property.
*/
User.prototype.setAttribute = function( name, value )
{
var parameters = "attribute=" + encodeURI(name) + "&value=" + encodeURI(value);
this.webservice.send(parameters);
}
/**
* Set Attribute
* @description Attributes are custom fields (why doesn't NF use props?)
*/
User.prototype.getAttribute = function( name )
{
return this.attributes[name];
}
/**
* Update from XML
* @description Load data from XML
*/
User.prototype.updateFromXML = function( xml )
{
if( xml.getElementsByTagName("id").item(0) )
this.id = parseInt( xml.getElementsByTagName("id").item(0).childNodes[0].data );
if( xml.getElementsByTagName("login").item(0) )
this.login = xml.getElementsByTagName("login").item(0).childNodes[0].data;
//Properties
if( xml.getElementsByTagName("props").item(0) && (xml.getElementsByTagName("props").item(0).childNodes.length != 0) )
this.props = setProps(xml.getElementsByTagName("props").item(0).childNodes[0].data);
else
this.props = setProps("");
//Flags
if( xml.getElementsByTagName("flags").item(0) && (xml.getElementsByTagName("props").item(0).childNodes.length != 0) )
this.flags = setFlags(xml.getElementsByTagName("flags").item(0).childNodes[0].data);
//Attributes
if( xml.getElementsByTagName("attributes").item(0) && (xml.getElementsByTagName("attributes").item(0).childNodes.length != 0) )
this.attributes = setAttributes(xml.getElementsByTagName("attributes").item(0).childNodes[0].data);
//Profile
if( xml.getElementsByTagName("profile").item(0) && (xml.getElementsByTagName("profile").item(0).childNodes.length != 0) ) {
this.incept = parseInt( xml.getElementsByTagName("profile").item(0).attributes.getNamedItem("incept").value );
var children = xml.getElementsByTagName("profile").item(0).childNodes;
for(var i=0; i < children.length; i++){
//TODO: fix; extra null child nodes are generated for some reason(WHY?)
if(children[i].tagName){
//is there a value associated with this value
if(children[i].childNodes.length != 0){
this.profile[children[i].tagName] = children[i].childNodes[0].data;
}else{
this.profile[children[i].tagName] = "";
}
}
}
}
}
/** COOKIE MANAGEMENT **/
/**
* Update From Cookie
* @description Init User object form cookie data
* requires valid cookie
*/
User.prototype.updateFromCookie = function()
{
}
/**
* Check Cookie Expiration
* @description
*/
User.prototype.checkCookie = function()
{
//same user?
//expired cookie?
//everything is okay, so update cookie
}
/**
*
* @description Write all user data to cookie and
* update
*/
User.prototype.refreshCookie = function()
{
var ptsJSL = getCookie('ptsJSL');
var ptsLogin = getCookie("ptsLogin");
alert(ptsJSL);
alert(ptsLogin);
}
/**
===============================================================
* Newsfutures ORDER
* @description
* This object is both for submitting new orders *and*
* current standing orders. The only real difference is that
* standing orders will have all parameters set while new orders
* will only have those that are needed for NFCoreBroker to accept
* an order submssion.
* EXAMPLE XML
0
true
true
14
1
[buy, long, absBuy]
-1
???
===============================================================
*/
function Order( market, type, qty, price )
{
//Parent Market
this.market = market;
this.name = market.name;
//Fields for new order submission
this.qty = qty;
this.price = price;
//"buy","sell","short","cover","cancel","liquidify","bundle"
this.type = type;
this.allowBundles = market.group.allowBundles;
this.allowShorts = !market.noShorts;
// Only standing orders will set these
this.id = -1;
this.user = null;
this.flags = [];
this.isAbsBuy = false;
this.isBuy = false;
//Response XML
this.response = null;
}
/**
* Get Flag
* @description
* @param Flag name String
* @return boolean Flag is checked on this object?
*/
Order.prototype.hasFlag = function( flag )
{
return (this.flags.indexOf(flag) != -1);
}
/**
* Update from XML
* @description
*
*/
Order.prototype.updateFromXML = function( xml )
{
if( xml.getElementsByTagName("id").item(0) ) this.id = parseInt(xml.getElementsByTagName("id").item(0).childNodes[0].data);
if( xml.getElementsByTagName("isBuy").item(0) ) this.isBuy = ("true" == xml.getElementsByTagName("isBuy").item(0).childNodes[0].data);
if( xml.getElementsByTagName("isAbsBuy").item(0) ) this.isAbsBuy = ( "true" == xml.getElementsByTagName("isAbsBuy").item(0).childNodes[0].data);
if( xml.getElementsByTagName("qty").item(0) ) this.qty = parseInt( xml.getElementsByTagName("qty").item(0).childNodes[0].data );
if( xml.getElementsByTagName("price").item(0) ) this.price = parseInt( xml.getElementsByTagName("price").item(0).childNodes[0].data );
if( xml.getElementsByTagName("flags").item(0) ) this.flags = setFlags( xml.getElementsByTagName("flags").item(0).childNodes[0].data );
//user
if( xml.getElementsByTagName("user").item(0) ){
this.user = new User();
var userXML = xml.getElementsByTagName("user").item(0);
this.user.login = userXML.getElementsByTagName("login").item(0).childNodes[0].data;
this.user.id = parseInt( userXML.getElementsByTagName("id").item(0).childNodes[0].data );
}
//set type
if(!this.isBuy && this.hasFlag("long")) this.type = "sell";
else if(this.isBuy && this.isAbsBuy && this.hasFlag("long")) this.type = "buy";
else if(!this.isAbsBuy && this.isBuy && !this.hasFlag("long") ) this.type = "short"; //NF parlance "pre-sell"
else if(this.isAbsBuy && !this.isBuy) this.type = "cover"; //NF parlance "buy-back"
}
/**
* To String
* @description String output
*/
Order.prototype.toString = function()
{
if(!user)
return "ORDER {name:" + this.name + " type:" + this.type + " qty:" + this.qty + " price" + this.price + "}";
else
return "ORDER {id:" + this.id + " isBuy:" + this.isBuy + " isAbsBuy:" + this.isAbsBuy + " login:" + this.user.login + "}";
}
/**
===============================================================
* Newsfutures OrderBook
* @description
* All Orders
===============================================================
*/
function OrderBook( market )
{
//parent Market
this.market = market;
this.bestBuy = null
this.bestSell = null;
this.buyOrders = [];
this.sellOrders = [];
//All current order ID's
this.ordersById = new Object();
}
/**
* Get Orders by User Login
* @description Return array of all orders (buy&sell)
* for a specific user
* @param String user login
* @return Array [ NFOrder,.. ]
*/
OrderBook.prototype.getOrdersByUser = function( login )
{
var orders = [];
var order;
for(var i=0; i < this.buyOrders.length; i++){
order = this.buyOrders[i];
if(order.user.login == login){
orders.push(order);
}
}
for(var i=0; i < this.sellOrders.length; i++){
order = this.sellOrders[i];
if(order.user.login == login){
orders.push(order);
}
}
return orders;
}
/**
* Is New Order
* @description Is this order already loaded?
*/
OrderBook.prototype.isNewOrder = function( id )
{
return (this.ordersById[id] == null);
}
/**
* Update from XML
* @description Load entire orderBook from XML
* Only store new Orders
*/
OrderBook.prototype.updateFromXML = function( xml )
{
//Best BUY
if( xml.getElementsByTagName("bestBuy").item(0) ){
this.bestBuy = new Order( this.market, "buy", 0, 0 );
this.bestBuy.updateFromXML( xml.getElementsByTagName("bestBuy").item(0) );
}
// Best SELL
if( xml.getElementsByTagName("bestSell").item(0) ){
this.bestSell = new Order( this.market, "sell", 0, 0 );
this.bestSell.updateFromXML( xml.getElementsByTagName("bestSell").item(0) );
}
var allBuyOrders = xml.getElementsByTagName("buyOrders").item(0).getElementsByTagName("order");
var allSellOrders = xml.getElementsByTagName("sellOrders").item(0).getElementsByTagName("order");
// alert(allBuyOrders.length + " " + allSellOrders.length);
// BUY ORDERS
for(var i=0; i b.price) {
return 1;
}else{
return 0;
}
}
OrderBook.prototype.orderByQty = function(a, b)
{
if (a.qty < b.qty) {
return -1;
}else if (a.qty > b.qty) {
return 1;
}else{
return 0;
}
}
/**
===============================================================
* Newsfutures TOURNAMENT
* @description
* Root NF trading object, while there is no
* analog in the existing IEhM nomenclature,
* we use Tournaments as container objects for
* Markets using the same currency and to define
* user group access permissions.
===============================================================
*/
function Tournament()
{
this.name = "unknown_name";
this.id = -1;
this.symbol = "unknown_symbol";
this.info = "unkown_info";
this.title = "unknown_title";
this.state = 0;
this.stateName = "";
this.nextStateTs = -1; //Epoch time
this.flags = [];
this.props = new Object();
this.keywords = [];
//Trnmt specific
this.isBAM = false;
this.memberCount = 0;
this.restricted = false;
this.account = null;
//User trmnt permissions
this.onAccessList = false;
this.appState = "";
// All Groups in this tournament
this.groups = new Array();
// All contracts that do not belong to any Group object
this.markets = new Array();
}
/**
* Get Child Group by some propery
*/
Tournament.prototype.getGroup = function( param, value )
{
for(var i=0; i (qual12ClassColors.length-1)) ci = Math.abs(qual12ClassColors.length - i);
market.color = qual12ClassColors[ci];
}
this.markets.push(market);
this.holdings.push(market.holdings);
}
}
/**
* Allow Shorts
* @description Test each child Market's noShorts flag to
* see if short sales are allowed.
*/
Group.prototype.allowShorts = function()
{
var shorts = false;
for(var i=0; i
1233532800000
36
5
*
*/
function setPriceHistory( xml )
{
var prices = new Array();
var volume = new Array();
var datapoints = xml.getElementsByTagName("data");
for(var i=0; i< datapoints.length; i++){
var data = datapoints.item(i);
var ts = parseInt( data.getElementsByTagName("date").item(0).childNodes[0].data );
var price = parseInt( data.getElementsByTagName("price").item(0).childNodes[0].data );
var tradeVolume = parseInt( data.getElementsByTagName("volume").item(0).childNodes[0].data );
// [epoch time date, value]
prices.push( [ ts, price ] );
volume.push( [ ts, tradeVolume ] );
}
//flot doesn't automatically order items in a time series, so sort based on index[0]
prices = prices.sort();
volume = volume.sort();
return { prices:prices, volume:volume };
}
/**
* Set Flags
* @description
*/
function setFlags( list )
{
//strip out braces
list = list.replace("[","");
list = list.replace("]","");
//remove whitespace (all NF flags are continous words)
list = list.replace(/\s*/gi, "");
return list.split(",");
}
/**
* Set Attributes
* @description
*/
function setAttributes( list )
{
var attributes = new Object();
//strip out braces
list = list.replace("{","");
list = list.replace("}","");
//remove whitespace (all NF flags are continous words)
list = list.replace(/\s*/gi, "");
var items = list.split(",");
for(var i=0; i