<commit_before>"use strict";

var adapters = ['http-1', 'local-1'];
var qunit = module;

if (typeof module !== undefined && module.exports) {
  this.Pouch = require('../src/pouch.js');
  this.LevelPouch = require('../src/adapters/pouch.leveldb.js');
  this.utils = require('./test.utils.js');

  for (var k in this.utils) {
    global[k] = global[k] || this.utils[k];
  }
  adapters = ['http-1', 'leveldb-1']
  qunit = QUnit.module;
}

adapters.map(function(adapter) {

  qunit("basics: " + adapter, {
    setup: function() {
      this.name = generateAdapterUrl(adapter);
    },
    teardown: function() {
      if (!PERSIST_DATABASES) {
        Pouch.destroy(this.name);
      }
    }
  });

  asyncTest("Create a pouch", 1, function() {
    initTestDB(this.name, function(err, db) {
      ok(!err, 'created a pouch');
      start();
    });
  });

  asyncTest("Remove a pouch", 1, function() {
    var name = this.name;
    initTestDB(name, function(err, db) {
      Pouch.destroy(name, function(err, db) {
        ok(!err);
        start();
      });
    });
  });

  asyncTest("Add a doc", 2, function() {
    initTestDB(this.name, function(err, db) {
      ok(!err, 'opened the pouch');
      db.post({test:"somestuff"}, function (err, info) {
        ok(!err, 'saved a doc with post');
        start();
      });
    });
  });

  asyncTest("Modify a doc", 3, function() {
    console.info('testing: Modify a doc');
    initTestDB(this.name, function(err, db) {
      ok(!err, 'opened the pouch');
      db.post({test: "somestuff"}, function (err, info) {
        ok(!err, 'saved a doc with post');
        db.put({_id: info.id, _rev: info.rev, another: 'test'}, function(err, info2) {
          ok(!err && info2.rev !== info._rev, 'updated a doc with put');
          start();
        });
      });
    });
  });

  asyncTest("Modify a doc with incorrect rev", 3, function() {
    initTestDB(this.name, function(err, db) {
      ok(!err, 'opened the pouch');
      db.post({test: "somestuff"}, function (err, info) {
        ok(!err, 'saved a doc with post');
        var nDoc = {_id: info.id, _rev: info.rev + 'broken', another: 'test'};
        db.put(nDoc, function(err, info2) {
          ok(err, 'put was denied');
          start();
        });
      });
    });
  });

  asyncTest("Get doc", 2, function() {
    initTestDB(this.name, function(err, db) {
      db.post({test:"somestuff"}, function(err, info) {
        db.get(info.id, function(err, doc) {
          ok(doc.test);
          db.get(info.id+'asdf', function(err) {
            ok(err.error);
            start();
          });
        });
      });
    });
  });

  asyncTest("Add a doc with leading underscore in id", function() {
    initTestDB(this.name, function(err, db) {
      db.post({_id: '_testing', value: 42}, function(err, info) {
        ok(err);
        start();
      });
    });
  });

  asyncTest("Get revisions of removed doc", 1, function() {
    initTestDB(this.name, function(err, db) {
      db.post({test:"somestuff"}, function(err, info) {
        var rev = info.rev;
        db.remove({test:"somestuff", _id:info.id, _rev:info.rev}, function(doc) {
          db.get(info.id, {rev: rev}, function(err, doc) {
            ok(!err, 'Recieved deleted doc with rev');
            start();
          });
        });
      });
    });
  });

  asyncTest("Remove doc", 1, function() {
    initTestDB(this.name, function(err, db) {
      db.post({test:"somestuff"}, function(err, info) {
        db.remove({test:"somestuff", _id:info.id, _rev:info.rev}, function(doc) {
          db.get(info.id, function(err) {
            ok(err.error);
            start();
          });
        });
      });
    });
  });

  asyncTest("Remove doc twice with specified id", 4, function() {
    initTestDB(this.name, function(err, db) {
      db.put({_id:"specifiedId", test:"somestuff"}, function(err, info) {
        db.get("specifiedId", function(err, doc) {
          ok(doc.test, "Put and got doc");
          db.remove(doc, function(err, response) {
            ok(!err, "Removed doc");
            db.put({_id:"specifiedId", test:"somestuff2"}, function(err, info) {
              db.get("specifiedId", function(err, doc){
                ok(doc, "Put and got doc again");
                db.remove(doc, function(err, response) {
                  ok(!err, "Removed doc again");
                  start();
                });
              });
            });
          });
        });
      });
    });
  });

  asyncTest("Remove doc, no callback", 1, function() {
    initTestDB(this.name, function(err, db) {
      db.post({test:"somestuff"}, function (err, doc) {
        ok(!err, 'save a doc with post');
        db.remove(doc); // how to test remove with no callback properly?
        start();
      });
    });
  });

  asyncTest("Get design doc", 2, function() {
    initTestDB(this.name, function(err, db) {
      db.put({_id: '_design/someid', test:"somestuff"}, function(err, info) {
        db.get(info.id, function(err, doc) {
          ok(doc.test);
          db.get(info.id+'asdf', function(err) {
            ok(err.error);
            start();
          });
        });
      });
    });
  });

  asyncTest("Delete document without id", 1, function () {
    initTestDB(this.name, function(err, db) {
      db.remove({test:'ing'}, function(err) {
        ok(err, 'failed to delete');
        start();
      });
    });
  });

  asyncTest("Bulk docs", 3, function() {
    initTestDB(this.name, function(err, db) {
      ok(!err, 'opened the pouch');
      db.bulkDocs({docs: [{test:"somestuff"}, {test:"another"}]}, function(err, infos) {
        ok(!infos[0].error);
        ok(!infos[1].error);
        start();
      });
    });
  });

  /*
  asyncTest("Sync a doc", 6, function() {
    var couch = generateAdapterUrl('http-2');
    initTestDB(this.name, function(err, db) {
      ok(!err, 'opened the pouch');
      initTestDB(couch, function(err, db2) {
        ok(!err, 'opened the couch');
        db.put({_id:"adoc", test:"somestuff"}, function (err, info) {
          ok(!err, 'saved a doc with post');
          db.replicate.to(couch, function(err, info) {
            ok(!err, 'replicated pouch to couch');
            db.replicate.from(couch, function(err, info) {
              ok(!err, 'replicated couch back to pouch');
              db.get("adoc", {conflicts:true}, function(err, doc) {
                ok(!doc._conflicts, 'doc has no conflicts');
                start();
              });
            });
          });
        });
      })
    });
  });
  */

  asyncTest("Check revisions", 1, function() {
    initTestDB(this.name, function(err, db) {
      db.post({test: "somestuff"}, function (err, info) {
        db.put({_id: info.id, _rev: info.rev, another: 'test'}, function(err, info) {
          db.put({_id: info.id, _rev: info.rev, a: 'change'}, function(err, info2) {
            db.get(info.id, {revs_info:true}, function(err, doc) {
              ok(doc._revs_info.length === 3, 'updated a doc with put');
              start();
            });
          });
        });
      });
    });
  });

  // From here we are copying over tests from CouchDB
  // https://github.com/apache/couchdb/blob/master/share/www/script/test/basics.js
  /*
  asyncTest("Check database with slashes", 1, function() {
    initTestDB('idb://test_suite_db%2Fwith_slashes', function(err, db) {
      ok(!err, 'opened');
      start();
    });
  });
  */

  asyncTest("Basic checks", 8, function() {
    initTestDB(this.name, function(err, db) {
      db.info(function(err, info) {
        var updateSeq = info.update_seq;
        var doc = {_id: '0', a: 1, b:1};
        ok(info.doc_count === 0);
        db.put(doc, function(err, res) {
          ok(res.ok === true);
          ok(res.id);
          ok(res.rev);
          db.info(function(err, info) {
            ok(info.doc_count === 1);
            equal(info.update_seq, updateSeq + 1, 'update seq incremented');
            db.get(doc._id, function(err, doc) {
              ok(doc._id === res.id && doc._rev === res.rev);
              db.get(doc._id, {revs_info: true}, function(err, doc) {
                ok(doc._revs_info[0].status === 'available');
                start();
              });
            });
          });
        });
      });
    });
  });

  asyncTest("Testing Rev format", 2, function() {
    console.info('testing: Rev format');
    var revs = [];
    initTestDB(this.name, function(err, db) {
      db.post({test: "somestuff"}, function (err, info) {
        revs.unshift(info.rev.split('-')[1]);
        db.put({_id: info.id, _rev: info.rev, another: 'test1'}, function(err, info2) {
          revs.unshift(info2.rev.split('-')[1]);
          db.put({_id: info.id, _rev: info2.rev, last: 'test2'}, function(err, info3) {
            revs.unshift(info3.rev.split('-')[1]);
            db.get(info.id, {revs:true}, function(err, doc) {
              ok(doc._revisions.start === 3, 'correct starting position');
              deepEqual(revs, doc._revisions.ids, 'correct revs returned');
              start();
            });
          });
        });
      });
    });
  });

  asyncTest("Testing issue #48", 1, function() {

    var docs = [{"id":"0"}, {"id":"1"}, {"id":"2"}, {"id":"3"}, {"id":"4"}, {"id":"5"}];
    var x = 0;
    var timer;

    initTestDB(this.name, function(err, db) {
      var save = function() {
        db.bulkDocs({docs: docs}, function(err, res) {
          if (++x === 10) {
            ok(true, 'all updated succedded');
            clearInterval(timer);
            start();
          }
        });
      };
      timer = setInterval(save, 50);
    });
  });

  asyncTest("Testing valid id", 1, function() {
    initTestDB(this.name, function(err, db) {
      db.post({'_id': 123, test: "somestuff"}, function (err, info) {
        ok(err, 'id must be a string');
        start();
      });
    });
  });

  asyncTest("Put doc without _id should fail", 1, function() {
    initTestDB(this.name, function(err, db) {
      db.put({test:"somestuff"}, function(err, info) {
        ok(err, '_id is required');
        start();
      });
    });
  });

  asyncTest("Retrieve old revision", function() {
    initTestDB(this.name, function(err, db) {
      ok(!err, 'opened the pouch');
      db.post({version: "first"}, function (err, info) {
        var firstrev = info.rev;
        ok(!err, 'saved a doc with post');
        db.put({_id: info.id, _rev: info.rev, version: 'second'}, function(err, info2) {
          ok(!err && info2.rev !== info._rev, 'updated a doc with put');
          db.get(info.id, {rev: info.rev}, function(err, oldRev) {
            equal(oldRev.version, 'first', 'Fetched old revision');
            start();
          });
        });
      });
    });
  });

  asyncTest('update_seq persists', 2, function() {
    var name = this.name;
    initTestDB(name, function(err, db) {
      db.post({test:"somestuff"}, function (err, info) {
        Pouch(name, function(err, db) {
          db.info(function(err, info) {
            equal(info.update_seq, 1, 'Update seq persisted');
            equal(info.doc_count, 1, 'Doc Count persists');
            start();
          });
        });
      });
    });
  });
});
<commit_msg>Fix no callback remove test.<commit_after>"use strict";

var adapters = ['http-1', 'local-1'];
var qunit = module;

if (typeof module !== undefined && module.exports) {
  this.Pouch = require('../src/pouch.js');
  this.LevelPouch = require('../src/adapters/pouch.leveldb.js');
  this.utils = require('./test.utils.js');

  for (var k in this.utils) {
    global[k] = global[k] || this.utils[k];
  }
  adapters = ['http-1', 'leveldb-1']
  qunit = QUnit.module;
}

adapters.map(function(adapter) {

  qunit("basics: " + adapter, {
    setup: function() {
      this.name = generateAdapterUrl(adapter);
    },
    teardown: function() {
      if (!PERSIST_DATABASES) {
        Pouch.destroy(this.name);
      }
    }
  });

  asyncTest("Create a pouch", 1, function() {
    initTestDB(this.name, function(err, db) {
      ok(!err, 'created a pouch');
      start();
    });
  });

  asyncTest("Remove a pouch", 1, function() {
    var name = this.name;
    initTestDB(name, function(err, db) {
      Pouch.destroy(name, function(err, db) {
        ok(!err);
        start();
      });
    });
  });

  asyncTest("Add a doc", 2, function() {
    initTestDB(this.name, function(err, db) {
      ok(!err, 'opened the pouch');
      db.post({test:"somestuff"}, function (err, info) {
        ok(!err, 'saved a doc with post');
        start();
      });
    });
  });

  asyncTest("Modify a doc", 3, function() {
    console.info('testing: Modify a doc');
    initTestDB(this.name, function(err, db) {
      ok(!err, 'opened the pouch');
      db.post({test: "somestuff"}, function (err, info) {
        ok(!err, 'saved a doc with post');
        db.put({_id: info.id, _rev: info.rev, another: 'test'}, function(err, info2) {
          ok(!err && info2.rev !== info._rev, 'updated a doc with put');
          start();
        });
      });
    });
  });

  asyncTest("Modify a doc with incorrect rev", 3, function() {
    initTestDB(this.name, function(err, db) {
      ok(!err, 'opened the pouch');
      db.post({test: "somestuff"}, function (err, info) {
        ok(!err, 'saved a doc with post');
        var nDoc = {_id: info.id, _rev: info.rev + 'broken', another: 'test'};
        db.put(nDoc, function(err, info2) {
          ok(err, 'put was denied');
          start();
        });
      });
    });
  });

  asyncTest("Get doc", 2, function() {
    initTestDB(this.name, function(err, db) {
      db.post({test:"somestuff"}, function(err, info) {
        db.get(info.id, function(err, doc) {
          ok(doc.test);
          db.get(info.id+'asdf', function(err) {
            ok(err.error);
            start();
          });
        });
      });
    });
  });

  asyncTest("Add a doc with leading underscore in id", function() {
    initTestDB(this.name, function(err, db) {
      db.post({_id: '_testing', value: 42}, function(err, info) {
        ok(err);
        start();
      });
    });
  });

  asyncTest("Get revisions of removed doc", 1, function() {
    initTestDB(this.name, function(err, db) {
      db.post({test:"somestuff"}, function(err, info) {
        var rev = info.rev;
        db.remove({test:"somestuff", _id:info.id, _rev:info.rev}, function(doc) {
          db.get(info.id, {rev: rev}, function(err, doc) {
            ok(!err, 'Recieved deleted doc with rev');
            start();
          });
        });
      });
    });
  });

  asyncTest("Remove doc", 1, function() {
    initTestDB(this.name, function(err, db) {
      db.post({test:"somestuff"}, function(err, info) {
        db.remove({test:"somestuff", _id:info.id, _rev:info.rev}, function(doc) {
          db.get(info.id, function(err) {
            ok(err.error);
            start();
          });
        });
      });
    });
  });

  asyncTest("Remove doc twice with specified id", 4, function() {
    initTestDB(this.name, function(err, db) {
      db.put({_id:"specifiedId", test:"somestuff"}, function(err, info) {
        db.get("specifiedId", function(err, doc) {
          ok(doc.test, "Put and got doc");
          db.remove(doc, function(err, response) {
            ok(!err, "Removed doc");
            db.put({_id:"specifiedId", test:"somestuff2"}, function(err, info) {
              db.get("specifiedId", function(err, doc){
                ok(doc, "Put and got doc again");
                db.remove(doc, function(err, response) {
                  ok(!err, "Removed doc again");
                  start();
                });
              });
            });
          });
        });
      });
    });
  });

  asyncTest("Remove doc, no callback", 2, function() {
    initTestDB(this.name, function(err, db) {
      db.post({_id:"somestuff"}, function (err, res) {
        ok(!err, 'save a doc with post');
        db.changes({
          continuous: true,
          include_docs: true,
          onChange: function(change){
            if(change.seq == 2){
              ok(change.doc._deleted, 'Doc deleted properly');
              start();
            }
          }
        });
        db.remove({_id: res.id, _rev: res.rev});
      });
    });
  });

  asyncTest("Get design doc", 2, function() {
    initTestDB(this.name, function(err, db) {
      db.put({_id: '_design/someid', test:"somestuff"}, function(err, info) {
        db.get(info.id, function(err, doc) {
          ok(doc.test);
          db.get(info.id+'asdf', function(err) {
            ok(err.error);
            start();
          });
        });
      });
    });
  });

  asyncTest("Delete document without id", 1, function () {
    initTestDB(this.name, function(err, db) {
      db.remove({test:'ing'}, function(err) {
        ok(err, 'failed to delete');
        start();
      });
    });
  });

  asyncTest("Bulk docs", 3, function() {
    initTestDB(this.name, function(err, db) {
      ok(!err, 'opened the pouch');
      db.bulkDocs({docs: [{test:"somestuff"}, {test:"another"}]}, function(err, infos) {
        ok(!infos[0].error);
        ok(!infos[1].error);
        start();
      });
    });
  });

  /*
  asyncTest("Sync a doc", 6, function() {
    var couch = generateAdapterUrl('http-2');
    initTestDB(this.name, function(err, db) {
      ok(!err, 'opened the pouch');
      initTestDB(couch, function(err, db2) {
        ok(!err, 'opened the couch');
        db.put({_id:"adoc", test:"somestuff"}, function (err, info) {
          ok(!err, 'saved a doc with post');
          db.replicate.to(couch, function(err, info) {
            ok(!err, 'replicated pouch to couch');
            db.replicate.from(couch, function(err, info) {
              ok(!err, 'replicated couch back to pouch');
              db.get("adoc", {conflicts:true}, function(err, doc) {
                ok(!doc._conflicts, 'doc has no conflicts');
                start();
              });
            });
          });
        });
      })
    });
  });
  */

  asyncTest("Check revisions", 1, function() {
    initTestDB(this.name, function(err, db) {
      db.post({test: "somestuff"}, function (err, info) {
        db.put({_id: info.id, _rev: info.rev, another: 'test'}, function(err, info) {
          db.put({_id: info.id, _rev: info.rev, a: 'change'}, function(err, info2) {
            db.get(info.id, {revs_info:true}, function(err, doc) {
              ok(doc._revs_info.length === 3, 'updated a doc with put');
              start();
            });
          });
        });
      });
    });
  });

  // From here we are copying over tests from CouchDB
  // https://github.com/apache/couchdb/blob/master/share/www/script/test/basics.js
  /*
  asyncTest("Check database with slashes", 1, function() {
    initTestDB('idb://test_suite_db%2Fwith_slashes', function(err, db) {
      ok(!err, 'opened');
      start();
    });
  });
  */

  asyncTest("Basic checks", 8, function() {
    initTestDB(this.name, function(err, db) {
      db.info(function(err, info) {
        var updateSeq = info.update_seq;
        var doc = {_id: '0', a: 1, b:1};
        ok(info.doc_count === 0);
        db.put(doc, function(err, res) {
          ok(res.ok === true);
          ok(res.id);
          ok(res.rev);
          db.info(function(err, info) {
            ok(info.doc_count === 1);
            equal(info.update_seq, updateSeq + 1, 'update seq incremented');
            db.get(doc._id, function(err, doc) {
              ok(doc._id === res.id && doc._rev === res.rev);
              db.get(doc._id, {revs_info: true}, function(err, doc) {
                ok(doc._revs_info[0].status === 'available');
                start();
              });
            });
          });
        });
      });
    });
  });

  asyncTest("Testing Rev format", 2, function() {
    console.info('testing: Rev format');
    var revs = [];
    initTestDB(this.name, function(err, db) {
      db.post({test: "somestuff"}, function (err, info) {
        revs.unshift(info.rev.split('-')[1]);
        db.put({_id: info.id, _rev: info.rev, another: 'test1'}, function(err, info2) {
          revs.unshift(info2.rev.split('-')[1]);
          db.put({_id: info.id, _rev: info2.rev, last: 'test2'}, function(err, info3) {
            revs.unshift(info3.rev.split('-')[1]);
            db.get(info.id, {revs:true}, function(err, doc) {
              ok(doc._revisions.start === 3, 'correct starting position');
              deepEqual(revs, doc._revisions.ids, 'correct revs returned');
              start();
            });
          });
        });
      });
    });
  });

  asyncTest("Testing issue #48", 1, function() {

    var docs = [{"id":"0"}, {"id":"1"}, {"id":"2"}, {"id":"3"}, {"id":"4"}, {"id":"5"}];
    var x = 0;
    var timer;

    initTestDB(this.name, function(err, db) {
      var save = function() {
        db.bulkDocs({docs: docs}, function(err, res) {
          if (++x === 10) {
            ok(true, 'all updated succedded');
            clearInterval(timer);
            start();
          }
        });
      };
      timer = setInterval(save, 50);
    });
  });

  asyncTest("Testing valid id", 1, function() {
    initTestDB(this.name, function(err, db) {
      db.post({'_id': 123, test: "somestuff"}, function (err, info) {
        ok(err, 'id must be a string');
        start();
      });
    });
  });

  asyncTest("Put doc without _id should fail", 1, function() {
    initTestDB(this.name, function(err, db) {
      db.put({test:"somestuff"}, function(err, info) {
        ok(err, '_id is required');
        start();
      });
    });
  });

  asyncTest("Retrieve old revision", function() {
    initTestDB(this.name, function(err, db) {
      ok(!err, 'opened the pouch');
      db.post({version: "first"}, function (err, info) {
        var firstrev = info.rev;
        ok(!err, 'saved a doc with post');
        db.put({_id: info.id, _rev: info.rev, version: 'second'}, function(err, info2) {
          ok(!err && info2.rev !== info._rev, 'updated a doc with put');
          db.get(info.id, {rev: info.rev}, function(err, oldRev) {
            equal(oldRev.version, 'first', 'Fetched old revision');
            start();
          });
        });
      });
    });
  });

  asyncTest('update_seq persists', 2, function() {
    var name = this.name;
    initTestDB(name, function(err, db) {
      db.post({test:"somestuff"}, function (err, info) {
        Pouch(name, function(err, db) {
          db.info(function(err, info) {
            equal(info.update_seq, 1, 'Update seq persisted');
            equal(info.doc_count, 1, 'Doc Count persists');
            start();
          });
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>const rewiremock = require('rewiremock').default;
const rewire = require('rewire');
const sinon = require('sinon');
const assert = require('chai').assert;

process.env.APIAI_ACCESS_TOKEN = 'demo_access_token';
const apiai = rewire('../src/api-ai');

describe('Testing API.AI', () => {
    // beforeEach( () => rewiremock.enable() );
    it('Test processEvent', async function () {
        const revert = apiai.__set__('getApiAiResponse', async () => {
            return {
                result: {
                    fulfillment: {
                        messages: []
                    }
                }
            };
        });

        let ddd = await apiai.processEvent('demo', 'test_sender_id');
        console.log(ddd);
        revert();
        assert.isTrue(true);
    });
    // afterEach( () => rewiremock.disable() );
});
<commit_msg>first version of api-ai test eventRequest<commit_after>const lodash = require('lodash');
const rewire = require('rewire');
const assert = require('chai').assert;

const EventEmitter = require('events');

class TestEmitter extends EventEmitter {
    end() {
        console.log('End called');
    }
};

process.env.APIAI_ACCESS_TOKEN = 'demo_access_token';
const apiai = rewire('../src/api-ai');

const demoResponse =  {
    result: {
        fulfillment: {
            messages: [
                {
                    type: 0,
                    speech: 'Hello ?'
                }
            ]
        }
    }
};

describe('Testing API.AI', () => {

    it('Test processEvent', async function () {
        const revert = apiai.__set__('getApiAiResponse', async () => {
            return demoResponse;
        });

        const response = await apiai.processEvent('demo', 'test_sender_id');
        console.log(response);
        revert();
        assert.isTrue(true);
    });

    it('Test processEvent with eventRequest', async function () {
        const revert = apiai.__set__('apiAiService.eventRequest', () => {
            const testEmitter = new TestEmitter();
            setTimeout(() => {
                testEmitter.emit('response', demoResponse);
            }, 30);
            return testEmitter;
        });
        let response = await apiai.processEvent('demo', 'test_sender_id');
        revert();
        assert.isOk(lodash.get(response, 'messages'));
        assert.isTrue(lodash.get(lodash.find(response.messages, 'speech'), 'speech') === 'Hello ?');
    });
});
<|endoftext|>


<commit_before>/*
 * The MIT License
 *
 * Copyright 2014 RBC1B.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
$(document).ready(function() {
    var workingSunday = $("#working-sunday").attr("value");
    var startDate = $("#start-date").attr("value");
    var endDate = $("#end-date").attr("value");
    var calEndDate = incrementDate(endDate);

    $("#startDate").append(startDate);
    $("#endDate").append(endDate);

    $('#calendar').fullCalendar({
        header: {
            left: "title"
        },
        events: [
            {
                start: startDate,
                end: calEndDate,
                rendering: 'inverse-background'
            }
        ],
        eventColor: '#F0F0F0',
        dayClick: function(date, jsEvent, view) {
            if (date >= Date.parse(startDate) && date <= Date.parse(endDate)) {
                updateDateMap(date, this);
            }
        }
    });

    $('#calendar').fullCalendar('gotoDate', startDate);
    getExistingAvailableRecord();
    getExistingAttendanceRecords();

    $('#accommodationRequired').on("click", function(event) {
        updateRequirements("accommodationRequired");
    });
    $('#transportRequired').on("click", function(event) {
        updateRequirements("transportRequired");
    });

    $('#offerTransport').on("click", function(event) {
        updateRequirements("offerTransport");
    });

    function updateDateMap(dateClicked, thisObject) {
        if (workingSunday === "false") {
            if (checkIfSunday(dateClicked)) {
                return;
            }
        }
        var dateKey = "[data-date='" + dateClicked.format() + "']";
        var colour = $(dateKey).css('background-color');
        if (colour === "rgba(0, 0, 0, 0)" || colour == "rgb(255, 255, 255)" || colour === "transparent") {
            setAvailabilityDate(dateClicked)
                    .done(function() {
                $(thisObject).css('background-color', 'rgb(255, 255, 0)');
            });
        } else if (colour === "rgb(255, 255, 0)") {
            deleteAvailabilityDate(dateClicked)
                    .done(function() {
                $(thisObject).css('background-color', 'rgba(0,0,0,0');
            });
        } else if (colour === "rgb(0, 128, 0)") {
            alert("Your overseer has confirmed this date - please contact your overseer.");
        } else {
            alert("Unknown status - please contact Edifice.Help@gmail.com");
        }
    }

    function setAvailabilityDate(date) {
        return $.ajax({
            url: window.location.href + "/" + date.format(),
            type: 'POST',
            cache: false,
            error: function(jqXHR, textStatus) {
                alert("Failed to set the date. Status: " + textStatus);
            }
        });
    }

    function deleteAvailabilityDate(date) {
        return $.ajax({
            url: window.location.href + "/" + date.format(),
            type: 'DELETE',
            cache: false,
            error: function(jqXHR, textStatus) {
                alert("Failed to clear the date. Status: " + textStatus);
            }
        });
    }

    function updateRequirements(requirement) {
        $.ajax({
            url: window.location.href + "/" + requirement,
            type: "PUT",
            cache: false,
            error: function(jqXHR, textStatus) {
                alert("Failed to set the value. Status: " + textStatus);
            }
        });
    }

    function getExistingAvailableRecord() {
        return $.ajax({
            url: window.location.href + "/availability",
            type: "GET",
            cache: false,
            success: function(data) {
                if (!data || data.length === 0) {
                    return;
                }
                if (data["transportRequired"] === true) {
                    document.getElementById("transportRequired").checked = true;
                }
                if (data["offerTransport"] === true) {
                    document.getElementById("offerTransport").checked = true;
                }
                if (data["accommodationRequired"] === true) {
                    document.getElementById("accommodationRequired").checked = true;
                }
            }
        });
    }

    function getExistingAttendanceRecords() {
        $.ajax({
            url: window.location.href + "/attendance",
            type: "GET",
            cache: false,
            success: function(data) {
                if (!data || data.length === 0) {
                    return;
                }
                for (var key in data) {
                    var attendanceDate = key;
                    var required = data[attendanceDate];
                    var dateKey = "[data-date='" + attendanceDate + "']";
                    if (required) {
                        $(dateKey).css("background-color", "rgb(0, 128, 0)");
                    } else {
                        $(dateKey).css("background-color", "rgb(255, 255, 0)");
                    }
                }
            }
        });
    }

    function incrementDate(myDate) {
        var newDate = new Date(myDate);
        newDate.setDate(newDate.getDate() + 1);
        var month = newDate.getMonth();
        if (month < 10)
            month = "0" + month;
        var date = newDate.getDate();
        if (date < 10)
            date = "0" + date;
        var dateStr = newDate.getFullYear() + "-" + month + "-" + date;
        return dateStr;
    }

    function checkIfSunday(dateStr) {
        var myDate = new Date(dateStr);
        return (myDate.getDay() === 0);
    }
});

<commit_msg>[#75384126] Added additional OR clauses and message to indicate what the browser returns as the colour when deciding what action to take.<commit_after>/*
 * The MIT License
 *
 * Copyright 2014 RBC1B.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
$(document).ready(function() {
    var workingSunday = $("#working-sunday").attr("value");
    var startDate = $("#start-date").attr("value");
    var endDate = $("#end-date").attr("value");
    var calEndDate = incrementDate(endDate);

    $("#startDate").append(startDate);
    $("#endDate").append(endDate);

    $('#calendar').fullCalendar({
        header: {
            left: "title"
        },
        events: [
            {
                start: startDate,
                end: calEndDate,
                rendering: 'inverse-background'
            }
        ],
        eventColor: '#F0F0F0',
        dayClick: function(date, jsEvent, view) {
            if (date >= Date.parse(startDate) && date <= Date.parse(endDate)) {
                updateDateMap(date, this);
            }
        }
    });

    $('#calendar').fullCalendar('gotoDate', startDate);
    getExistingAvailableRecord();
    getExistingAttendanceRecords();

    $('#accommodationRequired').on("click", function(event) {
        updateRequirements("accommodationRequired");
    });
    $('#transportRequired').on("click", function(event) {
        updateRequirements("transportRequired");
    });

    $('#offerTransport').on("click", function(event) {
        updateRequirements("offerTransport");
    });

    function updateDateMap(dateClicked, thisObject) {
        if (workingSunday === "false") {
            if (checkIfSunday(dateClicked)) {
                return;
            }
        }
        var dateKey = "[data-date='" + dateClicked.format() + "']";
        var colour = $(dateKey).css('background-color');
        if (colour === "rgba(0, 0, 0, 0)" || colour == "rgb(255, 255, 255)" || colour === "rgb(252, 248, 227)" || colour === "transparent") {
            setAvailabilityDate(dateClicked)
                    .done(function() {
                $(thisObject).css('background-color', 'rgb(255, 255, 0)');
            });
        } else if (colour === "rgb(255, 255, 0)") {
            deleteAvailabilityDate(dateClicked)
                    .done(function() {
                $(thisObject).css('background-color', 'rgba(0,0,0,0');
            });
        } else if (colour === "rgb(0, 128, 0)") {
            alert("Your overseer has confirmed this date - please contact your overseer.");
        } else {
            alert("Unknown status - please contact Edifice.Help@gmail.com with the following code: " + colour);
        }
    }

    function setAvailabilityDate(date) {
        return $.ajax({
            url: window.location.href + "/" + date.format(),
            type: 'POST',
            cache: false,
            error: function(jqXHR, textStatus) {
                alert("Failed to set the date. Status: " + textStatus);
            }
        });
    }

    function deleteAvailabilityDate(date) {
        return $.ajax({
            url: window.location.href + "/" + date.format(),
            type: 'DELETE',
            cache: false,
            error: function(jqXHR, textStatus) {
                alert("Failed to clear the date. Status: " + textStatus);
            }
        });
    }

    function updateRequirements(requirement) {
        $.ajax({
            url: window.location.href + "/" + requirement,
            type: "PUT",
            cache: false,
            error: function(jqXHR, textStatus) {
                alert("Failed to set the value. Status: " + textStatus);
            }
        });
    }

    function getExistingAvailableRecord() {
        return $.ajax({
            url: window.location.href + "/availability",
            type: "GET",
            cache: false,
            success: function(data) {
                if (!data || data.length === 0) {
                    return;
                }
                if (data["transportRequired"] === true) {
                    document.getElementById("transportRequired").checked = true;
                }
                if (data["offerTransport"] === true) {
                    document.getElementById("offerTransport").checked = true;
                }
                if (data["accommodationRequired"] === true) {
                    document.getElementById("accommodationRequired").checked = true;
                }
            }
        });
    }

    function getExistingAttendanceRecords() {
        $.ajax({
            url: window.location.href + "/attendance",
            type: "GET",
            cache: false,
            success: function(data) {
                if (!data || data.length === 0) {
                    return;
                }
                for (var key in data) {
                    var attendanceDate = key;
                    var required = data[attendanceDate];
                    var dateKey = "[data-date='" + attendanceDate + "']";
                    if (required) {
                        $(dateKey).css("background-color", "rgb(0, 128, 0)");
                    } else {
                        $(dateKey).css("background-color", "rgb(255, 255, 0)");
                    }
                }
            }
        });
    }

    function incrementDate(myDate) {
        var newDate = new Date(myDate);
        newDate.setDate(newDate.getDate() + 1);
        var month = newDate.getMonth();
        if (month < 10)
            month = "0" + month;
        var date = newDate.getDate();
        if (date < 10)
            date = "0" + date;
        var dateStr = newDate.getFullYear() + "-" + month + "-" + date;
        return dateStr;
    }

    function checkIfSunday(dateStr) {
        var myDate = new Date(dateStr);
        return (myDate.getDay() === 0);
    }
});

<|endoftext|>


<commit_before>function ExportFile (job_id) {
  Job.call(this, job_id);

  this.exportedFile = ExportedFiles.findOne(this.job.args.exported_file_id);
  if (!this.exportedFile) {
    throw "Invalid exported_file_id";
  }
}
ExportFile.prototype = Object.create(Job.prototype);
ExportFile.prototype.constructor = ExportFile;
// Writes the data in the expression file
// Does some cool stuff with promises to buffer writing to the disk.
ExportFile.prototype.writeCopyNumberFile = function (filePath) {
  var self = this;

  var writeStream = fs.createWriteStream(filePath);

  var copyNumberSelector = {
    collaborations: {$in: this.exportedFile.collaborations}
  };

  console.log("copyNumberSelector:", copyNumberSelector);
  var aggregationResult = CopyNumber.aggregate([
      {$match: copyNumberSelector},
      {
        $project: { // equivalent to 'fields' in collection.find
          sample_label: 1,
          gene_label: 1,
        }
      },
      {
        $group: {
          _id: null,
          sampleLabels: {$addToSet: "$sample_label"},
          geneLabels: {$addToSet: "$gene_label"},
        }
      },
    ])[0];
  if (!aggregationResult) {
    throw "no results";
  }
  var sampleLabels = aggregationResult.sampleLabels;
  var geneLabels = aggregationResult.geneLabels;
  sampleLabels.sort();
  geneLabels.sort();

  // write the header line
  writeStream.write('Gene\t');
  _.map(sampleLabels, function(value, key) {
    writeStream.write(value);
    writeStream.write('\t');
  });
  writeStream.write('\n');

  var deferred = Q.defer();
  writeStream.end(deferred.resolve);
  return deferred.promise;

  // // get data for the rest of the file
  // var fields = { gene: 1 };
  // _.each(this.sampleList, function (value, key) {
  //   fields["samples." + key] = value;
  // });
  // var count = 0;
  // var copyNumberCursor = CopyNumber.rawCollection()
  //     .find(copyNumberSelector);
  //
  // // set up helper functions to write the rest of the file
  // //
  // // The reason we need all these functions instead of just calling write a
  // // bunch of times is because when write returns false, it's good practice
  // // to wait for the 'drain' event from the stream, meaning the internal
  // // buffer has been cleared and written to the disk. In practice, not
  // // waiting for this event and calling write many times means that writing
  // // becomes incredibly slow.
  // //
  // // https://nodejs.org/api/stream.html#stream_event_drain
  //
  // // expressionDeferred.resolve will be called when writeNextLine finds
  // // the end of the expression cursor
  // var expressionDeferred = Q.defer();
  //
  // function niceWrite(toWrite) {
  //   var keepWriting = writeStream.write(toWrite);
  //   if (keepWriting) {
  //     // return a promise that has already been resolved
  //     // any .then()s connected to this will fire immidiately
  //     return Q();
  //   }
  //
  //   // waits until the stream has drained, then resolves
  //   return new Q.Promise(function (resolve) {
  //     writeStream.once("drain", resolve);
  //   });
  // }
  //
  // function writeArray(arrayOfStrings) {
  //   // NOTE: The way I'm starting all of the writes here means there could
  //   // be multiple 'drain' events on writeStream. This is not a probelm
  //   // because in this context we're only calling writeArray with less than
  //   // 10 elements in arrayOfStrings.
  //
  //   var arrayPromises = [];
  //   for (var index in arrayOfStrings) {
  //     arrayPromises.push(niceWrite(arrayOfStrings[index]));
  //   }
  //   return Q.all(arrayPromises);
  // }
  //
  // function writeNextLine() {
  //   expressionCursor.nextObject(function (error, expressionDoc) {
  //     // check to see if we've found the end of the cursor
  //     if (!expressionDoc) {
  //       writeStream.end(expressionDeferred.resolve);
  //       return; // don't run the rest of the function
  //     }
  //
  //     // actually write to the file
  //     var toWriteArray = [];
  //     toWriteArray.push(expressionDoc.gene);
  //     toWriteArray.push('\t');
  //     var sampleArray = []; // don't call write more than we need
  //     _.map(expressionDoc.samples, function(value, key) {
  //       if (self.sampleList[key] !== undefined) {
  //         geneExp = value.rsem_quan_log2;
  //         sampleArray.push(geneExp);
  //       }
  //     });
  //     toWriteArray.push(sampleArray.join('\t'));
  //     toWriteArray.push('\n');
  //
  //     // write toWriteArray to the file, then write the next line
  //     writeArray(toWriteArray).then(writeNextLine);
  //   });
  // }
  //
  // // start out the promise-based recursive looping through the cursor
  // writeNextLine();
  //
  // return expressionDeferred.promise;
};
ExportFile.prototype.run = function () {
  var self = this;

  // create paths for files on the disk
  var workDir = ntemp.mkdirSync('RunLimma');
  var copyNumberFilePath = path.join(workDir, 'copy_number_data.tsv');
  console.log('workDir: ', workDir);

  var deferred = Q.defer();
  this.writeCopyNumberFile.call(this, copyNumberFilePath)
    .then(Meteor.bindEnvironment(function () {
      console.log("done writing file!");
      // we did it!
      ExportedFiles.update(self.exportedFile._id, {
        $set: {
          status: "done"
        }
      });

      console.log("about to resolve");
      deferred.resolve();
    }, deferred.reject));

  return deferred.promise;
};
ExportFile.prototype.onError = function (e) {
  ExportedFiles.update(this.job.args.exported_file_id, {
    $set: {
      status: "error",
      error_description: "Error running job: " + e.toString(),
    }
  });
};

JobClasses.ExportFile = ExportFile;
<commit_msg>ExportFile: added blob.metadata.user_id<commit_after>function ExportFile (job_id) {
  Job.call(this, job_id);

  this.exportedFile = ExportedFiles.findOne(this.job.args.exported_file_id);
  if (!this.exportedFile) {
    throw "Invalid exported_file_id";
  }
}
ExportFile.prototype = Object.create(Job.prototype);
ExportFile.prototype.constructor = ExportFile;
// Writes the data in the expression file
// Does some cool stuff with promises to buffer writing to the disk.
ExportFile.prototype.writeCopyNumberFile = function (filePath) {
  var self = this;

  var writeStream = fs.createWriteStream(filePath);

  var copyNumberSelector = {
    collaborations: {$in: this.exportedFile.collaborations}
  };

  console.log("copyNumberSelector:", copyNumberSelector);
  var aggregationResult = CopyNumber.aggregate([
      {$match: copyNumberSelector},
      {
        $project: { // equivalent to 'fields' in collection.find
          sample_label: 1,
          gene_label: 1,
        }
      },
      {
        $group: {
          _id: null,
          sampleLabels: {$addToSet: "$sample_label"},
          geneLabels: {$addToSet: "$gene_label"},
        }
      },
    ])[0];
  if (!aggregationResult) {
    throw "no results";
  }
  var sampleLabels = aggregationResult.sampleLabels;
  var geneLabels = aggregationResult.geneLabels;
  sampleLabels.sort();
  geneLabels.sort();

  // write the header line
  writeStream.write('Gene\t');
  _.map(sampleLabels, function(value, key) {
    writeStream.write(value);
    writeStream.write('\t');
  });
  writeStream.write('\n');

  var deferred = Q.defer();
  writeStream.end(deferred.resolve);
  return deferred.promise;

  // // get data for the rest of the file
  // var fields = { gene: 1 };
  // _.each(this.sampleList, function (value, key) {
  //   fields["samples." + key] = value;
  // });
  // var count = 0;
  // var copyNumberCursor = CopyNumber.rawCollection()
  //     .find(copyNumberSelector);
  //
  // // set up helper functions to write the rest of the file
  // //
  // // The reason we need all these functions instead of just calling write a
  // // bunch of times is because when write returns false, it's good practice
  // // to wait for the 'drain' event from the stream, meaning the internal
  // // buffer has been cleared and written to the disk. In practice, not
  // // waiting for this event and calling write many times means that writing
  // // becomes incredibly slow.
  // //
  // // https://nodejs.org/api/stream.html#stream_event_drain
  //
  // // expressionDeferred.resolve will be called when writeNextLine finds
  // // the end of the expression cursor
  // var expressionDeferred = Q.defer();
  //
  // function niceWrite(toWrite) {
  //   var keepWriting = writeStream.write(toWrite);
  //   if (keepWriting) {
  //     // return a promise that has already been resolved
  //     // any .then()s connected to this will fire immidiately
  //     return Q();
  //   }
  //
  //   // waits until the stream has drained, then resolves
  //   return new Q.Promise(function (resolve) {
  //     writeStream.once("drain", resolve);
  //   });
  // }
  //
  // function writeArray(arrayOfStrings) {
  //   // NOTE: The way I'm starting all of the writes here means there could
  //   // be multiple 'drain' events on writeStream. This is not a probelm
  //   // because in this context we're only calling writeArray with less than
  //   // 10 elements in arrayOfStrings.
  //
  //   var arrayPromises = [];
  //   for (var index in arrayOfStrings) {
  //     arrayPromises.push(niceWrite(arrayOfStrings[index]));
  //   }
  //   return Q.all(arrayPromises);
  // }
  //
  // function writeNextLine() {
  //   expressionCursor.nextObject(function (error, expressionDoc) {
  //     // check to see if we've found the end of the cursor
  //     if (!expressionDoc) {
  //       writeStream.end(expressionDeferred.resolve);
  //       return; // don't run the rest of the function
  //     }
  //
  //     // actually write to the file
  //     var toWriteArray = [];
  //     toWriteArray.push(expressionDoc.gene);
  //     toWriteArray.push('\t');
  //     var sampleArray = []; // don't call write more than we need
  //     _.map(expressionDoc.samples, function(value, key) {
  //       if (self.sampleList[key] !== undefined) {
  //         geneExp = value.rsem_quan_log2;
  //         sampleArray.push(geneExp);
  //       }
  //     });
  //     toWriteArray.push(sampleArray.join('\t'));
  //     toWriteArray.push('\n');
  //
  //     // write toWriteArray to the file, then write the next line
  //     writeArray(toWriteArray).then(writeNextLine);
  //   });
  // }
  //
  // // start out the promise-based recursive looping through the cursor
  // writeNextLine();
  //
  // return expressionDeferred.promise;
};
ExportFile.prototype.run = function () {
  var self = this;

  // create paths for files on the disk
  var workDir = ntemp.mkdirSync('RunLimma');
  var copyNumberFilePath = path.join(workDir, 'copy_number_export.tsv');
  console.log('workDir: ', workDir);

  var deferred = Q.defer();
  this.writeCopyNumberFile.call(this, copyNumberFilePath)
    .then(Meteor.bindEnvironment(function () {
      console.log("done writing file!");

      var blob = Blobs.insert(copyNumberFilePath);
      if (!self.job.user_id) {
        throw "self.job.user_id not set";
      }
      Blobs.update(blob._id, {
        metadata: {
          user_id: self.job.user_id,
        }
      });

      // we did it!
      ExportedFiles.update(self.exportedFile._id, {
        $set: {
          status: "done",
          blob_id: blob._id,
          blob_name: blob.original.name,
        }
      });

      console.log("about to resolve");
      deferred.resolve();
    }, deferred.reject));

  return deferred.promise;
};
ExportFile.prototype.onError = function (e) {
  ExportedFiles.update(this.job.args.exported_file_id, {
    $set: {
      status: "error",
      error_description: "Error running job: " + e.toString(),
    }
  });
};

JobClasses.ExportFile = ExportFile;
<|endoftext|>


<commit_before>import _ from 'lodash'
import Reflux from 'reflux'
import StateMixin from'reflux-state-mixin'
import IndicatorActions from 'actions/IndicatorActions'
import treeify from 'data/transform/treeify'

var IndicatorStore = Reflux.createStore({

  mixins: [StateMixin.store],

  listenables: IndicatorActions,

  indicators: {
    meta: null,
    raw: null,
    index: null,
    filtered: [],
    list: [],
    tree: []
  },

  getInitialState () {
    return this.indicators
  },

  // =========================================================================== //
  //                              API CALL HANDLERS                              //
  // =========================================================================== //

  // ============================  Fetch Indicators  =========================== //
  onFetchIndicators () {
    this.setState({ raw: [] })
  },
  onFetchIndicatorsCompleted (response) {
    console.log('fetching indicators')
    this.indicators.meta = response.meta
    this.indicators.raw = response.objects[0].indicators || response.objects
    this.indicators.filtered = this.indicators.raw
    this.indicators.index = _.indexBy(this.indicators.raw, 'id')
    this.processIndicators()
  },
  onFetchIndicatorsFailed (error) {
    this.setState({ error: error })
  },

  // ===========================  Fetch Indicator Tags ========================= //
  onFetchIndicatorTags () {
    this.setState({ raw: [] })
  },
  onFetchIndicatorTagsCompleted (response) {
    this.indicators.tags = response.objects[0].indicator_tags || response.objects
    this.processIndicators()
  },
  onFetchIndicatorTagsFailed (error) {
    this.setState({ error: error })
  },

  // =========================================================================== //
  //                                   UTILITIES                                 //
  // =========================================================================== //
  processIndicators () {
    if (this.indicators.raw && this.indicators.tags) {
      this.indicators.tree = this.buildIndicatorsTree(this.indicators.raw, this.indicators.tags, true, true)
      this.indicators.list = _.sortBy(this.indicators.tree, 'title')
      this.trigger(this.indicators)
    }
  },

  makeTagId (tId) {
    return 'tag-' + tId
  },

  pickAllNodesInTrees (parent, nodes) {
    let children = parent.children
    if (children && children.length) {
      children.forEach(item => this.pickAllNodesInTrees(item, nodes))
    } else {
      if (parent.noValue) nodes.push(parent)
    }
  },

  removeIndicatorEmptyNode (sourceList) {
    if (!sourceList || !sourceList.length) {
      return sourceList
    }

    let virtualRoot = {noValue: false, parentNode: null, title: 'No Available Indicator', children: sourceList}
    virtualRoot.children.forEach(item => item.parentNode = virtualRoot)

    let nodes
    do {
      nodes = []
      this.pickAllNodesInTrees(virtualRoot, nodes)
      nodes.forEach(item => item.parentNode.children.splice(item.parentNode.children.indexOf(item), 1))
    } while (nodes.length > 0)

    if (sourceList.length > 0) {
      return sourceList
    } else {
      virtualRoot.noValue = true
      virtualRoot.children = []
      return [virtualRoot]
    }
  },

  buildIndicatorsTree (indicators, tags, isClone, isRemoveEmpty, indicatorFilterType) {
    if (isClone) {
      tags = _.cloneDeep(tags)
      indicators = _.cloneDeep(indicators)
    }

    let sortTags = _.sortBy(tags, 'tag_name').reverse()

    let tags_map = {}
    sortTags.forEach(tag => {
      tags_map[tag.id] = tag
      tag.id = this.makeTagId(tag.id)
      tag.noValue = true
      tag.parent = tag.parent_tag_id && tag.parent_tag_id !== 'None' ? this.makeTagId(tag.parent_tag_id) : null
      tag.children = []
      tag.title = tag.tag_name
      tag.value = tag.id
    })

    // add 'Other Indicators' tag to collect any indicators without tags
    const otherTag = {
      'id': 0,
      'value': this.makeTagId(0),
      'noValue': true,
      'title': 'Other Indicators',
      'children': []
    }

    indicators.forEach(indicator => {
      console.log('indicatorStore.jxs: ', indicator)
      indicator.title = indicator.name
      indicator.value = indicator.id
      indicator.displayTitle = indicator.name + ' (' + indicator.id + ')'
      indicator.parsed_tag_json = JSON.parse(indicator.tag_json)

      if (indicatorFilterType) {
        if (!_.isArray(indicator.tag_json) || indicator.tag_json.length === 0) {
          if (indicatorFilterType && indicator.data_format === indicatorFilterType) {
            otherTag.children.push(indicator)
            indicator.parentNode = otherTag
          }
        } else if (_.isArray(indicator.parsed_tag_json)) {
          indicator.parsed_tag_json.forEach(tId => {
            console.log('indicatorStore.jxs -- indicator.id : indicator.id ')
            console.log('indicatorStore.jxs -- tId: ', tId)
            if (indicatorFilterType && indicator.data_format === indicatorFilterType) {
              let tagParent = tags_map[tId]
              console.log('indicatorStore.jxs -- tagParent.children.push(indicator): ', indicator)
              tagParent.children.push(indicator)
              indicator.parentNode = tagParent
            }
          })
        }
      } else {
        if (!_.isArray(indicator.parsed_tag_json) || indicator.parsed_tag_json.length === 0) {
          otherTag.children.push(indicator)
          indicator.parentNode = otherTag
        } else if (_.isArray(indicator.parsed_tag_json)) {
          indicator.parsed_tag_json.forEach(tId => {
            let tagParent = tags_map[tId]
            tagParent.children.push(indicator)
            indicator.parentNode = tagParent
          })
        }
      }
    })

    // add other tag?
    if (otherTag.children.length > 0) {
      sortTags.push(otherTag)
    }

    // sort indicators with each tag
    sortTags.forEach(tag => tag.children = _.sortBy(tag.children, 'title'))
    sortTags = treeify(sortTags, 'id')
    sortTags.reverse()

    if (isRemoveEmpty) {
      sortTags = this.removeIndicatorEmptyNode(sortTags)
    }

    return sortTags
  }
})

export default IndicatorStore
<commit_msg>remove logs<commit_after>import _ from 'lodash'
import Reflux from 'reflux'
import StateMixin from'reflux-state-mixin'
import IndicatorActions from 'actions/IndicatorActions'
import treeify from 'data/transform/treeify'

var IndicatorStore = Reflux.createStore({

  mixins: [StateMixin.store],

  listenables: IndicatorActions,

  indicators: {
    meta: null,
    raw: null,
    index: null,
    filtered: [],
    list: [],
    tree: []
  },

  getInitialState () {
    return this.indicators
  },

  // =========================================================================== //
  //                              API CALL HANDLERS                              //
  // =========================================================================== //

  // ============================  Fetch Indicators  =========================== //
  onFetchIndicators () {
    this.setState({ raw: [] })
  },
  onFetchIndicatorsCompleted (response) {
    this.indicators.meta = response.meta
    this.indicators.raw = response.objects[0].indicators || response.objects
    this.indicators.filtered = this.indicators.raw
    this.indicators.index = _.indexBy(this.indicators.raw, 'id')
    this.processIndicators()
  },
  onFetchIndicatorsFailed (error) {
    this.setState({ error: error })
  },

  // ===========================  Fetch Indicator Tags ========================= //
  onFetchIndicatorTags () {
    this.setState({ raw: [] })
  },
  onFetchIndicatorTagsCompleted (response) {
    this.indicators.tags = response.objects[0].indicator_tags || response.objects
    this.processIndicators()
  },
  onFetchIndicatorTagsFailed (error) {
    this.setState({ error: error })
  },

  // =========================================================================== //
  //                                   UTILITIES                                 //
  // =========================================================================== //
  processIndicators () {
    if (this.indicators.raw && this.indicators.tags) {
      this.indicators.tree = this.buildIndicatorsTree(this.indicators.raw, this.indicators.tags, true, true)
      this.indicators.list = _.sortBy(this.indicators.tree, 'title')
      this.trigger(this.indicators)
    }
  },

  makeTagId (tId) {
    return 'tag-' + tId
  },

  pickAllNodesInTrees (parent, nodes) {
    let children = parent.children
    if (children && children.length) {
      children.forEach(item => this.pickAllNodesInTrees(item, nodes))
    } else {
      if (parent.noValue) nodes.push(parent)
    }
  },

  removeIndicatorEmptyNode (sourceList) {
    if (!sourceList || !sourceList.length) {
      return sourceList
    }

    let virtualRoot = {noValue: false, parentNode: null, title: 'No Available Indicator', children: sourceList}
    virtualRoot.children.forEach(item => item.parentNode = virtualRoot)

    let nodes
    do {
      nodes = []
      this.pickAllNodesInTrees(virtualRoot, nodes)
      nodes.forEach(item => item.parentNode.children.splice(item.parentNode.children.indexOf(item), 1))
    } while (nodes.length > 0)

    if (sourceList.length > 0) {
      return sourceList
    } else {
      virtualRoot.noValue = true
      virtualRoot.children = []
      return [virtualRoot]
    }
  },

  buildIndicatorsTree (indicators, tags, isClone, isRemoveEmpty, indicatorFilterType) {
    if (isClone) {
      tags = _.cloneDeep(tags)
      indicators = _.cloneDeep(indicators)
    }

    let sortTags = _.sortBy(tags, 'tag_name').reverse()

    let tags_map = {}
    sortTags.forEach(tag => {
      tags_map[tag.id] = tag
      tag.id = this.makeTagId(tag.id)
      tag.noValue = true
      tag.parent = tag.parent_tag_id && tag.parent_tag_id !== 'None' ? this.makeTagId(tag.parent_tag_id) : null
      tag.children = []
      tag.title = tag.tag_name
      tag.value = tag.id
    })

    // add 'Other Indicators' tag to collect any indicators without tags
    const otherTag = {
      'id': 0,
      'value': this.makeTagId(0),
      'noValue': true,
      'title': 'Other Indicators',
      'children': []
    }

    indicators.forEach(indicator => {
      indicator.title = indicator.name
      indicator.value = indicator.id
      indicator.displayTitle = indicator.name + ' (' + indicator.id + ')'
      indicator.parsed_tag_json = JSON.parse(indicator.tag_json)

      if (indicatorFilterType) {
        if (!_.isArray(indicator.tag_json) || indicator.tag_json.length === 0) {
          if (indicatorFilterType && indicator.data_format === indicatorFilterType) {
            otherTag.children.push(indicator)
            indicator.parentNode = otherTag
          }
        } else if (_.isArray(indicator.parsed_tag_json)) {
          indicator.parsed_tag_json.forEach(tId => {
            if (indicatorFilterType && indicator.data_format === indicatorFilterType) {
              let tagParent = tags_map[tId]
              tagParent.children.push(indicator)
              indicator.parentNode = tagParent
            }
          })
        }
      } else {
        if (!_.isArray(indicator.parsed_tag_json) || indicator.parsed_tag_json.length === 0) {
          otherTag.children.push(indicator)
          indicator.parentNode = otherTag
        } else if (_.isArray(indicator.parsed_tag_json)) {
          indicator.parsed_tag_json.forEach(tId => {
            let tagParent = tags_map[tId]
            tagParent.children.push(indicator)
            indicator.parentNode = tagParent
          })
        }
      }
    })

    // add other tag?
    if (otherTag.children.length > 0) {
      sortTags.push(otherTag)
    }

    // sort indicators with each tag
    sortTags.forEach(tag => tag.children = _.sortBy(tag.children, 'title'))
    sortTags = treeify(sortTags, 'id')
    sortTags.reverse()

    if (isRemoveEmpty) {
      sortTags = this.removeIndicatorEmptyNode(sortTags)
    }

    return sortTags
  }
})

export default IndicatorStore
<|endoftext|>


<commit_before>/* eslint global-require: 0 */

'use strict';

var fs        = require('fs');
var path      = require('path');
var assert    = require('assert');
var yaml      = require('js-yaml');
var format    = require('format');
var encode    = require('htmlencode').htmlEncode;
var validator = require('html-validator');

var response  = {};

// for array of types, first will be chosen when testing strictly
var CONTENT_TYPE_MAP = {
    css: 'text/css',
    js: ['application/javascript',
        'text/javascript',
        'application/x-javascript'
    ],

    // fonts
    eot: 'application/vnd.ms-fontobject',
    svg: 'image/svg+xml',
    ttf: ['application/x-font-ttf',
        'font/ttf'
    ],

    woff: 'application/font-woff',
    woff2: 'application/font-woff2',
    otf: 'application/x-font-otf'
};

function extension(str) {
    return str.match(/[A-Za-z0-9]+$/)[0];
}

function assertContentType(uri, contentType) {
    var ext  = extension(uri);
    var type = CONTENT_TYPE_MAP[ext];

    // Making TEST_STRICT=true default, pass TEST_STRICT=false to disable
    // strict checking.

    if (process.env.TEST_STRICT === 'false' && Array.isArray(type)) {
        assert(type.indexOf(contentType) >= 0,
            format('invalid content-type for "%s", expected one of "%s" but got "%s"',
                   ext, type.join('", "'), contentType));
    } else {
        type = Array.isArray(type) ? type[0] : type;

        assert.equal(type, contentType,
            format('invalid content-type for "%s", expected "%s" but got "%s"',
                ext, type, contentType));
    }
}

function config() {
    return yaml.safeLoad(fs.readFileSync(path.join(__dirname, '..', 'config', '_config.yml'), 'utf8'));
}

function cleanEndpoint(endpoint) {
    endpoint = typeof endpoint === 'undefined' ? '/' : endpoint;
    endpoint = endpoint[0] === '/' ? endpoint : '/' + endpoint;
    endpoint = endpoint[endpoint.length - 1] === '/' ? endpoint : endpoint + '/';

    return endpoint;
}

function app(config, endpoint) {
    endpoint = cleanEndpoint(endpoint);

    // don't use configured port
    process.env.PORT = config.port < 3000 ? config.port + 3000 : config.port + 1;

    // load app
    require('../app.js');
    return format('http://localhost:%s%s', process.env.PORT, endpoint);
}

function assertResponse(response, code) {
    code = typeof code === 'undefined' ? 200 : code;
    assert(response);
    assert.equal(code, response.statusCode);
}

function assertContains(needle, haystack) {
    assert(haystack.indexOf(needle) > 0);
}

function assertValidHTML(response, done) {
    var options = {
        data: response.body,
        format: 'text'
    };

    validator(options, function (err, data) {
        if (err) {
            console.trace(err);
        }

        var errors = data.split('\n')
            .filter(function (e) {
                if (e.match(/^Error:/)) {
                    return true;
                }
                return false;
            })
            .filter(function(e) {
                console.log('>> e:', e);
                if (e.match(/^Error: Attribute.+color.+not allowed on element.+link.+at this point./)) {
                    return false;
                }
                return true;
            });

        if (errors.length > 0) {
            var sep = '\n\t - ';

            assert(false, sep + errors.join(sep));
        } else {
            assert(true);
        }
        done();
    });
}

function preFetch(uri, cb, http) {
    http = typeof http === 'undefined' ? require('http') : http;

    http.get(uri, function (res) {
        response = res;
        response.body = '';
        res.on('data', function (chunk) {
            response.body += chunk;
        });
        res.on('end', function () {
            cb(response);
        });
    });
}

function cssHTML(uri, sri) {
    return encode('<link href="' + uri + '" rel="stylesheet" integrity="' + sri + '" crossorigin="anonymous">');
}

function cssJade(uri, sri) {
    return encode('link(href="' + uri + '", rel="stylesheet", integrity="' + sri + '", crossorigin="anonymous")');
}

function cssHAML(uri, sri) {
    return encode('%link{href: "' + uri + '", rel: "stylesheet", integrity: "' + sri + '", crossorigin: "anonymous"}');
}

function jsHTML(uri, sri) {
    return encode('<script src="' + uri + '" integrity="' + sri + '" crossorigin="anonymous"></script>');
}

function jsJade(uri, sri) {
    return encode('script(src="' + uri + '", integrity="' + sri + '", crossorigin="anonymous")');
}

function jsHAML(uri, sri) {
    return encode('%script{src: "' + uri + '", integrity: "' + sri + '", crossorigin: "anonymous"}');
}

function domainCheck(uri) {
    if (typeof process.env.TEST_S3 === 'undefined') {
        return uri;
    }

    return uri.replace('https://maxcdn.bootstrapcdn.com/', process.env.TEST_S3);
}

module.exports = {
    config: config,
    app: app,
    assert: {
        response:    assertResponse,
        contains:    assertContains,
        contentType: assertContentType,
        validHTML:   assertValidHTML
    },
    preFetch: preFetch,
    extension: extension,
    css: {
        pug:  cssJade,
        html: cssHTML,
        haml: cssHAML
    },
    javascript: {
        pug:  jsJade,
        html: jsHTML,
        haml: jsHAML
    },
    CONTENT_TYPE_MAP: CONTENT_TYPE_MAP,
    domainCheck: domainCheck
};
<commit_msg>Ignore the new HTML validation error about `link rel=apple-touch-icon`. (#834)<commit_after>/* eslint global-require: 0 */

'use strict';

var fs        = require('fs');
var path      = require('path');
var assert    = require('assert');
var yaml      = require('js-yaml');
var format    = require('format');
var encode    = require('htmlencode').htmlEncode;
var validator = require('html-validator');

var response  = {};

// for array of types, first will be chosen when testing strictly
var CONTENT_TYPE_MAP = {
    css: 'text/css',
    js: ['application/javascript',
        'text/javascript',
        'application/x-javascript'
    ],

    // fonts
    eot: 'application/vnd.ms-fontobject',
    svg: 'image/svg+xml',
    ttf: ['application/x-font-ttf',
        'font/ttf'
    ],

    woff: 'application/font-woff',
    woff2: 'application/font-woff2',
    otf: 'application/x-font-otf'
};

function extension(str) {
    return str.match(/[A-Za-z0-9]+$/)[0];
}

function assertContentType(uri, contentType) {
    var ext  = extension(uri);
    var type = CONTENT_TYPE_MAP[ext];

    // Making TEST_STRICT=true default, pass TEST_STRICT=false to disable
    // strict checking.

    if (process.env.TEST_STRICT === 'false' && Array.isArray(type)) {
        assert(type.indexOf(contentType) >= 0,
            format('invalid content-type for "%s", expected one of "%s" but got "%s"',
                   ext, type.join('", "'), contentType));
    } else {
        type = Array.isArray(type) ? type[0] : type;

        assert.equal(type, contentType,
            format('invalid content-type for "%s", expected "%s" but got "%s"',
                ext, type, contentType));
    }
}

function config() {
    return yaml.safeLoad(fs.readFileSync(path.join(__dirname, '..', 'config', '_config.yml'), 'utf8'));
}

function cleanEndpoint(endpoint) {
    endpoint = typeof endpoint === 'undefined' ? '/' : endpoint;
    endpoint = endpoint[0] === '/' ? endpoint : '/' + endpoint;
    endpoint = endpoint[endpoint.length - 1] === '/' ? endpoint : endpoint + '/';

    return endpoint;
}

function app(config, endpoint) {
    endpoint = cleanEndpoint(endpoint);

    // don't use configured port
    process.env.PORT = config.port < 3000 ? config.port + 3000 : config.port + 1;

    // load app
    require('../app.js');
    return format('http://localhost:%s%s', process.env.PORT, endpoint);
}

function assertResponse(response, code) {
    code = typeof code === 'undefined' ? 200 : code;
    assert(response);
    assert.equal(code, response.statusCode);
}

function assertContains(needle, haystack) {
    assert(haystack.indexOf(needle) > 0);
}

function assertValidHTML(response, done) {
    var options = {
        data: response.body,
        format: 'text'
    };

    validator(options, function (err, data) {
        if (err) {
            console.trace(err);
        }

        var errors = data.split('\n')
            .filter(function (e) {
                if (e.match(/^Error:/)) {
                    return true;
                }
                return false;
            })
            .filter(function(e) {
                var ignores = [
                    /^Error: Attribute.+color.+not allowed on element.+link.+at this point./,
                    /^Error: A.+link.+element with a.+sizes.+attribute must have a.+rel.+attribute that contains the value.+icon.+./
                ];

                for (var i = 0, len = ignores.length; i < len; i++) {
                    if (e.match(ignores[i])) {
                        console.log('\n>> (IGNORED) ' + e);
                        return false;
                    }
                }
                console.error('\n>> ' + e + '\n');
                return true;
            });

        if (errors.length > 0) {
            var sep = '\n\t - ';

            assert(false, sep + errors.join(sep));
        } else {
            assert(true);
        }
        done();
    });
}

function preFetch(uri, cb, http) {
    http = typeof http === 'undefined' ? require('http') : http;

    http.get(uri, function (res) {
        response = res;
        response.body = '';
        res.on('data', function (chunk) {
            response.body += chunk;
        });
        res.on('end', function () {
            cb(response);
        });
    });
}

function cssHTML(uri, sri) {
    return encode('<link href="' + uri + '" rel="stylesheet" integrity="' + sri + '" crossorigin="anonymous">');
}

function cssJade(uri, sri) {
    return encode('link(href="' + uri + '", rel="stylesheet", integrity="' + sri + '", crossorigin="anonymous")');
}

function cssHAML(uri, sri) {
    return encode('%link{href: "' + uri + '", rel: "stylesheet", integrity: "' + sri + '", crossorigin: "anonymous"}');
}

function jsHTML(uri, sri) {
    return encode('<script src="' + uri + '" integrity="' + sri + '" crossorigin="anonymous"></script>');
}

function jsJade(uri, sri) {
    return encode('script(src="' + uri + '", integrity="' + sri + '", crossorigin="anonymous")');
}

function jsHAML(uri, sri) {
    return encode('%script{src: "' + uri + '", integrity: "' + sri + '", crossorigin: "anonymous"}');
}

function domainCheck(uri) {
    if (typeof process.env.TEST_S3 === 'undefined') {
        return uri;
    }

    return uri.replace('https://maxcdn.bootstrapcdn.com/', process.env.TEST_S3);
}

module.exports = {
    config: config,
    app: app,
    assert: {
        response:    assertResponse,
        contains:    assertContains,
        contentType: assertContentType,
        validHTML:   assertValidHTML
    },
    preFetch: preFetch,
    extension: extension,
    css: {
        pug:  cssJade,
        html: cssHTML,
        haml: cssHAML
    },
    javascript: {
        pug:  jsJade,
        html: jsHTML,
        haml: jsHAML
    },
    CONTENT_TYPE_MAP: CONTENT_TYPE_MAP,
    domainCheck: domainCheck
};
<|endoftext|>


<commit_before>// ==UserScript==
// @name        Why No Bounty?
// @namespace   https://github.com/Glorfindel83/
// @description Adds information to a question indicating why you can't start a bounty.
// @author      Glorfindel
// @version     0.1
// @match       *://*.stackexchange.com/*
// @match       *://*.stackoverflow.com/*
// @match       *://*.superuser.com/*
// @match       *://*.serverfault.com/*
// @match       *://*.askubuntu.com/*
// @match       *://*.stackapps.com/*
// @match       *://*.mathoverflow.net/*
// @grant       none
// ==/UserScript==

(function () {
  "use strict";

  // Is this a Q&A page?
  var questionLink = $("#question-header a").attr("href");
  if (typeof(questionLink) === "undefined") {
    return;
  }

  // If there's a 'start a bounty' link, we have nothing to do.
  if ($("a.bounty-link.bounty").length !== 0) {
    return;
  }

  var addInformation = function (message) {
    $("#question > table > tbody").append("
"
      + "bounty not possible: " + message + "
");
  };

  // Meta site?
  if (window.location.host != "meta.stackexchange.com" && window.location.host.contains("meta")) {
    addInformation("meta sites don't have bounties");
    return;
  }

  // Is there an open bounty?
  if ($("div.question-status.bounty").length !== 0) {
  	addInformation("there is already an open bounty");
    return;
  }

  // Is the question closed / locked?
  var status = $("#question .question-status h2 b").text();
  if (status === "closed" || status === "put on hold" || status == "marked") {
    addInformation("the question is closed");
    return;
  } else if (status === "locked") {
    addInformation("the question is locked");
    return;
  }

  // Is the question at least two days old?
  var creationDate = Date.parse($("#question .owner .user-action-time span").attr("title"));
  var ageInSeconds = (Date.now() - creationDate)  / 1000;
  if (ageInSeconds < 2 * 86400) {
    addInformation("the question is not two days old yet");
    return;
  }

  // Get reputation of current user
  var reputation = parseInt($("div.-rep.js-header-rep").text().replace(",", ""), 10);
  if (reputation < 75) {
    addInformation("you need 75 reputation to create a bounty");
    return;
  }

  // Does the user have an answer to this question?
  var profileURL = $("a.my-profile.js-gps-track").attr("href");
  var hasAnswer = $(".answercell .user-details a").is(function(index, element) {
    return $(element).attr("href") == profileURL;
  });
  if (hasAnswer && reputation < 100) {
    addInformation("you need 100 reputation to create a bounty for a question which you've already answered");
    return;
  }

  // Find previous bounties on this question by current user
  var questionID = /^\/questions\/(\d+)\//.exec(questionLink)[1];
  $.get("https://" + window.location.host + "/users/current?tab=bounties&sort=offered", function (data) {
    var summaries = $(data).find("#question-summary-" + questionID);
    var minimumBounty = 50;
    if (summaries.length !== 0) {
      // assume the last (highest) bounty is the first in this list
      var highestBounty = parseInt(summaries[0].find("div.bounty-indicator").replace("+", ""), 10);
      minimumBounty = highestBounty * 2;
      if (minimumBounty > 500) {
        addInformation("last bounty was " + highestBounty + " which cannot be doubled");
        return;
      }
    }
    if (reputation > minimumBounty) {
      addInformation("minimum bounty (" + minimumBounty + ") higher than reputation (" + reputation + ")");
      return;
    }

    // Find currently active bounties by current user
    $.get("https://" + window.location.host + "/users/current?tab=bounties&sort=active", function (data) {
      var activeCount = parseInt($(data).find("#user-tab-bounties h1 span.count").text(), 10);
      if (activeCount >= 3) {
        addInformation("you have " + activeCount + " currently active bounties");
        return;
      }
    });
  });
})();
<commit_msg>Why No Bounty v0.2: - deleted questions - reputation comparison fix<commit_after>// ==UserScript==
// @name        Why No Bounty?
// @namespace   https://github.com/Glorfindel83/
// @description Adds information to a question indicating why you can't start a bounty.
// @author      Glorfindel
// @version     0.2
// @match       *://*.stackexchange.com/*
// @match       *://*.stackoverflow.com/*
// @match       *://*.superuser.com/*
// @match       *://*.serverfault.com/*
// @match       *://*.askubuntu.com/*
// @match       *://*.stackapps.com/*
// @match       *://*.mathoverflow.net/*
// @grant       none
// ==/UserScript==

(function () {
  "use strict";

  // Is this a Q&A page?
  var questionLink = $("#question-header a").attr("href");
  if (typeof(questionLink) === "undefined") {
    return;
  }

  // If there's a 'start a bounty' link, we have nothing to do.
  if ($("a.bounty-link.bounty").length !== 0) {
    return;
  }

  var addInformation = function (message) {
    $("#question > table > tbody").append("
"
      + "bounty not possible: " + message + "
");
  };

  // Meta site?
  if (window.location.host != "meta.stackexchange.com" && window.location.host.contains("meta")) {
    addInformation("meta sites don't have bounties");
    return;
  }

  // Is there an open bounty?
  if ($("div.question-status.bounty").length !== 0) {
  	addInformation("there is already an open bounty");
    return;
  }

  // Is the question closed / locked?
  var status = $("#question .question-status h2 b").text();
  if (status === "closed" || status === "put on hold" || status == "marked") {
    addInformation("the question is closed");
    return;
  } else if (status === "locked") {
    addInformation("the question is locked");
    return;
  } else if (status === "deleted") {
    addInformation("the question is deleted");
    return;
  }

  // Is the question at least two days old?
  var creationDate = Date.parse($("#question .owner .user-action-time span").attr("title"));
  var ageInSeconds = (Date.now() - creationDate)  / 1000;
  if (ageInSeconds < 2 * 86400) {
    addInformation("the question is not two days old yet");
    return;
  }

  // Get reputation of current user
  var reputation = parseInt($("div.-rep.js-header-rep").text().replace(",", ""), 10);
  if (reputation < 75) {
    addInformation("you need 75 reputation to create a bounty");
    return;
  }

  // Does the user have an answer to this question?
  var profileURL = $("a.my-profile.js-gps-track").attr("href");
  var hasAnswer = $(".answercell .user-details a").is(function(index, element) {
    return $(element).attr("href") == profileURL;
  });
  if (hasAnswer && reputation < 100) {
    addInformation("you need 100 reputation to create a bounty for a question which you've already answered");
    return;
  }

  // Find previous bounties on this question by current user
  var questionID = /^\/questions\/(\d+)\//.exec(questionLink)[1];
  $.get("https://" + window.location.host + "/users/current?tab=bounties&sort=offered", function (data) {
    var summaries = $(data).find("#question-summary-" + questionID);
    var minimumBounty = 50;
    if (summaries.length !== 0) {
      // assume the last (highest) bounty is the first in this list
      var highestBounty = parseInt(summaries[0].find("div.bounty-indicator").replace("+", ""), 10);
      minimumBounty = highestBounty * 2;
      if (minimumBounty > 500) {
        addInformation("last bounty was " + highestBounty + " which cannot be doubled");
        return;
      }
    }
    if (reputation < minimumBounty) {
      addInformation("minimum bounty (" + minimumBounty + ") higher than reputation (" + reputation + ")");
      return;
    }

    // Find currently active bounties by current user
    $.get("https://" + window.location.host + "/users/current?tab=bounties&sort=active", function (data) {
      var activeCount = parseInt($(data).find("#user-tab-bounties h1 span.count").text(), 10);
      if (activeCount >= 3) {
        addInformation("you have " + activeCount + " currently active bounties");
        return;
      }
    });
  });
})();
<|endoftext|>


<commit_before>//////////////////////
// Helper functions //
//////////////////////

var globalScope = typeof global !== 'undefined' ? global : window;

globalScope.resetStage = function() {
  Crafty.viewport.reset();
  Crafty.viewport.scroll('_x', 0);
  Crafty.viewport.scroll('_y', 0);
  Crafty.viewport.clampToEntities = true;
};

globalScope.Round = function(x){
  return Math.round(x*100)/100;
};

globalScope.keysUp = function() {
  var keysToRelease = Array.prototype.slice.call(arguments);
    for (var k in keysToRelease) {
      var key = Crafty.keys[keysToRelease[k]] || keysToRelease[k];
      Crafty.keydown[key] = false;
      Crafty.trigger("KeyUp", {key: key});
    }
};
globalScope.keysDown = function() {
    var keysToPress = Array.prototype.slice.call(arguments);
    for (var k in keysToPress) {
      var key = Crafty.keys[keysToPress[k]] || keysToPress[k];
      Crafty.keydown[key] = true;
      Crafty.trigger("KeyDown", {key: key});
    }
};

//////////////////
// QUnit config //
//////////////////

QUnit.testDone(function() {
  // Clean all entities at the end of each test
  Crafty("*").destroy();
});

QUnit.config.hidepassed = true;
QUnit.config.reorder = false;

///////////////////////
// OpenSauce logging //
///////////////////////

var log = [];
QUnit.testStart(function(testDetails){
  QUnit.log(function(details){
    if (!details.result) {
      details.name = testDetails.name;
      log.push(details);
    }
  });
});
QUnit.done(function (test_results) {
  var tests = [];
  for(var i = 0, len = log.length; i < len; i++) {
    var details = log[i];
    tests.push({
      name: details.name,
      result: details.result,
      expected: details.expected,
      actual: details.actual,
      source: details.source
    });
  }
  test_results.tests = tests;
  if (typeof window !== "undefined")
    window.global_test_results = test_results;
  else if (typeof global !== "undefined")
    global.global_test_results = test_results;
});
<commit_msg>Remove global prefix from common helper functions<commit_after>//////////////////////
// Helper functions //
//////////////////////

resetStage = function() { // jshint ignore:line
  Crafty.viewport.reset();
  Crafty.viewport.scroll('_x', 0);
  Crafty.viewport.scroll('_y', 0);
  Crafty.viewport.clampToEntities = true;
};

Round = function(x){ // jshint ignore:line
  return Math.round(x*100)/100;
};

keysUp = function() { // jshint ignore:line
  var keysToRelease = Array.prototype.slice.call(arguments);
    for (var k in keysToRelease) {
      var key = Crafty.keys[keysToRelease[k]] || keysToRelease[k];
      Crafty.keydown[key] = false;
      Crafty.trigger("KeyUp", {key: key});
    }
};
keysDown = function() { // jshint ignore:line
    var keysToPress = Array.prototype.slice.call(arguments);
    for (var k in keysToPress) {
      var key = Crafty.keys[keysToPress[k]] || keysToPress[k];
      Crafty.keydown[key] = true;
      Crafty.trigger("KeyDown", {key: key});
    }
};

//////////////////
// QUnit config //
//////////////////

QUnit.testDone(function() {
  // Clean all entities at the end of each test
  Crafty("*").destroy();
});

QUnit.config.hidepassed = true;
QUnit.config.reorder = false;

///////////////////////
// OpenSauce logging //
///////////////////////

var log = [];
QUnit.testStart(function(testDetails){
  QUnit.log(function(details){
    if (!details.result) {
      details.name = testDetails.name;
      log.push(details);
    }
  });
});
QUnit.done(function (test_results) {
  var tests = [];
  for(var i = 0, len = log.length; i < len; i++) {
    var details = log[i];
    tests.push({
      name: details.name,
      result: details.result,
      expected: details.expected,
      actual: details.actual,
      source: details.source
    });
  }
  test_results.tests = tests;
  if (typeof window !== "undefined")
    window.global_test_results = test_results;
  else if (typeof global !== "undefined")
    global.global_test_results = test_results;
});
<|endoftext|>