diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000..a79bb4ce61
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,2 @@
+compile:
+ ./node_modules/browserify/bin/cmd.js index.js > index-browser.js
\ No newline at end of file
diff --git a/README.md b/README.md
index 37fda89096..268859e4de 100644
--- a/README.md
+++ b/README.md
@@ -4,9 +4,10 @@ Shared resources useful for the multiple HabitRPG repositories, that way all the
* Algorithms - level up algorithm, scoring functions, etc
* Item definitions - weapons, armor, pets
-You only need to include algos.coffee
-It will include the rest as necessary.
-
+##Browserify Usage (TODO fix up this documentation to use old browserify setup)
+The `Makefile` runs Browserify to compile `index-browser.js`, which you include in a `` tag in your index.html. This way, you get all the JS min/concat'd
+ * `npm install`
+ * `make`
##Installation
diff --git a/index.js b/index.js
new file mode 100644
index 0000000000..b0dd046519
--- /dev/null
+++ b/index.js
@@ -0,0 +1,8 @@
+exports.algos = require('./script/algos')
+exports.items = require('./script/items')
+exports.helpers = require('./script/helpers')
+
+try {
+ window;
+ window.habitrpgShared = exports;
+} catch(e) {}
\ No newline at end of file
diff --git a/package.json b/package.json
index 1ff2bbde60..e5aac23bf0 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,9 @@
{
- "name": "habitrpg-shared",
- "version": "0.0.0",
- "dependencies": {
- }
+ "name": "habitrpg-shared",
+ "version": "0.0.0",
+ "dependencies": {
+ "browserify": "~2.14.1",
+ "lodash": "~1.2.1",
+ "moment": "~2.0.0"
+ }
}
diff --git a/script/items.coffee b/script/items.coffee
new file mode 100644
index 0000000000..78f5abc409
--- /dev/null
+++ b/script/items.coffee
@@ -0,0 +1,109 @@
+_ = require 'lodash'
+
+items = module.exports.items =
+ weapon: [
+ {index: 0, text: "Training Sword", classes: "weapon_0", notes:'Training weapon.', strength: 0, value:0}
+ {index: 1, text: "Sword", classes:'weapon_1', notes:'Increases experience gain by 3%.', strength: 3, value:20}
+ {index: 2, text: "Axe", classes:'weapon_2', notes:'Increases experience gain by 6%.', strength: 6, value:30}
+ {index: 3, text: "Morningstar", classes:'weapon_3', notes:'Increases experience gain by 9%.', strength: 9, value:45}
+ {index: 4, text: "Blue Sword", classes:'weapon_4', notes:'Increases experience gain by 12%.', strength: 12, value:65}
+ {index: 5, text: "Red Sword", classes:'weapon_5', notes:'Increases experience gain by 15%.', strength: 15, value:90}
+ {index: 6, text: "Golden Sword", classes:'weapon_6', notes:'Increases experience gain by 18%.', strength: 18, value:120}
+ {index: 7, text: "Dark Souls Blade", classes:'weapon_7', notes:'Increases experience gain by 21%.', strength: 21, value:150}
+ ]
+ armor: [
+ {index: 0, text: "Cloth Armor", classes: 'armor_0', notes:'Training armor.', defense: 0, value:0}
+ {index: 1, text: "Leather Armor", classes: 'armor_1', notes:'Decreases HP loss by 4%.', defense: 4, value:30}
+ {index: 2, text: "Chain Mail", classes: 'armor_2', notes:'Decreases HP loss by 6%.', defense: 6, value:45}
+ {index: 3, text: "Plate Mail", classes: 'armor_3', notes:'Decreases HP loss by 7%.', defense: 7, value:65}
+ {index: 4, text: "Red Armor", classes: 'armor_4', notes:'Decreases HP loss by 8%.', defense: 8, value:90}
+ {index: 5, text: "Golden Armor", classes: 'armor_5', notes:'Decreases HP loss by 10%.', defense: 10, value:120}
+ {index: 6, text: "Shade Armor", classes: 'armor_6', notes:'Decreases HP loss by 12%.', defense: 12, value:150}
+ ]
+ head: [
+ {index: 0, text: "No Helm", classes: 'head_0', notes:'Training helm.', defense: 0, value:0}
+ {index: 1, text: "Leather Helm", classes: 'head_1', notes:'Decreases HP loss by 2%.', defense: 2, value:15}
+ {index: 2, text: "Chain Coif", classes: 'head_2', notes:'Decreases HP loss by 3%.', defense: 3, value:25}
+ {index: 3, text: "Plate Helm", classes: 'head_3', notes:'Decreases HP loss by 4%.', defense: 4, value:45}
+ {index: 4, text: "Red Helm", classes: 'head_4', notes:'Decreases HP loss by 5%.', defense: 5, value:60}
+ {index: 5, text: "Golden Helm", classes: 'head_5', notes:'Decreases HP loss by 6%.', defense: 6, value:80}
+ {index: 6, text: "Shade Helm", classes: 'head_6', notes:'Decreases HP loss by 7%.', defense: 7, value:100}
+ ]
+ shield: [
+ {index: 0, text: "No Shield", classes: 'shield_0', notes:'No Shield.', defense: 0, value:0}
+ {index: 1, text: "Wooden Shield", classes: 'shield_1', notes:'Decreases HP loss by 3%', defense: 3, value:20}
+ {index: 2, text: "Buckler", classes: 'shield_2', notes:'Decreases HP loss by 4%.', defense: 4, value:35}
+ {index: 3, text: "Enforced Shield", classes: 'shield_3', notes:'Decreases HP loss by 5%.', defense: 5, value:55}
+ {index: 4, text: "Red Shield", classes: 'shield_4', notes:'Decreases HP loss by 7%.', defense: 7, value:70}
+ {index: 5, text: "Golden Shield", classes: 'shield_5', notes:'Decreases HP loss by 8%.', defense: 8, value:90}
+ {index: 6, text: "Tormented Skull", classes: 'shield_6', notes:'Decreases HP loss by 9%.', defense: 9, value:120}
+ ]
+ potion: {type: 'potion', text: "Potion", notes: "Recover 15 HP", value: 25, classes: 'potion'}
+ reroll: {type: 'reroll', text: "Re-Roll", classes: 'reroll', notes: "Resets your task values back to 0 (yellow). Useful when everything's red and it's hard to stay alive.", value:0 }
+
+ pets: [
+ {text: 'Wolf', name: 'Wolf', value: 3}
+ {text: 'Tiger Cub', name: 'TigerCub', value: 3}
+ #{text: 'Polar Bear Cub', name: 'PolarBearCub', value: 3} #commented out because there are no polarbear modifiers yet, special drop?
+ {text: 'Panda Cub', name: 'PandaCub', value: 3}
+ {text: 'Lion Cub', name: 'LionCub', value: 3}
+ {text: 'Fox', name: 'Fox', value: 3}
+ {text: 'Flying Pig', name: 'FlyingPig', value: 3}
+ {text: 'Dragon', name: 'Dragon', value: 3}
+ {text: 'Cactus', name: 'Cactus', value: 3}
+ {text: 'Bear Cub', name: 'BearCub', value: 3}
+ ]
+
+ hatchingPotions: [
+ {text: 'Base', name: 'Base', notes: "Hatches your pet in it's base form.", value: 1}
+ {text: 'White', name: 'White', notes: 'Turns your animal into a White pet.', value: 2}
+ {text: 'Desert', name: 'Desert', notes: 'Turns your animal into a Desert pet.', value: 2}
+ {text: 'Red', name: 'Red', notes: 'Turns your animal into a Red pet.', value: 3}
+ {text: 'Shade', name: 'Shade', notes: 'Turns your animal into a Shade pet.', value: 3}
+ {text: 'Skeleton', name: 'Skeleton', notes: 'Turns your animal into a Skeleton.', value: 3}
+ {text: 'Zombie', name: 'Zombie', notes: 'Turns your animal into a Zombie.', value: 4}
+ {text: 'Cotton Candy Pink', name: 'CottonCandyPink', notes: 'Turns your animal into a Cotton Candy Pink pet.', value: 4}
+ {text: 'Cotton Candy Blue', name: 'CottonCandyBlue', notes: 'Turns your animal into a Cotton Candy Blue pet.', value: 4}
+ {text: 'Golden', name: 'Golden', notes: 'Turns your animal into a Golden pet.', value: 5}
+ ]
+
+# add "type" to each item, so we can reference that as "weapon" or "armor" in the html
+_.each ['weapon', 'armor', 'head', 'shield'], (key) ->
+ _.each items[key], (item) -> item.type = key
+
+_.each items.pets, (pet) -> pet.notes = 'Find a hatching potion to pour on this egg, and one day it will hatch into a loyal pet.'
+_.each items.hatchingPotions, (hatchingPotion) -> hatchingPotion.notes = "Pour this on an egg, and it will hatch as a #{hatchingPotion.text} pet."
+
+module.exports.buyItem = (user, type, value, index) ->
+ return false if user.stats.gp < value
+ changes = {}
+ switch type
+ when 'weapon' then changes['items.weapon'] = index
+ when 'armor' then changes['items.armor'] = index
+ when 'head' then changes['items.head'] = index
+ when 'shield' then changes['items.shield'] = index
+ when 'potion'
+ hp = user.stats.hp
+ hp += 15; hp = 50 if hp > 50
+ changes['stats.hp'] = hp
+ changes['stats.gp'] = user.stats.gp - value
+ #_.each changes, (v,k) -> helpers.pathSet(k,v,user) # @yangit uncomment this i
+ return changes
+
+###
+ update store
+###
+module.exports.updateStore = (user) ->
+ changes = {}
+ _.each ['weapon', 'armor', 'shield', 'head'], (type) ->
+ i = parseInt(user.items?[type] || 0) + 1
+ showNext = true
+ if i is items[type].length - 1
+ if (type in ['armor', 'shield', 'head'])
+ showNext = user.backer.tier >= 45 # backer armor
+ else
+ showNext = user.backer.tier >= 70 # backer weapon
+ else if i is items[type].length
+ showNext = false
+ changes[type] = if showNext then items[type][i] else {hide:true}
+ return changes
\ No newline at end of file
diff --git a/script/items.js b/script/items.js
deleted file mode 100644
index c3a98253ba..0000000000
--- a/script/items.js
+++ /dev/null
@@ -1,453 +0,0 @@
-({
- define: (typeof define === "function" ? define : function (F) {
- return F(require, exports, module);
- })
-}).define(function (require, exports, module) {
- var items, obj, updateStore;
-
- obj = module.exports = {};
- items = obj.items = {
- weapon: [
- {
- index: 0,
- text: "Training Sword",
- classes: "weapon_0",
- notes: 'Training weapon.',
- strength: 0,
- value: 0
- },
- {
- index: 1,
- text: "Sword",
- classes: 'weapon_1',
- notes: 'Increases experience gain by 3%.',
- strength: 3,
- value: 20
- },
- {
- index: 2,
- text: "Axe",
- classes: 'weapon_2',
- notes: 'Increases experience gain by 6%.',
- strength: 6,
- value: 30
- },
- {
- index: 3,
- text: "Morningstar",
- classes: 'weapon_3',
- notes: 'Increases experience gain by 9%.',
- strength: 9,
- value: 45
- },
- {
- index: 4,
- text: "Blue Sword",
- classes: 'weapon_4',
- notes: 'Increases experience gain by 12%.',
- strength: 12,
- value: 65
- },
- {
- index: 5,
- text: "Red Sword",
- classes: 'weapon_5',
- notes: 'Increases experience gain by 15%.',
- strength: 15,
- value: 90
- },
- {
- index: 6,
- text: "Golden Sword",
- classes: 'weapon_6',
- notes: 'Increases experience gain by 18%.',
- strength: 18,
- value: 120
- },
- {
- index: 7,
- text: "Dark Souls Blade",
- classes: 'weapon_7',
- notes: 'Increases experience gain by 21%.',
- strength: 21,
- value: 150
- }
- ],
- armor: [
- {
- index: 0,
- text: "Cloth Armor",
- classes: 'armor_0',
- notes: 'Training armor.',
- defense: 0,
- value: 0
- },
- {
- index: 1,
- text: "Leather Armor",
- classes: 'armor_1',
- notes: 'Decreases HP loss by 4%.',
- defense: 4,
- value: 30
- },
- {
- index: 2,
- text: "Chain Mail",
- classes: 'armor_2',
- notes: 'Decreases HP loss by 6%.',
- defense: 6,
- value: 45
- },
- {
- index: 3,
- text: "Plate Mail",
- classes: 'armor_3',
- notes: 'Decreases HP loss by 7%.',
- defense: 7,
- value: 65
- },
- {
- index: 4,
- text: "Red Armor",
- classes: 'armor_4',
- notes: 'Decreases HP loss by 8%.',
- defense: 8,
- value: 90
- },
- {
- index: 5,
- text: "Golden Armor",
- classes: 'armor_5',
- notes: 'Decreases HP loss by 10%.',
- defense: 10,
- value: 120
- },
- {
- index: 6,
- text: "Shade Armor",
- classes: 'armor_6',
- notes: 'Decreases HP loss by 12%.',
- defense: 12,
- value: 150
- }
- ],
- head: [
- {
- index: 0,
- text: "No Helm",
- classes: 'head_0',
- notes: 'Training helm.',
- defense: 0,
- value: 0
- },
- {
- index: 1,
- text: "Leather Helm",
- classes: 'head_1',
- notes: 'Decreases HP loss by 2%.',
- defense: 2,
- value: 15
- },
- {
- index: 2,
- text: "Chain Coif",
- classes: 'head_2',
- notes: 'Decreases HP loss by 3%.',
- defense: 3,
- value: 25
- },
- {
- index: 3,
- text: "Plate Helm",
- classes: 'head_3',
- notes: 'Decreases HP loss by 4%.',
- defense: 4,
- value: 45
- },
- {
- index: 4,
- text: "Red Helm",
- classes: 'head_4',
- notes: 'Decreases HP loss by 5%.',
- defense: 5,
- value: 60
- },
- {
- index: 5,
- text: "Golden Helm",
- classes: 'head_5',
- notes: 'Decreases HP loss by 6%.',
- defense: 6,
- value: 80
- },
- {
- index: 6,
- text: "Shade Helm",
- classes: 'head_6',
- notes: 'Decreases HP loss by 7%.',
- defense: 7,
- value: 100
- }
- ],
- shield: [
- {
- index: 0,
- text: "No Shield",
- classes: 'shield_0',
- notes: 'No Shield.',
- defense: 0,
- value: 0
- },
- {
- index: 1,
- text: "Wooden Shield",
- classes: 'shield_1',
- notes: 'Decreases HP loss by 3%',
- defense: 3,
- value: 20
- },
- {
- index: 2,
- text: "Buckler",
- classes: 'shield_2',
- notes: 'Decreases HP loss by 4%.',
- defense: 4,
- value: 35
- },
- {
- index: 3,
- text: "Enforced Shield",
- classes: 'shield_3',
- notes: 'Decreases HP loss by 5%.',
- defense: 5,
- value: 55
- },
- {
- index: 4,
- text: "Red Shield",
- classes: 'shield_4',
- notes: 'Decreases HP loss by 7%.',
- defense: 7,
- value: 70
- },
- {
- index: 5,
- text: "Golden Shield",
- classes: 'shield_5',
- notes: 'Decreases HP loss by 8%.',
- defense: 8,
- value: 90
- },
- {
- index: 6,
- text: "Tormented Skull",
- classes: 'shield_6',
- notes: 'Decreases HP loss by 9%.',
- defense: 9,
- value: 120
- }
- ],
- potion: {
- type: 'potion',
- text: "Potion",
- notes: "Recover 15 HP",
- value: 25,
- classes: 'potion'
- },
- reroll: {
- type: 'reroll',
- text: "Re-Roll",
- classes: 'reroll',
- notes: "Resets your task values back to 0 (yellow). Useful when everything's red and it's hard to stay alive.",
- value: 0
- },
- pets: [
- {
- text: 'Wolf',
- name: 'Wolf',
- value: 3
- },
- {
- text: 'Tiger Cub',
- name: 'TigerCub',
- value: 3
- },
- {
- text: 'Panda Cub',
- name: 'PandaCub',
- value: 3
- },
- {
- text: 'Lion Cub',
- name: 'LionCub',
- value: 3
- },
- {
- text: 'Fox',
- name: 'Fox',
- value: 3
- },
- {
- text: 'Flying Pig',
- name: 'FlyingPig',
- value: 3
- },
- {
- text: 'Dragon',
- name: 'Dragon',
- value: 3
- },
- {
- text: 'Cactus',
- name: 'Cactus',
- value: 3
- },
- {
- text: 'Bear Cub',
- name: 'BearCub',
- value: 3
- }
- ],
- hatchingPotions: [
- {
- text: 'Base',
- name: 'Base',
- notes: "Hatches your pet in it's base form.",
- value: 1
- },
- {
- text: 'White',
- name: 'White',
- notes: 'Turns your animal into a White pet.',
- value: 2
- },
- {
- text: 'Desert',
- name: 'Desert',
- notes: 'Turns your animal into a Desert pet.',
- value: 2
- },
- {
- text: 'Red',
- name: 'Red',
- notes: 'Turns your animal into a Red pet.',
- value: 3
- },
- {
- text: 'Shade',
- name: 'Shade',
- notes: 'Turns your animal into a Shade pet.',
- value: 3
- },
- {
- text: 'Skeleton',
- name: 'Skeleton',
- notes: 'Turns your animal into a Skeleton.',
- value: 3
- },
- {
- text: 'Zombie',
- name: 'Zombie',
- notes: 'Turns your animal into a Zombie.',
- value: 4
- },
- {
- text: 'Cotton Candy Pink',
- name: 'CottonCandyPink',
- notes: 'Turns your animal into a Cotton Candy Pink pet.',
- value: 4
- },
- {
- text: 'Cotton Candy Blue',
- name: 'CottonCandyBlue',
- notes: 'Turns your animal into a Cotton Candy Blue pet.',
- value: 4
- },
- {
- text: 'Golden',
- name: 'Golden',
- notes: 'Turns your animal into a Golden pet.',
- value: 5
- }
- ]
- };
- ['weapon', 'armor', 'head', 'shield'].forEach(function (key) {
- return items[key].forEach(function (item) {
- return item.type = key;
- });
- });
- items.pets.forEach(function (pet) {
- return pet.notes = 'Find a hatching potion to pour on this egg, and one day it will hatch into a loyal pet.';
- });
- items.hatchingPotions.forEach(function (hatchingPotion) {
- return hatchingPotion.notes = "Pour this on an egg, and it will hatch as a " + hatchingPotion.text + " pet.";
- });
- /*
- app exports
- */
-
- obj.app = function (appExports, user) {
- return appExports.buyItem = function (e, el, next) {
- var deductGP, gp, hp, index, type, value, _ref;
-
- gp = user.stats.gp;
- _ref = [$(el).attr('data-type'), $(el).attr('data-value'), $(el).attr('data-index')], type = _ref[0], value = _ref[1], index = _ref[2];
- if (gp < value) {
- return;
- }
- deductGP = function () {
- return user.stats.gp = gp - value;
- };
- if (type === 'weapon') {
- user.set('items.weapon', index, deductGP);
- return updateStore(model);
- } else if (type === 'armor') {
- user.set('items.armor', index, deductGP);
- return updateStore(model);
- } else if (type === 'head') {
- user.set('items.head', index, deductGP);
- return updateStore(model);
- } else if (type === 'shield') {
- user.set('items.shield', index, deductGP);
- return updateStore(model);
- } else if (type === 'potion') {
- hp = user.get('stats.hp');
- hp += 15;
- if (hp > 50) {
- hp = 50;
- }
- return user.set('stats.hp', hp, deductGP);
- }
- };
- };
- /*
- update store
- */
-
- return obj.updateStore = updateStore = function (user) {
- var equipped;
-
- if (items.next == null) {
- items.next = {};
- }
- equipped = user.items;
- return ['weapon', 'armor', 'shield', 'head'].forEach(function (type) {
- var i, showNext;
-
- i = parseInt(typeof equipped === "function" ? equipped([type] || 0) : void 0) + 1;
- showNext = true;
- if (i === items[type].length - 1) {
- if ((type === 'armor' || type === 'shield' || type === 'head')) {
- showNext = user.backer.tier >= 45;
- } else {
- showNext = user.backer.tier >= 70;
- }
- } else if (i === items[type].length) {
- showNext = false;
- }
- return items.next[type] = showNext ? items[type][i] : {
- hide: true
- };
- });
- };
- });
\ No newline at end of file
diff --git a/script/moment.js b/script/moment.js
deleted file mode 100644
index 4e8497a9d7..0000000000
--- a/script/moment.js
+++ /dev/null
@@ -1,6 +0,0 @@
-// moment.js
-// version : 2.0.0
-// author : Tim Wood
-// license : MIT
-// momentjs.com
-(function(e){function O(e,t){return function(n){return j(e.call(this,n),t)}}function M(e){return function(t){return this.lang().ordinal(e.call(this,t))}}function _(){}function D(e){H(this,e)}function P(e){var t=this._data={},n=e.years||e.year||e.y||0,r=e.months||e.month||e.M||0,i=e.weeks||e.week||e.w||0,s=e.days||e.day||e.d||0,o=e.hours||e.hour||e.h||0,u=e.minutes||e.minute||e.m||0,a=e.seconds||e.second||e.s||0,f=e.milliseconds||e.millisecond||e.ms||0;this._milliseconds=f+a*1e3+u*6e4+o*36e5,this._days=s+i*7,this._months=r+n*12,t.milliseconds=f%1e3,a+=B(f/1e3),t.seconds=a%60,u+=B(a/60),t.minutes=u%60,o+=B(u/60),t.hours=o%24,s+=B(o/24),s+=i*7,t.days=s%30,r+=B(s/30),t.months=r%12,n+=B(r/12),t.years=n}function H(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}function B(e){return e<0?Math.ceil(e):Math.floor(e)}function j(e,t){var n=e+"";while(n.length68?1900:2e3);break;case"YYYY":case"YYYYY":s[0]=~~t;break;case"a":case"A":n._isPm=(t+"").toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":s[3]=~~t;break;case"m":case"mm":s[4]=~~t;break;case"s":case"ss":s[5]=~~t;break;case"S":case"SS":case"SSS":s[6]=~~(("0."+t)*1e3);break;case"X":n._d=new Date(parseFloat(t)*1e3);break;case"Z":case"ZZ":n._useUTC=!0,r=(t+"").match(x),r&&r[1]&&(n._tzh=~~r[1]),r&&r[2]&&(n._tzm=~~r[2]),r&&r[0]==="+"&&(n._tzh=-n._tzh,n._tzm=-n._tzm)}t==null&&(n._isValid=!1)}function J(e){var t,n,r=[];if(e._d)return;for(t=0;t<7;t++)e._a[t]=r[t]=e._a[t]==null?t===2?1:0:e._a[t];r[3]+=e._tzh||0,r[4]+=e._tzm||0,n=new Date(0),e._useUTC?(n.setUTCFullYear(r[0],r[1],r[2]),n.setUTCHours(r[3],r[4],r[5],r[6])):(n.setFullYear(r[0],r[1],r[2]),n.setHours(r[3],r[4],r[5],r[6])),e._d=n}function K(e){var t=e._f.match(a),n=e._i,r,i;e._a=[];for(r=0;r0,f[4]=n,Z.apply({},f)}function tt(e,n,r){var i=r-n,s=r-e.day();return s>i&&(s-=7),s11?n?"pm":"PM":n?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},calendar:function(e,t){var n=this._calendar[e];return typeof n=="function"?n.apply(t):n},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(e,t,n,r){var i=this._relativeTime[n];return typeof i=="function"?i(e,t,n,r):i.replace(/%d/i,e)},pastFuture:function(e,t){var n=this._relativeTime[e>0?"future":"past"];return typeof n=="function"?n(t):n.replace(/%s/i,t)},ordinal:function(e){return this._ordinal.replace("%d",e)},_ordinal:"%d",preparse:function(e){return e},postformat:function(e){return e},week:function(e){return tt(e,this._week.dow,this._week.doy)},_week:{dow:0,doy:6}},t=function(e,t,n){return nt({_i:e,_f:t,_l:n,_isUTC:!1})},t.utc=function(e,t,n){return nt({_useUTC:!0,_isUTC:!0,_l:n,_i:e,_f:t})},t.unix=function(e){return t(e*1e3)},t.duration=function(e,n){var r=t.isDuration(e),i=typeof e=="number",s=r?e._data:i?{}:e,o;return i&&(n?s[n]=e:s.milliseconds=e),o=new P(s),r&&e.hasOwnProperty("_lang")&&(o._lang=e._lang),o},t.version=n,t.defaultFormat=E,t.lang=function(e,n){var r;if(!e)return t.fn._lang._abbr;n?R(e,n):s[e]||U(e),t.duration.fn._lang=t.fn._lang=U(e)},t.langData=function(e){return e&&e._lang&&e._lang._abbr&&(e=e._lang._abbr),U(e)},t.isMoment=function(e){return e instanceof D},t.isDuration=function(e){return e instanceof P},t.fn=D.prototype={clone:function(){return t(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._d},toJSON:function(){return t.utc(this).format("YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var e=this;return[e.year(),e.month(),e.date(),e.hours(),e.minutes(),e.seconds(),e.milliseconds()]},isValid:function(){return this._isValid==null&&(this._a?this._isValid=!q(this._a,(this._isUTC?t.utc(this._a):t(this._a)).toArray()):this._isValid=!isNaN(this._d.getTime())),!!this._isValid},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(e){var n=X(this,e||t.defaultFormat);return this.lang().postformat(n)},add:function(e,n){var r;return typeof e=="string"?r=t.duration(+n,e):r=t.duration(e,n),F(this,r,1),this},subtract:function(e,n){var r;return typeof e=="string"?r=t.duration(+n,e):r=t.duration(e,n),F(this,r,-1),this},diff:function(e,n,r){var i=this._isUTC?t(e).utc():t(e).local(),s=(this.zone()-i.zone())*6e4,o,u;return n&&(n=n.replace(/s$/,"")),n==="year"||n==="month"?(o=(this.daysInMonth()+i.daysInMonth())*432e5,u=(this.year()-i.year())*12+(this.month()-i.month()),u+=(this-t(this).startOf("month")-(i-t(i).startOf("month")))/o,n==="year"&&(u/=12)):(o=this-i-s,u=n==="second"?o/1e3:n==="minute"?o/6e4:n==="hour"?o/36e5:n==="day"?o/864e5:n==="week"?o/6048e5:o),r?u:B(u)},from:function(e,n){return t.duration(this.diff(e)).lang(this.lang()._abbr).humanize(!n)},fromNow:function(e){return this.from(t(),e)},calendar:function(){var e=this.diff(t().startOf("day"),"days",!0),n=e<-6?"sameElse":e<-1?"lastWeek":e<0?"lastDay":e<1?"sameDay":e<2?"nextDay":e<7?"nextWeek":"sameElse";return this.format(this.lang().calendar(n,this))},isLeapYear:function(){var e=this.year();return e%4===0&&e%100!==0||e%400===0},isDST:function(){return this.zone()+t(e).startOf(n)},isBefore:function(e,n){return n=typeof n!="undefined"?n:"millisecond",+this.clone().startOf(n)<+t(e).startOf(n)},isSame:function(e,n){return n=typeof n!="undefined"?n:"millisecond",+this.clone().startOf(n)===+t(e).startOf(n)},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return t.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(e){var n=r((t(this).startOf("day")-t(this).startOf("year"))/864e5)+1;return e==null?n:this.add("d",e-n)},isoWeek:function(e){var t=tt(this,1,4);return e==null?t:this.add("d",(e-t)*7)},week:function(e){var t=this.lang().week(this);return e==null?t:this.add("d",(e-t)*7)},lang:function(t){return t===e?this._lang:(this._lang=U(t),this)}};for(i=0;i