<commit_before>var HTerm = function () {

    "use strict";

    var ellipsoids = {"1": "bessel", "2": "international", "3": "wgs84"};
    var ell_txt = "VALG AV ELLIPSOIDE.P SETTES LIK 1 FOR:\nNORSK BESSELS,LIK 2 FOR INTERNASJONAL:\nOG LIK 3 FOR WGS-84-ELLIPSOIDEN:\nLEGG INN P:";

    var Program = Backbone.View.extend({

        currentArg: null,

        running: false,

        args: [],

        cmd: function (command, term) {
            var arg = this.getArg(command);
            if (arg) {
                term.echo(arg);
            } else {
                this.doCompute(term);
            }
        },

        getArg: function (data) {
            if (this.args.length === 0) {
                return null;
            }
            var arg;
            if (this.currentArg === null) {
                this.currentArg = 0;
                arg = this.args[this.currentArg];
                return arg.text;
            } else if (this.currentArg < this.args.length) {
                arg = this.args[this.currentArg];
                arg.value = data;
                this.currentArg++;
                if (this.currentArg < this.args.length) {
                    arg = this.args[this.currentArg];
                    return arg.text;
                }
            }
            return null;
        },

        getRunning: function () {
            return this.running;
        },

        setRunning: function (running) {
            this.running = running;
        },

        doCompute: function (term) {
            this.running = false;
            term.set_prompt("holsenJS> ");
        },

        getValue: function (name) {
            return _.find(this.args, function (arg) {
                return arg.name === name;
            }).value;
        }
    });

    var ProgramWithSelection = Program.extend({

        getArg: function (data) {
            if (this.args.length === 0) {
                return null;
            }
            var arg;
            if (this.currentArg === null) {
                this.currentArg = 0;
                arg = this.args[this.currentArg];
                return arg.text;
            } else if (this.currentArg < this.args.length) {
                arg = this.args[this.currentArg];

                if (arg.name === "r") {
                    this.args = _.filter(this.args, function (arg) {
                        return (arg["for"] === undefined || arg["for"] === parseInt(data, 10));
                    });
                }

                arg.value = data;
                this.currentArg++;
                if (this.currentArg < this.args.length) {
                    arg = this.args[this.currentArg];
                    return arg.text;
                }
            }
            return null;
        }
    });

    var Krrad = Program.extend({
        args: [
            {"name": "p", "text": ell_txt},
            {"name": "br", "text": "Legg inn bredde for punkt :"},
            {"name": "a", "text": "Legg inn asimut for punkt :"}
        ],

        doCompute: function (term) {

            var p = this.getValue("p");
            var br = this.getValue("br");
            var a = this.getValue("a");

            var holsen = new Holsen();
            holsen.setEllipsoid(ellipsoids[p]);
            var data = holsen.krrad(parseFloat(br), parseFloat(a));
            term.echo("Meridiankrumningsradius M  = " + data.M + "\n" +
                "Normalkrumningsradius   N  = " + data.N  + "\n" +
                "Midlere krumningsradius MR = " + data.MR  + "\n" +
                "Krumningsradius i retning asimut AR = " + data.AR + "\n");
            Program.prototype.doCompute.apply(this, arguments);
        }
    });

    var Lgeo1 = Program.extend({
        args: [
            {"name": "b1", "text": "Legg inn b1 :"},
            {"name": "l1", "text": "Legg inn l1 :"},
            {"name": "s12", "text": "Legg inn s12 :"},
            {"name": "a12", "text": "Legg inn a12 :"},
            {"name": "p", "text": ell_txt}
        ],

        doCompute: function (term) {

            var b1 = this.getValue("b1");
            var l1 = this.getValue("l1");
            var s12 = this.getValue("s12");
            var a12 = this.getValue("a12");
            var p = this.getValue("p");

            var holsen = new Holsen();
            holsen.setEllipsoid(ellipsoids[p]);
            var data = holsen.lgeo1(parseFloat(l1), parseFloat(b1), parseFloat(s12), parseFloat(a12));
            term.echo('GEOGRAFISKE KOORDINATER:\n' +
                'B2:' + data.B2 + "\n" +
                'NEGATIV B2 BETYR SYDLIG BREDDE:\n\n' +
                'L2:' + data.L2 + '\n\n' +
                'ASIMUT FRA PUNKT 2 TIL PUNKT 1:\n' +
                'A2:' + data.A2 + '\n' +
                'PROGRAMMET REGNER A2 I FORHOLD TIL NORD,OGSÅ PÅ\n' +
                'DEN SYDLIGE HALVELLIPSOIDE');

            Program.prototype.doCompute.apply(this, arguments);
        }
    });

    var Lgeo2 = Program.extend({
        args: [
            {"name": "b1", "text": "Legg inn b1 :"},
            {"name": "l1", "text": "Legg inn l1 :"},
            {"name": "b2", "text": "Legg inn b2 :"},
            {"name": "l2", "text": "Legg inn l2 :"},
            {"name": "p", "text": ell_txt}
        ],

        doCompute: function (term) {

            var b1 = this.getValue("b1");
            var l1 = this.getValue("l1");
            var b2 = this.getValue("b2");
            var l2 = this.getValue("l2");
            var p = this.getValue("p");

            var holsen = new Holsen();
            holsen.setEllipsoid(ellipsoids[p]);
            var data = holsen.lgeo2(parseFloat(l1), parseFloat(b1), parseFloat(l2), parseFloat(b2));

            term.echo('ASIMUT FRA 1 TIL 2 OG FRA 2 TIL 1,I FORHOLD\n' +
                'TIL NORD OGSÅ PÅ DEN SYDLIGE HALVELLIPSOIDE\n' +
                'A1:' + data.A1 + '\n' +
                'A2:' + data.A2 + '\n ' +
                'GEODETISK LINJE FRA 1 TIL 2:\n' +
                'S:' + data.S);
            Program.prototype.doCompute.apply(this, arguments);
        }
    });

    var Meridbue = ProgramWithSelection.extend({
        args: [
            {"name": "r", "text": "R SETTES LIK 0 NÅR (B1,B2) ER GITT .I MOTSATT FALL SETTES R LIK 1 NÅR B1 0G G ER GITT'"},
            {"name": "p", "text": ell_txt},
            {"name": "b1", "text": "LEGG INN BREDDEN B1:"},
            {"name": "b2", "text": "LEGG INN BREDDEN B2:", "for": 0},
            {"name": "g", "text": "LEGG INN G:", "for": 1}
        ],

        doCompute: function (term) {
            var p = this.getValue("p");
            var holsen = new Holsen();
            holsen.setEllipsoid(ellipsoids[p]);

            var operation = parseInt(this.getValue("r"), 10);
            var b1 = parseFloat(this.getValue("b1"));
            if (operation === 0) {
                var b2 = parseFloat(this.getValue("b2"));
                term.echo('MERIDIANBUE =  ' + holsen.meridbue(b1, b2));
            } else if (operation === 1) {
                var g = parseFloat(this.getValue("g"));
                term.echo('BREDDE B2 =  ' + holsen.meridbue_inv(b1, g));
            }

            Program.prototype.doCompute.apply(this, arguments);
        }
    });

    var Terminal = Backbone.View.extend({

        programs: {
            "l-geo1": {
                "program": Lgeo1,
                "help": "BEREGNING AV GEOGRAFISKE KOORDINATER FOR PUNKT 2 OG ASIMUT FOR LINJEN I PUNKT 2"
            },
            "l-geo2": {
                "program": Lgeo2,
                "help": "GEOGRAFISKE KOORDINATER ER GITT FOR TO PUNKTER 1 OG 2,(B1,L1) OG(B2,L2).BEREGN GEODETISK LINJE FRA 1 TIL 2 OG ASIMUT I PUNKT 1 OG I PUNKT 2."
            },
            "krrad": {
                "program": Krrad,
                "help": "BEREGNING AV KRUMNINGSRADIER"
            },
            "meridbue": {
                "program": Meridbue,
                "help": "BEREGNING AV MERIDIANBUEN MELLOM BREDDE B1 OG B2\n ELLER B2 NåR B1 OG MERIDIANBUEN G ER GITT"
            }
        },

        program: null,

        cmd: function (command, term) {
            if (this.program && this.program.getRunning()) {
                this.program.cmd(command, term, this);
            } else {
                term.set_prompt("holsenJS> ");
                if (command === "help") {
                    term.echo("Available commands are:");
                    _.each(this.programs, function (program, key) {
                        term.echo("\t" + key + ": " + program.help);
                    });
                } else if(this.programs[command]) {
                    this.program = new this.programs[command].program;
                    this.program.setRunning(true);
                    term.set_prompt(command + "> ");
                    this.cmd(command, term);
                } else {
                    term.echo("Invalid command: " + command);
                }
            }
        }
    });

/*
    var Terminal = function () {

        var programs = {
            "meridbue": {
                "program": Meridbue,
                "help": "BEREGNING AV MERIDIANBUEN MELLOM BREDDE B1 OG B2\n ELLER B2 NåR B1 OG MERIDIANBUEN G ER GITT"
            },
            "krrad": {
                "program": Krrad,
                "help": "BEREGNING AV KRUMNINGSRADIER"
            },
            "l-geo1": {
                "program": Lgeo1,
                "help": "BEREGNING AV GEOGRAFISKE KOORDINATER FOR PUNKT 2 OG ASIMUT FOR LINJEN I PUNKT 2"
            }
        };

        var program;

        var cmd = function (command, term) {

            if (program && program.getRunning()) {
                program.cmd(command, term, this);
            } else {
                term.set_prompt("holsenJS> ");
                if (command === "help") {
                    term.echo("Available commands are:");
                    for (var key in programs) {
                        term.echo("\t" + key + ": " + programs[key].help);
                    }
                }
                else if(programs[command]) {
                    program = new programs[command].program();
                    program.setRunning(true);
                    term.set_prompt( command + "> ");
                    this.cmd(command, term);
                } else {
                    term.echo("Invalid command: " + command);
                }
            }
        };
        return {
            "cmd": cmd
        }
    };

    */

    var createTerminal = function (element) {
        jQuery(function($, undefined) {
            var terminal = new Terminal();
            element.terminal(function(command, term) {
                    terminal.cmd(command, term);
                },
                {
                    greetings: 'Holsens smaaprog in JavaScript',
                    name: 'js_demo',
                    height: 600,
                    width: 600,
                    prompt: 'holsenJS> '
                }
            );
        });
    };

    return {
        "createTerminal": createTerminal
    };
};<commit_msg>more shait removed<commit_after>var HTerm = function () {

    "use strict";

    var ellipsoids = {"1": "bessel", "2": "international", "3": "wgs84"};
    var ell_txt = "VALG AV ELLIPSOIDE.P SETTES LIK 1 FOR:\nNORSK BESSELS,LIK 2 FOR INTERNASJONAL:\nOG LIK 3 FOR WGS-84-ELLIPSOIDEN:\nLEGG INN P:";

    var Program = Backbone.View.extend({

        currentArg: null,

        running: false,

        args: [],

        cmd: function (command, term) {
            var arg = this.getArg(command);
            if (arg) {
                term.echo(arg);
            } else {
                this.doCompute(term);
            }
        },

        getArg: function (data) {
            if (this.args.length === 0) {
                return null;
            }
            var arg;
            if (this.currentArg === null) {
                this.currentArg = 0;
                arg = this.args[this.currentArg];
                return arg.text;
            } else if (this.currentArg < this.args.length) {
                arg = this.args[this.currentArg];
                arg.value = data;
                this.currentArg++;
                if (this.currentArg < this.args.length) {
                    arg = this.args[this.currentArg];
                    return arg.text;
                }
            }
            return null;
        },

        getRunning: function () {
            return this.running;
        },

        setRunning: function (running) {
            this.running = running;
        },

        doCompute: function (term) {
            this.running = false;
            term.set_prompt("holsenJS> ");
        },

        getValue: function (name) {
            return _.find(this.args, function (arg) {
                return arg.name === name;
            }).value;
        }
    });

    var ProgramWithSelection = Program.extend({

        getArg: function (data) {
            if (this.args.length === 0) {
                return null;
            }
            var arg;
            if (this.currentArg === null) {
                this.currentArg = 0;
                arg = this.args[this.currentArg];
                return arg.text;
            } else if (this.currentArg < this.args.length) {
                arg = this.args[this.currentArg];

                if (arg.name === "r") {
                    this.args = _.filter(this.args, function (arg) {
                        return (arg["for"] === undefined || arg["for"] === parseInt(data, 10));
                    });
                }

                arg.value = data;
                this.currentArg++;
                if (this.currentArg < this.args.length) {
                    arg = this.args[this.currentArg];
                    return arg.text;
                }
            }
            return null;
        }
    });

    var Krrad = Program.extend({
        args: [
            {"name": "p", "text": ell_txt},
            {"name": "br", "text": "Legg inn bredde for punkt :"},
            {"name": "a", "text": "Legg inn asimut for punkt :"}
        ],

        doCompute: function (term) {

            var p = this.getValue("p");
            var br = this.getValue("br");
            var a = this.getValue("a");

            var holsen = new Holsen();
            holsen.setEllipsoid(ellipsoids[p]);
            var data = holsen.krrad(parseFloat(br), parseFloat(a));
            term.echo("Meridiankrumningsradius M  = " + data.M + "\n" +
                "Normalkrumningsradius   N  = " + data.N  + "\n" +
                "Midlere krumningsradius MR = " + data.MR  + "\n" +
                "Krumningsradius i retning asimut AR = " + data.AR + "\n");
            Program.prototype.doCompute.apply(this, arguments);
        }
    });

    var Lgeo1 = Program.extend({
        args: [
            {"name": "b1", "text": "Legg inn b1 :"},
            {"name": "l1", "text": "Legg inn l1 :"},
            {"name": "s12", "text": "Legg inn s12 :"},
            {"name": "a12", "text": "Legg inn a12 :"},
            {"name": "p", "text": ell_txt}
        ],

        doCompute: function (term) {

            var b1 = this.getValue("b1");
            var l1 = this.getValue("l1");
            var s12 = this.getValue("s12");
            var a12 = this.getValue("a12");
            var p = this.getValue("p");

            var holsen = new Holsen();
            holsen.setEllipsoid(ellipsoids[p]);
            var data = holsen.lgeo1(parseFloat(l1), parseFloat(b1), parseFloat(s12), parseFloat(a12));
            term.echo('GEOGRAFISKE KOORDINATER:\n' +
                'B2:' + data.B2 + "\n" +
                'NEGATIV B2 BETYR SYDLIG BREDDE:\n\n' +
                'L2:' + data.L2 + '\n\n' +
                'ASIMUT FRA PUNKT 2 TIL PUNKT 1:\n' +
                'A2:' + data.A2 + '\n' +
                'PROGRAMMET REGNER A2 I FORHOLD TIL NORD,OGSÅ PÅ\n' +
                'DEN SYDLIGE HALVELLIPSOIDE');

            Program.prototype.doCompute.apply(this, arguments);
        }
    });

    var Lgeo2 = Program.extend({
        args: [
            {"name": "b1", "text": "Legg inn b1 :"},
            {"name": "l1", "text": "Legg inn l1 :"},
            {"name": "b2", "text": "Legg inn b2 :"},
            {"name": "l2", "text": "Legg inn l2 :"},
            {"name": "p", "text": ell_txt}
        ],

        doCompute: function (term) {

            var b1 = this.getValue("b1");
            var l1 = this.getValue("l1");
            var b2 = this.getValue("b2");
            var l2 = this.getValue("l2");
            var p = this.getValue("p");

            var holsen = new Holsen();
            holsen.setEllipsoid(ellipsoids[p]);
            var data = holsen.lgeo2(parseFloat(l1), parseFloat(b1), parseFloat(l2), parseFloat(b2));

            term.echo('ASIMUT FRA 1 TIL 2 OG FRA 2 TIL 1,I FORHOLD\n' +
                'TIL NORD OGSÅ PÅ DEN SYDLIGE HALVELLIPSOIDE\n' +
                'A1:' + data.A1 + '\n' +
                'A2:' + data.A2 + '\n ' +
                'GEODETISK LINJE FRA 1 TIL 2:\n' +
                'S:' + data.S);
            Program.prototype.doCompute.apply(this, arguments);
        }
    });

    var Meridbue = ProgramWithSelection.extend({
        args: [
            {"name": "r", "text": "R SETTES LIK 0 NÅR (B1,B2) ER GITT .I MOTSATT FALL SETTES R LIK 1 NÅR B1 0G G ER GITT'"},
            {"name": "p", "text": ell_txt},
            {"name": "b1", "text": "LEGG INN BREDDEN B1:"},
            {"name": "b2", "text": "LEGG INN BREDDEN B2:", "for": 0},
            {"name": "g", "text": "LEGG INN G:", "for": 1}
        ],

        doCompute: function (term) {
            var p = this.getValue("p");
            var holsen = new Holsen();
            holsen.setEllipsoid(ellipsoids[p]);

            var operation = parseInt(this.getValue("r"), 10);
            var b1 = parseFloat(this.getValue("b1"));
            if (operation === 0) {
                var b2 = parseFloat(this.getValue("b2"));
                term.echo('MERIDIANBUE =  ' + holsen.meridbue(b1, b2));
            } else if (operation === 1) {
                var g = parseFloat(this.getValue("g"));
                term.echo('BREDDE B2 =  ' + holsen.meridbue_inv(b1, g));
            }

            Program.prototype.doCompute.apply(this, arguments);
        }
    });

    var Terminal = Backbone.View.extend({

        programs: {
            "l-geo1": {
                "program": Lgeo1,
                "help": "BEREGNING AV GEOGRAFISKE KOORDINATER FOR PUNKT 2 OG ASIMUT FOR LINJEN I PUNKT 2"
            },
            "l-geo2": {
                "program": Lgeo2,
                "help": "GEOGRAFISKE KOORDINATER ER GITT FOR TO PUNKTER 1 OG 2,(B1,L1) OG(B2,L2).BEREGN GEODETISK LINJE FRA 1 TIL 2 OG ASIMUT I PUNKT 1 OG I PUNKT 2."
            },
            "krrad": {
                "program": Krrad,
                "help": "BEREGNING AV KRUMNINGSRADIER"
            },
            "meridbue": {
                "program": Meridbue,
                "help": "BEREGNING AV MERIDIANBUEN MELLOM BREDDE B1 OG B2\n ELLER B2 NåR B1 OG MERIDIANBUEN G ER GITT"
            }
        },

        program: null,

        cmd: function (command, term) {
            if (this.program && this.program.getRunning()) {
                this.program.cmd(command, term, this);
            } else {
                term.set_prompt("holsenJS> ");
                if (command === "help") {
                    term.echo("Available commands are:");
                    _.each(this.programs, function (program, key) {
                        term.echo("\t" + key + ": " + program.help);
                    });
                } else if(this.programs[command]) {
                    this.program = new this.programs[command].program;
                    this.program.setRunning(true);
                    term.set_prompt(command + "> ");
                    this.cmd(command, term);
                } else {
                    term.echo("Invalid command: " + command);
                }
            }
        }
    });

    var createTerminal = function (element) {
        jQuery(function($, undefined) {
            var terminal = new Terminal();
            element.terminal(function(command, term) {
                    terminal.cmd(command, term);
                },
                {
                    greetings: 'Holsens smaaprog in JavaScript',
                    name: 'js_demo',
                    height: 600,
                    width: 600,
                    prompt: 'holsenJS> '
                }
            );
        });
    };

    return {
        "createTerminal": createTerminal
    };
};<|endoftext|>


<commit_before>var CEXio = require('cexio'),
   moment = require('moment'),
    async = require('async'),
        _ = require('lodash'),
     util = require('../core/util'),
      log = require('../core/log');

var Trader = function(config) {
  this.user = config.username;
  this.key = config.key;
  this.secret = config.secret;
  this.pair = 'ghs_' + config.currency.toLowerCase();
  this.name = 'cex.io';

  this.cexio = new CEXio(
    this.pair,
    this.user,
    this.key,
    this.secret
  );

  _.bindAll(this);
}

Trader.prototype.getTrades = function(since, callback, descending) {
  var args = _.toArray(arguments);
  var process = function(err, trades) {
    if(err || !trades || trades.length === 0)
      return this.retry(this.getTrades, args, err);

    var f = parseFloat;

    if(descending)
      callback(null, trades);
    else
      callback(null, trades.reverse());
  }

  this.cexio.trades({}, _.bind(process, this));
}

Trader.prototype.buy = function(amount, price, callback) {
  // Prevent "You incorrectly entered one of fields."
  // because of more than 8 decimals.
  amount *= 100000000;
  amount = Math.floor(amount);
  amount /= 100000000;

  log.debug('BUY', amount, 'GHS @', price, 'BTC');

  var set = function(err, data) {
    if(err)
      return log.error('unable to buy:', err);
    if(data.error)
      return log.error('unable to buy:', data.error);

    log.debug('BUY order placed.  Order ID', data.id);
    callback(null, data.id);
  };

  this.cexio.place_order('buy', amount, price, _.bind(set, this));
}

Trader.prototype.sell = function(amount, price, callback) {
  // Prevent "You incorrectly entered one of fields."
  // because of more than 8 decimals.
  amount *= 100000000;
  amount = Math.floor(amount);
  amount /= 100000000;

  // test placing orders which will not be filled
  //price *= 10; price = price.toFixed(8);

  log.debug('SELL', amount, 'GHS @', price, 'BTC');

  var set = function(err, data) {
    if(err)
      return log.error('unable to sell:', err);
    if(data.error)
      return log.error('unable to sell:', data.error);

    log.debug('SELL order placed.  Order ID', data.id);
    callback(null, data.id);
  };

  this.cexio.place_order('sell', amount, price, _.bind(set, this));
}

Trader.prototype.retry = function(method, args, err) {
  var wait = +moment.duration(10, 'seconds');
  log.debug(this.name, 'returned an error, retrying..', err, 'waiting for', wait, 'ms');

  if (!_.isFunction(method)) {
    log.error(this.name, 'failed to retry, no method supplied.');
    return;
  }

  var self = this;

  // make sure the callback (and any other fn)
  // is bound to Trader
  _.each(args, function(arg, i) {
    if(_.isFunction(arg))
      args[i] = _.bind(arg, self);
  });

  // run the failed method again with the same
  // arguments after wait
  setTimeout(
    function() { method.apply(self, args) },
    wait
  );
}

Trader.prototype.getPortfolio = function(callback) {
  var args = _.toArray(arguments);
  var calculate = function(err, data) {
    if(err)
      return this.retry(this.getPortfolio, args, err);

    currency = parseFloat(data.BTC.available)
    if(parseFloat(data.BTC.orders)){
      currency -= parseFloat(data.BTC.orders)
    }
    assets = parseFloat(data.GHS.available);
    if( parseFloat(data.GHS.orders)){
	  assets -= parseFloat(data.GHS.orders);
    }

    var portfolio = [];
    portfolio.push({name: 'BTC', amount: currency});
    portfolio.push({name: 'GHS', amount: assets});
    callback(err, portfolio);
  }
  this.cexio.balance(_.bind(calculate, this));
}

Trader.prototype.getTicker = function(callback) {
  var set = function(err, data) {
    var ticker = {
      ask: data.ask,
      bid: data.bid
    };
    callback(err, ticker);
  }
  this.cexio.ticker(_.bind(set, this));
}

Trader.prototype.getFee = function(callback) {
  // cexio does currently don't take a fee on trades
  callback(false, 0.0);
}

Trader.prototype.checkOrder = function(order, callback) {
  var check = function(err, result) {

    if(err)
      callback(false, true);
    if(result.error)
      callback(false, true);

    var exists = false;
    _.forEach(result, function(entry) {
      if(entry.id === order) {
        exists = true; return;
      }
    });
    callback(err, !exists);
  };

  this.cexio.open_orders(_.bind(check, this));
}

Trader.prototype.cancelOrder = function(order) {
  var check= function(err, result) {
    if(err)
      log.error('cancel order failed:', err);
    if(typeof(result) !== 'undefined' && result.error)
      log.error('cancel order failed:', result.error);
  }
  this.cexio.cancel_order(order, check);
}

module.exports = Trader;
<commit_msg>fixed checkorder in cexio<commit_after>var CEXio = require('cexio'),
   moment = require('moment'),
    async = require('async'),
        _ = require('lodash'),
     util = require('../core/util'),
      log = require('../core/log');

var Trader = function(config) {
  this.user = config.username;
  this.key = config.key;
  this.secret = config.secret;
  this.pair = 'ghs_' + config.currency.toLowerCase();
  this.name = 'cex.io';

  this.cexio = new CEXio(
    this.pair,
    this.user,
    this.key,
    this.secret
  );

  _.bindAll(this);
}

Trader.prototype.getTrades = function(since, callback, descending) {
  var args = _.toArray(arguments);
  var process = function(err, trades) {
    if(err || !trades || trades.length === 0)
      return this.retry(this.getTrades, args, err);

    var f = parseFloat;

    if(descending)
      callback(null, trades);
    else
      callback(null, trades.reverse());
  }

  this.cexio.trades({}, _.bind(process, this));
}

Trader.prototype.buy = function(amount, price, callback) {
  // Prevent "You incorrectly entered one of fields."
  // because of more than 8 decimals.
  amount *= 100000000;
  amount = Math.floor(amount);
  amount /= 100000000;

  log.debug('BUY', amount, 'GHS @', price, 'BTC');

  var set = function(err, data) {
    if(err)
      return log.error('unable to buy:', err);
    if(data.error)
      return log.error('unable to buy:', data.error);

    log.debug('BUY order placed.  Order ID', data.id);
    callback(null, data.id);
  };

  this.cexio.place_order('buy', amount, price, _.bind(set, this));
}

Trader.prototype.sell = function(amount, price, callback) {
  // Prevent "You incorrectly entered one of fields."
  // because of more than 8 decimals.
  amount *= 100000000;
  amount = Math.floor(amount);
  amount /= 100000000;

  // test placing orders which will not be filled
  //price *= 10; price = price.toFixed(8);

  log.debug('SELL', amount, 'GHS @', price, 'BTC');

  var set = function(err, data) {
    if(err)
      return log.error('unable to sell:', err);
    if(data.error)
      return log.error('unable to sell:', data.error);

    log.debug('SELL order placed.  Order ID', data.id);
    callback(null, data.id);
  };

  this.cexio.place_order('sell', amount, price, _.bind(set, this));
}

Trader.prototype.retry = function(method, args, err) {
  var wait = +moment.duration(10, 'seconds');
  log.debug(this.name, 'returned an error, retrying..', err, 'waiting for', wait, 'ms');

  if (!_.isFunction(method)) {
    log.error(this.name, 'failed to retry, no method supplied.');
    return;
  }

  var self = this;

  // make sure the callback (and any other fn)
  // is bound to Trader
  _.each(args, function(arg, i) {
    if(_.isFunction(arg))
      args[i] = _.bind(arg, self);
  });

  // run the failed method again with the same
  // arguments after wait
  setTimeout(
    function() { method.apply(self, args) },
    wait
  );
}

Trader.prototype.getPortfolio = function(callback) {
  var args = _.toArray(arguments);
  var calculate = function(err, data) {
    if(err)
      return this.retry(this.getPortfolio, args, err);

    currency = parseFloat(data.BTC.available)
    if(parseFloat(data.BTC.orders)){
      currency -= parseFloat(data.BTC.orders)
    }
    assets = parseFloat(data.GHS.available);
    if( parseFloat(data.GHS.orders)){
	  assets -= parseFloat(data.GHS.orders);
    }

    var portfolio = [];
    portfolio.push({name: 'BTC', amount: currency});
    portfolio.push({name: 'GHS', amount: assets});
    callback(err, portfolio);
  }
  this.cexio.balance(_.bind(calculate, this));
}

Trader.prototype.getTicker = function(callback) {
  var set = function(err, data) {
    var ticker = {
      ask: data.ask,
      bid: data.bid
    };
    callback(err, ticker);
  }
  this.cexio.ticker(_.bind(set, this));
}

Trader.prototype.getFee = function(callback) {
  // cexio does currently don't take a fee on trades
  // TODO: isn't there an API call for this?
  callback(false, 0.0);
}

Trader.prototype.checkOrder = function(order, callback) {
  var check = function(err, result) {

    if(err)
      return callback(false, true);
    if(result.error)
      return callback(false, true);

    var exists = false;
    _.each(result, function(entry) {
      if(entry.id === order) {
        exists = true;
        return;
      }
    });
    callback(err, !exists);
  };

  this.cexio.open_orders(_.bind(check, this));
}

Trader.prototype.cancelOrder = function(order) {
  var check= function(err, result) {
    if(err)
      log.error('cancel order failed:', err);
    if(typeof(result) !== 'undefined' && result.error)
      log.error('cancel order failed:', result.error);
  }
  this.cexio.cancel_order(order, check);
}

module.exports = Trader;
<|endoftext|>


<commit_before>/**
 *  Copyright (C) 2014 3D Repo Ltd
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

// generic stash function
var ModelFactory = require('../factory/modelFactory');
var stream = require('stream');
var GridFSBucket = require('mongodb').GridFSBucket;
var systemLogger = require("../../logger.js").systemLogger;

function getGridFSBucket (account, bucketName){
	'use strict';
	return ModelFactory.dbManager.getGridFSBucket(account, { bucketName:  bucketName});
}

function _getGridFSBucket (dbCol, format){
	'use strict';

	return getGridFSBucket(dbCol.account, { bucketName:  `${dbCol.model}.stash.${format}`});
}

function findStashByFilename(dbCol, format, filename, getStreamOnly){
	'use strict';

	let bucket = _getGridFSBucket(dbCol, format);

	return bucket.find({ filename }).toArray().then(files => {
		if(!files.length){
			systemLogger.logInfo(filename + " - Attempt to retrieved from stash but not found");
			return Promise.resolve(false);

		} else {
			systemLogger.logInfo(filename + " - Retrieved from stash");

			return new Promise((resolve) => {

				let downloadStream = bucket.openDownloadStreamByName(filename);

				if(getStreamOnly){

					resolve(downloadStream);

				} else {

					let bufs = [];

					downloadStream.on('data', function(d){ bufs.push(d); });
					downloadStream.on('end', function(){
						resolve(Buffer.concat(bufs));
					});

				}

			});

		}
	});
}

function saveStashByFilename(dbCol, format, filename, buffer){
	'use strict';

	let bucket = _getGridFSBucket(dbCol, format);
	let uploadStream = bucket.openUploadStream(filename);

	let bufferStream = new stream.PassThrough();
	bufferStream.end(buffer);

	bufferStream.pipe(uploadStream);

	return new Promise((resolve, reject) => {
		uploadStream.once('finish', function(fileMeta) {
			resolve(fileMeta);
		});

		uploadStream.once('error', function(err) {
			reject(err);
		});
	});
}

module.exports = {
	findStashByFilename: findStashByFilename,
	saveStashByFilename: saveStashByFilename,
	getGridFSBucket: getGridFSBucket

};
<commit_msg>ISSUE #614 fix yet another typo<commit_after>/**
 *  Copyright (C) 2014 3D Repo Ltd
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

// generic stash function
var ModelFactory = require('../factory/modelFactory');
var stream = require('stream');
var GridFSBucket = require('mongodb').GridFSBucket;
var systemLogger = require("../../logger.js").systemLogger;

function getGridFSBucket (account, bucketName){
	'use strict';
	return ModelFactory.dbManager.getGridFSBucket(account, { bucketName:  bucketName});
}

function _getGridFSBucket (dbCol, format){
	'use strict';

	return getGridFSBucket(dbCol.account, `${dbCol.model}.stash.${format}`);
}

function findStashByFilename(dbCol, format, filename, getStreamOnly){
	'use strict';

	let bucket = _getGridFSBucket(dbCol, format);
	console.log(filename);
	return bucket.find({ filename }).toArray().then(files => {
		if(!files.length){
			systemLogger.logInfo(filename + " - Attempt to retrieved from stash but not found");
			return Promise.resolve(false);

		} else {
			systemLogger.logInfo(filename + " - Retrieved from stash");

			return new Promise((resolve) => {

				let downloadStream = bucket.openDownloadStreamByName(filename);

				if(getStreamOnly){

					resolve(downloadStream);

				} else {

					let bufs = [];

					downloadStream.on('data', function(d){ bufs.push(d); });
					downloadStream.on('end', function(){
						resolve(Buffer.concat(bufs));
					});

				}

			});

		}
	});
}

function saveStashByFilename(dbCol, format, filename, buffer){
	'use strict';

	let bucket = _getGridFSBucket(dbCol, format);
	let uploadStream = bucket.openUploadStream(filename);

	let bufferStream = new stream.PassThrough();
	bufferStream.end(buffer);

	bufferStream.pipe(uploadStream);

	return new Promise((resolve, reject) => {
		uploadStream.once('finish', function(fileMeta) {
			resolve(fileMeta);
		});

		uploadStream.once('error', function(err) {
			reject(err);
		});
	});
}

module.exports = {
	findStashByFilename: findStashByFilename,
	saveStashByFilename: saveStashByFilename,
	getGridFSBucket: getGridFSBucket

};
<|endoftext|>


<commit_before>var cliArgs = require('command-line-args');
var koa = require('koa');
var router = require('koa-router')();
var datasets = require('./db/datasets');
var user = require('./db/user');
var action = require('./db/actions');
var appreciate = require('./db/appreciate');
var browse = require('./db/browse');
var view = require('./db/view');
var tag = require('./db/tag');
var comment = require('./db/comment');
var download = require('./db/download');
var path = require('path');
//var koaBody = require('koa-body')({
//    multipart: true,
//    formidable: {uploadDir: './../assets/user-images'},
//    keepExtensions: true
//});
var r = require('./dash');
var apikey = require('./apikey')();

// Look for changes on the users table. If a change it detected then invalidate
// the apikey cache so it will be reloaded.
const apikeyCache = require('./apikey-cache')();
r.db('materialscommons').table('users').changes().toStream().on('data', function() {
    apikeyCache.clear()
});

var app = koa();
app.use(apikey);
router.get('/datasets', datasets.getAll);
router.get('/datasets/count', datasets.getAllCount);
router.get('/datasets/recent', datasets.getRecent);
router.get('/datasets/views', datasets.getTopViews);
router.get('/datasets/:id/user/:user_id', datasets.getOne);
router.get('/user/:email', user.get);
router.get('/actions/:dataset_id', action.getAll);
router.post('/appreciate', appreciate.addAppreciate);
router.put('/appreciate/remove', appreciate.removeAppreciation);
router.post('/views', view.addView);
router.post('/comments', comment.addComment);
router.post('/tags', tag.addTag);
router.put('/tags', tag.removeTag);
router.get('/tags', tag.getAllTags);
router.get('/tags/count', tag.getAllCount);
router.get('/tags/bycount', tag.getTagsByCount);
router.get('/tags/:id/datasets', tag.getDatasetsByTag);
router.get('/processes/types', browse.getProcessTypes);
router.get('/samples', browse.getSamples);
router.get('/authors/count', browse.getAllAuthorsCount);
router.get('/authors/datasets', browse.getAuthors);
//router.post('/upload', koaBody, user.upload);

app.use(router.routes());
app.use(router.allowedMethods());

if (!module.parent) {
    var cli = cliArgs([
        {name: 'port', type: Number, alias: 'p', description: 'Port to listen on'}
    ]);

    var options = cli.parse();
    var port = options.port || 5006;
    console.log('MCPUB listening on port: ' + port + ' pid: ' + process.pid);
    app.listen(port);
}

<commit_msg>Remove passing in the user.<commit_after>var cliArgs = require('command-line-args');
var koa = require('koa');
var router = require('koa-router')();
var datasets = require('./db/datasets');
var user = require('./db/user');
var action = require('./db/actions');
var appreciate = require('./db/appreciate');
var browse = require('./db/browse');
var view = require('./db/view');
var tag = require('./db/tag');
var comment = require('./db/comment');
var download = require('./db/download');
var path = require('path');
//var koaBody = require('koa-body')({
//    multipart: true,
//    formidable: {uploadDir: './../assets/user-images'},
//    keepExtensions: true
//});
var r = require('./dash');
var apikey = require('./apikey')();

// Look for changes on the users table. If a change it detected then invalidate
// the apikey cache so it will be reloaded.
const apikeyCache = require('./apikey-cache')();
r.db('materialscommons').table('users').changes().toStream().on('data', function() {
    apikeyCache.clear()
});

var app = koa();
app.use(apikey);
router.get('/datasets', datasets.getAll);
router.get('/datasets/count', datasets.getAllCount);
router.get('/datasets/recent', datasets.getRecent);
router.get('/datasets/views', datasets.getTopViews);
router.get('/datasets/:id', datasets.getOne);
router.get('/user/:email', user.get);
router.get('/actions/:dataset_id', action.getAll);
router.post('/appreciate', appreciate.addAppreciate);
router.put('/appreciate/remove', appreciate.removeAppreciation);
router.post('/views', view.addView);
router.post('/comments', comment.addComment);
router.post('/tags', tag.addTag);
router.put('/tags', tag.removeTag);
router.get('/tags', tag.getAllTags);
router.get('/tags/count', tag.getAllCount);
router.get('/tags/bycount', tag.getTagsByCount);
router.get('/tags/:id/datasets', tag.getDatasetsByTag);
router.get('/processes/types', browse.getProcessTypes);
router.get('/samples', browse.getSamples);
router.get('/authors/count', browse.getAllAuthorsCount);
router.get('/authors/datasets', browse.getAuthors);
//router.post('/upload', koaBody, user.upload);

app.use(router.routes());
app.use(router.allowedMethods());

if (!module.parent) {
    var cli = cliArgs([
        {name: 'port', type: Number, alias: 'p', description: 'Port to listen on'}
    ]);

    var options = cli.parse();
    var port = options.port || 5006;
    console.log('MCPUB listening on port: ' + port + ' pid: ' + process.pid);
    app.listen(port);
}

<|endoftext|>


<commit_before>'use strict';

/**
 * The processor handling a single asset.
 */

var Q = require('q');
var assetMapping = require('../../lib/asset-mapping.js');
var cip = require('../../lib/services/natmus-cip');

var DATA_REGEXP = new RegExp('\\d+');
var CM_PR_IN = 2.54;

function cleanCategoryString(str) {
	var regexp = new RegExp('^[0-9]+[A-Z]+.[0-9]+.[0-9]+ ');
	if(str.search(regexp) === 0) {
		return str.replace(regexp, '');
	}
	regexp = new RegExp('^[A-Z]?[0-9]+[a-z]? - ');
	if(str.search(regexp) === 0) {
		return str.replace(regexp, '');
	}
	regexp = new RegExp('^[A-F] - ');
	if(str.search(regexp) === 0) {
		return str.replace(regexp, '');
	}
	regexp = new RegExp('^[0-9][0-9] ');
	if(str.search(regexp) === 0) {
		return str.replace(regexp, '');
	}
	return str;
}

function relatedFilenameComparison(assetA, assetB) {
    var filenameA = assetA.filename;
    var filenameB = assetB.filename;
    return filenameA.localeCompare(filenameB);
}

// This list of transformations are a list of functions that takes two
// arguments (cip_client, metadata) and returns a mutated metadata, which
// is passed on to the next function in the list.
var METADATA_TRANSFORMATIONS = [
	function transform_field_names(state, metadata) {
		var transformedMetadata = assetMapping.format_result( metadata );
		// The catalog will be removed when formatting.
		transformedMetadata.catalog = metadata.catalog;
		return transformedMetadata;
	},
	function transform_modification_time(state, metadata) {
		var re_result = DATA_REGEXP.exec(metadata.modification_time);
		if(re_result && re_result.length > 0) {
			metadata.modification_time = parseInt(re_result[0], 10);
		}
		return metadata;
	},
	function transform_categories_and_derive_suggest(state, metadata) {
		// Transforms the categories.
		if(metadata.categories !== undefined) {
			metadata.categories_int = [];
			metadata.suggest = {'input': []};

			for(var j=0; j < metadata.categories.length; ++j) {
				if(metadata.categories[j].path.indexOf('$Categories') !== 0) {
					continue;
				}
				var path = state.categories[metadata.catalog].get_path(metadata.categories[j].id);
				if(path) {
					for(var k=0; k < path.length; k++) {
						metadata.categories_int.push(path[k].id);

						if(path[k].name.indexOf('$Categories') === 0) {
							continue;
						}

						metadata.suggest.input.push(cleanCategoryString(path[k].name));
					}
				}
			}
		}
		return metadata;
	},
	function transform_relations(state, metadata) {
		// Transforms the binary representations of each relation.
		metadata.related_master_assets = cip.parseBinaryRelations(
			metadata.related_master_assets);
		metadata.related_sub_assets = cip.parseBinaryRelations(
			metadata.related_sub_assets);
		// Sort these by their filename.
		metadata.related_master_assets.sort( relatedFilenameComparison );
		metadata.related_sub_assets.sort( relatedFilenameComparison );
		return metadata;
	},
	function derive_in_artifact_rotation_series(state, metadata) {
		// Let's assume it's not.
		metadata.in_artifact_rotation_series = false;
		// Finds out if this asset is in a rotation series.
		// Initially looking at the assets categories - is this the front
		// facing asset in the rotation series?
		for(var c in metadata.categories) {
			var category = metadata.categories[c];
			if(category.name === 'Rotationsbilleder') {
				metadata.in_artifact_rotation_series = true;
				// The asset in Rotationsbilleder is always rank 0.
				metadata.artifact_rotation_series_rank = 0;
				return metadata;
			}
		}
		// Loop through the assets related master assets to find if a
		// master asset is in fact in the correct category to make this
		// asset a part of an artifact rotation series.
		var rotationalMasterAsset;
		for(var r in metadata.related_master_assets) {
			var masterAsset = metadata.related_master_assets[r];
			if(masterAsset.relation === '9ed0887f-40e8-4091-a91c-de356c869251') {
				rotationalMasterAsset = masterAsset;
			}
		}

		// TODO: Implement this as a post-processing step reading asset metadata
		// of related assets from the index instead of from the CIP.
		// If we found a rotational master asset.
		if(rotationalMasterAsset) {
			// Get the asset's metadata, to check it's categories.
			return cip.getAsset(state.cip, metadata.catalog, rotationalMasterAsset.id)
			.then(function(masterAsset) {
				var masterAssetMetadata = masterAsset.fields;
				masterAssetMetadata = assetMapping.format_result( masterAssetMetadata );
				for(var c in masterAssetMetadata.categories) {
					var category = masterAssetMetadata.categories[c];
					if(category.name === 'Rotationsbilleder') {
						metadata.in_artifact_rotation_series = true;
						// TODO: Consider computing the artifact_rotation_series_rank
						return metadata;
					}
				}
				return metadata;
			}, function(reason) {
				// An error occured when getting the master asset, let's not fail
				// on this sub-asset just because of that.
				console.error('Could not get the master asset', reason);
				// Let's return a new promise to overwrite the failed.
				return new Q(metadata);
			});
		} else {
			return metadata;
		}
	},
	function derive_dimensions_in_cm(state, metadata) {
		metadata.width_cm = metadata.width_in * CM_PR_IN;
		metadata.height_cm = metadata.height_in * CM_PR_IN;
		return metadata;
	},
	function derive_is_searchable(state, metadata) {
		// Compute a value on if it's drafted, part of a rotational series
		// or an original that has more representable croppings.
		// Adds an is_searchable field to the metadata.
		metadata.is_searchable = true; // Let's assume that it is.
		if(metadata.cropping_status &&
			metadata.cropping_status.id === 2) {
			// The croping status is 'has been cropped' / 'Er friskåret'
			metadata.is_searchable = false;
		} else if(!metadata.review_state ||
			(metadata.review_state.id !== 3 && metadata.review_state.id !== 4 ) ) {
			// The asset's review state is neither 3 or 4 (public).
			metadata.is_searchable = false;
		} else if(metadata.in_artifact_rotation_series &&
			metadata.artifact_rotation_series_rank !== 0) {
			// The asset is part of a rotation series but it's not the front.
			metadata.is_searchable = false;
		}
		// Return the updated metedata.
		return metadata;
	},
	function derive_latitude_and_longitude(state, metadata) {
		var coordinates;
		if(metadata.google_maps_coordinates) {
			coordinates = metadata.google_maps_coordinates;
		} else if(metadata.google_maps_coordinates_crowd) {
			coordinates = metadata.google_maps_coordinates_crowd;
		}
		if(coordinates) {
			coordinates = coordinates.split(',').map(parseFloat);
			if(coordinates.length !== 2) {
				throw new Error('Encountered an unexpected format when parsing coordinates.');
			} else {
				metadata.latitude = coordinates[0];
				metadata.longitude = coordinates[1];
			}
		}
		return metadata;
	},
	/*function cracy_fails(state, metadata) {
		throw new Error('Catch me if you can ... ' + metadata.id);
	}*/
];

function transformMetadata(state, metadata, transformations) {
	return transformations.reduce(function(metadata, transformation) {
		return Q.when(metadata).then(function(metadata) {
			return transformation(state, metadata);
		});
	}, new Q(metadata));
}

function processAsset(state, metadata, transformations) {
	//console.log('Processing an asset.');
	// Use all transformations by default.
	if(typeof(transformations) === 'undefined') {
		transformations = METADATA_TRANSFORMATIONS;
	}
	// Perform additional transformations and index the result.
	return transformMetadata(state, metadata, transformations)
	.then(function(metadata) {
		var es_id = metadata.catalog + '-' + metadata.id;
		return state.es.index({
			index: process.env.ES_INDEX || 'assets',
			type: 'asset',
			id: es_id,
			body: metadata
		});
	})
	.then(function(resp) {
		console.log('Successfully indexed ' + resp._id);
		return resp._id;
	}, function(err) {
		err.catalogAlias = metadata.catalog;
		err.assetId = metadata.id;
		console.error( err.stack );
		return err;
	});
}

module.exports = processAsset;
module.exports.METADATA_TRANSFORMATIONS = METADATA_TRANSFORMATIONS;
<commit_msg>Adding a heading when the coordinates has three values.<commit_after>'use strict';

/**
 * The processor handling a single asset.
 */

var Q = require('q');
var assetMapping = require('../../lib/asset-mapping.js');
var cip = require('../../lib/services/natmus-cip');

var DATA_REGEXP = new RegExp('\\d+');
var CM_PR_IN = 2.54;

function cleanCategoryString(str) {
	var regexp = new RegExp('^[0-9]+[A-Z]+.[0-9]+.[0-9]+ ');
	if(str.search(regexp) === 0) {
		return str.replace(regexp, '');
	}
	regexp = new RegExp('^[A-Z]?[0-9]+[a-z]? - ');
	if(str.search(regexp) === 0) {
		return str.replace(regexp, '');
	}
	regexp = new RegExp('^[A-F] - ');
	if(str.search(regexp) === 0) {
		return str.replace(regexp, '');
	}
	regexp = new RegExp('^[0-9][0-9] ');
	if(str.search(regexp) === 0) {
		return str.replace(regexp, '');
	}
	return str;
}

function relatedFilenameComparison(assetA, assetB) {
    var filenameA = assetA.filename;
    var filenameB = assetB.filename;
    return filenameA.localeCompare(filenameB);
}

// This list of transformations are a list of functions that takes two
// arguments (cip_client, metadata) and returns a mutated metadata, which
// is passed on to the next function in the list.
var METADATA_TRANSFORMATIONS = [
	function transform_field_names(state, metadata) {
		var transformedMetadata = assetMapping.format_result( metadata );
		// The catalog will be removed when formatting.
		transformedMetadata.catalog = metadata.catalog;
		return transformedMetadata;
	},
	function transform_modification_time(state, metadata) {
		var re_result = DATA_REGEXP.exec(metadata.modification_time);
		if(re_result && re_result.length > 0) {
			metadata.modification_time = parseInt(re_result[0], 10);
		}
		return metadata;
	},
	function transform_categories_and_derive_suggest(state, metadata) {
		// Transforms the categories.
		if(metadata.categories !== undefined) {
			metadata.categories_int = [];
			metadata.suggest = {'input': []};

			for(var j=0; j < metadata.categories.length; ++j) {
				if(metadata.categories[j].path.indexOf('$Categories') !== 0) {
					continue;
				}
				var path = state.categories[metadata.catalog].get_path(metadata.categories[j].id);
				if(path) {
					for(var k=0; k < path.length; k++) {
						metadata.categories_int.push(path[k].id);

						if(path[k].name.indexOf('$Categories') === 0) {
							continue;
						}

						metadata.suggest.input.push(cleanCategoryString(path[k].name));
					}
				}
			}
		}
		return metadata;
	},
	function transform_relations(state, metadata) {
		// Transforms the binary representations of each relation.
		metadata.related_master_assets = cip.parseBinaryRelations(
			metadata.related_master_assets);
		metadata.related_sub_assets = cip.parseBinaryRelations(
			metadata.related_sub_assets);
		// Sort these by their filename.
		metadata.related_master_assets.sort( relatedFilenameComparison );
		metadata.related_sub_assets.sort( relatedFilenameComparison );
		return metadata;
	},
	function derive_in_artifact_rotation_series(state, metadata) {
		// Let's assume it's not.
		metadata.in_artifact_rotation_series = false;
		// Finds out if this asset is in a rotation series.
		// Initially looking at the assets categories - is this the front
		// facing asset in the rotation series?
		for(var c in metadata.categories) {
			var category = metadata.categories[c];
			if(category.name === 'Rotationsbilleder') {
				metadata.in_artifact_rotation_series = true;
				// The asset in Rotationsbilleder is always rank 0.
				metadata.artifact_rotation_series_rank = 0;
				return metadata;
			}
		}
		// Loop through the assets related master assets to find if a
		// master asset is in fact in the correct category to make this
		// asset a part of an artifact rotation series.
		var rotationalMasterAsset;
		for(var r in metadata.related_master_assets) {
			var masterAsset = metadata.related_master_assets[r];
			if(masterAsset.relation === '9ed0887f-40e8-4091-a91c-de356c869251') {
				rotationalMasterAsset = masterAsset;
			}
		}

		// TODO: Implement this as a post-processing step reading asset metadata
		// of related assets from the index instead of from the CIP.
		// If we found a rotational master asset.
		if(rotationalMasterAsset) {
			// Get the asset's metadata, to check it's categories.
			return cip.getAsset(state.cip, metadata.catalog, rotationalMasterAsset.id)
			.then(function(masterAsset) {
				var masterAssetMetadata = masterAsset.fields;
				masterAssetMetadata = assetMapping.format_result( masterAssetMetadata );
				for(var c in masterAssetMetadata.categories) {
					var category = masterAssetMetadata.categories[c];
					if(category.name === 'Rotationsbilleder') {
						metadata.in_artifact_rotation_series = true;
						// TODO: Consider computing the artifact_rotation_series_rank
						return metadata;
					}
				}
				return metadata;
			}, function(reason) {
				// An error occured when getting the master asset, let's not fail
				// on this sub-asset just because of that.
				console.error('Could not get the master asset', reason);
				// Let's return a new promise to overwrite the failed.
				return new Q(metadata);
			});
		} else {
			return metadata;
		}
	},
	function derive_dimensions_in_cm(state, metadata) {
		metadata.width_cm = metadata.width_in * CM_PR_IN;
		metadata.height_cm = metadata.height_in * CM_PR_IN;
		return metadata;
	},
	function derive_is_searchable(state, metadata) {
		// Compute a value on if it's drafted, part of a rotational series
		// or an original that has more representable croppings.
		// Adds an is_searchable field to the metadata.
		metadata.is_searchable = true; // Let's assume that it is.
		if(metadata.cropping_status &&
			metadata.cropping_status.id === 2) {
			// The croping status is 'has been cropped' / 'Er friskåret'
			metadata.is_searchable = false;
		} else if(!metadata.review_state ||
			(metadata.review_state.id !== 3 && metadata.review_state.id !== 4 ) ) {
			// The asset's review state is neither 3 or 4 (public).
			metadata.is_searchable = false;
		} else if(metadata.in_artifact_rotation_series &&
			metadata.artifact_rotation_series_rank !== 0) {
			// The asset is part of a rotation series but it's not the front.
			metadata.is_searchable = false;
		}
		// Return the updated metedata.
		return metadata;
	},
	function derive_latitude_and_longitude(state, metadata) {
		var coordinates;
		if(metadata.google_maps_coordinates) {
			coordinates = metadata.google_maps_coordinates;
		} else if(metadata.google_maps_coordinates_crowd) {
			coordinates = metadata.google_maps_coordinates_crowd;
		}
		if(coordinates) {
			coordinates = coordinates.split(',').map(parseFloat);
			if(coordinates.length == 2) {
				metadata.latitude = coordinates[0];
				metadata.longitude = coordinates[1];
			} else if(coordinates.length == 3) {
				metadata.latitude = coordinates[0];
				metadata.longitude = coordinates[1];
				metadata.heading = coordinates[2];
			} else {
				throw new Error('Encountered unexpected format when parsing coordinates.');
			}
		}
		return metadata;
	},
	/*function cracy_fails(state, metadata) {
		throw new Error('Catch me if you can ... ' + metadata.id);
	}*/
];

function transformMetadata(state, metadata, transformations) {
	return transformations.reduce(function(metadata, transformation) {
		return Q.when(metadata).then(function(metadata) {
			return transformation(state, metadata);
		});
	}, new Q(metadata));
}

function processAsset(state, metadata, transformations) {
	//console.log('Processing an asset.');
	// Use all transformations by default.
	if(typeof(transformations) === 'undefined') {
		transformations = METADATA_TRANSFORMATIONS;
	}
	// Perform additional transformations and index the result.
	return transformMetadata(state, metadata, transformations)
	.then(function(metadata) {
		var es_id = metadata.catalog + '-' + metadata.id;
		return state.es.index({
			index: process.env.ES_INDEX || 'assets',
			type: 'asset',
			id: es_id,
			body: metadata
		});
	})
	.then(function(resp) {
		console.log('Successfully indexed ' + resp._id);
		return resp._id;
	}, function(err) {
		err.catalogAlias = metadata.catalog;
		err.assetId = metadata.id;
		console.error( err.stack );
		return err;
	});
}

module.exports = processAsset;
module.exports.METADATA_TRANSFORMATIONS = METADATA_TRANSFORMATIONS;
<|endoftext|>


<commit_before>// NodeRESTHost.js
// A simple REST host in Node.js with using Express.js framework.
//
// All data stored in memory, requests are handled in particular routes.
//
// Created in 2014 by Radek Tomasek / SeaCat Ltd.

// Include Express.js framework scripts.
var express = require('express');
var bodyParser = require('body-parser');

// Initialize app by using Express framework.
var app = express();

// Use Body Parser.
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());

// Set default port 1337 or custom if defined by user externally.
app.set('port', process.env.PORT || 1337);

// Initialization of books array.
var movies = [
  {
    id: 1,
    name: "Forrest Gump",
    director: "Robert Zemeckis",
    release: 1994
  },
  {
    id: 2,
    name: "Donnie Darko",
    director: "Richard Kelly",
    release: 2001
  },
  {
    id: 3,
    name: "Inception",
    director: "Christopher Nolan",
    release: 2010
  }
];

// A simulation of creating new IDs. Basically get the last element and increase the value of an ID.
function getNewId(){
  return movies[movies.length -1].id + 1;
}

function findIndexOfElement(inputArray, key, value){
  for (var i = 0; i < inputArray.length; i++){
    if (inputArray[i][key] === value){
      return i;
    }
  }
  return -1;
}

// GET - list of all records.
app.get('/api/books', function(request, response){
  response.json(movies.map(function(movie){
    return {
      id: movie.id,
      name: movie.name,
      director: movie.director,
      release: movie.release
    }
  }));
});

// GET - list of a record with particular id. If not found, forward the request to 404 - not found.
app.get('/api/book/:id', function(request, response, next){
  // Get an integer interpretation of URL parameter.
  var urlIntParam = parseInt(request.params.id);
  // Check whether the element exists or not (or it is not a number). If not (following case, redirect the request to 404).
  if (urlIntParam < 0 || isNaN(urlIntParam)){
    // Use following middleware - matched 404.
    next();
  }
  else {
    // Find array index in our movie array based on the input parameter (converted to integer).
    var elementIndex = findIndexOfElement(movies, 'id', urlIntParam);
    // Get an object from movie array.
    var selectedMovie = movies[elementIndex];
    // Return JSON response with selected attributes.
    response.json({
      id: selectedMovie.id,
      name: selectedMovie.name,
      director: selectedMovie.director,
      release: selectedMovie.release
    });
  }
});

// POST - create a new element.
app.post('/api/books', function(request, response){
  var requestBody = request.body.name;
  console.log(requestBody);
  response.status(200).end();
});

app.put('/api/book/:id', function(request, response, next){
  // Get an integer interpretation of URL parameter.
  var urlIntParam = parseInt(request.params.id);
  // Check whether the element exists or not (or it is not a number). If not (following case, redirect the request to 404).
  if (urlIntParam < 0 || isNaN(urlIntParam)){
    // Use following middleware - matched 404.
    next();
  }
  else {
    // Find array index in our movie array based on the input parameter (converted to integer).
    var elementIndex = findIndexOfElement(movies, 'id', urlIntParam);
    // Update element accordingly.
    movies[elementIndex] = {
      id: elementIndex,
      name: request.body.name,
      director: request.body.director,
      release: request.body.release
    };
    // Element successfuly updated.
    response.status(200).end();
  }
});

// DELETE - remove particular record from array.
app.delete('/api/book/:id', function(request, response, next){
  // Get an integer interpretation of URL parameter.
  var urlIntParam = parseInt(request.params.id);
  // Check whether the element exists or not (or it is not a number). If not (following case, redirect the request to 404).
  if (urlIntParam < 0 || isNaN(urlIntParam)){
    // Use following middleware - matched 404.
    next();
  }
  else {
    // Find array index in our movie array based on the input parameter (converted to integer).
    var elementIndex = findIndexOfElement(movies, 'id', urlIntParam);
    // Delete element according to index parameter.
    movies.splice(elementIndex, 1);
    // Element successfuly deleted.
    response.status(200);
  }
});

// Use Express midleware to handle 404 and 500 error states.
app.use(function(request, response){
   // Set status 404 if none of above routes processed incoming request.
   response.status(404);
   // Generate the output.
   response.send('404 - not found');
});

// 500 error handling. This will be handled in case of any internal issue on the host side.
app.use(function(err, request, response){
  // Set response type to application/json.
  response.type('application/json');
  // Set response status to 500 (error code for internal server error).
  response.status(500);
  // Generate the output - an Internal server error message.
  response.send('500 - internal server error');
});

// Start listening on defined port, this keep running the application until hit Ctrl + C key combination.
app.listen(app.get('port'), function(){
  console.log("Host is running and listening on http://localhost:" + app.get('port') + '; press Ctrl-C to terminate.');
});<commit_msg>fix of POST and PUT methods<commit_after>// NodeRESTHost.js
// A simple REST host in Node.js with using Express.js framework.
//
// All data stored in memory, requests are handled in particular routes.
//
// Created in 2014 by Radek Tomasek / SeaCat Ltd.

// Include Express.js framework scripts.
var express = require('express');
var bodyParser = require('body-parser');

// Initialize app by using Express framework.
var app = express();

// Use Body Parser.
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());

// Set default port 1337 or custom if defined by user externally.
app.set('port', process.env.PORT || 1337);

// Initialization of books array.
var movies = [
  {
    id: 1,
    name: "Forrest Gump",
    director: "Robert Zemeckis",
    release: 1994
  },
  {
    id: 2,
    name: "Donnie Darko",
    director: "Richard Kelly",
    release: 2001
  },
  {
    id: 3,
    name: "Inception",
    director: "Christopher Nolan",
    release: 2010
  }
];

// A simulation of creating new IDs. Basically get the last element and increase the value of an ID.
function getNewId(){
  return movies[movies.length -1].id + 1;
}

function findIndexOfElement(inputArray, key, value){
  for (var i = 0; i < inputArray.length; i++){
    if (inputArray[i][key] === value){
      return i;
    }
  }
  return -1;
}

// GET - list of all records.
app.get('/api/books', function(request, response){
  response.json(movies.map(function(movie){
    return {
      id: movie.id,
      name: movie.name,
      director: movie.director,
      release: movie.release
    }
  }));
});

// GET - list of a record with particular id. If not found, forward the request to 404 - not found.
app.get('/api/book/:id', function(request, response, next){
  // Get an integer interpretation of URL parameter.
  var urlIntParam = parseInt(request.params.id);
  // Check whether the element exists or not (or it is not a number). If not (following case, redirect the request to 404).
  if (urlIntParam < 0 || isNaN(urlIntParam)){
    // Use following middleware - matched 404.
    next();
  }
  else {
    // Find array index in our movie array based on the input parameter (converted to integer).
    var elementIndex = findIndexOfElement(movies, 'id', urlIntParam);
    // Get an object from movie array.
    var selectedMovie = movies[elementIndex];
    // Return JSON response with selected attributes.
    response.json({
      id: selectedMovie.id,
      name: selectedMovie.name,
      director: selectedMovie.director,
      release: selectedMovie.release
    });
  }
});

// POST - create a new element.
app.post('/api/books', function(request, response){
  // complete request body
  var requestBody = request.body;

  movies.push({
    id: getNewId(),
    name: requestBody.name,
    director: requestBody.director,
    release: requestBody.release
  });

  response.status(200).end();
});

app.put('/api/book/:id', function(request, response, next){
  // Get an integer interpretation of URL parameter.
  var urlIntParam = parseInt(request.params.id);
  // Check whether the element exists or not (or it is not a number). If not (following case, redirect the request to 404).
  if (urlIntParam < 0 || isNaN(urlIntParam)){
    // Use following middleware - matched 404.
    next();
  }
  else {
    // Find array index in our movie array based on the input parameter (converted to integer).
    var elementIndex = findIndexOfElement(movies, 'id', urlIntParam);
    // Update element accordingly.
    movies[elementIndex] = {
      id: urlIntParam,
      name: request.body.name,
      director: request.body.director,
      release: request.body.release
    };
    // Element successfuly updated.
    response.status(200).end();
  }
});

// DELETE - remove particular record from array.
app.delete('/api/book/:id', function(request, response, next){
  // Get an integer interpretation of URL parameter.
  var urlIntParam = parseInt(request.params.id);
  // Check whether the element exists or not (or it is not a number). If not (following case, redirect the request to 404).
  if (urlIntParam < 0 || isNaN(urlIntParam)){
    // Use following middleware - matched 404.
    next();
  }
  else {
    // Find array index in our movie array based on the input parameter (converted to integer).
    var elementIndex = findIndexOfElement(movies, 'id', urlIntParam);
    // Delete element according to index parameter.
    movies.splice(elementIndex, 1);
    // Element successfuly deleted.
    response.status(200);
  }
});

// Use Express midleware to handle 404 and 500 error states.
app.use(function(request, response){
   // Set status 404 if none of above routes processed incoming request.
   response.status(404);
   // Generate the output.
   response.send('404 - not found');
});

// 500 error handling. This will be handled in case of any internal issue on the host side.
app.use(function(err, request, response){
  // Set response type to application/json.
  response.type('application/json');
  // Set response status to 500 (error code for internal server error).
  response.status(500);
  // Generate the output - an Internal server error message.
  response.send('500 - internal server error');
});

// Start listening on defined port, this keep running the application until hit Ctrl + C key combination.
app.listen(app.get('port'), function(){
  console.log("Host is running and listening on http://localhost:" + app.get('port') + '; press Ctrl-C to terminate.');
});<|endoftext|>