<commit_before>var cheerio = require('cheerio');
var nodeio  = require('node.io');
var request = require('request');
var debug   = require('debug')('tumblr:fetch.lists');
var async   = require('async');
var path    = require('path');
var url     = require('url');
var db      = require('nano')('http://localhost:5984/tumblr');
var _       = require('underscore');

_.templateSettings = { interpolate: /\{\{(.+?)\}\}/g };

var defaults = {
    name: 'tof34',
    count: 50,
    start: 1
};

var options = {
    timeout: 10,
    max: 4,
    retries: 3
};
var tpl = _.template('http://{{name}}.tumblr.com/api/read?type=photo&num={{count}}&start={{start}}');

exports.job = new nodeio.Job({
    input: _.range(2000, 3500, 50),
    run: function (num) {
        var options = { start: num };
        _.defaults(options, defaults);
        var url = tpl(options);
        console.log(url);
        this.get(url, function(err, data, headers) {
            if (err) { return this.fail(err); }

            var $ = cheerio.load(data);
            var posts = $('tumblr post').map(mapJson(options, $));
            debug('fetched post count', posts.length);

            async.filter(posts, filterExisting, doEachLimit.bind(this));
        });
    }
});

function filterExisting(post, next) { db.head(post._id, next); }

function doEachLimit(posts) {
    debug('new post count', posts.length);
    async.eachLimit(posts, 5, doWaterfall, completed.bind(this));
}

function doWaterfall(post, next) {
    debug('waterfall', post._id);
    async.waterfall([
        async.apply(saveDocument, post),
        streamAttachment
    ], next);
}

function saveDocument(post, next) {
    debug('saveDocument', post._id);
    db.insert(post, post._id, function(err, data) {
        next(err, _.extend({}, post, data));
    });
}

function streamAttachment(post, next) {
    debug('streamAttachment', post.image, post._id, post.rev);

    var reader = request.get(post.image);
    var writer = db.attachment.insert(
        post._id, 'image.' + post.extension,
        null, 'image/' + post.extension,
        { rev: post.rev }, next);

    reader.pipe(writer);
}

function completed(err, result) {
    debug('completed', result);
    if (err) { return this.fail(err); }
    this.emit(result);
}

function mapJson(options, $) {
    return function mapFn() {
        var $el = $(this);

        var id = options.name + '--' + $el.attr('id') ;
        var img = $el.find('photo-url[max-width=1280]').text();
        var tags = $el.find('tag').map(function() { return $(this).text(); });
        var ext = path.extname(url.parse(img).pathname);

        return {
            _id       : id,
            id        : id,
            url       : $el.attr('url'),
            type      : 'photo',
            date      : $el.attr('date-gmt'),
            timestamp : $el.attr('unix-timestamp'),
            width     : $el.attr('width'),
            height    : $el.attr('height'),
            reblogKey : $el.attr('reblog-key'),
            image     : img,
            extension : ext.replace(/^\./,''),
            tags      : tags
        };
    };
}

<commit_msg>tweak job.<commit_after>var cheerio = require('cheerio');
var nodeio  = require('node.io');
var request = require('request');
var debug   = require('debug')('tumblr:fetch.lists');
var async   = require('async');
var path    = require('path');
var url     = require('url');
var db      = require('nano')('http://localhost:5984/tumblr');
var _       = require('underscore');

_.templateSettings = { interpolate: /\{\{(.+?)\}\}/g };

var defaults = {
    name: 'tof34',
    count: 50,
    start: 1
};

var options = {
    timeout: 10,
    max: 4,
    retries: 3
};
var tpl = _.template('http://{{name}}.tumblr.com/api/read?type=photo&num={{count}}&start={{start}}');

exports.job = new nodeio.Job({
    input: _.range(1, 200, 50),
    run: function (num) {
        var options = { start: num };
        _.defaults(options, defaults);
        var url = tpl(options);
        this.get(url, function(err, data, headers) {
            if (err) { return this.fail(err); }

            var $ = cheerio.load(data);
            var posts = $('tumblr post').map(mapJson(options, $));
            debug('fetched post count', posts.length);

            // only comics
            posts = _(posts).filter(function(o) { return _(o.tags).include('comics'); });
            async.filter(posts, filterExisting, doEachLimit.bind(this));
        });
    }
});

function filterExisting(post, next) { db.head(post._id, next); }

function doEachLimit(posts) {
    debug('new post count', posts.length);
    async.eachLimit(posts, 5, doWaterfall, completed.bind(this));
}

function doWaterfall(post, next) {
    debug('waterfall', post._id);
    async.waterfall([
        async.apply(saveDocument, post),
        streamAttachment
    ], next);
}

function saveDocument(post, next) {
    debug('saveDocument', post._id);
    db.insert(post, post._id, function(err, data) {
        next(err, _.extend({}, post, data));
    });
}

function streamAttachment(post, next) {
    debug('streamAttachment', post.images[0], post._id, post.rev);

    var reader = request.get(post.images[0]);
    var writer = db.attachment.insert(
        post._id, 'image.' + post.extension,
        null, 'image/' + post.extension,
        { rev: post.rev }, next);

    reader.pipe(writer);
}

function completed(err, result) {
    debug('completed', result);
    if (err) { return this.fail(err); }
    this.emit(result);
}

function mapJson(options, $) {
    return function mapFn() {
        var $el = $(this);

        function getTextFn() { return $(this).text(); }

        var id = options.name + '--' + $el.attr('id') ;
        var img = $el.find('photo-url[max-width=1280]').map(getTextFn);
        var tags = $el.find('tag').map(getTextFn);
        var ext = path.extname(url.parse(img[0]).pathname);

        return {
            _id       : id,
            id        : id,
            url       : $el.attr('url'),
            type      : 'photo',
            date      : $el.attr('date-gmt'),
            timestamp : $el.attr('unix-timestamp'),
            width     : $el.attr('width'),
            height    : $el.attr('height'),
            reblogKey : $el.attr('reblog-key'),
            images    : img,
            extension : ext.replace(/^\./,''),
            tags      : tags
        };
    };
}

<|endoftext|>


<commit_before>/*global Resumable, FLOW, $, Ember */

FLOW.uuid = function (file) {
  return Math.uuidFast();
};

FLOW.uploader = Ember.Object.create({
  r: new Resumable({
    target: FLOW.Env.flowServices + '/upload',
    uploadDomain: FLOW.Env.surveyuploadurl.split('/')[2],
    simultaneousUploads: 1,
    testChunks: false,
    throttleProgressCallbacks: 1, // 1s
    chunkRetryInterval: 1000, // 1s
    chunkSize: 512 * 1024, // 512KB,
    generateUniqueIdentifier: FLOW.uuid
  }),

  assignDrop: function (el) {
    return this.get('r').assignDrop(el);
  },

  assignBrowse: function (el) {
    return this.get('r').assignBrowse(el);
  },

  support: function () {
    return this.get('r').support;
  }.property(),

  upload: function () {
    return this.get('r').upload();
  },

  pause: function () {
    return this.get('r').pause();
  },

  isUploading: function () {
    return this.get('r').isUploading();
  },

  cancel: function () {
    return this.get('r').cancel();
  },

  addFile: function (file) {
    return this.get('r').addFile(file);
  },

  registerEvents: function () {
    var r = this.get('r');

    // Handle file add event
    r.on('fileAdded', function (file) {
      var li;

      FLOW.uploader.set('cancelled', false);

      // Show progress pabr
      $('.resumable-list').show();

      // Add the file to the list
      li = $('.resumable-file-' + file.uniqueIdentifier);
      if (file.file.type != "application/zip" && file.file.type !="application/x-zip-compressed") {
        $('.resumable-progress').hide();
        $('.resumable-list').append('
'+''+file.fileName+'' + ''
          + Ember.String.loc('_unsupported_file_type')) + '
' ;
        $('.resumable-list').css({
            color: '#FF0000'
        })
      } else {
        $('.resumable-progress').show();
        if (li.length === 0) {
          $('.resumable-list').append('
Uploading...  ');
        }

        $('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-name').html(file.fileName);

        $('.progress-bar').css({
          width: '0%'
        });
        // Actually start the upload
        r.upload();
      }
    });

    r.on('pause', function () {
      // Show resume, hide pause
      $('.resumable-progress .progress-resume-link').show();
      $('.resumable-progress .progress-pause-link').hide();
    });

    r.on('complete', function () {
      // Hide pause/resume when the upload has completed
      $('.resumable-progress .progress-resume-link, .resumable-progress .progress-pause-link').hide();
      /*if (!FLOW.uploader.get('cancelled')) {
        FLOW.uploader.showCompleteMessage();
      }*/
    });

    r.on('fileSuccess', function (file, message) {
      var target = this.opts.target,
      data = {
        uniqueIdentifier: file.uniqueIdentifier,
        filename: file.fileName,
        baseURL: location.protocol + '//' + location.host,
        appId: FLOW.Env.appId,
        uploadDomain: this.opts.uploadDomain,
        complete: true
      },
      fname = file.fileName,
      excel = /\.xlsx$/gi,
      csv = /\.csv$/gi,
      sc;

      if (excel.test(fname)) {
        data.surveyId = FLOW.selectedControl.selectedSurvey.get('id');
      }

      if (csv.test(fname)) {
        sc = FLOW.selectedControl.selectedCascadeResource;
        data.cascadeResourceId = sc.get('keyId');
        data.numLevels = FLOW.selectedControl.get('cascadeImportNumLevels');
        data.includeCodes = !!FLOW.selectedControl.get('cascadeImportIncludeCodes');
      }

      // Reflect that the file upload has completed
      //$('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html( Ember.String.loc('_upload_complete') );
      $('.resumable-list').append('
' +''+file.fileName+''
                       + '' + ''
                       + Ember.String.loc('_upload_complete')
                       + '
'
                     );

      setTimeout(function() {
        $.ajax({
          url : target,
          cache : false,
          type : 'POST',
          data : data
        });
      }, 500);

    });

    r.on('fileError', function (file, message) {
      // Reflect that the file upload has resulted in error
      $('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html('(file could not be uploaded: ' + message + ')');
    });

    r.on('fileProgress', function (file) {
      // Handle progress for both the file and the overall upload
      $('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html(Math.floor(file.progress() * 100) + '%');
      $('.progress-bar').css({
        width: Math.floor(r.progress() * 100) + '%'
      });
    });

  },
  showCancelledMessage: function () {
    FLOW.dialogControl.set('activeAction', 'ignore');
    FLOW.dialogControl.set('header', Ember.String.loc('_upload_cancelled'));
    FLOW.dialogControl.set('message', Ember.String.loc('_upload_cancelled_due_to_navigation'));
    FLOW.dialogControl.set('showCANCEL', false);
    FLOW.dialogControl.set('showDialog', true);
  },
  showCompleteMessage: function () {
    FLOW.dialogControl.set('activeAction', 'ignore');
    FLOW.dialogControl.set('header', Ember.String.loc('_upload_complete'));
    FLOW.dialogControl.set('message', Ember.String.loc('_upload_complete_message'));
    FLOW.dialogControl.set('showCANCEL', false);
    FLOW.dialogControl.set('showDialog', true);
  }
});

FLOW.BulkUploadAppletView = FLOW.View.extend({
  didInsertElement: function () {
    FLOW.uploader.assignDrop($('.resumable-drop')[0]);
    FLOW.uploader.assignBrowse($('.resumable-browse')[0]);
    FLOW.uploader.registerEvents();
  },
  willDestroyElement: function () {
    FLOW.uploader.set('cancelled', FLOW.uploader.isUploading());
    FLOW.uploader.cancel();
    this._super();
  }
});

/* Show warning when trying to close the tab/window with an upload process in progress */
window.onbeforeunload = function (e) {
  var confirmationMessage = Ember.String.loc('_upload_in_progress');

  if (FLOW.uploader.isUploading()) {
    (e || window.event).returnValue = confirmationMessage;
    return confirmationMessage;
  }
};
<commit_msg>[#2471]-Removed the message dialog that shows up when the file upload completes<commit_after>/*global Resumable, FLOW, $, Ember */

FLOW.uuid = function (file) {
  return Math.uuidFast();
};

FLOW.uploader = Ember.Object.create({
  r: new Resumable({
    target: FLOW.Env.flowServices + '/upload',
    uploadDomain: FLOW.Env.surveyuploadurl.split('/')[2],
    simultaneousUploads: 1,
    testChunks: false,
    throttleProgressCallbacks: 1, // 1s
    chunkRetryInterval: 1000, // 1s
    chunkSize: 512 * 1024, // 512KB,
    generateUniqueIdentifier: FLOW.uuid
  }),

  assignDrop: function (el) {
    return this.get('r').assignDrop(el);
  },

  assignBrowse: function (el) {
    return this.get('r').assignBrowse(el);
  },

  support: function () {
    return this.get('r').support;
  }.property(),

  upload: function () {
    return this.get('r').upload();
  },

  pause: function () {
    return this.get('r').pause();
  },

  isUploading: function () {
    return this.get('r').isUploading();
  },

  cancel: function () {
    return this.get('r').cancel();
  },

  addFile: function (file) {
    return this.get('r').addFile(file);
  },

  registerEvents: function () {
    var r = this.get('r');

    // Handle file add event
    r.on('fileAdded', function (file) {
      var li;

      FLOW.uploader.set('cancelled', false);

      // Show progress pabr
      $('.resumable-list').show();

      // Add the file to the list
      li = $('.resumable-file-' + file.uniqueIdentifier);
      if (file.file.type != "application/zip" && file.file.type !="application/x-zip-compressed") {
        $('.resumable-progress').hide();
        $('.resumable-list').append('
'+''+file.fileName+'' + ''
          + Ember.String.loc('_unsupported_file_type')) + '
' ;
        $('.resumable-list').css({
            color: '#FF0000'
        })
      } else {
        $('.resumable-progress').show();
        if (li.length === 0) {
          $('.resumable-list').append('
Uploading...  ');
        }

        $('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-name').html(file.fileName);

        $('.progress-bar').css({
          width: '0%'
        });
        // Actually start the upload
        r.upload();
      }
    });

    r.on('pause', function () {
      // Show resume, hide pause
      $('.resumable-progress .progress-resume-link').show();
      $('.resumable-progress .progress-pause-link').hide();
    });

    r.on('complete', function () {
      // Hide pause/resume when the upload has completed
      $('.resumable-progress .progress-resume-link, .resumable-progress .progress-pause-link').hide();
    });

    r.on('fileSuccess', function (file, message) {
      var target = this.opts.target,
      data = {
        uniqueIdentifier: file.uniqueIdentifier,
        filename: file.fileName,
        baseURL: location.protocol + '//' + location.host,
        appId: FLOW.Env.appId,
        uploadDomain: this.opts.uploadDomain,
        complete: true
      },
      fname = file.fileName,
      excel = /\.xlsx$/gi,
      csv = /\.csv$/gi,
      sc;

      if (excel.test(fname)) {
        data.surveyId = FLOW.selectedControl.selectedSurvey.get('id');
      }

      if (csv.test(fname)) {
        sc = FLOW.selectedControl.selectedCascadeResource;
        data.cascadeResourceId = sc.get('keyId');
        data.numLevels = FLOW.selectedControl.get('cascadeImportNumLevels');
        data.includeCodes = !!FLOW.selectedControl.get('cascadeImportIncludeCodes');
      }

      // Reflect that the file upload has completed
      //$('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html( Ember.String.loc('_upload_complete') );
      $('.resumable-list').append('
' +''+file.fileName+''
                       + '' + ' '
                       + Ember.String.loc('_upload_complete')
                       + '
'
                     );

      setTimeout(function() {
        $.ajax({
          url : target,
          cache : false,
          type : 'POST',
          data : data
        });
      }, 500);

    });

    r.on('fileError', function (file, message) {
      // Reflect that the file upload has resulted in error
      $('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html('(file could not be uploaded: ' + message + ')');
    });

    r.on('fileProgress', function (file) {
      // Handle progress for both the file and the overall upload
      $('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html(Math.floor(file.progress() * 100) + '%');
      $('.progress-bar').css({
        width: Math.floor(r.progress() * 100) + '%'
      });
    });

  },
  showCancelledMessage: function () {
    FLOW.dialogControl.set('activeAction', 'ignore');
    FLOW.dialogControl.set('header', Ember.String.loc('_upload_cancelled'));
    FLOW.dialogControl.set('message', Ember.String.loc('_upload_cancelled_due_to_navigation'));
    FLOW.dialogControl.set('showCANCEL', false);
    FLOW.dialogControl.set('showDialog', true);
  },
  showCompleteMessage: function () {
    FLOW.dialogControl.set('activeAction', 'ignore');
    FLOW.dialogControl.set('header', Ember.String.loc('_upload_complete'));
    FLOW.dialogControl.set('message', Ember.String.loc('_upload_complete_message'));
    FLOW.dialogControl.set('showCANCEL', false);
    FLOW.dialogControl.set('showDialog', true);
  }
});

FLOW.BulkUploadAppletView = FLOW.View.extend({
  didInsertElement: function () {
    FLOW.uploader.assignDrop($('.resumable-drop')[0]);
    FLOW.uploader.assignBrowse($('.resumable-browse')[0]);
    FLOW.uploader.registerEvents();
  },
  willDestroyElement: function () {
    FLOW.uploader.set('cancelled', FLOW.uploader.isUploading());
    FLOW.uploader.cancel();
    this._super();
  }
});

/* Show warning when trying to close the tab/window with an upload process in progress */
window.onbeforeunload = function (e) {
  var confirmationMessage = Ember.String.loc('_upload_in_progress');

  if (FLOW.uploader.isUploading()) {
    (e || window.event).returnValue = confirmationMessage;
    return confirmationMessage;
  }
};
<|endoftext|>


<commit_before><commit_msg>art<commit_after><|endoftext|>


<commit_before>/* globals module Promise */

'use strict';

module.exports = function ({
  models
}) {
  const {
    Project
  } = models;

  return {
    getAllProjects() {
      return new Promise((resolve, reject) => {
        Project.find((err, projects) => {
          if (err) {
            return reject(err);
          }

          return resolve(projects);
        });
      });
    },
    getProjectByName(projectName) {
      return new Promise((resolve, reject) => {
        Project.findOne({
          name: projectName
        }, (err, project) => {
          if (err) {
            return reject(err);
          }

          return resolve(project);
        });
      });
    },
    updateProjectAplyersByName(projectName, applyer) {
      return new Promise((resolve, reject) => {
        Project.findOne({
          name: projectName
        }, (err, project) => {
          if (err) {
            return reject(err);
          }
          if (!project.applyers.some(x => x === applyer)) {
            project.applyers.push(applyer);
            project.save();
          }
          return resolve(project);
        });
      });
    },
    updateProjectEmployeesByName(projectName, employee) {
      return new Promise((resolve, reject) => {
        Project.findOne({
          name: projectName
        }, (err, project) => {
          if (err) {
            return reject(err);
          }

          if (!project.employees.some(x => x.employeeName === employee.employeeName)) {
            project.employees.push(employee);
            project.save();
          }
          return resolve(project);
        });
      });
    },
    getProjectsWhichContains(string) {
      let regex = new RegExp(string, 'i');

      return new Promise((resolve, reject) => {
        Project.find({
          name: regex
        }, (err, projects) => {
          if (err) {
            return reject(err);
          }

          return resolve(projects);
        });
      });
    },
    getProjectById(id) {
      return new Promise((resolve, reject) => {
        Project.findOne({
          _id: id
        }, (err, project) => {
          if (err) {
            return reject(err);
          }

          return resolve(project);
        });
      });
    },
    createProject(project) {
      const newProject = Project.getProject(project);

      return new Promise((resolve, reject) => {
        newProject.save(err => {
          if (err) {
            return reject(err);
          }

          return resolve(newProject);
        });
      });
    },
    getProjectBySkill(skill) {
      return new Promise((resolve, reject) => {
        Project.find({
          devSkills: skill
        }, (err, project) => {
          if (err) {
            return reject(err);
          }

          return resolve(project);
        });
      });
    },
    updateProject(project) {
      return new Promise((resolve, reject) => {
        project.save((err, updated) => {
          if (err) {
            return reject(err);
          }

          return resolve(updated);
        });
      });
    }
  };
};<commit_msg>projects-data.js appliers removed when hired<commit_after>/* globals module Promise */

'use strict';

module.exports = function ({
  models
}) {
  const {
    Project
  } = models;

  return {
    getAllProjects() {
      return new Promise((resolve, reject) => {
        Project.find((err, projects) => {
          if (err) {
            return reject(err);
          }

          return resolve(projects);
        });
      });
    },
    getProjectByName(projectName) {
      return new Promise((resolve, reject) => {
        Project.findOne({
          name: projectName
        }, (err, project) => {
          if (err) {
            return reject(err);
          }

          return resolve(project);
        });
      });
    },
    updateProjectAplyersByName(projectName, applyer) {
      return new Promise((resolve, reject) => {
        Project.findOne({
          name: projectName
        }, (err, project) => {
          if (err) {
            return reject(err);
          }
          if (!project.applyers.some(x => x === applyer)) {
            project.applyers.push(applyer);
            project.save();
          }
          return resolve(project);
        });
      });
    },
    updateProjectEmployeesByName(projectName, employee) {
      return new Promise((resolve, reject) => {
        Project.findOne({
          name: projectName
        }, (err, project) => {
          if (err) {
            return reject(err);
          }

          if (!project.employees.some(x => x.employeeName === employee.employeeName)) {
            project.employees.push(employee);
            project.applyers.remove(employee.employeeName);
            project.save();
          }

          return resolve(project);
        });
      });
    },
    getProjectsWhichContains(string) {
      let regex = new RegExp(string, 'i');

      return new Promise((resolve, reject) => {
        Project.find({
          name: regex
        }, (err, projects) => {
          if (err) {
            return reject(err);
          }

          return resolve(projects);
        });
      });
    },
    getProjectById(id) {
      return new Promise((resolve, reject) => {
        Project.findOne({
          _id: id
        }, (err, project) => {
          if (err) {
            return reject(err);
          }

          return resolve(project);
        });
      });
    },
    createProject(project) {
      const newProject = Project.getProject(project);

      return new Promise((resolve, reject) => {
        newProject.save(err => {
          if (err) {
            return reject(err);
          }

          return resolve(newProject);
        });
      });
    },
    getProjectBySkill(skill) {
      return new Promise((resolve, reject) => {
        Project.find({
          devSkills: skill
        }, (err, project) => {
          if (err) {
            return reject(err);
          }

          return resolve(project);
        });
      });
    },
    updateProject(project) {
      return new Promise((resolve, reject) => {
        project.save((err, updated) => {
          if (err) {
            return reject(err);
          }

          return resolve(updated);
        });
      });
    }
  };
};<|endoftext|>


<commit_before>// ========================================================================
// SproutCore
// copyright 2006-2008 Sprout Systems, Inc.
// ========================================================================

require('Core') ;
require('foundation/object') ;

/** @class

  An InputManager knows how to convert incoming keyboard events and convert
  them into actions on a responder.  The default version should provide the
  correct behavior for most people.  However, if you want some special
  behavior, you can always write your own.

  An instance of this input manager is created as a property of
  SC.Responder.  To overide the inputManager used for all responders, replace
  this property with your own instance.  To override the inputManager used
  only for one responder, set the inputManager property on your specific
  instance.

  Note that generally you do not want to write your own inputManager.  They
  are tricky to get right.  Instead, you should implement the various handler
  methods on the responder.

  @extends SC.Object
  @author Charles Jolley
*/
SC.InputManager = SC.Object.extend(
/** @scope SC.InputManager.prototype */ {

  /**
    The is the primary entry point for the inputManager.  If you override
    the input manager, have this method process the key event and invoke
    methods on the responder.
  */
  interpretKeyEvents: function(event, responder)
  {
    var codes = this.codesForEvent(event) ;
    var cmd = codes[0]; var chr = codes[1];
    if (!cmd && !chr) return false ;  //nothing to do.

    // if this is a command key, try to do something about it.
    if (cmd)
    {
      var methodName = SC.MODIFIED_COMMAND_MAP[cmd] || SC.BASE_COMMAND_MAP[cmd.split('_').last()];
      if (methodName && responder.respondsTo(methodName))
      {
        // the responder has a method matching the keybinding... call it.
        return responder[methodName]( event );
      }
    }
    if (chr && responder.respondsTo('insertText'))
    {
      // if we haven't returned yet and there is plain text, then do an insert of the text.
      return responder.insertText(chr);
    }

    return false ; //nothing to do.
  },

  /**
    this will get a standardized command code for the event.  It returns
    null if the event is plain text, not a command code.
  */
  codesForEvent: function(e) {
    var code = e.keyCode ;
    var ret = null ; var key = null ;
    var modifiers = '' ;

    // handle function keys.
    if (code) {
      ret = SC.FUNCTION_KEYS[code] ;
      if (!ret && (e.altKey || e.ctrlKey)) ret = SC.PRINTABLE_KEYS[code] ;
      if (ret) {
        if (e.altKey) modifiers += 'alt_' ;
        if (e.ctrlKey) modifiers += 'ctrl_' ;
        if (e.shiftKey) modifiers += 'shift_' ;
      }
    }

    // otherwise just go get the right key.
    if (!ret) {
      var code = e.charCode || e.keyCode ;
      key = ret = String.fromCharCode(code) ;
      var lowercase = ret.toLowerCase() ;
      if (ret != lowercase) {
        modifiers = 'shift_' ;
        ret = lowercase ;
      } else ret = null ;
    }

    if (ret) ret = modifiers + ret ;
    return [ret, key] ;
  }

});

SC.MODIFIED_COMMAND_MAP = {
  'ctrl_.': 'cancel',
  'shift_tab': 'insertBacktab',
  'shift_left': 'moveLeftAndModifySelection',
  'shift_right': 'moveRightAndModifySelection',
  'shift_up': 'moveUpAndModifySelection',
  'shift_down': 'moveDownAndModifySelection',
  'alt_left': 'moveLeftAndModifySelection',
  'alt_right': 'moveRightAndModifySelection',
  'alt_up': 'moveUpAndModifySelection',
  'alt_down': 'moveDownAndModifySelection',
  'ctrl_a': 'selectAll'
} ;

SC.BASE_COMMAND_MAP = {
  'escape': 'cancel',
  'backspace': 'deleteBackward',
  'delete': 'deleteForward',
  'return': 'insertNewline',
  'tab': 'insertTab',
  'left': 'moveLeft',
  'right': 'moveRight',
  'up': 'moveUp',
  'down': 'moveDown',
  'home': 'moveToBeginningOfDocument',
  'end': 'moveToEndOfDocument',
  'pagedown': 'pageDown',
  'pageup': 'pageUp'
} ;

SC.MODIFIER_KEYS = {
  16:'shift', 17:'ctrl', 18: 'alt'
};

SC.FUNCTION_KEYS = {
  8: 'backspace',  9: 'tab',  13: 'return',  19: 'pause',  27: 'escape',
  32: 'space',  33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home',
  37: 'left', 38: 'up', 39: 'right', 40: 'down', 44: 'printscreen',
  45: 'insert', 46: 'delete', 112: 'f1', 113: 'f2', 114: 'f3', 115: 'f4',
  116: 'f5', 117: 'f7', 119: 'f8', 120: 'f9', 121: 'f10', 122: 'f11',
  123: 'f12', 144: 'numlock', 145: 'scrolllock'
} ;

SC.PRINTABLE_KEYS = {
  48:"0", 49:"1", 50:"2", 51:"3", 52:"4", 53:"5", 54:"6", 55:"7", 56:"8",
  57:"9", 59:";", 61:"=", 65:"a", 66:"b", 67:"c", 68:"d", 69:"e", 70:"f",
  71:"g", 72:"h", 73:"i", 74:"j", 75:"k", 76:"l", 77:"m", 78:"n", 79:"o",
  80:"p", 81:"q", 82:"r", 83:"s", 84:"t", 85:"u", 86:"v", 87:"w", 88:"x",
  89:"y", 90:"z", 107:"+", 109:"-", 110:".", 188:",", 190:".", 191:"/",
  192:"`", 219:"[", 220:"\\", 221:"]", 222:"\""
} ;

// make reverse keycode lookup for using in unit tests...
SC.KEY_CODES = {};
for (var i=0, n=256; i < n; i++)
{
  if (SC.MODIFIER_KEYS[i] !== undefined) {
    SC.KEY_CODES[ SC.MODIFIER_KEYS[i] ] = i;
  } else if (SC.FUNCTION_KEYS[i] !== undefined) {
    SC.KEY_CODES[ SC.FUNCTION_KEYS[i] ] = i;
  } else if (SC.PRINTABLE_KEYS[i] !== undefined) {
    SC.KEY_CODES[ SC.PRINTABLE_KEYS[i] ] = i;
  }
}

<commit_msg>sproutcore now treats space as a printable key instead of a function key.<commit_after>// ========================================================================
// SproutCore
// copyright 2006-2008 Sprout Systems, Inc.
// ========================================================================

require('Core') ;
require('foundation/object') ;

/** @class

  An InputManager knows how to convert incoming keyboard events and convert
  them into actions on a responder.  The default version should provide the
  correct behavior for most people.  However, if you want some special
  behavior, you can always write your own.

  An instance of this input manager is created as a property of
  SC.Responder.  To overide the inputManager used for all responders, replace
  this property with your own instance.  To override the inputManager used
  only for one responder, set the inputManager property on your specific
  instance.

  Note that generally you do not want to write your own inputManager.  They
  are tricky to get right.  Instead, you should implement the various handler
  methods on the responder.

  @extends SC.Object
  @author Charles Jolley
*/
SC.InputManager = SC.Object.extend(
/** @scope SC.InputManager.prototype */ {

  /**
    The is the primary entry point for the inputManager.  If you override
    the input manager, have this method process the key event and invoke
    methods on the responder.
  */
  interpretKeyEvents: function(event, responder)
  {
    var codes = this.codesForEvent(event) ;
    var cmd = codes[0]; var chr = codes[1];
    if (!cmd && !chr) return false ;  //nothing to do.

    // if this is a command key, try to do something about it.
    if (cmd)
    {
      var methodName = SC.MODIFIED_COMMAND_MAP[cmd] || SC.BASE_COMMAND_MAP[cmd.split('_').last()];
      if (methodName && responder.respondsTo(methodName))
      {
        // the responder has a method matching the keybinding... call it.
        return responder[methodName]( event );
      }
    }
    // if(cmd == "space") chr = " ";
    if ( chr && responder.respondsTo('insertText'))
    {
      // if we haven't returned yet and there is plain text, then do an insert of the text.
      return responder.insertText(chr);
    }

    return false ; //nothing to do.
  },

  /**
    this will get a standardized command code for the event.  It returns
    null if the event is plain text, not a command code.
  */
  codesForEvent: function(e) {
    var code = e.keyCode ;
    var ret = null ; var key = null ;
    var modifiers = '' ;

    // handle function keys.
    if (code) {
      ret = SC.FUNCTION_KEYS[code] ;
      if (!ret && (e.altKey || e.ctrlKey)) ret = SC.PRINTABLE_KEYS[code] ;
      if (ret) {
        if (e.altKey) modifiers += 'alt_' ;
        if (e.ctrlKey) modifiers += 'ctrl_' ;
        if (e.shiftKey) modifiers += 'shift_' ;
      }
    }

    // otherwise just go get the right key.
    if (!ret) {
      var code = e.charCode || e.keyCode ;
      key = ret = String.fromCharCode(code) ;
      var lowercase = ret.toLowerCase() ;
      if (ret != lowercase) {
        modifiers = 'shift_' ;
        ret = lowercase ;
      } else ret = null ;
    }

    if (ret) ret = modifiers + ret ;
    return [ret, key] ;
  }

});

SC.MODIFIED_COMMAND_MAP = {
  'ctrl_.': 'cancel',
  'shift_tab': 'insertBacktab',
  'shift_left': 'moveLeftAndModifySelection',
  'shift_right': 'moveRightAndModifySelection',
  'shift_up': 'moveUpAndModifySelection',
  'shift_down': 'moveDownAndModifySelection',
  'alt_left': 'moveLeftAndModifySelection',
  'alt_right': 'moveRightAndModifySelection',
  'alt_up': 'moveUpAndModifySelection',
  'alt_down': 'moveDownAndModifySelection',
  'ctrl_a': 'selectAll'
} ;

SC.BASE_COMMAND_MAP = {
  'escape': 'cancel',
  'backspace': 'deleteBackward',
  'delete': 'deleteForward',
  'return': 'insertNewline',
  'tab': 'insertTab',
  'left': 'moveLeft',
  'right': 'moveRight',
  'up': 'moveUp',
  'down': 'moveDown',
  'home': 'moveToBeginningOfDocument',
  'end': 'moveToEndOfDocument',
  'pagedown': 'pageDown',
  'pageup': 'pageUp'
} ;

SC.MODIFIER_KEYS = {
  16:'shift', 17:'ctrl', 18: 'alt'
};

SC.FUNCTION_KEYS = {
  8: 'backspace',  9: 'tab',  13: 'return',  19: 'pause',  27: 'escape',
  33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home',
  37: 'left', 38: 'up', 39: 'right', 40: 'down', 44: 'printscreen',
  45: 'insert', 46: 'delete', 112: 'f1', 113: 'f2', 114: 'f3', 115: 'f4',
  116: 'f5', 117: 'f7', 119: 'f8', 120: 'f9', 121: 'f10', 122: 'f11',
  123: 'f12', 144: 'numlock', 145: 'scrolllock'
} ;

SC.PRINTABLE_KEYS = {
  32: ' ', 48:"0", 49:"1", 50:"2", 51:"3", 52:"4", 53:"5", 54:"6", 55:"7",
  56:"8", 57:"9", 59:";", 61:"=", 65:"a", 66:"b", 67:"c", 68:"d", 69:"e",
  70:"f", 71:"g", 72:"h", 73:"i", 74:"j", 75:"k", 76:"l", 77:"m", 78:"n",
  79:"o", 80:"p", 81:"q", 82:"r", 83:"s", 84:"t", 85:"u", 86:"v", 87:"w",
  88:"x", 89:"y", 90:"z", 107:"+", 109:"-", 110:".", 188:",", 190:".",
  191:"/", 192:"`", 219:"[", 220:"\\", 221:"]", 222:"\""
} ;

// make reverse keycode lookup for using in unit tests...
SC.KEY_CODES = {};
for (var i=0, n=256; i < n; i++)
{
  if (SC.MODIFIER_KEYS[i] !== undefined) {
    SC.KEY_CODES[ SC.MODIFIER_KEYS[i] ] = i;
  } else if (SC.FUNCTION_KEYS[i] !== undefined) {
    SC.KEY_CODES[ SC.FUNCTION_KEYS[i] ] = i;
  } else if (SC.PRINTABLE_KEYS[i] !== undefined) {
    SC.KEY_CODES[ SC.PRINTABLE_KEYS[i] ] = i;
  }
}

<|endoftext|>


<commit_before>/*
 * fis
 * http://fis.baidu.com/
 */

'use strict';

var CleanCss = require('clean-css');

module.exports = function(content, file, conf){
    conf.processImport = false;
    return CleanCss.process(content, conf);
};<commit_msg>hotfix<commit_after>/*
 * fis
 * http://fis.baidu.com/
 */

'use strict';

var CleanCSS = require('clean-css');

module.exports = function(content, file, conf){
    conf.processImport = false;
    return (new CleanCSS(conf)).minify(content);
};<|endoftext|>


<commit_before>function MainController(resources) {
    this.resources = resources;
    this.logger = this.resources.logger.getLogger('AsterTrace.Express');
}

function CallsController(resources) {
    this.resources = resources;
    this.logger = this.resources.logger.getLogger('AsterTrace.Express');
}

MainController.prototype.home = function (req, res) {
    res.send('hello world');
};
CallsController.prototype.callsList = function (req, res) {
    var pageStart = req.query.pageStart;
    var pageLen = req.query.pageLen;
    var dateStart = req.query.dateStart;
    var dateEnd = req.query.dateEnd;
    var status = req.query.status;
    var online = req.query.online;
    var clid = req.query.clid;
    var dialString = req.query.dialString;
    var queryObject = {};
    var ret = [];
    if (online !== undefined) {
        queryObject.dialStatus = null;
    } else {
        if (status !== 'undefined') {
            queryObject.dialStatus = status;
        }
    }
    if (clid !== 'undefined') {
        var re = new RegExp(clid, "g");
        queryObject.clidName = re;
        queryObject.clidNum = re;
    }
    if (dialString !== 'undefined') {
        var re = new RegExp(dialString, "g");
        queryObject.dialString = re;
        queryObject.dialString = re;
    }
    var options = {};
    options.skip = (pageStart - 1) * pageLen;
    options.limit = pageLen;
    this.resources.mongo.CallModel.find(queryObject, {}, options, function (err, obj) {
        if (err !== null) {
            res.send(err);
        } else {
            ret = obj;
            res.send(ret);
        }
    });
};

exports.callsController = function (resources) { return new CallsController(resources); }
exports.mainController = function (resources) { return new MainController(resources); }
<commit_msg>added apache license to controllers<commit_after>/*!
 * Controllers.
 *
 * Copyright 2011 Marcelo Gornstein <marcelog@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
function MainController(resources) {
    this.resources = resources;
    this.logger = this.resources.logger.getLogger('AsterTrace.Express');
}

function CallsController(resources) {
    this.resources = resources;
    this.logger = this.resources.logger.getLogger('AsterTrace.Express');
}

MainController.prototype.home = function (req, res) {
    res.send('hello world');
};
CallsController.prototype.callsList = function (req, res) {
    var pageStart = req.query.pageStart;
    var pageLen = req.query.pageLen;
    var dateStart = req.query.dateStart;
    var dateEnd = req.query.dateEnd;
    var status = req.query.status;
    var online = req.query.online;
    var clid = req.query.clid;
    var dialString = req.query.dialString;
    var queryObject = {};
    var ret = [];
    if (online !== undefined) {
        queryObject.dialStatus = null;
    } else {
        if (status !== 'undefined') {
            queryObject.dialStatus = status;
        }
    }
    if (clid !== 'undefined') {
        var re = new RegExp(clid, "g");
        queryObject.clidName = re;
        queryObject.clidNum = re;
    }
    if (dialString !== 'undefined') {
        var re = new RegExp(dialString, "g");
        queryObject.dialString = re;
        queryObject.dialString = re;
    }
    var options = {};
    options.skip = (pageStart - 1) * pageLen;
    options.limit = pageLen;
    this.resources.mongo.CallModel.find(queryObject, {}, options, function (err, obj) {
        if (err !== null) {
            res.send(err);
        } else {
            ret = obj;
            res.send(ret);
        }
    });
};

exports.callsController = function (resources) { return new CallsController(resources); }
exports.mainController = function (resources) { return new MainController(resources); }
<|endoftext|>


<commit_before>/* global app:true */

var socket;

var currenttime;
var username='noname';

var width = 600,
	height = 560,
	cellWidth = 56,
	cellHeight = 36, // cell size
	gapWidth = 60;
	gapHeight = 10;

var hour = d3.time.format("%I"),
	minute = d3.time.format("%M"),
	month = d3.time.format("%b"),
	weekday = d3.time.format("%a"),
	date = d3.time.format("%d"),
	ampm = d3.time.format("%p"),
	format = d3.time.format("%b/%d %H:%M%p");

var blockdata = [];

(function() {
  'use strict';

  socket = io.connect('http://171.65.102.132:3006');

  socket.on('postblocks', function(data){
	for (var i=0;i<=data.length/4;i++){
		var block = new Object();
		block.id = i;

		var d = new Date(0);
		d.setTime(data[i*4]);
		block.time = d;

		block.lock = data[i*4+1];
		block.userid = data[i*4+2];
		block.expid = data[i*4+3];
		blockdata.push(block);
	}
	blockdata.length = blockdata.length-2;
	console.dir(blockdata);
	draw(blockdata);
  });

  socket.on('message', function(msg){
	console.log(msg);
  });

  socket.on('connect', function() {
	console.log("Connected!");
	callBlocks(new Date());
  });

  socket.on('disconnect', function() {
	console.log('disconnected');
	chat.html("Disconnected!");
  });

  function callBlocks(ticket){
	console.log(month(ticket)+" "+date(ticket)+" "+hour(ticket)+":"+minute(ticket)+ampm(ticket));

	// +- 1 hour blocks range
	var beginT = d3.time.hour.floor(ticket);
	beginT = d3.time.hour.offset(beginT, -1);
	var endT = d3.time.hour.offset(beginT, 3);

	console.log(month(beginT)+" "+date(beginT)+" "+hour(beginT)+":"+minute(beginT)+ampm(beginT));
	console.log(month(endT)+" "+date(endT)+" "+hour(endT)+":"+minute(endT)+ampm(endT));

	socket.emit('timeline', { type: 'callblocks', user:username, begintime: beginT, endtime: endT});
  }

  function draw(blockdata){
	var tip = d3.tip()
		.attr('class', 'd3-tip')
		.direction('e')
		.offset([0,10])
		.html(function(d) {
			return "time: "+d.time;
		});

	var color = d3.scale.quantize()
    	.domain([-.05, .05])
    	.range(d3.range(11).map(function(d) { return "q" + d + "-11"; }));

	var svg = d3.select("#d3Area").append("svg")
		.attr("width", width)
		.attr("height", height)
		.attr("class", "RdYlGn")
	.append("g")
		.attr("transform", "translate(24, 24)");

	svg.call(tip);

	var column = svg.selectAll(".column")
		.data(blockdata)
	.enter().append("g")
		.attr("class", "column")
		.attr("transform", function (d,i)
		{ return "translate("+ (i-i%12)/12 * (cellWidth+gapWidth)+ ","+i%12 * (cellHeight+gapHeight) + ")"; })
		.on('mouseover', tip.show)
		.on('mouseout', tip.hide);

	column.append("rect")
		.attr("width", cellWidth)
		.attr("height", cellHeight);

	column.append("text")
		.attr("class", "block-name")
		.attr("x",cellWidth/2)
		.attr("y",cellHeight/2)
		.attr("dy", ".3em")
		.style("text-anchor", "middle")
		.text(function(d) {
			var h = d.time.getHours();
			h=("0" + h%12).slice(-2);
			var m = d.time.getMinutes();
			m=("0" + m).slice(-2);
			return h+":"+m;
		})
		.on('mouseover', tip.show)
		.on('mouseout', tip.hide);
  }

  app = app || {};

  app.Blocks = Backbone.Model.extend({
    url: '/account/timeline/',
    defaults: {
      reqTime:'',
      username: '',
      timestamp: ''
    }
  });

  app.BlocksView = Backbone.View.extend({
    el: '#blocks_nav',
    template: _.template( $('#tmpl-blocks_nav').html() ),
    events: {
      'click .btn-prev': 'reqPrev',
      'click .btn-now': 'reqNow',
      'click .btn-next': 'reqNext'
    },
    initialize: function() {
      this.model = new app.Blocks();
      this.listenTo(this.model, 'sync', this.render);
      this.render();
    },
    render: function() {
      this.$el.html(this.template( this.model.attributes));
    },
    reqPrev: function() {
      this.model.save({
        reqTime: '',
        username: '',
        timestamp: ''
      },{
        success: function(model, response) {
          if (response.success) {
            location.href = '/account/timeline/';
          }
          else {
            model.set(response);
          }
        }
      });
    },
    reqNow: function() {
      // request new hour
      this.model.save({
        reqTime: '',
        username: '',
        timestamp: ''
      },{
        success: function(model, response) {
          if (response.success) {
            location.href = '/account/timeline/';
          }
          else {
            model.set(response);
          }
        }
      });
    },
    reqNext: function() {
      // request new hour
      this.model.save({
        reqTime: '',
        username: '',
        timestamp: ''
      },{
        success: function(model, response) {
          if (response.success) {
            location.href = '/account/timeline/';
          }
          else {
            model.set(response);
          }
        }
      });
    }
  });

  $(document).ready(function() {
    app.blocksView = new app.BlocksView();
  });

}());<commit_msg>d3 timeline<commit_after>/* global app:true */

var socket;

var currenttime;
var username='noname';

var width = 600,
	height = 600,
	cellWidth = 56,
	cellHeight = 36, // cell size
	gapWidth = 60;
	gapHeight = 10;

var hour = d3.time.format("%I"),
	minute = d3.time.format("%M"),
	month = d3.time.format("%b"),
	weekday = d3.time.format("%a"),
	date = d3.time.format("%d"),
	ampm = d3.time.format("%p"),
	format = d3.time.format("%b/%d %H:%M%p");

var blockdata = [];

(function() {
  'use strict';

  socket = io.connect('http://171.65.102.132:3006');

  socket.on('postblocks', function(data){
	for (var i=0;i<=data.length/4;i++){
		var block = new Object();
		block.id = i;

		var d = new Date(0);
		d.setTime(data[i*4]);
		block.time = d;

		block.lock = data[i*4+1];
		block.userid = data[i*4+2];
		block.expid = data[i*4+3];
		blockdata.push(block);
	}
	blockdata.length = blockdata.length-2;
	console.dir(blockdata);
	draw(blockdata);
  });

  socket.on('message', function(msg){
	console.log(msg);
  });

  socket.on('connect', function() {
	console.log("Connected!");
	callBlocks(new Date());
  });

  socket.on('disconnect', function() {
	console.log('disconnected');
	chat.html("Disconnected!");
  });

  function callBlocks(ticket){
	console.log(month(ticket)+" "+date(ticket)+" "+hour(ticket)+":"+minute(ticket)+ampm(ticket));

	// +- 1 hour blocks range
	var beginT = d3.time.hour.floor(ticket);
	beginT = d3.time.hour.offset(beginT, -1);
	var endT = d3.time.hour.offset(beginT, 3);

	console.log(month(beginT)+" "+date(beginT)+" "+hour(beginT)+":"+minute(beginT)+ampm(beginT));
	console.log(month(endT)+" "+date(endT)+" "+hour(endT)+":"+minute(endT)+ampm(endT));

	socket.emit('timeline', { type: 'callblocks', user:username, begintime: beginT, endtime: endT});
  }

  function draw(blockdata){
	var tip = d3.tip()
		.attr('class', 'd3-tip')
		.direction('e')
		.offset([0,10])
		.html(function(d) {
			return "time: "+d.time;
		});

	var color = d3.scale.quantize()
    	.domain([-.05, .05])
    	.range(d3.range(11).map(function(d) { return "q" + d + "-11"; }));

	var svg = d3.select("#d3Area").append("svg")
		.attr("width", width)
		.attr("height", height)
		.attr("class", "RdYlGn")
	.append("g")
		.attr("transform", "translate(24, 24)");

	svg.call(tip);

	var column = svg.selectAll(".column")
		.data(blockdata)
	.enter().append("g")
		.attr("class", "column")
		.attr("transform", function (d,i)
		{ return "translate("+ (i-i%12)/12 * (cellWidth+gapWidth)+ ","+i%12 * (cellHeight+gapHeight) + ")"; })
		.on('mouseover', tip.show)
		.on('mouseout', tip.hide);

	column.append("rect")
		.attr("width", cellWidth)
		.attr("height", cellHeight);

	column.append("text")
		.attr("class", "block-name")
		.attr("x",cellWidth/2)
		.attr("y",cellHeight/2)
		.attr("dy", ".3em")
		.style("text-anchor", "middle")
		.text(function(d) {
			var h = d.time.getHours();
			h=("0" + h%12).slice(-2);
			var m = d.time.getMinutes();
			m=("0" + m).slice(-2);
			return h+":"+m;
		})
		.on('mouseover', tip.show)
		.on('mouseout', tip.hide);
  }

  app = app || {};

  app.Blocks = Backbone.Model.extend({
    url: '/account/timeline/',
    defaults: {
      reqTime:'',
      username: '',
      timestamp: ''
    }
  });

  app.BlocksView = Backbone.View.extend({
    el: '#blocks_nav',
    template: _.template( $('#tmpl-blocks_nav').html() ),
    events: {
      'click .btn-prev': 'reqPrev',
      'click .btn-now': 'reqNow',
      'click .btn-next': 'reqNext'
    },
    initialize: function() {
      this.model = new app.Blocks();
      this.listenTo(this.model, 'sync', this.render);
      this.render();
    },
    render: function() {
      this.$el.html(this.template( this.model.attributes));
    },
    reqPrev: function() {
      var d = new Date();
      d.setHours(d.getHours() + 1);
      callBlocks(d);
    },
    reqNow: function() {
      callBlocks(new Date());
    },
    reqNext: function() {
      // request new hour
      this.model.save({
        reqTime: '',
        username: '',
        timestamp: ''
      },{
        success: function(model, response) {
          if (response.success) {
            location.href = '/account/timeline/';
          }
          else {
            model.set(response);
          }
        }
      });
    }
  });

  $(document).ready(function() {
    app.blocksView = new app.BlocksView();
  });

}());<|endoftext|>


<commit_before>define(['jquery', 'base/js/dialog'], function ($, dialog) {
    var api = "/spark/api/v1";

    var show_running_jobs = function() {
        var element = $('<div/>');

        $.getJSON(api + '/applications').done(function(data) {
            data.forEach(function(e, i) {
                var application_div = $('<div/>');
                var application_table = $('<table/>').addClass('table table-hover');

                var header_row = $('<tr/>');
                header_row.append($('<th/>').text('Job ID'));
                header_row.append($('<th/>').text('Job Name'));
                header_row.append($('<th/>').text('Progress'));
                application_table.append(header_row);

                $.getJSON(api + '/applications/' + e.id + '/jobs').done(function (jobs) {
                    jobs.forEach(function(e, i) {
                        var row = $('<tr/>');
                        row.append($('<td/>').text(e.jobId));
                        row.append($('<td/>').text(e.name));

                        var status_class;
                        switch(e.status) {
                            case 'SUCCEEDED':
                                status_class = 'progress-bar-success';
                                break;
                            case 'RUNNING':
                                status_class = 'progress-bar-info';
                                break;
                            // TODO: find error case status
                        }

                        // progress defined in percent
                        var progress = e.numCompletedTasks / e.numTasks * 100;

                        var progress_bar_div = $('<div/>').addClass('progress').css({'min-width': '100px', 'margin-bottom': 0});
                        var progress_bar = $('<div/>')
                            .addClass('progress-bar ' + status_class)
                            .attr('role', 'progressbar')
                            .attr('aria-valuenow', progress)
                            .attr('aria-valuemin', 0)
                            .attr('aria-valuemax', 100)
                            .css('width', progress + '%')
                            .text(e.numCompletedTasks + ' out of ' + e.numTasks + ' tasks');
                        progress_bar_div.append(progress_bar);
                        row.append($('<td/>').append(progress_bar_div));

                        application_table.append(row);
                    })
                })
                application_div.append(application_table);
                element.append(application_div);
            });
        })

        var modal = dialog.modal({
            title: "Running Spark Jobs",
            body: element,
            buttons: {
                "Close": {}
            }
        });
        modal.addClass("modal_stretch");
    };

    var load_ipython_extension = function () {
        Jupyter.keyboard_manager.command_shortcuts.add_shortcut('Alt-S', show_running_jobs);
        Jupyter.toolbar.add_buttons_group([{
            'label':    'show running Spark jobs',
            'icon':     'fa-tasks',
            'callback': show_running_jobs,
            'id':       'show_running_jobs'
        }]);
    };

    return {
        load_ipython_extension: load_ipython_extension
    };
});<commit_msg>Add application name and ID to each table<commit_after>define(['jquery', 'base/js/dialog'], function ($, dialog) {
    var api = "/spark/api/v1";

    var show_running_jobs = function() {
        var element = $('<div/>');

        $.getJSON(api + '/applications').done(function(data) {
            data.forEach(function(e, i) {
                var application_div = $('<div/>');
                application_div.append($('<h5/>').text(e.name + ': ' + e.id));
                var application_table = $('<table/>').addClass('table table-hover');

                var header_row = $('<tr/>');
                header_row.append($('<th/>').text('Job ID'));
                header_row.append($('<th/>').text('Job Name'));
                header_row.append($('<th/>').text('Progress'));
                application_table.append(header_row);

                $.getJSON(api + '/applications/' + e.id + '/jobs').done(function (jobs) {
                    jobs.forEach(function(e, i) {
                        var row = $('<tr/>');
                        row.append($('<td/>').text(e.jobId));
                        row.append($('<td/>').text(e.name));

                        var status_class;
                        switch(e.status) {
                            case 'SUCCEEDED':
                                status_class = 'progress-bar-success';
                                break;
                            case 'RUNNING':
                                status_class = 'progress-bar-info';
                                break;
                            // TODO: find error case status
                        }

                        // progress defined in percent
                        var progress = e.numCompletedTasks / e.numTasks * 100;

                        var progress_bar_div = $('<div/>').addClass('progress').css({'min-width': '100px', 'margin-bottom': 0});
                        var progress_bar = $('<div/>')
                            .addClass('progress-bar ' + status_class)
                            .attr('role', 'progressbar')
                            .attr('aria-valuenow', progress)
                            .attr('aria-valuemin', 0)
                            .attr('aria-valuemax', 100)
                            .css('width', progress + '%')
                            .text(e.numCompletedTasks + ' out of ' + e.numTasks + ' tasks');
                        progress_bar_div.append(progress_bar);
                        row.append($('<td/>').append(progress_bar_div));

                        application_table.append(row);
                    })
                })
                application_div.append(application_table);
                element.append(application_div);
            });
        })

        var modal = dialog.modal({
            title: "Running Spark Jobs",
            body: element,
            buttons: {
                "Close": {}
            }
        });
        modal.addClass("modal_stretch");
    };

    var load_ipython_extension = function () {
        Jupyter.keyboard_manager.command_shortcuts.add_shortcut('Alt-S', show_running_jobs);
        Jupyter.toolbar.add_buttons_group([{
            'label':    'show running Spark jobs',
            'icon':     'fa-tasks',
            'callback': show_running_jobs,
            'id':       'show_running_jobs'
        }]);
    };

    return {
        load_ipython_extension: load_ipython_extension
    };
});<|endoftext|>


<commit_before>function showDiv(divName) {
  $('.all').hide();
  $(divName).show();
}

// When the user clicks the button
$('.btn-username').click(processForm, function(){
	showDiv(".prep");
	$('.btn-all').hide();
	setTimeout(function() {$('.btn-prep').show();},10000);

});

// When the user clicks the button
$('.btn-prep').click(function(){
	showDiv(".instruction");
	setTimeout(function() {$('.btn-instruction').show();},10000);
})

// Get the form, listen to its submit event

$('.form-set-username').on('submit', processForm);

$('.btn-instruction').click(finishedOnboarding);

// function to run when the form is submitted
function processForm() {

	showDiv(".prep");
	$('.btn-all').hide();
	setTimeout(function() {$('.btn-prep').show();},10000);
 // get the entered user name from the input
	var username = $('input').val();
	if (username == null || username == ""){
		username = "anonymous";
	}
 	localStorage.setItem('username', username);
		database.ref('users/'+ username).set({
    	username: username
    });
 	return false;
};

showDiv(".username")
startCurrentView();

<commit_msg>speed up on the button<commit_after>function showDiv(divName) {
  $('.all').hide();
  $(divName).show();
}

// When the user clicks the button
$('.btn-username').click(processForm, function(){
	showDiv(".prep");
	$('.btn-all').hide();
	setTimeout(function() {$('.btn-prep').show();},3000);

});

// When the user clicks the button
$('.btn-prep').click(function(){
	showDiv(".instruction");
	setTimeout(function() {$('.btn-instruction').show();},3000);
})

// Get the form, listen to its submit event

$('.form-set-username').on('submit', processForm);

$('.btn-instruction').click(finishedCurrentView);

// function to run when the form is submitted
function processForm() {

	showDiv(".prep");
	$('.btn-all').hide();
	setTimeout(function() {$('.btn-prep').show();},3000);
 // get the entered user name from the input
	var username = $('input').val();
 	localStorage.setItem('username', username);
		database.ref('users/'+ username).set({
    	username: username
    });
 	return false;
};

showDiv(".username")
startCurrentView();

<|endoftext|>


<commit_before>
var x = 100,
    y = 100,
    client_color = '#'+Math.floor(Math.random()*16777215).toString(16),
    speed = 1,
    width = 500,
    height = 500;

var left, right, up, down;
left = right = up = down = false;
var edging = false;

var websocket;

var all_clients = {};

function key_down(e) {
    switch (e.keyCode) {
        case 40:
            down = true;
            break;

        case 38:
            up = true;
            break;

        case 37:
            left = true;
            break;

        case 39:
            right = true;
            break;
    }
}

function key_up(e) {
    switch (e.keyCode) {
        case 40:
            down = false;
            break;

        case 38:
            up = false;
            break;

        case 37:
            left = false;
            break;

        case 39:
            right = false;
            break;
    }
}

function update_position() {
    // Respond to user input
    if (down) {
        y += speed;
    }
    if (up) {
        y -= speed;
    }
    if (left) {
        x -= speed;
    }
    if (right) {
        x += speed;
    }

    //Don't let them out of the box
    if (x > width){
        x = width;
    }
    if (x < 0){
        x = 0;
    }
    if (y > height){
        y = height;
    }
    if (y < 0){
        y = 0;
    }

    if (x > 0 && y > 0 && x < width && y < height) {
        edging = false;
    }
    else {
        edging = true;
    }
}

function redraw() {

    var c = document.getElementById("dot_canvas");
    var context = c.getContext("2d");
    context.fillStyle = "#1F8FCE";
    if (edging) {
        context.fillStyle = '#'+Math.floor(Math.random()*16777215).toString(16);
    }
    context.fillRect(0, 0, width, height);

    var radius = 15;
    context.beginPath();
    context.arc(x, y, radius, 0, 2 * Math.PI, false);
    context.fillStyle = client_color;
    context.fill();
    context.lineWidth = 5;
    context.strokeStyle = '#003300';
    context.stroke();

    // console.log(all_clients);

    // for (var i = all_clients.length - 1; i >= 0; i--) {
    //     client = all_clients[i];

    //     console.log(client);

    // };

    $.each(all_clients, function(col, client) {
        console.log(client);
        if (client['color'] != client_color) {
            context.beginPath();
            context.arc(client.x, client.y, radius, 0, 2 * Math.PI, false);
            context.fillStyle = client.color;
            context.fill();
            context.lineWidth = 5;
            context.strokeStyle = '#003300';
            context.stroke();
        }
    })
}

function say_stuff() {
    client = {
        x: x,
        y: y,
        color: client_color,
    };
    websocket.send(JSON.stringify(client));
}

$(function(){
    window.onkeydown = key_down;
    window.onkeyup = key_up;
    setInterval(update_position, 10);
    setInterval(redraw, 100);

    websocket = new WebSocket("ws://" + window.location.host + ":8000/ws");
    websocket.onclose = function(e) {
        console.log('closing');
    };

    websocket.onmessage = function(e) {
        data = JSON.parse(e.data);
        all_clients[data['color']] = data;
    };

    setInterval(say_stuff, 1000);

});

<commit_msg>better timings<commit_after>
var x = 100,
    y = 100,
    client_color = '#'+Math.floor(Math.random()*16777215).toString(16),
    speed = 1,
    width = 500,
    height = 500;

var left, right, up, down;
left = right = up = down = false;
var edging = false;

var websocket;

var all_clients = {};

function key_down(e) {
    switch (e.keyCode) {
        case 40:
            down = true;
            break;

        case 38:
            up = true;
            break;

        case 37:
            left = true;
            break;

        case 39:
            right = true;
            break;
    }
}

function key_up(e) {
    switch (e.keyCode) {
        case 40:
            down = false;
            break;

        case 38:
            up = false;
            break;

        case 37:
            left = false;
            break;

        case 39:
            right = false;
            break;
    }
}

function update_position() {
    // Respond to user input
    if (down) {
        y += speed;
    }
    if (up) {
        y -= speed;
    }
    if (left) {
        x -= speed;
    }
    if (right) {
        x += speed;
    }

    //Don't let them out of the box
    if (x > width){
        x = width;
    }
    if (x < 0){
        x = 0;
    }
    if (y > height){
        y = height;
    }
    if (y < 0){
        y = 0;
    }

    if (x > 0 && y > 0 && x < width && y < height) {
        edging = false;
    }
    else {
        edging = true;
    }
}

function redraw() {

    var c = document.getElementById("dot_canvas");
    var context = c.getContext("2d");
    context.fillStyle = "#1F8FCE";
    if (edging) {
        context.fillStyle = '#'+Math.floor(Math.random()*16777215).toString(16);
    }
    context.fillRect(0, 0, width, height);

    var radius = 15;
    context.beginPath();
    context.arc(x, y, radius, 0, 2 * Math.PI, false);
    context.fillStyle = client_color;
    context.fill();
    context.lineWidth = 5;
    context.strokeStyle = '#003300';
    context.stroke();

    $.each(all_clients, function(col, client) {
        console.log(client);
        if (client['color'] != client_color) {
            context.beginPath();
            context.arc(client.x, client.y, radius, 0, 2 * Math.PI, false);
            context.fillStyle = client.color;
            context.fill();
            context.lineWidth = 5;
            context.strokeStyle = '#003300';
            context.stroke();
        }
    })
}

function say_stuff() {
    client = {
        x: x,
        y: y,
        color: client_color,
    };
    websocket.send(JSON.stringify(client));
}

$(function(){
    window.onkeydown = key_down;
    window.onkeyup = key_up;
    setInterval(update_position, 10);
    setInterval(redraw, 10);

    websocket = new WebSocket("ws://" + window.location.host + ":8000/ws");
    websocket.onclose = function(e) {
        console.log('closing');
    };

    websocket.onmessage = function(e) {
        data = JSON.parse(e.data);
        all_clients[data['color']] = data;
    };

    setInterval(say_stuff, 10);

});

<|endoftext|>


<commit_before>/* formating.js
 * Written by Dominic Shelton.
 * Provides a number of functions for formatting text, cards and decks on Slack using the Slack API and Markdown.
 */
'use strict';

module.exports = {cardHelpMessage, deckHelpMessage, cardNoHitsMessage, deckNoHitsMessage, formatTitle, formatDecklist, formatCards, formatText};

var colours = require('./colours.json');
var packs = require('./datapacks.json');

var thumbsURL = process.env.THUMBS_URL;
var messages = {
    noCardHits: [
        "The run was successful but you didn't access _\u200b[cards]\u200b_.",
        "I was unable to find _\u200b[cards]\u200b_ in any of my remotes.",
        "Despite 822 Medium counters, _\u200b[cards]\u200b_ wasn't found.",
        "The Near-Earth Hub couldn't locate _\u200b[cards]\u200b_."
    ],
    noDeckHits: [
        "The archetype of that deck would be _\u200bnon-existant\u200b_."
    ],
    helpBrackets:
        "Search for a card by (partial) name, or acronym, or a decklist by its netrunnerdb link e.g.\`\`\`[sneakdoor] [hiemdal] [etf]\n[netrunnerdb\u200b.com/en/decklist/17055/example]\`\`\`",
    helpDeck:
        "Search for a decklist by its netrunnerdb link or ID number e.g.\`\`\`[command] 12345, [command] netrunnerdb\u200b.com/en/decklist/17055/example\`\`\`",
    helpCard:
        "Search for a card by (partial) name, approximation or acronym e.g.\`\`\`[command]sneakdoor, [command]hiemdal, [command]etf\`\`\`"
};
var headings = [
    ['Event', 'Hardware', 'Resource', 'Agenda', 'Asset', 'Upgrade', 'Operation'],
    ['Icebreaker', 'Program', 'Barrier', 'Code Gate', 'Sentry', 'Multi', 'Other']
];
var stats = [
    ['baselink', ' :_link:'],
    ['cost', ':_credit:'],
    ['memoryunits', ' :_mu:'],
    ['strength', ' str'],
    ['trash', ' :_trash:'],
    ['advancementcost', ' :_advance:'],
    ['minimumdecksize', ' :_deck:'],
    ['influencelimit', '•'],
    ['agendapoints', ' :_agenda:']
];

function influenceDots(influence) {
    return '•'.repeat(influence);
}

function getPack(code) {
    var cycle = packs[Math.floor(code/1000)];
    if (Array.isArray(cycle)) {
        cycle = cycle[Math.floor(((code % 1000) - 1) / 20)];
    }
    return '_\u200b' + cycle + '\u200b_';
}

function formatLink(text, url) {
    return '<' + url + '|' + text + '>';
}

function getFactionEmoji(faction) {
    return ':_' + faction.replace(/\s.*/, '').toLowerCase() + ':';
}

function getCardNoHitsMessage(text) {
    var r = Math.floor(Math.random() * messages.noCardHits.length);
    return messages.noCardHits[r].replace(/\[cards\]/g, text);
}

function cardHelpMessage(command) {
    if (command) {
        return {
            text: messages.helpCard.replace(/\[command\]/g, command + ' ')
        };
    }
    return {
        text: messages.helpBrackets
    };
};

function deckHelpMessage(command) {
    return {
        text: messages.helpDeck.replace(/\[command\]/g, command)
    };
};

// Generates a message indicating that cards weren't found, by concatenating the names with commas and 'or'
function cardNoHitsMessage(cards) {
    var text;
    if (cards.length >= 2) {
        text = cards.slice(0, cards.length - 1).join(', ');
        text += ' or ' + cards[cards.length - 1];
    } else {
        text = cards[0];
    }
    var message = getCardNoHitsMessage(text);
    return {
        text: message
    };
};

function deckNoHitsMessage() {
    var r = Math.floor(Math.random() * messages.noDeckHits.length);
    return {
        text: messages.noDeckHits[r]
    };
};

// Makes the title text bold and makes a link if requested
function formatTitle(title, url) {
    title = '*\u200b' + title + '\u200b*';
    if (url && url !== '') {
        return formatLink(title, url);
    }
    return title;
};

function formatDecklist(decklist) {
    // Initialise the return object.
    var o = {text: '', attachments:[{mrkdwn_in: ['pretext', 'fields']}]};
    var faction = decklist.cards.Identity[0].card.faction;
    var usedInfluence = 0;
    var decksize = 0;
    var agendapoints = 0;
    var fields = [];
    // Initialise the newestCard var to a card that is guaranteed to be in every deck.
    var newestCard = parseInt(decklist.cards.Identity[0].card.code);
    o.text = formatTitle(decklist.name, decklist.url);
    o.text += ' - _\u200b' + decklist.creator + '\u200b_';
    for (let column in headings) {
        // Create the columns as Slack 'fields'.
        fields[column] = {title: '', value: '', short: true};
        for (let heading in headings[column]) {
            var type = headings[column][heading];
            // Check if the deck actually contains cards of the specified heading
            if (decklist.cards[type]) {
                // If this is not the first heading, add padding after the previous.
                if (heading != 0) {
                    fields[column].value += '\n\n';
                }
                fields[column].value += formatTitle(type);
                // Iterate through all the cards of the type in the decklist.
                for (let i in decklist.cards[type]) {
                    var card = decklist.cards[type][i];
                    var code = parseInt(card.card.code);
                    fields[column].value += '\n' + card.quantity;
                    fields[column].value += ' × ' + formatLink(card.card.title, card.card.url);
                    decksize += card.quantity;
                    // Check that the card is not newer than the previous newest card.
                    if (code > newestCard) {
                        newestCard = code;
                    }
                    if (card.card.agendapoints) {
                        agendapoints += card.card.agendapoints * card.quantity;
                    }
                    // Add influence dots after the card name if required.
                    if (card.card.faction !== faction) {
                        var inf = card.quantity * card.card.factioncost;
                        fields[column].value += ' ' + influenceDots(inf);
                        usedInfluence += inf;
                    }
                }
            }
        }
    }
    o.attachments[0].color = colours[faction];
    o.attachments[0].fields = fields;
    // The identity of the decklist is displayed before the decklist.
    o.attachments[0].pretext = formatLink(decklist.cards.Identity[0].card.title,
            decklist.cards.Identity[0].card.url);
    o.attachments[0].pretext += '\n' + decksize + ' :_deck: (min ';
    o.attachments[0].pretext +=  decklist.cards.Identity[0].card.minimumdecksize;
    o.attachments[0].pretext += ') - ' + usedInfluence + '/';
    o.attachments[0].pretext += (decklist.cards.Identity[0].card.influencelimit || '∞') + '•';
    if (decklist.cards.Identity[0].card.side !== 'Runner') {
        o.attachments[0].pretext += ' - ' + agendapoints + ' :_agenda:';
    }
    o.attachments[0].pretext += '\nCards up to ' + getPack(newestCard);
    return o;
};

function formatCards(cards, missing) {
    var o;
    // If there are cards that could not be found, tell the user.
    if (missing && missing.length > 0) {
        o = cardNoHitsMessage(missing);
        o.attachments = [];
    } else {
        o = {text:'', attachments:[]};
    }
    // Display the cards that were found either way.
    for (var i = 0; i < cards.length; i++) {
        var a = {pretext: '', mrkdwn_in: ['pretext', 'text']};
        var faction = cards[i].faction;
        var title = cards[i].title;
        if (cards[i].uniqueness){
            title = '◆ ' + title;
        }
        // If the Slack message is blank, put the title of the first card there.
        // The Slack API won't display messages with blank text even when there are attachments.
        if (o.text === '') {
            o.text = formatTitle(title, cards[0].url);
        } else {
            a.pretext = formatTitle(title, cards[i].url) + '\n';
        }
        // Append the rest of the card details to the attachment.
        a.pretext += '*\u200b' + cards[i].type;
        if (cards[i].subtype ) {
            a.pretext += ':\u200b* ' + cards[i].subtype;
        } else {
            a.pretext += '\u200b*';
        }
        a.pretext += ' - ' + getFactionEmoji(faction);
        if (cards[i].factioncost) {
            a.pretext += influenceDots(cards[i].factioncost);
        }
        if (cards[i].mwl) {
            a.pretext += '☆';
        }
        a.pretext += '\n';
        var first = true;
        // For some cards, the cost is actually a rez cost, this should be reflected in the emoji.
        if (cards[i].type === 'Asset' || cards[i].type === 'Upgrade' || cards[i].type === 'ICE') {
            stats[1][1] = ' :_rez:';
        } else {
            stats[1][1] = ':_credit:';
        }
        // Iterate through the possible card stats adding them to the text where present.
        for (var j = 0; j < stats.length; j++) {
            if (cards[i][stats[j][0]] || cards[i][stats[j][0]] === 0) {
                if (!first) {
                    a.pretext += ' - ';
                }
                a.pretext += cards[i][stats[j][0]] + stats[j][1];
                first = false;
            // Special case for draft IDs with infinite influence limit
            } else if (cards[i].type === 'Identity' && stats[j][0] === 'influencelimit' && !cards[i].influencelimit) {
                a.pretext += ' - ∞•';
            }
        }
        // Replace memory units with the slack emoji
        a.pretext = a.pretext.replace(/(\d|X)\s*:_mu:/gi, function (x) {
            return x.replace(/(.).*/, ':_$1mu:').toLowerCase();
        });
        a.pretext += ' - ' + getPack(parseInt(cards[i].code));
        a.color = colours[faction];
        // Add the card text to the attachment if present.
        if (cards[i].text) {
            a.text = formatText(cards[i].text);
        }
        a.thumb_url = thumbsURL + cards[i].code + '.png';
        o.attachments.push(a);
    }
    return o;
};

// Replace all the html and nrdb text with the Slack equivalent.
function formatText(text) {
    if (!text) return text;

    text = text.replace(/\r\n/g, '\n');

    // NRDB symbols to Slack emoji.
    text = text.replace(/\[Credits\]/g, ':_credit:');
    text = text.replace(/\[Recurring\ Credits\]/g, ':_recurringcredit:');
    text = text.replace(/\[Click\]/g, ':_click:');
    text = text.replace(/\ *\[Link\]/g, ' :_link:');
    text = text.replace(/\[Trash\]/g, ':_trash:');
    text = text.replace(/\[Subroutine\]/g, ':_subroutine:');
    // Individual mu emoji for numbers and 'Xmu'
    text = text.replace(/(\d|X)\s*\[Memory\ Unit\]/gi, function (x) {
        return x.replace(/(.).*/, ':_$1mu:').toLowerCase();
    });
    text = text.replace(/\[Memory Unit\]/g, ':_mu:');

    // HTML bold to Slack bold
    text = text.replace(/<strong>/g, '*\u200b');
    text = text.replace(/<\/strong>/g, '\u200b*');
    // HTML superscript to unicode superscript since Slack markdown doesn't support it.
    text = text.replace(/<sup>(?:\d|X)+<\/sup>/gi, function(x){
        x = x.replace(/<sup>|<\/sup>/g, '');
        x = x.replace(/X/i,'ˣ');
        x = x.replace(/\d/g, function(d){
            return ['⁰','¹','²','³','⁴','⁵','⁶','⁷','⁸','⁹'][parseInt(d)];
        });
        return x;
    });

    // Replace nrdb faction symbols with Slack emoji
    text = text.replace(/\[(jinteki|weyland-consortium|nbn|haas-bioroid)\]/, (a, x) => {
        return ":_" + x.replace(/-.*/, '') + ":";
    });

    text = text.replace(/&/g, '&');
    text = text.replace(/</g, '<');
    text = text.replace(/>/g, '>');

    return text;
};

<commit_msg>Added MWL support to decklists.<commit_after>/* formating.js
 * Written by Dominic Shelton.
 * Provides a number of functions for formatting text, cards and decks on Slack using the Slack API and Markdown.
 */
'use strict';

module.exports = {cardHelpMessage, deckHelpMessage, cardNoHitsMessage, deckNoHitsMessage, formatTitle, formatDecklist, formatCards, formatText};

var colours = require('./colours.json');
var packs = require('./datapacks.json');

var thumbsURL = process.env.THUMBS_URL;
var messages = {
    noCardHits: [
        "The run was successful but you didn't access _\u200b[cards]\u200b_.",
        "I was unable to find _\u200b[cards]\u200b_ in any of my remotes.",
        "Despite 822 Medium counters, _\u200b[cards]\u200b_ wasn't found.",
        "The Near-Earth Hub couldn't locate _\u200b[cards]\u200b_."
    ],
    noDeckHits: [
        "The archetype of that deck would be _\u200bnon-existant\u200b_."
    ],
    helpBrackets:
        "Search for a card by (partial) name, or acronym, or a decklist by its netrunnerdb link e.g.\`\`\`[sneakdoor] [hiemdal] [etf]\n[netrunnerdb\u200b.com/en/decklist/17055/example]\`\`\`",
    helpDeck:
        "Search for a decklist by its netrunnerdb link or ID number e.g.\`\`\`[command] 12345, [command] netrunnerdb\u200b.com/en/decklist/17055/example\`\`\`",
    helpCard:
        "Search for a card by (partial) name, approximation or acronym e.g.\`\`\`[command]sneakdoor, [command]hiemdal, [command]etf\`\`\`"
};
var headings = [
    ['Event', 'Hardware', 'Resource', 'Agenda', 'Asset', 'Upgrade', 'Operation'],
    ['Icebreaker', 'Program', 'Barrier', 'Code Gate', 'Sentry', 'Multi', 'Other']
];
var stats = [
    ['baselink', ' :_link:'],
    ['cost', ':_credit:'],
    ['memoryunits', ' :_mu:'],
    ['strength', ' str'],
    ['trash', ' :_trash:'],
    ['advancementcost', ' :_advance:'],
    ['minimumdecksize', ' :_deck:'],
    ['influencelimit', '•'],
    ['agendapoints', ' :_agenda:']
];

function influenceDots(influence) {
    return '•'.repeat(influence);
}

function getPack(code) {
    var cycle = packs[Math.floor(code/1000)];
    if (Array.isArray(cycle)) {
        cycle = cycle[Math.floor(((code % 1000) - 1) / 20)];
    }
    return '_\u200b' + cycle + '\u200b_';
}

function formatLink(text, url) {
    return '<' + url + '|' + text + '>';
}

function getFactionEmoji(faction) {
    return ':_' + faction.replace(/\s.*/, '').toLowerCase() + ':';
}

function getCardNoHitsMessage(text) {
    var r = Math.floor(Math.random() * messages.noCardHits.length);
    return messages.noCardHits[r].replace(/\[cards\]/g, text);
}

function cardHelpMessage(command) {
    if (command) {
        return {
            text: messages.helpCard.replace(/\[command\]/g, command + ' ')
        };
    }
    return {
        text: messages.helpBrackets
    };
};

function deckHelpMessage(command) {
    return {
        text: messages.helpDeck.replace(/\[command\]/g, command)
    };
};

// Generates a message indicating that cards weren't found, by concatenating the names with commas and 'or'
function cardNoHitsMessage(cards) {
    var text;
    if (cards.length >= 2) {
        text = cards.slice(0, cards.length - 1).join(', ');
        text += ' or ' + cards[cards.length - 1];
    } else {
        text = cards[0];
    }
    var message = getCardNoHitsMessage(text);
    return {
        text: message
    };
};

function deckNoHitsMessage() {
    var r = Math.floor(Math.random() * messages.noDeckHits.length);
    return {
        text: messages.noDeckHits[r]
    };
};

// Makes the title text bold and makes a link if requested
function formatTitle(title, url) {
    title = '*\u200b' + title + '\u200b*';
    if (url && url !== '') {
        return formatLink(title, url);
    }
    return title;
};

function formatDecklist(decklist) {
    // Initialise the return object.
    var o = {text: '', attachments:[{mrkdwn_in: ['pretext', 'fields']}]};
    var faction = decklist.cards.Identity[0].card.faction;
    var usedInfluence = 0;
    var mwlDeduction = 0;
    var decksize = 0;
    var agendapoints = 0;
    var fields = [];
    // Initialise the newestCard var to a card that is guaranteed to be in every deck.
    var newestCard = parseInt(decklist.cards.Identity[0].card.code);
    o.text = formatTitle(decklist.name, decklist.url);
    o.text += ' - _\u200b' + decklist.creator + '\u200b_';
    for (let column in headings) {
        // Create the columns as Slack 'fields'.
        fields[column] = {title: '', value: '', short: true};
        for (let heading in headings[column]) {
            var type = headings[column][heading];
            // Check if the deck actually contains cards of the specified heading
            if (decklist.cards[type]) {
                // If this is not the first heading, add padding after the previous.
                if (heading != 0) {
                    fields[column].value += '\n\n';
                }
                fields[column].value += formatTitle(type);
                // Iterate through all the cards of the type in the decklist.
                for (let i in decklist.cards[type]) {
                    var card = decklist.cards[type][i];
                    var code = parseInt(card.card.code);
                    fields[column].value += '\n' + card.quantity;
                    fields[column].value += ' × ' + formatLink(card.card.title, card.card.url);
                    decksize += card.quantity;
                    // Check that the card is not newer than the previous newest card.
                    if (code > newestCard) {
                        newestCard = code;
                    }
                    if (card.card.agendapoints) {
                        agendapoints += card.card.agendapoints * card.quantity;
                    }
                    // Add MWL star if required.
                    if (card.card.mwl)
                    {
                        var mwl = card.quantity * card.card.mwl;
                        fields[column].value += ' ' + '☆'.repeat(mwl);
                        mwlDeduction += mwl;
                    }
                    // Add influence dots after the card name if required.
                    if (card.card.faction !== faction) {
                        var inf = card.quantity * card.card.factioncost;
                        fields[column].value += ' ' + influenceDots(inf);
                        usedInfluence += inf;
                    }
                }
            }
        }
    }
    o.attachments[0].color = colours[faction];
    o.attachments[0].fields = fields;
    // The identity of the decklist is displayed before the decklist.
    o.attachments[0].pretext = formatLink(decklist.cards.Identity[0].card.title,
            decklist.cards.Identity[0].card.url);
    o.attachments[0].pretext += '\n' + decksize + ' :_deck: (min ';
    o.attachments[0].pretext +=  decklist.cards.Identity[0].card.minimumdecksize;
    o.attachments[0].pretext += ') - ' + usedInfluence + '/';
    if (decklist.cards.Identity[0].card.influencelimit) {
        o.attachments[0].pretext += decklist.cards.Identity[0].card.influencelimit - mwlDeduction + '•';
        if (mwlDeduction > 0) {
            o.attachments[0].pretext += '(' + decklist.cards.Identity[0].card.influencelimit + '-';
            o.attachments[0].pretext += mwlDeduction + '☆)';
        }
    } else {
        o.attachments[0].pretext += '∞•';
    }
    if (decklist.cards.Identity[0].card.side !== 'Runner') {
        o.attachments[0].pretext += ' - ' + agendapoints + ' :_agenda:';
    }
    o.attachments[0].pretext += '\nCards up to ' + getPack(newestCard);
    return o;
};

function formatCards(cards, missing) {
    var o;
    // If there are cards that could not be found, tell the user.
    if (missing && missing.length > 0) {
        o = cardNoHitsMessage(missing);
        o.attachments = [];
    } else {
        o = {text:'', attachments:[]};
    }
    // Display the cards that were found either way.
    for (var i = 0; i < cards.length; i++) {
        var a = {pretext: '', mrkdwn_in: ['pretext', 'text']};
        var faction = cards[i].faction;
        var title = cards[i].title;
        if (cards[i].uniqueness){
            title = '◆ ' + title;
        }
        // If the Slack message is blank, put the title of the first card there.
        // The Slack API won't display messages with blank text even when there are attachments.
        if (o.text === '') {
            o.text = formatTitle(title, cards[0].url);
        } else {
            a.pretext = formatTitle(title, cards[i].url) + '\n';
        }
        // Append the rest of the card details to the attachment.
        a.pretext += '*\u200b' + cards[i].type;
        if (cards[i].subtype ) {
            a.pretext += ':\u200b* ' + cards[i].subtype;
        } else {
            a.pretext += '\u200b*';
        }
        a.pretext += ' - ' + getFactionEmoji(faction);
        if (cards[i].factioncost) {
            a.pretext += influenceDots(cards[i].factioncost);
        }
        if (cards[i].mwl) {
            a.pretext += '☆';
        }
        a.pretext += '\n';
        var first = true;
        // For some cards, the cost is actually a rez cost, this should be reflected in the emoji.
        if (cards[i].type === 'Asset' || cards[i].type === 'Upgrade' || cards[i].type === 'ICE') {
            stats[1][1] = ' :_rez:';
        } else {
            stats[1][1] = ':_credit:';
        }
        // Iterate through the possible card stats adding them to the text where present.
        for (var j = 0; j < stats.length; j++) {
            if (cards[i][stats[j][0]] || cards[i][stats[j][0]] === 0) {
                if (!first) {
                    a.pretext += ' - ';
                }
                a.pretext += cards[i][stats[j][0]] + stats[j][1];
                first = false;
            // Special case for draft IDs with infinite influence limit
            } else if (cards[i].type === 'Identity' && stats[j][0] === 'influencelimit' && !cards[i].influencelimit) {
                a.pretext += ' - ∞•';
            }
        }
        // Replace memory units with the slack emoji
        a.pretext = a.pretext.replace(/(\d|X)\s*:_mu:/gi, function (x) {
            return x.replace(/(.).*/, ':_$1mu:').toLowerCase();
        });
        a.pretext += ' - ' + getPack(parseInt(cards[i].code));
        a.color = colours[faction];
        // Add the card text to the attachment if present.
        if (cards[i].text) {
            a.text = formatText(cards[i].text);
        }
        a.thumb_url = thumbsURL + cards[i].code + '.png';
        o.attachments.push(a);
    }
    return o;
};

// Replace all the html and nrdb text with the Slack equivalent.
function formatText(text) {
    if (!text) return text;

    text = text.replace(/\r\n/g, '\n');

    // NRDB symbols to Slack emoji.
    text = text.replace(/\[Credits\]/g, ':_credit:');
    text = text.replace(/\[Recurring\ Credits\]/g, ':_recurringcredit:');
    text = text.replace(/\[Click\]/g, ':_click:');
    text = text.replace(/\ *\[Link\]/g, ' :_link:');
    text = text.replace(/\[Trash\]/g, ':_trash:');
    text = text.replace(/\[Subroutine\]/g, ':_subroutine:');
    // Individual mu emoji for numbers and 'Xmu'
    text = text.replace(/(\d|X)\s*\[Memory\ Unit\]/gi, function (x) {
        return x.replace(/(.).*/, ':_$1mu:').toLowerCase();
    });
    text = text.replace(/\[Memory Unit\]/g, ':_mu:');

    // HTML bold to Slack bold
    text = text.replace(/<strong>/g, '*\u200b');
    text = text.replace(/<\/strong>/g, '\u200b*');
    // HTML superscript to unicode superscript since Slack markdown doesn't support it.
    text = text.replace(/<sup>(?:\d|X)+<\/sup>/gi, function(x){
        x = x.replace(/<sup>|<\/sup>/g, '');
        x = x.replace(/X/i,'ˣ');
        x = x.replace(/\d/g, function(d){
            return ['⁰','¹','²','³','⁴','⁵','⁶','⁷','⁸','⁹'][parseInt(d)];
        });
        return x;
    });

    // Replace nrdb faction symbols with Slack emoji
    text = text.replace(/\[(jinteki|weyland-consortium|nbn|haas-bioroid)\]/, (a, x) => {
        return ":_" + x.replace(/-.*/, '') + ":";
    });

    text = text.replace(/&/g, '&');
    text = text.replace(/</g, '<');
    text = text.replace(/>/g, '>');

    return text;
};

<|endoftext|>


<commit_before>// JavaScript source code
var iTodo = angular.module('iTodo', []);

function mainController($scope, $http) {
    $scope.formData = {};

}<commit_msg>get create delete todo in core.js<commit_after>// JavaScript source code
var iTodo = angular.module('iTodo', []);

function mainController($scope, $http) {
    $scope.formData = {};
    $http.get('/api/todos')
        .success(function (data) {
            $scope.todos = data;
            console.log(data);
        })
        .error(function (data) {
            console.log('Error: ' + data);
        });

    // when submitting the add form, send the text to the node API
    $scope.createTodo = function () {
        $http.post('/api/todos', $scope.formData)
            .success(function (data) {
                $scope.formData = {}; // clear the form so our user is ready to enter another
                $scope.todos = data;
                console.log(data);
            })
            .error(function (data) {
                console.log('Error: ' + data);
            });
    };

    // delete a todo after checking it
    $scope.deleteTodo = function (id) {
        $http.delete('/api/todos/' + id)
            .success(function (data) {
                $scope.todos = data;
                console.log(data);
            })
            .error(function (data) {
                console.log('Error: ' + data);
            });
    };
}<|endoftext|>