<commit_before>;(function(exports) {
  var Collider = function(coquette) {
    this.coquette = coquette;
  };

  // if no entities have uncollision(), skip expensive record keeping for uncollisions
  var isUncollisionOn = function(entities) {
    for (var i = 0, len = entities.length; i < len; i++) {
      if (entities[i].uncollision !== undefined) {
        return true;
      }
    }
    return false;
  };

  var isSetupForCollisions = function(obj) {
    return obj.pos !== undefined && obj.size !== undefined;
  };

  Collider.prototype = {
    _collideRecords: [],

    update: function() {
      var ent = this.coquette.entities.all();
      for (var i = 0, len = ent.length; i < len; i++) {
        for (var j = i + 1; j < len; j++) {
          if (this.isColliding(ent[i], ent[j])) {
            this.collision(ent[i], ent[j]);
          } else {
            this.removeOldCollision(this.getCollideRecordIds(ent[i], ent[j])[0]);
          }
        }
      }
    },

    collision: function(entity1, entity2) {
      var collisionType;
      if (!isUncollisionOn(this.coquette.entities.all())) {
        collisionType = this.INITIAL;
      } else if (this.getCollideRecordIds(entity1, entity2).length === 0) {
        this._collideRecords.push([entity1, entity2]);
        collisionType = this.INITIAL;
      } else {
        collisionType = this.SUSTAINED;
      }

      notifyEntityOfCollision(entity1, entity2, collisionType);
      notifyEntityOfCollision(entity2, entity1, collisionType);
    },

    destroyEntity: function(entity) {
      var recordIds = this.getCollideRecordIds(entity);
      for (var i = 0; i < recordIds.length; i++) {
        this.removeOldCollision(recordIds[i]);
      }
    },

    // remove collision at passed index
    removeOldCollision: function(recordId) {
      var record = this._collideRecords[recordId];
      if (record !== undefined) {
        notifyEntityOfUncollision(record[0], record[1])
        notifyEntityOfUncollision(record[1], record[0])
        this._collideRecords.splice(recordId, 1);
      }
    },

    getCollideRecordIds: function(entity1, entity2) {
      if (entity1 !== undefined && entity2 !== undefined) {
        var recordIds = [];
        for (var i = 0, len = this._collideRecords.length; i < len; i++) {
          if (this._collideRecords[i][0] === entity1 &&
              this._collideRecords[i][1] === entity2) {
            recordIds.push(i);
          }
        }
        return recordIds;
      } else if (entity1 !== undefined) {
        for (var i = 0, len = this._collideRecords.length; i < len; i++) {
          if (this._collideRecords[i][0] === entity1 ||
              this._collideRecords[i][1] === entity1) {
            return [i];
          }
        }
        return [];
      } else {
        throw "You must pass at least one entity when searching collision records."
      }
    },

    isColliding: function(obj1, obj2) {
      return isSetupForCollisions(obj1) && isSetupForCollisions(obj2) &&
        this.isIntersecting(obj1, obj2);
    },

    isIntersecting: function(obj1, obj2) {
      var obj1BoundingBox = obj1.boundingBox || this.RECTANGLE;
      var obj2BoundingBox = obj2.boundingBox || this.RECTANGLE;

      if (obj1BoundingBox === this.RECTANGLE && obj2BoundingBox === this.RECTANGLE) {
        return Maths.rectanglesIntersecting(obj1, obj2);
      } else if (obj1BoundingBox === this.CIRCLE && obj2BoundingBox === this.RECTANGLE) {
        return Maths.circleAndRectangleIntersecting(obj1, obj2);
      } else if (obj1BoundingBox === this.RECTANGLE && obj2BoundingBox === this.CIRCLE) {
        return Maths.circleAndRectangleIntersecting(obj2, obj1);
      } else if (obj1BoundingBox === this.CIRCLE && obj2BoundingBox === this.CIRCLE) {
        return Maths.circlesIntersecting(obj1, obj2);
      } else {
        throw "Objects being collision tested have unsupported bounding box types."
      }
    },

    INITIAL: 0,
    SUSTAINED: 1,

    RECTANGLE: 0,
    CIRCLE: 1
  };

  var orEqual = function(obj1BB, obj2BB, bBType1, bBType2) {
    return (obj1BB === bBType1 && obj2BB === bBType2) ||
      (obj1BB === bBType2 && obj2BB === bBType1);
  }

  var notifyEntityOfCollision = function(entity, other, type) {
    if (entity.collision !== undefined) {
      entity.collision(other, type);
    }
  };

  var notifyEntityOfUncollision = function(entity, other) {
    if (entity.uncollision !== undefined) {
      entity.uncollision(other);
    }
  };

  var Maths = {
    circlesIntersecting: function(obj1, obj2) {
      return Maths.distance(Maths.center(obj1), Maths.center(obj2)) <
        obj1.size.x / 2 + obj2.size.x / 2;
    },

    rectanglesIntersecting: function(obj1, obj2) {
      if(obj1.pos.x + obj1.size.x < obj2.pos.x) {
        return false;
      } else if(obj1.pos.x > obj2.pos.x + obj2.size.x) {
        return false;
      } else if(obj1.pos.y > obj2.pos.y + obj2.size.y) {
        return false;
      } else if(obj1.pos.y + obj1.size.y < obj2.pos.y) {
        return false
      } else {
        return true;
      }
    },

    circleAndRectangleIntersecting: function(circleObj, rectangleObj) {
      var corners = Maths.rectangleCorners(rectangleObj);
      return Maths.pointInsideObj(Maths.center(circleObj), rectangleObj) ||
        Maths.isLineIntersectingCircle(circleObj, corners[0], corners[1]) ||
        Maths.isLineIntersectingCircle(circleObj, corners[1], corners[2]) ||
        Maths.isLineIntersectingCircle(circleObj, corners[2], corners[3]) ||
        Maths.isLineIntersectingCircle(circleObj, corners[3], corners[0]);
    },

    center: function(obj) {
      if(obj.pos !== undefined) {
        return {
          x: obj.pos.x + (obj.size.x / 2),
          y: obj.pos.y + (obj.size.y / 2),
        };
      }
    },

    pointInsideObj: function(point, obj) {
      return point.x >= obj.pos.x
        && point.y >= obj.pos.y
        && point.x <= obj.pos.x + obj.size.x
        && point.y <= obj.pos.y + obj.size.y;
    },

    distance: function(point1, point2) {
      var x = point1.x - point2.x;
      var y = point1.y - point2.y;
      return Math.sqrt((x * x) + (y * y));
    },

    rectangleCorners: function(rectangleObj) {
      var corners = [];
      corners.push({ x:rectangleObj.pos.x, y: rectangleObj.pos.y });
      corners.push({ x:rectangleObj.pos.x + rectangleObj.size.x, y:rectangleObj.pos.y });
      corners.push({
        x:rectangleObj.pos.x + rectangleObj.size.x,
        y:rectangleObj.pos.y + rectangleObj.size.y
      });
      corners.push({ x:rectangleObj.pos.x, y: rectangleObj.pos.y + rectangleObj.size.y });
      return corners;
    },

    vectorTo: function(start, end) {
      return {
        x: end.x - start.x,
        y: end.y - start.y
      };
    },

    magnitude: function(vector) {
      return Math.sqrt(vector.x * vector.x + vector.y * vector.y);
    },

    dotProduct: function(vector1, vector2) {
      return vector1.x * vector2.x + vector1.y * vector2.y;
    },

    unitVector: function(vector) {
      return {
        x: vector.x / Maths.magnitude(vector),
        y: vector.y / Maths.magnitude(vector)
      };
    },

    closestPointOnSeg: function(linePointA, linePointB, circ_pos) {
      var seg_v = Maths.vectorTo(linePointA, linePointB);
      var pt_v = Maths.vectorTo(linePointA, circ_pos);
      if (Maths.magnitude(seg_v) <= 0) {
        throw "Invalid segment length";
      }

      var seg_v_unit = Maths.unitVector(seg_v);
      var proj = Maths.dotProduct(pt_v, seg_v_unit);
      if (proj <= 0) {
        return linePointA;
      } else if (proj >= Maths.magnitude(seg_v)) {
        return linePointB;
      } else {
        return {
          x: linePointA.x + seg_v_unit.x * proj,
          y: linePointA.y + seg_v_unit.y * proj
        };
      }
    },

    isLineIntersectingCircle: function(circleObj, linePointA, linePointB) {
      var circ_pos = {
        x: circleObj.pos.x + circleObj.size.x / 2,
        y: circleObj.pos.y + circleObj.size.y / 2
      };

      var closest = Maths.closestPointOnSeg(linePointA, linePointB, circ_pos);
      var dist_v = Maths.vectorTo(closest, circ_pos);
      return Maths.magnitude(dist_v) < circleObj.size.x / 2;
    }
  };

  exports.Collider = Collider;
  exports.Collider.Maths = Maths;
})(typeof exports === 'undefined' ? this.Coquette : exports);
<commit_msg>Remove unused fn<commit_after>;(function(exports) {
  var Collider = function(coquette) {
    this.coquette = coquette;
  };

  // if no entities have uncollision(), skip expensive record keeping for uncollisions
  var isUncollisionOn = function(entities) {
    for (var i = 0, len = entities.length; i < len; i++) {
      if (entities[i].uncollision !== undefined) {
        return true;
      }
    }
    return false;
  };

  var isSetupForCollisions = function(obj) {
    return obj.pos !== undefined && obj.size !== undefined;
  };

  Collider.prototype = {
    _collideRecords: [],

    update: function() {
      var ent = this.coquette.entities.all();
      for (var i = 0, len = ent.length; i < len; i++) {
        for (var j = i + 1; j < len; j++) {
          if (this.isColliding(ent[i], ent[j])) {
            this.collision(ent[i], ent[j]);
          } else {
            this.removeOldCollision(this.getCollideRecordIds(ent[i], ent[j])[0]);
          }
        }
      }
    },

    collision: function(entity1, entity2) {
      var collisionType;
      if (!isUncollisionOn(this.coquette.entities.all())) {
        collisionType = this.INITIAL;
      } else if (this.getCollideRecordIds(entity1, entity2).length === 0) {
        this._collideRecords.push([entity1, entity2]);
        collisionType = this.INITIAL;
      } else {
        collisionType = this.SUSTAINED;
      }

      notifyEntityOfCollision(entity1, entity2, collisionType);
      notifyEntityOfCollision(entity2, entity1, collisionType);
    },

    destroyEntity: function(entity) {
      var recordIds = this.getCollideRecordIds(entity);
      for (var i = 0; i < recordIds.length; i++) {
        this.removeOldCollision(recordIds[i]);
      }
    },

    // remove collision at passed index
    removeOldCollision: function(recordId) {
      var record = this._collideRecords[recordId];
      if (record !== undefined) {
        notifyEntityOfUncollision(record[0], record[1])
        notifyEntityOfUncollision(record[1], record[0])
        this._collideRecords.splice(recordId, 1);
      }
    },

    getCollideRecordIds: function(entity1, entity2) {
      if (entity1 !== undefined && entity2 !== undefined) {
        var recordIds = [];
        for (var i = 0, len = this._collideRecords.length; i < len; i++) {
          if (this._collideRecords[i][0] === entity1 &&
              this._collideRecords[i][1] === entity2) {
            recordIds.push(i);
          }
        }
        return recordIds;
      } else if (entity1 !== undefined) {
        for (var i = 0, len = this._collideRecords.length; i < len; i++) {
          if (this._collideRecords[i][0] === entity1 ||
              this._collideRecords[i][1] === entity1) {
            return [i];
          }
        }
        return [];
      } else {
        throw "You must pass at least one entity when searching collision records."
      }
    },

    isColliding: function(obj1, obj2) {
      return isSetupForCollisions(obj1) && isSetupForCollisions(obj2) &&
        this.isIntersecting(obj1, obj2);
    },

    isIntersecting: function(obj1, obj2) {
      var obj1BoundingBox = obj1.boundingBox || this.RECTANGLE;
      var obj2BoundingBox = obj2.boundingBox || this.RECTANGLE;

      if (obj1BoundingBox === this.RECTANGLE && obj2BoundingBox === this.RECTANGLE) {
        return Maths.rectanglesIntersecting(obj1, obj2);
      } else if (obj1BoundingBox === this.CIRCLE && obj2BoundingBox === this.RECTANGLE) {
        return Maths.circleAndRectangleIntersecting(obj1, obj2);
      } else if (obj1BoundingBox === this.RECTANGLE && obj2BoundingBox === this.CIRCLE) {
        return Maths.circleAndRectangleIntersecting(obj2, obj1);
      } else if (obj1BoundingBox === this.CIRCLE && obj2BoundingBox === this.CIRCLE) {
        return Maths.circlesIntersecting(obj1, obj2);
      } else {
        throw "Objects being collision tested have unsupported bounding box types."
      }
    },

    INITIAL: 0,
    SUSTAINED: 1,

    RECTANGLE: 0,
    CIRCLE: 1
  };

  var notifyEntityOfCollision = function(entity, other, type) {
    if (entity.collision !== undefined) {
      entity.collision(other, type);
    }
  };

  var notifyEntityOfUncollision = function(entity, other) {
    if (entity.uncollision !== undefined) {
      entity.uncollision(other);
    }
  };

  var Maths = {
    circlesIntersecting: function(obj1, obj2) {
      return Maths.distance(Maths.center(obj1), Maths.center(obj2)) <
        obj1.size.x / 2 + obj2.size.x / 2;
    },

    rectanglesIntersecting: function(obj1, obj2) {
      if(obj1.pos.x + obj1.size.x < obj2.pos.x) {
        return false;
      } else if(obj1.pos.x > obj2.pos.x + obj2.size.x) {
        return false;
      } else if(obj1.pos.y > obj2.pos.y + obj2.size.y) {
        return false;
      } else if(obj1.pos.y + obj1.size.y < obj2.pos.y) {
        return false
      } else {
        return true;
      }
    },

    circleAndRectangleIntersecting: function(circleObj, rectangleObj) {
      var corners = Maths.rectangleCorners(rectangleObj);
      return Maths.pointInsideObj(Maths.center(circleObj), rectangleObj) ||
        Maths.isLineIntersectingCircle(circleObj, corners[0], corners[1]) ||
        Maths.isLineIntersectingCircle(circleObj, corners[1], corners[2]) ||
        Maths.isLineIntersectingCircle(circleObj, corners[2], corners[3]) ||
        Maths.isLineIntersectingCircle(circleObj, corners[3], corners[0]);
    },

    center: function(obj) {
      if(obj.pos !== undefined) {
        return {
          x: obj.pos.x + (obj.size.x / 2),
          y: obj.pos.y + (obj.size.y / 2),
        };
      }
    },

    pointInsideObj: function(point, obj) {
      return point.x >= obj.pos.x
        && point.y >= obj.pos.y
        && point.x <= obj.pos.x + obj.size.x
        && point.y <= obj.pos.y + obj.size.y;
    },

    distance: function(point1, point2) {
      var x = point1.x - point2.x;
      var y = point1.y - point2.y;
      return Math.sqrt((x * x) + (y * y));
    },

    rectangleCorners: function(rectangleObj) {
      var corners = [];
      corners.push({ x:rectangleObj.pos.x, y: rectangleObj.pos.y });
      corners.push({ x:rectangleObj.pos.x + rectangleObj.size.x, y:rectangleObj.pos.y });
      corners.push({
        x:rectangleObj.pos.x + rectangleObj.size.x,
        y:rectangleObj.pos.y + rectangleObj.size.y
      });
      corners.push({ x:rectangleObj.pos.x, y: rectangleObj.pos.y + rectangleObj.size.y });
      return corners;
    },

    vectorTo: function(start, end) {
      return {
        x: end.x - start.x,
        y: end.y - start.y
      };
    },

    magnitude: function(vector) {
      return Math.sqrt(vector.x * vector.x + vector.y * vector.y);
    },

    dotProduct: function(vector1, vector2) {
      return vector1.x * vector2.x + vector1.y * vector2.y;
    },

    unitVector: function(vector) {
      return {
        x: vector.x / Maths.magnitude(vector),
        y: vector.y / Maths.magnitude(vector)
      };
    },

    closestPointOnSeg: function(linePointA, linePointB, circ_pos) {
      var seg_v = Maths.vectorTo(linePointA, linePointB);
      var pt_v = Maths.vectorTo(linePointA, circ_pos);
      if (Maths.magnitude(seg_v) <= 0) {
        throw "Invalid segment length";
      }

      var seg_v_unit = Maths.unitVector(seg_v);
      var proj = Maths.dotProduct(pt_v, seg_v_unit);
      if (proj <= 0) {
        return linePointA;
      } else if (proj >= Maths.magnitude(seg_v)) {
        return linePointB;
      } else {
        return {
          x: linePointA.x + seg_v_unit.x * proj,
          y: linePointA.y + seg_v_unit.y * proj
        };
      }
    },

    isLineIntersectingCircle: function(circleObj, linePointA, linePointB) {
      var circ_pos = {
        x: circleObj.pos.x + circleObj.size.x / 2,
        y: circleObj.pos.y + circleObj.size.y / 2
      };

      var closest = Maths.closestPointOnSeg(linePointA, linePointB, circ_pos);
      var dist_v = Maths.vectorTo(closest, circ_pos);
      return Maths.magnitude(dist_v) < circleObj.size.x / 2;
    }
  };

  exports.Collider = Collider;
  exports.Collider.Maths = Maths;
})(typeof exports === 'undefined' ? this.Coquette : exports);
<|endoftext|>


<commit_before>'use strict'

const execFileSync = require('child_process').execFileSync,
      fmt = require('./fmt.js'),
      date = require('./date.js'),
      time = require('./time.js'),
      { padStr, unique } = require('./utils.js')

module.exports = function(log, colors) {
    const formatter = fmt(colors)

    function add({
        dates = [date.today().getTime()],
        time,
        tail,
        tags = []
    }) {
        if (dates == ['all'])
            throw 'Invalid date'
        else if (!tail)
            throw 'No activity submitted'
        else if (!time || !time.stop || !time.start)
            throw 'Invalid time range'

        if (dates.length == 1 && time.stop < time.start)
            dates.push(dates[1] + time.convert('24'))

        dates.forEach((n, i, a) => {
            const start = (i == 0) ? time.start : 0,
                  stop = (i == a.length - 1) ? time.stop : time.convert('24')

            log.add(n, {
                start,
                stop,
                duration: stop - start,
                activity: tail.join(' '),
                tags
            })
        })

        print({ dates })

        return log
    }

    function help() {
        console.log(require('fs').readFileSync(`${__dirname}/../help.txt`, 'utf-8'))
    }

    function dates() {
        console.log(Object.keys(log.data)
                    .filter(n => n != 'queue')
                    .sort()
                    .map(n => formatter.date(Number(n), {
                        day: 'numeric',
                        year: 'numeric',
                        month: 'short'
                    }))
                    .join('\n'))
    }

    function edit({ dates = [date.today().getTime()], tail = [] }) {
        if (dates.length > 1)
            throw 'Can\'t edit range of dates'

        if (tail.length == 0 || !log.data[dates[0]])
            throw 'Invalid entry'

        tail.forEach(i => {
            const index = i - 1

            if (isNaN(index) || !log.data[dates[0]][index])
                throw 'Invalid index'

            const { start, stop, activity = '', tags = [], timestamp } = log.data[dates[0]][index],
                  json = JSON.stringify({
                      start: time.timef(start, '%H.%M.%S'),
                      stop: time.timef(stop, '%H.%M.%S'),
                      activity,
                      tags
                  }, null, 4)

            const edit = JSON.parse(execFileSync('vipe', { input: json })),
                  nstart = time.convert(edit.start),
                  nstop = time.convert(edit.stop)

            log.data[dates[0]][index] = {
                start: nstart,
                stop: nstop,
                duration: nstop - nstart,
                activity: edit.activity || '',
                tags: edit.tags || [],
                timestamp
            }
        })

        print({ dates })

        return log
    }

    function queue({ time: start, tail = [], tags }) {
        if (typeof start == 'object')
            throw 'Cannot queue time range'

        const subcmd = (tail.length > 0) ? tail[0].toLowerCase() : ''

        function print() {
            log.data.queue.forEach((n, i) => console.log(formatter.entry(n, i)))
        }

        function pop(added) {
            if (log.data.queue.length == 0)
                throw 'No entries in queue'

            const stop = time.now(),
                  dateStop = date.today().getTime(),
                  { dateStart, start, activity, tags } = log.pop()

            date.range(dateStart, dateStop).forEach((n, i, a) => {
                const timeStart = (i == 0) ? start : 0,
                      timeStop = (i == a.length - 1) ? stop : time.convert('24')

                log.add(n, {
                    start: timeStart,
                    stop: timeStop,
                    duration: timeStop - timeStart,
                    activity: added.activity || activity,
                    tags: added.tags || tags
                })
            })

            print()

            return log
        }

        function clear() {
            log.rm('queue', 1)
            if (log.data.queue.length > 0)
                clear()

            return log
        }

        function push({ start, activity, tags }) {
            log.add('queue', {
                dateStart: date.today().getTime(),
                start,
                activity,
                tags
            })

            return log
        }

        switch (subcmd) {
            case 'pop':
                return pop({
                    activity: tail.slice(1).join(' '),
                    tags
                })
            case 'clear':
                return clear()
            case 'print':
                return print()
            default:
                return push({
                    start: start || time.now(),
                    activity: tail.join(' '),
                    tags
                })
        }
    }

    function rm({ dates = [date.today().getTime()], tail }) {
        if (dates.length > 1)
            throw 'rm only works on a single date'
        else if (tail.length == 0 || tail.some(n => isNaN(n)))
            throw 'Invalid index'

        unique(tail).sort((a, b) => a < b)
            .forEach(n => log.rm(dates[0], n))

        print({ dates })

        return log
    }

    function print({ dates = [date.today().getTime()], tags = [] } = {}) {
        const keys = (dates.indexOf('all') > -1) ? log.keys() : dates

        keys.forEach(d => {
            if (log.data[d]) {
                const e = log.data[d].filter(n => {
                    return tags.length == 0 || tags.every(t => n.tags.indexOf(t) > -1)
                })

                if (e.length > 0) {
                    console.log(formatter.date(Number(d), {
                        weekday: 'long',
                        day: 'numeric',
                        month: 'short',
                        year: 'numeric'
                    }))

                    e.forEach((n, i) => {
                        console.log(padStr.left(formatter.entry(n, i), ' ', 4))
                    })
                }
            }
        })
    }

    function summarise({ dates = [] } = {}) {
        const keys = (dates.indexOf('all') > -1) ? log.keys() : dates,
              range = (keys.length < 2)
                  ? date.range(keys[0] || date.today().setHours(-24 * 7), date.today().getTime())
                  : keys

        const entries = range.filter(n => log.keys().indexOf(n) > -1)
                             .map(n => log.data[n].map(e => ({ ...e, date: n })))
                             .reduce((m, n) => m.concat(n), [])

        if (entries.length == 0)
            throw 'No entries for specified range'

        console.log(colors.title('Top 5 entries:'))
        entries.sort((a, b) => b.duration - a.duration)
               .slice(0, 5)
               .forEach((n, i) => {
                   const opts = {
                       weekday: 'short',
                       day: 'numeric',
                       month: 'short'
                   }

                   console.log(`${formatter.date(n.date, opts)} ${formatter.entry(n, i)}`)
               })

        console.log(colors.title('\nBy Tag:'))
        const tags = log.tags().reduce((m, t) => {
            const e = entries.filter(n => n.tags.indexOf(t) > -1)
                             .reduce((m, n) => m + n.duration, 0)

            if (e > 0)
                m[t] = e

            return m
        }, {})

        Object.keys(tags).sort((a, b) => tags[a] < tags[b])
              .forEach(n => console.log(`${colors.tag(n)} ${formatter.elapsed(tags[n])}`))

        const f = [
            `Total hrs: ${formatter.elapsed(entries.reduce((m, n) =>
                                                           m + n.duration, 0))}`,
            `Tags: ${colors.tag(log.tags().length)}`,
            `Entries: ${colors.action(entries.length)}`
        ].join(' ')

        console.log(`\n${colors.fill(f)}`)
    }

    function tags({ dates }) {
        console.log(formatter.tag(log.tags((dates || []).indexOf('all') > -1
                                           ? log.keys()
                                           : dates)))
    }

    return { add, dates, edit, help, print, queue, rm, summarise, tags }
}
<commit_msg>Allow stop time in queue pop<commit_after>'use strict'

const execFileSync = require('child_process').execFileSync,
      fmt = require('./fmt.js'),
      date = require('./date.js'),
      time = require('./time.js'),
      { padStr, unique } = require('./utils.js')

module.exports = function(log, colors) {
    const formatter = fmt(colors)

    function add({
        dates = [date.today().getTime()],
        time,
        tail,
        tags = []
    }) {
        if (dates == ['all'])
            throw 'Invalid date'
        else if (!tail)
            throw 'No activity submitted'
        else if (!time || !time.stop || !time.start)
            throw 'Invalid time range'

        if (dates.length == 1 && time.stop < time.start)
            dates.push(dates[1] + time.convert('24'))

        dates.forEach((n, i, a) => {
            const start = (i == 0) ? time.start : 0,
                  stop = (i == a.length - 1) ? time.stop : time.convert('24')

            log.add(n, {
                start,
                stop,
                duration: stop - start,
                activity: tail.join(' '),
                tags
            })
        })

        print({ dates })

        return log
    }

    function help() {
        console.log(require('fs').readFileSync(`${__dirname}/../help.txt`, 'utf-8'))
    }

    function dates() {
        console.log(Object.keys(log.data)
                    .filter(n => n != 'queue')
                    .sort()
                    .map(n => formatter.date(Number(n), {
                        day: 'numeric',
                        year: 'numeric',
                        month: 'short'
                    }))
                    .join('\n'))
    }

    function edit({ dates = [date.today().getTime()], tail = [] }) {
        if (dates.length > 1)
            throw 'Can\'t edit range of dates'

        if (tail.length == 0 || !log.data[dates[0]])
            throw 'Invalid entry'

        tail.forEach(i => {
            const index = i - 1

            if (isNaN(index) || !log.data[dates[0]][index])
                throw 'Invalid index'

            const { start, stop, activity = '', tags = [], timestamp } = log.data[dates[0]][index],
                  json = JSON.stringify({
                      start: time.timef(start, '%H.%M.%S'),
                      stop: time.timef(stop, '%H.%M.%S'),
                      activity,
                      tags
                  }, null, 4)

            const edit = JSON.parse(execFileSync('vipe', { input: json })),
                  nstart = time.convert(edit.start),
                  nstop = time.convert(edit.stop)

            log.data[dates[0]][index] = {
                start: nstart,
                stop: nstop,
                duration: nstop - nstart,
                activity: edit.activity || '',
                tags: edit.tags || [],
                timestamp
            }
        })

        print({ dates })

        return log
    }

    function queue({ time: mark, tail = [], tags }) {
        if (typeof mark == 'object')
            throw 'Cannot queue time range'

        const subcmd = (tail.length > 0) ? tail[0].toLowerCase() : ''

        function print() {
            log.data.queue.forEach((n, i) => console.log(formatter.entry(n, i)))
        }

        function pop(added) {
            if (log.data.queue.length == 0)
                throw 'No entries in queue'

            const stop = added.stop || time.now(),
                  dateStop = date.today().getTime(),
                  { dateStart, start, activity, tags } = log.pop()

            date.range(dateStart, dateStop).forEach((n, i, a) => {
                const timeStart = (i == 0) ? start : 0,
                      timeStop = (i == a.length - 1) ? stop : time.convert('24')

                log.add(n, {
                    start: timeStart,
                    stop: timeStop,
                    duration: timeStop - timeStart,
                    activity: added.activity || activity,
                    tags: added.tags || tags
                })
            })

            print()

            return log
        }

        function clear() {
            log.rm('queue', 1)
            if (log.data.queue.length > 0)
                clear()

            return log
        }

        function push({ start, activity, tags }) {
            log.add('queue', {
                dateStart: date.today().getTime(),
                start,
                activity,
                tags
            })

            return log
        }

        switch (subcmd) {
            case 'pop':
                return pop({
                    stop: mark,
                    activity: tail.slice(1).join(' '),
                    tags
                })
            case 'clear':
                return clear()
            case 'print':
                return print()
            default:
                return push({
                    start: mark || time.now(),
                    activity: tail.join(' '),
                    tags
                })
        }
    }

    function rm({ dates = [date.today().getTime()], tail }) {
        if (dates.length > 1)
            throw 'rm only works on a single date'
        else if (tail.length == 0 || tail.some(n => isNaN(n)))
            throw 'Invalid index'

        unique(tail).sort((a, b) => a < b)
            .forEach(n => log.rm(dates[0], n))

        print({ dates })

        return log
    }

    function print({ dates = [date.today().getTime()], tags = [] } = {}) {
        const keys = (dates.indexOf('all') > -1) ? log.keys() : dates

        keys.forEach(d => {
            if (log.data[d]) {
                const e = log.data[d].filter(n => {
                    return tags.length == 0 || tags.every(t => n.tags.indexOf(t) > -1)
                })

                if (e.length > 0) {
                    console.log(formatter.date(Number(d), {
                        weekday: 'long',
                        day: 'numeric',
                        month: 'short',
                        year: 'numeric'
                    }))

                    e.forEach((n, i) => {
                        console.log(padStr.left(formatter.entry(n, i), ' ', 4))
                    })
                }
            }
        })
    }

    function summarise({ dates = [] } = {}) {
        const keys = (dates.indexOf('all') > -1) ? log.keys() : dates,
              range = (keys.length < 2)
                  ? date.range(keys[0] || date.today().setHours(-24 * 7), date.today().getTime())
                  : keys

        const entries = range.filter(n => log.keys().indexOf(n) > -1)
                             .map(n => log.data[n].map(e => ({ ...e, date: n })))
                             .reduce((m, n) => m.concat(n), [])

        if (entries.length == 0)
            throw 'No entries for specified range'

        console.log(colors.title('Top 5 entries:'))
        entries.sort((a, b) => b.duration - a.duration)
               .slice(0, 5)
               .forEach((n, i) => {
                   const opts = {
                       weekday: 'short',
                       day: 'numeric',
                       month: 'short'
                   }

                   console.log(`${formatter.date(n.date, opts)} ${formatter.entry(n, i)}`)
               })

        console.log(colors.title('\nBy Tag:'))
        const tags = log.tags().reduce((m, t) => {
            const e = entries.filter(n => n.tags.indexOf(t) > -1)
                             .reduce((m, n) => m + n.duration, 0)

            if (e > 0)
                m[t] = e

            return m
        }, {})

        Object.keys(tags).sort((a, b) => tags[a] < tags[b])
              .forEach(n => console.log(`${colors.tag(n)} ${formatter.elapsed(tags[n])}`))

        const f = [
            `Total hrs: ${formatter.elapsed(entries.reduce((m, n) =>
                                                           m + n.duration, 0))}`,
            `Tags: ${colors.tag(log.tags().length)}`,
            `Entries: ${colors.action(entries.length)}`
        ].join(' ')

        console.log(`\n${colors.fill(f)}`)
    }

    function tags({ dates }) {
        console.log(formatter.tag(log.tags((dates || []).indexOf('all') > -1
                                           ? log.keys()
                                           : dates)))
    }

    return { add, dates, edit, help, print, queue, rm, summarise, tags }
}
<|endoftext|>


<commit_before>_html2canvas.Renderer.Canvas = function(options) {

  options = options || {};

  var doc = document,
  safeImages = [],
  testCanvas = document.createElement("canvas"),
  testctx = testCanvas.getContext("2d"),
  canvas = options.canvas || doc.createElement('canvas');

  function createShape(ctx, args) {
    ctx.beginPath();
    args.forEach(function(arg) {
      ctx[arg.name].apply(ctx, arg['arguments']);
    });
    ctx.closePath();
  }

  function safeImage(item) {
    if (safeImages.indexOf(item['arguments'][0].src ) === -1) {
      testctx.drawImage(item['arguments'][0], 0, 0);
      try {
        testctx.getImageData(0, 0, 1, 1);
      } catch(e) {
        testCanvas = doc.createElement("canvas");
        testctx = testCanvas.getContext("2d");
        return false;
      }
      safeImages.push(item['arguments'][0].src);
    }
    return true;
  }

  function isTransparent(backgroundColor) {
    return (backgroundColor === "transparent" || backgroundColor === "rgba(0, 0, 0, 0)");
  }

  function renderItem(ctx, item) {
    switch(item.type){
      case "variable":
        ctx[item.name] = item['arguments'];
        break;
      case "function":
        if (item.name === "createPattern") {
          if (item['arguments'][0].width > 0 && item['arguments'][0].height > 0) {
            try {
              ctx.fillStyle = ctx.createPattern(item['arguments'][0], "repeat");
            }
            catch(e) {
              h2clog("html2canvas: Renderer: Error creating pattern", e.message);
            }
          }
        } else if (item.name === "drawShape") {
          createShape(ctx, item['arguments']);
        } else if (item.name === "drawImage") {
          if (item['arguments'][8] > 0 && item['arguments'][7] > 0) {
            if (!options.taintTest || (options.taintTest && safeImage(item))) {
              ctx.drawImage.apply( ctx, item['arguments'] );
            }
          }
        } else {
          ctx[item.name].apply(ctx, item['arguments']);
        }
        break;
    }
  }

  return function(zStack, options, doc, queue, _html2canvas) {

    var ctx = canvas.getContext("2d"),
    storageContext,
    i,
    queueLen,
    newCanvas,
    bounds,
    fstyle;

    canvas.width = canvas.style.width =  options.width || zStack.ctx.width;
    canvas.height = canvas.style.height = options.height || zStack.ctx.height;

    fstyle = ctx.fillStyle;
    ctx.webkitImageSmoothingEnabled = ctx.mozImageSmoothingEnabled = ctx.imageSmoothingEnabled = false;
    ctx.fillStyle = (isTransparent(zStack.backgroundColor) && options.background !== undefined) ? options.background : zStack.backgroundColor;
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = fstyle;

    if ( options.svgRendering && zStack.svgRender !== undefined ) {
      // TODO: enable async rendering to support this
      ctx.drawImage( zStack.svgRender, 0, 0 );
    } else {
      for ( i = 0, queueLen = queue.length; i < queueLen; i+=1 ) {
        storageContext = queue.splice(0, 1)[0];
        storageContext.canvasPosition = storageContext.canvasPosition || {};

        // set common settings for canvas
        ctx.textBaseline = "bottom";

        if (storageContext.clip){
          ctx.save();
          ctx.beginPath();
          // console.log(storageContext);
          ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);
          ctx.clip();
        }

        if (storageContext.ctx.storage) {
          storageContext.ctx.storage.forEach(renderItem.bind(null, ctx));
        }

        if (storageContext.clip){
          ctx.restore();
        }
      }
    }

    h2clog("html2canvas: Renderer: Canvas renderer done - returning canvas obj");

    queueLen = options.elements.length;

    if (queueLen === 1) {
      if (typeof options.elements[0] === "object" && options.elements[0].nodeName !== "BODY") {
        // crop image to the bounds of selected (single) element
        bounds = _html2canvas.Util.Bounds(options.elements[0]);
        newCanvas = doc.createElement('canvas');
        newCanvas.width = bounds.width;
        newCanvas.height = bounds.height;
        ctx = newCanvas.getContext("2d");

        ctx.drawImage(canvas, bounds.left, bounds.top, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height);
        canvas = null;
        return newCanvas;
      }
    }

    return canvas;
  };
};<commit_msg>revert image smooth disabling<commit_after>_html2canvas.Renderer.Canvas = function(options) {

  options = options || {};

  var doc = document,
  safeImages = [],
  testCanvas = document.createElement("canvas"),
  testctx = testCanvas.getContext("2d"),
  canvas = options.canvas || doc.createElement('canvas');

  function createShape(ctx, args) {
    ctx.beginPath();
    args.forEach(function(arg) {
      ctx[arg.name].apply(ctx, arg['arguments']);
    });
    ctx.closePath();
  }

  function safeImage(item) {
    if (safeImages.indexOf(item['arguments'][0].src ) === -1) {
      testctx.drawImage(item['arguments'][0], 0, 0);
      try {
        testctx.getImageData(0, 0, 1, 1);
      } catch(e) {
        testCanvas = doc.createElement("canvas");
        testctx = testCanvas.getContext("2d");
        return false;
      }
      safeImages.push(item['arguments'][0].src);
    }
    return true;
  }

  function isTransparent(backgroundColor) {
    return (backgroundColor === "transparent" || backgroundColor === "rgba(0, 0, 0, 0)");
  }

  function renderItem(ctx, item) {
    switch(item.type){
      case "variable":
        ctx[item.name] = item['arguments'];
        break;
      case "function":
        if (item.name === "createPattern") {
          if (item['arguments'][0].width > 0 && item['arguments'][0].height > 0) {
            try {
              ctx.fillStyle = ctx.createPattern(item['arguments'][0], "repeat");
            }
            catch(e) {
              h2clog("html2canvas: Renderer: Error creating pattern", e.message);
            }
          }
        } else if (item.name === "drawShape") {
          createShape(ctx, item['arguments']);
        } else if (item.name === "drawImage") {
          if (item['arguments'][8] > 0 && item['arguments'][7] > 0) {
            if (!options.taintTest || (options.taintTest && safeImage(item))) {
              ctx.drawImage.apply( ctx, item['arguments'] );
            }
          }
        } else {
          ctx[item.name].apply(ctx, item['arguments']);
        }
        break;
    }
  }

  return function(zStack, options, doc, queue, _html2canvas) {

    var ctx = canvas.getContext("2d"),
    storageContext,
    i,
    queueLen,
    newCanvas,
    bounds,
    fstyle;

    canvas.width = canvas.style.width =  options.width || zStack.ctx.width;
    canvas.height = canvas.style.height = options.height || zStack.ctx.height;

    fstyle = ctx.fillStyle;
    ctx.fillStyle = (isTransparent(zStack.backgroundColor) && options.background !== undefined) ? options.background : zStack.backgroundColor;
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = fstyle;

    if ( options.svgRendering && zStack.svgRender !== undefined ) {
      // TODO: enable async rendering to support this
      ctx.drawImage( zStack.svgRender, 0, 0 );
    } else {
      for ( i = 0, queueLen = queue.length; i < queueLen; i+=1 ) {
        storageContext = queue.splice(0, 1)[0];
        storageContext.canvasPosition = storageContext.canvasPosition || {};

        // set common settings for canvas
        ctx.textBaseline = "bottom";

        if (storageContext.clip){
          ctx.save();
          ctx.beginPath();
          // console.log(storageContext);
          ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);
          ctx.clip();
        }

        if (storageContext.ctx.storage) {
          storageContext.ctx.storage.forEach(renderItem.bind(null, ctx));
        }

        if (storageContext.clip){
          ctx.restore();
        }
      }
    }

    h2clog("html2canvas: Renderer: Canvas renderer done - returning canvas obj");

    queueLen = options.elements.length;

    if (queueLen === 1) {
      if (typeof options.elements[0] === "object" && options.elements[0].nodeName !== "BODY") {
        // crop image to the bounds of selected (single) element
        bounds = _html2canvas.Util.Bounds(options.elements[0]);
        newCanvas = doc.createElement('canvas');
        newCanvas.width = bounds.width;
        newCanvas.height = bounds.height;
        ctx = newCanvas.getContext("2d");

        ctx.drawImage(canvas, bounds.left, bounds.top, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height);
        canvas = null;
        return newCanvas;
      }
    }

    return canvas;
  };
};<|endoftext|>


<commit_before>let fs = require('fs')
var async = require('async')
var path = require('path')

let RemixCompiler = require('remix-solidity').Compiler

// TODO: replace this with remix's own compiler code

function compileFileOrFiles (filename, isDirectory, cb) {
  let compiler, filepath

  const sources = {
    'tests.sol': {content: fs.readFileSync('sol/tests.sol').toString()}
  }

  // TODO: for now assumes filepath dir contains all tests, later all this
  // should be replaced with remix's & browser solidity compiler code
  if (isDirectory) {
    filepath = filename
    fs.readdirSync(filename).forEach(file => {
      sources[file] = {content: fs.readFileSync(path.join(filename, file)).toString()}
    })
  } else {
    filepath = path.dirname(filename)
    fs.readdirSync(filepath).forEach(file => {
      sources[file] = {content: fs.readFileSync(path.join(filepath, file)).toString()}
    })
  }

  async.waterfall([
    function loadCompiler (next) {
      compiler = new RemixCompiler()
      compiler.onInternalCompilerLoaded()
      // compiler.event.register('compilerLoaded', this, function (version) {
      next()
      // });
    },
    function doCompilation (next) {
      compiler.event.register('compilationFinished', this, function (success, data, source) {
        next(null, data)
      })
      compiler.compile(sources, filepath)
    }
  ], function (err, result) {
    cb(err, result.contracts)
  })
}

module.exports = {
  compileFileOrFiles: compileFileOrFiles
}
<commit_msg>refactor condition<commit_after>let fs = require('fs')
var async = require('async')
var path = require('path')

let RemixCompiler = require('remix-solidity').Compiler

// TODO: replace this with remix's own compiler code

function compileFileOrFiles (filename, isDirectory, cb) {
  let compiler, filepath

  const sources = {
    'tests.sol': {content: fs.readFileSync('sol/tests.sol').toString()}
  }

  // TODO: for now assumes filepath dir contains all tests, later all this
  // should be replaced with remix's & browser solidity compiler code
  filepath = (isDirectory ? filename : path.dirname(filename))

  fs.readdirSync(filepath).forEach(file => {
    sources[file] = {content: fs.readFileSync(path.join(filepath, file)).toString()}
  })

  async.waterfall([
    function loadCompiler (next) {
      compiler = new RemixCompiler()
      compiler.onInternalCompilerLoaded()
      // compiler.event.register('compilerLoaded', this, function (version) {
      next()
      // });
    },
    function doCompilation (next) {
      compiler.event.register('compilationFinished', this, function (success, data, source) {
        next(null, data)
      })
      compiler.compile(sources, filepath)
    }
  ], function (err, result) {
    cb(err, result.contracts)
  })
}

module.exports = {
  compileFileOrFiles: compileFileOrFiles
}
<|endoftext|>


<commit_before>angular.module('com.dailymotion.ngEveResource')
    .constant("eveCfg", {
        "dateformat": "YYYY-MM-DDTHH:mm:ss[Z]"
    })
    .factory('eveResource', function ($window, $resource, eveCfg) {
        return function(url, paramDefaults, actions, options, toJsonReplacer) {
            var Resource,
                toJSON;

            if (!angular.isFunction(toJsonReplacer)) {
                if (angular.isFunction(options)) {
                    toJsonReplacer = options;
                    options = {};
                } else {
                    toJsonReplacer = function(key, value) {
                        return value;
                    };
                }
            }

            Resource = $resource(url, paramDefaults, actions, options);

            toJSON = Resource.prototype.toJSON;

            Resource.prototype.toJSON = function() {
                var data = toJSON.call(this);

                angular.forEach(data, function(value, key) {
                    data[key] = key.charAt(0) === '_' ? undefined : toJsonReplacer(key, value);
                });

                return data;
            };

            Resource.prototype.exists = function() {
                return !!this._id;
            };

            function format (time, fmt) {
                return $window.moment && $window.moment.utc ? moment.utc(time).format(fmt || eveCfg.dateformat) : time;
            }

            Resource.prototype.formatUpdated = function (fmt) {
                return format(this._updated, fmt);
            };

            Resource.prototype.formatCreated = function (fmt) {
                return format(this._created, fmt);
            };

            return Resource;
        };
    });
<commit_msg>styles(resource): fix jslint<commit_after>angular.module('com.dailymotion.ngEveResource')
    .constant('eveCfg', {
        'dateformat': 'YYYY-MM-DDTHH:mm:ss[Z]'
    })
    .factory('eveResource', function ($window, $resource, eveCfg) {
        return function(url, paramDefaults, actions, options, toJsonReplacer) {
            var Resource,
                toJSON;

            if (!angular.isFunction(toJsonReplacer)) {
                if (angular.isFunction(options)) {
                    toJsonReplacer = options;
                    options = {};
                } else {
                    toJsonReplacer = function(key, value) {
                        return value;
                    };
                }
            }

            Resource = $resource(url, paramDefaults, actions, options);

            toJSON = Resource.prototype.toJSON;

            Resource.prototype.toJSON = function() {
                var data = toJSON.call(this);

                angular.forEach(data, function(value, key) {
                    data[key] = key.charAt(0) === '_' ? undefined : toJsonReplacer(key, value);
                });

                return data;
            };

            Resource.prototype.exists = function() {
                return !!this._id;
            };

            function format (time, fmt) {
                return $window.moment && $window.moment.utc ? $window.moment.utc(time).format(fmt || eveCfg.dateformat) : time;
            }

            Resource.prototype.formatUpdated = function (fmt) {
                return format(this._updated, fmt);
            };

            Resource.prototype.formatCreated = function (fmt) {
                return format(this._created, fmt);
            };

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


<commit_before>/*
Copyright (c) 2014, Yahoo! Inc. All rights reserved.
Copyrights licensed under the New BSD License.
See the accompanying LICENSE file for terms.
*/

/* jslint esnext: true */

export default Compiler;

function Compiler(locales, formats, pluralFn) {
    this.locales  = locales;
    this.formats  = formats;
    this.pluralFn = pluralFn;
}

Compiler.prototype.compile = function (ast) {
    this.pluralStack        = [];
    this.currentPlural      = null;
    this.pluralNumberFormat = null;

    return this.compileMessage(ast);
};

Compiler.prototype.compileMessage = function (ast) {
    if (!(ast && ast.type === 'messageFormatPattern')) {
        throw new Error('Message AST is not of type: "messageFormatPattern"');
    }

    var elements = ast.elements,
        pattern  = [];

    var i, len, element;

    for (i = 0, len = elements.length; i < len; i += 1) {
        element = elements[i];

        switch (element.type) {
            case 'messageTextElement':
                pattern.push(this.compileMessageText(element));
                break;

            case 'argumentElement':
                pattern.push(this.compileArgument(element));
                break;

            default:
                throw new Error('Message element does not have a valid type');
        }
    }

    return pattern;
};

Compiler.prototype.compileMessageText = function (element) {
    // When this `element` is part of plural sub-pattern and its value contains
    // an unescaped '#', use a `PluralOffsetString` helper to properly output
    // the number with the correct offset in the string.
    if (this.currentPlural && /(^|[^\\])#/g.test(element.value)) {
        // Create a cache a NumberFormat instance that can be reused for any
        // PluralOffsetString instance in this message.
        if (!this.pluralNumberFormat) {
            this.pluralNumberFormat = new Intl.NumberFormat(this.locales);
        }

        return new PluralOffsetString(
                this.currentPlural.id,
                this.currentPlural.format.offset,
                this.pluralNumberFormat,
                element.value);
    }

    // Unescape the escaped '#'s in the message text.
    return element.value.replace(/\\#/g, '#');
};

Compiler.prototype.compileArgument = function (element) {
    var format = element.format;

    if (!format) {
        return new StringFormat(element.id);
    }

    var formats  = this.formats,
        locales  = this.locales,
        pluralFn = this.pluralFn,
        options;

    switch (format.type) {
        case 'numberFormat':
            options = formats.number[format.style];
            return {
                id    : element.id,
                format: new Intl.NumberFormat(locales, options).format
            };

        case 'dateFormat':
            options = formats.date[format.style];
            return {
                id    : element.id,
                format: new Intl.DateTimeFormat(locales, options).format
            };

        case 'timeFormat':
            options = formats.time[format.style];
            return {
                id    : element.id,
                format: new Intl.DateTimeFormat(locales, options).format
            };

        case 'pluralFormat':
            options = this.compileOptions(element);
            return new PluralFormat(
                element.id, format.ordinal, format.offset, options, pluralFn
            );

        case 'selectFormat':
            options = this.compileOptions(element);
            return new SelectFormat(element.id, options);

        default:
            throw new Error('Message element does not have a valid format type');
    }
};

Compiler.prototype.compileOptions = function (element) {
    var format      = element.format,
        options     = format.options,
        optionsHash = {};

    // Save the current plural element, if any, then set it to a new value when
    // compiling the options sub-patterns. This conforms the spec's algorithm
    // for handling `"#"` syntax in message text.
    this.pluralStack.push(this.currentPlural);
    this.currentPlural = format.type === 'pluralFormat' ? element : null;

    var i, len, option;

    for (i = 0, len = options.length; i < len; i += 1) {
        option = options[i];

        // Compile the sub-pattern and save it under the options's selector.
        optionsHash[option.selector] = this.compileMessage(option.value);
    }

    // Pop the plural stack to put back the original current plural value.
    this.currentPlural = this.pluralStack.pop();

    return optionsHash;
};

// -- Compiler Helper Classes --------------------------------------------------

function StringFormat(id) {
    this.id = id;
}

StringFormat.prototype.format = function (value) {
    if (typeof value === 'undefined' || value === null) {
        return '';
    }

    return typeof value === 'string' ? value : String(value);
};

function PluralFormat(id, useOrdinal, offset, options, pluralFn) {
    this.id         = id;
    this.useOrdinal = useOrdinal;
    this.offset     = offset;
    this.options    = options;
    this.pluralFn   = pluralFn;
}

PluralFormat.prototype.getOption = function (value) {
    var options = this.options;

    var option = options['=' + value] ||
            options[this.pluralFn(value - this.offset, this.useOrdinal)];

    return option || options.other;
};

function PluralOffsetString(id, offset, numberFormat, string) {
    this.id           = id;
    this.offset       = offset;
    this.numberFormat = numberFormat;
    this.string       = string;
}

PluralOffsetString.prototype.format = function (value) {
    var number = this.numberFormat.format(value - this.offset);

    return this.string
            .replace(/(^|[^\\])#/g, '$1' + number)
            .replace(/\\#/g, '#');
};

function SelectFormat(id, options) {
    this.id      = id;
    this.options = options;
}

SelectFormat.prototype.getOption = function (value) {
    var options = this.options;
    return options[value] || options.other;
};
<commit_msg>Revert "fix #154 values for 0"<commit_after>/*
Copyright (c) 2014, Yahoo! Inc. All rights reserved.
Copyrights licensed under the New BSD License.
See the accompanying LICENSE file for terms.
*/

/* jslint esnext: true */

export default Compiler;

function Compiler(locales, formats, pluralFn) {
    this.locales  = locales;
    this.formats  = formats;
    this.pluralFn = pluralFn;
}

Compiler.prototype.compile = function (ast) {
    this.pluralStack        = [];
    this.currentPlural      = null;
    this.pluralNumberFormat = null;

    return this.compileMessage(ast);
};

Compiler.prototype.compileMessage = function (ast) {
    if (!(ast && ast.type === 'messageFormatPattern')) {
        throw new Error('Message AST is not of type: "messageFormatPattern"');
    }

    var elements = ast.elements,
        pattern  = [];

    var i, len, element;

    for (i = 0, len = elements.length; i < len; i += 1) {
        element = elements[i];

        switch (element.type) {
            case 'messageTextElement':
                pattern.push(this.compileMessageText(element));
                break;

            case 'argumentElement':
                pattern.push(this.compileArgument(element));
                break;

            default:
                throw new Error('Message element does not have a valid type');
        }
    }

    return pattern;
};

Compiler.prototype.compileMessageText = function (element) {
    // When this `element` is part of plural sub-pattern and its value contains
    // an unescaped '#', use a `PluralOffsetString` helper to properly output
    // the number with the correct offset in the string.
    if (this.currentPlural && /(^|[^\\])#/g.test(element.value)) {
        // Create a cache a NumberFormat instance that can be reused for any
        // PluralOffsetString instance in this message.
        if (!this.pluralNumberFormat) {
            this.pluralNumberFormat = new Intl.NumberFormat(this.locales);
        }

        return new PluralOffsetString(
                this.currentPlural.id,
                this.currentPlural.format.offset,
                this.pluralNumberFormat,
                element.value);
    }

    // Unescape the escaped '#'s in the message text.
    return element.value.replace(/\\#/g, '#');
};

Compiler.prototype.compileArgument = function (element) {
    var format = element.format;

    if (!format) {
        return new StringFormat(element.id);
    }

    var formats  = this.formats,
        locales  = this.locales,
        pluralFn = this.pluralFn,
        options;

    switch (format.type) {
        case 'numberFormat':
            options = formats.number[format.style];
            return {
                id    : element.id,
                format: new Intl.NumberFormat(locales, options).format
            };

        case 'dateFormat':
            options = formats.date[format.style];
            return {
                id    : element.id,
                format: new Intl.DateTimeFormat(locales, options).format
            };

        case 'timeFormat':
            options = formats.time[format.style];
            return {
                id    : element.id,
                format: new Intl.DateTimeFormat(locales, options).format
            };

        case 'pluralFormat':
            options = this.compileOptions(element);
            return new PluralFormat(
                element.id, format.ordinal, format.offset, options, pluralFn
            );

        case 'selectFormat':
            options = this.compileOptions(element);
            return new SelectFormat(element.id, options);

        default:
            throw new Error('Message element does not have a valid format type');
    }
};

Compiler.prototype.compileOptions = function (element) {
    var format      = element.format,
        options     = format.options,
        optionsHash = {};

    // Save the current plural element, if any, then set it to a new value when
    // compiling the options sub-patterns. This conforms the spec's algorithm
    // for handling `"#"` syntax in message text.
    this.pluralStack.push(this.currentPlural);
    this.currentPlural = format.type === 'pluralFormat' ? element : null;

    var i, len, option;

    for (i = 0, len = options.length; i < len; i += 1) {
        option = options[i];

        // Compile the sub-pattern and save it under the options's selector.
        optionsHash[option.selector] = this.compileMessage(option.value);
    }

    // Pop the plural stack to put back the original current plural value.
    this.currentPlural = this.pluralStack.pop();

    return optionsHash;
};

// -- Compiler Helper Classes --------------------------------------------------

function StringFormat(id) {
    this.id = id;
}

StringFormat.prototype.format = function (value) {
    if (!value) {
        return '';
    }

    return typeof value === 'string' ? value : String(value);
};

function PluralFormat(id, useOrdinal, offset, options, pluralFn) {
    this.id         = id;
    this.useOrdinal = useOrdinal;
    this.offset     = offset;
    this.options    = options;
    this.pluralFn   = pluralFn;
}

PluralFormat.prototype.getOption = function (value) {
    var options = this.options;

    var option = options['=' + value] ||
            options[this.pluralFn(value - this.offset, this.useOrdinal)];

    return option || options.other;
};

function PluralOffsetString(id, offset, numberFormat, string) {
    this.id           = id;
    this.offset       = offset;
    this.numberFormat = numberFormat;
    this.string       = string;
}

PluralOffsetString.prototype.format = function (value) {
    var number = this.numberFormat.format(value - this.offset);

    return this.string
            .replace(/(^|[^\\])#/g, '$1' + number)
            .replace(/\\#/g, '#');
};

function SelectFormat(id, options) {
    this.id      = id;
    this.options = options;
}

SelectFormat.prototype.getOption = function (value) {
    var options = this.options;
    return options[value] || options.other;
};
<|endoftext|>


<commit_before>/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-present Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import React from 'react';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from './Home.css';
import imgUrl1 from './cell-pic-1.jpg';
import imgUrl2 from './cell-pic-2.jpg';

// TODO: break all this text out into separate files!
const Home = () => (

ARF6 Inhibitors

          ARF6 plays a critical role in pathologic protein trafficking in
          conditions as seemingly diverse as acute lung injury and melanoma.  A6
          Pharmaceuticals has identified proprietary small molecule inhibitors
          of ARF6. Using these compounds, we have demonstrated efficacy in
          {` in vivo `}
          models of disease including uveal melanoma, malignant sarcoma, acute
          lung injury/acute respiratory distress syndrome, multi-drug resistant
          gram negative bacterial pneumonia, and diabetic retinopathy.

);

export default withStyles(s)(Home);
<commit_msg>Home page edits.<commit_after>/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-present Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import React from 'react';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from './Home.css';
import imgUrl1 from './cell-pic-1.jpg';
import imgUrl2 from './cell-pic-2.jpg';

// TODO: break all this text out into separate files!
const Home = () => (

ARF6 Inhibitors

          ARF6 plays a critical role in pathologic protein trafficking in
          conditions as seemingly diverse as acute lung injury and melanoma. A6
          Pharmaceuticals has identified proprietary small molecule inhibitors
          of ARF6. Using these compounds, we have demonstrated efficacy in
          {` in vivo `}
          models of disease including uveal melanoma, malignant sarcoma, acute
          lung injury/acute respiratory distress syndrome, multi-drug resistant
          gram negative bacterial pneumonia, and diabetic retinopathy.

          A6 is aggressively advancing its lead program in acute respiratory
          distress syndrome through IND and into Phase 1 safety and proof of
          concept, and its pancreatic cancer program through proof of concept in
          animals and into IND-enabling studies.

          A6 is guided by a team of senior managers, scientists, directors, and
          advisors with extensive experience in the pharma industry, finance,
          regulatory affairs, clinical practice, and basic research.

);

export default withStyles(s)(Home);
<|endoftext|>


<commit_before>import DeviceInfo from 'react-native-device-info'

const options = {
	"Content-Type": "application/json",
    headers: {
      'Content-Type': "application/json",
      "Voter-ID": DeviceInfo ? "javazone2017" : "javazone2017"
    }
}

export const feedback: (feedback) => any =
  (feedback) => {
    options.method = 'POST'
    options.body = JSON.stringify(feedback.feedback)
    return fetch(`${config.urls.devnull}/events/${feedback.eventId}/sessions/${feedback.sessionId}/feedbacks`, options)
      .then(res => res.json())
  }<commit_msg>add missing config import<commit_after>import DeviceInfo from 'react-native-device-info'
import config from '../config'

const options = {
	"Content-Type": "application/json",
    headers: {
      'Content-Type': "application/json",
      "Voter-ID": DeviceInfo ? "javazone2017" : "javazone2017"
    }
}

export const feedback: (feedback) => any =
  (feedback) => {
    options.method = 'POST'
    options.body = JSON.stringify(feedback.feedback)
    return fetch(`${config.urls.devnull}/events/${feedback.eventId}/sessions/${feedback.sessionId}/feedbacks`, options)
      .then(res => res.json())
  }<|endoftext|>


<commit_before>
function processTabs(tabs) {
    var tl = tabs.length;
    var wid;
    for(var j=0; j < tl; j++) {
        var tab = tabs[j];
        wid = tab.windowId
        var tid = tab.id;

        tabMap[tid] = tab;

        var mtab = $('

').attr('class','mtab')
                    .attr('id','tab_'+tid);

        var favicon = $('');
        if(tab.favIconUrl) {
            favicon.attr('src', tab.favIconUrl)
                        .attr('class','favicon')
                        .width('24px')
                        .height('24px');
        } else {
            favicon.attr('src', chrome.extension.getURL('images/icon28x28.png'))
                        .attr('class','favicon')
                        .width('24px')
                        .height('24px');
        }
        mtab.append(favicon);

        var staricon = $('');
        staricon.attr('src', chrome.extension.getURL('images/fav'+
                    (Fav.is(tab.url) ? 'on':'off')+'.png'))
                    .attr('class','star')
                    .width('24px')
                    .height('24px');
        mtab.append(staricon);
        staricon.hide();
        staricon.click(function(){
            var p = $(this).parent();
            var match = /tab_(\d+)/.exec(p.attr('id'));
            if(match && match[1]) {
                var tab = tabMap[parseInt(match[1])];
                if(Fav.is(tab.url)) {
                    Fav.remove(tab.url);
                    $(this).attr('src',
                        chrome.extension.getURL('images/favoff.png'));
                } else {
                    var fi = $(this).siblings('.favicon');
                    Fav.add(tab.url, fi.attr('src'));
                    $(this).attr('src',
                        chrome.extension.getURL('images/favon.png'));
                }
            } else {
                alert('Error recognizing the tab');
            }
            return false;
        });

        tabtitle = $('

')
                .attr('class','title').text(tab.title);
        mtab.append(tabtitle);

        windowMap[wid].append(mtab);
    }
    $('.mtab:even',windowMap[wid]).css('background','#eee');
    $('.mtab:odd',windowMap[wid]).css('background','#ddd');
    $('.mtab', windowMap[wid]).click(function(ev) {
        var match = /tab_(\d+)/.exec($(this).attr('id'));
        if(match && match[1]) {
            chrome.tabs.update(parseInt(match[1]), {selected : true});
        }
    });

    $('.mtab', windowMap[wid]).mouseenter(function(ev) {
        $('.star', $(this)).show();
    });
    $('.mtab', windowMap[wid]).mouseleave(function(ev) {
        $('.star', $(this)).hide();
    });

    $('.mtab', windowMap[wid]).css({'width': (winw-50)+'px'})
    $('.mtab > div', windowMap[wid]).css({'width': (winw-140)+'px'})

    $('.mtab:last', windowMap[wid]).css({
        '-webkit-border-bottom-left-radius':'15px',
        '-webkit-border-bottom-right-radius':'15px'
    });

    doneWindows.push({wid:wid,numtabs:tl});

    if(doneWindows.length == windowList.length) {
        layout_windows();
    }
}

function layout_windows() {
    var total_tabs = 0;
    for(var i=0; i < doneWindows.length; i++) {
        total_tabs += doneWindows[i].numtabs;
    }
    tabs_per_col = parseInt(total_tabs/NUMCOL);
    doneWindows.sort(function(a,b) { return (a.numtabs-b.numtabs); });

    columns = new Array(NUMCOL);
    for(var i=0; i < NUMCOL; i++) {
        columns[i] = [];
        columntabs = 0;
        for(j=0; j < doneWindows.length; j++) {
            if(!doneWindows[j]) continue;

            if(doneWindows[j].numtabs + columntabs <= tabs_per_col ||
                i == (NUMCOL-1))
            {
                columns[i].push(doneWindows[j].wid);
                columntabs += doneWindows[j].numtabs;
                doneWindows[j] = null;
            }
        }
    }
    columns.sort(function(a,b) { return b.length-a.length; });
    for(var i=0; i < NUMCOL; i++) {
        var ceiling = CEILING;
        for(var j=0; j < columns[i].length; j++) {
            var wid = columns[i][j];
            var mwin = windowMap[wid];
            mwin.css({
                'left' : (i * winw + (i+0.5) * HMARGIN)+'px',
                'top' : ceiling+'px'
            });
            ceiling += mwin.height() + VMARGIN;
        }
    }
}

var tabMap = [];
var windowMap = [];
var windowList = [];
var doneWindows = [];
var dw, dh, winw;
var HMARGIN = 20;
var VMARGIN = 20;
var NUMCOL = 3;
var CEILING = 20;

$(document).ready(function(){

    dw = $(document).width();
    dh = $(document).height();

    winw = parseInt((dw/NUMCOL) - HMARGIN);

    function create_window_title(title) {
        return $('

')
            .attr('class','wtitle')
            .text(title)
            .css({
                'color' : '#eee',
                'height':'30px',
                'padding-top' : '10px',
                '-webkit-border-top-left-radius':'15px',
                '-webkit-border-top-right-radius':'15px',
                'text-align':'center'
            })
            .click(title_modifier);
    }

    function create_window_title_input() {
        var inp = $('<input></input>')
            .css({
                'height':'20px',
                'margin-top' : '5px',
                'text-align':'center'
            });
        var inpw = $('

').css({
                'height':'30px',
                '-webkit-border-top-left-radius':'15px',
                '-webkit-border-top-right-radius':'15px',
                'text-align':'center'
            });
        inpw.append(inp);
        return { wrapper:inpw, inp:inp };
    }

    function title_modifier() {
        var p = $(this).parent();
        $(this).remove();

        var ninput = create_window_title_input();
        p.prepend(ninput.wrapper);
        ninput.inp.focus();
        ninput.inp.blur(function() {
            var p = $(this).parent().parent();
            $(this).parent().remove();
            var wtitle = create_window_title($(this).val());
            window.localStorage.setItem(
                'window_title_'+p.attr('id'), $(this).val());
            p.prepend(wtitle);
        });
    }

    chrome.windows.getAll(null,
        function(windows) {

            var wl = windows.length;
            for(var i=0; i < wl; i++) {

                var mwin = $('

')
                            .attr('class','mwin')
                            .attr('id', windows[i].id);
                var title_str = window.localStorage.getItem(
                                    'window_title_'+windows[i].id);
                if(title_str) {
                    var wtitle = create_window_title(title_str);
                } else {
                    var wtitle = create_window_title("Name this window");
                }
                mwin.append(wtitle);

                windowMap[windows[i].id] = mwin;
                windowList[i] = mwin;

                $('body').append(mwin);

                chrome.tabs.getAllInWindow(windows[i].id, processTabs);
            }
        }
    );

    $('#creator').css('top',(dh-50)+'px');
    $('#creator').css('left',(dw-140)+'px');
});
<commit_msg>[FAVLIST] adding favorite favicons in the topbar.<commit_after>
function processTabs(tabs) {
    var tl = tabs.length;
    var wid;
    for(var j=0; j < tl; j++) {
        var tab = tabs[j];
        wid = tab.windowId
        var tid = tab.id;

        tabMap[tid] = tab;

        var mtab = $('

').attr('class','mtab')
                    .attr('id','tab_'+tid);

        var favicon = $('');
        if(tab.favIconUrl) {
            favicon.attr('src', tab.favIconUrl)
                        .attr('class','favicon')
                        .width('24px')
                        .height('24px');
        } else {
            favicon.attr('src', chrome.extension.getURL('images/icon28x28.png'))
                        .attr('class','favicon')
                        .width('24px')
                        .height('24px');
        }
        mtab.append(favicon);

        var staricon = $('');
        staricon.attr('src', chrome.extension.getURL('images/fav'+
                    (Fav.is(tab.url) ? 'on':'off')+'.png'))
                    .attr('class','star')
                    .width('24px')
                    .height('24px');
        mtab.append(staricon);
        staricon.hide();
        staricon.click(function(){
            var p = $(this).parent();
            var match = /tab_(\d+)/.exec(p.attr('id'));
            if(match && match[1]) {
                var tab = tabMap[parseInt(match[1])];
                if(Fav.is(tab.url)) {
                    Fav.remove(tab.url);
                    $(this).attr('src',
                        chrome.extension.getURL('images/favoff.png'));
                } else {
                    var fi = $(this).siblings('.favicon');
                    Fav.add(tab.url, fi.attr('src'));
                    $(this).attr('src',
                        chrome.extension.getURL('images/favon.png'));
                }
                refresh_favorites();
            } else {
                alert('Error recognizing the tab');
            }
            return false;
        });

        tabtitle = $('

')
                .attr('class','title').text(tab.title);
        mtab.append(tabtitle);

        windowMap[wid].append(mtab);
    }
    $('.mtab:even',windowMap[wid]).css('background','#eee');
    $('.mtab:odd',windowMap[wid]).css('background','#ddd');
    $('.mtab', windowMap[wid]).click(function(ev) {
        var match = /tab_(\d+)/.exec($(this).attr('id'));
        if(match && match[1]) {
            chrome.tabs.update(parseInt(match[1]), {selected : true});
        }
    });

    $('.mtab', windowMap[wid]).mouseenter(function(ev) {
        $('.star', $(this)).show();
    });
    $('.mtab', windowMap[wid]).mouseleave(function(ev) {
        $('.star', $(this)).hide();
    });

    $('.mtab', windowMap[wid]).css({'width': (winw-50)+'px'})
    $('.mtab > div', windowMap[wid]).css({'width': (winw-140)+'px'})

    $('.mtab:last', windowMap[wid]).css({
        '-webkit-border-bottom-left-radius':'15px',
        '-webkit-border-bottom-right-radius':'15px'
    });

    doneWindows.push({wid:wid,numtabs:tl});

    if(doneWindows.length == windowList.length) {
        layout_windows();
    }
}

function layout_windows() {
    var total_tabs = 0;
    for(var i=0; i < doneWindows.length; i++) {
        total_tabs += doneWindows[i].numtabs;
    }
    tabs_per_col = parseInt(total_tabs/NUMCOL);
    doneWindows.sort(function(a,b) { return (a.numtabs-b.numtabs); });

    columns = new Array(NUMCOL);
    for(var i=0; i < NUMCOL; i++) {
        columns[i] = [];
        columntabs = 0;
        for(j=0; j < doneWindows.length; j++) {
            if(!doneWindows[j]) continue;

            if(doneWindows[j].numtabs + columntabs <= tabs_per_col ||
                i == (NUMCOL-1))
            {
                columns[i].push(doneWindows[j].wid);
                columntabs += doneWindows[j].numtabs;
                doneWindows[j] = null;
            }
        }
    }
    columns.sort(function(a,b) { return b.length-a.length; });
    for(var i=0; i < NUMCOL; i++) {
        var ceiling = CEILING;
        for(var j=0; j < columns[i].length; j++) {
            var wid = columns[i][j];
            var mwin = windowMap[wid];
            mwin.css({
                'left' : (i * winw + (i+0.5) * HMARGIN)+'px',
                'top' : ceiling+'px'
            });
            ceiling += mwin.height() + VMARGIN;
        }
    }
}

var tabMap = [];
var windowMap = [];
var windowList = [];
var doneWindows = [];
var dw, dh, winw;
var HMARGIN = 20;
var VMARGIN = 20;
var NUMCOL = 3;
var CEILING = 50;

$(document).ready(function(){

    dw = $(document).width();
    dh = $(document).height();

    winw = parseInt((dw/NUMCOL) - HMARGIN);

    function create_window_title(title) {
        return $('

')
            .attr('class','wtitle')
            .text(title)
            .css({
                'color' : '#eee',
                'height':'30px',
                'padding-top' : '10px',
                '-webkit-border-top-left-radius':'15px',
                '-webkit-border-top-right-radius':'15px',
                'text-align':'center'
            })
            .click(title_modifier);
    }

    function create_window_title_input() {
        var inp = $('<input></input>')
            .css({
                'height':'20px',
                'margin-top' : '5px',
                'text-align':'center'
            });
        var inpw = $('

').css({
                'height':'30px',
                '-webkit-border-top-left-radius':'15px',
                '-webkit-border-top-right-radius':'15px',
                'text-align':'center'
            });
        inpw.append(inp);
        return { wrapper:inpw, inp:inp };
    }

    function title_modifier() {
        var p = $(this).parent();
        $(this).remove();

        var ninput = create_window_title_input();
        p.prepend(ninput.wrapper);
        ninput.inp.focus();
        ninput.inp.blur(function() {
            var p = $(this).parent().parent();
            $(this).parent().remove();
            var wtitle = create_window_title($(this).val());
            window.localStorage.setItem(
                'window_title_'+p.attr('id'), $(this).val());
            p.prepend(wtitle);
        });
    }

    chrome.windows.getAll(null,
        function(windows) {

            var wl = windows.length;
            for(var i=0; i < wl; i++) {

                var mwin = $('

')
                            .attr('class','mwin')
                            .attr('id', windows[i].id);
                var title_str = window.localStorage.getItem(
                                    'window_title_'+windows[i].id);
                if(title_str) {
                    var wtitle = create_window_title(title_str);
                } else {
                    var wtitle = create_window_title("Name this window");
                }
                mwin.append(wtitle);

                windowMap[windows[i].id] = mwin;
                windowList[i] = mwin;

                $('body').append(mwin);

                chrome.tabs.getAllInWindow(windows[i].id, processTabs);
            }
        }
    );
    refresh_favorites();

    $('#creator').css('top',(dh-50)+'px');
    $('#creator').css('left',(dw-140)+'px');
});

function refresh_favorites()
{
    // Load favorite favicons
    var favlist = Fav.list();
    var fll = favlist.length;
    var topbar = $('#topbar');
    topbar.empty();
    for(var i=0; i < fll; i++) {
        if(favlist[i].favIconUrl) {
            var img = $('').attr('src',favlist[i].favIconUrl)
                                .width('24px')
                                .height('24px');
            var link = $('').attr('href', favlist[i].url);
            link.append(img);
            topbar.append(link);
        }
    }
}
<|endoftext|>


<commit_before>const eastasianwidth = require('eastasianwidth');
const strpad = (str, count) => new Array(count + 1).join(str)

module.exports = (robot) => {
    robot.respond(/突然の (.+)$/i, (msg) => {
        const message = msg.match[1].replace(/^\s+|\s+$/g, '')
        const length = Math.floor(eastasianwidth.length(message) / 2)
        const suddendeath = [
            `＿${strpad('人', length + 2)}＿`,
            `＞　${message}　＜`,
            `￣Y${strpad('^Y', length)}￣`
        ];
        msg.send(suddendeath.join("\n"))
    })
}
<commit_msg>Add help<commit_after>// Description:
//
//
// Commands:
//   hubot 突然の {text} - 突然
//

"use strict"
const eastasianwidth = require('eastasianwidth');
const strpad = (str, count) => new Array(count + 1).join(str)

module.exports = (robot) => {
    robot.respond(/突然の (.+)$/i, (msg) => {
        const message = msg.match[1].replace(/^\s+|\s+$/g, '')
        const length = Math.floor(eastasianwidth.length(message) / 2)
        const suddendeath = [
            `＿${strpad('人', length + 2)}＿`,
            `＞　${message}　＜`,
            `￣Y${strpad('^Y', length)}￣`
        ];
        msg.send(suddendeath.join("\n"))
    })
}
<|endoftext|>


<commit_before>Crafty.extend({
	down: null, //object mousedown, waiting for up
	over: null, //object mouseover, waiting for out

	mouseDispatch: function(e) {
		var maxz = -1,
			closest,
			q,
			i = 0, l;

		//search for all mouse entities
		q = Crafty.map.search(Crafty.viewport.rect());
		for(l=q.length;i<l;++i) {
			//check if has mouse component
			if(!q[i].has("mouse")) continue;

			var current = q[i],
				flag = false,
				x = e.clientX - Crafty.stage.x,
				y = e.clientY - Crafty.stage.y;

			if(current.map) {
				if(current.map.containsPoint(x, y)) {
					flag = true;
				}
			} else if(current.isAt(x, y)) flag = true;

			if(flag && (current._z >= maxz || maxz === -1)) {
				//if the Z is the same, select the closest GUID
				if(current._z === maxz && current[0] < closest[0]) {
					continue;
				}
				maxz = current._z
				closest = current;
			}
		}

		//found closest object to mouse
		if(closest) {

			//click must mousedown and out on tile
			if(e.type === "mousedown") {
				this.down = closest;
			}
			if(e.type === "mouseup") {
				//check that down exists and this is down
				if(this.down && closest === this.down) {
					this.down.trigger("click", e);
					this.down = null;
					return; //exit early
				}
				//reset down
				this.down = null;
			}

			if(e.type === "mousemove") {
				if(this.over !== closest) { //if new mousemove, it is over
					if(this.over) {
						this.over.trigger("mouseout", e); //if over wasn't null, send mouseout
						this.over = null;
					}
					this.over = closest;
					closest.trigger("mouseover", e);
					return;
				}
			}
			closest.trigger(e.type, e);
		} else {
			if(e.type === "mousemove" && this.over) {
				this.over.trigger("mouseout", e);
				this.over = null;
			}
		}
	}
});

//initialize the mouse events onload
Crafty.onload(this, function() {
	Crafty.addEvent(this, Crafty.stage.elem, "mousedown", Crafty.mouseDispatch);
	Crafty.addEvent(this, Crafty.stage.elem, "mouseup", Crafty.mouseDispatch);
	Crafty.addEvent(this, Crafty.stage.elem, "mousemove", Crafty.mouseDispatch);
});

Crafty.c("mouse", {
	areaMap: function(poly) {
		//create polygon
		if(arguments.length > 1) {
			//convert args to array to create polygon
			var args = Array.prototype.slice.call(arguments, 0),
				i = 0, l = args.length;

			for(;i<l;i++) {
				args[i][0] += this.x;
				args[i][1] += this.y;
			}

			poly = new Crafty.polygon(args);
		}

		this.map = poly;
		this.attach(this.map);
		return this;
	}
});

Crafty.c("controls", {
	init: function() {
		function dispatch(e) {
			//e.keyCode = e.charCode || e.keyCode;
			this.trigger(e.type, e);
		}

		Crafty.addEvent(this, "keydown", dispatch);
		Crafty.addEvent(this, "keyup", dispatch);

		//remove events
		this.bind("remove", function() {
			Crafty.removeEvent(this, "keydown", dispatch);
			Crafty.removeEvent(this, "keyup", dispatch);
		});
	},

	preventTypeaheadFind: function(e) {
		if(!(e.metaKey || e.altKey || e.shiftKey || e.ctrlKey) && e.preventDefault){
			e.preventDefault();
		}
		return this;
 	}
});

Crafty.c("fourway", {
	__move: {left: false, right: false, up: false, down: false},
	_speed: 3,

	init: function() {
		if(!this.has("controls")) this.addComponent("controls");
	},

	fourway: function(speed) {
		if(speed) this._speed = speed;
		var move = this.__move;

		this.bind("enterframe", function() {
			var old = this.pos(),
				changed = false;
			if(move.right) {
				this.x += this._speed;
				changed = true;
			}
			if(move.left) {
				this.x -= this._speed;
				changed = true;
			}
			if(move.up) {
				this.y -= this._speed;
				changed = true;
			}
			if(move.down) {
				this.y += this._speed;
				changed = true;
			}
		}).bind("keydown", function(e) {
			if(e.keyCode === Crafty.keys.RA || e.keyCode === Crafty.keys.D) {
				move.right = true;
			}
			if(e.keyCode === Crafty.keys.LA || e.keyCode === Crafty.keys.A) {
				move.left = true;
			}
			if(e.keyCode === Crafty.keys.UA || e.keyCode === Crafty.keys.W) {
				move.up = true;
			}
			if(e.keyCode === Crafty.keys.DA || e.keyCode === Crafty.keys.S) {
				move.down = true;
			}
			this.preventTypeaheadFind(e);
		}).bind("keyup", function(e) {
			if(e.keyCode === Crafty.keys.RA || e.keyCode === Crafty.keys.D) {
				move.right = false;
			}
			if(e.keyCode === Crafty.keys.LA || e.keyCode === Crafty.keys.A) {
				move.left = false;
			}
			if(e.keyCode === Crafty.keys.UA || e.keyCode === Crafty.keys.W) {
				move.up = false;
			}
			if(e.keyCode === Crafty.keys.DA || e.keyCode === Crafty.keys.S) {
				move.down = false;
			}
			this.preventTypeaheadFind(e);
		});

		return this;
	}
});

Crafty.c("twoway", {
	__move: {left: false, right: false, up: false, falling: false},
	_speed: 3,

	init: function() {
		if(!this.has("controls")) this.addComponent("controls");
	},

	twoway: function(speed,jump) {
		if(speed) this._speed = speed;
		jump = jump || this._speed * 2;

		var move = this.__move;

		this.bind("enterframe", function() {
			var old = this.pos(),
				changed = false;
			if(move.right) {
				this.x += this._speed;
				changed = true;
			}
			if(move.left) {
				this.x -= this._speed;
				changed = true;
			}
			if(move.up) {
				this.y -= jump;
				this._falling = true;
				changed = true;
			}
		}).bind("keydown", function(e) {
			if(e.keyCode === Crafty.keys.RA || e.keyCode === Crafty.keys.D) {
				move.right = true;
			}
			if(e.keyCode === Crafty.keys.LA || e.keyCode === Crafty.keys.A) {
				move.left = true;
			}
			if(e.keyCode === Crafty.keys.UA || e.keyCode === Crafty.keys.W) {
				move.up = true;
			}
		}).bind("keyup", function(e) {
			if(e.keyCode === Crafty.keys.RA || e.keyCode === Crafty.keys.D) {
				move.right = false;
			}
			if(e.keyCode === Crafty.keys.LA || e.keyCode === Crafty.keys.A) {
				move.left = false;
			}
		});

		return this;
	}
});
<commit_msg>* Added Adrians patch issue #20 with areaMap and passing a polygon<commit_after>Crafty.extend({
	down: null, //object mousedown, waiting for up
	over: null, //object mouseover, waiting for out

	mouseDispatch: function(e) {
		var maxz = -1,
			closest,
			q,
			i = 0, l;

		//search for all mouse entities
		q = Crafty.map.search(Crafty.viewport.rect());
		for(l=q.length;i<l;++i) {
			//check if has mouse component
			if(!q[i].has("mouse")) continue;

			var current = q[i],
				flag = false,
				x = e.clientX - Crafty.stage.x,
				y = e.clientY - Crafty.stage.y;

			if(current.map) {
				if(current.map.containsPoint(x, y)) {
					flag = true;
				}
			} else if(current.isAt(x, y)) flag = true;

			if(flag && (current._z >= maxz || maxz === -1)) {
				//if the Z is the same, select the closest GUID
				if(current._z === maxz && current[0] < closest[0]) {
					continue;
				}
				maxz = current._z
				closest = current;
			}
		}

		//found closest object to mouse
		if(closest) {

			//click must mousedown and out on tile
			if(e.type === "mousedown") {
				this.down = closest;
			}
			if(e.type === "mouseup") {
				//check that down exists and this is down
				if(this.down && closest === this.down) {
					this.down.trigger("click", e);
					this.down = null;
					return; //exit early
				}
				//reset down
				this.down = null;
			}

			if(e.type === "mousemove") {
				if(this.over !== closest) { //if new mousemove, it is over
					if(this.over) {
						this.over.trigger("mouseout", e); //if over wasn't null, send mouseout
						this.over = null;
					}
					this.over = closest;
					closest.trigger("mouseover", e);
					return;
				}
			}
			closest.trigger(e.type, e);
		} else {
			if(e.type === "mousemove" && this.over) {
				this.over.trigger("mouseout", e);
				this.over = null;
			}
		}
	}
});

//initialize the mouse events onload
Crafty.onload(this, function() {
	Crafty.addEvent(this, Crafty.stage.elem, "mousedown", Crafty.mouseDispatch);
	Crafty.addEvent(this, Crafty.stage.elem, "mouseup", Crafty.mouseDispatch);
	Crafty.addEvent(this, Crafty.stage.elem, "mousemove", Crafty.mouseDispatch);
});

Crafty.c("mouse", {
	areaMap: function(poly) {
		//create polygon
		if(arguments.length > 1) {
			//convert args to array to create polygon
			var args = Array.prototype.slice.call(arguments, 0),
				i = 0, l = args.length;

			for(;i<l;i++) {
				args[i][0] += this.x;
				args[i][1] += this.y;
			}

			poly = new Crafty.polygon(args);
		}

		this.map = poly;
		this.map.shift(this._x, this._y);

		this.attach(this.map);
		return this;
	}
});

Crafty.c("controls", {
	init: function() {
		function dispatch(e) {
			//e.keyCode = e.charCode || e.keyCode;
			this.trigger(e.type, e);
		}

		Crafty.addEvent(this, "keydown", dispatch);
		Crafty.addEvent(this, "keyup", dispatch);

		//remove events
		this.bind("remove", function() {
			Crafty.removeEvent(this, "keydown", dispatch);
			Crafty.removeEvent(this, "keyup", dispatch);
		});
	},

	preventTypeaheadFind: function(e) {
		if(!(e.metaKey || e.altKey || e.shiftKey || e.ctrlKey) && e.preventDefault){
			e.preventDefault();
		}
		return this;
 	}
});

Crafty.c("fourway", {
	__move: {left: false, right: false, up: false, down: false},
	_speed: 3,

	init: function() {
		if(!this.has("controls")) this.addComponent("controls");
	},

	fourway: function(speed) {
		if(speed) this._speed = speed;
		var move = this.__move;

		this.bind("enterframe", function() {
			var old = this.pos(),
				changed = false;
			if(move.right) {
				this.x += this._speed;
				changed = true;
			}
			if(move.left) {
				this.x -= this._speed;
				changed = true;
			}
			if(move.up) {
				this.y -= this._speed;
				changed = true;
			}
			if(move.down) {
				this.y += this._speed;
				changed = true;
			}
		}).bind("keydown", function(e) {
			if(e.keyCode === Crafty.keys.RA || e.keyCode === Crafty.keys.D) {
				move.right = true;
			}
			if(e.keyCode === Crafty.keys.LA || e.keyCode === Crafty.keys.A) {
				move.left = true;
			}
			if(e.keyCode === Crafty.keys.UA || e.keyCode === Crafty.keys.W) {
				move.up = true;
			}
			if(e.keyCode === Crafty.keys.DA || e.keyCode === Crafty.keys.S) {
				move.down = true;
			}
			this.preventTypeaheadFind(e);
		}).bind("keyup", function(e) {
			if(e.keyCode === Crafty.keys.RA || e.keyCode === Crafty.keys.D) {
				move.right = false;
			}
			if(e.keyCode === Crafty.keys.LA || e.keyCode === Crafty.keys.A) {
				move.left = false;
			}
			if(e.keyCode === Crafty.keys.UA || e.keyCode === Crafty.keys.W) {
				move.up = false;
			}
			if(e.keyCode === Crafty.keys.DA || e.keyCode === Crafty.keys.S) {
				move.down = false;
			}
			this.preventTypeaheadFind(e);
		});

		return this;
	}
});

Crafty.c("twoway", {
	__move: {left: false, right: false, up: false, falling: false},
	_speed: 3,

	init: function() {
		if(!this.has("controls")) this.addComponent("controls");
	},

	twoway: function(speed,jump) {
		if(speed) this._speed = speed;
		jump = jump || this._speed * 2;

		var move = this.__move;

		this.bind("enterframe", function() {
			var old = this.pos(),
				changed = false;
			if(move.right) {
				this.x += this._speed;
				changed = true;
			}
			if(move.left) {
				this.x -= this._speed;
				changed = true;
			}
			if(move.up) {
				this.y -= jump;
				this._falling = true;
				changed = true;
			}
		}).bind("keydown", function(e) {
			if(e.keyCode === Crafty.keys.RA || e.keyCode === Crafty.keys.D) {
				move.right = true;
			}
			if(e.keyCode === Crafty.keys.LA || e.keyCode === Crafty.keys.A) {
				move.left = true;
			}
			if(e.keyCode === Crafty.keys.UA || e.keyCode === Crafty.keys.W) {
				move.up = true;
			}
		}).bind("keyup", function(e) {
			if(e.keyCode === Crafty.keys.RA || e.keyCode === Crafty.keys.D) {
				move.right = false;
			}
			if(e.keyCode === Crafty.keys.LA || e.keyCode === Crafty.keys.A) {
				move.left = false;
			}
		});

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