<commit_before>// Generated by CoffeeScript 1.6.3
(function() {
  var PollingRequest;

  PollingRequest = (function() {
    function PollingRequest(options) {
      var _base, _base1, _base2, _base3;
      this.options = options;
      this.progress = 0;
      this.status = 'pending';
      (_base = this.options).interval || (_base.interval = 1000);
      (_base1 = this.options).success || (_base1.success = function() {});
      (_base2 = this.options).progress || (_base2.progress = function() {});
      (_base3 = this.options).error || (_base3.error = function() {});
    }

    PollingRequest.prototype.start = function() {
      var _this = this;
      if (this.timer) {
        return;
      }
      return this.timer = setInterval(function() {
        return _this._run();
      }, this.options.interval);
    };

    PollingRequest.prototype.stop = function() {
      this.status = 'stopped';
      clearInterval(this.timer);
      return this.timer = null;
    };

    PollingRequest.prototype.status = function() {
      return this.status;
    };

    PollingRequest.prototype.progress = function() {
      return this.progress;
    };

    PollingRequest.prototype._run = function() {
      var _this = this;
      return $.ajax({
        url: this.options.url,
        beforeSend: function(jqXHR, settings) {
          return _this.status = 'running';
        },
        statusCode: {
          200: function(data, textStatus, jqXHR) {
            _this.progress = 100;
            _this.options.success(data);
            return _this.stop();
          },
          202: function(data, textStatus, jqXHR) {
            _this.progress = data.progress || 0;
            return _this.options.progress(data.progress);
          }
        },
        error: function(jqXHR, textStatus, errorThrown) {
          _this.options.error(jqXHR.status, jqXHR.responseText);
          return _this.stop();
        }
      });
    };

    return PollingRequest;

  })();

  (typeof exports !== "undefined" && exports !== null ? exports : this).PollingRequest = PollingRequest;

}).call(this);
<commit_msg>forgot to check in compiled js<commit_after>// Generated by CoffeeScript 1.6.3
(function() {
  var PollingRequest;

  PollingRequest = (function() {
    function PollingRequest(options) {
      var _base, _base1, _base2, _base3, _base4;
      this.options = options;
      this.progress = 0;
      this.status = 'pending';
      (_base = this.options).interval || (_base.interval = 1000);
      (_base1 = this.options).success || (_base1.success = function() {});
      (_base2 = this.options).progress || (_base2.progress = function() {});
      (_base3 = this.options).error || (_base3.error = function() {});
      (_base4 = this.options).stopped || (_base4.stopped = function() {});
    }

    PollingRequest.prototype.start = function() {
      var _this = this;
      if (this.timer) {
        return;
      }
      return this.timer = setInterval(function() {
        return _this._run();
      }, this.options.interval);
    };

    PollingRequest.prototype.stop = function() {
      this.status = 'stopped';
      clearInterval(this.timer);
      this.timer = null;
      return this.options.stopped();
    };

    PollingRequest.prototype.status = function() {
      return this.status;
    };

    PollingRequest.prototype.progress = function() {
      return this.progress;
    };

    PollingRequest.prototype._run = function() {
      var _this = this;
      return $.ajax({
        url: this.options.url,
        cached: false,
        accepts: {
          json: 'application/json'
        },
        beforeSend: function(jqXHR, settings) {
          return _this.status = 'running';
        },
        statusCode: {
          200: function(data, textStatus, jqXHR) {
            _this.progress = 100;
            _this.options.success(data);
            return _this.stop();
          },
          202: function(data, textStatus, jqXHR) {
            _this.progress = data.progress || 0;
            return _this.options.progress(_this.progress);
          }
        },
        error: function(jqXHR, textStatus, errorThrown) {
          _this.options.error(jqXHR.status, jqXHR.responseText);
          return _this.stop();
        }
      });
    };

    return PollingRequest;

  })();

  (typeof exports !== "undefined" && exports !== null ? exports : this).PollingRequest = PollingRequest;

}).call(this);
<|endoftext|>


<commit_before>import { WidthScreen, scoreToWin } from "../constants.js";
const style = {font: '80px Arial', fill: '#FFFFFF', align: 'center'}
const styleWinner = {font: '50px Arial', fill: '#FFFFFF', align: 'center'}
const top = 10;
const winnerLabel =  "Winner !";

class Hud extends Phaser.Group {

  constructor(game, scores) {
    super(game);
    this.scoreLeft = game.add.text(WidthScreen * 0.25, top, scores[0], style);
    this.scoreLeft.anchor.set(0.5, 0);
    this.winnerLeft = game.add.text(WidthScreen * 0.25, top + 100, winnerLabel, styleWinner);
    this.winnerLeft.anchor.set(0.5, 0.5);
    this.winnerLeft.visible = false;

    this.scoreRight = game.add.text(WidthScreen * 0.75, top, scores[1], style);
    this.scoreRight.anchor.set(0.5, 0);
    this.winnerRight = game.add.text(WidthScreen * 0.75, top + 100, winnerLabel, styleWinner);
    this.winnerRight.anchor.set(0.5, 0.5);
    this.winnerRight.visible = false;

    this.add(this.scoreRight);
    this.add(this.scoreLeft);
  }

  updateTexts(scores) {
    this.scoreLeft.text = scores[0];
    this.scoreRight.text = scores[1];
  }

  makeWinnerVisible(scores) {
    if(scores[0] === scoreToWin) {
      this.winnerLeft.visible = true;
    } else if(scores[1] === scoreToWin) {
      this.winnerRight.visible = true;
    }
  }

  makeWinnerInvisible(scores) {
    this.winnerLeft.visible = false;
    this.winnerRight.visible = false;
  }

}

export default Hud;<commit_msg>add switching hud<commit_after>import { WidthScreen, HeightScreen, scoreToWin } from "../constants.js";
const style = {font: '80px Arial', fill: '#FFFFFF', align: 'center'}
const styleWinner = {font: '50px Arial', fill: '#FFFFFF', align: 'center'}
const top = 50;
const left = WidthScreen - 80;
const winnerLabel =  "Winner !";

class Hud extends Phaser.Group {

  constructor(game, scores, direction = "vertical") {
    super(game);
    this.switchHub(game, scores, direction);

    this.scoreLeft.anchor.set(0.5, 0.5);
    this.winnerLeft.anchor.set(0.5, 0.5);
    //this.winnerLeft.visible = false;

    this.scoreRight.anchor.set(0.5, 0.5);
    this.winnerRight.anchor.set(0.5, 0.5);
    //this.winnerRight.visible = false;

    this.add(this.scoreRight);
    this.add(this.scoreLeft);
  }

  updateTexts(scores) {
    this.scoreLeft.text = scores[0];
    this.scoreRight.text = scores[1];
  }

  makeWinnerVisible(scores) {
    if(scores[0] === scoreToWin) {
      this.winnerLeft.visible = true;
    } else if(scores[1] === scoreToWin) {
      this.winnerRight.visible = true;
    }
  }

  makeWinnerInvisible(scores) {
    this.winnerLeft.visible = false;
    this.winnerRight.visible = false;
  }

  switchHub(game, scores, direction) {
    if(direction === "vertical") {
      this.scoreLeft = game.add.text(WidthScreen * 0.25, top, scores[0], style);
      this.winnerLeft = game.add.text(WidthScreen * 0.25, top + 100, winnerLabel, styleWinner);

      this.scoreRight = game.add.text(WidthScreen * 0.75, top, scores[1], style);
      this.winnerRight = game.add.text(WidthScreen * 0.75, top + 100, winnerLabel, styleWinner);
    } else {
      this.scoreLeft = game.add.text(left, HeightScreen * 0.25, scores[0], style);
      this.winnerLeft = game.add.text(left - 20, HeightScreen * 0.25 + 100, winnerLabel, styleWinner);

      this.scoreRight = game.add.text(left, HeightScreen * 0.75, scores[1], style);
      this.winnerRight = game.add.text(left - 20, HeightScreen * 0.75 + 100, winnerLabel, styleWinner);
    }

  }

}

export default Hud;<|endoftext|>


<commit_before>(function() {
    'use strict';

    // http://docs.python-cerberus.org/en/stable/usage.html
    var DEFAULT_SCHEMA = Object.freeze({
        slugline: {maxlength: 24, type: 'string', required: true},
        relatedItems: {},
        genre: {type: 'list'},
        anpa_take_key: {},
        place: {type: 'list'},
        priority: {},
        urgency: {},
        anpa_category: {type: 'list', required: true},
        subject: {type: 'list', required: true},
        company_codes: {type: 'list'},
        ednote: {},
        headline: {maxlength: 64, type: 'string', required: true},
        sms: {maxlength: 160},
        abstract: {maxlength: 160, type: 'string'},
        body_html: {},
        byline: {type: 'string'},
        dateline: {type: 'dict', required: true},
        sign_off: {type: 'string'},
        footer: {},
        body_footer: {},
        media: {},
        media_description: {}
    });

    var DEFAULT_EDITOR = Object.freeze({
        slugline: {order: 1, sdWidth: 'full'},
        genre: {order: 2, sdWidth: 'half'},
        anpa_take_key: {order: 3, sdWidth: 'half'},
        place: {order: 4, sdWidth: 'half'},
        priority: {order: 5, sdWidth: 'quarter'},
        urgency: {order: 6, sdWidth: 'quarter'},
        anpa_category: {order: 7, sdWidth: 'full'},
        subject: {order: 8, sdWidth: 'full'},
        company_codes: {order: 9, sdWidth: 'full'},
        ednote: {order: 10, sdWidth: 'full'},
        headline: {order: 11, formatOptions: ['underline', 'anchor', 'bold', 'removeFormat']},
        sms: {order: 12},
        abstract: {order: 13, formatOptions: ['bold', 'italic', 'underline', 'anchor', 'removeFormat']},
        byline: {order: 14},
        dateline: {order: 15},
        body_html: {
            order: 16,
            formatOptions: ['h2', 'bold', 'italic', 'underline', 'quote', 'anchor', 'embed', 'picture', 'removeFormat']
        },
        footer: {order: 17},
        body_footer: {order: 18},
        sign_off: {order: 19},
        media: {},
        media_description: {}
    });

    angular.module('superdesk.workspace.content', [
        'superdesk.api',
        'superdesk.menu',
        'superdesk.archive',
        'superdesk.templates',
        'superdesk.packaging'
    ])
        .service('content', ContentService)
        .directive('sdContentCreate', ContentCreateDirective)
        .directive('sdContentSchemaEditor', ContentProfileSchemaEditor)
        .controller('ContentProfilesController', ContentProfilesController)
        .config(['superdeskProvider', function(superdesk) {
            superdesk
                .activity('/settings/content-profiles', {
                    label: gettext('Content Profiles'),
                    controller: ContentProfilesController,
                    controllerAs: 'ctrl',
                    templateUrl: 'scripts/superdesk-workspace/content/views/profile-settings.html',
                    category: superdesk.MENU_SETTINGS,
                    priority: 100,
                    privileges: {} // todo(petr): pick something
                });
        }])
        .run(['keyboardManager', 'gettext', function(keyboardManager, gettext) {
            keyboardManager.register('General', 'ctrl + m', gettext('Creates new item'));
        }])
        ;

    ContentService.$inject = ['api', 'superdesk', 'templates', 'desks', 'packages', 'archiveService'];
    function ContentService(api, superdesk, templates, desks, packages, archiveService) {

        var TEXT_TYPE = 'text';

        function newItem(type) {
            return {
                type: type || TEXT_TYPE,
                version: 0
            };
        }

        /**
         * Save data to content api
         *
         * @param {Object} data
         * @return {Promise}
         */
        function save(data) {
            return api.save('archive', data);
        }

        /**
         * Create an item of given type
         *
         * @param {string} type
         * @return {Promise}
         */
        this.createItem = function(type) {
            var item = newItem(type);
            archiveService.addTaskToArticle(item);
            return save(item);
        };

        /**
         * Create a package containing given item
         *
         * @param {Object} item
         * @return {Promise}
         */
        this.createPackageItem = function(item) {
            var data = item ? {items: [item]} : {};
            return packages.createEmptyPackage(data);
        };

        /**
         * Create a package containing given item
         *
         * @param {Object} item
         * @return {Promise}
         */
        this.createPackageFromItems = function(item) {
            return packages.createPackageFromItems([item]);
        };

        /**
         * Create new item using given template
         *
         * @param {Object} template
         * @return {Promise}
         */
        this.createItemFromTemplate = function(template) {
            var item = newItem(template.data.type || null);
            angular.extend(item, templates.pickItemData(template.data || {}), {template: template._id});
            archiveService.addTaskToArticle(item);
            return save(item).then(function(_item) {
                templates.addRecentTemplate(desks.activeDeskId, template._id);
                return _item;
            });
        };

        /**
         * Create new item using given content type
         *
         * @param {Object} contentType
         * @return {Promise}
         */
        this.createItemFromContentType = function(contentType) {
            var item = {
                type: TEXT_TYPE,
                profile: contentType._id,
                version: 0
            };

            archiveService.addTaskToArticle(item);

            return save(item);
        };

        /**
         * Creates a new content profile.
         *
         * @param {Object} data
         * @return {Promise}
         */
        this.createProfile = function(data) {
            return api.save('content_types', data);
        };

        /**
         * Creates a new content profile.
         *
         * @param {Object} item
         * @param {Object} updates
         * @return {Promise}
         */
        this.updateProfile = function(item, updates) {
            return api.update('content_types', item, updates);
        };

        /**
         * Creates a new content profile.
         *
         * @param {Object} item
         * @return {Promise}
         */
        this.removeProfile = function(item) {
            return api.remove(item, {}, 'content_types');
        };

        /**
         * Get content types from server
         *
         * @param {Boolean} includeDisabled
         * @return {Promise}
         */
        this.getTypes = function(includeDisabled) {
            var self = this;
            var params = {};

            if (!includeDisabled) {
                params = {where: {enabled: true}};
            }

            return api.query('content_types', params).then(function(result) {
                self.types = result._items.sort(function(a, b) {
                    return b.priority - a.priority; // with higher priority goes up
                });
                return self.types;
            }, function(reason) {
                self.types = [];
                return self.types;
            });
        };

        /**
         * Get content type by id
         *
         * @param {string} id
         * @return {Promise}
         */
        this.getType = function(id) {
            return api.find('content_types', id);
        };

        /**
         * Get schema for given content type
         *
         * @param {Object} contentType
         * @return {Object}
         */
        this.schema = function(contentType) {
            return contentType && contentType.schema ? angular.extend({}, contentType.schema) : DEFAULT_SCHEMA;
        };

        /**
         * Get editor config for given content type
         *
         * @param {Object} contentType
         * @return {Object}
         */
        this.editor = function(contentType) {
            return contentType && contentType.editor ? angular.extend({}, contentType.editor) : DEFAULT_EDITOR;
        };

        /**
         * Get profiles selected for given desk
         *
         * @param {Object} desk
         * @return {Promise}
         */
        this.getDeskProfiles = function(desk) {
            return this.getTypes().then(function(profiles) {
                return !desk || _.isEmpty(desk.content_profiles) ?
                    profiles :
                    profiles.filter(function(profile) {
                        return desk.content_profiles[profile._id];
                    }
                );
            });
        };
    }

    ContentCreateDirective.$inject = ['api', 'desks', 'templates', 'content', 'authoringWorkspace', 'superdesk', 'keyboardManager',
    '$location'];
    function ContentCreateDirective(api, desks, templates, content, authoringWorkspace, superdesk, keyboardManager,
        $location) {
        return {
            scope: true,
            templateUrl: 'scripts/superdesk-workspace/content/views/sd-content-create.html',
            link: function(scope) {
                var NUM_ITEMS = 5;

                /**
                 * Start editing given item in sidebar editor
                 *
                 * @param {Object} item
                 */
                function edit(item) {
                    authoringWorkspace.edit(item);
                }

                /**
                 * Create and start editing item of given type
                 *
                 * @param {string} type
                 */
                scope.create = function(type) {
                    content.createItem(type).then(edit);
                };

                /**
                 * Create and start editing a package
                 */
                scope.createPackage = function() {
                    content.createPackageItem().then(edit);
                };

                /**
                 * Do not allow packages to be created from personal workspace
                **/
                scope.canCreatePackage = function() {
                    return $location.path() !== '/workspace/personal';
                };

                /**
                 * Create and start editing an item based on given package
                 *
                 * @param {Object} template
                 */
                scope.createFromTemplate = function(template) {
                    content.createItemFromTemplate(template).then(edit).then(function() {
                        templates.getRecentTemplates(desks.activeDeskId, NUM_ITEMS)
                        .then(function(result) {
                            scope.contentTemplates = result;
                        });
                    });
                };

                /**
                 * Start content upload modal
                 */
                scope.openUpload = function openUpload() {
                    superdesk.intent('upload', 'media');
                };

                scope.contentTemplates = null;

                desks.initialize().then(function() {
                    scope.$watch(function() {
                        return desks.active.desk;
                    }, function(activeDeskId) {
                        templates.getRecentTemplates(activeDeskId, NUM_ITEMS).then(function(result) {
                            scope.contentTemplates = result;
                        });

                        content.getDeskProfiles(activeDeskId ? desks.getCurrentDesk() : null)
                            .then(function(profiles) {
                                scope.profiles = profiles;
                            });
                    });
                });

                keyboardManager.bind('ctrl+m', function(e) {
                    if (e) {
                        e.preventDefault();
                    }
                    scope.create();
                });

                scope.$on('$destroy', function() {
                    keyboardManager.unbind('ctrl+m');
                });

                /**
                 * Create a new item using given type and start editing
                 *
                 * @param {Object} contentType
                 */
                scope.createFromType = function(contentType) {
                    content.createItemFromContentType(contentType).then(edit);
                };
            }
        };
    }

    ContentProfilesController.$inject = ['$scope', 'notify', 'content', 'modal'];
    function ContentProfilesController($scope, notify, content, modal) {
        var that = this;

        // creating will be true while the modal for creating a new content
        // profile is visible.
        $scope.creating = false;

        // editing will hold data about the content profile being edited, as well
        // as the bind to the editing form. If no profile is being edited, it will
        // be null.
        $scope.editing = null;

        /**
         * @description Refreshes the list of content profiles by fetching them.
         * @returns {Promise}
         * @private
         */
        function refreshList() {
            return content.getTypes(true).then(function(types) {
                that.items = types;
            });
        }

        /**
         * @description Reports that an error has occurred.
         * @private
         */
        function reportError(resp) {
            notify.error('Operation failed (check console for response).');
            console.error(resp);
        }

        /**
         * @description Toggles the visibility of the creation modal.
         */
        this.toggleCreate = function() {
            $scope.new = {};
            $scope.creating = !$scope.creating;
        };

        /**
         * @description Toggles the visibility of the profile editing modal.
         * @param {Object} p the content profile being edited.
         */
        this.toggleEdit = function(p) {
            $scope.editing = angular.isObject(p) ? {
                form: _.cloneDeep(p),
                original: p
            } : null;
        };

        /**
         * @description Creates a new content profile.
         */
        this.save = function() {
            content.createProfile($scope.new)
                .then(refreshList, reportError)
                .then(this.toggleCreate);
        };

        /**
         * @description Commits the changes made in the editing form for a profile
         * to the server.
         */
        this.update = function() {
            var e = $scope.editing;
            var diff = {};

            Object.keys(e.form).forEach(function(k) {
                if (!_.isEqual(e.form[k], e.original[k])) {
                    diff[k] = e.form[k];
                }
            });

            content.updateProfile(e.original, diff)
                .then(refreshList, reportError)
                .then(this.toggleEdit.bind(this, null));
        };

        /**
         * @description Queries the user for confirmation and deletes the content profile.
         */
        this.delete = function(item) {
            modal.confirm('Are you sure you want to delete this profile?').then(function() {
                content.removeProfile(item)
                    .then(refreshList, reportError)
                    .then(this.toggleEdit.bind(this, null));
            }.bind(this));
        };

        refreshList();
    }

    ContentProfileSchemaEditor.$inject = ['gettext'];
    function ContentProfileSchemaEditor(gettext) {
        // labelMap maps schema entry keys to their display names.
        var labelMap = {
            'headline': gettext('Headline'),
            'slugline': gettext('Slug'),
            'genre': gettext('Genre'),
            'anpa_take_key': gettext('ANPA Take Key'),
            'place': gettext('Place'),
            'priority': gettext('Priority'),
            'urgency': gettext('Urgency'),
            'anpa_category': gettext('ANPA Category'),
            'subject': gettext('Subject'),
            'ednote': gettext('Editorial Note'),
            'abstract': gettext('Abstract'),
            'body_html': gettext('Body HTML'),
            'byline': gettext('By'),
            'dateline': gettext('Date'),
            'located': gettext('Located'),
            'sign_off': gettext('Sign Off')
        };

        return {
            restrict: 'E',
            templateUrl: 'scripts/superdesk-workspace/content/views/schema-editor.html',
            require: '^form',
            scope: {
                schema: '=ngModel',
            },
            link: function(scope, elem, attr, form) {
                /**
                 * @description label returns the display name for a key.
                 */
                scope.label = function(id) {
                    return labelMap[id];
                };

                /**
                 * @description Toggles whether a field is enabled or not.
                 * @param {String} id the key of the field to toggle.
                 */
                scope.toggle = function(id) {
                    scope.schema[id] = !!scope.schema[id] ? null : {};
                    form.$dirty = true;
                };
            }
        };
    }
})();
<commit_msg>fix(authoring): SD-4577 Added required flag for body input field<commit_after>(function() {
    'use strict';

    // http://docs.python-cerberus.org/en/stable/usage.html
    var DEFAULT_SCHEMA = Object.freeze({
        slugline: {maxlength: 24, type: 'string', required: true},
        relatedItems: {},
        genre: {type: 'list'},
        anpa_take_key: {},
        place: {type: 'list'},
        priority: {},
        urgency: {},
        anpa_category: {type: 'list', required: true},
        subject: {type: 'list', required: true},
        company_codes: {type: 'list'},
        ednote: {},
        headline: {maxlength: 64, type: 'string', required: true},
        sms: {maxlength: 160},
        abstract: {maxlength: 160, type: 'string'},
        body_html: {required: true},
        byline: {type: 'string'},
        dateline: {type: 'dict', required: true},
        sign_off: {type: 'string'},
        footer: {},
        body_footer: {},
        media: {},
        media_description: {}
    });

    var DEFAULT_EDITOR = Object.freeze({
        slugline: {order: 1, sdWidth: 'full'},
        genre: {order: 2, sdWidth: 'half'},
        anpa_take_key: {order: 3, sdWidth: 'half'},
        place: {order: 4, sdWidth: 'half'},
        priority: {order: 5, sdWidth: 'quarter'},
        urgency: {order: 6, sdWidth: 'quarter'},
        anpa_category: {order: 7, sdWidth: 'full'},
        subject: {order: 8, sdWidth: 'full'},
        company_codes: {order: 9, sdWidth: 'full'},
        ednote: {order: 10, sdWidth: 'full'},
        headline: {order: 11, formatOptions: ['underline', 'anchor', 'bold', 'removeFormat']},
        sms: {order: 12},
        abstract: {order: 13, formatOptions: ['bold', 'italic', 'underline', 'anchor', 'removeFormat']},
        byline: {order: 14},
        dateline: {order: 15},
        body_html: {
            order: 16,
            formatOptions: ['h2', 'bold', 'italic', 'underline', 'quote', 'anchor', 'embed', 'picture', 'removeFormat']
        },
        footer: {order: 17},
        body_footer: {order: 18},
        sign_off: {order: 19},
        media: {},
        media_description: {}
    });

    angular.module('superdesk.workspace.content', [
        'superdesk.api',
        'superdesk.menu',
        'superdesk.archive',
        'superdesk.templates',
        'superdesk.packaging'
    ])
        .service('content', ContentService)
        .directive('sdContentCreate', ContentCreateDirective)
        .directive('sdContentSchemaEditor', ContentProfileSchemaEditor)
        .controller('ContentProfilesController', ContentProfilesController)
        .config(['superdeskProvider', function(superdesk) {
            superdesk
                .activity('/settings/content-profiles', {
                    label: gettext('Content Profiles'),
                    controller: ContentProfilesController,
                    controllerAs: 'ctrl',
                    templateUrl: 'scripts/superdesk-workspace/content/views/profile-settings.html',
                    category: superdesk.MENU_SETTINGS,
                    priority: 100,
                    privileges: {} // todo(petr): pick something
                });
        }])
        .run(['keyboardManager', 'gettext', function(keyboardManager, gettext) {
            keyboardManager.register('General', 'ctrl + m', gettext('Creates new item'));
        }])
        ;

    ContentService.$inject = ['api', 'superdesk', 'templates', 'desks', 'packages', 'archiveService'];
    function ContentService(api, superdesk, templates, desks, packages, archiveService) {

        var TEXT_TYPE = 'text';

        function newItem(type) {
            return {
                type: type || TEXT_TYPE,
                version: 0
            };
        }

        /**
         * Save data to content api
         *
         * @param {Object} data
         * @return {Promise}
         */
        function save(data) {
            return api.save('archive', data);
        }

        /**
         * Create an item of given type
         *
         * @param {string} type
         * @return {Promise}
         */
        this.createItem = function(type) {
            var item = newItem(type);
            archiveService.addTaskToArticle(item);
            return save(item);
        };

        /**
         * Create a package containing given item
         *
         * @param {Object} item
         * @return {Promise}
         */
        this.createPackageItem = function(item) {
            var data = item ? {items: [item]} : {};
            return packages.createEmptyPackage(data);
        };

        /**
         * Create a package containing given item
         *
         * @param {Object} item
         * @return {Promise}
         */
        this.createPackageFromItems = function(item) {
            return packages.createPackageFromItems([item]);
        };

        /**
         * Create new item using given template
         *
         * @param {Object} template
         * @return {Promise}
         */
        this.createItemFromTemplate = function(template) {
            var item = newItem(template.data.type || null);
            angular.extend(item, templates.pickItemData(template.data || {}), {template: template._id});
            archiveService.addTaskToArticle(item);
            return save(item).then(function(_item) {
                templates.addRecentTemplate(desks.activeDeskId, template._id);
                return _item;
            });
        };

        /**
         * Create new item using given content type
         *
         * @param {Object} contentType
         * @return {Promise}
         */
        this.createItemFromContentType = function(contentType) {
            var item = {
                type: TEXT_TYPE,
                profile: contentType._id,
                version: 0
            };

            archiveService.addTaskToArticle(item);

            return save(item);
        };

        /**
         * Creates a new content profile.
         *
         * @param {Object} data
         * @return {Promise}
         */
        this.createProfile = function(data) {
            return api.save('content_types', data);
        };

        /**
         * Creates a new content profile.
         *
         * @param {Object} item
         * @param {Object} updates
         * @return {Promise}
         */
        this.updateProfile = function(item, updates) {
            return api.update('content_types', item, updates);
        };

        /**
         * Creates a new content profile.
         *
         * @param {Object} item
         * @return {Promise}
         */
        this.removeProfile = function(item) {
            return api.remove(item, {}, 'content_types');
        };

        /**
         * Get content types from server
         *
         * @param {Boolean} includeDisabled
         * @return {Promise}
         */
        this.getTypes = function(includeDisabled) {
            var self = this;
            var params = {};

            if (!includeDisabled) {
                params = {where: {enabled: true}};
            }

            return api.query('content_types', params).then(function(result) {
                self.types = result._items.sort(function(a, b) {
                    return b.priority - a.priority; // with higher priority goes up
                });
                return self.types;
            }, function(reason) {
                self.types = [];
                return self.types;
            });
        };

        /**
         * Get content type by id
         *
         * @param {string} id
         * @return {Promise}
         */
        this.getType = function(id) {
            return api.find('content_types', id);
        };

        /**
         * Get schema for given content type
         *
         * @param {Object} contentType
         * @return {Object}
         */
        this.schema = function(contentType) {
            return contentType && contentType.schema ? angular.extend({}, contentType.schema) : DEFAULT_SCHEMA;
        };

        /**
         * Get editor config for given content type
         *
         * @param {Object} contentType
         * @return {Object}
         */
        this.editor = function(contentType) {
            return contentType && contentType.editor ? angular.extend({}, contentType.editor) : DEFAULT_EDITOR;
        };

        /**
         * Get profiles selected for given desk
         *
         * @param {Object} desk
         * @return {Promise}
         */
        this.getDeskProfiles = function(desk) {
            return this.getTypes().then(function(profiles) {
                return !desk || _.isEmpty(desk.content_profiles) ?
                    profiles :
                    profiles.filter(function(profile) {
                        return desk.content_profiles[profile._id];
                    }
                );
            });
        };
    }

    ContentCreateDirective.$inject = ['api', 'desks', 'templates', 'content', 'authoringWorkspace', 'superdesk', 'keyboardManager',
    '$location'];
    function ContentCreateDirective(api, desks, templates, content, authoringWorkspace, superdesk, keyboardManager,
        $location) {
        return {
            scope: true,
            templateUrl: 'scripts/superdesk-workspace/content/views/sd-content-create.html',
            link: function(scope) {
                var NUM_ITEMS = 5;

                /**
                 * Start editing given item in sidebar editor
                 *
                 * @param {Object} item
                 */
                function edit(item) {
                    authoringWorkspace.edit(item);
                }

                /**
                 * Create and start editing item of given type
                 *
                 * @param {string} type
                 */
                scope.create = function(type) {
                    content.createItem(type).then(edit);
                };

                /**
                 * Create and start editing a package
                 */
                scope.createPackage = function() {
                    content.createPackageItem().then(edit);
                };

                /**
                 * Do not allow packages to be created from personal workspace
                **/
                scope.canCreatePackage = function() {
                    return $location.path() !== '/workspace/personal';
                };

                /**
                 * Create and start editing an item based on given package
                 *
                 * @param {Object} template
                 */
                scope.createFromTemplate = function(template) {
                    content.createItemFromTemplate(template).then(edit).then(function() {
                        templates.getRecentTemplates(desks.activeDeskId, NUM_ITEMS)
                        .then(function(result) {
                            scope.contentTemplates = result;
                        });
                    });
                };

                /**
                 * Start content upload modal
                 */
                scope.openUpload = function openUpload() {
                    superdesk.intent('upload', 'media');
                };

                scope.contentTemplates = null;

                desks.initialize().then(function() {
                    scope.$watch(function() {
                        return desks.active.desk;
                    }, function(activeDeskId) {
                        templates.getRecentTemplates(activeDeskId, NUM_ITEMS).then(function(result) {
                            scope.contentTemplates = result;
                        });

                        content.getDeskProfiles(activeDeskId ? desks.getCurrentDesk() : null)
                            .then(function(profiles) {
                                scope.profiles = profiles;
                            });
                    });
                });

                keyboardManager.bind('ctrl+m', function(e) {
                    if (e) {
                        e.preventDefault();
                    }
                    scope.create();
                });

                scope.$on('$destroy', function() {
                    keyboardManager.unbind('ctrl+m');
                });

                /**
                 * Create a new item using given type and start editing
                 *
                 * @param {Object} contentType
                 */
                scope.createFromType = function(contentType) {
                    content.createItemFromContentType(contentType).then(edit);
                };
            }
        };
    }

    ContentProfilesController.$inject = ['$scope', 'notify', 'content', 'modal'];
    function ContentProfilesController($scope, notify, content, modal) {
        var that = this;

        // creating will be true while the modal for creating a new content
        // profile is visible.
        $scope.creating = false;

        // editing will hold data about the content profile being edited, as well
        // as the bind to the editing form. If no profile is being edited, it will
        // be null.
        $scope.editing = null;

        /**
         * @description Refreshes the list of content profiles by fetching them.
         * @returns {Promise}
         * @private
         */
        function refreshList() {
            return content.getTypes(true).then(function(types) {
                that.items = types;
            });
        }

        /**
         * @description Reports that an error has occurred.
         * @private
         */
        function reportError(resp) {
            notify.error('Operation failed (check console for response).');
            console.error(resp);
        }

        /**
         * @description Toggles the visibility of the creation modal.
         */
        this.toggleCreate = function() {
            $scope.new = {};
            $scope.creating = !$scope.creating;
        };

        /**
         * @description Toggles the visibility of the profile editing modal.
         * @param {Object} p the content profile being edited.
         */
        this.toggleEdit = function(p) {
            $scope.editing = angular.isObject(p) ? {
                form: _.cloneDeep(p),
                original: p
            } : null;
        };

        /**
         * @description Creates a new content profile.
         */
        this.save = function() {
            content.createProfile($scope.new)
                .then(refreshList, reportError)
                .then(this.toggleCreate);
        };

        /**
         * @description Commits the changes made in the editing form for a profile
         * to the server.
         */
        this.update = function() {
            var e = $scope.editing;
            var diff = {};

            Object.keys(e.form).forEach(function(k) {
                if (!_.isEqual(e.form[k], e.original[k])) {
                    diff[k] = e.form[k];
                }
            });

            content.updateProfile(e.original, diff)
                .then(refreshList, reportError)
                .then(this.toggleEdit.bind(this, null));
        };

        /**
         * @description Queries the user for confirmation and deletes the content profile.
         */
        this.delete = function(item) {
            modal.confirm('Are you sure you want to delete this profile?').then(function() {
                content.removeProfile(item)
                    .then(refreshList, reportError)
                    .then(this.toggleEdit.bind(this, null));
            }.bind(this));
        };

        refreshList();
    }

    ContentProfileSchemaEditor.$inject = ['gettext'];
    function ContentProfileSchemaEditor(gettext) {
        // labelMap maps schema entry keys to their display names.
        var labelMap = {
            'headline': gettext('Headline'),
            'slugline': gettext('Slug'),
            'genre': gettext('Genre'),
            'anpa_take_key': gettext('ANPA Take Key'),
            'place': gettext('Place'),
            'priority': gettext('Priority'),
            'urgency': gettext('Urgency'),
            'anpa_category': gettext('ANPA Category'),
            'subject': gettext('Subject'),
            'ednote': gettext('Editorial Note'),
            'abstract': gettext('Abstract'),
            'body_html': gettext('Body HTML'),
            'byline': gettext('By'),
            'dateline': gettext('Date'),
            'located': gettext('Located'),
            'sign_off': gettext('Sign Off')
        };

        return {
            restrict: 'E',
            templateUrl: 'scripts/superdesk-workspace/content/views/schema-editor.html',
            require: '^form',
            scope: {
                schema: '=ngModel',
            },
            link: function(scope, elem, attr, form) {
                /**
                 * @description label returns the display name for a key.
                 */
                scope.label = function(id) {
                    return labelMap[id];
                };

                /**
                 * @description Toggles whether a field is enabled or not.
                 * @param {String} id the key of the field to toggle.
                 */
                scope.toggle = function(id) {
                    scope.schema[id] = !!scope.schema[id] ? null : {};
                    form.$dirty = true;
                };
            }
        };
    }
})();
<|endoftext|>


<commit_before>const easingCache = 3
const easingFraction = 0.95
const easingAccelerator = 1.5
const quadraticEasing = 0.5
const abs = Math.abs

const bounds = (target, val) => {
  if (val < -target._height) {
    // target._easing = false
    return -target._height
  } else if (val > 0) {
    // target._easing = false
    return 0
  } else {
    return val
  }
}

const easeOut = (target, distance, original, event, stamp, easingFraction, setVal) => {
  if (target._easing) {
    // maybe stop when 2 ticks are same value
    target._ly = setVal(target, target._ly + distance * (1 - easingFraction), original, event, stamp)
    if (distance > 0.5 || distance < -0.5) {
      target._isEasing = global.requestAnimationFrame(() => easeOut(target, distance * easingFraction, original, event, stamp, easingFraction, setVal))
    } else {
      target._easing = false
    }
  }
}

const setValX = (target, val, original, event, stamp) => {
  val = bounds(target, val)
  target.style.transform = `translate3d(${val}rem, 0, 0)`
  if (!original) {
    original = target
  }
  if (original._ && original._._scrollListener) {
    original._._scrollListener({ x: val, target: original, scroller: target, state: event.state }, stamp)
  }
  return val
}

const setValY = (target, val, original, event, stamp) => {
  val = bounds(target, val)
  target.style.transform = `translate3d(0, ${val}rem, 0)`
  if (!original) {
    original = target
  }

  if (original._ && original._._scrollListener) {
    original._._scrollListener({ y: val, target: original, scroller: target, state: event.state }, stamp)
  }
  return val
}

const touchstart = ({ target, event }, x, y, ch, sh) => {
  global.cancelAnimationFrame(target._isEasing)

  if (ch >= sh) {
    target._block = true
    target.__init = false
    return true
  }

  target.__init = true
  target._start = y
  target._y = target._ly || 0
  target._easing = false
  target._prev = [ 1, 0, 0, 0 ]
  target._height = sh - ch
  target._block = ch >= sh
  target._sh = sh
  target._ey = y
  target._ex = x
}

const touchmove = (event, x, y, stamp, setVal) => {
  const target = event.target
  if (
    target._block ||
    abs(target._ey - y) <= abs(target._ex - x)
  ) {
    return true
  }
  event.prevent = true
  const original = event.original
  const index = target._prev[0]
  target._prev[0]++
  if (target._prev[0] > easingCache) {
    target._prev[0] = 1
  }
  const val = y - target._start + target._y
  target._prev[index] = val - (target._ly || 0)
  target._ly = setVal(target, val, original, event, stamp)
  target._ey = y
  target._ex = x
}

const touchend = (event, stamp, setVal) => {
  const target = event.target
  target.__init = false
  if (!target._prev) return
  const original = event.original
  var delta = 0
  var i = easingCache
  while (i--) {
    delta += target._prev[i] || 0
  }
  delta = (delta / easingCache) * easingAccelerator
  const sing = delta < 0 ? -1 : 1
  var distance = quadraticEasing * ((delta * delta) * sing)
  if (distance > 750) {
    distance = 750
  }
  target._easing = true
  easeOut(target, distance, original, event, stamp, easingFraction, setVal)
}

const lookupMode = [1.0, 28.0, 500.0]

const wheelX = (event, stamp, sh) => {
  const evt = event.event

  if ('deltaX' in evt) {
    if (abs(evt.deltaX) <= abs(evt.deltaY)) {
      return
    } else {
      event.prevent = true
      evt.preventDefault()
    }
    const mode = lookupMode[evt.deltaMode] || lookupMode[0]
    event.x = evt.deltaX * mode * -1
  } else {
    // is this ok on x?
    event.x = evt.wheelDelta / -3
  }

  const target = event.target
  if (!target.__init) {
    if (!target._ly) {
      target._ly = 0
    }
    if (touchstart(event, event.y, event.x, event.target.parentNode.clientWidth, sh)) {
      return
    }
  }
  clearTimeout(target._timeout)
  target._timeout = setTimeout(() => {
    if (target.offsetParent !== null) {
      target.__init = false
    }
  }, 20)
  target._ly = setValX(target, target._ly + event.x, event.original, event, stamp)
}

const wheelY = (event, stamp, sh) => {
  event.prevent = true
  const evt = event.event
  evt.preventDefault()
  if ('deltaY' in evt) {
    if (abs(evt.deltaX) >= abs(evt.deltaY)) {
      return
    } else {
      event.prevent = true
      evt.preventDefault()
    }
    const mode = lookupMode[evt.deltaMode] || lookupMode[0]
    event.y = evt.deltaY * mode * -1
  } else {
    event.y = evt.wheelDelta / -3
  }
  const target = event.target
  if (!target.__init) {
    if (!target._ly) {
      target._ly = 0
    }
    if (touchstart(event, event.x, event.y, event.target.parentNode.clientHeight, sh)) {
      return
    }
  }
  clearTimeout(target._timeout)
  target._timeout = setTimeout(() => {
    if (target.offsetParent !== null) {
      target.__init = false
    }
  }, 20)
  target._ly = setValY(target, target._ly + event.y, event.original, event, stamp)
}

export default {
  props: {
    scroll: (t, val) => {
      var fn, target, size, direction

      if (!val) return
      if (typeof val === 'function') {
        fn = val
      } else if (typeof val === 'object') {
        if (val.target) target = val.target
        fn = val.onScroll
        direction = val.direction
        size = val.size
      }

      t.set({
        define: {
          hasScrollY: true
        }
      }, false)

      if (fn) {
        t.set({
          define: {
            _scrollListener: fn
          }
        }, false)
      }

      if (!direction) {
        direction = 'y'
      }

      if (!size) {
        size = direction === 'y'
          ? (val) => val.target.scrollHeight
          : (val) => val.target.scrollWidth
      }

      if (!target) {
        target = t => t
      }

      t.set({
        define: {
          setScroll (y, t, stamp) {
            const rt = target(t)
            const event = {
              original: t,
              target: rt,
              state: t._s
            }
            global.cancelAnimationFrame(rt._isEasing)
            if (!rt._ly) rt._ly = 0
            if (direction === 'y') {
              rt._height = size(event) - rt.parentNode.clientHeight
              rt._ly = setValY(rt, bounds(rt, -y) - rt._ly, t, event, stamp)
            } else {
              rt._height = size(event) - rt.parentNode.clientWidth
              rt._ly = setValX(rt, bounds(rt, -y) - rt._ly, t, event, stamp)
            }
          },
          easeScroll (y, t, stamp) {
            // if its scrolling from the fingers dont do it
            const rt = target(t)
            const event = {
              original: t,
              target: rt,
              state: t._s
            }
            global.cancelAnimationFrame(rt._isEasing)
            rt._easing = true
            if (!rt._ly) rt._ly = 0
            if (direction === 'y') {
              rt._height = size(event) - rt.parentNode.clientHeight
              easeOut(rt, bounds(rt, -y) - rt._ly, t, event, stamp, 0.9, setValY)
            } else {
              rt._height = size(event) - rt.parentNode.clientWidth
              easeOut(rt, bounds(rt, -y) - rt._ly, t, event, stamp, 0.9, setValX)
            }
          }
        },
        on: {
          touchstart: {
            scroll: direction === 'y' ? (val, stamp) => {
              val.target = target(val.target)
              touchstart(val, val.x, val.y, val.target.parentNode.clientHeight, size(val))
            } : (val, stamp) => {
              val.target = target(val.target)
              touchstart(val, val.y, val.x, val.target.parentNode.clientWidth, size(val))
            }
          },
          touchmove: {
            scroll: direction === 'y' ? (val, stamp) => {
              val.original = val.target
              val.target = target(val.target)
              touchmove(val, val.x, val.y, stamp, setValY)
            } : (val, stamp) => {
              val.original = val.target
              val.target = target(val.target)
              touchmove(val, val.y, val.x, stamp, setValX)
            }
          },
          touchend: {
            scroll: direction === 'y' ? (val, stamp) => {
              val.original = val.target
              val.target = target(val.target)
              touchend(val, stamp, setValY)
            } : (val, stamp) => {
              val.original = val.target
              val.target = target(val.target)
              touchend(val, stamp, setValX)
            }
          },
          wheel: {
            scroll: direction === 'y' ? (val, stamp) => {
              val.original = val.target
              val.target = target(val.target)
              wheelY(val, stamp, size(val))
            } : (val, stamp) => {
              val.original = val.target
              val.target = target(val.target)
              wheelX(val, stamp, size(val))
            }
          }
        }
      }, false)
    }
  }
}
<commit_msg>updates<commit_after>const easingCache = 3
const easingFraction = 0.95
const easingAccelerator = 1.5
const quadraticEasing = 0.5
const abs = Math.abs

const bounds = (target, val) => {
  if (val < -target._height) {
    // target._easing = false
    return -target._height
  } else if (val > 0) {
    // target._easing = false
    return 0
  } else {
    return val
  }
}

const easeOut = (target, distance, original, event, stamp, easingFraction, setVal) => {
  if (target._easing) {
    // maybe stop when 2 ticks are same value
    target._ly = setVal(target, target._ly + distance * (1 - easingFraction), original, event, stamp)
    if (distance > 0.5 || distance < -0.5) {
      target._isEasing = global.requestAnimationFrame(() => easeOut(target, distance * easingFraction, original, event, stamp, easingFraction, setVal))
    } else {
      target._easing = false
    }
  }
}

const setValX = (target, val, original, event, stamp) => {
  val = bounds(target, val)
  target.style.transform = `translate3d(${val}px, 0, 0)`
  if (!original) {
    original = target
  }
  if (original._ && original._._scrollListener) {
    original._._scrollListener({ x: val, target: original, scroller: target, state: event.state }, stamp)
  }
  return val
}

const setValY = (target, val, original, event, stamp) => {
  val = bounds(target, val)
  target.style.transform = `translate3d(0, ${val}px, 0)`
  if (!original) {
    original = target
  }

  if (original._ && original._._scrollListener) {
    original._._scrollListener({ y: val, target: original, scroller: target, state: event.state }, stamp)
  }
  return val
}

const touchstart = ({ target, event }, x, y, ch, sh) => {
  global.cancelAnimationFrame(target._isEasing)

  if (ch >= sh) {
    target._block = true
    target.__init = false
    return true
  }

  target.__init = true
  target._start = y
  target._y = target._ly || 0
  target._easing = false
  target._prev = [ 1, 0, 0, 0 ]
  target._height = sh - ch
  console.log(sh, ch)
  target._block = ch >= sh
  target._sh = sh
  target._ey = y
  target._ex = x
}

const touchmove = (event, x, y, stamp, setVal) => {
  const target = event.target
  if (
    target._block ||
    abs(target._ey - y) <= abs(target._ex - x)
  ) {
    return true
  }
  event.prevent = true
  const original = event.original
  const index = target._prev[0]
  target._prev[0]++
  if (target._prev[0] > easingCache) {
    target._prev[0] = 1
  }
  const val = y - target._start + target._y
  target._prev[index] = val - (target._ly || 0)
  target._ly = setVal(target, val, original, event, stamp)
  target._ey = y
  target._ex = x
}

const touchend = (event, stamp, setVal) => {
  const target = event.target
  target.__init = false
  if (!target._prev) return
  const original = event.original
  var delta = 0
  var i = easingCache
  while (i--) {
    delta += target._prev[i] || 0
  }
  delta = (delta / easingCache) * easingAccelerator
  const sing = delta < 0 ? -1 : 1
  var distance = quadraticEasing * ((delta * delta) * sing)
  if (distance > 750) {
    distance = 750
  }
  target._easing = true
  easeOut(target, distance, original, event, stamp, easingFraction, setVal)
}

const lookupMode = [1.0, 28.0, 500.0]

const wheelX = (event, stamp, sh) => {
  const evt = event.event
  evt.preventDefault()
  if ('deltaX' in evt) {
    if (abs(evt.deltaX) <= abs(evt.deltaY)) {
      return
    } else {
      event.prevent = true
    }
    const mode = lookupMode[evt.deltaMode] || lookupMode[0]
    event.x = evt.deltaX * mode * -1
  } else {
    // is this ok on x?
    event.x = evt.wheelDelta / -3
  }

  const target = event.target
  if (!target.__init) {
    if (!target._ly) {
      target._ly = 0
    }
    console.log('-->', event.target.parentNode.clientWidth, event.target.parentNode)
    if (touchstart(event, event.y, event.x, event.target.parentNode.clientWidth, sh)) {
      return
    }
  }
  clearTimeout(target._timeout)
  target._timeout = setTimeout(() => {
    if (target.offsetParent !== null) {
      target.__init = false
    }
  }, 20)
  target._ly = setValX(target, target._ly + event.x, event.original, event, stamp)
}

const wheelY = (event, stamp, sh) => {
  event.prevent = true
  const evt = event.event
  evt.preventDefault()
  if ('deltaY' in evt) {
    if (abs(evt.deltaX) >= abs(evt.deltaY)) {
      return
    } else {
      event.prevent = true
      evt.preventDefault()
    }
    const mode = lookupMode[evt.deltaMode] || lookupMode[0]
    event.y = evt.deltaY * mode * -1
  } else {
    event.y = evt.wheelDelta / -3
  }
  const target = event.target
  if (!target.__init) {
    if (!target._ly) {
      target._ly = 0
    }
    if (touchstart(event, event.x, event.y, event.target.parentNode.clientHeight, sh)) {
      return
    }
  }
  clearTimeout(target._timeout)
  target._timeout = setTimeout(() => {
    if (target.offsetParent !== null) {
      target.__init = false
    }
  }, 20)
  target._ly = setValY(target, target._ly + event.y, event.original, event, stamp)
}

export default {
  props: {
    scroll: (t, val) => {
      var fn, target, size, direction

      if (!val) return
      if (typeof val === 'function') {
        fn = val
      } else if (typeof val === 'object') {
        if (val.target) target = val.target
        fn = val.onScroll
        direction = val.direction
        size = val.size
      }

      t.set({
        define: {
          hasScrollY: true
        }
      }, false)

      if (fn) {
        t.set({
          define: {
            _scrollListener: fn
          }
        }, false)
      }

      if (!direction) {
        direction = 'y'
      }

      if (!size) {
        size = direction === 'y'
          ? (val) => val.target.scrollHeight
          : (val) => val.target.scrollWidth
      }

      if (!target) {
        target = t => t
      }

      t.set({
        define: {
          setScroll (y, t, stamp) {
            const rt = target(t)
            const event = {
              original: t,
              target: rt,
              state: t._s
            }
            global.cancelAnimationFrame(rt._isEasing)
            if (!rt._ly) rt._ly = 0
            if (direction === 'y') {
              rt._height = size(event) - rt.parentNode.clientHeight
              rt._ly = setValY(rt, bounds(rt, -y) - rt._ly, t, event, stamp)
            } else {
              rt._height = size(event) - rt.parentNode.clientWidth
              rt._ly = setValX(rt, bounds(rt, -y) - rt._ly, t, event, stamp)
            }
          },
          easeScroll (y, t, stamp) {
            // if its scrolling from the fingers dont do it
            const rt = target(t)
            const event = {
              original: t,
              target: rt,
              state: t._s
            }
            global.cancelAnimationFrame(rt._isEasing)
            rt._easing = true
            if (!rt._ly) rt._ly = 0
            if (direction === 'y') {
              rt._height = size(event) - rt.parentNode.clientHeight
              easeOut(rt, bounds(rt, -y) - rt._ly, t, event, stamp, 0.9, setValY)
            } else {
              rt._height = size(event) - rt.parentNode.clientWidth
              easeOut(rt, bounds(rt, -y) - rt._ly, t, event, stamp, 0.9, setValX)
            }
          }
        },
        on: {
          touchstart: {
            scroll: direction === 'y' ? (val, stamp) => {
              val.target = target(val.target)
              touchstart(val, val.x, val.y, val.target.parentNode.clientHeight, size(val))
            } : (val, stamp) => {
              val.target = target(val.target)
              touchstart(val, val.y, val.x, val.target.parentNode.clientWidth, size(val))
            }
          },
          touchmove: {
            scroll: direction === 'y' ? (val, stamp) => {
              val.original = val.target
              val.target = target(val.target)
              touchmove(val, val.x, val.y, stamp, setValY)
            } : (val, stamp) => {
              val.original = val.target
              val.target = target(val.target)
              touchmove(val, val.y, val.x, stamp, setValX)
            }
          },
          touchend: {
            scroll: direction === 'y' ? (val, stamp) => {
              val.original = val.target
              val.target = target(val.target)
              touchend(val, stamp, setValY)
            } : (val, stamp) => {
              val.original = val.target
              val.target = target(val.target)
              touchend(val, stamp, setValX)
            }
          },
          wheel: {
            scroll: direction === 'y' ? (val, stamp) => {
              val.original = val.target
              val.target = target(val.target)
              wheelY(val, stamp, size(val))
            } : (val, stamp) => {
              val.original = val.target
              val.target = target(val.target)
              wheelX(val, stamp, size(val))
            }
          }
        }
      }, false)
    }
  }
}
<|endoftext|>


<commit_before>// @flow

import React, { Component } from 'react';
import { View, Animated, StyleSheet, ScrollView, Dimensions } from 'react-native';
import AnimatedOverlay from 'react-native-animated-overlay';

import Animation from './Animation';

const { width: WIDTH, height: HEIGHT } = Dimensions.get('window');

// action sheet states
const ACTION_SHEET_OPENING: string = 'opening';
const ACTION_SHEET_OPENED: string = 'opened';
const ACTION_SHEET_CLOSING: string = 'closing';
const ACTION_SHEET_CLOSED: string = 'closed';

const DEFAULT_ANIMATION_DURATION: number = 250;

const INITIAL_TOP_POSITION: number = -180;
const INITIAL_BOTTOM_POSITION: number = HEIGHT * -1;

const styles = StyleSheet.create({
  container: {
    position: 'absolute',
    top: 0,
    left: 0,
    backgroundColor: 'white',
  },
  contentContainer: {
    width: WIDTH,
    position: 'absolute',
    backgroundColor: 'white',
  },
  scrollView: {
  },
});

type Props = {
  onShow?: () => void;
  onHide?: () => void;
  show?: boolean;
  animationDuration?: number;
  overlayOpacity?: number;
  position?: 'top' | 'bottom';
  children?: any;
};

const defaultProps = {
  onShow: () => {},
  onHide: () => {},
  show: false,
  animationDuration: DEFAULT_ANIMATION_DURATION,
  overlayOpacity: 0.3,
  position: 'top',
  children: null,
};

class ActionSheet extends Component {
  props: Props

  static defaultProps = defaultProps

  constructor(props: Props) {
    super(props);

    this.state = {
      show: props.show,
      actionSheetState: ACTION_SHEET_CLOSED,
      actionSheetAnimation: new Animation(this.hideActionSheetPosition),
    };
  }

  componentDidMount() {
    if (this.props.show) {
      this.show();
    }
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.show !== nextProps.show) {
      if (nextProps.show) {
        this.show();
      } else {
        this.hide();
      }
    }
  }

  get showActionSheetPosition(): string {
    const { position } = this.props;
    if (position === 'top') {
      return INITIAL_TOP_POSITION * -1;
    }
    return 0;
  }

  get hideActionSheetPosition(): string {
    const { position } = this.props;
    if (position === 'top') {
      return INITIAL_TOP_POSITION;
    }
    return INITIAL_BOTTOM_POSITION * -1;
  }

  setActionSheetState(toValue: number, callback?: Function = () => {}): void {
    const { animationDuration } = this.props;
    const isClosed = (this.state.actionSheetState === ACTION_SHEET_CLOSED);

    let actionSheetState = isClosed ? ACTION_SHEET_OPENING : ACTION_SHEET_CLOSING;

    this.setState({ actionSheetState });

    this.state.actionSheetAnimation.toValue(toValue, animationDuration, () => {
      const isClosing = (this.state.actionSheetState === ACTION_SHEET_CLOSING);
      actionSheetState = isClosing ? ACTION_SHEET_CLOSED : ACTION_SHEET_OPENED;

      this.setState({ actionSheetState });
      callback();
    });
  }

  onOverlayPress = (): void => {
    this.hide();
  }

  show = (callback?: Function = () => {}): void => {
    if ([ACTION_SHEET_OPENING, ACTION_SHEET_OPENED].includes(this.state.actionSheetState)) {
      return;
    }

    const { onShow } = this.props;

    this.setState({ show: true });
    this.setActionSheetState(this.showActionSheetPosition);
    onShow();
    callback();
  }

  hide = (callback?: Function = () => {}): void => {
    if ([ACTION_SHEET_CLOSING, ACTION_SHEET_CLOSED].includes(this.state.actionSheetState)) {
      return;
    }

    const { onHide } = this.props;

    this.setState({ show: false });
    this.setActionSheetState(this.hideActionSheetPosition);
    onHide();
    callback();
  }

  render() {
    const { children, animationDuration, overlayOpacity, position } = this.props;
    const { actionSheetState, actionSheetAnimation: { animations } } = this.state;

    const overlayShow = [ACTION_SHEET_OPENED, ACTION_SHEET_OPENING].includes(actionSheetState);

    const contentPosition = (position === 'top')
      ? { top: INITIAL_TOP_POSITION }
      : { bottom: INITIAL_BOTTOM_POSITION };

    const scrollView = (position === 'top')
      ? { paddingTop: 30 }
      : null;

    return (
      <View style={[styles.container]}>
        <AnimatedOverlay
          onPress={this.onOverlayPress}
          overlayShow={overlayShow}
          duration={animationDuration}
          opacity={overlayOpacity}
        />
        <Animated.View
          style={[styles.contentContainer, contentPosition, animations]}
        >
          <ScrollView style={[styles.scrollView, scrollView]}>
            {children}
          </ScrollView>
        </Animated.View>
      </View>
    );
  }
}

export default ActionSheet;
<commit_msg>disable overlay touch event until action sheet opened<commit_after>// @flow

import React, { Component } from 'react';
import { View, Animated, StyleSheet, ScrollView, Dimensions } from 'react-native';
import AnimatedOverlay from 'react-native-animated-overlay';

import Animation from './Animation';

const { width: WIDTH, height: HEIGHT } = Dimensions.get('window');

// action sheet states
const ACTION_SHEET_OPENING: string = 'opening';
const ACTION_SHEET_OPENED: string = 'opened';
const ACTION_SHEET_CLOSING: string = 'closing';
const ACTION_SHEET_CLOSED: string = 'closed';

const DEFAULT_ANIMATION_DURATION: number = 250;

const INITIAL_TOP_POSITION: number = -180;
const INITIAL_BOTTOM_POSITION: number = HEIGHT * -1;

const styles = StyleSheet.create({
  container: {
    position: 'absolute',
    top: 0,
    left: 0,
    backgroundColor: 'white',
  },
  contentContainer: {
    width: WIDTH,
    position: 'absolute',
    backgroundColor: 'white',
  },
  scrollView: {
  },
});

type Props = {
  onShow?: () => void;
  onHide?: () => void;
  show?: boolean;
  animationDuration?: number;
  overlayOpacity?: number;
  position?: 'top' | 'bottom';
  children?: any;
};

const defaultProps = {
  onShow: () => {},
  onHide: () => {},
  show: false,
  animationDuration: DEFAULT_ANIMATION_DURATION,
  overlayOpacity: 0.3,
  position: 'top',
  children: null,
};

class ActionSheet extends Component {
  props: Props

  static defaultProps = defaultProps

  constructor(props: Props) {
    super(props);

    this.state = {
      show: props.show,
      actionSheetState: ACTION_SHEET_CLOSED,
      actionSheetAnimation: new Animation(this.hideActionSheetPosition),
    };
  }

  componentDidMount() {
    if (this.props.show) {
      this.show();
    }
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.show !== nextProps.show) {
      if (nextProps.show) {
        this.show();
      } else {
        this.hide();
      }
    }
  }

  get showActionSheetPosition(): string {
    const { position } = this.props;
    if (position === 'top') {
      return INITIAL_TOP_POSITION * -1;
    }
    return 0;
  }

  get hideActionSheetPosition(): string {
    const { position } = this.props;
    if (position === 'top') {
      return INITIAL_TOP_POSITION;
    }
    return INITIAL_BOTTOM_POSITION * -1;
  }

  setActionSheetState(toValue: number, callback?: Function = () => {}): void {
    const { animationDuration } = this.props;
    const isClosed = (this.state.actionSheetState === ACTION_SHEET_CLOSED);

    let actionSheetState = isClosed ? ACTION_SHEET_OPENING : ACTION_SHEET_CLOSING;

    this.setState({ actionSheetState });

    this.state.actionSheetAnimation.toValue(toValue, animationDuration, () => {
      const isClosing = (this.state.actionSheetState === ACTION_SHEET_CLOSING);
      actionSheetState = isClosing ? ACTION_SHEET_CLOSED : ACTION_SHEET_OPENED;

      this.setState({ actionSheetState });
      callback();
    });
  }

  onOverlayPress = (): void => {
    this.hide();
  }

  show = (callback?: Function = () => {}): void => {
    if ([ACTION_SHEET_OPENING, ACTION_SHEET_OPENED].includes(this.state.actionSheetState)) {
      return;
    }

    const { onShow } = this.props;

    this.setState({ show: true });
    this.setActionSheetState(this.showActionSheetPosition);
    onShow();
    callback();
  }

  hide = (callback?: Function = () => {}): void => {
    if ([ACTION_SHEET_CLOSING, ACTION_SHEET_CLOSED].includes(this.state.actionSheetState)) {
      return;
    }

    const { onHide } = this.props;

    this.setState({ show: false });
    this.setActionSheetState(this.hideActionSheetPosition);
    onHide();
    callback();
  }

  render() {
    const { children, animationDuration, overlayOpacity, position } = this.props;
    const { actionSheetState, actionSheetAnimation: { animations } } = this.state;

    const overlayShow = [ACTION_SHEET_OPENED, ACTION_SHEET_OPENING].includes(actionSheetState);
    const pointerEvents = (actionSheetState === ACTION_SHEET_OPENED) ? 'auto' : 'none';

    const contentPosition = (position === 'top')
      ? { top: INITIAL_TOP_POSITION }
      : { bottom: INITIAL_BOTTOM_POSITION };

    const scrollView = (position === 'top')
      ? { paddingTop: 30 }
      : null;

    return (
      <View style={[styles.container]}>
        <AnimatedOverlay
          onPress={this.onOverlayPress}
          overlayShow={overlayShow}
          duration={animationDuration}
          opacity={overlayOpacity}
          pointerEvents={pointerEvents}
        />
        <Animated.View
          style={[styles.contentContainer, contentPosition, animations]}
        >
          <ScrollView style={[styles.scrollView, scrollView]}>
            {children}
          </ScrollView>
        </Animated.View>
      </View>
    );
  }
}

export default ActionSheet;
<|endoftext|>


<commit_before>// ==UserScript==
// @name         Slither.io-bot
// @namespace    http://slither.io/
// @version      0.2.5
// @description  Slither.io bot
// @author       Ermiya Eskandary & Théophile Cailliau
// @match        http://slither.io/
// @grant        none
// ==/UserScript==
// Functions needed for the bot
// Custom logging function - disabled by default
window.logDebugging = false;
window.log = function (message) {
    if (window.logDebugging === true) {
        console.log.apply(console, arguments);
    }
};
// Set fake mouse coordinates
window.setMouseCoordinates = function (x, y) {
    window.xm = x;
    window.ym = y;
};
// Return the coordinates relative to the center (snake position).
window.mouseRelativeToCenter = function (x, y) {
    mapX = x - getHeight() / 2;
    mapY = y - getWidth() / 2;
    return [mapX, mapY];
};
// mouse coordinates to screen coordinates
window.mouseToScreen = function (x, y) {
    screenX = x + (getHeight() / 2);
    screenY = y + (getWidth() / 2);
    return [screenX, screenY];
};
window.onresize = function () {
    window.resize();
    window.canvasRatio = [mc.height / getHeight(), mc.width / getWidth()];
};
window.screenToCanvas = function (x, y) {
    canvasX = csc * x * window.canvasRatio[0] - parseInt(mc.style.left);
    canvasY = csc * y * window.canvasRatio[1] - parseInt(mc.style.top);
    return [canvasX, canvasY];
};
// Map to mouse coordinates
window.mapToMouse = function (x, y) {
    mouseX = (x - getX()) * gsc;
    mouseY = (y - getY()) * gsc;
    return [mouseX, mouseY];
};
// Canvas width
window.getWidth = function () {
    return window.ww;
};
// Canvas height
window.getHeight = function () {
    return window.hh;
};
// X coordinates on the screen
window.getX = function () {
    return window.px;
};
// Y coordinates on the screen
window.getY = function () {
    return window.py;
};
window.setZoom = function (e) {
    if (window.gsc) {
        window.gsc *= Math.pow(0.9, e.wheelDelta / -120 || e.detail / 2 || 0);
    }
};
document.body.onmousewheel = window.setZoom;
// Get scaling ratio
window.getScale = function () {
    return window.gsc;
};
window.isBotRunning = false;
window.isBotEnabled = true;
// Save the original slither.io onmousemove function so we can re enable it back later
window.mousemovelistener = window.onmousemove;
// Starts the bot
window.launchBot = function (d) {
    window.log("Starting Bot.");
    window.isBotRunning = true;
    // Removed the onemousemove listener so we can move the snake manually by setting coordinates
    window.onmousemove = function () {};
    window.botInterval = setInterval(window.loop, d);
    return botInterval;
};
// Stops the bot
window.stopBot = function () {
    window.log("Stopping Bot.");
    // Re enable the original onmousemove function
    window.onmousemove = window.mousemovelistener;
    window.isBotRunning = false;
    // Clear the interval which starts the bot
    return clearInterval(window.botInterval);
};

window.connectBot = function () {
    window.stopBot();
    window.log("Connecting...");
    window.connect();
    window.botCanStart = setInterval(function() {
        if(playing){
            window.launchBot(5);
            clearInterval(window.botCanStart);
        }
    }, 100);
};
// Save the original slither.io onkeydown function so we can add stuff to it
document.oldKeyDown = document.onkeydown;
// Re write the function with our function
document.onkeydown = function (e) {
    // Original slither.io onkeydown function + whatever is under it
    document.oldKeyDown(e);
    // If the letter "t" is pressed, check if the bot is running. If it is, stop the bot. If it isn't, start the bot.
    if (e.keyCode === 84) {
        if(window.isBotRunning){
            window.stopBot();
            window.isBotEnabled = false;
        } else {
            window.launchBot(5);
            window.isBotEnabled = true;
        }
    }
};

// Sorting function, from property 'distance'
window.sortObjects = function (a, b) {
    return a.distance - b.distance;
};

// Given an object (of which properties xx and yy are not null), return the object with an additional property 'distance'
window.getDistanceFromMe = function (point) {
    if (point === null) return null;
    point.distance = getDistance(px, py, point.xx, point.yy);
    return point;
};

// Get a distance from point (x1; y1) to point (x2; y2).
window.getDistance = function (x1, y1, x2, y2) {
    // Calculate the vector coordinates.
    var xDistance = (x1 - x2);
    var yDistance = (y1 - y2);
    // Get the absolute value of each coordinate
    xDistance = xDistance < 0 ? xDistance * -1 : xDistance;
    yDistance = yDistance < 0 ? yDistance * -1 : yDistance;
    //Add the coordinates of the vector to get a distance. Not the real distance, but reliable for distance comparison.
    var distance = xDistance + yDistance;
    return distance;
};
// Sort food based on distance
window.getSortedFood = function () {
    // Filters the nearest food by getting the distance
    return window.foods.filter(function (val) {
        return val != null;
    }).map(getDistanceFromMe).sort(sortObjects);
};

// Sort enemies based on distance
window.getSortedEnemies = function () {
    // Filters the nearest food by getting the distance
    return window.snakes.filter(function (val) {
        return val != null && val.id != snake.id;
    }).map(getDistanceFromMe).sort(sortObjects);
};

window.drawDot = function (x, y, radius, colour) {
    var context = mc.getContext("2d");
    context.beginPath();
    context.arc(x, y, radius, 0, Math.PI * 2);
    context.closePath();
    context.fillStyle = ('green red white yellow black cyan blue'.indexOf(colour) < 0) ? 'white' : colour;
    context.fill();
};

window.drawLine = function (x2, y2, colour) {
    var context = mc.getContext("2d");
    var center = [mc.height / 2, mc.width / 2];
    context.lineWidth = 5;
    context.strokeStyle = (colour === 'green') ? '#00FF00' : '#FF0000';
    context.moveTo(center[1], center[0]);
    context.lineTo(x2, y2);
    context.stroke();
};

window.oldOef = window.oef;

window.oef = function () {
    window.oldOef();
    window.onFrameUpdate();
};
window.canvasRatio = [mc.height / getHeight(), mc.width / getWidth()];
window.onFrameUpdate = function () {
    if (playing) {
        var foodCoordinates = mapToMouse(window.currentFood.xx, window.currentFood.yy);
        foodCoordinates = mouseToScreen(foodCoordinates[0], foodCoordinates[1]);
        foodCoordinates = screenToCanvas(foodCoordinates[0], foodCoordinates[1]);
        drawLine(foodCoordinates[0], foodCoordinates[1], 'green');
        for(var i=0; i<10; i++){
            var item = window.sortedFood[i];
            foodCoordinates = mapToMouse(item.xx, item.yy);
            foodCoordinates = mouseToScreen(foodCoordinates[0], foodCoordinates[1]);
            foodCoordinates = screenToCanvas(foodCoordinates[0], foodCoordinates[1]);
            drawDot(foodCoordinates[0], foodCoordinates[1], 5, 'red');
        }
    }
};

/*
window.isInFoods = function (foodObject) {
    return (foodObject === null) ? false : (window.foods.indexOf(foodObject) >= 0);
};
window.currentFood = null;
window.sortedFood = getSortedFood();
window.loop = function () {
    if (!isInFoods(currentFood)) {
        window.sortedFood = getSortedFood();
        window.currentFood = sortedFood[0];
        var coordinatesOfClosestFood = window.mapToMouse(window.sortedFood[0].xx, window.sortedFood[0].yy);
        window.setMouseCoordinates(coordinatesOfClosestFood[0], coordinatesOfClosestFood[1]);
    }
};
*/
// Actual bot code

// Loop for running the bot
window.loop = function () {
    // If the game is running
    if (playing) {
        // Sort the food and enemies based on their distance relative to player's snake
        window.sortedFood = getSortedFood();
        window.sortedEnemies = getSortedEnemies();
        // Take the closest of each
        window.closestEnemy = sortedEnemies[0];
        window.currentFood = sortedFood[0];
        // Convert coordinates of the closest food using mapToMouse
        var coordinatesOfClosestFood = window.mapToMouse(currentFood.xx, currentFood.yy);
        if (closestEnemy.distance < 5) {
            log("close enemy! (distance = " + closestEnemy.distance);
            // !handle close enemies!
        }
        // Set the mouse coordinates to the coordinates of the closest food
        window.setMouseCoordinates(coordinatesOfClosestFood[0], coordinatesOfClosestFood[1]);

    } else {
        window.startInterval = setInterval(window.startInterval, 1000);
        window.stopBot();
    }
};

window.startInterval = function () {
    if (playing === false && window.isBotEnabled === true) {
        window.connectBot();
        clearInterval(window.startInterval);
    }
};
window.startInterval();
<commit_msg>Fixed zoom code for FireFox<commit_after>// ==UserScript==
// @name         Slither.io-bot
// @namespace    http://slither.io/
// @version      0.2.6
// @description  Slither.io bot
// @author       Ermiya Eskandary & Théophile Cailliau
// @match        http://slither.io/
// @grant        none
// ==/UserScript==
// Functions needed for the bot
// Custom logging function - disabled by default
window.logDebugging = false;
window.log = function (message) {
    if (window.logDebugging === true) {
        console.log.apply(console, arguments);
    }
};
// Set fake mouse coordinates
window.setMouseCoordinates = function (x, y) {
    window.xm = x;
    window.ym = y;
};
// Return the coordinates relative to the center (snake position).
window.mouseRelativeToCenter = function (x, y) {
    mapX = x - getHeight() / 2;
    mapY = y - getWidth() / 2;
    return [mapX, mapY];
};
// mouse coordinates to screen coordinates
window.mouseToScreen = function (x, y) {
    screenX = x + (getHeight() / 2);
    screenY = y + (getWidth() / 2);
    return [screenX, screenY];
};
window.onresize = function () {
    window.resize();
    window.canvasRatio = [mc.height / getHeight(), mc.width / getWidth()];
};
window.screenToCanvas = function (x, y) {
    canvasX = csc * x * window.canvasRatio[0] - parseInt(mc.style.left);
    canvasY = csc * y * window.canvasRatio[1] - parseInt(mc.style.top);
    return [canvasX, canvasY];
};
// Map to mouse coordinates
window.mapToMouse = function (x, y) {
    mouseX = (x - getX()) * gsc;
    mouseY = (y - getY()) * gsc;
    return [mouseX, mouseY];
};
// Canvas width
window.getWidth = function () {
    return window.ww;
};
// Canvas height
window.getHeight = function () {
    return window.hh;
};
// X coordinates on the screen
window.getX = function () {
    return window.px;
};
// Y coordinates on the screen
window.getY = function () {
    return window.py;
};
window.setZoom = function (e) {
    if (window.gsc) {
        window.gsc *= Math.pow(0.9, e.wheelDelta / -120 || e.detail / 2 || 0);
    }
};
if (/firefox/i.test(navigator.userAgent)) {
            document.addEventListener("DOMMouseScroll", zoom, false);
        } else {
            document.body.onmousewheel = window.setZoom;
        }
// Get scaling ratio
window.getScale = function () {
    return window.gsc;
};
window.isBotRunning = false;
window.isBotEnabled = true;
// Save the original slither.io onmousemove function so we can re enable it back later
window.mousemovelistener = window.onmousemove;
// Starts the bot
window.launchBot = function (d) {
    window.log("Starting Bot.");
    window.isBotRunning = true;
    // Removed the onemousemove listener so we can move the snake manually by setting coordinates
    window.onmousemove = function () {};
    window.botInterval = setInterval(window.loop, d);
    return botInterval;
};
// Stops the bot
window.stopBot = function () {
    window.log("Stopping Bot.");
    // Re enable the original onmousemove function
    window.onmousemove = window.mousemovelistener;
    window.isBotRunning = false;
    // Clear the interval which starts the bot
    return clearInterval(window.botInterval);
};

window.connectBot = function () {
    window.stopBot();
    window.log("Connecting...");
    window.connect();
    window.botCanStart = setInterval(function() {
        if(playing){
            window.launchBot(5);
            clearInterval(window.botCanStart);
        }
    }, 100);
};
// Save the original slither.io onkeydown function so we can add stuff to it
document.oldKeyDown = document.onkeydown;
// Re write the function with our function
document.onkeydown = function (e) {
    // Original slither.io onkeydown function + whatever is under it
    document.oldKeyDown(e);
    // If the letter "t" is pressed, check if the bot is running. If it is, stop the bot. If it isn't, start the bot.
    if (e.keyCode === 84) {
        if(window.isBotRunning){
            window.stopBot();
            window.isBotEnabled = false;
        } else {
            window.launchBot(5);
            window.isBotEnabled = true;
        }
    }
};

// Sorting function, from property 'distance'
window.sortObjects = function (a, b) {
    return a.distance - b.distance;
};

// Given an object (of which properties xx and yy are not null), return the object with an additional property 'distance'
window.getDistanceFromMe = function (point) {
    if (point === null) return null;
    point.distance = getDistance(px, py, point.xx, point.yy);
    return point;
};

// Get a distance from point (x1; y1) to point (x2; y2).
window.getDistance = function (x1, y1, x2, y2) {
    // Calculate the vector coordinates.
    var xDistance = (x1 - x2);
    var yDistance = (y1 - y2);
    // Get the absolute value of each coordinate
    xDistance = xDistance < 0 ? xDistance * -1 : xDistance;
    yDistance = yDistance < 0 ? yDistance * -1 : yDistance;
    //Add the coordinates of the vector to get a distance. Not the real distance, but reliable for distance comparison.
    var distance = xDistance + yDistance;
    return distance;
};
// Sort food based on distance
window.getSortedFood = function () {
    // Filters the nearest food by getting the distance
    return window.foods.filter(function (val) {
        return val != null;
    }).map(getDistanceFromMe).sort(sortObjects);
};

// Sort enemies based on distance
window.getSortedEnemies = function () {
    // Filters the nearest food by getting the distance
    return window.snakes.filter(function (val) {
        return val != null && val.id != snake.id;
    }).map(getDistanceFromMe).sort(sortObjects);
};

window.drawDot = function (x, y, radius, colour) {
    var context = mc.getContext("2d");
    context.beginPath();
    context.arc(x, y, radius, 0, Math.PI * 2);
    context.closePath();
    context.fillStyle = ('green red white yellow black cyan blue'.indexOf(colour) < 0) ? 'white' : colour;
    context.fill();
};

window.drawLine = function (x2, y2, colour) {
    var context = mc.getContext("2d");
    var center = [mc.height / 2, mc.width / 2];
    context.lineWidth = 5;
    context.strokeStyle = (colour === 'green') ? '#00FF00' : '#FF0000';
    context.moveTo(center[1], center[0]);
    context.lineTo(x2, y2);
    context.stroke();
};

window.oldOef = window.oef;

window.oef = function () {
    window.oldOef();
    window.onFrameUpdate();
};
window.canvasRatio = [mc.height / getHeight(), mc.width / getWidth()];
window.onFrameUpdate = function () {
    if (playing) {
        var foodCoordinates = mapToMouse(window.currentFood.xx, window.currentFood.yy);
        foodCoordinates = mouseToScreen(foodCoordinates[0], foodCoordinates[1]);
        foodCoordinates = screenToCanvas(foodCoordinates[0], foodCoordinates[1]);
        drawLine(foodCoordinates[0], foodCoordinates[1], 'green');
        for(var i=0; i<10; i++){
            var item = window.sortedFood[i];
            foodCoordinates = mapToMouse(item.xx, item.yy);
            foodCoordinates = mouseToScreen(foodCoordinates[0], foodCoordinates[1]);
            foodCoordinates = screenToCanvas(foodCoordinates[0], foodCoordinates[1]);
            drawDot(foodCoordinates[0], foodCoordinates[1], 5, 'red');
        }
    }
};

/*
window.isInFoods = function (foodObject) {
    return (foodObject === null) ? false : (window.foods.indexOf(foodObject) >= 0);
};
window.currentFood = null;
window.sortedFood = getSortedFood();
window.loop = function () {
    if (!isInFoods(currentFood)) {
        window.sortedFood = getSortedFood();
        window.currentFood = sortedFood[0];
        var coordinatesOfClosestFood = window.mapToMouse(window.sortedFood[0].xx, window.sortedFood[0].yy);
        window.setMouseCoordinates(coordinatesOfClosestFood[0], coordinatesOfClosestFood[1]);
    }
};
*/
// Actual bot code

// Loop for running the bot
window.loop = function () {
    // If the game is running
    if (playing) {
        // Sort the food and enemies based on their distance relative to player's snake
        window.sortedFood = getSortedFood();
        window.sortedEnemies = getSortedEnemies();
        // Take the closest of each
        window.closestEnemy = sortedEnemies[0];
        window.currentFood = sortedFood[0];
        // Convert coordinates of the closest food using mapToMouse
        var coordinatesOfClosestFood = window.mapToMouse(currentFood.xx, currentFood.yy);
        if (closestEnemy.distance < 5) {
            log("close enemy! (distance = " + closestEnemy.distance);
            // !handle close enemies!
        }
        // Set the mouse coordinates to the coordinates of the closest food
        window.setMouseCoordinates(coordinatesOfClosestFood[0], coordinatesOfClosestFood[1]);

    } else {
        window.startInterval = setInterval(window.startInterval, 1000);
        window.stopBot();
    }
};

window.startInterval = function () {
    if (playing === false && window.isBotEnabled === true) {
        window.connectBot();
        clearInterval(window.startInterval);
    }
};
window.startInterval();
<|endoftext|>