server/helpers/achievement.js

"use strict";

require("core-js/modules/es.weak-map.js");
require("core-js/modules/es.object.get-own-property-descriptor.js");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getConsecutiveDaysWithEdits = getConsecutiveDaysWithEdits;
exports.getEntityVisits = getEntityVisits;
exports.getTypeCreation = getTypeCreation;
exports.processEdit = processEdit;
exports.processPageVisit = processPageVisit;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
require("core-js/modules/es.object.to-string.js");
require("core-js/modules/web.dom-collections.for-each.js");
require("core-js/modules/es.object.keys.js");
require("core-js/modules/es.date.to-json.js");
require("core-js/modules/web.url.to-json.js");
require("core-js/modules/es.array.map.js");
require("core-js/modules/es.function.name.js");
require("core-js/modules/es.array.iterator.js");
require("core-js/modules/es.promise.js");
require("core-js/modules/es.string.iterator.js");
require("core-js/modules/web.dom-collections.iterator.js");
require("core-js/modules/es.array.concat.js");
require("core-js/modules/es.array.join.js");
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _isNil2 = _interopRequireDefault(require("lodash/isNil"));
var _flattenDeep2 = _interopRequireDefault(require("lodash/flattenDeep"));
var error = _interopRequireWildcard(require("../../common/helpers/error"));
var _dateFns = require("date-fns");
var _log = _interopRequireDefault(require("log"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/*
 * Copyright (C) 2016  Max Prettyjohns
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
/**
 * Achievement Module
 * @module Achievement
 */
/**
 * Awards an Unlock type with awardAttribs if not already awarded
 * @param {function} UnlockType - Either TitleUnlock or AchievementUnlock
 * @param {object} awardAttribs - Values that are supplied to Unlock constructor
 * @returns {object} - 'already unlocked' or JSON of new unlock
 */
function awardUnlock(_x, _x2) {
  return _awardUnlock.apply(this, arguments);
}
/**
 * Awards an Achievement
 * @param {object} orm - the BookBrainz ORM, initialized during app setup
 * @param {int} editorId - The editor the achievement will be awarded to
 * @param {string} achievementName - Name of achievement in database
 * @returns {object} - {achievementName: unlock} where unlock is JSON returned
 * from awardUnlock
 * @memberof module:Achievement
 */
function _awardUnlock() {
  _awardUnlock = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(UnlockType, awardAttribs) {
    var award, unlock;
    return _regenerator.default.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.next = 2;
            return new UnlockType(awardAttribs).fetch({
              require: false
            });
          case 2:
            award = _context.sent;
            if (!(award === null || typeof award === 'undefined')) {
              _context.next = 8;
              break;
            }
            _context.next = 6;
            return new UnlockType(awardAttribs).save(null, {
              method: 'insert'
            });
          case 6:
            unlock = _context.sent;
            return _context.abrupt("return", unlock.toJSON());
          case 8:
            return _context.abrupt("return", 'Already unlocked');
          case 9:
          case "end":
            return _context.stop();
        }
      }
    }, _callee);
  }));
  return _awardUnlock.apply(this, arguments);
}
function awardAchievement(_x3, _x4, _x5) {
  return _awardAchievement.apply(this, arguments);
}
/**
 * Awards a Title
 * @param {object} orm - the BookBrainz ORM, initialized during app setup
 * @param {int} editorId - The editor the title will be assigned to
 * @param {object} tier - Achievement Tier the Title (if it exists) belongs to
 * @returns {object} - {tier.titleName: unlock} where unlock comes from
 * awardUnlock or false if the title is not in the tier
 * @memberof module:Achievement
 */
function _awardAchievement() {
  _awardAchievement = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(orm, editorId, achievementName) {
    var AchievementType, AchievementUnlock, achievementTier, achievementAttribs, unlock;
    return _regenerator.default.wrap(function _callee2$(_context2) {
      while (1) {
        switch (_context2.prev = _context2.next) {
          case 0:
            AchievementType = orm.AchievementType, AchievementUnlock = orm.AchievementUnlock;
            _context2.next = 3;
            return new AchievementType({
              name: achievementName
            }).fetch({
              require: false
            });
          case 3:
            achievementTier = _context2.sent;
            if (!(achievementTier === null)) {
              _context2.next = 8;
              break;
            }
            throw new error.AwardNotUnlockedError("Achievement ".concat(achievementName, " not found in database"));
          case 8:
            _context2.prev = 8;
            achievementAttribs = {
              achievementId: achievementTier.id,
              editorId: editorId
            };
            _context2.next = 12;
            return awardUnlock(AchievementUnlock, achievementAttribs);
          case 12:
            unlock = _context2.sent;
            return _context2.abrupt("return", (0, _defineProperty2.default)({}, achievementName, unlock));
          case 16:
            _context2.prev = 16;
            _context2.t0 = _context2["catch"](8);
            throw new error.AwardNotUnlockedError(_context2.t0.message);
          case 19:
          case "end":
            return _context2.stop();
        }
      }
    }, _callee2, null, [[8, 16]]);
  }));
  return _awardAchievement.apply(this, arguments);
}
function awardTitle(_x6, _x7, _x8) {
  return _awardTitle.apply(this, arguments);
}
/**
 * In testTiers a tier is mapped to a list of achievements/titles this
 * converts it to an object keyed by achievementName where it is easier
 * to find a specific achievement.
 * @example
 * awardListToAwardObject([[{'Achievement I': unlockI}]])
 * //returns {'Achievement I': unlockI}
 * @param {object} awardList - List of List of achievement unlocks
 * @returns {object} - Object keyed by achievement name with values
 * unlock json
 */
function _awardTitle() {
  _awardTitle = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(orm, editorId, tier) {
    var TitleType, TitleUnlock, title, titleAttribs, unlock;
    return _regenerator.default.wrap(function _callee3$(_context3) {
      while (1) {
        switch (_context3.prev = _context3.next) {
          case 0:
            TitleType = orm.TitleType, TitleUnlock = orm.TitleUnlock;
            if (!tier.titleName) {
              _context3.next = 22;
              break;
            }
            _context3.next = 4;
            return new TitleType({
              title: tier.titleName
            }).fetch({
              require: false
            });
          case 4:
            title = _context3.sent;
            if (!(title === null)) {
              _context3.next = 9;
              break;
            }
            throw new error.AwardNotUnlockedError("Title ".concat(tier.titleName, " not found in database"));
          case 9:
            _context3.prev = 9;
            titleAttribs = {
              editorId: editorId,
              titleId: title.id
            };
            _context3.next = 13;
            return awardUnlock(TitleUnlock, titleAttribs);
          case 13:
            unlock = _context3.sent;
            return _context3.abrupt("return", (0, _defineProperty2.default)({}, tier.titleName, unlock));
          case 17:
            _context3.prev = 17;
            _context3.t0 = _context3["catch"](9);
            throw new error.AwardNotUnlockedError(_context3.t0.message);
          case 20:
            _context3.next = 23;
            break;
          case 22:
            return _context3.abrupt("return", false);
          case 23:
          case "end":
            return _context3.stop();
        }
      }
    }, _callee3, null, [[9, 17]]);
  }));
  return _awardTitle.apply(this, arguments);
}
function awardListToAwardObject(awardList) {
  var track = {};
  if (awardList) {
    awardList.forEach(function (awardSet) {
      if (!(0, _isNil2.default)(awardSet)) {
        awardSet.forEach(function (award) {
          if (!(0, _isNil2.default)(award)) {
            Object.keys(award).forEach(function (key) {
              track[key] = award[key];
            });
          }
        });
      }
    });
  }
  return track;
}

/**
 * Takes a list of achievement 'tiers' and awards the related achievement and
 * title if the signal is greater than or equal to the threshold
 * @param {object} orm - the BookBrainz ORM, initialized during app setup
 * @param {int} signal - Value tier threshold will be compared against
 * @param {int} editorId - Editor to award achievements/titles to
 * @param {object} tiers - Object with threshold and relatedachievement/title
 * names
 * @example
 * testTiers(10, 1, [{
 * 	threshold: 10, name: 'achievement I', titleName: 'achievement'
 * }])
 * //returns {'achievement I': achievementJSON}
 * @returns {object} - Returns a track of achievements keyed by achievement
 * name/title containing their respective unlockJSON each tier
 */
function testTiers(_x9, _x10, _x11, _x12) {
  return _testTiers.apply(this, arguments);
}
/**
 * Returns number of revisions of a certain type created by a specified
 * editor
 * @param {function} revisionType - Constructor for the revisionType
 * @param {string} revisionString - Snake case string of revisionType
 * @param {int} editor - Editor id being queried
 * @returns {int} - Number of revisions of type (type)
 */
function _testTiers() {
  _testTiers = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5(orm, signal, editorId, tiers) {
    var tierPromise, awardList;
    return _regenerator.default.wrap(function _callee5$(_context5) {
      while (1) {
        switch (_context5.prev = _context5.next) {
          case 0:
            tierPromise = tiers.map( /*#__PURE__*/function () {
              var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4(tier) {
                var achievementUnlock, title, out, _out;
                return _regenerator.default.wrap(function _callee4$(_context4) {
                  while (1) {
                    switch (_context4.prev = _context4.next) {
                      case 0:
                        if (!(signal >= tier.threshold)) {
                          _context4.next = 19;
                          break;
                        }
                        _context4.prev = 1;
                        _context4.next = 4;
                        return awardAchievement(orm, editorId, tier.name);
                      case 4:
                        achievementUnlock = _context4.sent;
                        _context4.next = 7;
                        return awardTitle(orm, editorId, tier);
                      case 7:
                        title = _context4.sent;
                        out = [];
                        if (title) {
                          out.push(title);
                        }
                        out.push(achievementUnlock);
                        return _context4.abrupt("return", out);
                      case 14:
                        _context4.prev = 14;
                        _context4.t0 = _context4["catch"](1);
                        return _context4.abrupt("return", _log.default.debug(_context4.t0));
                      case 17:
                        _context4.next = 23;
                        break;
                      case 19:
                        _out = {};
                        _out[tier.name] = false;
                        if (tier.titleName) {
                          _out[tier.titleName] = false;
                        }
                        return _context4.abrupt("return", [_out]);
                      case 23:
                      case "end":
                        return _context4.stop();
                    }
                  }
                }, _callee4, null, [[1, 14]]);
              }));
              return function (_x56) {
                return _ref3.apply(this, arguments);
              };
            }());
            _context5.next = 3;
            return Promise.all(tierPromise);
          case 3:
            awardList = _context5.sent;
            return _context5.abrupt("return", awardListToAwardObject(awardList));
          case 5:
          case "end":
            return _context5.stop();
        }
      }
    }, _callee5);
  }));
  return _testTiers.apply(this, arguments);
}
function getTypeCreation(_x13, _x14, _x15) {
  return _getTypeCreation.apply(this, arguments);
}
function _getTypeCreation() {
  _getTypeCreation = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee6(revisionType, revisionString, editor) {
    var out;
    return _regenerator.default.wrap(function _callee6$(_context6) {
      while (1) {
        switch (_context6.prev = _context6.next) {
          case 0:
            _context6.next = 2;
            return revisionType.query(function (qb) {
              qb.innerJoin('bookbrainz.revision', 'bookbrainz.revision.id', "bookbrainz.".concat(revisionString, ".id"));
              qb.groupBy("".concat(revisionString, ".id"), "".concat(revisionString, ".bbid"), 'revision.id');
              qb.where('bookbrainz.revision.author_id', '=', editor);
              qb.leftOuterJoin('bookbrainz.revision_parent', 'bookbrainz.revision_parent.child_id', "bookbrainz.".concat(revisionString, ".id"));
              qb.whereNull('bookbrainz.revision_parent.parent_id');
            }).fetchAll({
              require: false
            });
          case 2:
            out = _context6.sent;
            return _context6.abrupt("return", out.length);
          case 4:
          case "end":
            return _context6.stop();
        }
      }
    }, _callee6);
  }));
  return _getTypeCreation.apply(this, arguments);
}
function processRevisionist(_x16, _x17) {
  return _processRevisionist.apply(this, arguments);
}
function _processRevisionist() {
  _processRevisionist = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee7(orm, editorId) {
    var Editor, editor, revisions, tiers;
    return _regenerator.default.wrap(function _callee7$(_context7) {
      while (1) {
        switch (_context7.prev = _context7.next) {
          case 0:
            Editor = orm.Editor;
            _context7.next = 3;
            return new Editor({
              id: editorId
            }).fetch({
              require: false
            });
          case 3:
            editor = _context7.sent;
            revisions = editor.get('revisionsApplied');
            tiers = [{
              name: 'Revisionist III',
              threshold: 250,
              titleName: 'Revisionist'
            }, {
              name: 'Revisionist II',
              threshold: 50
            }, {
              name: 'Revisionist I',
              threshold: 1
            }];
            return _context7.abrupt("return", testTiers(orm, revisions, editorId, tiers));
          case 7:
          case "end":
            return _context7.stop();
        }
      }
    }, _callee7);
  }));
  return _processRevisionist.apply(this, arguments);
}
function processAuthorCreator(_x18, _x19) {
  return _processAuthorCreator.apply(this, arguments);
}
function _processAuthorCreator() {
  _processAuthorCreator = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee8(orm, editorId) {
    var AuthorRevision, rowCount, tiers;
    return _regenerator.default.wrap(function _callee8$(_context8) {
      while (1) {
        switch (_context8.prev = _context8.next) {
          case 0:
            AuthorRevision = orm.AuthorRevision;
            _context8.next = 3;
            return getTypeCreation(new AuthorRevision(), 'author_revision', editorId);
          case 3:
            rowCount = _context8.sent;
            tiers = [{
              name: 'Author Creator III',
              threshold: 100,
              titleName: 'Author Creator'
            }, {
              name: 'Author Creator II',
              threshold: 10
            }, {
              name: 'Author Creator I',
              threshold: 1
            }];
            return _context8.abrupt("return", testTiers(orm, rowCount, editorId, tiers));
          case 6:
          case "end":
            return _context8.stop();
        }
      }
    }, _callee8);
  }));
  return _processAuthorCreator.apply(this, arguments);
}
function processLimitedEdition(_x20, _x21) {
  return _processLimitedEdition.apply(this, arguments);
}
function _processLimitedEdition() {
  _processLimitedEdition = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee9(orm, editorId) {
    var EditionRevision, rowCount, tiers;
    return _regenerator.default.wrap(function _callee9$(_context9) {
      while (1) {
        switch (_context9.prev = _context9.next) {
          case 0:
            EditionRevision = orm.EditionRevision;
            _context9.next = 3;
            return getTypeCreation(new EditionRevision(), 'edition_revision', editorId);
          case 3:
            rowCount = _context9.sent;
            tiers = [{
              name: 'Limited Edition III',
              threshold: 100,
              titleName: 'Limited Edition'
            }, {
              name: 'Limited Edition II',
              threshold: 10
            }, {
              name: 'Limited Edition I',
              threshold: 1
            }];
            return _context9.abrupt("return", testTiers(orm, rowCount, editorId, tiers));
          case 6:
          case "end":
            return _context9.stop();
        }
      }
    }, _callee9);
  }));
  return _processLimitedEdition.apply(this, arguments);
}
function processPublisher(_x22, _x23) {
  return _processPublisher.apply(this, arguments);
}
function _processPublisher() {
  _processPublisher = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee10(orm, editorId) {
    var EditionGroupRevision, rowCount, tiers;
    return _regenerator.default.wrap(function _callee10$(_context10) {
      while (1) {
        switch (_context10.prev = _context10.next) {
          case 0:
            EditionGroupRevision = orm.EditionGroupRevision;
            _context10.next = 3;
            return getTypeCreation(new EditionGroupRevision(), 'edition_group_revision', editorId);
          case 3:
            rowCount = _context10.sent;
            tiers = [{
              name: 'Publisher III',
              threshold: 100,
              titleName: 'Publisher'
            }, {
              name: 'Publisher II',
              threshold: 10
            }, {
              name: 'Publisher I',
              threshold: 1
            }];
            return _context10.abrupt("return", testTiers(orm, rowCount, editorId, tiers));
          case 6:
          case "end":
            return _context10.stop();
        }
      }
    }, _callee10);
  }));
  return _processPublisher.apply(this, arguments);
}
function processPublisherCreator(_x24, _x25) {
  return _processPublisherCreator.apply(this, arguments);
}
function _processPublisherCreator() {
  _processPublisherCreator = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee11(orm, editorId) {
    var PublisherRevision, rowCount, tiers;
    return _regenerator.default.wrap(function _callee11$(_context11) {
      while (1) {
        switch (_context11.prev = _context11.next) {
          case 0:
            PublisherRevision = orm.PublisherRevision;
            _context11.next = 3;
            return getTypeCreation(new PublisherRevision(), 'publisher_revision', editorId);
          case 3:
            rowCount = _context11.sent;
            tiers = [{
              name: 'Publisher Creator III',
              threshold: 100,
              titleName: 'Publisher Creator'
            }, {
              name: 'Publisher Creator II',
              threshold: 10
            }, {
              name: 'Publisher Creator I',
              threshold: 1
            }];
            return _context11.abrupt("return", testTiers(orm, rowCount, editorId, tiers));
          case 6:
          case "end":
            return _context11.stop();
        }
      }
    }, _callee11);
  }));
  return _processPublisherCreator.apply(this, arguments);
}
function processWorkerBee(_x26, _x27) {
  return _processWorkerBee.apply(this, arguments);
}
function _processWorkerBee() {
  _processWorkerBee = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee12(orm, editorId) {
    var WorkRevision, rowCount, tiers;
    return _regenerator.default.wrap(function _callee12$(_context12) {
      while (1) {
        switch (_context12.prev = _context12.next) {
          case 0:
            WorkRevision = orm.WorkRevision;
            _context12.next = 3;
            return getTypeCreation(new WorkRevision(), 'work_revision', editorId);
          case 3:
            rowCount = _context12.sent;
            tiers = [{
              name: 'Worker Bee III',
              threshold: 100,
              titleName: 'Worker Bee'
            }, {
              name: 'Worker Bee II',
              threshold: 10
            }, {
              name: 'Worker Bee I',
              threshold: 1
            }];
            return _context12.abrupt("return", testTiers(orm, rowCount, editorId, tiers));
          case 6:
          case "end":
            return _context12.stop();
        }
      }
    }, _callee12);
  }));
  return _processWorkerBee.apply(this, arguments);
}
function processSeriesCreator(_x28, _x29) {
  return _processSeriesCreator.apply(this, arguments);
}
function _processSeriesCreator() {
  _processSeriesCreator = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee13(orm, editorId) {
    var SeriesRevision, rowCount, tiers;
    return _regenerator.default.wrap(function _callee13$(_context13) {
      while (1) {
        switch (_context13.prev = _context13.next) {
          case 0:
            SeriesRevision = orm.SeriesRevision;
            _context13.next = 3;
            return getTypeCreation(new SeriesRevision(), 'series_revision', editorId);
          case 3:
            rowCount = _context13.sent;
            tiers = [{
              name: 'Series Creator III',
              threshold: 100,
              titleName: 'Series Creator'
            }, {
              name: 'Series Creator II',
              threshold: 10
            }, {
              name: 'Series Creator I',
              threshold: 1
            }];
            return _context13.abrupt("return", testTiers(orm, rowCount, editorId, tiers));
          case 6:
          case "end":
            return _context13.stop();
        }
      }
    }, _callee13);
  }));
  return _processSeriesCreator.apply(this, arguments);
}
function processSprinter(_x30, _x31) {
  return _processSprinter.apply(this, arguments);
}
/**
 * Gets number of consecutive days from today the editor created revisions upto a specified
 * time limit
 * @param {object} orm - the BookBrainz ORM, initialized during app setup
 * @param {int} editorId - Editor to query on
 * @param {int} days - Number of days before today to collect edits from
 * @returns {int} - Number of consecutive days edits were performed on
 */
function _processSprinter() {
  _processSprinter = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee14(orm, editorId) {
    var bookshelf, rawSql, out, tiers;
    return _regenerator.default.wrap(function _callee14$(_context14) {
      while (1) {
        switch (_context14.prev = _context14.next) {
          case 0:
            bookshelf = orm.bookshelf;
            rawSql = "SELECT * from bookbrainz.revision WHERE author_id=".concat(editorId, " \t\tand created_at > (SELECT CURRENT_DATE - INTERVAL '1 hour');");
            _context14.next = 4;
            return bookshelf.knex.raw(rawSql);
          case 4:
            out = _context14.sent;
            tiers = [{
              name: 'Sprinter',
              threshold: 10,
              titleName: 'Sprinter'
            }];
            return _context14.abrupt("return", testTiers(orm, out.rowCount, editorId, tiers));
          case 7:
          case "end":
            return _context14.stop();
        }
      }
    }, _callee14);
  }));
  return _processSprinter.apply(this, arguments);
}
function getConsecutiveDaysWithEdits(_x32, _x33, _x34) {
  return _getConsecutiveDaysWithEdits.apply(this, arguments);
}
function _getConsecutiveDaysWithEdits() {
  _getConsecutiveDaysWithEdits = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee15(orm, editorId, days) {
    var bookshelf, rawSql, out, dateList, countDays, lastDate, i;
    return _regenerator.default.wrap(function _callee15$(_context15) {
      while (1) {
        switch (_context15.prev = _context15.next) {
          case 0:
            bookshelf = orm.bookshelf;
            rawSql = "SELECT DISTINCT created_at::date from bookbrainz.revision \t\tWHERE author_id=".concat(editorId, " \t\tand created_at > (SELECT CURRENT_DATE - INTERVAL '").concat(days, " days');");
            _context15.next = 4;
            return bookshelf.knex.raw(rawSql);
          case 4:
            out = _context15.sent;
            dateList = out.rows.map(function (row) {
              return (0, _dateFns.parseISO)(row.created_at);
            });
            countDays = 0;
            lastDate = new Date(); // count number of consecutive days starting from today
            i = dateList.length - 1;
          case 9:
            if (!(i >= 0)) {
              _context15.next = 17;
              break;
            }
            if (!((0, _dateFns.differenceInCalendarDays)(lastDate, dateList[i]) > 1)) {
              _context15.next = 12;
              break;
            }
            return _context15.abrupt("break", 17);
          case 12:
            countDays++;
            lastDate = dateList[i];
          case 14:
            i--;
            _context15.next = 9;
            break;
          case 17:
            return _context15.abrupt("return", countDays);
          case 18:
          case "end":
            return _context15.stop();
        }
      }
    }, _callee15);
  }));
  return _getConsecutiveDaysWithEdits.apply(this, arguments);
}
function processFunRunner(_x35, _x36) {
  return _processFunRunner.apply(this, arguments);
}
function _processFunRunner() {
  _processFunRunner = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee16(orm, editorId) {
    var rowCount, tiers;
    return _regenerator.default.wrap(function _callee16$(_context16) {
      while (1) {
        switch (_context16.prev = _context16.next) {
          case 0:
            _context16.next = 2;
            return getConsecutiveDaysWithEdits(orm, editorId, 6);
          case 2:
            rowCount = _context16.sent;
            tiers = [{
              name: 'Fun Runner',
              threshold: 7,
              titleName: 'Fun Runner'
            }];
            return _context16.abrupt("return", testTiers(orm, rowCount, editorId, tiers));
          case 5:
          case "end":
            return _context16.stop();
        }
      }
    }, _callee16);
  }));
  return _processFunRunner.apply(this, arguments);
}
function processMarathoner(_x37, _x38) {
  return _processMarathoner.apply(this, arguments);
}
/**
 * Converts achievementTier object to a list of achievementUnlock id's,
 * this will be used to notify the user which achievement they unlocked
 * @param {object}  achievementUnlock - A track of achievements containing
 * unlock JSON for each
 * @returns {list} - A list of achievementUnlock id's
 */
function _processMarathoner() {
  _processMarathoner = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee17(orm, editorId) {
    var rowCount, tiers;
    return _regenerator.default.wrap(function _callee17$(_context17) {
      while (1) {
        switch (_context17.prev = _context17.next) {
          case 0:
            _context17.next = 2;
            return getConsecutiveDaysWithEdits(orm, editorId, 29);
          case 2:
            rowCount = _context17.sent;
            tiers = [{
              name: 'Marathoner',
              threshold: 30,
              titleName: 'Marathoner'
            }];
            return _context17.abrupt("return", testTiers(orm, rowCount, editorId, tiers));
          case 5:
          case "end":
            return _context17.stop();
        }
      }
    }, _callee17);
  }));
  return _processMarathoner.apply(this, arguments);
}
function achievementToUnlockId(achievementUnlock) {
  var unlockIds = [];
  Object.keys(achievementUnlock).forEach(function (key) {
    if (achievementUnlock[key].id) {
      unlockIds.push(String(achievementUnlock[key].id));
    }
  });
  return unlockIds;
}

/**
 * Gets days since edition release date, positive implies released in future
 * @param {object} orm - the BookBrainz ORM, initialized during app setup
 * @param {int} revisionId - Revision to get release date of
 * @returns {int} - Days since edition was released
 */
function getEditionDateDifference(_x39, _x40) {
  return _getEditionDateDifference.apply(this, arguments);
}
function _getEditionDateDifference() {
  _getEditionDateDifference = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee18(orm, revisionId) {
    var EditionRevision, edition, editionJSON, releaseEvents, msInOneDay, attribs, date, now;
    return _regenerator.default.wrap(function _callee18$(_context18) {
      while (1) {
        switch (_context18.prev = _context18.next) {
          case 0:
            EditionRevision = orm.EditionRevision;
            _context18.prev = 1;
            _context18.next = 4;
            return new EditionRevision({
              id: revisionId
            }).fetch({
              withRelated: 'data.releaseEventSet.releaseEvents'
            });
          case 4:
            edition = _context18.sent;
            editionJSON = edition.toJSON();
            releaseEvents = editionJSON.data.releaseEventSet.releaseEvents;
            if (!(releaseEvents.length > 0)) {
              _context18.next = 13;
              break;
            }
            msInOneDay = 86400000;
            attribs = releaseEvents[0];
            date = new Date(attribs.year, attribs.month - 1, attribs.day);
            now = Date.now();
            return _context18.abrupt("return", Math.round((date.getTime() - now) / msInOneDay));
          case 13:
            throw new Error('no date attribute');
          case 16:
            _context18.prev = 16;
            _context18.t0 = _context18["catch"](1);
            throw new Error('no date attribute');
          case 19:
          case "end":
            return _context18.stop();
        }
      }
    }, _callee18, null, [[1, 16]]);
  }));
  return _getEditionDateDifference.apply(this, arguments);
}
function processTimeTraveller(_x41, _x42, _x43) {
  return _processTimeTraveller.apply(this, arguments);
}
function _processTimeTraveller() {
  _processTimeTraveller = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee19(orm, editorId, revisionId) {
    var diff, tiers;
    return _regenerator.default.wrap(function _callee19$(_context19) {
      while (1) {
        switch (_context19.prev = _context19.next) {
          case 0:
            _context19.prev = 0;
            _context19.next = 3;
            return getEditionDateDifference(orm, revisionId);
          case 3:
            diff = _context19.sent;
            tiers = [{
              name: 'Time Traveller',
              threshold: 0,
              titleName: 'Time Traveller'
            }];
            return _context19.abrupt("return", testTiers(orm, diff, editorId, tiers));
          case 8:
            _context19.prev = 8;
            _context19.t0 = _context19["catch"](0);
            return _context19.abrupt("return", {
              'Time Traveller': _context19.t0
            });
          case 11:
          case "end":
            return _context19.stop();
        }
      }
    }, _callee19, null, [[0, 8]]);
  }));
  return _processTimeTraveller.apply(this, arguments);
}
function processHotOffThePress(_x44, _x45, _x46) {
  return _processHotOffThePress.apply(this, arguments);
}
/**
 * Returns number of distinct entities viewed by an editor
 * @param {object} orm - the BookBrainz ORM, initialized during app setup
 * @param {int} editorId - Editor to get views for
 * @returns {int} - Number of views user has
 */
function _processHotOffThePress() {
  _processHotOffThePress = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee20(orm, editorId, revisionId) {
    var diff, tiers;
    return _regenerator.default.wrap(function _callee20$(_context20) {
      while (1) {
        switch (_context20.prev = _context20.next) {
          case 0:
            _context20.prev = 0;
            _context20.next = 3;
            return getEditionDateDifference(orm, revisionId);
          case 3:
            diff = _context20.sent;
            if (!(diff < 0)) {
              _context20.next = 7;
              break;
            }
            tiers = [{
              name: 'Hot Off the Press',
              threshold: -7,
              titleName: 'Hot Off the Press'
            }];
            return _context20.abrupt("return", testTiers(orm, diff, editorId, tiers));
          case 7:
            return _context20.abrupt("return", {
              'Hot Off the Press': false
            });
          case 10:
            _context20.prev = 10;
            _context20.t0 = _context20["catch"](0);
            return _context20.abrupt("return", {
              'Hot Off the Press': _context20.t0
            });
          case 13:
          case "end":
            return _context20.stop();
        }
      }
    }, _callee20, null, [[0, 10]]);
  }));
  return _processHotOffThePress.apply(this, arguments);
}
function getEntityVisits(_x47, _x48) {
  return _getEntityVisits.apply(this, arguments);
}
function _getEntityVisits() {
  _getEntityVisits = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee21(orm, editorId) {
    var EditorEntityVisits, visits;
    return _regenerator.default.wrap(function _callee21$(_context21) {
      while (1) {
        switch (_context21.prev = _context21.next) {
          case 0:
            EditorEntityVisits = orm.EditorEntityVisits;
            _context21.prev = 1;
            _context21.next = 4;
            return new EditorEntityVisits().where('editor_id', editorId).fetchAll({
              require: true
            });
          case 4:
            visits = _context21.sent;
            return _context21.abrupt("return", visits.length);
          case 8:
            _context21.prev = 8;
            _context21.t0 = _context21["catch"](1);
            return _context21.abrupt("return", 0);
          case 11:
          case "end":
            return _context21.stop();
        }
      }
    }, _callee21, null, [[1, 8]]);
  }));
  return _getEntityVisits.apply(this, arguments);
}
function processExplorer(_x49, _x50) {
  return _processExplorer.apply(this, arguments);
}
function _processExplorer() {
  _processExplorer = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee22(orm, editorId) {
    var visits, tiers;
    return _regenerator.default.wrap(function _callee22$(_context22) {
      while (1) {
        switch (_context22.prev = _context22.next) {
          case 0:
            _context22.prev = 0;
            _context22.next = 3;
            return getEntityVisits(orm, editorId);
          case 3:
            visits = _context22.sent;
            tiers = [{
              name: 'Explorer I',
              threshold: 10
            }, {
              name: 'Explorer II',
              threshold: 100
            }, {
              name: 'Explorer III',
              threshold: 1000,
              titleName: 'Explorer'
            }];
            return _context22.abrupt("return", testTiers(orm, visits, editorId, tiers));
          case 8:
            _context22.prev = 8;
            _context22.t0 = _context22["catch"](0);
            return _context22.abrupt("return", {
              Explorer: _context22.t0
            });
          case 11:
          case "end":
            return _context22.stop();
        }
      }
    }, _callee22, null, [[0, 8]]);
  }));
  return _processExplorer.apply(this, arguments);
}
function processPageVisit(_x51, _x52) {
  return _processPageVisit.apply(this, arguments);
}
/**
 * Run each time an edit occurs on the site, will test for each achievement
 * type
 * @param {object} orm - the BookBrainz ORM, initialized during app setup
 * @param {int} userId - Id of the user to query
 * @param {int} revisionId - Id of latest revision
 * @returns {object} - Output of each achievement test as well as an alert
 * containing id's for each unlocked achievement in .alert
 */
function _processPageVisit() {
  _processPageVisit = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee23(orm, userId) {
    var explorer, unlockIds, alert;
    return _regenerator.default.wrap(function _callee23$(_context23) {
      while (1) {
        switch (_context23.prev = _context23.next) {
          case 0:
            _context23.next = 2;
            return processExplorer(orm, userId);
          case 2:
            explorer = _context23.sent;
            unlockIds = achievementToUnlockId(explorer);
            alert = unlockIds.join(',');
            return _context23.abrupt("return", {
              alert: alert,
              explorer: explorer
            });
          case 6:
          case "end":
            return _context23.stop();
        }
      }
    }, _callee23);
  }));
  return _processPageVisit.apply(this, arguments);
}
function processEdit(_x53, _x54, _x55) {
  return _processEdit.apply(this, arguments);
}
function _processEdit() {
  _processEdit = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee24(orm, userId, revisionId) {
    var revisionist, authorCreator, limitedEdition, publisher, publisherCreator, workerBee, seriesCreator, sprinter, funRunner, marathoner, timeTraveller, hotOffThePress, alert;
    return _regenerator.default.wrap(function _callee24$(_context24) {
      while (1) {
        switch (_context24.prev = _context24.next) {
          case 0:
            _context24.next = 2;
            return processRevisionist(orm, userId);
          case 2:
            revisionist = _context24.sent;
            _context24.next = 5;
            return processAuthorCreator(orm, userId);
          case 5:
            authorCreator = _context24.sent;
            _context24.next = 8;
            return processLimitedEdition(orm, userId);
          case 8:
            limitedEdition = _context24.sent;
            _context24.next = 11;
            return processPublisher(orm, userId);
          case 11:
            publisher = _context24.sent;
            _context24.next = 14;
            return processPublisherCreator(orm, userId);
          case 14:
            publisherCreator = _context24.sent;
            _context24.next = 17;
            return processWorkerBee(orm, userId);
          case 17:
            workerBee = _context24.sent;
            _context24.next = 20;
            return processSeriesCreator(orm, userId);
          case 20:
            seriesCreator = _context24.sent;
            _context24.next = 23;
            return processSprinter(orm, userId);
          case 23:
            sprinter = _context24.sent;
            _context24.next = 26;
            return processFunRunner(orm, userId);
          case 26:
            funRunner = _context24.sent;
            _context24.next = 29;
            return processMarathoner(orm, userId);
          case 29:
            marathoner = _context24.sent;
            _context24.next = 32;
            return processTimeTraveller(orm, userId, revisionId);
          case 32:
            timeTraveller = _context24.sent;
            _context24.next = 35;
            return processHotOffThePress(orm, userId, revisionId);
          case 35:
            hotOffThePress = _context24.sent;
            alert = [];
            alert.push(achievementToUnlockId(revisionist), achievementToUnlockId(authorCreator), achievementToUnlockId(limitedEdition), achievementToUnlockId(publisher), achievementToUnlockId(publisherCreator), achievementToUnlockId(workerBee), achievementToUnlockId(seriesCreator), achievementToUnlockId(sprinter), achievementToUnlockId(funRunner), achievementToUnlockId(marathoner), achievementToUnlockId(timeTraveller), achievementToUnlockId(hotOffThePress));
            alert = (0, _flattenDeep2.default)(alert);
            alert = alert.join(',');
            return _context24.abrupt("return", {
              alert: alert,
              authorCreator: authorCreator,
              funRunner: funRunner,
              hotOffThePress: hotOffThePress,
              limitedEdition: limitedEdition,
              marathoner: marathoner,
              publisher: publisher,
              publisherCreator: publisherCreator,
              revisionist: revisionist,
              seriesCreator: seriesCreator,
              sprinter: sprinter,
              timeTraveller: timeTraveller,
              workerBee: workerBee
            });
          case 41:
          case "end":
            return _context24.stop();
        }
      }
    }, _callee24);
  }));
  return _processEdit.apply(this, arguments);
}
//# sourceMappingURL=achievement.js.map