<commit_before>module.exports = submissions;
submissions.usage = "fhc submissions [list]\n" +
              "fhc submissions list app=<app-id> form=<form-id>\n" +
              "fhc submissions get <submission-id>\n" +
              "fhc submissions delete <submission-id>\n" +
              "fhc submissions getfile <filegroup-id> <outputfilename>\n" +
              "fhc submissions submitdata <submission-file.json>\n" +
              "fhc submissions submitfile <submission-id> <field-id> <file-id> <file>\n" +
              "fhc submissions complete <submission-id>\n" +
              "fhc submissions status <submission-id>\n" +
              "fhc submissions export file=<zip-file> app=<app-id> || form=<form-id>\n" +
              "fhc submissions template <app-id> <form-id>";
submissions.doList = doList;
submissions.doGetSubmission = doGetSubmission;

var fs = require('fs');
var util = require('util');
var fhc = require("./fhc");
var fhreq = require("./utils/request");
var url = require('url');
var http = require('http');
var https = require('https');
var forms = require('./forms.js');
var request = require('request');

// Get FeedHenry platform version
function submissions (args, cb) {
  var url = fhreq.getFeedHenryUrl();
  if (args.length === 0) return doList(null, cb);
  var action = args[0];

  if (action === 'list') {
    args.shift(); // get rid of 'list'
    return doList(args, cb);
  }
  if (action === 'get') {
    if (!args[1]) return cb(submissions.usage);
    return doGetSubmission(args[1], cb);
  }
  if (action === 'delete') {
    if (!args[1]) return cb(submissions.usage);
    return doDeleteSubmission(args[1], cb);
  }
  if (action === 'getfile') {
    if (!args[1] || !args[2]) return cb(submissions.usage);
    return doGetSubmissionFile(args[1], args[2], cb);
  }
  if (action === 'submitdata') {
    if (!args[1]) return cb(submissions.usage);
    return doSubmit(args[1], cb);
  }
  if (action === 'submitfile') {
    if (!args[1] || !args[2] || !args[3] || !args[4]) return cb(submissions.usage);
    return doSubmitFile(args[1], args[2], args[3], args[4], cb);
  }
  if (action === 'complete') {
    if (!args[1]) return cb(submissions.usage);
    return doComplete(args[1], cb);
  }
  if (action === 'status') {
    if (!args[1]) return cb(submissions.usage);
    return doStatus(args[1], cb);
  }
  if (action === 'export') {
    args.shift(); // get rid of 'export'
    return doExport(args, cb);
  }
  if (action == 'template') {
    var appId = args[1];
    var formId = args[2];
    if (!appId || !formId) return cb(submissions.usage);
    return doTemplate(appId, formId, cb);
  }

  return cb(submissions.usage);
};

// parses the args for 'app=xxx' and 'form=yyy'
function getAppFormIds(args, cb) {
  var appId, formId, file;
  if (!args) return cb(null, appId, formId, file);
  for (var i=0; i<args.length; i++) {
    var arg = args[i];
    if (arg.indexOf('app=') === 0){
      appId = arg.replace('app=', '');
    }else if (arg.indexOf('form=') === 0){
      formId = arg.replace('form=', '');
    }else if (arg.indexOf('file=') === 0){
      file = arg.replace('file=', '');
    }else {
      return cb('Unknown argument: ' + arg + '\n' + submissions.usage);
    }
  };
  process.nextTick(function() {
    return cb(null, appId, formId, file);
  });
};

function doList(args, cb) {
  var payload = {};
  getAppFormIds(args, function(err, appId, formId) {
    if (err) return cb(err);

    if (appId) payload.appId = appId;
    if (formId) payload.formId = formId;
    payload.wantRestrictions = false;

    fhreq.POST(fhreq.getFeedHenryUrl(), "api/v2/forms/submission", payload, function (err, remoteData, raw, res) {
      if (err) return cb(err);
      if (res.statusCode !== 200) return cb('Unexpected response code: ' + res.statusCode + ' - ' + raw);

      remoteData.status = "ok";
      remoteData.statusCode = 200;
      return cb(err, remoteData);
    });
  });
};

function doGetSubmission(submissionId, cb) {
  fhreq.GET(fhreq.getFeedHenryUrl(), "api/v2/forms/submission/" + submissionId, function (err, remoteData, raw, res) {
    if (err) return cb(err);
    if (res.statusCode !== 200) return cb('Unexpected response code: ' + res.statusCode + ' - ' + raw);

    remoteData.status = "ok";
    remoteData.statusCode = 200;
    return cb(err, remoteData);
  });
};

function doDeleteSubmission(submissionId, cb) {
  fhreq.DELETE(fhreq.getFeedHenryUrl(), "api/v2/forms/submission/" + submissionId, function (err, remoteData, raw, res) {
    if (err) return cb(err);
    if (res.statusCode !== 200) return cb('Unexpected response code: ' + res.statusCode + ' - ' + raw);

    remoteData.status = "ok";
    remoteData.statusCode = 200;
    return cb(err, remoteData);
  });
};

function doGetSubmissionFile(fileGroupId, outputFileName, cb) {
  //TODO the main part of this function should be moved into utils/request.js
  var fhUrl = url.resolve(fhreq.getFeedHenryUrl(),  "api/v2/forms/submission/file/" + fileGroupId);

  var uri = url.parse(fhUrl);
  var proto = uri.protocol === 'https:' ? https : http;

  var headers = {};
  var cookie = fhc.config.get("cookie");
  if (cookie != undefined) {
    headers.cookie = "feedhenry=" + cookie + ";";
  }

  uri.headers = headers;

  var req = proto.get(uri, function(res){
    if(res.statusCode !== 200) return cb("Unexpected response code for file download: " + res.statusCode + " message: " + res.body);

    var stream = fs.createWriteStream(outputFileName);
    res.on('data',function (chunk) {
      stream.write(chunk);
    });

    res.on('end',function (){
      stream.end(function () {
        return cb(undefined, {status: "ok", statusCode: res.statusCode, url: fhUrl, file: outputFileName});
      });
    });
  });

  req.on('error',function(err){
     return cb("Error downloading file: " + err.message);
  });
};

function doSubmit(file, cb) {
  if (!fs.existsSync(file)) return cb("File does not exist: " + file);
  fs.readFile(file, function(err, data) {
    if (err) return cb(err);
    var sub = JSON.parse(data);
    if (!sub.formId) return cb("'formId' missing from submission");
    var url = "api/v2/forms/submission/" + sub.formId + '/submitData';
    fhreq.POST(fhreq.getFeedHenryUrl(), url, sub, function (err, remoteData, raw, res) {
      if (err) return cb(err);
      if (res.statusCode !== 200) return cb('Unexpected response code: ' + res.statusCode + ' - ' + raw);

      remoteData.status = "ok";
      remoteData.statusCode = 200;
      return cb(err, remoteData);
    });
  });
};

function doSubmitFile(submissionId, fieldId, fileId, file, cb) {
  if (!fs.existsSync(file)) return cb("File does not exist: " + file);
  var url = fhreq.getFeedHenryUrl() + "api/v2/forms/submission/" + submissionId + '/' + fieldId + '/' + fileId + '/submitFile';
  var headers = {};
  var cookie = fhc.config.get("cookie");
  if (cookie) {
    headers.cookie = "feedhenry=" + cookie + ";";
  }

  var r = request.post({url: url, headers: headers}, function(err, res, body) {
    if (err) return cb(err);
    if (res.statusCode !== 200) return cb('Unexpected response code: ' + res.statusCode + ' - ' + body);

    body.status = "ok";
    body.statusCode = 200;
    return cb(err, body);
  });

  r.form().append('fileStream', fs.createReadStream(file));
};

function doComplete(submissionId, cb) {
  var url = "api/v2/forms/submission/" + submissionId + '/complete';
  fhreq.POST(fhreq.getFeedHenryUrl(), url, {}, function (err, remoteData, raw, res) {
    if (err) return cb(err);
    if (res.statusCode !== 200) return cb('Unexpected response code: ' + res.statusCode + ' - ' + raw);

    remoteData.status = "ok";
    remoteData.statusCode = 200;
    return cb(err, remoteData);
  });
};

function doStatus(submissionId, cb) {
  var url = "api/v2/forms/submission/" + submissionId + '/status';
  fhreq.GET(fhreq.getFeedHenryUrl(), url, function (err, remoteData, raw, res) {
    if (err) return cb(err);
    if (res.statusCode !== 200) return cb('Unexpected response code: ' + res.statusCode + ' - ' + raw);

    remoteData.status = "ok";
    remoteData.statusCode = 200;
    return cb(err, remoteData);
  });
};

function doExport(args, cb) {
  var payload = {};
  getAppFormIds(args, function(err, appId, formId, file) {
    if (err) return cb(err);
    if (!file) return cb("No file specified, use 'file=<zip-file>, e.g. 'file=/tmp/foo.zip'\n" + submissions.usage);

    if (appId) payload.appId = appId;
    if (formId) payload.formId = formId;

    var url = fhreq.getFeedHenryUrl() + "api/v2/forms/submission/export";
    var headers = {};
    var cookie = fhc.config.get("cookie");
    if (cookie) {
      headers.cookie = "feedhenry=" + cookie + ";";
    }

    var cbCalled = false;
    var f = fs.createWriteStream(file);
    f.on('close', function() {
      if (!cbCalled) {
        cbCalled = true;
        return cb(null, file);
      }
    });

    f.on('error', function(err) {
      if (!cbCalled) {
        cbCalled = true;
        return cb(err);
      };
    });
    var r = request.post({url: url, json:payload, headers: headers}, function(err, res, body) {
      if (err) {
        if (!cbCalled) {
          cbCalled = true;
          return cb(err);
        }
      };
      if(res.statusCode !== 200) {
        if (!cbCalled) {
          cbCalled = true;
          return cb(body);
        }
      }
    });
    r.on('error', function(err) {
      if (!cbCalled) {
        cbCalled = true;
        return cb(err);
      };
    });
    r.pipe(f);
  });
};

function doTemplate(appId, formId, cb) {
  forms(['get', formId], function(err, form) {
    if (err) return cb(err);

    var sub = {
      "appId": appId,
      "formId": formId,
      "appCloudName": "<app-cloud-name>",
      "appEnvironment": "dev",
      "userId": "<used-id>",
      "deviceId": "<device-id>",
      "deviceIPAddress": "192.168.1.1",
      "timezoneOffset": 120,
      "deviceFormTimestamp": new Date(Date.now()).toUTCString(),
      "comments": [{
        "madeBy": "somePerson@example.com",
        "madeOn": new Date(Date.now()).toUTCString(),
        "value": "This is a comment"
      }]
    };

    // now create dummy form field submission values based on the forms form fields
    var fields = [];
    form.pages.forEach(function(page) {
      page.fields.forEach(function(field) {
        if (field.type !== 'matrix' && field.type !== 'sectionBreak') {
          fields.push(field);
        }
      });
    });

    var formFields = [];
    fields.forEach(function(field) {
      var ff = {
        fieldId: field._id,
        fieldValues: []
      };

      if (field.repeating === true) {
        for (var i=0; i<field.fieldOptions.definition.maxRepeat; i++) {
          ff.fieldValues.push(sampleValue(field, (i+1)));
        }
      }else {
        ff.fieldValues.push(sampleValue(field));
      }

      // write out field metadata to the submission to help fill in submission (sent to the server but ignored)
      ff.meta = field;
      formFields.push(ff);
    });

    sub.formFields = formFields;

    return cb(null, sub);
  });
};

function sampleValue(field, num) {
  if (field.type === 'number') return num ? 42 + num: 42;
  if (field.type === 'emailAddress') return num ? 'foo' + num + '@example.com' : 'foo@example.com';
  if (field.type === 'dateTime') {
    if (field.fieldOptions.definition.dateTimeUnit === 'time') return '11:11:11';
    else return new Date(Date.now()).toUTCString();
  }
  if (field.type === 'radio') return field.fieldOptions.definition.options[0].label;
  if (field.type === 'dropdown') return field.fieldOptions.definition.options[0].label;
  if (field.type === 'location') {
    if (field.fieldOptions.definition.locationUnit === 'northEast') {
      return {"zone" : "11U", "eastings" : "594934", "northings" : "5636174"};
    }
    return {"lat" : "5.555848", "long" : "-52.031250"};
  }
  if (field.type === 'locationMap') {
    return {"lat" : "5.555848", "long" : "-52.031250"};
  }
  if (field.type === 'file' || field.type === 'photo' || field.type === 'signature'){
    var f = {
      "fileName" : field.name + (num ? num: ''),
      "fileSize" : field.fieldOptions.definition.file_size || 42,
      "fileType" : field.type === 'photo' ? "application/jpeg" : "application/pdf",
      "fileUpdateTime" : new Date().getTime(),
      "hashName" : "filePlaceHolder123456"
    };
    return f;
  }
  if (field.type === 'checkboxes') {
    var min = field.fieldOptions.validation.min;
    var sel = {
      selections: []
    };
    for (var i=0; i<min; i++) {
      var box = field.fieldOptions.definition.checkboxChoices[i];
      sel.selections.push(Object.keys(box)[0]);
    }
    return sel;
  }
  return "<" + field.name + (num ? '-' + num : '') + ">";
};<commit_msg>Checkboxes changed from 'checkboxChoices' to 'options'<commit_after>module.exports = submissions;
submissions.usage = "fhc submissions [list]\n" +
              "fhc submissions list app=<app-id> form=<form-id>\n" +
              "fhc submissions get <submission-id>\n" +
              "fhc submissions delete <submission-id>\n" +
              "fhc submissions getfile <filegroup-id> <outputfilename>\n" +
              "fhc submissions submitdata <submission-file.json>\n" +
              "fhc submissions submitfile <submission-id> <field-id> <file-id> <file>\n" +
              "fhc submissions complete <submission-id>\n" +
              "fhc submissions status <submission-id>\n" +
              "fhc submissions export file=<zip-file> app=<app-id> || form=<form-id>\n" +
              "fhc submissions template <app-id> <form-id>";
submissions.doList = doList;
submissions.doGetSubmission = doGetSubmission;

var fs = require('fs');
var util = require('util');
var fhc = require("./fhc");
var fhreq = require("./utils/request");
var url = require('url');
var http = require('http');
var https = require('https');
var forms = require('./forms.js');
var request = require('request');

// Get FeedHenry platform version
function submissions (args, cb) {
  var url = fhreq.getFeedHenryUrl();
  if (args.length === 0) return doList(null, cb);
  var action = args[0];

  if (action === 'list') {
    args.shift(); // get rid of 'list'
    return doList(args, cb);
  }
  if (action === 'get') {
    if (!args[1]) return cb(submissions.usage);
    return doGetSubmission(args[1], cb);
  }
  if (action === 'delete') {
    if (!args[1]) return cb(submissions.usage);
    return doDeleteSubmission(args[1], cb);
  }
  if (action === 'getfile') {
    if (!args[1] || !args[2]) return cb(submissions.usage);
    return doGetSubmissionFile(args[1], args[2], cb);
  }
  if (action === 'submitdata') {
    if (!args[1]) return cb(submissions.usage);
    return doSubmit(args[1], cb);
  }
  if (action === 'submitfile') {
    if (!args[1] || !args[2] || !args[3] || !args[4]) return cb(submissions.usage);
    return doSubmitFile(args[1], args[2], args[3], args[4], cb);
  }
  if (action === 'complete') {
    if (!args[1]) return cb(submissions.usage);
    return doComplete(args[1], cb);
  }
  if (action === 'status') {
    if (!args[1]) return cb(submissions.usage);
    return doStatus(args[1], cb);
  }
  if (action === 'export') {
    args.shift(); // get rid of 'export'
    return doExport(args, cb);
  }
  if (action == 'template') {
    var appId = args[1];
    var formId = args[2];
    if (!appId || !formId) return cb(submissions.usage);
    return doTemplate(appId, formId, cb);
  }

  return cb(submissions.usage);
};

// parses the args for 'app=xxx' and 'form=yyy'
function getAppFormIds(args, cb) {
  var appId, formId, file;
  if (!args) return cb(null, appId, formId, file);
  for (var i=0; i<args.length; i++) {
    var arg = args[i];
    if (arg.indexOf('app=') === 0){
      appId = arg.replace('app=', '');
    }else if (arg.indexOf('form=') === 0){
      formId = arg.replace('form=', '');
    }else if (arg.indexOf('file=') === 0){
      file = arg.replace('file=', '');
    }else {
      return cb('Unknown argument: ' + arg + '\n' + submissions.usage);
    }
  };
  process.nextTick(function() {
    return cb(null, appId, formId, file);
  });
};

function doList(args, cb) {
  var payload = {};
  getAppFormIds(args, function(err, appId, formId) {
    if (err) return cb(err);

    if (appId) payload.appId = appId;
    if (formId) payload.formId = formId;
    payload.wantRestrictions = false;

    fhreq.POST(fhreq.getFeedHenryUrl(), "api/v2/forms/submission", payload, function (err, remoteData, raw, res) {
      if (err) return cb(err);
      if (res.statusCode !== 200) return cb('Unexpected response code: ' + res.statusCode + ' - ' + raw);

      remoteData.status = "ok";
      remoteData.statusCode = 200;
      return cb(err, remoteData);
    });
  });
};

function doGetSubmission(submissionId, cb) {
  fhreq.GET(fhreq.getFeedHenryUrl(), "api/v2/forms/submission/" + submissionId, function (err, remoteData, raw, res) {
    if (err) return cb(err);
    if (res.statusCode !== 200) return cb('Unexpected response code: ' + res.statusCode + ' - ' + raw);

    remoteData.status = "ok";
    remoteData.statusCode = 200;
    return cb(err, remoteData);
  });
};

function doDeleteSubmission(submissionId, cb) {
  fhreq.DELETE(fhreq.getFeedHenryUrl(), "api/v2/forms/submission/" + submissionId, function (err, remoteData, raw, res) {
    if (err) return cb(err);
    if (res.statusCode !== 200) return cb('Unexpected response code: ' + res.statusCode + ' - ' + raw);

    remoteData.status = "ok";
    remoteData.statusCode = 200;
    return cb(err, remoteData);
  });
};

function doGetSubmissionFile(fileGroupId, outputFileName, cb) {
  //TODO the main part of this function should be moved into utils/request.js
  var fhUrl = url.resolve(fhreq.getFeedHenryUrl(),  "api/v2/forms/submission/file/" + fileGroupId);

  var uri = url.parse(fhUrl);
  var proto = uri.protocol === 'https:' ? https : http;

  var headers = {};
  var cookie = fhc.config.get("cookie");
  if (cookie != undefined) {
    headers.cookie = "feedhenry=" + cookie + ";";
  }

  uri.headers = headers;

  var req = proto.get(uri, function(res){
    if(res.statusCode !== 200) return cb("Unexpected response code for file download: " + res.statusCode + " message: " + res.body);

    var stream = fs.createWriteStream(outputFileName);
    res.on('data',function (chunk) {
      stream.write(chunk);
    });

    res.on('end',function (){
      stream.end(function () {
        return cb(undefined, {status: "ok", statusCode: res.statusCode, url: fhUrl, file: outputFileName});
      });
    });
  });

  req.on('error',function(err){
     return cb("Error downloading file: " + err.message);
  });
};

function doSubmit(file, cb) {
  if (!fs.existsSync(file)) return cb("File does not exist: " + file);
  fs.readFile(file, function(err, data) {
    if (err) return cb(err);
    var sub = JSON.parse(data);
    if (!sub.formId) return cb("'formId' missing from submission");
    var url = "api/v2/forms/submission/" + sub.formId + '/submitData';
    fhreq.POST(fhreq.getFeedHenryUrl(), url, sub, function (err, remoteData, raw, res) {
      if (err) return cb(err);
      if (res.statusCode !== 200) return cb('Unexpected response code: ' + res.statusCode + ' - ' + raw);

      remoteData.status = "ok";
      remoteData.statusCode = 200;
      return cb(err, remoteData);
    });
  });
};

function doSubmitFile(submissionId, fieldId, fileId, file, cb) {
  if (!fs.existsSync(file)) return cb("File does not exist: " + file);
  var url = fhreq.getFeedHenryUrl() + "api/v2/forms/submission/" + submissionId + '/' + fieldId + '/' + fileId + '/submitFile';
  var headers = {};
  var cookie = fhc.config.get("cookie");
  if (cookie) {
    headers.cookie = "feedhenry=" + cookie + ";";
  }

  var r = request.post({url: url, headers: headers}, function(err, res, body) {
    if (err) return cb(err);
    if (res.statusCode !== 200) return cb('Unexpected response code: ' + res.statusCode + ' - ' + body);

    body.status = "ok";
    body.statusCode = 200;
    return cb(err, body);
  });

  r.form().append('fileStream', fs.createReadStream(file));
};

function doComplete(submissionId, cb) {
  var url = "api/v2/forms/submission/" + submissionId + '/complete';
  fhreq.POST(fhreq.getFeedHenryUrl(), url, {}, function (err, remoteData, raw, res) {
    if (err) return cb(err);
    if (res.statusCode !== 200) return cb('Unexpected response code: ' + res.statusCode + ' - ' + raw);

    remoteData.status = "ok";
    remoteData.statusCode = 200;
    return cb(err, remoteData);
  });
};

function doStatus(submissionId, cb) {
  var url = "api/v2/forms/submission/" + submissionId + '/status';
  fhreq.GET(fhreq.getFeedHenryUrl(), url, function (err, remoteData, raw, res) {
    if (err) return cb(err);
    if (res.statusCode !== 200) return cb('Unexpected response code: ' + res.statusCode + ' - ' + raw);

    remoteData.status = "ok";
    remoteData.statusCode = 200;
    return cb(err, remoteData);
  });
};

function doExport(args, cb) {
  var payload = {};
  getAppFormIds(args, function(err, appId, formId, file) {
    if (err) return cb(err);
    if (!file) return cb("No file specified, use 'file=<zip-file>, e.g. 'file=/tmp/foo.zip'\n" + submissions.usage);

    if (appId) payload.appId = appId;
    if (formId) payload.formId = formId;

    var url = fhreq.getFeedHenryUrl() + "api/v2/forms/submission/export";
    var headers = {};
    var cookie = fhc.config.get("cookie");
    if (cookie) {
      headers.cookie = "feedhenry=" + cookie + ";";
    }

    var cbCalled = false;
    var f = fs.createWriteStream(file);
    f.on('close', function() {
      if (!cbCalled) {
        cbCalled = true;
        return cb(null, file);
      }
    });

    f.on('error', function(err) {
      if (!cbCalled) {
        cbCalled = true;
        return cb(err);
      };
    });
    var r = request.post({url: url, json:payload, headers: headers}, function(err, res, body) {
      if (err) {
        if (!cbCalled) {
          cbCalled = true;
          return cb(err);
        }
      };
      if(res.statusCode !== 200) {
        if (!cbCalled) {
          cbCalled = true;
          return cb(body);
        }
      }
    });
    r.on('error', function(err) {
      if (!cbCalled) {
        cbCalled = true;
        return cb(err);
      };
    });
    r.pipe(f);
  });
};

function doTemplate(appId, formId, cb) {
  forms(['get', formId], function(err, form) {
    if (err) return cb(err);

    var sub = {
      "appId": appId,
      "formId": formId,
      "appCloudName": "<app-cloud-name>",
      "appEnvironment": "dev",
      "userId": "<used-id>",
      "deviceId": "<device-id>",
      "deviceIPAddress": "192.168.1.1",
      "timezoneOffset": 120,
      "deviceFormTimestamp": new Date(Date.now()).toUTCString(),
      "comments": [{
        "madeBy": "somePerson@example.com",
        "madeOn": new Date(Date.now()).toUTCString(),
        "value": "This is a comment"
      }]
    };

    // now create dummy form field submission values based on the forms form fields
    var fields = [];
    form.pages.forEach(function(page) {
      page.fields.forEach(function(field) {
        if (field.type !== 'matrix' && field.type !== 'sectionBreak') {
          fields.push(field);
        }
      });
    });

    var formFields = [];
    fields.forEach(function(field) {
      var ff = {
        fieldId: field._id,
        fieldValues: []
      };

      if (field.repeating === true) {
        for (var i=0; i<field.fieldOptions.definition.maxRepeat; i++) {
          ff.fieldValues.push(sampleValue(field, (i+1)));
        }
      }else {
        ff.fieldValues.push(sampleValue(field));
      }

      // write out field metadata to the submission to help fill in submission (sent to the server but ignored)
      ff.meta = field;
      formFields.push(ff);
    });

    sub.formFields = formFields;

    return cb(null, sub);
  });
};

function sampleValue(field, num) {
  if (field.type === 'number') return num ? 42 + num: 42;
  if (field.type === 'emailAddress') return num ? 'foo' + num + '@example.com' : 'foo@example.com';
  if (field.type === 'dateTime') {
    if (field.fieldOptions.definition.dateTimeUnit === 'time') return '11:11:11';
    else return new Date(Date.now()).toUTCString();
  }
  if (field.type === 'radio') return field.fieldOptions.definition.options[0].label;
  if (field.type === 'dropdown') return field.fieldOptions.definition.options[0].label;
  if (field.type === 'location') {
    if (field.fieldOptions.definition.locationUnit === 'northEast') {
      return {"zone" : "11U", "eastings" : "594934", "northings" : "5636174"};
    }
    return {"lat" : "5.555848", "long" : "-52.031250"};
  }
  if (field.type === 'locationMap') {
    return {"lat" : "5.555848", "long" : "-52.031250"};
  }
  if (field.type === 'file' || field.type === 'photo' || field.type === 'signature'){
    var f = {
      "fileName" : field.name + (num ? num: ''),
      "fileSize" : field.fieldOptions.definition.file_size || 42,
      "fileType" : field.type === 'photo' ? "application/jpeg" : "application/pdf",
      "fileUpdateTime" : new Date().getTime(),
      "hashName" : "filePlaceHolder123456"
    };
    return f;
  }
  if (field.type === 'checkboxes') {
    var min = field.fieldOptions.validation.min;
    var sel = {
      selections: []
    };
    for (var i=0; i<min; i++) {
      var box = field.fieldOptions.definition.options[i];
      sel.selections.push(Object.keys(box)[0]);
    }
    return sel;
  }
  return "<" + field.name + (num ? '-' + num : '') + ">";
};<|endoftext|>


<commit_before>/**
 * Created with JetBrains WebStorm.
 * User: Gerd
 * Date: 06.03.14
 * Time: 21:51
 * To change this template use File | Settings | File Templates.
 */
var myApp = angular.module('App', ["ngResource", "highcharts-ng", "ui.router", "ui.bootstrap","ui.utils", "LocalStorageModule"]);

function appController($scope, $resource, $window) {
    $scope.TeamDevMembers = $window.exports.AllTeams;
    $scope.common = {};

    $scope.log = function (value) {
        $window.console.log(value);
    };

    $scope.isExist = function (item) {
        return angular.isDefined(item);
    };

    $scope.isString = function (item) {
        return _.isString(item);
    };

    $scope.isInt = function (n) {
        return typeof n === 'number' && parseFloat(n) == parseInt(n, 10) && !isNaN(n);
    };

    $scope.allTeams = function () {
        var allTeamsArray = [{"id": "All", "name": "All"}];
        allTeamsArray.push.apply(allTeamsArray,$scope.TeamDevMembers.teams);
        return allTeamsArray;
    }();

    $scope.allStreams = [{id: "All", name: "All"}];
    $scope.allSMEs = [{id: "All", name: "All"}];
    $scope.allModuleGroups = [{id: "All", name: "All"}];
    $scope.allModules = [{id: "All", name: "All"}];
    $scope.allVersions = [{id: "All", name: "All"}];

    $scope.statuses = $window.exports.statuses;
    $scope.STATUS = $window.exports.STATUS;
    $scope.RESOLUTION = $window.exports.RESOLUTION;

    $scope.getPriorityNumber = $window.exports.getPriorityNumber;
}

myApp.run(function ($rootScope, $location) {

});
<commit_msg>-- fix missed common functions<commit_after>/**
 * Created with JetBrains WebStorm.
 * User: Gerd
 * Date: 06.03.14
 * Time: 21:51
 * To change this template use File | Settings | File Templates.
 */
var myApp = angular.module('App', ["ngResource", "highcharts-ng", "ui.router", "ui.bootstrap","ui.utils", "LocalStorageModule"]);

function appController($scope, $resource, $window) {
    $scope.TeamDevMembers = $window.exports.AllTeams;
    $scope.common = {};

    $scope.log = function (value) {
        $window.console.log(value);
    };

    $scope.isExist = function (item) {
        return angular.isDefined(item);
    };

    $scope.isString = function (item) {
        return _.isString(item);
    };

    $scope.isInt = function (n) {
        return typeof n === 'number' && parseFloat(n) == parseInt(n, 10) && !isNaN(n);
    };

    $scope.allTeams = function () {
        var allTeamsArray = [{"id": "All", "name": "All"}];
        allTeamsArray.push.apply(allTeamsArray,$scope.TeamDevMembers.teams);
        return allTeamsArray;
    }();

    $scope.allStreams = [{id: "All", name: "All"}];
    $scope.allSMEs = [{id: "All", name: "All"}];
    $scope.allModuleGroups = [{id: "All", name: "All"}];
    $scope.allModules = [{id: "All", name: "All"}];
    $scope.allVersions = [{id: "All", name: "All"}];

    $scope.statuses = $window.exports.statuses;
    $scope.STATUS = $window.exports.STATUS;
    $scope.RESOLUTION = $window.exports.RESOLUTION;

    $scope.getPriorityNumber = $window.exports.getPriorityNumber;
}

myApp.run(function ($rootScope, $location) {
    Number.prototype.mod = function(n) {
        return ((this%n)+n)%n;sdlkfj
    };

    Date.prototype.addBusDays = function(dd, holidays) {
        var initialDate = new Date(this);
        var wks = Math.floor(dd/5);
        var dys = dd.mod(5);
        var dy = this.getDay();
        if (dy === 6 && dys > -1) {
            if (dys === 0) {dys-=2; dy+=2;}
            dys++; dy -= 6;}
        if (dy === 0 && dys < 1) {
            if (dys === 0) {dys+=2; dy-=2;}
            dys--; dy += 6;}
        if (dy + dys > 5) dys += 2;
        if (dy + dys < 1) dys -= 2;
        this.setDate(this.getDate()+wks*7+dys);

        if(holidays){
            var shiftDaysCount = 0
            _.each(holidays, function(holiday){
                if(
                    (initialDate.getTime() < holiday.getTime() && this.getTime() > holiday.getTime())
                    || initialDate.getTime() === holiday.getTime()
                    || this.getTime() === holiday.getTime())
                {
                    shiftDaysCount++
                }
            }, this);
            if(shiftDaysCount > 0){
                this.addBusDays(shiftDaysCount,holidays);
            }
        }

        return this;
    }
});
<|endoftext|>


<commit_before>var Download = require('./download'),
    Package = require('./package'),
    UrlCheck = require('./urlcheck'),
    debug = require('debug')('npm-mirror:SyncManager'),
    fs = require('graceful-fs'),
    maybeMkdir = require('./maybemkdir'),
    path = require('path'),
    url = require('url');

/**
 * @constructor
 *
 * @param {string} master npm registry to get packages from.
 * @param {Object} packageToVersions map from package name to object with
 *     key list of versions we need for the package.
 * @param {string} hostname new host that will serve mirrored packages.
 * @param {string} root path for mirrored packages.
 */
function SyncManager(master, packageToVersions, hostname, root) {
  this.master = master;
  this.packageToVersions = packageToVersions;
  this.hostname = hostname;
  this.root = root;
}
module.exports = SyncManager;

SyncManager.prototype = {
  /**
   * @type {string}
   */
  master: null,

  /**
   * @type {Object}
   */
  packageToVersions: null,

  /**
   * @type {string}
   */
  hostname: null,

  /**
   * @type {string}
   */
  root: null,

  /**
   * Sync the packages we're watching from the master registry.
   *
   * 1. Use semver to resolve all loose dependency declarations.
   * 2. Find all of our package version dependencies recursively.
   * 3. Make sure that we have directories for each package version.
   * 4. Download the world.
   *
   * @param {Function} callback invoke when done.
   */
  sync: function(callback) {
    debug('sync');

    // Step 1: Resolve loose package versions.
    Package.versions(
      this.master, this.packageToVersions, function(e, packageToVersions) {
      if (e) {
        return callback && callback(e);
      }

      this.packageToVersions = packageToVersions;

      // Step 2: Dependency search.
      debug('dependency search');
      this.dependencySearch(this.packageToVersions, function(e) {
        if (e) {
          return callback && callback(e);
        }

        // Step 3: Make sure we have package and package version dirs.
        this.makedirs(function(e) {
          if (e) {
            return callback && callback(e);
          }

          // Step 4: Download the world.
          this.download(callback);
        }.bind(this));
      }.bind(this));
    }.bind(this));
  },

  /**
   * Check each package version we're syncing for the master's
   * package version object. Add any new package version dependencies
   * to the in-memory map we're building. Then recursively perform the
   * procedure for all new package version dependencies.
   *
   * @param {Object} packageToVersions map from package name to object with key
   *     list of versions we need for the package.
   * @param {Function} callback invoke when done.
   */
  dependencySearch: function(packageToVersions, callback) {
    var count = Package.versionCount(packageToVersions);

    // Base case.
    if (count === 0) {
      return callback && callback();
    }

    // For each package version, check master package version object.
    // Issue a recursive dependencySearch with all of the "new" deps we find.
    var packages = Object.keys(packageToVersions);
    packages.forEach(function(package) {
      var versions = Object.keys(packageToVersions[package]);
      versions.forEach(function(version) {
        function process() {
          if (--count <= 0) {
            return callback && callback();
          }
        }

        // Careful! The version could still be a git/tarball url...
        // Or version could be null if semver couldn't find a match.
        if (!version || version === 'null' || UrlCheck.isWebUrl(version) ||
            UrlCheck.isGitUrl(version)) {
          // TODO(gaye): Eh? What to do?
          delete this.packageToVersions[package][version];
          return process();
        }

        var packageVersionUrl = Package.url(this.master, package, version);
        Download.inst.download(
          packageVersionUrl, function(e, packageVersionData) {
          if (e) {
            // If we choke on a package, it's probably something wacky or
            // no longer exists. Let's ignore it for now, but log it just
            // in case.
            debug('error downloading package ' + package + ': ' + e);
            delete this.packageToVersions[package][version];
            return process();
          }

          var packageVersion = JSON.parse(packageVersionData);
          var deps = Package.dependencies(
            packageVersion, ['dependencies', 'peerDependencies'] /* types */);
          Package.versions(this.master, deps, function(e, depToVersions) {
            if (e) {
              return callback && callback(e);
            }

            var newDeps =
              this.addDependencies(packageVersion.name, depToVersions);
            this.dependencySearch(newDeps, function(e) {
              if (e) {
                return callback && callback(e);
              }

              return process();
            });
          }.bind(this));
        }.bind(this));
      }.bind(this));
    }.bind(this));
  },

  /**
   * Add dependencies to our in-memory map from packages to versions.
   *
   * @param {string} parent package that needs these dependencies.
   * @param {Object} depToVersions map from package name to object with key list
   *     of versions we need for the dep package.
   * @return {Object} new deps.
   */
  addDependencies: function(parent, depToVersions) {
    var newDeps = {};
    for (var package in depToVersions) {
      var currVersions = this.packageToVersions[package];
      var depVersions = depToVersions[package];
      newDeps[package] = {};

      // Check if we are watching this package.
      if (!currVersions) {
        // Add all of the versions.
        debug(parent + ' needs ' + package + '@' +
              Object.keys(depVersions).join(', '));
        this.packageToVersions[package] = depVersions;
        newDeps[package] = depVersions;
        continue;
      }

      // Check which versions we are watching.
      for (var version in depVersions) {
        if (!(version in currVersions)) {
          // Add this version.
          debug(parent + ' needs ' + package + '@' + version);
          this.packageToVersions[package][version] = true;
          newDeps[package][version] = true;
        }
      }
    }

    return newDeps;
  },

  /**
   * Make directories for all of the packages and package versions.
   *
   * @param {Function} callback [err] invoke when done.
   */
  makedirs: function(callback) {
    var dirs = [];
    for (var package in this.packageToVersions) {
      var packagePath = path.resolve(this.root, package);
      dirs.push(packagePath);

      var versions = this.packageToVersions[package];
      for (var version in versions) {
        var packageVersionPath = path.resolve(this.root, package, version);
        dirs.push(packageVersionPath);
      }
    }

    var count = dirs.length;
    debug('maybe make ' + count + ' dirs');
    dirs.forEach(function(dir) {
      maybeMkdir(dir, function onMaybeMkdir(e) {
        if (e) {
          // TODO(gaye): Eventually we should give up.
          debug('error maybemkdir, will try again ' + dir + ': ' + e);
          return maybeMkdir(dir, onMaybeMkdir);
        }

        if (--count <= 0) {
          return callback && callback();
        }
      });
    });
  },

  /**
   * Download all the package root objects, package version objects,
   * and tarballs.
   *
   * @param {Function} callback invoke when done.
   */
  download: function(callback) {
    this.downloadPackageRootObjects(function(e) {
      if (e) {
        return callback && callback(e);
      }

      this.downloadPackageVersions(callback);
    }.bind(this));
  },

  /**
   * Download a package root object for each package.
   *
   * @param {Function} callback invoke when done.
   */
  downloadPackageRootObjects: function(callback) {
    var packages = Object.keys(this.packageToVersions);
    var count = packages.length;
    function process() {
      if (--count <= 0) {
        return callback && callback();
      }
    }

    packages.forEach(function(package) {
      var packageRootUrl = url.resolve(this.master, package);
      // TODO(gaye): Use etags here so that we don't download again
      //     if, for instance, no new packages have been published.
      Download.inst.download(packageRootUrl, function(e, packageRootData) {
        if (e) {
          debug('error downloading package ' + package + ': ' + e);
          return process();
        }

        var packageRoot = JSON.parse(packageRootData);
        var copy = {};
        copy.name = packageRoot.name;
        copy._id = packageRoot.name;
        copy.versions = {};
        var versions = Object.keys(this.packageToVersions[package]);
        versions.forEach(function(version) {
          copy.versions[version] = Package.url(this.hostname, package, version);
        }.bind(this));

        copy['dist-tags'] = {};
        var sorted = versions.sort();
        copy['dist-tags'].latest = sorted[sorted.length - 1];

        var dest = path.resolve(this.root, package, 'index.json');
        fs.writeFile(dest, JSON.stringify(copy), function(e) {
          if (e) {
            return callback && callback(e);
          }

          return process();
        });
      }.bind(this));
    }.bind(this));
  },

  /**
   * Download a package version object and tarball for each package version.
   *
   * @param {Function} callback invoke when done.
   */
  downloadPackageVersions: function(callback) {
    var count = Package.versionCount(this.packageToVersions);
    function process() {
      if (--count <= 0) {
        return callback && callback();
      }
    }

    var packages = Object.keys(this.packageToVersions);
    packages.forEach(function(package) {
      var versions = this.packageToVersions[package];

      var onExists = function(exists) {
        // TODO(gaye): Use etags here to prevent the cases where packages
        //     are modified or deleted after being synced.
        if (exists) {
          return process();
        }

        var packageVersionUrl = Package.url(this.master, package, version);
        Download.inst.download(
          packageVersionUrl, function(e, packageVersionData) {
          if (e) {
            debug('error downloading package ' + package + ': ' + e);
            return process();
          }

          var packageVersion = JSON.parse(packageVersionData);
          var copy = {};
          copy.name = packageVersion.name;
          copy.version = packageVersion.version;
          copy.dependencies = packageVersion.dependencies;
          copy.devDependencies = packageVersion.devDependencies;
          copy.peerDependencies = packageVersion.peerDependencies;
          copy.dist = {};
          copy.dist.tarball =
            Package.tarballUrl(this.master, package, version);

          fs.writeFile(dest, JSON.stringify(copy), function() {
            var tarball = packageVersion.dist.tarball;
            var dest = path.resolve(
              this.root, package, version,
              package + '-' + version + '.tgz');
            Download.inst.downloadToDisk(tarball, dest, function(e) {
              if (e) {
                return callback && callback(e);
              }

              process();
            });
          }.bind(this));
        }.bind(this));
      }.bind(this);

      for (var version in versions) {
        var dest = path.resolve(this.root, package, version, 'index.json');
        fs.exists(dest, onExists);
      }
    }.bind(this));
  }
};
<commit_msg>Use filter + forEach for adding new deps<commit_after>var Download = require('./download'),
    Package = require('./package'),
    UrlCheck = require('./urlcheck'),
    debug = require('debug')('npm-mirror:SyncManager'),
    fs = require('graceful-fs'),
    maybeMkdir = require('./maybemkdir'),
    path = require('path'),
    url = require('url');

/**
 * @constructor
 *
 * @param {string} master npm registry to get packages from.
 * @param {Object} packageToVersions map from package name to object with
 *     key list of versions we need for the package.
 * @param {string} hostname new host that will serve mirrored packages.
 * @param {string} root path for mirrored packages.
 */
function SyncManager(master, packageToVersions, hostname, root) {
  this.master = master;
  this.packageToVersions = packageToVersions;
  this.hostname = hostname;
  this.root = root;
}
module.exports = SyncManager;

SyncManager.prototype = {
  /**
   * @type {string}
   */
  master: null,

  /**
   * @type {Object}
   */
  packageToVersions: null,

  /**
   * @type {string}
   */
  hostname: null,

  /**
   * @type {string}
   */
  root: null,

  /**
   * Sync the packages we're watching from the master registry.
   *
   * 1. Use semver to resolve all loose dependency declarations.
   * 2. Find all of our package version dependencies recursively.
   * 3. Make sure that we have directories for each package version.
   * 4. Download the world.
   *
   * @param {Function} callback invoke when done.
   */
  sync: function(callback) {
    debug('sync');

    // Step 1: Resolve loose package versions.
    Package.versions(
      this.master, this.packageToVersions, function(e, packageToVersions) {
      if (e) {
        return callback && callback(e);
      }

      this.packageToVersions = packageToVersions;

      // Step 2: Dependency search.
      debug('dependency search');
      this.dependencySearch(this.packageToVersions, function(e) {
        if (e) {
          return callback && callback(e);
        }

        // Step 3: Make sure we have package and package version dirs.
        this.makedirs(function(e) {
          if (e) {
            return callback && callback(e);
          }

          // Step 4: Download the world.
          this.download(callback);
        }.bind(this));
      }.bind(this));
    }.bind(this));
  },

  /**
   * Check each package version we're syncing for the master's
   * package version object. Add any new package version dependencies
   * to the in-memory map we're building. Then recursively perform the
   * procedure for all new package version dependencies.
   *
   * @param {Object} packageToVersions map from package name to object with key
   *     list of versions we need for the package.
   * @param {Function} callback invoke when done.
   */
  dependencySearch: function(packageToVersions, callback) {
    var count = Package.versionCount(packageToVersions);

    // Base case.
    if (count === 0) {
      return callback && callback();
    }

    // For each package version, check master package version object.
    // Issue a recursive dependencySearch with all of the "new" deps we find.
    var packages = Object.keys(packageToVersions);
    packages.forEach(function(package) {
      var versions = Object.keys(packageToVersions[package]);
      versions.forEach(function(version) {
        function process() {
          if (--count <= 0) {
            return callback && callback();
          }
        }

        // Careful! The version could still be a git/tarball url...
        // Or version could be null if semver couldn't find a match.
        if (!version || version === 'null' || UrlCheck.isWebUrl(version) ||
            UrlCheck.isGitUrl(version)) {
          // TODO(gaye): Eh? What to do?
          delete this.packageToVersions[package][version];
          return process();
        }

        var packageVersionUrl = Package.url(this.master, package, version);
        Download.inst.download(
          packageVersionUrl, function(e, packageVersionData) {
          if (e) {
            // If we choke on a package, it's probably something wacky or
            // no longer exists. Let's ignore it for now, but log it just
            // in case.
            debug('error downloading package ' + package + ': ' + e);
            delete this.packageToVersions[package][version];
            return process();
          }

          var packageVersion = JSON.parse(packageVersionData);
          var deps = Package.dependencies(
            packageVersion, ['dependencies', 'peerDependencies'] /* types */);
          Package.versions(this.master, deps, function(e, depToVersions) {
            if (e) {
              return callback && callback(e);
            }

            var newDeps =
              this.addDependencies(packageVersion.name, depToVersions);
            this.dependencySearch(newDeps, function(e) {
              if (e) {
                return callback && callback(e);
              }

              return process();
            });
          }.bind(this));
        }.bind(this));
      }.bind(this));
    }.bind(this));
  },

  /**
   * Add dependencies to our in-memory map from packages to versions.
   *
   * @param {string} parent package that needs these dependencies.
   * @param {Object} depToVersions map from package name to object with key list
   *     of versions we need for the dep package.
   * @return {Object} new deps.
   */
  addDependencies: function(parent, depToVersions) {
    var newDeps = {};
    var packages = Object.keys(depToVersions);
    packages.forEach(function(package) {
      var currVersions = this.packageToVersions[package];
      var depVersions = depToVersions[package];
      newDeps[package] = {};

      // Check if we are watching this package.
      if (!currVersions) {
        // Add all of the versions.
        debug(parent + ' needs ' + package + '@' +
              Object.keys(depVersions).join(', '));
        this.packageToVersions[package] = depVersions;
        newDeps[package] = depVersions;
        return;
      }

      // Check which versions we are watching.
      var versions = Object.keys(depVersions);
      versions
        .filter(function(version) {
          return !(version in currVersions);
        })
        .forEach(function(version) {
          // Add this version.
          debug(parent + ' needs ' + package + '@' + version);
          this.packageToVersions[package][version] = true;
          newDeps[package][version] = true;
        }.bind(this));
    }.bind(this));

    return newDeps;
  },

  /**
   * Make directories for all of the packages and package versions.
   *
   * @param {Function} callback [err] invoke when done.
   */
  makedirs: function(callback) {
    var dirs = [];
    for (var package in this.packageToVersions) {
      var packagePath = path.resolve(this.root, package);
      dirs.push(packagePath);

      var versions = this.packageToVersions[package];
      for (var version in versions) {
        var packageVersionPath = path.resolve(this.root, package, version);
        dirs.push(packageVersionPath);
      }
    }

    var count = dirs.length;
    debug('maybe make ' + count + ' dirs');
    dirs.forEach(function(dir) {
      maybeMkdir(dir, function onMaybeMkdir(e) {
        if (e) {
          // TODO(gaye): Eventually we should give up.
          debug('error maybemkdir, will try again ' + dir + ': ' + e);
          return maybeMkdir(dir, onMaybeMkdir);
        }

        if (--count <= 0) {
          return callback && callback();
        }
      });
    });
  },

  /**
   * Download all the package root objects, package version objects,
   * and tarballs.
   *
   * @param {Function} callback invoke when done.
   */
  download: function(callback) {
    this.downloadPackageRootObjects(function(e) {
      if (e) {
        return callback && callback(e);
      }

      this.downloadPackageVersions(callback);
    }.bind(this));
  },

  /**
   * Download a package root object for each package.
   *
   * @param {Function} callback invoke when done.
   */
  downloadPackageRootObjects: function(callback) {
    var packages = Object.keys(this.packageToVersions);
    var count = packages.length;
    function process() {
      if (--count <= 0) {
        return callback && callback();
      }
    }

    packages.forEach(function(package) {
      var packageRootUrl = url.resolve(this.master, package);
      // TODO(gaye): Use etags here so that we don't download again
      //     if, for instance, no new packages have been published.
      Download.inst.download(packageRootUrl, function(e, packageRootData) {
        if (e) {
          debug('error downloading package ' + package + ': ' + e);
          return process();
        }

        var packageRoot = JSON.parse(packageRootData);
        var copy = {};
        copy.name = packageRoot.name;
        copy._id = packageRoot.name;
        copy.versions = {};
        var versions = Object.keys(this.packageToVersions[package]);
        versions.forEach(function(version) {
          copy.versions[version] = Package.url(this.hostname, package, version);
        }.bind(this));

        copy['dist-tags'] = {};
        var sorted = versions.sort();
        copy['dist-tags'].latest = sorted[sorted.length - 1];

        var dest = path.resolve(this.root, package, 'index.json');
        fs.writeFile(dest, JSON.stringify(copy), function(e) {
          if (e) {
            return callback && callback(e);
          }

          return process();
        });
      }.bind(this));
    }.bind(this));
  },

  /**
   * Download a package version object and tarball for each package version.
   *
   * @param {Function} callback invoke when done.
   */
  downloadPackageVersions: function(callback) {
    var count = Package.versionCount(this.packageToVersions);
    function process() {
      if (--count <= 0) {
        return callback && callback();
      }
    }

    var packages = Object.keys(this.packageToVersions);
    packages.forEach(function(package) {
      var versions = this.packageToVersions[package];

      var onExists = function(exists) {
        // TODO(gaye): Use etags here to prevent the cases where packages
        //     are modified or deleted after being synced.
        if (exists) {
          return process();
        }

        var packageVersionUrl = Package.url(this.master, package, version);
        Download.inst.download(
          packageVersionUrl, function(e, packageVersionData) {
          if (e) {
            debug('error downloading package ' + package + ': ' + e);
            return process();
          }

          var packageVersion = JSON.parse(packageVersionData);
          var copy = {};
          copy.name = packageVersion.name;
          copy.version = packageVersion.version;
          copy.dependencies = packageVersion.dependencies;
          copy.devDependencies = packageVersion.devDependencies;
          copy.peerDependencies = packageVersion.peerDependencies;
          copy.dist = {};
          copy.dist.tarball =
            Package.tarballUrl(this.master, package, version);

          fs.writeFile(dest, JSON.stringify(copy), function() {
            var tarball = packageVersion.dist.tarball;
            var dest = path.resolve(
              this.root, package, version,
              package + '-' + version + '.tgz');
            Download.inst.downloadToDisk(tarball, dest, function(e) {
              if (e) {
                return callback && callback(e);
              }

              process();
            });
          }.bind(this));
        }.bind(this));
      }.bind(this);

      for (var version in versions) {
        var dest = path.resolve(this.root, package, version, 'index.json');
        fs.exists(dest, onExists);
      }
    }.bind(this));
  }
};
<|endoftext|>


<commit_before>;(function() {

    var container = null;
    var markers = null;

    var mousewheel = "onwheel" in document.createElement("div") ? "wheel" :
            document.onmousewheel !== undefined ? "mousewheel" :
            "DOMMouseScroll";

    function panZoom() {
        var pz = {
            pan: {}
        };
        var self = this;
        pz.elm = self;
        var svg = self;
        while ((svg = self.parent).node.tagName.toUpperCase() !== "SVG") {}
        var rect = new SVG(document.createDocumentFragment()).rect().attr({
            width: svg.width(),
            height: svg.height(),
            fill: "none"
        }).style("pointer-events", "all");
        self.parent.node.insertBefore(rect.node, self.node)

        function updateMatrix() {
            self.matrix([
                pz.transform.scaleX, 0, 0,
                pz.transform.scaleY, pz.transform.x, pz.transform.y
            ].join(","));
        }

        function pan(e) {
            if (!pz.pan.mousedown) {
                return;
            }
            var tr = pz.transform = self.transform();
            var diffX = (pz.pan.fPos.x - pz.pan.iPos.x) / (tr.scaleX * 2);
            var diffY = (pz.pan.fPos.y - pz.pan.iPos.y) / (tr.scaleY * 2);
            tr.x += diffX;
            tr.y += diffY;
            pz.pan.iPos = pz.pan.fPos;
            updateMatrix();
        }

        function zoom (e) {
            var tr = pz.transform = self.transform();
            var d = e.deltaY / 1000
            var scale = tr.scaleX + d;

            var oX = e.clientX;
            var oY = e.clientY;

            var scaleD = scale / tr.scaleX;
            var currentX = tr.x;
            var currentY = tr.y;
            var x = scaleD * (currentX - oX) + oX;
            var y = scaleD * (currentY - oY) + oY;

            tr.scaleY = tr.scaleX = scale;
            tr.x = x;
            tr.y = y;
            updateMatrix();
        }

        rect.on(mousewheel, zoom);
        rect.on("mousedown", function (e) {
            pz.pan.mousedown = true;
            pz.pan.iPos = {
                x: e.clientX,
                y: e.clientY
            };
        }).on("mousemove", function (e) {
            pz.pan.fPos = {
                x: e.clientX,
                y: e.clientY
            };
            pan();
        }).on("mouseup", function (e) {
            pz.pan.mousedown = false;
            pz.pan.fPos = {
                x: e.clientX,
                y: e.clientY
            };
            pan();
        }).on("mouseleave", function () {
            pz.pan.mousedown = false;
        });
        self.on(mousewheel, zoom);
    }

    SVG.extend(SVG.Element, {
        panZoom: panZoom
    });
}).call(this);
<commit_msg>Trigger zoom and pan events<commit_after>;(function() {

    var container = null;
    var markers = null;

    var mousewheel = "onwheel" in document.createElement("div") ? "wheel" :
            document.onmousewheel !== undefined ? "mousewheel" :
            "DOMMouseScroll";

    function panZoom() {
        var pz = {
            pan: {}
        };
        var self = this;
        pz.elm = self;
        var svg = self;
        while ((svg = self.parent).node.tagName.toUpperCase() !== "SVG") {}
        var rect = new SVG(document.createDocumentFragment()).rect().attr({
            width: svg.width(),
            height: svg.height(),
            fill: "none"
        }).style("pointer-events", "all");
        self.parent.node.insertBefore(rect.node, self.node)

        function updateMatrix() {
            self.matrix([
                pz.transform.scaleX, 0, 0,
                pz.transform.scaleY, pz.transform.x, pz.transform.y
            ].join(","));
        }

        function pan(e) {
            if (!pz.pan.mousedown) {
                return;
            }
            var tr = pz.transform = self.transform();
            var diffX = (pz.pan.fPos.x - pz.pan.iPos.x) / (tr.scaleX * 2);
            var diffY = (pz.pan.fPos.y - pz.pan.iPos.y) / (tr.scaleY * 2);
            tr.x += diffX;
            tr.y += diffY;
            pz.pan.iPos = pz.pan.fPos;
            self.node.dispatchEvent(new CustomEvent("pan", e, tr));
            updateMatrix();
        }

        function zoom (e) {
            var tr = pz.transform = self.transform();
            var d = e.deltaY / 1000
            var scale = tr.scaleX + d;

            var oX = e.clientX;
            var oY = e.clientY;

            var scaleD = scale / tr.scaleX;
            var currentX = tr.x;
            var currentY = tr.y;
            var x = scaleD * (currentX - oX) + oX;
            var y = scaleD * (currentY - oY) + oY;

            tr.scaleY = tr.scaleX = scale;
            tr.x = x;
            tr.y = y;

            self.node.dispatchEvent(new CustomEvent("zoom", e, tr));
            updateMatrix();
        }

        rect.on(mousewheel, zoom);
        rect.on("mousedown", function (e) {
            pz.pan.mousedown = true;
            pz.pan.iPos = {
                x: e.clientX,
                y: e.clientY
            };
        }).on("mousemove", function (e) {
            pz.pan.fPos = {
                x: e.clientX,
                y: e.clientY
            };
            pan();
        }).on("mouseup", function (e) {
            pz.pan.mousedown = false;
            pz.pan.fPos = {
                x: e.clientX,
                y: e.clientY
            };
            pan();
        }).on("mouseleave", function () {
            pz.pan.mousedown = false;
        });
        self.on(mousewheel, zoom);
    }

    SVG.extend(SVG.Element, {
        panZoom: panZoom
    });
}).call(this);
<|endoftext|>


<commit_before>module.exports = function TeamNerver(nira){
    if(!(this instanceof TeamNerver)) {
        return new TeamNerver(nira);
    }
    this.nira = nira;
    this.period = 60000*10;//10 minutes
    this.hasInitialized = false;
    this.progressSize = Math.floor(15000/this.period);

    this.prompt = function(cb) {
        var prompt = require('prompt');

        var properties = [
        {
            name: 'username'
        },
        {
            name: 'password',
            hidden: true
        }
        ];

        prompt.start();

        prompt.get(properties, function (err, result) {
            if (err) { return onErr(err); }
            this.nira.login(result.username, result.password, function(isLoggedIn){
                cb && cb(isLoggedIn);
            });
        });

        function onErr(err) {
            this.consoleLog(err);
            return 1;
        }
    };

    this.start = function(arg) {

        if(arg === "x" || arg === "-x" || arg === "silent"){
            this.silent = true;
        }
        this.prompt(function(isLoggedIn) {
            this.listen(isLoggedIn);
        });
        return this;
    };

    this.listen = function(isLoggedIn){
        this.isLoggedIn = isLoggedIn;
        this.onStart();
        this.startTime = (new Date().getTime());
        require(__dirname+"/../team/server_team.js")(this);
        this.runInterval = setInterval(function() {

            if(this.shouldEnd()){
                clearInterval(this.runInterval);
                this.consoleLog("Team this session ended.");
                process.exit();
                return;
            }

            this.writeProgress();
        }, this.period);
    };

    this.shouldEnd = function(){
        return false
    };

    this.writeProgress = function() {
        if(this.hasInitialized && !this.silent){
            if(this.counter % this.progressSize === 0){
                this.initWriteProgress();
            }
        }
    };

    this.initWriteProgress = function(){
        if(!this.silent) {
            process.stdout.clearLine();
            process.stdout.cursorTo(0);
        }
    };

    this.onStart = function(){
        this.clearScreen();
         this.consoleLog("\n\n");
        if(!this.isLoggedIn){
            this.consoleLog("Not Logged in");
        }else {
            this.consoleLog("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
            this.consoleLog("!!!!!!!!!!Logged in!!!!!!!!!!");
            this.consoleLog("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
        }
        this.consoleLog("Team this is listening...\n\n\n");
        setTimeout(function(){this.hasInitialized = true; this.initWriteProgress(); }, 1550);
    };

    this.write = function(str) {
        if(!this.silent) {
            process.stdout.write(str);
        }
    };

    this.consoleLog = function(str) {
        if(!this.silent) {
            console.log(str);
        }
    }

    this.clearScreen = function(){
        var numLines = process.stdout.getWindowSize()[1];
        this.cursorUp(numLines, false);
    };

    this.cursorUp = function up (i, save) {
        i = i || 1;
        if (i > 0) {
            while(i--) {
                process.stdout.write(!save ? '\033[K\033[1A\r' : '\033[1A\r');
            }
        }
        process.stdout.cursorTo(0);
    };
};
<commit_msg>NIT-classy self<commit_after>module.exports = function TeamNerver(nira){
    if(!(this instanceof TeamNerver)) {
        return new TeamNerver(nira);
    }
    this.nira = nira;
    this.period = 60000*10;//10 minutes
    this.hasInitialized = false;
    this.progressSize = Math.floor(15000/this.period);

    this.prompt = function(cb) {
        var self = this;
        var prompt = require('prompt');

        var properties = [
        {
            name: 'username'
        },
        {
            name: 'password',
            hidden: true
        }
        ];

        prompt.start();

        prompt.get(properties, function (err, result) {
            if (err) { return onErr(err); }
            self.nira.login(result.username, result.password, function(isLoggedIn){
                cb && cb(isLoggedIn);
            });
        });

        function onErr(err) {
            self.consoleLog(err);
            return 1;
        }
    };

    this.start = function(arg) {
        var self = this;
        if(arg === "x" || arg === "-x" || arg === "silent"){
            self.silent = true;
        }
        this.prompt(function(isLoggedIn) {
            self.listen(isLoggedIn);
        });
        return self;
    };

    this.listen = function(isLoggedIn){
        var self = this;
        self.isLoggedIn = isLoggedIn;
        self.onStart();
        self.startTime = (new Date().getTime());
        require(__dirname+"/../team/server_team.js")(self);
        self.runInterval = setInterval(function() {

            if(self.shouldEnd()){
                clearInterval(self.runInterval);
                self.consoleLog("Team this session ended.");
                process.exit();
                return;
            }

            self.writeProgress();
        }, self.period);
    };

    this.shouldEnd = function(){
        return false
    };

    this.writeProgress = function() {
        if(this.hasInitialized && !this.silent){
            if(this.counter % this.progressSize === 0){
                this.initWriteProgress();
            }
        }
    };

    this.initWriteProgress = function(){
        if(!this.silent) {
            process.stdout.clearLine();
            process.stdout.cursorTo(0);
        }
    };

    this.onStart = function(){
        this.clearScreen();
         this.consoleLog("\n\n");
        if(!this.isLoggedIn){
            this.consoleLog("Not Logged in");
        }else {
            this.consoleLog("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
            this.consoleLog("!!!!!!!!!!Logged in!!!!!!!!!!");
            this.consoleLog("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
        }
        this.consoleLog("Team this is listening...\n\n\n");
        setTimeout(function(){this.hasInitialized = true; this.initWriteProgress(); }, 1550);
    };

    this.write = function(str) {
        if(!this.silent) {
            process.stdout.write(str);
        }
    };

    this.consoleLog = function(str) {
        if(!this.silent) {
            console.log(str);
        }
    }

    this.clearScreen = function(){
        var numLines = process.stdout.getWindowSize()[1];
        this.cursorUp(numLines, false);
    };

    this.cursorUp = function up (i, save) {
        i = i || 1;
        if (i > 0) {
            while(i--) {
                process.stdout.write(!save ? '\033[K\033[1A\r' : '\033[1A\r');
            }
        }
        process.stdout.cursorTo(0);
    };
};
<|endoftext|>


<commit_before>/**
 * Map constructor
 *
 * @class Roguelike.Map
 * @classdesc The object that holds all the rooms, corridors and tiles
 *
 * @property {Roguelike.Game} game - Reference to the current game object
 */
Roguelike.Map = function(game) {

	/**
	 * @property {Roguelike.Game} game - Reference to the current game object
	 */
	this.game = game;

	/**
	 * @property {Roguelike.Group} entities - Holds all the entities of this game
	 */
	this.entities = null;

	/**
	 * @property {number} tilesX - The number of horizontal tiles on this map
	 */
	this.tilesX = game.settings.tilesX;

	/**
	 * @property {number} tilesY - The number of vertical tiles on this map
	 */
	this.tilesY = game.settings.tilesY;

	/**
	 * @property {number} maxRooms - The maximum number of rooms allowed on this map
	 */
	this.maxRooms = game.settings.maxRooms;

	/**
	 * @property {array} rooms - An array that holds all room objects
	 */
	this.rooms = [];

	/**
	 * @property {array} corridors - An array that holds all corridor objects
	 */
	this.corridors = [];

	/**
	 * @property {array} tiles - An array that holds all tile objects
	 */
	this.tiles = [];

	/**
	 * @property {array} objects - An array that holds all objects that are on the map
	 */
	this.objects = [];

	/**
	 * @property {number} tileSize - The width and height of a single tile on the map
	 */
	this.tileSize = game.settings.tileSize;

	/**
	 * @property {number} minRoomWidth - The minimum width of a room on this map
	 */
	this.minRoomWidth = game.settings.minRoomWidth;

	/**
	 * @property {number} maxRoomWidth - The maximum width of a room on this map
	 */
	this.maxRoomWidth = game.settings.maxRoomWidth;

	/**
	 * @property {number} minRoomHeight - The minimum heigth of a room on this map
	 */
	this.minRoomHeight = game.settings.minRoomHeight;

	/**
	 * @property {number} maxRoomHeight - The maximum heigth of a room on this map
	 */
	this.maxRoomHeight = game.settings.maxRoomHeight;

	/**
	 * @property {Roguelike.MapFactory} mapFactory - The room factory is responsible for creating rooms and corridors on this map
	 */
	this.mapFactory = null;

	/**
	 * @property {entrance} object - An object that holds the position of the entrance of this map
	 */
	this.entrance = null;

	/**
	 * @property {exit} object - An object that holds the position of the exit of this map
	 */
	this.exit = null;

};

Roguelike.Map.prototype = {

	/**
	 * Initialize the layout of the map, filling it with empty tiles
	 * @protected
	 */
	initialize: function() {

		//Create the map factory
		this.mapFactory = new Roguelike.MapFactory(this.game);

		//Loop through every horizontal row
		for(var x = 0; x < this.tilesX; x++) {

			//Initialize this row
			this.tiles[x] = [];

			//Loop through every vertical row
			for(var y = 0; y < this.tilesY; y++) {

				//Initialize this position by setting it to zero, and blocking light
				this.tiles[x][y] = new Roguelike.Tile(0, true, 0, 0);

			}

		}

	},

	/**
	 * Check if a single room overlaps a room that is allready on the map
	 * @protected
	 *
	 * @param {Roguelike.Room} room - The room object that has to be checked
	 */
	roomIntersectsWith: function(room) {

		//Loop through every room in the list
		for(var i = 0; i < this.rooms.length; i++) {

			//Check if the room intersects with the current room
			if(room.x1 <= this.rooms[i].x2 && room.x2 >= this.rooms[i].x1 && room.y1 <= this.rooms[i].y2 && room.y2 >= this.rooms[i].y1) {
				return true;
			}

		}
		//If the room doesn't intersect another room, return false
		return false;

	},

	/**
	 * Add all the rooms from the room list to the map, get the tiles from each room's layout
	 * @protected
	 */
	addRooms: function() {

		//Loop through each room in the list
		for(var i = 0; i < this.rooms.length; i++) {

			//Loop through every horizontal row
			for(var x = this.rooms[i].x1; x < this.rooms[i].x2; x++) {

				//What is the current Y position in the layout of the current room
				var layoutXPos = this.rooms[i].x2 - x - 1;

				//Loop through every vertical row
				for(var y = this.rooms[i].y1; y < this.rooms[i].y2; y++) {

					//What is the current X position in the layout of the current room
					var layoutYPos = this.rooms[i].y2 - y - 1;

					//Get the current tile object
					var currentTile = this.rooms[i].layout[layoutXPos][layoutYPos];

					//Place the tile that is on the layout on this position on the map
					this.tiles[x][y] = currentTile;

				}

			}

		}

	}

};
<commit_msg>Removed an unused variable.<commit_after>/**
 * Map constructor
 *
 * @class Roguelike.Map
 * @classdesc The object that holds all the rooms, corridors and tiles
 *
 * @property {Roguelike.Game} game - Reference to the current game object
 */
Roguelike.Map = function(game) {

	/**
	 * @property {Roguelike.Game} game - Reference to the current game object
	 */
	this.game = game;

	/**
	 * @property {Roguelike.Group} entities - Holds all the entities of this game
	 */
	this.entities = null;

	/**
	 * @property {number} tilesX - The number of horizontal tiles on this map
	 */
	this.tilesX = game.settings.tilesX;

	/**
	 * @property {number} tilesY - The number of vertical tiles on this map
	 */
	this.tilesY = game.settings.tilesY;

	/**
	 * @property {number} maxRooms - The maximum number of rooms allowed on this map
	 */
	this.maxRooms = game.settings.maxRooms;

	/**
	 * @property {array} rooms - An array that holds all room objects
	 */
	this.rooms = [];

	/**
	 * @property {array} tiles - An array that holds all tile objects
	 */
	this.tiles = [];

	/**
	 * @property {array} objects - An array that holds all objects that are on the map
	 */
	this.objects = [];

	/**
	 * @property {number} tileSize - The width and height of a single tile on the map
	 */
	this.tileSize = game.settings.tileSize;

	/**
	 * @property {number} minRoomWidth - The minimum width of a room on this map
	 */
	this.minRoomWidth = game.settings.minRoomWidth;

	/**
	 * @property {number} maxRoomWidth - The maximum width of a room on this map
	 */
	this.maxRoomWidth = game.settings.maxRoomWidth;

	/**
	 * @property {number} minRoomHeight - The minimum heigth of a room on this map
	 */
	this.minRoomHeight = game.settings.minRoomHeight;

	/**
	 * @property {number} maxRoomHeight - The maximum heigth of a room on this map
	 */
	this.maxRoomHeight = game.settings.maxRoomHeight;

	/**
	 * @property {Roguelike.MapFactory} mapFactory - The room factory is responsible for creating rooms and corridors on this map
	 */
	this.mapFactory = null;

	/**
	 * @property {entrance} object - An object that holds the position of the entrance of this map
	 */
	this.entrance = null;

	/**
	 * @property {exit} object - An object that holds the position of the exit of this map
	 */
	this.exit = null;

};

Roguelike.Map.prototype = {

	/**
	 * Initialize the layout of the map, filling it with empty tiles
	 * @protected
	 */
	initialize: function() {

		//Create the map factory
		this.mapFactory = new Roguelike.MapFactory(this.game);

		//Loop through every horizontal row
		for(var x = 0; x < this.tilesX; x++) {

			//Initialize this row
			this.tiles[x] = [];

			//Loop through every vertical row
			for(var y = 0; y < this.tilesY; y++) {

				//Initialize this position by setting it to zero, and blocking light
				this.tiles[x][y] = new Roguelike.Tile(0, true, 0, 0);

			}

		}

	},

	/**
	 * Check if a single room overlaps a room that is allready on the map
	 * @protected
	 *
	 * @param {Roguelike.Room} room - The room object that has to be checked
	 */
	roomIntersectsWith: function(room) {

		//Loop through every room in the list
		for(var i = 0; i < this.rooms.length; i++) {

			//Check if the room intersects with the current room
			if(room.x1 <= this.rooms[i].x2 && room.x2 >= this.rooms[i].x1 && room.y1 <= this.rooms[i].y2 && room.y2 >= this.rooms[i].y1) {
				return true;
			}

		}
		//If the room doesn't intersect another room, return false
		return false;

	},

	/**
	 * Add all the rooms from the room list to the map, get the tiles from each room's layout
	 * @protected
	 */
	addRooms: function() {

		//Loop through each room in the list
		for(var i = 0; i < this.rooms.length; i++) {

			//Loop through every horizontal row
			for(var x = this.rooms[i].x1; x < this.rooms[i].x2; x++) {

				//What is the current Y position in the layout of the current room
				var layoutXPos = this.rooms[i].x2 - x - 1;

				//Loop through every vertical row
				for(var y = this.rooms[i].y1; y < this.rooms[i].y2; y++) {

					//What is the current X position in the layout of the current room
					var layoutYPos = this.rooms[i].y2 - y - 1;

					//Get the current tile object
					var currentTile = this.rooms[i].layout[layoutXPos][layoutYPos];

					//Place the tile that is on the layout on this position on the map
					this.tiles[x][y] = currentTile;

				}

			}

		}

	}

};
<|endoftext|>


<commit_before>/**
 * # transaction
 * Copyright (c)2011, by Branko Vukelic <branko@herdhound.com>
 *
 * @author Branko Vukelic <branko@herdhound.com>
 * @license MIT (see LICENSE)
 */

var config = require('./config');
var DaimyoError = require('./error');
var xmlutils = require('./xmlutils');
var authpost = require('./authpost');
var messages = require('./messages');
var ducttape = require('./ducttape');
var daimyoRecipes = require('./daimyo').recipes;
var debug = config.debug;
var transaction = exports;

var VALID_TRANSACTIONS = ['purchase', 'authorize', 'capture', 'void', 'credit'];

/**
 * ## MAPPINGS
 * *Mappings between Daimyo fields and Samurai node names*
 */
transaction.MAPPINGS = {
  currency: 'currency_code'
};

/**
 * ## transaction.recipes
 * *Recipes for parsing XML data*
 *
 * Recipes are used to parse XML data returned by the Samurai gateway. For more
 * infomration on parsing recipes, see `xmlutils` documentation.
 *
 * The key name of each recipe corresponds to the XML node name.
 *
 * @private
 */
transaction.recipes = {
  transaction: {
    '@': 'transaction',
    reference_id: xmlutils.toString,
    transaction_token: xmlutils.toString,
    created_at: xmlutils.toDate,
    descriptor: xmlutils.toString,
    custom: xmlutils.toString,
    transaction_type: xmlutils.toString,
    amount: xmlutils.toFloat,
    currency_code: xmlutils.toString,
    success: xmlutils.toBool
  },
  paymentMethod: daimyoRecipes.paymentMethod
};

/**
 * ## getTransactionPath(type, [transactionId])
 * *Builds transaction path*
 *
 * @param {String} subpath Subpath of the transaction
 * @param {String} [transactionId] Transaction ID for capture, void and fetch
 */
function getTransactionPath(type, transactionId) {
  var subpath = '/gateways/';
  if (transactionId) {
    subpath = '/transactions/';
  }
  return subpath + (transactionId || config.option('processorId')) + '/' +
    type + '.xml';
}

/**
 * ## transaction.Transaction(opts)
 * *Low-level transaction object*
 *
 * Options for the transaction object are:
 *
 *  + _type_: Transaction type
 *  + _data_: Transaction data
 *  + _[transactionId]_: (optional) Transaction ID
 *
 * Note that the `Transaction` constructor is not meant to be used directly.
 * However, if you find that other higher-level specialized constructors do
 * not perform the kind of transaction you are looking for, you can use the
 * generic `Transaction` constructor to make the transactions.
 *
 * To use the generic constructor, supply the type of the transaction (it
 * should be named after the request URI component that identifies the
 * transaction type (e.g, if the URI ends in `/credit.xml`, the transaction
 * type is `credit`), and the `transactionId` option as necessary. The data
 * option should be an object that contains key-value mappings such that
 * each key corresponds to an XML node of the request payload.
 *
 * When naming the keys, feel free to use camel-case names, as those will get
 * decamelized prior to XML conversion. For example if the node is called
 * `payment_method_token`, you may call it either that, or
 * `paymentMethodToken`. Either way will work just fine (if it doesn't, file
 * a bug, please).
 *
 * @param {Object} opts Transaction options
 * @constructor
 */
transaction.Transaction = function(opts) {
  // opts are required
  if (!opts) {
    throw new DaimyoError('system', 'Missing options object', null);
  }
  // opts.type are required
  if (!opts.type || VALID_TRANSACTIONS.indexOf(opts.type) < 0) {
    throw new DaimyoError('system', 'Missing or invalid transaction type', null);
  }
  // opts.data are required
  if (!opts.data) {
    throw new DaimyoError('system', 'Missing payload data');
  }

  // Make data and path tamper-free properties
  ducttape.addOneTimeAccessor(this, 'data');
  ducttape.addOneTimeAccessor(this, 'path');

  // Some defaults for complex transactions
  if (!opts.transactionId) {
    opts.data.type = opts.type;
    opts.data.currency = opts.data.currency || config.option('currency');
  }

  this.data = opts.data;
  this.path = getTransactionPath(opts.type, opts.transactionId);

  // Add methods to remember and check the response validation hash
  (function(self, ducttape) {
    var hash;

    // Remember the hash (works only the first time)
    self.rememberHash = function(val) {
      if (!hash) {
        hash = val;
      }
    };

    // Compare given value to the remembered hash
    self.checkHash = function(val) {

      // Always fail if no hash is remembered
      if (!hash) { return false; }

      return val === hash;
    };

  }(this, ducttape));

};

/**
 * ## transaction.Transaction._loadFromResponse(xml, token)
 * *Loads transaction and payment details from XML response*
 *
 * This method returns a boolean flag that signifies the success status.
 * This method will return `false` for any sort of integrity check. It
 * basically means that the gateway's response is invalid. In 100% of cases,
 * this should indicate that the data has been tampered with (unless there
 * is an undiscovered flaw in Daimyo itself).
 *
 * @param {String} xml XML response data
 * @param {Object} card Payment method used for this transaction
 * @return {Boolean} Success status
 * @private
 */
transaction.Transaction.prototype._loadFromResponse = function(xml, card) {
  var self = this;
  var transData = xmlutils.extractData(xml, transaction.recipes.transaction);
  var methodData = xmlutils.extractData(xml, transaction.recipes.paymentMethod);
  var customData;

  if (methodData.payment_method_token !== card.token) {
    return false;
  }

  if (transData.transaction_type.toLowerCase() !== self.data.type) {
    return false;
  }

  // Load transaction information into receipt property
  self.receipt = {};

  // Parse custom data (it should be a JSON string)
  if (transData.custom) {
    try {
      // Parse custom data and remove the check token
      customData = JSON.parse(transData.custom);

      // Return early if response validation fails
      if (!customData._check || !self.checkHash(customData._check)) {
        return false;
      }

      if (customData.hasOwnProperty('_check')) {
        delete customData._check;
      }

      // Assign custom data to receipt.custom
      self.receipt.custom = customData;

    } catch(err1) { /* Fail silently */ }
  }

  self.receipt.referenceId = transData.reference_id;
  self.receipt.transactionId = transData.transaction_token;
  self.receipt.createdAt = transData.created_at;
  self.receipt.descriptor = transData.descriptor;
  self.receipt.type = transData.transaction_type.toLowerCase();
  self.receipt.amount = transData.amount;
  self.receipt.currency = transData.currency_code;
  self.receipt.success = transData.success;

  // Update the card object from payment method response information
  card.method = {};
  card.method.valid = methodData.is_sensitive_data_valid;
  card.method.updatedAt = methodData.updated_at;
  card.method.createdAt = methodData.created_at;
  card.method.retained = methodData.is_retained;
  card.method.redacted = methodData.is_redacted;
  card.last4 = methodData.last_four_digits;
  card.issuer = methodData.card_type;
  card.year = methodData.expiry_year;
  card.month = methodData.expiry_month;
  card.firstName = methodData.first_name;
  card.lastName = methodData.last_name;
  card.address1 = methodData.address_1;
  card.address2 = methodData.address_2;
  card.city = methodData.city;
  card.state = methodData.state;
  card.zip = methodData.zip;
  card.country = methodData.country;

  // Parse card's custom data
  if (methodData.custom) {
    try {
      card.custom = JSON.parse(methodData.custom);
    } catch (err2) { /* Fail silently */ }
  }

  return true;
};

/**
 * ## transaction.Transaction.process(card, callback)
 * *Process the transaction using the given card*
 *
 * After a transaction is processed, the transaction object gains one new
 * property, `receipt`, which contains useful details on the status of the
 * transaction:
 *
 *  + _referenceId_: reference ID (this is not the transaction ID)
 *  + _transactionId_: this token can be used later to void or credit
 *  + _cretedAt_: time the transaction took place
 *  + _descriptor_: if gateway supports descriptors, it will be given here
 *  + _custom_: any custom fields you have set
 *  + _type_: transaction type (this should match the original transaction
 *    type)
 *  + _amount_: amount in the transaction (this may differ from original
 *    amount due to rounding errors; you should make sure this is correct)
 *  + _currency_: currency used in the transaction
 *  + _success_: boolean success flag (`true` if all went well)
 *
 * The transaction object will also gain a property `messages` which will
 * contain any messages generated by the gateway. In case of a successful
 * transaction, A message will be returned for the field 'transaction', which
 * will read 'Success'. Other messages are assigned to individual fields for
 * which there were any errors.
 *
 * The card object used for the transaction will also be update after
 * processing a transaction. The card will gain the method property, and
 * have all its fields populated with data from the gateway. This is
 * effectively like doing a ``card.load()``. Refer to documentaiton for the
 * ``daimyo.Card.load()`` method.
 *
 * @param {daimyo.Card} card Payment method to use for the transaction
 */
transaction.Transaction.prototype.process = function(card, callback) {
  var self = this;
  var transactionData;

  if (!card || !card.token) {
    callback(new DaimyoError('system', 'Card has no token', null));
    return;
  }

  // Augment transaction data with token
  transactionData = self.data;

  // Currency check
  if (transactionData.currency &&
      config.option('allowedCurrencies').indexOf(transactionData.currency) < 0) {

    callback(new DaimyoError(
      'system',
      'Currency not allowed',
      transactionData.currency
    ));
    return;

  }

  if (!transactionData.custom) {
    transactionData.custom = {};
  }

  // Add response validation hash and remember it
  transactionData.custom._check = ducttape.randomHash();
  self.rememberHash(transactionData.custom._check);

  // JSONify custom field
  try {
    transactionData.custom = JSON.stringify(transactionData.custom);
  } catch(e) {
    // If JSONification failes, remove the custom data completely
    delete transactionData.custom;
  }

  transactionData.paymentMethodToken = card.token;
  transactionData = xmlutils.toSamurai(transactionData, transaction.MAPPINGS);

  authpost.makeRequest({
    path: self.path,
    payload: xmlutils.toXML(transactionData, 'transaction'),
    method: 'POST'
  }, function(err, res) {
    // Error handling

    if (err && err.category === 'system') {
      callback(err);
      return;
    }

    if (res.status !== 200) {
      callback(new DaimyoError(
        'system',
        'Gateway responded with non-200 status',
        {status: res.status, body: res.body, messages: messages.translateAll(err.details)}
      ));
      return;
    }

    // This should always be true unless there were system errors
    if (err && err.category == 'gateway') {
      self.messages = messages.translateAll(err.details, 'en_US');
    }

    // Load transaction data and payment method data
    if (!self._loadFromResponse(res.body, card)) {
      callback(new DaimyoError(
        'transaction',
        'Request data does not match the response data',
        null
      ));
    }

    // Exit with no error
    callback(null);
  });

};
<commit_msg>Added customerReference and billingReference to transaction.receipt, and removed the obsolete (or missing?) success property.<commit_after>/**
 * # transaction
 * Copyright (c)2011, by Branko Vukelic <branko@herdhound.com>
 *
 * @author Branko Vukelic <branko@herdhound.com>
 * @license MIT (see LICENSE)
 */

var config = require('./config');
var DaimyoError = require('./error');
var xmlutils = require('./xmlutils');
var authpost = require('./authpost');
var messages = require('./messages');
var ducttape = require('./ducttape');
var daimyoRecipes = require('./daimyo').recipes;
var debug = config.debug;
var transaction = exports;

var VALID_TRANSACTIONS = ['purchase', 'authorize', 'capture', 'void', 'credit'];

/**
 * ## MAPPINGS
 * *Mappings between Daimyo fields and Samurai node names*
 */
transaction.MAPPINGS = {
  currency: 'currency_code'
};

/**
 * ## transaction.recipes
 * *Recipes for parsing XML data*
 *
 * Recipes are used to parse XML data returned by the Samurai gateway. For more
 * infomration on parsing recipes, see `xmlutils` documentation.
 *
 * The key name of each recipe corresponds to the XML node name.
 *
 * @private
 */
transaction.recipes = {
  transaction: {
    '@': 'transaction',
    reference_id: xmlutils.toString,
    transaction_token: xmlutils.toString,
    created_at: xmlutils.toDate,
    descriptor: xmlutils.toString,
    custom: xmlutils.toString,
    billing_reference: xmlutils.toString,
    customer_reference: xmlutils.toString,
    transaction_type: xmlutils.toString,
    amount: xmlutils.toFloat,
    currency_code: xmlutils.toString,
    processor_token: xmlutils.toString,
    success: xmlutils.toBool
  },
  paymentMethod: daimyoRecipes.paymentMethod
};

/**
 * ## getTransactionPath(type, [transactionId])
 * *Builds transaction path*
 *
 * @param {String} subpath Subpath of the transaction
 * @param {String} [transactionId] Transaction ID for capture, void and fetch
 */
function getTransactionPath(type, transactionId) {
  var subpath = '/gateways/';
  if (transactionId) {
    subpath = '/transactions/';
  }
  return subpath + (transactionId || config.option('processorId')) + '/' +
    type + '.xml';
}

/**
 * ## transaction.Transaction(opts)
 * *Low-level transaction object*
 *
 * Options for the transaction object are:
 *
 *  + _type_: Transaction type
 *  + _data_: Transaction data
 *  + _[transactionId]_: (optional) Transaction ID
 *
 * Note that the `Transaction` constructor is not meant to be used directly.
 * However, if you find that other higher-level specialized constructors do
 * not perform the kind of transaction you are looking for, you can use the
 * generic `Transaction` constructor to make the transactions.
 *
 * To use the generic constructor, supply the type of the transaction (it
 * should be named after the request URI component that identifies the
 * transaction type (e.g, if the URI ends in `/credit.xml`, the transaction
 * type is `credit`), and the `transactionId` option as necessary. The data
 * option should be an object that contains key-value mappings such that
 * each key corresponds to an XML node of the request payload.
 *
 * When naming the keys, feel free to use camel-case names, as those will get
 * decamelized prior to XML conversion. For example if the node is called
 * `payment_method_token`, you may call it either that, or
 * `paymentMethodToken`. Either way will work just fine (if it doesn't, file
 * a bug, please).
 *
 * @param {Object} opts Transaction options
 * @constructor
 */
transaction.Transaction = function(opts) {
  // opts are required
  if (!opts) {
    throw new DaimyoError('system', 'Missing options object', null);
  }
  // opts.type are required
  if (!opts.type || VALID_TRANSACTIONS.indexOf(opts.type) < 0) {
    throw new DaimyoError('system', 'Missing or invalid transaction type', null);
  }
  // opts.data are required
  if (!opts.data) {
    throw new DaimyoError('system', 'Missing payload data');
  }

  // Make data and path tamper-free properties
  ducttape.addOneTimeAccessor(this, 'data');
  ducttape.addOneTimeAccessor(this, 'path');

  // Some defaults for complex transactions
  if (!opts.transactionId) {
    opts.data.type = opts.type;
    opts.data.currency = opts.data.currency || config.option('currency');
  }

  this.data = opts.data;
  this.path = getTransactionPath(opts.type, opts.transactionId);

  // Add methods to remember and check the response validation hash
  (function(self, ducttape) {
    var hash;

    // Remember the hash (works only the first time)
    self.rememberHash = function(val) {
      if (!hash) {
        hash = val;
      }
    };

    // Compare given value to the remembered hash
    self.checkHash = function(val) {

      // Always fail if no hash is remembered
      if (!hash) { return false; }

      return val === hash;
    };

  }(this, ducttape));

};

/**
 * ## transaction.Transaction._loadFromResponse(xml, token)
 * *Loads transaction and payment details from XML response*
 *
 * This method returns a boolean flag that signifies the success status.
 * This method will return `false` for any sort of integrity check. It
 * basically means that the gateway's response is invalid. In 100% of cases,
 * this should indicate that the data has been tampered with (unless there
 * is an undiscovered flaw in Daimyo itself).
 *
 * @param {String} xml XML response data
 * @param {Object} card Payment method used for this transaction
 * @return {Boolean} Success status
 * @private
 */
transaction.Transaction.prototype._loadFromResponse = function(xml, card) {
  var self = this;
  var transData = xmlutils.extractData(xml, transaction.recipes.transaction);
  var methodData = xmlutils.extractData(xml, transaction.recipes.paymentMethod);
  var customData;

  if (methodData.payment_method_token !== card.token) {
    return false;
  }

  if (transData.transaction_type.toLowerCase() !== self.data.type) {
    return false;
  }

  // Load transaction information into receipt property
  self.receipt = {};

  // Parse custom data (it should be a JSON string)
  if (transData.custom) {
    try {
      // Parse custom data and remove the check token
      customData = JSON.parse(transData.custom);

      // Return early if response validation fails
      if (!customData._check || !self.checkHash(customData._check)) {
        return false;
      }

      if (customData.hasOwnProperty('_check')) {
        delete customData._check;
      }

      // Assign custom data to receipt.custom
      self.receipt.custom = customData;

    } catch(err1) { /* Fail silently */ }
  }

  self.receipt.referenceId = transData.reference_id;
  self.receipt.transactionId = transData.transaction_token;
  self.receipt.createdAt = transData.created_at;
  self.receipt.descriptor = transData.descriptor;
  self.receipt.type = transData.transaction_type.toLowerCase();
  self.receipt.amount = transData.amount;
  self.receipt.currency = transData.currency_code;
  self.receipt.customerReference = transData.customer_reference;
  self.receipt.billingReference = transData.billing_reference;

  // Update the card object from payment method response information
  card.method = {};
  card.method.valid = methodData.is_sensitive_data_valid;
  card.method.updatedAt = methodData.updated_at;
  card.method.createdAt = methodData.created_at;
  card.method.retained = methodData.is_retained;
  card.method.redacted = methodData.is_redacted;
  card.last4 = methodData.last_four_digits;
  card.issuer = methodData.card_type;
  card.year = methodData.expiry_year;
  card.month = methodData.expiry_month;
  card.firstName = methodData.first_name;
  card.lastName = methodData.last_name;
  card.address1 = methodData.address_1;
  card.address2 = methodData.address_2;
  card.city = methodData.city;
  card.state = methodData.state;
  card.zip = methodData.zip;
  card.country = methodData.country;

  // Parse card's custom data
  if (methodData.custom) {
    try {
      card.custom = JSON.parse(methodData.custom);
    } catch (err2) { /* Fail silently */ }
  }

  return true;
};

/**
 * ## transaction.Transaction.process(card, callback)
 * *Process the transaction using the given card*
 *
 * After a transaction is processed, the transaction object gains one new
 * property, `receipt`, which contains useful details on the status of the
 * transaction:
 *
 *  + _referenceId_: reference ID (this is not the transaction ID)
 *  + _transactionId_: this token can be used later to void or credit
 *  + _cretedAt_: time the transaction took place
 *  + _descriptor_: if gateway supports descriptors, it will be given here
 *  + _custom_: any custom fields you have set
 *  + _type_: transaction type (this should match the original transaction
 *    type)
 *  + _amount_: amount in the transaction (this may differ from original
 *    amount due to rounding errors; you should make sure this is correct)
 *  + _currency_: currency used in the transaction
 *  + _success_: boolean success flag (`true` if all went well)
 *
 * The transaction object will also gain a property `messages` which will
 * contain any messages generated by the gateway. In case of a successful
 * transaction, A message will be returned for the field 'transaction', which
 * will read 'Success'. Other messages are assigned to individual fields for
 * which there were any errors.
 *
 * The card object used for the transaction will also be update after
 * processing a transaction. The card will gain the method property, and
 * have all its fields populated with data from the gateway. This is
 * effectively like doing a ``card.load()``. Refer to documentaiton for the
 * ``daimyo.Card.load()`` method.
 *
 * @param {daimyo.Card} card Payment method to use for the transaction
 */
transaction.Transaction.prototype.process = function(card, callback) {
  var self = this;
  var transactionData;

  if (!card || !card.token) {
    callback(new DaimyoError('system', 'Card has no token', null));
    return;
  }

  // Augment transaction data with token
  transactionData = self.data;

  // Currency check
  if (transactionData.currency &&
      config.option('allowedCurrencies').indexOf(transactionData.currency) < 0) {

    callback(new DaimyoError(
      'system',
      'Currency not allowed',
      transactionData.currency
    ));
    return;

  }

  if (!transactionData.custom) {
    transactionData.custom = {};
  }

  // Add response validation hash and remember it
  transactionData.custom._check = ducttape.randomHash();
  self.rememberHash(transactionData.custom._check);

  // JSONify custom field
  try {
    transactionData.custom = JSON.stringify(transactionData.custom);
  } catch(e) {
    // If JSONification failes, remove the custom data completely
    delete transactionData.custom;
  }

  transactionData.paymentMethodToken = card.token;
  transactionData = xmlutils.toSamurai(transactionData, transaction.MAPPINGS);

  authpost.makeRequest({
    path: self.path,
    payload: xmlutils.toXML(transactionData, 'transaction'),
    method: 'POST'
  }, function(err, res) {
    // Error handling

    if (err && err.category === 'system') {
      callback(err);
      return;
    }

    if (res.status !== 200) {
      callback(new DaimyoError(
        'system',
        'Gateway responded with non-200 status',
        {status: res.status, body: res.body, messages: messages.translateAll(err.details)}
      ));
      return;
    }

    // This should always be true unless there were system errors
    if (err && err.category == 'gateway') {
      self.messages = messages.translateAll(err.details, 'en_US');
    }

    // Load transaction data and payment method data
    if (!self._loadFromResponse(res.body, card)) {
      callback(new DaimyoError(
        'transaction',
        'Request data does not match the response data',
        null
      ));
    }

    // FIXME: Find out the right API for finding the success status

    // Exit with no error
    callback(null);
  });

};
<|endoftext|>


<commit_before>import React, {Component} from 'react';

class HotelsIndv extends Component {
    showHotel(){

    }
    render(){
        return (

{this.props.name.length > 20 ? this.props.name.slice(0,20) + '...' : this.props.name}

{this.props.rate}

        );
    }
}

export default HotelsIndv;<commit_msg>added callback<commit_after>import React, {Component} from 'react';

class HotelsIndv extends Component {

    render(){
        return (

{this.props.name.length > 20 ? this.props.name.slice(0,20) + '...' : this.props.name}

{this.props.rate}

        );
    }
}

export default HotelsIndv;<|endoftext|>