/** =============================================================== 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