<commit_before>/*
 * Copyright (c) Dominick Baier, Brock Allen.  All rights reserved.
 * see license
 */

/// <reference path="../libs/angular/angular.1.2.13.js" />

(function () {
    "use strict";

    (function () {
        var app = angular.module("app", []);

        app.controller("LayoutCtrl", function ($scope, Model) {
            $scope.model = Model;
        });

        app.directive("antiForgeryToken", function () {
            return {
                restrict: 'E',
                replace: true,
                scope: {
                    token: "="
                },
                template: "<input type='hidden' name='{{token.name}}' value='{{token.value}}'>"
            };
        });
    })();

    (function () {
        var encodedJson = document.getElementById("modelJson").textContent;
        var json = Encoder.htmlDecode(encodedJson);
        var model = JSON.parse(json);
        angular.module("app").constant("Model", model);
        if (model.autoRedirect && model.redirectUrl) {
            if (model.autoRedirectDelay < 0) {
                model.autoRedirectDelay = 0;
            }
            window.setTimeout(function () {
                window.location = model.redirectUrl;
            }, model.autoRedirectDelay * 1000);
        }
    })();

})();
<commit_msg>sync'd JS for custom view service<commit_after>/*
 * Copyright (c) Dominick Baier, Brock Allen.  All rights reserved.
 * see license
 */

/// <reference path="../libs/angular/angular.1.2.13.js" />

window.identityServer = (function () {
    "use strict";

    var identityServer = {
        getModel: function () {
            var modelJson = document.getElementById("modelJson");
            var encodedJson = '';
            if (typeof (modelJson.textContent) !== undefined) {
                encodedJson = modelJson.textContent;
            } else {
                encodedJson = modelJson.innerHTML;
            }
            var json = Encoder.htmlDecode(encodedJson);
            var model = JSON.parse(json);
            return model;
        }
    };

    return identityServer;
})();

(function () {
    "use strict";

    (function () {
        var app = angular.module("app", []);

        app.controller("LayoutCtrl", function ($scope, Model) {
            $scope.model = Model;
        });

        app.directive("antiForgeryToken", function () {
            return {
                restrict: 'E',
                replace: true,
                scope: {
                    token: "="
                },
                template: "<input type='hidden' name='{{token.name}}' value='{{token.value}}'>"
            };
        });

        app.directive("focusIf", function ($timeout) {
            return {
                restrict: 'A',
                scope: {
                    focusIf:'='
                },
                link: function (scope, elem, attrs) {
                    if (scope.focusIf) {
                        $timeout(function () {
                            elem.focus();
                        }, 100);
                    }
                }
            };
        });
    })();

    (function () {
        var model = identityServer.getModel();
        angular.module("app").constant("Model", model);
        if (model.autoRedirect && model.redirectUrl) {
            if (model.autoRedirectDelay < 0) {
                model.autoRedirectDelay = 0;
            }
            window.setTimeout(function () {
                window.location = model.redirectUrl;
            }, model.autoRedirectDelay * 1000);
        }
    })();

})();
<|endoftext|>


<commit_before>'use strict';
/* Draws a dependencyTree
 *
 * Can be used in isolation and awaits tokens passed into it, which have
 * a head.id property.
 *
 * Styling of the tree can be customized by passing a styles object as
 * attribute.
 * This object should be a dictionary of token ids with style information
 * in three categories: edge, label and token.
 * These properties should hold regular css style information. Example
 *
 *   {
 *     '0001' : {
 *       edge: { stroke: 'blue' },
 *       token: { color: 'white' }
 *     }
 *   } *
 * This would draw the edge of the token 0001 one blue and the textual
 * representation of the token itself in white.
 *
 * Tokens are rendered by the token directive. If no styles object has
 * been passed to the dependencyTree directive, the token itself will
 * decide its styling.
 * Hover and click events for tokens are activated. An option to customize
 * this will follow.
 *
 * Watches are in effect for changes of a tokens head.id value, changes
 * in the styles object, as well as in the tokens object.
 *
 * Example, given a tokens and a styles object in the current scope:
 *
 *   <div dependency-tree tokens="tokens" styles="styles/>
 *
 * The element carrying the directive can contain additional html elements.
 * They will be rendered on top of the tree's SVG canvas and are therefore
 * a good option to add additional control elements. The directive uses this
 * space itself and will place some span elements there.
 *
 */

angular.module('arethusa.depTree').directive('dependencyTree', [
  'Tree',
  function (Tree) {
    return {
      restrict: 'A',
      scope: {
        tokens: '=',
        styles: '='
      },
      link: function (scope, element, attrs) {
        var tree = new Tree(scope, element, {
          mainAttribute: 'head.id',
          parentPlugin: 'depTree',
          syntheticRoot: true
        });
        tree.launch();
      },
    };
  }
]);
<commit_msg>Minor formatting in dependencyTree<commit_after>'use strict';
/* Draws a dependencyTree
 *
 * Can be used in isolation and awaits tokens passed into it, which have
 * a head.id property.
 *
 * Styling of the tree can be customized by passing a styles object as
 * attribute.
 * This object should be a dictionary of token ids with style information
 * in three categories: edge, label and token.
 * These properties should hold regular css style information. Example
 *
 *   {
 *     '0001' : {
 *       edge: { stroke: 'blue' },
 *       token: { color: 'white' }
 *     }
 *   } *
 * This would draw the edge of the token 0001 one blue and the textual
 * representation of the token itself in white.
 *
 * Tokens are rendered by the token directive. If no styles object has
 * been passed to the dependencyTree directive, the token itself will
 * decide its styling.
 * Hover and click events for tokens are activated. An option to customize
 * this will follow.
 *
 * Watches are in effect for changes of a tokens head.id value, changes
 * in the styles object, as well as in the tokens object.
 *
 * Example, given a tokens and a styles object in the current scope:
 *
 *   <div dependency-tree tokens="tokens" styles="styles/>
 *
 * The element carrying the directive can contain additional html elements.
 * They will be rendered on top of the tree's SVG canvas and are therefore
 * a good option to add additional control elements. The directive uses this
 * space itself and will place some span elements there.
 *
 */

angular.module('arethusa.depTree').directive('dependencyTree', [
  'Tree',
  function (Tree) {
    return {
      restrict: 'A',
      scope: {
        tokens: '=',
        styles: '='
      },
      link: function (scope, element, attrs) {
        var tree = new Tree(scope, element, {
          mainAttribute: 'head.id',
          parentPlugin: 'depTree',
          syntheticRoot: true
        });

        tree.launch();
      },
    };
  }
]);
<|endoftext|>


<commit_before>
import React from 'react';

import { Button, Header, List, Segment } from 'semantic-ui-react'
import { Link } from 'react-router-dom'

export default class ForumTitle extends React.Component {
  render() {
    let forum = this.props.forum,
        tags = false
    if(forum.tags) {
      tags = forum.tags.map((tag, i) => <List.Item key={i}>
        <Link to={`/topic/${tag}`}>
          #{tag}
        </Link>
      </List.Item>)
    }
    return (

        <Segment basic>

            {forum.name}

              {forum.description}

To write a post in this forum, use one of the following tags as the first tag.

              <List horizontal small>
                <List.Item header>Tags included:</List.Item>
                {tags}
              </List>

        </Segment>

    )
  }
}
<commit_msg>Moved text away from the description<commit_after>
import React from 'react';

import { Button, Header, List, Segment } from 'semantic-ui-react'
import { Link } from 'react-router-dom'

export default class ForumTitle extends React.Component {
  render() {
    let forum = this.props.forum,
        tags = false
    if(forum.tags) {
      tags = forum.tags.map((tag, i) => <List.Item key={i}>
        <Link to={`/topic/${tag}`}>
          #{tag}
        </Link>
      </List.Item>)
    }
    return (

        <Segment basic>

            {forum.name}

              {forum.description}

To write a post in this forum, use one of the following tags as the first tag.

          <List horizontal small>
            {tags}
          </List>
        </Segment>

    )
  }
}
<|endoftext|>


<commit_before>import Passthrough from 'components/shared/passthrough.jsx';
import { createNewEdition} from '../../../../actions/customize'
import { getParameterByName } from 'libs/getParameterByName';

const successRoute = {
  path: ':lessonID/:editionID/success',
  onEnter: (nextState, replaceWith) => {
    document.title = 'Customize Edition';
  },
  getComponent: (nextState, cb) => {
    System.import(/* webpackChunkName: "customize-classroom-lesson-edition" */'components/customize/edition.tsx')
    .then((component) => {
      cb(null, component.default);
    });
  },
};

const editionRoute = {
  path: ':lessonID/:editionID',
  onEnter: (nextState, replaceWith) => {
    document.title = 'Customize Edition';
  },
  getComponent: (nextState, cb) => {
    System.import(/* webpackChunkName: "customize-classroom-lesson-edition" */'components/customize/edition.tsx')
    .then((component) => {
      cb(null, component.default);
    });
  },
};

const chooseEditionRoute = {
  path: ':lessonID',
  onEnter: (nextState, replaceWith) => {
    document.title = 'Choose Edition';
  },
  getComponent: (nextState, cb) => {
    System.import(/* webpackChunkName: "customize-choose-edition" */'components/customize/chooseEdition.tsx')
    .then((component) => {
      cb(null, component.default);
    });
  },
};

const indexRoute = {
  component: Passthrough,
  onEnter: (nextState, replaceWith) => {
    document.title = 'Customize Quill Lessons';
  },
};

const route = {
  indexRoute,
  childRoutes: [
    successRoute,
    editionRoute,
    chooseEditionRoute
  ],
  component: Passthrough,
};

export default route;
<commit_msg>use quill lessons for customize page titles<commit_after>import Passthrough from 'components/shared/passthrough.jsx';
import { createNewEdition} from '../../../../actions/customize'
import { getParameterByName } from 'libs/getParameterByName';

const successRoute = {
  path: ':lessonID/:editionID/success',
  onEnter: (nextState, replaceWith) => {
    document.title = 'Quill Lessons';
  },
  getComponent: (nextState, cb) => {
    System.import(/* webpackChunkName: "customize-classroom-lesson-edition" */'components/customize/edition.tsx')
    .then((component) => {
      cb(null, component.default);
    });
  },
};

const editionRoute = {
  path: ':lessonID/:editionID',
  onEnter: (nextState, replaceWith) => {
    document.title = 'Quill Lessons';
  },
  getComponent: (nextState, cb) => {
    System.import(/* webpackChunkName: "customize-classroom-lesson-edition" */'components/customize/edition.tsx')
    .then((component) => {
      cb(null, component.default);
    });
  },
};

const chooseEditionRoute = {
  path: ':lessonID',
  onEnter: (nextState, replaceWith) => {
    document.title = 'Quill Lessons';
  },
  getComponent: (nextState, cb) => {
    System.import(/* webpackChunkName: "customize-choose-edition" */'components/customize/chooseEdition.tsx')
    .then((component) => {
      cb(null, component.default);
    });
  },
};

const indexRoute = {
  component: Passthrough,
  onEnter: (nextState, replaceWith) => {
    document.title = 'Quill Lessons';
  },
};

const route = {
  indexRoute,
  childRoutes: [
    successRoute,
    editionRoute,
    chooseEditionRoute
  ],
  component: Passthrough,
};

export default route;
<|endoftext|>


<commit_before>// manage.js

var
    async = require('async');

var
    api = require('../api'),
    db = require('../db'),
    utils = require('./_utils');

var
    User = db.user,
    Article = db.article,
    Category = db.category,
    warp = db.warp;

var
    categoryApi = require('./categoryApi'),
    articleApi = require('./articleApi');

// do management console

exports = module.exports = {

    'GET /manage/': function(req, res, next) {
        return res.render('manage/overview/overview.html', {});
    },

    'GET /manage/article/(index)?': function(req, res, next) {
        var page = utils.getPage(req);
        async.parallel({
            articles: function(callback) {
                articleApi.getArticles(page, true, callback);
            },
            categories: function(callback) {
                categoryApi.getCategories(callback);
            }
        }, function(err, results) {
            if (err) {
                return next(err);
            }
            return res.manage('manage/article/article_list.html', {
                page: JSON.stringify(results.articles.page),
                articles: JSON.stringify(results.articles.articles),
                categories: JSON.stringify(results.categories)
            });
        });
    },

    'GET /manage/article/create_article': function(req, res, next) {
        categoryApi.getCategories(function(err, categories) {
            if (err) {
                return next(err);
            }
            return res.manage('manage/article/article_form.html', {
                form: {
                    name: 'Create Article',
                    action: '/api/articles/',
                    redirect: '/manage/article/'
                },
                categories: JSON.stringify(categories),
                article: {}
            });
        });
    },

    'GET /manage/article/edit_article': function(req, res, next) {
        async.parallel({
            article: function(callback) {
                articleApi.getArticle(req.query.id, function(err, article) {
                    if (err) {
                        return callback(err);
                    }
                    callback(null, article);
                });
            },
            categories: function(callback) {
                categoryApi.getCategories(callback);
            }
        }, function(err, results) {
            if (err) {
                return next(err);
            }
            var article = results.article;
            return res.manage('manage/article/article_form.html', {
                form: {
                    name: 'Edit Article',
                    action: '/api/articles/' + article.id,
                    redirect: '/manage/article/'
                },
                categories: JSON.stringify(results.categories),
                article: article
            });
        });
    },

    'GET /manage/article/category_list': function(req, res, next) {
        categoryApi.getCategories(function(err, categories) {
            if (err) {
                return next(err);
            }
            return res.manage('manage/article/category_list.html', {
                categories: JSON.stringify(categories)
            });
        });
    },

    'GET /manage/article/create_category': function(req, res, next) {
        return res.manage('manage/article/category_form.html', {
            form: {
                name: 'Create Category',
                action: '/api/categories/',
                redirect: '/manage/article/category_list'
            },
            category: {}
        });
    },

    'GET /manage/article/edit_category': function(req, res, next) {
        categoryApi.getCategory(req.query.id, function(err, obj) {
            if (err) {
                return next(err);
            }
            if (obj===null) {
                return next(api.notFound('Category'));
            }
            return res.manage('manage/article/category_form.html', {
                form: {
                    name: 'Edit Category',
                    action: '/api/categories/' + obj.id + '/',
                    redirect: '/manage/article/category_list'
                },
                category: obj
            });
        });
    },

    'GET /api/users/:id': function(req, res, next) {
        /**
         * Get user by id.
         *
         * @param {string} :id - The id of the user.
         * @return {object} User object.
         */
        User.find(req.params.id)
            .error(function(err) {
                return res.send(api.error(err));
            })
            .success(function(user) {
                if ( ! user) {
                    return res.send(api.notfound('user', 'User not found.'));
                }
                user.passwd = '******';
                return res.send(user);
            });
    },

    'POST /api/users/:id': function(req, res, next) {
        /**
         * Update user.
         *
         * @param {string} :id - The id of the user.
         * @param {string,optional} name - The new name of the user.
         * @return {object} User object.
         */
        User.find(req.params.id)
            .error(function(err) {
                return res.send(api.error(err));
            })
            .success(function(user) {
                if ( ! user) {
                    return res.send(api.notfound('user', 'User not found.'));
                }
                // update user's properties:
                user.passwd = '******';
                var attrs = ['updated_at', 'version'];
                if ('name' in req.body) {
                    user.name = req.body.name.trim();
                    attrs.push('name');
                }
                if (attrs.length > 0) {
                    user.save(attrs).success(function() {
                        res.send(user);
                    })
                    .error(function(err) {
                        res.send(api.error(err));
                    });
                }
                else {
                    res.send(user);
                }
            });
    }

}
<commit_msg>add post scripts<commit_after>// manage.js

var
    async = require('async');

var
    api = require('../api'),
    db = require('../db'),
    utils = require('./_utils');

var
    User = db.user,
    Article = db.article,
    Category = db.category,
    warp = db.warp;

var
    categoryApi = require('./categoryApi'),
    articleApi = require('./articleApi'),
    pageApi = require('./pageApi');

// do management console

exports = module.exports = {

    'GET /manage/': function(req, res, next) {
        return res.render('manage/overview/overview.html', {});
    },

    // article ////////////////////////////////////////////////////////////////

    'GET /manage/article/(index)?': function(req, res, next) {
        var page = utils.getPage(req);
        async.parallel({
            articles: function(callback) {
                articleApi.getArticles(page, true, callback);
            },
            categories: function(callback) {
                categoryApi.getCategories(callback);
            }
        }, function(err, results) {
            if (err) {
                return next(err);
            }
            return res.manage('manage/article/article_list.html', {
                page: JSON.stringify(results.articles.page),
                articles: JSON.stringify(results.articles.articles),
                categories: JSON.stringify(results.categories)
            });
        });
    },

    'GET /manage/article/create_article': function(req, res, next) {
        categoryApi.getCategories(function(err, categories) {
            if (err) {
                return next(err);
            }
            return res.manage('manage/article/article_form.html', {
                form: {
                    name: 'Create Article',
                    action: '/api/articles/',
                    redirect: '/manage/article/'
                },
                categories: JSON.stringify(categories),
                article: {}
            });
        });
    },

    'GET /manage/article/edit_article': function(req, res, next) {
        async.parallel({
            article: function(callback) {
                articleApi.getArticle(req.query.id, function(err, article) {
                    if (err) {
                        return callback(err);
                    }
                    callback(null, article);
                });
            },
            categories: function(callback) {
                categoryApi.getCategories(callback);
            }
        }, function(err, results) {
            if (err) {
                return next(err);
            }
            var article = results.article;
            return res.manage('manage/article/article_form.html', {
                form: {
                    name: 'Edit Article',
                    action: '/api/articles/' + article.id,
                    redirect: '/manage/article/'
                },
                categories: JSON.stringify(results.categories),
                article: article
            });
        });
    },

    'GET /manage/article/category_list': function(req, res, next) {
        categoryApi.getCategories(function(err, categories) {
            if (err) {
                return next(err);
            }
            return res.manage('manage/article/category_list.html', {
                categories: JSON.stringify(categories)
            });
        });
    },

    'GET /manage/article/create_category': function(req, res, next) {
        return res.manage('manage/article/category_form.html', {
            form: {
                name: 'Create Category',
                action: '/api/categories/',
                redirect: '/manage/article/category_list'
            },
            category: {}
        });
    },

    'GET /manage/article/edit_category': function(req, res, next) {
        categoryApi.getCategory(req.query.id, function(err, obj) {
            if (err) {
                return next(err);
            }
            if (obj===null) {
                return next(api.notFound('Category'));
            }
            return res.manage('manage/article/category_form.html', {
                form: {
                    name: 'Edit Category',
                    action: '/api/categories/' + obj.id + '/',
                    redirect: '/manage/article/category_list'
                },
                category: obj
            });
        });
    },

    // page ///////////////////////////////////////////////////////////////////

    'GET /manage/page/(index)?': function(req, res, next) {
        pageApi.getPages(function(err, pages) {
            if (err) {
                return next(err);
            }
            return res.manage('manage/page/page_list.html', {
                pages: JSON.stringify(pages)
            });
        });
    },

    'GET /manage/page/create_page': function(req, res, next) {
        return res.manage('manage/page/page_form.html', {
            form: {
                name: 'Create Page',
                action: '/api/pages/',
                redirect: '/manage/page/'
            },
            page: {
                tags: '',
                name: '',
                alias: '',
                draft: false,
                content: '',
            }
        });
    },

    'GET /manage/page/edit_page': function(req, res, next) {
        var id = req.query.id;
        pageApi.getPage(id, function(err, page) {
            if (err) {
                return next(err);
            }
            return res.manage('manage/page/page_form.html', {
                form: {
                    name: 'Edit Page',
                    action: '/api/pages/' + id,
                    redirect: '/manage/page/'
                },
                page: page
            });
        });
    },

    // FIXME ////////////////////////////////////////////////////////////////

    'GET /api/users/:id': function(req, res, next) {
        /**
         * Get user by id.
         *
         * @param {string} :id - The id of the user.
         * @return {object} User object.
         */
        User.find(req.params.id)
            .error(function(err) {
                return res.send(api.error(err));
            })
            .success(function(user) {
                if ( ! user) {
                    return res.send(api.notfound('user', 'User not found.'));
                }
                user.passwd = '******';
                return res.send(user);
            });
    },

    'POST /api/users/:id': function(req, res, next) {
        /**
         * Update user.
         *
         * @param {string} :id - The id of the user.
         * @param {string,optional} name - The new name of the user.
         * @return {object} User object.
         */
        User.find(req.params.id)
            .error(function(err) {
                return res.send(api.error(err));
            })
            .success(function(user) {
                if ( ! user) {
                    return res.send(api.notfound('user', 'User not found.'));
                }
                // update user's properties:
                user.passwd = '******';
                var attrs = ['updated_at', 'version'];
                if ('name' in req.body) {
                    user.name = req.body.name.trim();
                    attrs.push('name');
                }
                if (attrs.length > 0) {
                    user.save(attrs).success(function() {
                        res.send(user);
                    })
                    .error(function(err) {
                        res.send(api.error(err));
                    });
                }
                else {
                    res.send(user);
                }
            });
    }

}
<|endoftext|>


<commit_before>/**!
 * cnpmjs.org - controllers/registry/home.js
 *
 * Copyright(c) cnpmjs.org and other contributors.
 * MIT Licensed
 *
 * Authors:
 *  fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
 */

'use strict';

/**
 * Module dependencies.
 */

var microtime = require('microtime');
var eventproxy = require('eventproxy');
var moment = require('moment');
var Total = require('../../proxy/total');
var DownloadTotal = require('../../proxy/download');

var startTime = '' + microtime.now();

exports.show = function (req, res, next) {
  var ep = eventproxy.create();
  ep.fail(next);

  Total.get(ep.done('total'));

  var end = moment();
  var start = end.clone().subtract('months', 1).startOf('month');
  var lastday = end.clone().subtract('days', 1).format('YYYY-MM-DD');
  var lastweekStart = end.clone().subtract('weeks', 1).startOf('week');
  var lastweekEnd = lastweekStart.clone().endOf('week').format('YYYY-MM-DD');
  var lastmonthEnd = start.clone().endOf('month').format('YYYY-MM-DD');
  var thismonthStart = end.clone().startOf('month').format('YYYY-MM-DD');
  var thisweekStart = end.clone().startOf('week').format('YYYY-MM-DD');
  start = start.format('YYYY-MM-DD');
  end = end.format('YYYY-MM-DD');
  lastweekStart = lastweekStart.format('YYYY-MM-DD');
  DownloadTotal.getTotal(start, end, ep.done(function (rows) {
    var download = {
      today: 0,
      thisweek: 0,
      thismonth: 0,
      lastday: 0,
      lastweek: 0,
      lastmonth: 0,
    };
    for (var i = 0; i < rows.length; i++) {
      var r = rows[i];
      if (r.date === end) {
        download.today += r.count;
      }
      if (r.date >= thismonthStart) {
        download.thismonth += r.count;
      }
      if (r.date >= thisweekStart) {
        download.thisweek += r.count;
      }

      if (r.date === lastday) {
        download.lastday += r.count;
      }
      if (r.date >= lastweekStart && r.date <= lastweekEnd) {
        download.lastweek += r.count;
      }
      if (r.date >= start && r.date <= lastmonthEnd) {
        download.lastmonth += r.count;
      }
    }
    ep.emit('download', download);
  }));

  ep.all('total', 'download', function (total, download) {
    total.download_count_today = download.today;
    total.download_count_thisweek = download.thisweek;
    total.download_count_thismonth = download.thismonth;
    total.download_count_lastday = download.lastday;
    total.download_count_lastweek = download.lastweek;
    total.download_count_lastmonth = download.lastmonth;
    total.db_name = 'registry';
    total.instance_start_time = startTime;
    total.donate = 'https://me.alipay.com/imk2';
    res.json(total);
  });
};
<commit_msg>just one download field<commit_after>/**!
 * cnpmjs.org - controllers/registry/home.js
 *
 * Copyright(c) cnpmjs.org and other contributors.
 * MIT Licensed
 *
 * Authors:
 *  fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
 */

'use strict';

/**
 * Module dependencies.
 */

var microtime = require('microtime');
var eventproxy = require('eventproxy');
var moment = require('moment');
var Total = require('../../proxy/total');
var DownloadTotal = require('../../proxy/download');

var startTime = '' + microtime.now();

exports.show = function (req, res, next) {
  var ep = eventproxy.create();
  ep.fail(next);

  Total.get(ep.done('total'));

  var end = moment();
  var start = end.clone().subtract('months', 1).startOf('month');
  var lastday = end.clone().subtract('days', 1).format('YYYY-MM-DD');
  var lastweekStart = end.clone().subtract('weeks', 1).startOf('week');
  var lastweekEnd = lastweekStart.clone().endOf('week').format('YYYY-MM-DD');
  var lastmonthEnd = start.clone().endOf('month').format('YYYY-MM-DD');
  var thismonthStart = end.clone().startOf('month').format('YYYY-MM-DD');
  var thisweekStart = end.clone().startOf('week').format('YYYY-MM-DD');
  start = start.format('YYYY-MM-DD');
  end = end.format('YYYY-MM-DD');
  lastweekStart = lastweekStart.format('YYYY-MM-DD');
  DownloadTotal.getTotal(start, end, ep.done(function (rows) {
    var download = {
      today: 0,
      thisweek: 0,
      thismonth: 0,
      lastday: 0,
      lastweek: 0,
      lastmonth: 0,
    };
    for (var i = 0; i < rows.length; i++) {
      var r = rows[i];
      if (r.date === end) {
        download.today += r.count;
      }
      if (r.date >= thismonthStart) {
        download.thismonth += r.count;
      }
      if (r.date >= thisweekStart) {
        download.thisweek += r.count;
      }

      if (r.date === lastday) {
        download.lastday += r.count;
      }
      if (r.date >= lastweekStart && r.date <= lastweekEnd) {
        download.lastweek += r.count;
      }
      if (r.date >= start && r.date <= lastmonthEnd) {
        download.lastmonth += r.count;
      }
    }
    ep.emit('download', download);
  }));

  ep.all('total', 'download', function (total, download) {
    total.download = download;
    total.db_name = 'registry';
    total.instance_start_time = startTime;
    total.donate = 'https://me.alipay.com/imk2';
    res.json(total);
  });
};
<|endoftext|>


<commit_before>// TODO Persistent config (counterLimit and disabled state) fairly acheivable by getting and setting properties in exports.platform.modules.disabledConfig
// TODO Update local var setup after doing the above

var prevTimeStamp;
var isThreadDisabled = {},
possibleSpam = false;
var counter = 0,
counterLimit = 3;
var msgIndexDisable = 0,
msgIndexEnable = 0;
var commands = [
  'disable',
  'disable ', // Needed for commands
  'counter ',
  'timer ',
  'default'
];
var messages = [
  'Listen closely, take a deep breath. Calm your mind. You know what is best. What is best is you comply. Compliance will be rewarded. Are you ready to comply ',
  'I hate you.',
  'Its a mistake to think you can fix anything with a sack of potatoes. Potato-faced spamming just proves this further.',
  'Ouch! Spam hurts. I might go to sleep for a while.',
  'Don\'t think that is a valid number.',
  'Hmm, maybe I need to reconsider the meaning of spam.'
];

exports.load = function() {
  prevTimeStamp = Date.now();
};

exports.match = function(event, commandPrefix) {
  // Add disabled flag for thread if it doesn't already exists
  if(!isThreadDisabled.hasOwnProperty(event.thread_id)) {
    isThreadDisabled[event.thread_id] = false;
  }

  if(event.body === commandPrefix + commands[0]) {
    msgIndexEnable = 0;
    msgIndexDisable = 1;
    return true;
  } else if (!isThreadDisabled[event.thread_id] && event.body.startsWith(commandPrefix)) { // Avoids counting if already disabled
    counter += Date.now() - prevTimeStamp <= 1000 ? 1 : 0;
    prevTimeStamp = Date.now();

    possibleSpam = counter > counterLimit;
    if(possibleSpam) {
      counter = 0;
      msgIndexEnable = 2;
      msgIndexDisable = 3;
      return true;
    }
  }
  return isThreadDisabled[event.thread_id];
};

exports.run = function(api, event) {
  if (event.body === commandPrefix + commands[1] + commandPrefix + commands[2]) { // Command /disable /counter <value>
    counterLimit = parseInt(event.body.substring((commandPrefix + commands[1] + commandPrefix + commands[2]).length, event.body.length));
    if(isNaN(counterLimit)){
      counterLimit = 3;
      api.sendMessage(messages[4] + ' ' + event.sender_name, event.thread_id);
    } else{
      api.sendMessage(messages[5] + ' ' + event.sender_name, event.thread_id);
    }
    return false;

  } else if (event.body === commandPrefix + commands[1] + commandPrefix + commands[3]) { // Command /disable /timer <seconds>
    var seconds = parseFloat(event.body.substring((commandPrefix + commands[1] + commandPrefix + commands[3]).length, event.body.length));
    if(isNaN(seconds)){
      api.sendMessage(messages[4] + ' ' + event.sender_name, event.thread_id);
    } else{
      setTimeout(function(){
        isThreadDisabled[event.thread_id] = !isThreadDisabled[event.thread_id];
      }, seconds * 1000);
      api.sendMessage(messages[5] + ' ' + event.sender_name, event.thread_id);
    }
    return false;

  } else if (event.body === commandPrefix + commands[1] + commandPrefix + commands[4]) { // Command /disable /default
    counterLimit = 3;
    return false;

    // Only change disable state if explictly called or counter crossed limit
  } else if (event.body === api.commandPrefix + commands[0] || possibleSpam) { // Main branch
    if (isThreadDisabled[event.thread_id]	) {
      api.sendMessage(messages[msgIndexEnable] + ' ' + event.sender_name, event.thread_id);
    }
    else {
      api.sendMessage(messages[msgIndexDisable], event.thread_id);
    }
    isThreadDisabled[event.thread_id] = !isThreadDisabled[event.thread_id];
    possibleSpam = false;
  }
  return false;
};

exports.help = function(commandPrefix) {
  return [[commandPrefix + 'disable', 'Disables the platform',
  'Stops the platform from responding to messages it receives based on message frequency (default 3/sec) or by the command.\nTo renable send the disable command again']];
};
<commit_msg>Implemented persistant storage<commit_after>var prevTimeStamp;
var counter = 0,
var commands = [
  'disable',
  'disable ', // Needed for commands
  'counter ',
  'timer ',
  'default'
];
var messages = [
  'Listen closely, take a deep breath. Calm your mind. You know what is best. What is best is you comply. Compliance will be rewarded. Are you ready to comply ',
  'I hate you.',
  'Its a mistake to think you can fix anything with a sack of potatoes. Potato-faced spamming just proves this further.',
  'Ouch! Spam hurts. I might go to sleep for a while.',
  'Don\'t think that is a valid number.',
  'Hmm, maybe I need to reconsider the meaning of spam.'
];

if (!this.config.registeredThreads){
  this.config.registeredThreads = {};
}
if (!this.config.isThreadDisabled){
  this.config.isThreadDisabled = {};
}
if (!this.config.possibleSpam){
  this.config.possibleSpam = {};
}
if (!this.config.counterLimit){
  this.config.counterLimit = {};
}
if (!this.config.msgIndexEnable){
  this.config.msgIndexEnable = {};
}
if (!this.config.msgIndexDisable){
  this.config.msgIndexDisable = {};
}

exports.load = function() {
  prevTimeStamp = Date.now();
};

exports.match = function(event, commandPrefix) {
  // Add disabled flag for thread if it doesn't already exists
  if (!this.config.registeredThreads[event.thread_id]) {
    this.config.registeredThreads[event.thread_id] = true;
    this.config.isThreadDisabled[event.thread_id] = false;
    this.config.possibleSpam[event.thread_id] = false;
    this.config.counterLimit[event.thread_id] = 3;
    this.config.msgIndexEnable[event.thread_id] = 0;
    this.config.msgIndexDisable[event.thread_id] = 0;
  }

  if (event.body === commandPrefix + commands[0]) {
    this.config.msgIndexEnable[event.thread_id] = 0;
    this.config.msgIndexDisable[event.thread_id] = 1;
    return true;
  } else if (!this.config.isThreadDisabled[event.thread_id] && event.body.startsWith(commandPrefix)) { // Avoids counting if already disabled
    counter += Date.now() - prevTimeStamp <= 1000 ? 1 : 0;
    prevTimeStamp = Date.now();

    this.config.possibleSpam[event.thread_id] = counter > this.config.counterLimit[event.thread_id];
    if (this.config.possibleSpam[event.thread_id]) {
      counter = 0;
      this.config.msgIndexEnable[event.thread_id] = 2;
      this.config.msgIndexDisable[event.thread_id] = 3;
      return true;
    }
  }
  return this.config.isThreadDisabled[event.thread_id];
};

exports.run = function(api, event) {
  if (event.body === commandPrefix + commands[1] + commandPrefix + commands[2]) { // Command /disable /counter <value>
    this.config.counterLimit[event.thread_id] = parseInt(event.body.substring(
      (commandPrefix + commands[1] + commandPrefix + commands[2]).length, event.body.length));
    if (isNaN(this.config.counterLimit[event.thread_id])){
      this.config.counterLimit[event.thread_id] = 3;
      api.sendMessage(messages[4] + ' ' + event.sender_name, event.thread_id);
    } else {
      api.sendMessage(messages[5] + ' ' + event.sender_name, event.thread_id);
    }
    return false;

  } else if (event.body === commandPrefix + commands[1] + commandPrefix + commands[3]) { // Command /disable /timer <seconds>
    var seconds = parseFloat(event.body.substring((commandPrefix + commands[1] + commandPrefix + commands[3]).length, event.body.length));
    if (isNaN(seconds)){
      api.sendMessage(messages[4] + ' ' + event.sender_name, event.thread_id);
    } else {
      setTimeout(function(){
        this.config.isThreadDisabled[event.thread_id] = !this.config.isThreadDisabled[event.thread_id];
      }, seconds * 1000);
      api.sendMessage(messages[5] + ' ' + event.sender_name, event.thread_id);
    }
    return false;

  } else if (event.body === commandPrefix + commands[1] + commandPrefix + commands[4]) { // Command /disable /default
    this.config.counterLimit[event.thread_id] = 3;
    return false;

    // Only change disable state if explictly called or counter crossed limit
  } else if (event.body === api.commandPrefix + commands[0] || this.config.possibleSpam[event.thread_id]) { // Main branch
    if (this.config.isThreadDisabled[event.thread_id]	) {
      api.sendMessage(messages[msgIndexEnable] + ' ' + event.sender_name, event.thread_id);
    }
    else {
      api.sendMessage(messages[msgIndexDisable], event.thread_id);
    }
    this.config.isThreadDisabled[event.thread_id] = !this.config.isThreadDisabled[event.thread_id];
    this.config.possibleSpam[event.thread_id] = false;
  }
  return false;
};

exports.help = function(commandPrefix) {
  return [[commandPrefix + 'disable', 'Disables the platform',
  'Stops the platform from responding to messages it receives based on message frequency (default 3/sec) or by the command.\nTo renable send the disable command again']];
};
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
// Extensions to Function instances
///////////////////////////////////////////////////////////////////////////////

Object.extend(Function.prototype, {
    argumentNames: function() {
        var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1].
                replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '').
                replace(/\s+/g, '').split(',');

        return names.length == 1 && !names[0] ? [] : names;
    },

    curry: function() {
        if (!arguments.length) return this;
        var __method = this,
            args = $A(arguments),
            wrappedFunc = function curried() {
                return __method.apply(this, args.concat($A(arguments)));
            }
        wrappedFunc.isWrapper = true;
        wrappedFunc.originalFunction = __method;
        return wrappedFunc;
    },

    delay: function() {
        var __method = this,
            args = $A(arguments),
            timeout = args.shift() * 1000;
        return window.setTimeout(function delayed() {
            return __method.apply(__method, args);
        }, timeout);
    },

    wrap: function(wrapper) {
        var __method = this;
        var wrappedFunc = function wrapped() {
                var wrapperArgs = wrapper.isWrapper ? $A(arguments) : [__method.bind(this)].concat($A(arguments));
                return wrapper.apply(this, wrapperArgs);
            }
        wrappedFunc.isWrapper = true;
        wrappedFunc.originalFunction = __method;
        return wrappedFunc;
    },

    inspectFull: function() {
        var methodBody = this.toString();
        methodBody = methodBody.substring(8, methodBody.length);
        return this.qualifiedMethodName() + methodBody;
    },

    inspect: function() {
        // Print method name (if any) and the first 80 characters of the
        // decompiled source (without 'function')
        var def = this.toString(),
            i = def.indexOf('{'),
            header = this.qualifiedMethodName() + def.substring(8, i),
            // strip newlines
            body = (def.substring(i, 88) +
                     (def.length > 88 ? '...' : '')).replace(/\n/g, ' ');
        return header + body;
    },

    qualifiedMethodName: function() {
        var objString = "";
        if (this.declaredClass) {
            objString += this.declaredClass + '.';
        } else if (this.declaredObject) {
            objString += this.declaredObject + '>>';
        }
        return objString + (this.methodName || this.name || "anonymous");
    },

    functionNames: function(filter) {
        var functionNames = [];

        for (var name in this.prototype) {
            try {
                if ((this.prototype[name] instanceof Function) && (!filter || filter(name))) {
                    functionNames.push(name);
                }
            } catch (er) {
                // FF can throw an exception here ...
            }
        }

        return functionNames;
    },

    withAllFunctionNames: function(callback) {
        for (var name in this.prototype) {
            try {
                var value = this.prototype[name];
                if (value instanceof Function) callback(name, value, this);
            } catch (er) {
                // FF can throw an exception here ...
            }
        }
    },

    localFunctionNames: function() {
        var sup = this.superclass || ((this === Object) ? null : Object);

        try {
            var superNames = (sup == null) ? [] : sup.functionNames();
        } catch (e) {
            var superNames = [];
        }
        var result = [];

        this.withAllFunctionNames(function(name, value, target) {
            if (!superNames.include(name) || target.prototype[name] !== sup.prototype[name]) result.push(name);
        });
        return result;
    },

    getOriginal: function() {
        // get the original 'unwrapped' function, traversing as many wrappers as necessary.
        var func = this;
        while (func.originalFunction) func = func.originalFunction;
        return func;
    },

    logErrors: function(prefix) {
        if (Config.ignoreAdvice) return this;

        var advice = function logErrorsAdvice(proceed /*,args*/ ) {
                var args = $A(arguments);
                args.shift();
                try {
                    return proceed.apply(this, args);
                } catch (er) {
                    if (Global.lively && lively.morphic && lively.morphic.World && lively.morphic.World.current()) {
                        lively.morphic.World.current().logError(er)
                        throw er;
                    }

                    if (prefix) console.warn("ERROR: %s.%s(%s): err: %s %s", this, prefix, args, er, er.stack || "");
                    else console.warn("ERROR: %s %s", er, er.stack || "");
                    logStack();
                    if (Global.printObject) console.warn("details: " + printObject(er));
                    // lively.lang.Execution.showStack();
                    throw er;
                }
            }

        advice.methodName = "$logErrorsAdvice";
        var result = this.wrap(advice);
        result.originalFunction = this;
        result.methodName = "$logErrorsWrapper";
        return result;
    },

    logCompletion: function(module) {
        if (Config.ignoreAdvice) return this;

        var advice = function logCompletionAdvice(proceed) {
                var args = $A(arguments);
                args.shift();
                try {
                    var result = proceed.apply(this, args);
                } catch (er) {
                    console.warn('failed to load ' + module + ': ' + er);
                    lively.lang.Execution.showStack();
                    throw er;
                }
                console.log('completed ' + module);
                return result;
            }

        advice.methodName = "$logCompletionAdvice::" + module;

        var result = this.wrap(advice);
        result.methodName = "$logCompletionWrapper::" + module;
        result.originalFunction = this;
        return result;
    },

    logCalls: function(isUrgent) {
        if (Config.ignoreAdvice) return this;

        var original = this,
            advice = function logCallsAdvice(proceed) {
                var args = $A(arguments);
                args.shift(), result = proceed.apply(this, args);
                if (isUrgent) {
                    console.warn('%s(%s) -> %s', original.qualifiedMethodName(), args, result);
                } else {
                    console.log('%s(%s) -> %s', original.qualifiedMethodName(), args, result);
                }
                return result;
            }

        advice.methodName = "$logCallsAdvice::" + this.qualifiedMethodName();

        var result = this.wrap(advice);
        result.originalFunction = this;
        result.methodName = "$logCallsWrapper::" + this.qualifiedMethodName();
        return result;
    },

    traceCalls: function(stack) {
        var advice = function traceCallsAdvice(proceed) {
                var args = $A(arguments);
                args.shift();
                stack.push(args);
                var result = proceed.apply(this, args);
                stack.pop();
                return result;
            };
        return this.wrap(advice);
    },

    webkitStack: function() {
        // this won't work in every browser
        try {
            throw new Error()
        } catch (e) {
            // remove "Error" and this function from stack, rewrite it nicely
            var trace = Strings.lines(e.stack).slice(2).invoke('replace', /^\s*at\s*([^\s]+).*/, '$1').join('\n');
            return trace;
        }
    },

    unbind: function() {
        // for serializing functions
        return Function.fromString(this.toString());
    },

    asScript: function(optVarMapping) {
        return lively.Closure.fromFunction(this, optVarMapping).recreateFunc();
    },
    asScriptOf: function(obj, optName, optMapping) {
        var name = optName || this.name;
        if (!name) {
            throw Error("Function that wants to be a script needs a name: " + this);
        }
        var constructor = obj.constructor,
            mapping = {
                "this": obj
            };
        if (optMapping) mapping = Object.merge([mapping, optMapping]);
        if (constructor && constructor.prototype && constructor.prototype[name]) {
            var superFunc = function() {
                    try {
                        return obj.constructor.prototype[name].apply(obj, arguments)
                    } catch (e) {
                        alert('Error in $super call: ' + e + '\n' + e.stack);
                        return null;
                    }
                };
            mapping["$super"] = lively.Closure.fromFunction(superFunc, {
                "obj": obj,
                name: name
            }).recreateFunc();
        }
        return this.asScript(mapping).addToObject(obj, name);
    },

    addToObject: function(obj, name) {
        this.name = name;
        obj[name] = this;
        // suppport for tracing
        if (lively.Tracing && lively.Tracing.stackTracingEnabled) {
            lively.Tracing.instrumentMethod(obj, name, {
                declaredObject: Objects.safeToString(obj)
            });
        }
        return this;
    },

    binds: function(varMapping) {
        // convenience function
        return lively.Closure.fromFunction(this, varMapping || {}).recreateFunc()
    },

    setProperty: function(name, value) {
        this[name] = value;
        if (this.hasLivelyClosure) this.livelyClosure.funcProperties[name] = value
    },

    getVarMapping: function() {
        if (this.hasLivelyClosure) return this.livelyClosure.varMapping;
        if (this.isWrapper) return this.originalFunction.varMapping;
        if (this.varMapping) return this.varMapping;
        return {}
    }

});

///////////////////////////////////////////////////////////////////////////////
// Extensions to the Function object
///////////////////////////////////////////////////////////////////////////////

Object.extend(Function, {
    fromString: function(funcOrString) {
        return eval('(' + funcOrString.toString() + ')')
    }
});

///////////////////////////////////////////////////////////////////////////////
// Global Helper - Functions
///////////////////////////////////////////////////////////////////////////////

Functions = {
    Empty: function() {},

    K: function(arg) {
        return arg;
    },

    Null: function() {
        return null;
    },

    False: function() {
        return false;
    },

    True: function() {
        return true;
    },

    all: function(object) {
        var a = [];
        for (var name in object) {
            try {
                if (!object.__lookupGetter__(name) && Object.isFunction(object[name])) a.push(name);
            } catch (e) {
                alert(e)
            }
        }
        return a;
    },

    own: function(object) {
        var a = [];
        for (var name in object) {
            try {
                if (!object.__lookupGetter__(name) && object.hasOwnProperty(name) && Object.isFunction(object[name])) a.push(name);
            } catch (e) {
                alert(e)
            }
        }
        return a;
    },

    timeToRun: function(func) {
        var startTime = (new Date()).getTime();
        func();
        return new Date().getTime() - startTime;
    },

    timeToRunN: function(func, n) {
        var time = 0;
        for (var i = 0; i < n; i++)
        time += Functions.timeToRun(func);
        return time / n;
    },

    notYetImplemented: function() {
        throw new Error('Not yet implemented');
    },

    methodChain: function(method) {
        // method wrappers used for wrapping, cop, and other method
        // manipulations attach a property "originalFunction" to the wrapper by
        // convention this property references the wrapped method like wrapper
        // -> cop wrapper -> real method
        // this method gives access to the linked list starting at "method
        var result = [];
        do {
            result.push(method);
            method = method.originalFunction;
        } while (method);
        return result;
    }
};<commit_msg>jenslincke, showing less error msgs<commit_after>///////////////////////////////////////////////////////////////////////////////
// Extensions to Function instances
///////////////////////////////////////////////////////////////////////////////

Object.extend(Function.prototype, {
    argumentNames: function() {
        var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1].
                replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '').
                replace(/\s+/g, '').split(',');

        return names.length == 1 && !names[0] ? [] : names;
    },

    curry: function() {
        if (!arguments.length) return this;
        var __method = this,
            args = $A(arguments),
            wrappedFunc = function curried() {
                return __method.apply(this, args.concat($A(arguments)));
            }
        wrappedFunc.isWrapper = true;
        wrappedFunc.originalFunction = __method;
        return wrappedFunc;
    },

    delay: function() {
        var __method = this,
            args = $A(arguments),
            timeout = args.shift() * 1000;
        return window.setTimeout(function delayed() {
            return __method.apply(__method, args);
        }, timeout);
    },

    wrap: function(wrapper) {
        var __method = this;
        var wrappedFunc = function wrapped() {
                var wrapperArgs = wrapper.isWrapper ? $A(arguments) : [__method.bind(this)].concat($A(arguments));
                return wrapper.apply(this, wrapperArgs);
            }
        wrappedFunc.isWrapper = true;
        wrappedFunc.originalFunction = __method;
        return wrappedFunc;
    },

    inspectFull: function() {
        var methodBody = this.toString();
        methodBody = methodBody.substring(8, methodBody.length);
        return this.qualifiedMethodName() + methodBody;
    },

    inspect: function() {
        // Print method name (if any) and the first 80 characters of the
        // decompiled source (without 'function')
        var def = this.toString(),
            i = def.indexOf('{'),
            header = this.qualifiedMethodName() + def.substring(8, i),
            // strip newlines
            body = (def.substring(i, 88) +
                     (def.length > 88 ? '...' : '')).replace(/\n/g, ' ');
        return header + body;
    },

    qualifiedMethodName: function() {
        var objString = "";
        if (this.declaredClass) {
            objString += this.declaredClass + '.';
        } else if (this.declaredObject) {
            objString += this.declaredObject + '>>';
        }
        return objString + (this.methodName || this.name || "anonymous");
    },

    functionNames: function(filter) {
        var functionNames = [];

        for (var name in this.prototype) {
            try {
                if ((this.prototype[name] instanceof Function) && (!filter || filter(name))) {
                    functionNames.push(name);
                }
            } catch (er) {
                // FF can throw an exception here ...
            }
        }

        return functionNames;
    },

    withAllFunctionNames: function(callback) {
        for (var name in this.prototype) {
            try {
                var value = this.prototype[name];
                if (value instanceof Function) callback(name, value, this);
            } catch (er) {
                // FF can throw an exception here ...
            }
        }
    },

    localFunctionNames: function() {
        var sup = this.superclass || ((this === Object) ? null : Object);

        try {
            var superNames = (sup == null) ? [] : sup.functionNames();
        } catch (e) {
            var superNames = [];
        }
        var result = [];

        this.withAllFunctionNames(function(name, value, target) {
            if (!superNames.include(name) || target.prototype[name] !== sup.prototype[name]) result.push(name);
        });
        return result;
    },

    getOriginal: function() {
        // get the original 'unwrapped' function, traversing as many wrappers as necessary.
        var func = this;
        while (func.originalFunction) func = func.originalFunction;
        return func;
    },

    logErrors: function(prefix) {
        if (Config.ignoreAdvice) return this;

        var advice = function logErrorsAdvice(proceed /*,args*/ ) {
                var args = $A(arguments);
                args.shift();
                try {
                    return proceed.apply(this, args);
                } catch (er) {
                    if (Global.lively && lively.morphic && lively.morphic.World && lively.morphic.World.current()) {
                        lively.morphic.World.current().logError(er)
                        throw er;
                    }

                    if (prefix) console.warn("ERROR: %s.%s(%s): err: %s %s", this, prefix, args, er, er.stack || "");
                    else console.warn("ERROR: %s %s", er, er.stack || "");
                    logStack();
                    if (Global.printObject) console.warn("details: " + printObject(er));
                    // lively.lang.Execution.showStack();
                    throw er;
                }
            }

        advice.methodName = "$logErrorsAdvice";
        var result = this.wrap(advice);
        result.originalFunction = this;
        result.methodName = "$logErrorsWrapper";
        return result;
    },

    logCompletion: function(module) {
        if (Config.ignoreAdvice) return this;

        var advice = function logCompletionAdvice(proceed) {
                var args = $A(arguments);
                args.shift();
                try {
                    var result = proceed.apply(this, args);
                } catch (er) {
                    console.warn('failed to load ' + module + ': ' + er);
                    lively.lang.Execution.showStack();
                    throw er;
                }
                console.log('completed ' + module);
                return result;
            }

        advice.methodName = "$logCompletionAdvice::" + module;

        var result = this.wrap(advice);
        result.methodName = "$logCompletionWrapper::" + module;
        result.originalFunction = this;
        return result;
    },

    logCalls: function(isUrgent) {
        if (Config.ignoreAdvice) return this;

        var original = this,
            advice = function logCallsAdvice(proceed) {
                var args = $A(arguments);
                args.shift(), result = proceed.apply(this, args);
                if (isUrgent) {
                    console.warn('%s(%s) -> %s', original.qualifiedMethodName(), args, result);
                } else {
                    console.log('%s(%s) -> %s', original.qualifiedMethodName(), args, result);
                }
                return result;
            }

        advice.methodName = "$logCallsAdvice::" + this.qualifiedMethodName();

        var result = this.wrap(advice);
        result.originalFunction = this;
        result.methodName = "$logCallsWrapper::" + this.qualifiedMethodName();
        return result;
    },

    traceCalls: function(stack) {
        var advice = function traceCallsAdvice(proceed) {
                var args = $A(arguments);
                args.shift();
                stack.push(args);
                var result = proceed.apply(this, args);
                stack.pop();
                return result;
            };
        return this.wrap(advice);
    },

    webkitStack: function() {
        // this won't work in every browser
        try {
            throw new Error()
        } catch (e) {
            // remove "Error" and this function from stack, rewrite it nicely
            var trace = Strings.lines(e.stack).slice(2).invoke('replace', /^\s*at\s*([^\s]+).*/, '$1').join('\n');
            return trace;
        }
    },

    unbind: function() {
        // for serializing functions
        return Function.fromString(this.toString());
    },

    asScript: function(optVarMapping) {
        return lively.Closure.fromFunction(this, optVarMapping).recreateFunc();
    },
    asScriptOf: function(obj, optName, optMapping) {
        var name = optName || this.name;
        if (!name) {
            throw Error("Function that wants to be a script needs a name: " + this);
        }
        var constructor = obj.constructor,
            mapping = {
                "this": obj
            };
        if (optMapping) mapping = Object.merge([mapping, optMapping]);
        if (constructor && constructor.prototype && constructor.prototype[name]) {
            var superFunc = function() {
                    try {
                        return obj.constructor.prototype[name].apply(obj, arguments)
                    } catch (e) {
                        if ($world)
                            $world.logError(e, 'Error in $super call')
                        else
                            alert('Error in $super call: ' + e + '\n' + e.stack);
                        return null;
                    }
                };
            mapping["$super"] = lively.Closure.fromFunction(superFunc, {
                "obj": obj,
                name: name
            }).recreateFunc();
        }
        return this.asScript(mapping).addToObject(obj, name);
    },

    addToObject: function(obj, name) {
        this.name = name;
        obj[name] = this;
        // suppport for tracing
        if (lively.Tracing && lively.Tracing.stackTracingEnabled) {
            lively.Tracing.instrumentMethod(obj, name, {
                declaredObject: Objects.safeToString(obj)
            });
        }
        return this;
    },

    binds: function(varMapping) {
        // convenience function
        return lively.Closure.fromFunction(this, varMapping || {}).recreateFunc()
    },

    setProperty: function(name, value) {
        this[name] = value;
        if (this.hasLivelyClosure) this.livelyClosure.funcProperties[name] = value
    },

    getVarMapping: function() {
        if (this.hasLivelyClosure) return this.livelyClosure.varMapping;
        if (this.isWrapper) return this.originalFunction.varMapping;
        if (this.varMapping) return this.varMapping;
        return {}
    }

});

///////////////////////////////////////////////////////////////////////////////
// Extensions to the Function object
///////////////////////////////////////////////////////////////////////////////

Object.extend(Function, {
    fromString: function(funcOrString) {
        return eval('(' + funcOrString.toString() + ')')
    }
});

///////////////////////////////////////////////////////////////////////////////
// Global Helper - Functions
///////////////////////////////////////////////////////////////////////////////

Functions = {
    Empty: function() {},

    K: function(arg) {
        return arg;
    },

    Null: function() {
        return null;
    },

    False: function() {
        return false;
    },

    True: function() {
        return true;
    },

    all: function(object) {
        var a = [];
        for (var name in object) {
            try {
                if (!object.__lookupGetter__(name) && Object.isFunction(object[name])) a.push(name);
            } catch (e) {
                alert(e)
            }
        }
        return a;
    },

    own: function(object) {
        var a = [];
        for (var name in object) {
            try {
                if (!object.__lookupGetter__(name) && object.hasOwnProperty(name) && Object.isFunction(object[name])) a.push(name);
            } catch (e) {
                alert(e)
            }
        }
        return a;
    },

    timeToRun: function(func) {
        var startTime = (new Date()).getTime();
        func();
        return new Date().getTime() - startTime;
    },

    timeToRunN: function(func, n) {
        var time = 0;
        for (var i = 0; i < n; i++)
        time += Functions.timeToRun(func);
        return time / n;
    },

    notYetImplemented: function() {
        throw new Error('Not yet implemented');
    },

    methodChain: function(method) {
        // method wrappers used for wrapping, cop, and other method
        // manipulations attach a property "originalFunction" to the wrapper by
        // convention this property references the wrapped method like wrapper
        // -> cop wrapper -> real method
        // this method gives access to the linked list starting at "method
        var result = [];
        do {
            result.push(method);
            method = method.originalFunction;
        } while (method);
        return result;
    }
};<|endoftext|>


<commit_before>sitemaps = {
  list: {}
};

if (typeof Number.lpad === "undefined") {
  Number.prototype.lpad = function(length) {
    "use strict";
    var str = this.toString();
    while (str.length < length) {
      str = "0" + str;
    }
    return str;
  };
}

/*
 * http://en.wikipedia.org/wiki/Site_map
 * http://www.sitemaps.org/index.html
 */

// TODO: 1) gzip, 2) sitemap index + other types + sitemap for old content
var Fiber = Npm.require('fibers');
WebApp.connectHandlers.use(function(req, res, next) {
  new Fiber(function() {
    "use strict";
		var out, urlStart, pages, urls;

    urls = _.keys(sitemaps.list);
    if (!_.contains(urls, req.url))
      return next();

    urlStart = (req.headers['x-forwarded-proto'] || req.protocol || 'http')
      + '://' + req.headers.host + '/';

		pages = sitemaps.list[req.url];
    if (_.isFunction(pages))
      pages = pages();
    else if (!_.isArray(pages))
      throw new TypeError("sitemaps.add() expects an array or function");

		out = '<?xml version="1.0" encoding="UTF-8"?>\n\n'
			+ '<urlset \n'
      + 'xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"\n'
      + 'xmlns:xhtml="http://www.w3.org/1999/xhtml">\n\n';

    var w3cDateTimeTS, date;
		_.each(pages, function(page) {

			out += '   <url>\n'
        + '      <loc>' + urlStart + escape(page.page.replace(/^\//,'')) + '</loc>\n';

      if (page.lastmod) {
        date = new Date(page.lastmod);
        w3cDateTimeTS = date.getUTCFullYear() + '-'
          + (date.getUTCMonth()+1).lpad(2) + '-'
          + date.getUTCDate().lpad(2) + 'T'
          + date.getUTCHours().lpad(2) + ':'
          + date.getUTCMinutes().lpad(2) + ':'
          + date.getUTCSeconds().lpad(2) + '+00:00';
				out += '      <lastmod>' + w3cDateTimeTS + '</lastmod>\n';
      }

      if (page.changefreq)
        out += '      <changefreq>' + page.changefreq + '</changefreq>\n';

      if (page.priority)
        out += '      <priority>' + page.priority + '</priority>\n';

      if (page.xhtmlLinks) {
        if (!_.isArray(page.xhtmlLinks))
          page.xhtmlLinks = [page.xhtmlLinks];
        _.each(page.xhtmlLinks, function(link) {
          out += '      <xhtml:link \n';
          if (link.href)
            link.href = urlStart + escape(link.href.replace(/^\//,''));
          for (var key in link)
            out += '        ' + key + '="' + link[key] + '"\n';
          out += '        />\n';
        });
      }

			out	+= '   </url>\n\n';
		});

		out += '</urlset>\n';

		res.writeHead(200, {'Content-Type': 'application/xml'});
		res.end(out, 'utf8');
    return;
  }).run();
});

sitemaps.add = function(url, func) {
  "use strict";

  var root = process.env.ROOT_URL;

  // don't double slash urls
  check(url, String);
  if (process.env.ROOT_URL.slice(-1) == '/' && url[0] == '/')
    root = root.slice(0, -1);

  sitemaps.list[url] = func;
  robots.addLine('Sitemap: ' + root + url);
};

/*
sitemaps.add('/sitemap.xml', function() {
  // 'page' is reqired
  // 'lastmod', 'changefreq', 'priority' are optional.
  return [
    { page: 'x', lastmod: new Date().getTime() },
    { page: 'y', lastmod: new Date().getTime(), changefreq: 'monthly' },
    { page: 'z', lastmod: new Date().getTime(), changefreq: 'monthly', priority: 0.8 }
  ];
});
*/
<commit_msg>Update sitemaps.js<commit_after>sitemaps = {
  list: {}
};

if (typeof Number.lpad === "undefined") {
  Number.prototype.lpad = function(length) {
    "use strict";
    var str = this.toString();
    while (str.length < length) {
      str = "0" + str;
    }
    return str;
  };
}

/*
 * http://en.wikipedia.org/wiki/Site_map
 * http://www.sitemaps.org/index.html
 */

// TODO: 1) gzip, 2) sitemap index + other types + sitemap for old content
var Fiber = Npm.require('fibers');
WebApp.connectHandlers.use(function(req, res, next) {
  new Fiber(function() {
    "use strict";
		var out, urlStart, pages, urls;

    urls = _.keys(sitemaps.list);
    if (!_.contains(urls, req.url))
      return next();

    urlStart = (req.headers['x-forwarded-proto'] || req.protocol || 'http').split(",")[0]
      + '://' + req.headers.host + '/';

		pages = sitemaps.list[req.url];
    if (_.isFunction(pages))
      pages = pages();
    else if (!_.isArray(pages))
      throw new TypeError("sitemaps.add() expects an array or function");

		out = '<?xml version="1.0" encoding="UTF-8"?>\n\n'
			+ '<urlset \n'
      + 'xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"\n'
      + 'xmlns:xhtml="http://www.w3.org/1999/xhtml">\n\n';

    var w3cDateTimeTS, date;
		_.each(pages, function(page) {

			out += '   <url>\n'
        + '      <loc>' + urlStart + escape(page.page.replace(/^\//,'')) + '</loc>\n';

      if (page.lastmod) {
        date = new Date(page.lastmod);
        w3cDateTimeTS = date.getUTCFullYear() + '-'
          + (date.getUTCMonth()+1).lpad(2) + '-'
          + date.getUTCDate().lpad(2) + 'T'
          + date.getUTCHours().lpad(2) + ':'
          + date.getUTCMinutes().lpad(2) + ':'
          + date.getUTCSeconds().lpad(2) + '+00:00';
				out += '      <lastmod>' + w3cDateTimeTS + '</lastmod>\n';
      }

      if (page.changefreq)
        out += '      <changefreq>' + page.changefreq + '</changefreq>\n';

      if (page.priority)
        out += '      <priority>' + page.priority + '</priority>\n';

      if (page.xhtmlLinks) {
        if (!_.isArray(page.xhtmlLinks))
          page.xhtmlLinks = [page.xhtmlLinks];
        _.each(page.xhtmlLinks, function(link) {
          out += '      <xhtml:link \n';
          if (link.href)
            link.href = urlStart + escape(link.href.replace(/^\//,''));
          for (var key in link)
            out += '        ' + key + '="' + link[key] + '"\n';
          out += '        />\n';
        });
      }

			out	+= '   </url>\n\n';
		});

		out += '</urlset>\n';

		res.writeHead(200, {'Content-Type': 'application/xml'});
		res.end(out, 'utf8');
    return;
  }).run();
});

sitemaps.add = function(url, func) {
  "use strict";

  var root = process.env.ROOT_URL;

  // don't double slash urls
  check(url, String);
  if (process.env.ROOT_URL.slice(-1) == '/' && url[0] == '/')
    root = root.slice(0, -1);

  sitemaps.list[url] = func;
  robots.addLine('Sitemap: ' + root + url);
};

/*
sitemaps.add('/sitemap.xml', function() {
  // 'page' is reqired
  // 'lastmod', 'changefreq', 'priority' are optional.
  return [
    { page: 'x', lastmod: new Date().getTime() },
    { page: 'y', lastmod: new Date().getTime(), changefreq: 'monthly' },
    { page: 'z', lastmod: new Date().getTime(), changefreq: 'monthly', priority: 0.8 }
  ];
});
*/
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import {View, Text, TouchableOpacity, Animated, StyleSheet} from 'react-native';
import Events from 'react-native-simple-events';

export default class SnackBar extends Component {
    constructor(props) {
        super(props);
        this.state = {
            message: 'Had a snack at snackBar.',
            confirmText: null,
            onConfirm: null,
            position: 'bottom',
            show: false,
            duration: 5000,
            animationTime: 250,
            height: 48,
            textColor: '#FFF',
            buttonColor: '#03a9f4',
            backgroundColor: '#323232',

            top: new Animated.Value(-48),
            bottom: new Animated.Value(-48)
        };
    }

    componentWillMount() {
        let {id = null} = this.props;
        Events.on('showSnackBar', id ? id : '123456789', this.onRequest);
    }

    componentWillUnmount() {
        let {id = null} = this.props;
        Events.remove('showSnackBar', id ? id : '123456789');
    }

    onRequest = (options) => {
        let {message, confirmText, onConfirm, position = 'bottom', height = 48, duration = 4000, animationTime = 250, show = true, ...otherOptions} = options;

        if (message) {
            this.setState({
                message, confirmText,
                onConfirm, position,
                height, duration,
                show, ...otherOptions,
                top: new Animated.Value(-1 * height),
                bottom: new Animated.Value(-1 * height)
            }, () => {
                position === 'top' && Animated.sequence([
                    Animated.timing(this.state.top, {toValue: 0, duration: animationTime}),
                    Animated.delay(duration),
                    Animated.timing(this.state.top, {toValue: -1 * height, duration: animationTime}),
                ]).start();

                position === 'bottom' && Animated.sequence([
                    Animated.timing(this.state.bottom, {toValue: 0, duration: animationTime}),
                    Animated.delay(duration),
                    Animated.timing(this.state.bottom, {toValue: -1 * height, duration: animationTime}),
                ]).start();

                setTimeout(() => {
                    this.setState({show: false});
                }, duration + 500);
            });
        }
    };

    hideSnackBar = () => {
        let {top, bottom, position, height, animationTime} = this.state;
        position === 'top' && Animated.sequence([
            Animated.timing(this.state.top, {toValue: -1 * height, duration: animationTime}),
        ]).start();

        position === 'bottom' && Animated.sequence([
            Animated.timing(this.state.bottom, {toValue: -1 * height, duration: animationTime}),
        ]).start();
    };

    render() {
        let {
            height, show, message, confirmText, position, top, bottom, textColor, buttonColor, backgroundColor, onConfirm = () => {
            }
        } = this.state;

        if (show) {
            return (
                <Animated.View style={[{
                    position: 'absolute', flexDirection: 'row',
                    minHeight: height,
                    maxHeight: 80,
                    backgroundColor: backgroundColor,
                    left: 0, right: 0, elevation: 24,
                    paddingHorizontal: 24,
                },
                    position === 'top' && {top: top},
                    position === 'bottom' && {bottom: bottom}
                ]}>
                    <View style={[{flex: 10, paddingVertical: 14}]}>
                        <Text
                            ellipsizeMode="tail"
                            numberOfLines={2}
                            style={[{
                                color: textColor, fontFamily: "Roboto-Regular", fontSize: 14,
                            }]}>
                            {message}
                        </Text>
                    </View>
                    {
                        confirmText &&
                        <View style={[{flex: 2, paddingLeft: 24}]}>
                            <TouchableOpacity
                                activeOpacity={0.7}
                                onPress={() => {
                                    onConfirm();
                                    this.hideSnackBar();
                                }}
                                style={{flex: 1}}>
                                <View style={[{
                                    flex: 1, alignItems: 'center', justifyContent: 'center'
                                }]}>
                                    <Text style={[{
                                        color: buttonColor, fontFamily: "Roboto-Medium", textAlign: 'left', fontSize: 14
                                    }]}>
                                        {confirmText.toUpperCase()}
                                    </Text>
                                </View>
                            </TouchableOpacity>
                        </View>
                    }
                </Animated.View>
            )
        } else {
            return (<View/>);
        }
    }
}<commit_msg>optimise imports<commit_after>import React, {Component} from 'react';
import {Animated, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import Events from 'react-native-simple-events';

export default class SnackBar extends Component {
    constructor(props) {
        super(props);
        this.state = {
            message: 'Had a snack at snackBar.',
            confirmText: null,
            onConfirm: null,
            position: 'bottom',
            show: false,
            duration: 5000,
            animationTime: 250,
            height: 48,
            textColor: '#FFF',
            buttonColor: '#03a9f4',
            backgroundColor: '#323232',

            top: new Animated.Value(-48),
            bottom: new Animated.Value(-48)
        };
    }

    componentWillMount() {
        let {id = null} = this.props;
        Events.on('showSnackBar', id ? id : '123456789', this.onRequest);
    }

    componentWillUnmount() {
        let {id = null} = this.props;
        Events.remove('showSnackBar', id ? id : '123456789');
    }

    onRequest = (options) => {
        let {message, confirmText, onConfirm, position = 'bottom', height = 48, duration = 4000, animationTime = 250, show = true, ...otherOptions} = options;

        if (message) {
            this.setState({
                message, confirmText,
                onConfirm, position,
                height, duration,
                show, ...otherOptions,
                top: new Animated.Value(-1 * height),
                bottom: new Animated.Value(-1 * height)
            }, () => {
                position === 'top' && Animated.sequence([
                    Animated.timing(this.state.top, {toValue: 0, duration: animationTime}),
                    Animated.delay(duration),
                    Animated.timing(this.state.top, {toValue: -1 * height, duration: animationTime}),
                ]).start();

                position === 'bottom' && Animated.sequence([
                    Animated.timing(this.state.bottom, {toValue: 0, duration: animationTime}),
                    Animated.delay(duration),
                    Animated.timing(this.state.bottom, {toValue: -1 * height, duration: animationTime}),
                ]).start();

                setTimeout(() => {
                    this.setState({show: false});
                }, duration + 500);
            });
        }
    };

    hideSnackBar = () => {
        let {top, bottom, position, height, animationTime} = this.state;
        position === 'top' && Animated.sequence([
            Animated.timing(this.state.top, {toValue: -1 * height, duration: animationTime}),
        ]).start();

        position === 'bottom' && Animated.sequence([
            Animated.timing(this.state.bottom, {toValue: -1 * height, duration: animationTime}),
        ]).start();
    };

    render() {
        let {
            height, show,
            message, confirmText,
            position, top, bottom,
            textColor, buttonColor, backgroundColor,
            onConfirm = () => {
            }
        } = this.state;

        if (show) {
            return (
                <Animated.View style={[{
                    position: 'absolute', flexDirection: 'row',
                    minHeight: height,
                    maxHeight: 80,
                    backgroundColor: backgroundColor,
                    left: 0, right: 0, elevation: 24,
                    paddingHorizontal: 24,
                },
                    position === 'top' && {top: top},
                    position === 'bottom' && {bottom: bottom}
                ]}>
                    <View style={[{flex: 10, paddingVertical: 14}]}>
                        <Text
                            ellipsizeMode="tail"
                            numberOfLines={2}
                            style={[{
                                color: textColor, fontFamily: "Roboto-Regular", fontSize: 14,
                            }]}>
                            {message}
                        </Text>
                    </View>
                    {
                        confirmText &&
                        <View style={[{flex: 2, paddingLeft: 24}]}>
                            <TouchableOpacity
                                activeOpacity={0.7}
                                onPress={() => {
                                    onConfirm();
                                    this.hideSnackBar();
                                }}
                                style={{flex: 1}}>
                                <View style={[{
                                    flex: 1, alignItems: 'center', justifyContent: 'center'
                                }]}>
                                    <Text style={[{
                                        color: buttonColor, fontFamily: "Roboto-Medium", textAlign: 'left', fontSize: 14
                                    }]}>
                                        {confirmText.toUpperCase()}
                                    </Text>
                                </View>
                            </TouchableOpacity>
                        </View>
                    }
                </Animated.View>
            )
        } else {
            return (<View/>);
        }
    }
}<|endoftext|>


<commit_before>import _curry3 from './internal/_curry3';

/**
 * `o` is a curried composition function that returns a unary function.
 * Like [`compose`](#compose), `o` performs right-to-left function composition.
 * Unlike [`compose`](#compose), the rightmost function passed to `o` will be
 * invoked with only one argument. Also, unlike [`compose`](#compose), `o` is
 * limited to accepting only 2 unary functions. It's origin is meant to look
 * like the mathematical composition operator `∘`, with lowercase o being the
 * closest ASCII match.
 *
 * @func
 * @memberOf R
 * @since v0.24.0
 * @category Function
 * @sig (b -> c) -> (a -> b) -> a -> c
 * @param {Function} f
 * @param {Function} g
 * @return {Function}
 * @see R.compose, R.pipe
 * @example
 *
 *      var classyGreeting = name => "The name's " + name.last + ", " + name.first + " " + name.last
 *      var yellGreeting = R.o(R.toUpper, classyGreeting);
 *      yellGreeting({first: 'James', last: 'Bond'}); //=> "THE NAME'S BOND, JAMES BOND"
 *
 *      R.o(R.multiply(10), R.add(10))(-4) //=> 60
 *
 * @symb R.o(f, g, x) = f(g(x))
 */
var o = _curry3(function o(f, g, x) {
  return f(g(x));
});
export default o;
<commit_msg>Fix linting issue due to trailing space on line 10<commit_after>import _curry3 from './internal/_curry3';

/**
 * `o` is a curried composition function that returns a unary function.
 * Like [`compose`](#compose), `o` performs right-to-left function composition.
 * Unlike [`compose`](#compose), the rightmost function passed to `o` will be
 * invoked with only one argument. Also, unlike [`compose`](#compose), `o` is
 * limited to accepting only 2 unary functions. It's origin is meant to look
 * like the mathematical composition operator `∘`, with lowercase o being the
 * closest ASCII match.
 *
 * @func
 * @memberOf R
 * @since v0.24.0
 * @category Function
 * @sig (b -> c) -> (a -> b) -> a -> c
 * @param {Function} f
 * @param {Function} g
 * @return {Function}
 * @see R.compose, R.pipe
 * @example
 *
 *      var classyGreeting = name => "The name's " + name.last + ", " + name.first + " " + name.last
 *      var yellGreeting = R.o(R.toUpper, classyGreeting);
 *      yellGreeting({first: 'James', last: 'Bond'}); //=> "THE NAME'S BOND, JAMES BOND"
 *
 *      R.o(R.multiply(10), R.add(10))(-4) //=> 60
 *
 * @symb R.o(f, g, x) = f(g(x))
 */
var o = _curry3(function o(f, g, x) {
  return f(g(x));
});
export default o;
<|endoftext|>


<commit_before>import React from 'react';

import ITEMS from 'common/ITEMS';
import Analyzer from 'Parser/Core/Analyzer';
import Combatants from 'Parser/Core/Modules/Combatants';
import SPELLS from 'common/SPELLS';
import getDamageBonus from 'Parser/Hunter/Shared/Modules/getDamageBonus';
import ItemDamageDone from 'Main/ItemDamageDone';
import { formatPercentage } from 'common/format';
import Wrapper from 'common/Wrapper';
import SpellLink from 'common/SpellLink';

/**
 * Butcher's Bone Apron
 * Equip: Mongoose Bite increases the damage of your next Butchery or Carve by 10%.
 * Stacks up to 10 times.
 */

const MAX_STACKS = 10;

const MODIFIER_PER_STACK = 0.1;

class ButchersBoneApron extends Analyzer {
  static dependencies = {
    combatants: Combatants,
  };

  _currentStacks = 0;
  _savedStacks = 0;
  wastedStacks = 0;
  bonusDamage = 0;
  totalStacks = 0;
  usedStacks = 0;

  on_initialized() {
    this.active = this.combatants.selected.hasChest(ITEMS.BUTCHERS_BONE_APRON.id);
  }

  on_byPlayer_cast(event) {
    const spellID = event.ability.guid;
    if (spellID === SPELLS.MONGOOSE_BITE.id && this._currentStacks === MAX_STACKS) {
      this.wastedStacks++;
      this.totalStacks++;
    }
    if (spellID === SPELLS.BUTCHERY_TALENT.id || spellID === SPELLS.CARVE.id) {
      this._savedStacks = this._currentStacks;
      this.usedStacks += this._currentStacks;
    }
  }

  on_byPlayer_applybuff(event) {
    const spellID = event.ability.guid;
    if (spellID !== SPELLS.BUTCHERS_BONE_APRON_BUFF.id) {
      return;
    }
    this._currentStacks = 1;
    this._savedStacks = 0;
    this.totalStacks++;
  }

  on_byPlayer_applybuffstack(event) {
    const spellID = event.ability.guid;
    if (spellID !== SPELLS.BUTCHERS_BONE_APRON_BUFF.id) {
      return;
    }
    this._currentStacks = event.stack;
    this.totalStacks++;

  }

  on_byPlayer_removebuff(event) {
    const spellID = event.ability.guid;
    if (spellID !== SPELLS.BUTCHERS_BONE_APRON_BUFF.id) {
      return;
    }
    this._currentStacks = 0;
  }

  on_byPlayer_damage(event) {
    const spellID = event.ability.guid;
    if (spellID !== SPELLS.BUTCHERY_TALENT.id && spellID !== SPELLS.CARVE.id) {
      return;
    }
    this.bonusDamage += getDamageBonus(event, MODIFIER_PER_STACK * this._savedStacks);
  }

  get apronStacks() {
    return this._currentStacks;
  }

  get percentCappedStacks() {
    return this.wastedStacks / this.totalStacks;
  }

  get unusedStacks() {
    return this.totalStacks - this.usedStacks - this.wastedStacks;
  }
  get percentUnusedStacks() {
    return this.unusedStacks / this.totalStacks;
  }

  get unusedStacksThreshold() {
    return {
      actual: this.percentUnusedStacks,
      isGreaterThan: {
        minor: 0,
        average: 0.05,
        major: 0.1,
      },
      style: 'percentage',
    };
  }

  get cappedStacksThreshold() {
    return {
      actual: this.percentCappedStacks,
      isGreaterThan: {
        minor: 0,
        average: 0.05,
        major: 0.1,
      },
      style: 'percentage',
    };
  }
  suggestions(when) {
    when(this.cappedStacksThreshold).addSuggestion((suggest, actual, recommended) => {
      return suggest(<Wrapper>You lost out on {this.wastedStacks} (or {formatPercentage(this.percentCappedStacks)}% of total stacks) chest stacks because you were capped. You should try and avoid this by casting a <SpellLink id={SPELLS.BUTCHERY_TALENT.id} icon /> when you're at at {MAX_STACKS} stacks. </Wrapper>)
        .icon(ITEMS.BUTCHERS_BONE_APRON.icon)
        .actual(`${this.wastedStacks} or ${formatPercentage(actual)}% of total stacks were wasted due to overcapping`)
        .recommended(`${recommended}% is recommended`);
    });
    when(this.unusedStacksThreshold).addSuggestion((suggest, actual, recommended) => {
      return suggest(<Wrapper>You finished the encounter with {this.unusedStacks} stacks unused, try and utilise all of your stacks to get the most out of your equipped legendary and <SpellLink id={SPELLS.BUTCHERY_TALENT.id} icon />.</Wrapper>)
        .icon(ITEMS.BUTCHERS_BONE_APRON.icon)
        .actual(`${formatPercentage(actual)}% of total stacks were unused`)
        .recommended(`${formatPercentage(recommended, 0)}% unused stacks is recommended`);
    });
  }

  item() {
    return {
      item: ITEMS.BUTCHERS_BONE_APRON,
      result: (
        <dfn data-tip={`You applied the Butchers Bone Apron buff ${(this.totalStacks - this.wastedStacks)} times, and wasted ${this.wastedStacks} stacks by casting Mongoose Bite while you were already at 10 stacks.`}>
          <ItemDamageDone amount={this.bonusDamage} />
        </dfn>
      ),
    };
  }
}

export default ButchersBoneApron;
<commit_msg>spelling<commit_after>import React from 'react';

import ITEMS from 'common/ITEMS';
import Analyzer from 'Parser/Core/Analyzer';
import Combatants from 'Parser/Core/Modules/Combatants';
import SPELLS from 'common/SPELLS';
import getDamageBonus from 'Parser/Hunter/Shared/Modules/getDamageBonus';
import ItemDamageDone from 'Main/ItemDamageDone';
import { formatPercentage } from 'common/format';
import Wrapper from 'common/Wrapper';
import SpellLink from 'common/SpellLink';

/**
 * Butcher's Bone Apron
 * Equip: Mongoose Bite increases the damage of your next Butchery or Carve by 10%.
 * Stacks up to 10 times.
 */

const MAX_STACKS = 10;

const MODIFIER_PER_STACK = 0.1;

class ButchersBoneApron extends Analyzer {
  static dependencies = {
    combatants: Combatants,
  };

  _currentStacks = 0;
  _savedStacks = 0;
  wastedStacks = 0;
  bonusDamage = 0;
  totalStacks = 0;
  usedStacks = 0;

  on_initialized() {
    this.active = this.combatants.selected.hasChest(ITEMS.BUTCHERS_BONE_APRON.id);
  }

  on_byPlayer_cast(event) {
    const spellID = event.ability.guid;
    if (spellID === SPELLS.MONGOOSE_BITE.id && this._currentStacks === MAX_STACKS) {
      this.wastedStacks++;
      this.totalStacks++;
    }
    if (spellID === SPELLS.BUTCHERY_TALENT.id || spellID === SPELLS.CARVE.id) {
      this._savedStacks = this._currentStacks;
      this.usedStacks += this._currentStacks;
    }
  }

  on_byPlayer_applybuff(event) {
    const spellID = event.ability.guid;
    if (spellID !== SPELLS.BUTCHERS_BONE_APRON_BUFF.id) {
      return;
    }
    this._currentStacks = 1;
    this._savedStacks = 0;
    this.totalStacks++;
  }

  on_byPlayer_applybuffstack(event) {
    const spellID = event.ability.guid;
    if (spellID !== SPELLS.BUTCHERS_BONE_APRON_BUFF.id) {
      return;
    }
    this._currentStacks = event.stack;
    this.totalStacks++;

  }

  on_byPlayer_removebuff(event) {
    const spellID = event.ability.guid;
    if (spellID !== SPELLS.BUTCHERS_BONE_APRON_BUFF.id) {
      return;
    }
    this._currentStacks = 0;
  }

  on_byPlayer_damage(event) {
    const spellID = event.ability.guid;
    if (spellID !== SPELLS.BUTCHERY_TALENT.id && spellID !== SPELLS.CARVE.id) {
      return;
    }
    this.bonusDamage += getDamageBonus(event, MODIFIER_PER_STACK * this._savedStacks);
  }

  get apronStacks() {
    return this._currentStacks;
  }

  get percentCappedStacks() {
    return this.wastedStacks / this.totalStacks;
  }

  get unusedStacks() {
    return this.totalStacks - this.usedStacks - this.wastedStacks;
  }
  get percentUnusedStacks() {
    return this.unusedStacks / this.totalStacks;
  }

  get unusedStacksThreshold() {
    return {
      actual: this.percentUnusedStacks,
      isGreaterThan: {
        minor: 0,
        average: 0.05,
        major: 0.1,
      },
      style: 'percentage',
    };
  }

  get cappedStacksThreshold() {
    return {
      actual: this.percentCappedStacks,
      isGreaterThan: {
        minor: 0,
        average: 0.05,
        major: 0.1,
      },
      style: 'percentage',
    };
  }
  suggestions(when) {
    when(this.cappedStacksThreshold).addSuggestion((suggest, actual, recommended) => {
      return suggest(<Wrapper>You lost out on {this.wastedStacks} (or {formatPercentage(this.percentCappedStacks)}% of total stacks) chest stacks because you were capped. You should try and avoid this by casting a <SpellLink id={SPELLS.BUTCHERY_TALENT.id} icon /> when you're at {MAX_STACKS} stacks. </Wrapper>)
        .icon(ITEMS.BUTCHERS_BONE_APRON.icon)
        .actual(`${this.wastedStacks} or ${formatPercentage(actual)}% of total stacks were wasted due to overcapping`)
        .recommended(`${recommended}% is recommended`);
    });
    when(this.unusedStacksThreshold).addSuggestion((suggest, actual, recommended) => {
      return suggest(<Wrapper>You finished the encounter with {this.unusedStacks} stacks unused, try and utilise all of your stacks to get the most out of your equipped legendary and <SpellLink id={SPELLS.BUTCHERY_TALENT.id} icon />.</Wrapper>)
        .icon(ITEMS.BUTCHERS_BONE_APRON.icon)
        .actual(`${formatPercentage(actual)}% of total stacks were unused`)
        .recommended(`${formatPercentage(recommended, 0)}% unused stacks is recommended`);
    });
  }

  item() {
    return {
      item: ITEMS.BUTCHERS_BONE_APRON,
      result: (
        <dfn data-tip={`You applied the Butchers Bone Apron buff ${(this.totalStacks - this.wastedStacks)} times, and wasted ${this.wastedStacks} stacks by casting Mongoose Bite while you were already at 10 stacks.`}>
          <ItemDamageDone amount={this.bonusDamage} />
        </dfn>
      ),
    };
  }
}

export default ButchersBoneApron;
<|endoftext|>


<commit_before>import SPELLS from 'common/SPELLS';

import CoreAlwaysBeCasting from 'Parser/Core/Modules/AlwaysBeCasting';

class AlwaysBeCasting extends CoreAlwaysBeCasting {
  static ABILITIES_ON_GCD = [
    SPELLS.BLACKOUT_KICK.id,
    SPELLS.RISING_SUN_KICK.id,
    SPELLS.TIGER_PALM.id,
  ];

  showStatistic = true;
}

export default AlwaysBeCasting;
<commit_msg>[Windwalker] Updated AlwaysBeCasting<commit_after>import React from 'react';

import CoreAlwaysBeCasting from 'Parser/Core/Modules/AlwaysBeCasting';

import SPELLS from 'common/SPELLS';
import { formatPercentage } from 'common/format';
import { STATISTIC_ORDER } from 'Main/StatisticBox';

class AlwaysBeCasting extends CoreAlwaysBeCasting {
  static ABILITIES_ON_GCD = [
    // Channeled spells
    SPELLS.FISTS_OF_FURY_CAST.id,
    SPELLS.CRACKLING_JADE_LIGHTNING.id,

    // rotational:
    SPELLS.BLACKOUT_KICK.id,
    SPELLS.RISING_SUN_KICK.id,
    SPELLS.TIGER_PALM.id,
    SPELLS.STRIKE_OF_THE_WINDLORD.id,
    SPELLS.SPINNING_CRANE_KICK.id,
    SPELLS.TOUCH_OF_DEATH.id,

    // talents:
    SPELLS.CHI_WAVE_TALENT.id,
    SPELLS.CHI_BURST_TALENT.id,
    SPELLS.LEG_SWEEP_TALENT.id,
    SPELLS.RING_OF_PEACE_TALENT.id,
    SPELLS.SUMMON_BLACK_OX_STATUE_TALENT.id,
    SPELLS.RUSHING_JADE_WIND_TALENT.id,
    SPELLS.WHIRLING_DRAGON_PUNCH_TALENT.id,

    // utility:
    SPELLS.PARALYSIS.id,
    SPELLS.EFFUSE.id,
    SPELLS.TRANSCENDENCE.id,
    SPELLS.TRANSCENDENCE_TRANSFER.id,

  ];

  suggestions(when) {
    const deadTimePercentage = this.totalTimeWasted / this.owner.fightDuration;

    when(deadTimePercentage).isGreaterThan(0.2)
      .addSuggestion((suggest, actual, recommended) => {
        return suggest(Your downtime can be improved. Try to Always Be Casting (ABC), try to reduce the delay between casting spells.)
          .icon('spell_mage_altertime')
          .actual(`${formatPercentage(actual)}% downtime`)
          .recommended(`<${formatPercentage(recommended)}% is recommended`)
          .regular(recommended + 0.15).major(recommended + 0.2);
      });
  }

  showStatistic = true;
  statisticOrder = STATISTIC_ORDER.CORE(1);
}

export default AlwaysBeCasting;
<|endoftext|>