<commit_before>// ==========================================================================
// Project:   The M-Project - Mobile HTML5 Application Framework
// Copyright: 2010 M-Way Solutions GmbH. All rights reserved.
// Creator:   Dominik
// Date:      26.10.2010
// License:   Dual licensed under the MIT or GPL Version 2 licenses.
//            http://github.com/mwaylabs/The-M-Project/blob/master/MIT-LICENSE
//            http://github.com/mwaylabs/The-M-Project/blob/master/GPL-LICENSE
// ==========================================================================

m_require('model.js');

/**
 * @class
 *
 * The root of all views.
 *
 */
M.View = M.Object.extend({

    /**
     * The type of this object.
     *
     * @property {String}
     */
    type: 'M.View',

    /**
     * Generic attribute for views. Some subclasses have a property that is more readable to its context than 'value'.
     * Internally these properties are mapped to 'value'.
     * e.g. in LabelView: value:this.text
     */
    value: null,

    contentBinding: null,

    childViews: null,

    /**
     * Determines whether this view renders directly to the DOM or just returns its HTML representation.
     *
     * @property {Boolean}
     */
    renderToDOM: YES,

    /**
     * The id of the View used for the HTML attribute ID.
     */
    id: null,

    /**
     * Indicates whether the view should be displayed inline or not.
     */
    isInline: NO,

    /**
     * This method encapsulates the 'extend' method of M.Object for better reading of code syntax.
     * It triggers the content binding for this view,
     * gets an ID from and registers itself at the ViewManager.
     *
     * @param {Object} obj The mixed in object for the extend call.
     */
    design: function(obj) {
        var extendedView = this.extend(obj);
        if(extendedView.contentBinding) {
            extendedView.attachToObservable(extendedView.contentBinding);
        }
        extendedView.id = M.ViewManager.getNextId();
        M.ViewManager.register(extendedView);
        return extendedView;
    },

     /**
     * Interface method.
     * Renders itself to HTML.
     * Render implementation is done by the special child obj of View (LabelView etc.).
     */
    render: function() {

    },

    /**
     * Interface method.
     * Updates itself in DOM.
     * Render implementation is done by the special child obj of View (LabelView etc.).
     */
    renderUpdate: function() {

    },

    /**
     * Triggers render() on all children.
     */
    renderChildViews: function() {
        var arr = this.childViews[0].split(' ');
        for(var i in arr) {
            this[arr[i]].render();
        }
    },

    /**
     * Interface method.
     * Triggers rendering engine to style this view/apply a theme.
     */
    applyTheme: function() {

    },

    /**
     * contentDidChange is called by the observable when observable's state did change.
     * It updates the view's value property.
     */
    contentDidChange: function(){
        var bindingPath = this.contentBinding.split('.');
        if(bindingPath && bindingPath.length === 3) {
            this.value = eval(bindingPath[0])[bindingPath[1]][bindingPath[2]];
            this.renderUpdate();
        } else {
            M.Logger.log('bindingPath not valid', M.WARN);
        }
    },

    /**
     * This method attaches itself to an observable.
     *
     * @param {String} contentBinding The path to the observable property.
     */
    attachToObservable: function(contentBinding) {
        var bindingPath = contentBinding.split('.');
        if(bindingPath && bindingPath.length === 3 && eval(bindingPath[0]) && eval(bindingPath[0])[bindingPath[1]]) {
            eval(bindingPath[0])[bindingPath[1]].observable.attach(this, bindingPath[2]);
            this.isObserver = YES;
        } else {
            M.Logger.log('bindingPath not valid', M.WARN);
        }
    }

});<commit_msg>small fix<commit_after>// ==========================================================================
// Project:   The M-Project - Mobile HTML5 Application Framework
// Copyright: 2010 M-Way Solutions GmbH. All rights reserved.
// Creator:   Dominik
// Date:      26.10.2010
// License:   Dual licensed under the MIT or GPL Version 2 licenses.
//            http://github.com/mwaylabs/The-M-Project/blob/master/MIT-LICENSE
//            http://github.com/mwaylabs/The-M-Project/blob/master/GPL-LICENSE
// ==========================================================================

m_require('model.js');

/**
 * @class
 *
 * The root of all views.
 *
 */
M.View = M.Object.extend({

    /**
     * The type of this object.
     *
     * @property {String}
     */
    type: 'M.View',

    /**
     * Generic attribute for views. Some subclasses have a property that is more readable to its context than 'value'.
     * Internally these properties are mapped to 'value'.
     * e.g. in LabelView: value:this.text
     */
    value: null,

    contentBinding: null,

    childViews: null,

    /**
     * Determines whether this view renders directly to the DOM or just returns its HTML representation.
     *
     * @property {Boolean}
     */
    renderToDOM: YES,

    /**
     * The id of the View used for the HTML attribute ID.
     */
    id: null,

    /**
     * Indicates whether the view should be displayed inline or not.
     */
    isInline: NO,

    /**
     * This method encapsulates the 'extend' method of M.Object for better reading of code syntax.
     * It triggers the content binding for this view,
     * gets an ID from and registers itself at the ViewManager.
     *
     * @param {Object} obj The mixed in object for the extend call.
     */
    design: function(obj) {
        var extendedView = this.extend(obj);
        if(extendedView.contentBinding) {
            extendedView.attachToObservable(extendedView.contentBinding);
        }
        extendedView.id = M.ViewManager.getNextId();
        M.ViewManager.register(extendedView);
        return extendedView;
    },

     /**
     * Interface method.
     * Renders itself to HTML.
     * Render implementation is done by the special child obj of View (LabelView etc.).
     */
    render: function() {

    },

    /**
     * Interface method.
     * Updates itself in DOM.
     * Render implementation is done by the special child obj of View (LabelView etc.).
     */
    renderUpdate: function() {

    },

    /**
     * Triggers render() on all children.
     */
    renderChildViews: function() {
        if(this.childViews) {
            var arr = this.childViews[0].split(' ');
            for(var i in arr) {
                this[arr[i]].render();
            }
        }
    },

    /**
     * Interface method.
     * Triggers rendering engine to style this view/apply a theme.
     */
    applyTheme: function() {

    },

    /**
     * contentDidChange is called by the observable when observable's state did change.
     * It updates the view's value property.
     */
    contentDidChange: function(){
        var bindingPath = this.contentBinding.split('.');
        if(bindingPath && bindingPath.length === 3) {
            this.value = eval(bindingPath[0])[bindingPath[1]][bindingPath[2]];
            this.renderUpdate();
        } else {
            M.Logger.log('bindingPath not valid', M.WARN);
        }
    },

    /**
     * This method attaches itself to an observable.
     *
     * @param {String} contentBinding The path to the observable property.
     */
    attachToObservable: function(contentBinding) {
        var bindingPath = contentBinding.split('.');
        if(bindingPath && bindingPath.length === 3 && eval(bindingPath[0]) && eval(bindingPath[0])[bindingPath[1]]) {
            eval(bindingPath[0])[bindingPath[1]].observable.attach(this, bindingPath[2]);
            this.isObserver = YES;
        } else {
            M.Logger.log('bindingPath not valid', M.WARN);
        }
    }

});<|endoftext|>


<commit_before>import { isGoZeroDateOrFalsy } from '../util/date.js'
import moment from 'moment'
import _ from 'lodash'
import Player from './Player.js'
// import Tournament from './Tournament.js'

// import store from '../core/store.js'a

export default class Match {
  static fromObject (obj, t) {
    let m = new Match()
    Object.assign(m, obj)

    m.started = moment(m.started)
    m.ended = moment(m.ended)
    m.scheduled = moment(m.scheduled)
    m.players = _.map(m.players, Player.fromObject)

    m.endScore = m.length

    // TODO(thiderman): There used to be this weird bug where some
    // matches are created without a length. This circumvents this in
    // a semi-ugly way. The bug is fixed, but workarounds are forever. <3
    if (m.endScore === 0) {
      m.endScore = m.kind === "final" ? 20 : 10
    }

    if (t !== undefined) {
      m.tournament = t
      m.tournament_id = t.id
    }

    return m
  }

  // TODO(thiderman): This could somehow not be migrated to here from
  // Match.vue. When moved, the request turns from a POST into a GET
  // and the backend rightfully denies it. A thing for later, I guess.
  // commit ($control, payload) {
  //   this.api.commit(this.id, payload).then((res) => {
  //     console.log("Round committed.")
  //     _.each($control.players, (p) => { p.reset() })
  //   }, (res) => {
  //     console.error('error when setting score', res)
  //   })
  // }

  get id () {
    return {
      id: this.tournament_id,
      index: this.index,
    }
  }

  get endScore () { return this._end }
  set endScore (value) { this._end = value }

  get title () {
    if (this.kind === "final") {
      return "Final"
    }
    let kind = this.kind + "s"
    return _.capitalize(this.kind) + " " + this.relativeIndex + " / " + this.tournament[kind].length
  }

  get relativeIndex () {
    if (this.kind === "semi") {
      return this.index - this.tournament.playoffs.length + 1
    }
    return this.index + 1
  }

  get isStarted () {
    // match is started if 'started' is defined and NOT equal to go's zero date
    return !isGoZeroDateOrFalsy(this.started)
  }

  get isEnded () {
    // match is ended if 'ended' is defined and NOT equal to go's zero date
    return !isGoZeroDateOrFalsy(this.ended)
  }

  get isScheduled () {
    return !isGoZeroDateOrFalsy(this.scheduled)
  }

  get canStart () {
    return !this.isStarted
  }

  get canEnd () {
    // can't end if already ended
    if (this.isEnded) {
      return false
    }

    // can end if at least one player has enough kills (ie >= end)
    return _.some(this.players, (player) => { return player.kills >= this.endScore })
  }

  get canReset () {
    return this.isRunning && this.commits.length > 0
  }

  get isRunning () {
    return this.isStarted && !this.isEnded
  }

  get chartData () {
    var out = []
    for (var i = 0; i < this.players.length; i++) {
      out.push([0])
      _.forEach(this.commits, function (commit) {
        let pastScore = _.last(out[i])
        let roundScore = _.sum(commit.kills[i])
        out[i].push(pastScore + roundScore)
      })
    }
    return out
  }

  get levelTitle () {
    if (this.level === "twilight") {
      return "Twilight Spire"
    } else if (this.level === "kingscourt") {
      return "King's Court"
    } else if (this.level === "frostfang") {
      return "Frostfang Keep"
    } else if (this.level === "sunken") {
      return "Sunken City"
    } else if (this.level === "amaranth") {
      return "The Amaranth"
    }
    return this.level.charAt(0).toUpperCase() + this.level.slice(1)
  }
};
<commit_msg>This took me over two hours to find<commit_after>import { isGoZeroDateOrFalsy } from '../util/date.js'
import moment from 'moment'
import _ from 'lodash'
import Player from './Player.js'
// import Tournament from './Tournament.js'

// import store from '../core/store.js'a

export default class Match {
  static fromObject (obj, t) {
    let m = new Match()
    Object.assign(m, obj)

    m.started = moment(m.started)
    m.ended = moment(m.ended)
    m.scheduled = moment(m.scheduled)
    m.players = _.map(m.players, Player.fromObject)

    m.endScore = m.length

    // TODO(thiderman): There used to be this weird bug where some
    // matches are created without a length. This circumvents this in
    // a semi-ugly way. The bug is fixed, but workarounds are forever. <3
    if (m.endScore === 0) {
      m.endScore = m.kind === "final" ? 20 : 10
    }

    if (t !== undefined) {
      m.tournament = t
      m.tournament_id = t.id
    }

    return m
  }

  // TODO(thiderman): This could somehow not be migrated to here from
  // Match.vue. When moved, the request turns from a POST into a GET
  // and the backend rightfully denies it. A thing for later, I guess.
  // commit ($control, payload) {
  //   this.api.commit(this.id, payload).then((res) => {
  //     console.log("Round committed.")
  //     _.each($control.players, (p) => { p.reset() })
  //   }, (res) => {
  //     console.error('error when setting score', res)
  //   })
  // }

  get id () {
    return {
      id: this.tournament_id,
      index: this.index,
    }
  }

  get endScore () { return this._end }
  set endScore (value) { this._end = value }

  get title () {
    if (this.kind === "final") {
      return "Final"
    }
    return _.capitalize(this.kind) + " " + this.relativeIndex
  }

  get relativeIndex () {
    if (this.kind === "semi") {
      return this.index - this.tournament.playoffs.length + 1
    }
    return this.index + 1
  }

  get isStarted () {
    // match is started if 'started' is defined and NOT equal to go's zero date
    return !isGoZeroDateOrFalsy(this.started)
  }

  get isEnded () {
    // match is ended if 'ended' is defined and NOT equal to go's zero date
    return !isGoZeroDateOrFalsy(this.ended)
  }

  get isScheduled () {
    return !isGoZeroDateOrFalsy(this.scheduled)
  }

  get canStart () {
    return !this.isStarted
  }

  get canEnd () {
    // can't end if already ended
    if (this.isEnded) {
      return false
    }

    // can end if at least one player has enough kills (ie >= end)
    return _.some(this.players, (player) => { return player.kills >= this.endScore })
  }

  get canReset () {
    return this.isRunning && this.commits.length > 0
  }

  get isRunning () {
    return this.isStarted && !this.isEnded
  }

  get chartData () {
    var out = []
    for (var i = 0; i < this.players.length; i++) {
      out.push([0])
      _.forEach(this.commits, function (commit) {
        let pastScore = _.last(out[i])
        let roundScore = _.sum(commit.kills[i])
        out[i].push(pastScore + roundScore)
      })
    }
    return out
  }

  get levelTitle () {
    if (this.level === "twilight") {
      return "Twilight Spire"
    } else if (this.level === "kingscourt") {
      return "King's Court"
    } else if (this.level === "frostfang") {
      return "Frostfang Keep"
    } else if (this.level === "sunken") {
      return "Sunken City"
    } else if (this.level === "amaranth") {
      return "The Amaranth"
    }
    return this.level.charAt(0).toUpperCase() + this.level.slice(1)
  }
};
<|endoftext|>


<commit_before>(() => {
  JumpToDiscussion = Vue.extend({
    mixins: [DiscussionMixins],
    props: {
      discussionId: String
    },
    data: function () {
      return {
        discussions: CommentsStore.state,
      };
    },
    computed: {
      discussion: function () {
        return this.discussions[this.discussionId];
      },
      allResolved: function () {
        if (this.discussion) {
          return this.unresolvedDiscussionCount === 0;
        }
      },
      showButton: function () {
        if (this.discussionId) {
          if (this.unresolvedDiscussionCount > 1) {
            return true;
          } else {
            return this.discussionId !== this.lastResolvedId;
          }
        } else {
          return this.unresolvedDiscussionCount >= 1;
        }
      },
      lastResolvedId: function () {
        let lastId;
        for (const discussionId in this.discussions) {
          const discussion = this.discussions[discussionId];

          if (!discussion.isResolved()) {
            lastId = discussion.id;
          }
        }
        return lastId;
      }
    },
    methods: {
      jumpToNextUnresolvedDiscussion: function () {
        let discussionsSelector,
            discussionIdsInScope,
            firstUnresolvedDiscussionId,
            nextUnresolvedDiscussionId,
            activeTab = window.mrTabs.currentAction,
            hasDiscussionsToJumpTo = true,
            jumpToFirstDiscussion = !this.discussionId;

        const discussionIdsForElements = function(elements) {
          return elements.map(function() {
            return $(this).attr('data-discussion-id');
          }).toArray();
        };

        const discussions = this.discussions;

        if (activeTab === 'diffs') {
          discussionsSelector = '.diffs .notes[data-discussion-id]';
          discussionIdsInScope = discussionIdsForElements($(discussionsSelector));

          let unresolvedDiscussionCount = 0;
          for (const discussionId of discussionIdsInScope) {
            const discussion = discussions[discussionId];
            if (discussion && !discussion.isResolved()) {
              unresolvedDiscussionCount++;
            }
          }

          if (this.discussionId && !this.discussion.isResolved()) {
            // If this is the last unresolved discussion on the diffs tab,
            // there are no discussions to jump to.
            if (unresolvedDiscussionCount === 1) {
              hasDiscussionsToJumpTo = false;
            }
          } else {
            // If there are no unresolved discussions on the diffs tab at all,
            // there are no discussions to jump to.
            if (unresolvedDiscussionCount === 0) {
              hasDiscussionsToJumpTo = false;
            }
          }
        } else if (activeTab !== 'notes') {
          // If we are on the commits or builds tabs,
          // there are no discussions to jump to.
          hasDiscussionsToJumpTo = false;
        }

        if (!hasDiscussionsToJumpTo) {
          // If there are no discussions to jump to on the current page,
          // switch to the notes tab and jump to the first disucssion there.
          window.mrTabs.activateTab('notes');
          activeTab = 'notes';
          jumpToFirstDiscussion = true;
        }

        if (activeTab === 'notes') {
          discussionsSelector = '.discussion[data-discussion-id]';
          discussionIdsInScope = discussionIdsForElements($(discussionsSelector));
        }

        let currentDiscussionFound = false;
        for (const discussionId of discussionIdsInScope) {
          const discussion = discussions[discussionId];

          if (!discussion) {
            // Discussions for comments on commits in this MR don't have a resolved status.
            continue;
          }

          if (!firstUnresolvedDiscussionId && !discussion.isResolved()) {
            firstUnresolvedDiscussionId = discussionId;

            if (jumpToFirstDiscussion) {
              break;
            }
          }

          if (!jumpToFirstDiscussion) {
            if (currentDiscussionFound) {
              if (!discussion.isResolved()) {
                nextUnresolvedDiscussionId = discussionId;
                break;
              }
              else {
                continue;
              }
            }

            if (discussionId === this.discussionId) {
              currentDiscussionFound = true;
            }
          }
        }

        nextUnresolvedDiscussionId = nextUnresolvedDiscussionId || firstUnresolvedDiscussionId;

        if (!nextUnresolvedDiscussionId) {
          return;
        }

        let $target = $(`${discussionsSelector}[data-discussion-id="${nextUnresolvedDiscussionId}"]`);

        if (activeTab === 'notes') {
          $target = $target.closest('.note-discussion');
        } else if (activeTab === 'diffs') {
          // Resolved discussions are hidden in the diffs tab by default.
          // If they are marked unresolved on the notes tab, they will still be hidden on the diffs tab.
          // When jumping between unresolved discussions on the diffs tab, we show them.
          $target.closest(".content").show();

          $target = $target.closest("tr.notes_holder");
          $target.show();

          // If we are on the diffs tab, we don't scroll to the discussion itself, but to
          // 4 diff lines above it: the line the discussion was in response to + 3 context
          let prevEl;
          for (let i = 0; i < 4; i++) {
            prevEl = $target.prev();

            // If the discussion doesn't have 4 lines above it, we'll have to do with fewer.
            if (!prevEl.hasClass("line_holder")) {
              break;
            }

            $target = prevEl;
          }
        }

        $.scrollTo($target, {
          offset: -($('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight())
        });
      }
    }
  });

  Vue.component('jump-to-discussion', JumpToDiscussion);
})();
<commit_msg>If the next discussion is closed, toggle it open.<commit_after>(() => {
  JumpToDiscussion = Vue.extend({
    mixins: [DiscussionMixins],
    props: {
      discussionId: String
    },
    data: function () {
      return {
        discussions: CommentsStore.state,
      };
    },
    computed: {
      discussion: function () {
        return this.discussions[this.discussionId];
      },
      allResolved: function () {
        if (this.discussion) {
          return this.unresolvedDiscussionCount === 0;
        }
      },
      showButton: function () {
        if (this.discussionId) {
          if (this.unresolvedDiscussionCount > 1) {
            return true;
          } else {
            return this.discussionId !== this.lastResolvedId;
          }
        } else {
          return this.unresolvedDiscussionCount >= 1;
        }
      },
      lastResolvedId: function () {
        let lastId;
        for (const discussionId in this.discussions) {
          const discussion = this.discussions[discussionId];

          if (!discussion.isResolved()) {
            lastId = discussion.id;
          }
        }
        return lastId;
      }
    },
    methods: {
      jumpToNextUnresolvedDiscussion: function () {
        let discussionsSelector,
            discussionIdsInScope,
            firstUnresolvedDiscussionId,
            nextUnresolvedDiscussionId,
            activeTab = window.mrTabs.currentAction,
            hasDiscussionsToJumpTo = true,
            jumpToFirstDiscussion = !this.discussionId;

        const discussionIdsForElements = function(elements) {
          return elements.map(function() {
            return $(this).attr('data-discussion-id');
          }).toArray();
        };

        const discussions = this.discussions;

        if (activeTab === 'diffs') {
          discussionsSelector = '.diffs .notes[data-discussion-id]';
          discussionIdsInScope = discussionIdsForElements($(discussionsSelector));

          let unresolvedDiscussionCount = 0;
          for (const discussionId of discussionIdsInScope) {
            const discussion = discussions[discussionId];
            if (discussion && !discussion.isResolved()) {
              unresolvedDiscussionCount++;
            }
          }

          if (this.discussionId && !this.discussion.isResolved()) {
            // If this is the last unresolved discussion on the diffs tab,
            // there are no discussions to jump to.
            if (unresolvedDiscussionCount === 1) {
              hasDiscussionsToJumpTo = false;
            }
          } else {
            // If there are no unresolved discussions on the diffs tab at all,
            // there are no discussions to jump to.
            if (unresolvedDiscussionCount === 0) {
              hasDiscussionsToJumpTo = false;
            }
          }
        } else if (activeTab !== 'notes') {
          // If we are on the commits or builds tabs,
          // there are no discussions to jump to.
          hasDiscussionsToJumpTo = false;
        }

        if (!hasDiscussionsToJumpTo) {
          // If there are no discussions to jump to on the current page,
          // switch to the notes tab and jump to the first disucssion there.
          window.mrTabs.activateTab('notes');
          activeTab = 'notes';
          jumpToFirstDiscussion = true;
        }

        if (activeTab === 'notes') {
          discussionsSelector = '.discussion[data-discussion-id]';
          discussionIdsInScope = discussionIdsForElements($(discussionsSelector));
        }

        let currentDiscussionFound = false;
        for (const discussionId of discussionIdsInScope) {
          const discussion = discussions[discussionId];

          if (!discussion) {
            // Discussions for comments on commits in this MR don't have a resolved status.
            continue;
          }

          if (!firstUnresolvedDiscussionId && !discussion.isResolved()) {
            firstUnresolvedDiscussionId = discussionId;

            if (jumpToFirstDiscussion) {
              break;
            }
          }

          if (!jumpToFirstDiscussion) {
            if (currentDiscussionFound) {
              if (!discussion.isResolved()) {
                nextUnresolvedDiscussionId = discussionId;
                break;
              }
              else {
                continue;
              }
            }

            if (discussionId === this.discussionId) {
              currentDiscussionFound = true;
            }
          }
        }

        nextUnresolvedDiscussionId = nextUnresolvedDiscussionId || firstUnresolvedDiscussionId;

        if (!nextUnresolvedDiscussionId) {
          return;
        }

        let $target = $(`${discussionsSelector}[data-discussion-id="${nextUnresolvedDiscussionId}"]`);

        if (activeTab === 'notes') {
          $target = $target.closest('.note-discussion');
        } else if (activeTab === 'diffs') {
          // Resolved discussions are hidden in the diffs tab by default.
          // If they are marked unresolved on the notes tab, they will still be hidden on the diffs tab.
          // When jumping between unresolved discussions on the diffs tab, we show them.
          $target.closest(".content").show();

          $target = $target.closest("tr.notes_holder");
          $target.show();

          // If we are on the diffs tab, we don't scroll to the discussion itself, but to
          // 4 diff lines above it: the line the discussion was in response to + 3 context
          let prevEl;
          for (let i = 0; i < 4; i++) {
            prevEl = $target.prev();

            // If the discussion doesn't have 4 lines above it, we'll have to do with fewer.
            if (!prevEl.hasClass("line_holder")) {
              break;
            }

            $target = prevEl;
          }
        }

        $.scrollTo($target, {
          offset: -($('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight())
        });

        // If the next discussion is closed, toggle it open.
        if ($target.find(".js-toggle-content").attr('style') == "display: none;") {
          $target.find('i').toggleClass('fa fa-chevron-down').toggleClass('fa fa-chevron-up');
          $target.find(".js-toggle-content").toggle();
        }
      }
    }
  });

  Vue.component('jump-to-discussion', JumpToDiscussion);
})();
<|endoftext|>


<commit_before>/**
Captcha input field
Verifying human involvament in form processing
@author: Prakash Paudel
*/
Ext.ux.Captcha = Ext.extend(Ext.form.TextField,  {

    initComponent: function(){
        Ext.ux.Captcha.superclass.initComponent.call(this);
    },

    onRender: function(ct, position){
        Ext.ux.Captcha.superclass.onRender.call(this, ct, position);
        randId = 'captcha_image_'+(Math.floor(Math.random()*10000000));
        src = this.src;
        captchaDiv = Ext.DomHelper.insertFirst(ct, {tag: 'div', style:'width:'+this.width+'px; margin:0px; margin-bottom:2px;float:left; padding:0px'});
        captchaImgDiv = Ext.DomHelper.insertFirst(captchaDiv, {tag: 'div', style:'margin:0px;float:left; padding:0px'});
        reloadImgDiv = Ext.DomHelper.insertFirst(captchaDiv, {tag: 'div', html:'
Can\'t see image? Reload
',  style:'margin:0px;float:right; padding:0px'});
        captchaImg = Ext.DomHelper.append(captchaImgDiv, {tag: 'img', id:randId, src:this.src, width:this.width,style:this.imgStyle});
        if(!this.input){
        	this.el.applyStyles({display:'none'});
        }
    }
});

Ext.reg("captcha", Ext.ux.Captcha);<commit_msg>#811 - fixed login captcha problem<commit_after>/**
Captcha input field
Verifying human involvament in form processing
@author: Prakash Paudel
*/
Ext.ux.Captcha = Ext.extend(Ext.form.TextField,  {

    initComponent: function(){
        Ext.ux.Captcha.superclass.initComponent.call(this);
    },

    onRender: function(ct, position){
        Ext.ux.Captcha.superclass.onRender.call(this, ct, position);
        randId = 'captcha_image_'+(Math.floor(Math.random()*10000000));
        src = this.src;
        captchaDiv = Ext.DomHelper.insertFirst(ct, {tag: 'div', style:'width:'+this.width+'px; margin:0px; margin-bottom:2px;float:left; padding:0px;clear:both;'});
        captchaImgDiv = Ext.DomHelper.insertFirst(captchaDiv, {tag: 'div', style:'margin:0px;float:left; padding:0px'});
        reloadImgDiv = Ext.DomHelper.insertFirst(captchaDiv, {tag: 'div', html:'
Can\'t see image? Reload
',  style:'margin:0px;float:right; padding:0px'});
        captchaImg = Ext.DomHelper.append(captchaImgDiv, {tag: 'img', id:randId, src:this.src, width:this.width,style:this.imgStyle});
        if(!this.input){
        	this.el.applyStyles({display:'none'});
        }
    }
});

Ext.reg("captcha", Ext.ux.Captcha);
<|endoftext|>


<commit_before>var Path = require('path'),
    fs = require('fs-extra');

function setEmptyMap() {
    Map.info = {};
    Map.units = [];
    Map.doodads = [];
    Map.terrain = {};
    Map.regions = [];
    Map.cameras = [];
    Map.sounds = [];

    Map.objects = {
        units: {},
        items: {},
        destructables: {},
        doodads: {},
        abilities: {},
        buffs: {},
        upgrades: {}
    };

    Map.imports = [];
    Map.strings = {};
}

var Map = {
    __Dir: '', // path to current map folder; blank if no map is open
    //__Dirty: false,

    // info: {},
    // units: [],
    // doodads: [],
    // terrain: {},
    // regions: [],
    // cameras: [],
    // sounds: [],
    // objects: {
    //     units: {},
    //     items: {},
    //     destructables: {},
    //     doodads: {},
    //     abilities: {},
    //     buffs: {},
    //     upgrades: {},
    // },
    // imports: [],
    // strings: {},

    Create: function(name) {
        // TODO: if the __Dirty is set, notify the user before continuing
        // since we don't want to overwrite changes

        Map.__Dir = Path.resolve('./' + name); // TODO: let user choose path with file chooser
        fs.ensureDirSync(Map.__Dir); // Creates the path if it doesn't exist

        // Set new Map object
        setEmptyMap();

        // Save the Map
        return Map.Save();
    },

    Load: function(projectDir) {
        console.log('Load map', projectDir);
        Map.__Dir = Path.resolve(projectDir);
        console.log('Load dir', Map.__Dir);

        if(!fs.existsSync(Map.__Dir)) {
            window.alert('This map does not exist!');
            return false;
        }

        var loadJson = function(file, def) {
            var path = Path.resolve(projectDir, file);

            if(!fs.existsSync(path)) {
                return def;
            }

            return fs.readJsonSync(path);
        }

        // Clear the global map when we are loading a new one
        Map.info =                  loadJson('info.json', {});
        Map.units =                 loadJson('units.json', []);
        Map.doodads =               loadJson('doodads.json', []);
        Map.terrain =               loadJson('terrain.json', {});
        Map.regions =               loadJson('regions.json', []);
        Map.cameras =               loadJson('cameras.json', []);
        Map.sounds =                loadJson('sounds.json', []);
        Map.objects.units =         loadJson('/objects/units.json', {});
        Map.objects.items =         loadJson('/objects/items.json', {});
        Map.objects.destructables = loadJson('/objects/destructables.json', {});
        Map.objects.doodads =       loadJson('/objects/doodads.json', {});
        Map.objects.abilities =     loadJson('/objects/abilities.json', {});
        Map.objects.buffs =         loadJson('/objects/buffs.json', {});
        Map.objects.upgrades =      loadJson('/objects/upgrades.json', {});
        Map.imports =               loadJson('imports.json', []);
        Map.strings =               loadJson('strings.json', {});

        console.log("Loading project: " + Map.info.name);
        console.log(" @ " + projectDir);

        return this; // in case the calling function wants the instance right away
    },

    Save: function() {
        // No map is open to save
        if(!Map.__Dir) return false;

        // Takes the global map object and dumps it into its separate project files
        var writeJson = function(file, data) {
            console.log('Writing file to', Path.resolve(Map.__Dir, file));

            fs.outputJsonSync(
                Path.resolve(Map.__Dir, file),
                data
            ); // Overwrites, and ensures file exists
        };

        writeJson('info.json', Map.info);
        writeJson('units.json', Map.units);
        writeJson('doodads.json', Map.doodads);
        writeJson('terrain.json', Map.terrain);
        writeJson('regions.json', Map.regions);
        writeJson('cameras.json', Map.cameras);
        writeJson('sounds.json', Map.sounds);
        writeJson('/objects/units.json', Map.objects.units);
        writeJson('/objects/items.json', Map.objects.items);
        writeJson('/objects/destructables.json', Map.objects.destructables);
        writeJson('/objects/doodads.json', Map.objects.doodads);
        writeJson('/objects/abilities.json', Map.objects.abilities);
        writeJson('/objects/buffs.json', Map.objects.buffs);
        writeJson('/objects/upgrades.json', Map.objects.upgrades);
        writeJson('imports.json', Map.imports);
        writeJson('strings.json', Map.strings);

        console.log("Saved map " + Map.info.name);
        console.log(" @ " + Map.__Dir);
        return this;
    },

    Compile: function() {
        // NOT IMPLEMENTED
        return false;
    }
}

setEmptyMap();
module.exports = Map;
<commit_msg>Remove debug code<commit_after>var Path = require('path'),
    fs = require('fs-extra');

function setEmptyMap() {
    Map.info = {};
    Map.units = [];
    Map.doodads = [];
    Map.terrain = {};
    Map.regions = [];
    Map.cameras = [];
    Map.sounds = [];

    Map.objects = {
        units: {},
        items: {},
        destructables: {},
        doodads: {},
        abilities: {},
        buffs: {},
        upgrades: {}
    };

    Map.imports = [];
    Map.strings = {};
}

var Map = {
    __Dir: '', // path to current map folder; blank if no map is open
    //__Dirty: false,

    // info: {},
    // units: [],
    // doodads: [],
    // terrain: {},
    // regions: [],
    // cameras: [],
    // sounds: [],
    // objects: {
    //     units: {},
    //     items: {},
    //     destructables: {},
    //     doodads: {},
    //     abilities: {},
    //     buffs: {},
    //     upgrades: {},
    // },
    // imports: [],
    // strings: {},

    Create: function(name) {
        // TODO: if the __Dirty is set, notify the user before continuing
        // since we don't want to overwrite changes

        Map.__Dir = Path.resolve('./' + name); // TODO: let user choose path with file chooser
        fs.ensureDirSync(Map.__Dir); // Creates the path if it doesn't exist

        // Set new Map object
        setEmptyMap();

        // Save the Map
        return Map.Save();
    },

    Load: function(projectDir) {
        Map.__Dir = Path.resolve(projectDir);

        if(!fs.existsSync(Map.__Dir)) {
            window.alert('This map does not exist!');
            return false;
        }

        var loadJson = function(file, def) {
            var path = Path.resolve(projectDir, file);

            if(!fs.existsSync(path)) {
                return def;
            }

            return fs.readJsonSync(path);
        }

        // Clear the global map when we are loading a new one
        Map.info =                  loadJson('info.json', {});
        Map.units =                 loadJson('units.json', []);
        Map.doodads =               loadJson('doodads.json', []);
        Map.terrain =               loadJson('terrain.json', {});
        Map.regions =               loadJson('regions.json', []);
        Map.cameras =               loadJson('cameras.json', []);
        Map.sounds =                loadJson('sounds.json', []);
        Map.objects.units =         loadJson('/objects/units.json', {});
        Map.objects.items =         loadJson('/objects/items.json', {});
        Map.objects.destructables = loadJson('/objects/destructables.json', {});
        Map.objects.doodads =       loadJson('/objects/doodads.json', {});
        Map.objects.abilities =     loadJson('/objects/abilities.json', {});
        Map.objects.buffs =         loadJson('/objects/buffs.json', {});
        Map.objects.upgrades =      loadJson('/objects/upgrades.json', {});
        Map.imports =               loadJson('imports.json', []);
        Map.strings =               loadJson('strings.json', {});

        console.log("Loading project: " + Map.info.name);
        console.log(" @ " + projectDir);

        return this; // in case the calling function wants the instance right away
    },

    Save: function() {
        // No map is open to save
        if(!Map.__Dir) return false;

        // Takes the global map object and dumps it into its separate project files
        var writeJson = function(file, data) {
            console.log('Writing file to', Path.resolve(Map.__Dir, file));

            fs.outputJsonSync(
                Path.resolve(Map.__Dir, file),
                data
            ); // Overwrites, and ensures file exists
        };

        writeJson('info.json', Map.info);
        writeJson('units.json', Map.units);
        writeJson('doodads.json', Map.doodads);
        writeJson('terrain.json', Map.terrain);
        writeJson('regions.json', Map.regions);
        writeJson('cameras.json', Map.cameras);
        writeJson('sounds.json', Map.sounds);
        writeJson('/objects/units.json', Map.objects.units);
        writeJson('/objects/items.json', Map.objects.items);
        writeJson('/objects/destructables.json', Map.objects.destructables);
        writeJson('/objects/doodads.json', Map.objects.doodads);
        writeJson('/objects/abilities.json', Map.objects.abilities);
        writeJson('/objects/buffs.json', Map.objects.buffs);
        writeJson('/objects/upgrades.json', Map.objects.upgrades);
        writeJson('imports.json', Map.imports);
        writeJson('strings.json', Map.strings);

        console.log("Saved map " + Map.info.name);
        console.log(" @ " + Map.__Dir);
        return this;
    },

    Compile: function() {
        // NOT IMPLEMENTED
        return false;
    }
}

setEmptyMap();
module.exports = Map;
<|endoftext|>


<commit_before>const { Guild } = require('discord.js');

class SettingsProvider {
	constructor(table) {
		this._table = table;
		this._settings = new Map();
	}

	async init() {
		const settings = await this._table.findAll();

		for (const setting of settings) {
			this._settings.set(setting.guildID, setting.settings);
		}
	}

	get(guild, key, defaultValue) {
		const guildID = this.constructor.getGuildID(guild);
		return this._settings.has(guildID) ? this._settings.get(guildID)[key] || defaultValue : defaultValue;
	}

	async set(guild, key, value) {
		const guildID = this.constructor.getGuildID(guild);
		const settings = this._settings.get(guildID) || {};
		settings[key] = value;

		this._settings.set(guildID, settings);

		await this._table.upsert({
			guildID,
			settings
		});
	}

	async delete(guild, key) {
		const guildID = this.constructor.getGuildID(guild);
		const settings = this._settings.get(guildID) || {};
		delete settings[key];

		await this._table.upsert({
			guildID,
			settings
		});
	}

	async clear(guild) {
		const guildID = this.constructor.getGuildID(guild);
		this._settings.delete(guildID);

		await this._table.destroy({ where: { guildID } });
	}

	static getGuildID(guild) {
		if (guild instanceof Guild) return guild.id;
		if (guild === 'global' || guild === null) return 'global';
		if (typeof guild === 'string' && !isNaN(guild)) return guild;
		throw new TypeError('Invalid guild specified. Must be a Guild instance, guild ID, "global", or null.');
	}
}

module.exports = SettingsProvider;
<commit_msg>Use Akairo SequelizeProvider<commit_after>const { SequelizeProvider } = require('discord-akairo');
const { Guild } = require('discord.js');

class SettingsProvider extends SequelizeProvider {
	constructor(table) {
		super(table, {
			idColumn: 'guildID',
			dataColumn: 'settings'
		});
	}

	get(guild, key, defaultValue) {
		const id = this.constructor.getGuildID(guild);
		return super.get(id, key, defaultValue);
	}

	set(guild, key, value) {
		const id = this.constructor.getGuildID(guild);
		return super.set(id, key, value);
	}

	delete(guild, key) {
		const id = this.constructor.getGuildID(guild);
		return super.delete(id, key);
	}

	clear(guild) {
		const id = this.constructor.getGuildID(guild);
		return super.clear(id);
	}

	static getGuildID(guild) {
		if (guild instanceof Guild) return guild.id;
		if (guild === 'global' || guild === null) return 'global';
		if (typeof guild === 'string' && /^\d+$/.test(guild)) return guild;
		throw new TypeError('Invalid guild specified. Must be a Guild instance, guild ID, "global", or null.');
	}
}

module.exports = SettingsProvider;
<|endoftext|>


<commit_before>/*
 ~ Copyright (c) WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 ~
 ~ Licensed under the Apache License, Version 2.0 (the "License");
 ~ you may not use this file except in compliance with the License.
 ~ You may obtain a copy of the License at
 ~
 ~      http://www.apache.org/licenses/LICENSE-2.0
 ~
 ~ Unless required by applicable law or agreed to in writing, software
 ~ distributed under the License is distributed on an "AS IS" BASIS,
 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ~ See the License for the specific language governing permissions and
 ~ limitations under the License.
 */

var httpUrl = location.protocol + "//" + location.host;
var CONTEXT = "bpmn-explorer";

$( document ).ready(function() {

    function getFileType(){
        var fileName = document.getElementById('files').value;
        if(fileName!== null) {
            var extension = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
            return extension;
        }
    }
    // Send attachment info the server
    $('#attachForm').ajaxForm({
        beforeSubmit: function(arr, formData, options) {
            for (var i=0; i < arr.length; i++) {
                if (!arr[i].value) {
                    $('#submit-attachment').popover({ content: "Please enter all values",
                        placement: "right"});
                    $('#submit-attachment').popover('show');

                    return false;
                }
            }

            setTimeout(function () {
                $('.btn-primary').popover('hide')
            }, 1000);
            var fileType = getFileType();
            if(fileType) {
                arr.push({name: 'type', value: fileType})
            }
        },

        success : function(res){
            var taskUrl = res.taskUrl;
            var taskId = taskUrl.substr(taskUrl.lastIndexOf('/') + 1);
            window.location = httpUrl + "/" + CONTEXT + "/task?id=" + taskId ;

        },
        error :  function(res){
            document.getElementById("error_content").style.visibility='visible';
        }
    });
});

function displayAttachmentData(id){
   window.location = httpUrl + "/" + CONTEXT + "/task?id=" + id ;
}
function completeTask(data, id) {
    var url = "/" + CONTEXT + "/send?req=/bpmn/runtime/tasks/" + id;
    var variables = [];
    for (var i = 0; i < data.length; i++) {
        variables.push({
            "name": data[i].name,
            "value": data[i].value
        });
    }
    var body = {
        "action": "complete",
        "variables": variables
    };

    $.ajax({
        type: 'POST',
        contentType: "application/json",
        url: httpUrl + url,
        data: JSON.stringify(body),
        success: function (data) {
            window.location = httpUrl + "/" + CONTEXT + "/myTasks";
        }
    });
}

function reassign(username, id) {
    var url = "/" + CONTEXT + "/send?req=/bpmn/runtime/tasks/" + id;
    var body = {
        "assignee": username
    };

    $.ajax({
        type: 'PUT',
        contentType: "application/json",
        url: httpUrl + url,
        data: JSON.stringify(body),
        success: function (data) {
            window.location = httpUrl + "/" + CONTEXT + "/myTasks";
        }
    });
}

function claim(username, id){
    var url = "/" + CONTEXT + "/send?req=/bpmn/runtime/tasks/" + id;
    var body = {
        "assignee" : username
    };

    $.ajax({
        type: 'PUT',
        contentType: "application/json",
        url: httpUrl + url,
        data: JSON.stringify(body),
        success: function(data){
            window.location=httpUrl+"/"+CONTEXT+"/myTasks";
        }
    });
}

function transfer(username, id) {
    var url = "/" + CONTEXT + "/send?req=/bpmn/runtime/tasks/" + id;
    var body = {
        "owner": username
    };

    $.ajax({
        type: 'PUT',
        contentType: "application/json",
        url: httpUrl + url,
        data: JSON.stringify(body),
        success: function (data) {
            window.location = httpUrl + "/" + CONTEXT + "/myTasks";
        }
    });
}

function startProcess(processDefId) {
    var url = "/" + CONTEXT + "/send?req=/bpmn/runtime/process-instances";
    var body = {
        "processDefinitionId": processDefId
    };

    $.ajax({
        type: 'POST',
        contentType: "application/json",
        url: httpUrl + url,
        data: JSON.stringify(body),
        success: function (data) {
            window.location = httpUrl + "/" + CONTEXT + "/myTasks";
        }
    });
}

function startProcessWithData(data, id) {
    var url = "/" + CONTEXT + "/send?req=/bpmn/runtime/process-instances";
    var variables = [];
    for (var i = 0; i < data.length; i++) {
        variables.push({
            "name": data[i].name,
            "value": data[i].value
        });
    }
    var body = {
        "processDefinitionId": id,
        "variables": variables
    };
    $.ajax({
        type: 'POST',
        contentType: "application/json",
        url: httpUrl + url,
        data: JSON.stringify(body),
        success: function (data) {
            showStatusForProcessWithData(id, 1);
        },
        error: function (xhr, status, error) {
            showStatusForProcessWithData(id, 0);
        }

    });
}

function showStatusForProcessWithData(id, status) {
    var statusContent = "";
    if (status == 1) {
        statusContent = "Successfully started process";
    }
    else {
        statusContent = "Failed to start process";
    }
    $('.btn-primary').popover({title: "Process Status", content: statusContent + " " + id,
        placement: "right"});
    $('.btn-primary').popover('show');
    setTimeout(function () {
        $('.btn-primary').popover('hide')
    }, 3000);
}

<commit_msg>Fixing issue: BPS-726<commit_after>/*
 ~ Copyright (c) WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 ~
 ~ Licensed under the Apache License, Version 2.0 (the "License");
 ~ you may not use this file except in compliance with the License.
 ~ You may obtain a copy of the License at
 ~
 ~      http://www.apache.org/licenses/LICENSE-2.0
 ~
 ~ Unless required by applicable law or agreed to in writing, software
 ~ distributed under the License is distributed on an "AS IS" BASIS,
 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ~ See the License for the specific language governing permissions and
 ~ limitations under the License.
 */

var httpUrl = location.protocol + "//" + location.host;
var CONTEXT = "bpmn-explorer";

$( document ).ready(function() {

    function getFileType(){
        var fileName = document.getElementById('files').value;
        if(fileName!== null) {
            var extension = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
            return extension;
        }
    }
    // Send attachment info the server
    $('#attachForm').ajaxForm({
        beforeSubmit: function(arr, formData, options) {
            for (var i=0; i < arr.length; i++) {
                if (!arr[i].value) {
                    $('#submit-attachment').popover({ content: "Please enter all values",
                        placement: "right"});
                    $('#submit-attachment').popover('show');

                    return false;
                }
            }

            setTimeout(function () {
                $('.btn-primary').popover('hide')
            }, 1000);
            var fileType = getFileType();
            if(fileType) {
                arr.push({name: 'type', value: fileType})
            }
        },

        success : function(res){
            var taskUrl = res.taskUrl;
            var taskId = taskUrl.substr(taskUrl.lastIndexOf('/') + 1);
            window.location = httpUrl + "/" + CONTEXT + "/task?id=" + taskId ;

        },
        error :  function(res){
            document.getElementById("error_content").style.visibility='visible';
        }
    });
});

function displayAttachmentData(id){
   window.location = httpUrl + "/" + CONTEXT + "/task?id=" + id ;
}
function completeTask(data, id) {
    var url = "/" + CONTEXT + "/send?req=/bpmn/runtime/tasks/" + id;
    var variables = [];
    for (var i = 0; i < data.length; i++) {
        variables.push({
            "name": data[i].name,
            "value": data[i].value
        });
    }
    var body = {
        "action": "complete",
        "variables": variables
    };

    $.ajax({
        type: 'POST',
        contentType: "application/json",
        url: httpUrl + url,
        data: JSON.stringify(body),
        success: function (data) {
            window.location = httpUrl + "/" + CONTEXT + "/myTasks";
        }
    });
}

function reassign(username, id) {
    var url = "/" + CONTEXT + "/send?req=/bpmn/runtime/tasks/" + id;
    var body = {
        "assignee": username
    };

    $.ajax({
        type: 'PUT',
        contentType: "application/json",
        url: httpUrl + url,
        data: JSON.stringify(body),
        success: function (data) {
            window.location = httpUrl + "/" + CONTEXT + "/myTasks";
        }
    });
}

function claim(username, id){
    var url = "/" + CONTEXT + "/send?req=/bpmn/runtime/tasks/" + id;
    var body = {
        "assignee" : username
    };

    $.ajax({
        type: 'PUT',
        contentType: "application/json",
        url: httpUrl + url,
        data: JSON.stringify(body),
        success: function(data){
            window.location = httpUrl + "/" + CONTEXT + "/task?id=" + id;
        }
    });
}

function transfer(username, id) {
    var url = "/" + CONTEXT + "/send?req=/bpmn/runtime/tasks/" + id;
    var body = {
        "owner": username
    };

    $.ajax({
        type: 'PUT',
        contentType: "application/json",
        url: httpUrl + url,
        data: JSON.stringify(body),
        success: function (data) {
            window.location = httpUrl + "/" + CONTEXT + "/myTasks";
        }
    });
}

function startProcess(processDefId) {
    var url = "/" + CONTEXT + "/send?req=/bpmn/runtime/process-instances";
    var body = {
        "processDefinitionId": processDefId
    };

    $.ajax({
        type: 'POST',
        contentType: "application/json",
        url: httpUrl + url,
        data: JSON.stringify(body),
        success: function (data) {
            window.location = httpUrl + "/" + CONTEXT + "/myTasks";
        }
    });
}

function startProcessWithData(data, id) {
    var url = "/" + CONTEXT + "/send?req=/bpmn/runtime/process-instances";
    var variables = [];
    for (var i = 0; i < data.length; i++) {
        variables.push({
            "name": data[i].name,
            "value": data[i].value
        });
    }
    var body = {
        "processDefinitionId": id,
        "variables": variables
    };
    $.ajax({
        type: 'POST',
        contentType: "application/json",
        url: httpUrl + url,
        data: JSON.stringify(body),
        success: function (data) {
            showStatusForProcessWithData(id, 1);
        },
        error: function (xhr, status, error) {
            showStatusForProcessWithData(id, 0);
        }

    });
}

function showStatusForProcessWithData(id, status) {
    var statusContent = "";
    if (status == 1) {
        statusContent = "Successfully started process";
    }
    else {
        statusContent = "Failed to start process";
    }
    $('.btn-primary').popover({title: "Process Status", content: statusContent + " " + id,
        placement: "right"});
    $('.btn-primary').popover('show');
    setTimeout(function () {
        $('.btn-primary').popover('hide')
    }, 3000);
}

<|endoftext|>


<commit_before>var EOL = require('os').EOL;

module.exports = {
  normalizeEntityName: function() {
  },

  afterInstall: function() {
    this.insertIntoFile('tests/.jshintrc',
      '    "authenticateSession",' + EOL +
      '    "invalidateSession",',
      { after: '  "predef": [' + EOL }
    );

    return this.addBowerPackageToProject('ember-simple-auth', '0.7.1');
  }
};
<commit_msg>automatically load helpers<commit_after>var EOL = require('os').EOL;

module.exports = {
  normalizeEntityName: function() {
  },

  afterInstall: function() {
    this.insertIntoFile('tests/.jshintrc',
      '    "authenticateSession",' + EOL +
      '    "invalidateSession",',
      { after: '  "predef": [' + EOL }
    );
    this.insertIntoFile('tests/helpers/start-app.js',
      "import 'simple-auth-testing/test-helpers';" + EOL + EOL
      { before: 'export default function startApp(attrs) {' + EOL }
    );

    return this.addBowerPackageToProject('ember-simple-auth', '0.7.1');
  }
};
<|endoftext|>


<commit_before>/**
 * @module ol/format/Feature
 */
import {assign} from '../obj.js';
import {abstract} from '../util.js';
import {get as getProjection, equivalent as equivalentProjection, transformExtent} from '../proj.js';

/**
 * @typedef {Object} ReadOptions
 * @property {import("../proj.js").ProjectionLike} [dataProjection] Projection of the data we are reading.
 * If not provided, the projection will be derived from the data (where possible) or
 * the `dataProjection` of the format is assigned (where set). If the projection
 * can not be derived from the data and if no `dataProjection` is set for a format,
 * the features will not be reprojected.
 * @property {import("../extent.js").Extent} [extent] Tile extent in map units of the tile being read.
 * This is only required when reading data with tile pixels as geometry units. When configured,
 * a `dataProjection` with `TILE_PIXELS` as `units` and the tile's pixel extent as `extent` needs to be
 * provided.
 * @property {import("../proj.js").ProjectionLike} [featureProjection] Projection of the feature geometries
 * created by the format reader. If not provided, features will be returned in the
 * `dataProjection`.
 */

/**
 * @typedef {Object} WriteOptions
 * @property {import("../proj.js").ProjectionLike} [dataProjection] Projection of the data we are writing.
 * If not provided, the `dataProjection` of the format is assigned (where set).
 * If no `dataProjection` is set for a format, the features will be returned
 * in the `featureProjection`.
 * @property {import("../proj.js").ProjectionLike} [featureProjection] Projection of the feature geometries
 * that will be serialized by the format writer. If not provided, geometries are assumed
 * to be in the `dataProjection` if that is set; in other words, they are not transformed.
 * @property {boolean} [rightHanded] When writing geometries, follow the right-hand
 * rule for linear ring orientation.  This means that polygons will have counter-clockwise
 * exterior rings and clockwise interior rings.  By default, coordinates are serialized
 * as they are provided at construction.  If `true`, the right-hand rule will
 * be applied.  If `false`, the left-hand rule will be applied (clockwise for
 * exterior and counter-clockwise for interior rings).  Note that not all
 * formats support this.  The GeoJSON format does use this property when writing
 * geometries.
 * @property {number} [decimals] Maximum number of decimal places for coordinates.
 * Coordinates are stored internally as floats, but floating-point arithmetic can create
 * coordinates with a large number of decimal places, not generally wanted on output.
 * Set a number here to round coordinates. Can also be used to ensure that
 * coordinates read in can be written back out with the same number of decimals.
 * Default is no rounding.
 */

/**
 * @classdesc
 * Abstract base class; normally only used for creating subclasses and not
 * instantiated in apps.
 * Base class for feature formats.
 * {FeatureFormat} subclasses provide the ability to decode and encode
 * {@link module:ol/Feature~Feature} objects from a variety of commonly used geospatial
 * file formats.  See the documentation for each format for more details.
 *
 * @abstract
 * @api
 */
class FeatureFormat {
  constructor() {

    /**
     * @protected
     * @type {import("../proj/Projection.js").default}
     */
    this.dataProjection = null;

    /**
     * @protected
     * @type {import("../proj/Projection.js").default}
     */
    this.defaultFeatureProjection = null;

  }

  /**
   * Adds the data projection to the read options.
   * @param {Document|Node|Object|string} source Source.
   * @param {ReadOptions=} opt_options Options.
   * @return {ReadOptions|undefined} Options.
   * @protected
   */
  getReadOptions(source, opt_options) {
    let options;
    if (opt_options) {
      let dataProjection = opt_options.dataProjection ?
        opt_options.dataProjection : this.readProjection(source);
      if (opt_options.extent) {
        dataProjection = getProjection(dataProjection);
        dataProjection.setWorldExtent(opt_options.extent);
      }
      options = {
        dataProjection: dataProjection,
        featureProjection: opt_options.featureProjection
      };
    }
    return this.adaptOptions(options);
  }

  /**
   * Sets the `dataProjection` on the options, if no `dataProjection`
   * is set.
   * @param {WriteOptions|ReadOptions|undefined} options
   *     Options.
   * @protected
   * @return {WriteOptions|ReadOptions|undefined}
   *     Updated options.
   */
  adaptOptions(options) {
    return assign({
      dataProjection: this.dataProjection,
      featureProjection: this.defaultFeatureProjection
    }, options);
  }

  /**
   * @abstract
   * @return {import("./FormatType.js").default} Format.
   */
  getType() {
    return abstract();
  }

  /**
   * Read a single feature from a source.
   *
   * @abstract
   * @param {Document|Node|Object|string} source Source.
   * @param {ReadOptions=} opt_options Read options.
   * @return {import("../Feature.js").FeatureLike} Feature.
   */
  readFeature(source, opt_options) {
    return abstract();
  }

  /**
   * Read all features from a source.
   *
   * @abstract
   * @param {Document|Node|ArrayBuffer|Object|string} source Source.
   * @param {ReadOptions=} opt_options Read options.
   * @return {Array<import("../Feature.js").FeatureLike>} Features.
   */
  readFeatures(source, opt_options) {
    return abstract();
  }

  /**
   * Read a single geometry from a source.
   *
   * @abstract
   * @param {Document|Node|Object|string} source Source.
   * @param {ReadOptions=} opt_options Read options.
   * @return {import("../geom/Geometry.js").default} Geometry.
   */
  readGeometry(source, opt_options) {
    return abstract();
  }

  /**
   * Read the projection from a source.
   *
   * @abstract
   * @param {Document|Node|Object|string} source Source.
   * @return {import("../proj/Projection.js").default} Projection.
   */
  readProjection(source) {
    return abstract();
  }

  /**
   * Encode a feature in this format.
   *
   * @abstract
   * @param {import("../Feature.js").default} feature Feature.
   * @param {WriteOptions=} opt_options Write options.
   * @return {string} Result.
   */
  writeFeature(feature, opt_options) {
    return abstract();
  }

  /**
   * Encode an array of features in this format.
   *
   * @abstract
   * @param {Array<import("../Feature.js").default>} features Features.
   * @param {WriteOptions=} opt_options Write options.
   * @return {string} Result.
   */
  writeFeatures(features, opt_options) {
    return abstract();
  }

  /**
   * Write a single geometry in this format.
   *
   * @abstract
   * @param {import("../geom/Geometry.js").default} geometry Geometry.
   * @param {WriteOptions=} opt_options Write options.
   * @return {string} Result.
   */
  writeGeometry(geometry, opt_options) {
    return abstract();
  }
}

export default FeatureFormat;

/**
 * @param {import("../geom/Geometry.js").default} geometry Geometry.
 * @param {boolean} write Set to true for writing, false for reading.
 * @param {(WriteOptions|ReadOptions)=} opt_options Options.
 * @return {import("../geom/Geometry.js").default} Transformed geometry.
 */
export function transformGeometryWithOptions(geometry, write, opt_options) {
  const featureProjection = opt_options ? getProjection(opt_options.featureProjection) : null;
  const dataProjection = opt_options ? getProjection(opt_options.dataProjection) : null;

  let transformed;
  if (featureProjection && dataProjection && !equivalentProjection(featureProjection, dataProjection)) {
    transformed = (write ? geometry.clone() : geometry).transform(
      write ? featureProjection : dataProjection,
      write ? dataProjection : featureProjection);
  } else {
    transformed = geometry;
  }
  if (write && opt_options && /** @type {WriteOptions} */ (opt_options).decimals !== undefined) {
    const power = Math.pow(10, /** @type {WriteOptions} */ (opt_options).decimals);
    // if decimals option on write, round each coordinate appropriately
    /**
     * @param {Array<number>} coordinates Coordinates.
     * @return {Array<number>} Transformed coordinates.
     */
    const transform = function(coordinates) {
      for (let i = 0, ii = coordinates.length; i < ii; ++i) {
        coordinates[i] = Math.round(coordinates[i] * power) / power;
      }
      return coordinates;
    };
    if (transformed === geometry) {
      transformed = geometry.clone();
    }
    transformed.applyTransform(transform);
  }
  return transformed;
}

/**
 * @param {import("../extent.js").Extent} extent Extent.
 * @param {ReadOptions=} opt_options Read options.
 * @return {import("../extent.js").Extent} Transformed extent.
 */
export function transformExtentWithOptions(extent, opt_options) {
  const featureProjection = opt_options ? getProjection(opt_options.featureProjection) : null;
  const dataProjection = opt_options ? getProjection(opt_options.dataProjection) : null;

  if (featureProjection && dataProjection && !equivalentProjection(featureProjection, dataProjection)) {
    return transformExtent(extent, dataProjection, featureProjection);
  } else {
    return extent;
  }
}
<commit_msg>Set world projection only for tile-pixels units<commit_after>/**
 * @module ol/format/Feature
 */
import {assign} from '../obj.js';
import {abstract} from '../util.js';
import {get as getProjection, equivalent as equivalentProjection, transformExtent} from '../proj.js';
import Units from '../proj/Units.js';

/**
 * @typedef {Object} ReadOptions
 * @property {import("../proj.js").ProjectionLike} [dataProjection] Projection of the data we are reading.
 * If not provided, the projection will be derived from the data (where possible) or
 * the `dataProjection` of the format is assigned (where set). If the projection
 * can not be derived from the data and if no `dataProjection` is set for a format,
 * the features will not be reprojected.
 * @property {import("../extent.js").Extent} [extent] Tile extent in map units of the tile being read.
 * This is only required when reading data with tile pixels as geometry units. When configured,
 * a `dataProjection` with `TILE_PIXELS` as `units` and the tile's pixel extent as `extent` needs to be
 * provided.
 * @property {import("../proj.js").ProjectionLike} [featureProjection] Projection of the feature geometries
 * created by the format reader. If not provided, features will be returned in the
 * `dataProjection`.
 */

/**
 * @typedef {Object} WriteOptions
 * @property {import("../proj.js").ProjectionLike} [dataProjection] Projection of the data we are writing.
 * If not provided, the `dataProjection` of the format is assigned (where set).
 * If no `dataProjection` is set for a format, the features will be returned
 * in the `featureProjection`.
 * @property {import("../proj.js").ProjectionLike} [featureProjection] Projection of the feature geometries
 * that will be serialized by the format writer. If not provided, geometries are assumed
 * to be in the `dataProjection` if that is set; in other words, they are not transformed.
 * @property {boolean} [rightHanded] When writing geometries, follow the right-hand
 * rule for linear ring orientation.  This means that polygons will have counter-clockwise
 * exterior rings and clockwise interior rings.  By default, coordinates are serialized
 * as they are provided at construction.  If `true`, the right-hand rule will
 * be applied.  If `false`, the left-hand rule will be applied (clockwise for
 * exterior and counter-clockwise for interior rings).  Note that not all
 * formats support this.  The GeoJSON format does use this property when writing
 * geometries.
 * @property {number} [decimals] Maximum number of decimal places for coordinates.
 * Coordinates are stored internally as floats, but floating-point arithmetic can create
 * coordinates with a large number of decimal places, not generally wanted on output.
 * Set a number here to round coordinates. Can also be used to ensure that
 * coordinates read in can be written back out with the same number of decimals.
 * Default is no rounding.
 */

/**
 * @classdesc
 * Abstract base class; normally only used for creating subclasses and not
 * instantiated in apps.
 * Base class for feature formats.
 * {FeatureFormat} subclasses provide the ability to decode and encode
 * {@link module:ol/Feature~Feature} objects from a variety of commonly used geospatial
 * file formats.  See the documentation for each format for more details.
 *
 * @abstract
 * @api
 */
class FeatureFormat {
  constructor() {

    /**
     * @protected
     * @type {import("../proj/Projection.js").default}
     */
    this.dataProjection = null;

    /**
     * @protected
     * @type {import("../proj/Projection.js").default}
     */
    this.defaultFeatureProjection = null;

  }

  /**
   * Adds the data projection to the read options.
   * @param {Document|Node|Object|string} source Source.
   * @param {ReadOptions=} opt_options Options.
   * @return {ReadOptions|undefined} Options.
   * @protected
   */
  getReadOptions(source, opt_options) {
    let options;
    if (opt_options) {
      let dataProjection = opt_options.dataProjection ?
        getProjection(opt_options.dataProjection) : this.readProjection(source);
      if (opt_options.extent &&
          dataProjection && dataProjection.getUnits() === Units.TILE_PIXELS) {
        dataProjection = getProjection(dataProjection);
        dataProjection.setWorldExtent(opt_options.extent);
      }
      options = {
        dataProjection: dataProjection,
        featureProjection: opt_options.featureProjection
      };
    }
    return this.adaptOptions(options);
  }

  /**
   * Sets the `dataProjection` on the options, if no `dataProjection`
   * is set.
   * @param {WriteOptions|ReadOptions|undefined} options
   *     Options.
   * @protected
   * @return {WriteOptions|ReadOptions|undefined}
   *     Updated options.
   */
  adaptOptions(options) {
    return assign({
      dataProjection: this.dataProjection,
      featureProjection: this.defaultFeatureProjection
    }, options);
  }

  /**
   * @abstract
   * @return {import("./FormatType.js").default} Format.
   */
  getType() {
    return abstract();
  }

  /**
   * Read a single feature from a source.
   *
   * @abstract
   * @param {Document|Node|Object|string} source Source.
   * @param {ReadOptions=} opt_options Read options.
   * @return {import("../Feature.js").FeatureLike} Feature.
   */
  readFeature(source, opt_options) {
    return abstract();
  }

  /**
   * Read all features from a source.
   *
   * @abstract
   * @param {Document|Node|ArrayBuffer|Object|string} source Source.
   * @param {ReadOptions=} opt_options Read options.
   * @return {Array<import("../Feature.js").FeatureLike>} Features.
   */
  readFeatures(source, opt_options) {
    return abstract();
  }

  /**
   * Read a single geometry from a source.
   *
   * @abstract
   * @param {Document|Node|Object|string} source Source.
   * @param {ReadOptions=} opt_options Read options.
   * @return {import("../geom/Geometry.js").default} Geometry.
   */
  readGeometry(source, opt_options) {
    return abstract();
  }

  /**
   * Read the projection from a source.
   *
   * @abstract
   * @param {Document|Node|Object|string} source Source.
   * @return {import("../proj/Projection.js").default} Projection.
   */
  readProjection(source) {
    return abstract();
  }

  /**
   * Encode a feature in this format.
   *
   * @abstract
   * @param {import("../Feature.js").default} feature Feature.
   * @param {WriteOptions=} opt_options Write options.
   * @return {string} Result.
   */
  writeFeature(feature, opt_options) {
    return abstract();
  }

  /**
   * Encode an array of features in this format.
   *
   * @abstract
   * @param {Array<import("../Feature.js").default>} features Features.
   * @param {WriteOptions=} opt_options Write options.
   * @return {string} Result.
   */
  writeFeatures(features, opt_options) {
    return abstract();
  }

  /**
   * Write a single geometry in this format.
   *
   * @abstract
   * @param {import("../geom/Geometry.js").default} geometry Geometry.
   * @param {WriteOptions=} opt_options Write options.
   * @return {string} Result.
   */
  writeGeometry(geometry, opt_options) {
    return abstract();
  }
}

export default FeatureFormat;

/**
 * @param {import("../geom/Geometry.js").default} geometry Geometry.
 * @param {boolean} write Set to true for writing, false for reading.
 * @param {(WriteOptions|ReadOptions)=} opt_options Options.
 * @return {import("../geom/Geometry.js").default} Transformed geometry.
 */
export function transformGeometryWithOptions(geometry, write, opt_options) {
  const featureProjection = opt_options ? getProjection(opt_options.featureProjection) : null;
  const dataProjection = opt_options ? getProjection(opt_options.dataProjection) : null;

  let transformed;
  if (featureProjection && dataProjection && !equivalentProjection(featureProjection, dataProjection)) {
    transformed = (write ? geometry.clone() : geometry).transform(
      write ? featureProjection : dataProjection,
      write ? dataProjection : featureProjection);
  } else {
    transformed = geometry;
  }
  if (write && opt_options && /** @type {WriteOptions} */ (opt_options).decimals !== undefined) {
    const power = Math.pow(10, /** @type {WriteOptions} */ (opt_options).decimals);
    // if decimals option on write, round each coordinate appropriately
    /**
     * @param {Array<number>} coordinates Coordinates.
     * @return {Array<number>} Transformed coordinates.
     */
    const transform = function(coordinates) {
      for (let i = 0, ii = coordinates.length; i < ii; ++i) {
        coordinates[i] = Math.round(coordinates[i] * power) / power;
      }
      return coordinates;
    };
    if (transformed === geometry) {
      transformed = geometry.clone();
    }
    transformed.applyTransform(transform);
  }
  return transformed;
}

/**
 * @param {import("../extent.js").Extent} extent Extent.
 * @param {ReadOptions=} opt_options Read options.
 * @return {import("../extent.js").Extent} Transformed extent.
 */
export function transformExtentWithOptions(extent, opt_options) {
  const featureProjection = opt_options ? getProjection(opt_options.featureProjection) : null;
  const dataProjection = opt_options ? getProjection(opt_options.dataProjection) : null;

  if (featureProjection && dataProjection && !equivalentProjection(featureProjection, dataProjection)) {
    return transformExtent(extent, dataProjection, featureProjection);
  } else {
    return extent;
  }
}
<|endoftext|>


<commit_before>/**
 *
 */

/**
 *
 */
function MapperFactory() {

}

Object.assign(MapperFactory.prototype, {
  isMapperFactory: true,

  MAPPERS: [
    /* 0 */ {'name': 'NROM',  class: NROMMapper},
    /* 1 */ {'name': 'MMC1',  class: MMC1Mapper},
    /* 2 */ {'name': 'UNROM', class: UNROMMapper},
    /* 3 */ {'name': 'CNROM', class: CNROMMapper},
    /* 4 */ {'name': 'MMC3',  class: MMC3Mapper}
  ],

  /**
   *
   */
  getMapperParam: function(number) {
    if(this.MAPPERS[number] === undefined)
      throw new Error('unsupport No.' + number + ' Mapper');

    return this.MAPPERS[number];
  },

  /**
   *
   */
  create: function(number, rom) {
    return new (this.getMapperParam(number)).class(rom);
  },

  /**
   *
   */
  getName: function(number) {
    return this.getMapperParam(number).name;
  }
});

/**
 *
 */
function Mapper(rom) {
  this.rom = rom;
  this.prgBankNum = rom.header.getPRGROMBanksNum();
  this.chrBankNum = rom.header.getCHRROMBanksNum();
}

Object.assign(Mapper.prototype, {
  isMapper: true,

  /**
   *
   */
  map: function(address) {
    return address;
  },

  /**
   *
   */
  mapForCHRROM: function(address) {
    return address;
  },

  /**
   *
   */
  store: function(address, value) {
  },

  /**
   *
   */
  getMirroringType: function() {
    return this.rom.header.isHorizontalMirroring() === true
             ? this.rom.MIRRORINGS.HORIZONTAL : this.rom.MIRRORINGS.VERTICAL;
  }
});

/**
 *
 */
function NROMMapper(rom) {
  Mapper.call(this, rom);
}

NROMMapper.prototype = Object.assign(Object.create(Mapper.prototype), {
  isNROMMapper: true,

  /**
   *
   */
  map: function(address) {
    // 0x8000 - 0xBFFF: First 16 KB of ROM
    // 0xC000 - 0xFFFF: Last 16 KB of ROM (NROM-256) or
    //                  mirror of 0x8000 - 0xBFFF (NROM-128).

    if(this.prgBankNum === 1 && address >= 0xC000)
      address -= 0x4000;

    return address;
  }
});

/**
 *
 */
function MMC1Mapper(rom) {
  Mapper.call(this, rom);

  this.controlRegister = new Register8bit();  // register 0
  this.chrBank0Register = new Register8bit(); // register 1
  this.chrBank1Register = new Register8bit(); // register 2
  this.prgBankRegister = new Register8bit();  // register 3

  this.latch = new Register8bit();

  this.registerWriteCount = 0;

  this.controlRegister.store(0x0C);  // seems like 0xC would be default value
}

MMC1Mapper.prototype = Object.assign(Object.create(Mapper.prototype), {
  isMMC1Mapper: true,

  /**
   *
   */
  map: function(address) {
    var bank = 0;
    var offset = address & 0x3FFF;
    var bankNum = this.prgBankRegister.load() & 0x0F;

    switch(this.controlRegister.loadBits(2, 2)) {
      case 0:
      case 1:

        // switch 32KB at 0x8000, ignoring low bit of bank number

        // TODO: Fix me

        offset = offset | (address & 0x4000);
        bank = bankNum & 0x0E;
        break;

      case 2:

        // fix first bank at 0x8000 and switch 16KB bank at 0xC000

        bank = (address < 0xC000) ? 0 : bankNum;
        break;

      case 3:

        // fix last bank at 0xC000 and switch 16KB bank at 0x8000

        bank = (address >= 0xC000) ? this.prgBankNum - 1 : bankNum;
        break;
    }

    return bank * 0x4000 + offset + 0x8000;
  },

  /**
   *
   */
  mapForCHRROM: function(address) {
    var bank;
    var offset = address & 0x0FFF;

    if(this.controlRegister.loadBit(4) === 0) {

      // switch 8KB at a time

      bank = (this.chrBank0Register.load() & 0x1E);
      offset = offset | (address & 0x1000);
    } else {

      // switch two separate 4KB banks

      bank = ((address < 0x1000) ? this.chrBank0Register.load() : this.chrBank1Register.load()) & 0x1F;
    }

    return bank * 0x1000 + offset;
  },

  /**
   *
   */
  store: function(address, value) {
    if(value & 0x80) {
      this.registerWriteCount = 0;
      this.latch.clear();

      if((address & 0x6000) === 0)
        this.controlRegister.storeBits(2, 2, 3)
    } else {
      this.latch.store(((value & 1) << 4) | (this.latch.load() >> 1));
      this.registerWriteCount++;

      if(this.registerWriteCount >= 5) {
        var val = this.latch.load();

        switch(address & 0x6000) {
          case 0x0000:
            this.controlRegister.store(val);
            break;

          case 0x2000:
            this.chrBank0Register.store(val);
            break;

          case 0x4000:
            this.chrBank1Register.store(val);
            break;

          case 0x6000:
            this.prgBankRegister.store(val);
            break;
        }

        this.registerWriteCount = 0;
        this.latch.clear();
      }
    }
  },

  /**
   * TODO: Fix me
   */
  getMirroringType: function() {
    switch(this.controlRegister.loadBits(0, 2)) {
      case 0:
      case 1:
        return this.rom.MIRRORINGS.SINGLE_SCREEN;

      case 2:
        return this.rom.MIRRORINGS.VERTICAL;

      case 3:
        return this.rom.MIRRORINGS.HORIZONTAL;
    }
  }
});

/**
 *
 */
function UNROMMapper(rom) {
  Mapper.call(this, rom);
  this.reg = new Register8bit();
}

UNROMMapper.prototype = Object.assign(Object.create(Mapper.prototype), {
  isUNROMMapper: true,

  /**
   *
   */
  map: function(address) {
    var bank = (address < 0xC000) ? this.reg.load() : 7;
    var offset = address & 0x3fff;
    return 0x4000 * bank + offset + 0x8000;
  },

  /**
   *
   */
  store: function(address, value) {
    this.reg.store(value & 0x7);
  }
});

/**
 *
 */
function CNROMMapper(rom) {
  Mapper.call(this, rom);
  this.reg = new Register8bit();
}

CNROMMapper.prototype = Object.assign(Object.create(Mapper.prototype), {
  isCNROMMapper: true,

  /**
   *
   */
  mapForCHRROM: function(address) {
    return this.reg.load() * 0x2000 + (address & 0x1FFF);
  },

  /**
   *
   */
  store: function(address, value) {
    this.reg.store(value & 0xF);
  }
});

/**
 *
 */
function MMC3Mapper(rom) {
  Mapper.call(this, rom);
}

MMC3Mapper.prototype = Object.assign(Object.create(Mapper.prototype), {
  isMMC3Mapper: true,

  /**
   *
   */
  map: function(address) {
    // TODO: Fix me

    return address;
  },

  /**
   *
   */
  mapForCHRROM: function(address) {
    // TODO: Fix me

    return address;
  },

  /**
   *
   */
  store: function(address, value) {
    // TODO: Fix me

    address = address & 0xFFFF;  // just in case

    if(address >= 0x8000 && address < 0xA000) {
      if(address & 1 === 0) {

      } else {

      }
    } else if(address >= 0xA000 && address < 0xC000) {
      if(address & 1 === 0) {

      } else {

      }
    } else if(address >= 0xC000 && address < 0xE000) {
      if(address & 1 === 0) {

      } else {

      }
    } else {
      if(address & 1 === 0) {

      } else {

      }
    }
  }
});

/**
 *
 */
function Mapper76(rom) {
  Mapper.call(this, rom);
  this.addrReg = new Register8bit();
  this.chrReg0 = new Register8bit();
  this.chrReg1 = new Register8bit();
  this.chrReg2 = new Register8bit();
  this.chrReg3 = new Register8bit();
  this.prgReg0 = new Register8bit();
  this.prgReg1 = new Register8bit();
}

Mapper76.prototype = Object.assign(Object.create(Mapper.prototype), {
  isMapper76: true,

  /**
   *
   */
  map: function(address) {
    var bank;
    var offset = address & 0x1FFF;
    switch(address & 0x6000) {
      case 0x0000:
        bank = this.prgReg0.load();
        break;
      case 0x2000:
        bank = this.prgReg1.load();
        break;
      case 0x4000:
        bank = this.prgBankNum - 2;
        break;
      case 0x6000:
        bank = this.prgBankNum - 1;
        break;
    }
    return bank * 0x2000 + offset;
  },

  /**
   *
   */
  mapForCHRROM: function(address) {
    var bank;
    var offset = address & 0x7FF;
    switch(address & 0x1800) {
      case 0x0000:
        bank = this.chrReg0.load();
        break;
      case 0x0800:
        bank = this.chrReg1.load();
        break;
      case 0x1000:
        bank = this.chrReg2.load();
        break;
      case 0x1800:
        bank = this.chrReg3.load();
        break;
    }
    return bank * 0x800 + offset;
  },

  /**
   *
   */
  store: function(address, value) {
    if(address == 1) {
      var reg;
      switch(this.addrReg.load()) {
        case 0:
        case 1:
          return;
        case 2:
          reg = this.chrReg0;
          break;
        case 3:
          reg = this.chrReg1;
          break;
        case 4:
          reg = this.chrReg2;
          break;
        case 5:
          reg = this.chrReg3;
          break;
        case 6:
          reg = this.prgReg0;
          break;
        case 7:
          reg = this.prgReg1;
          break;
      }
      reg.store(value & 0x3F);
    } else {
      this.addrReg.store(value & 7);
    }
  }
});
<commit_msg>Fix UNROMMapper<commit_after>/**
 *
 */

/**
 *
 */
function MapperFactory() {

}

Object.assign(MapperFactory.prototype, {
  isMapperFactory: true,

  MAPPERS: [
    /* 0 */ {'name': 'NROM',  class: NROMMapper},
    /* 1 */ {'name': 'MMC1',  class: MMC1Mapper},
    /* 2 */ {'name': 'UNROM', class: UNROMMapper},
    /* 3 */ {'name': 'CNROM', class: CNROMMapper},
    /* 4 */ {'name': 'MMC3',  class: MMC3Mapper}
  ],

  /**
   *
   */
  getMapperParam: function(number) {
    if(this.MAPPERS[number] === undefined)
      throw new Error('unsupport No.' + number + ' Mapper');

    return this.MAPPERS[number];
  },

  /**
   *
   */
  create: function(number, rom) {
    return new (this.getMapperParam(number)).class(rom);
  },

  /**
   *
   */
  getName: function(number) {
    return this.getMapperParam(number).name;
  }
});

/**
 *
 */
function Mapper(rom) {
  this.rom = rom;
  this.prgBankNum = rom.header.getPRGROMBanksNum();
  this.chrBankNum = rom.header.getCHRROMBanksNum();
}

Object.assign(Mapper.prototype, {
  isMapper: true,

  /**
   *
   */
  map: function(address) {
    return address;
  },

  /**
   *
   */
  mapForCHRROM: function(address) {
    return address;
  },

  /**
   *
   */
  store: function(address, value) {
  },

  /**
   *
   */
  getMirroringType: function() {
    return this.rom.header.isHorizontalMirroring() === true
             ? this.rom.MIRRORINGS.HORIZONTAL : this.rom.MIRRORINGS.VERTICAL;
  }
});

/**
 *
 */
function NROMMapper(rom) {
  Mapper.call(this, rom);
}

NROMMapper.prototype = Object.assign(Object.create(Mapper.prototype), {
  isNROMMapper: true,

  /**
   *
   */
  map: function(address) {
    // 0x8000 - 0xBFFF: First 16 KB of ROM
    // 0xC000 - 0xFFFF: Last 16 KB of ROM (NROM-256) or
    //                  mirror of 0x8000 - 0xBFFF (NROM-128).

    if(this.prgBankNum === 1 && address >= 0xC000)
      address -= 0x4000;

    return address;
  }
});

/**
 *
 */
function MMC1Mapper(rom) {
  Mapper.call(this, rom);

  this.controlRegister = new Register8bit();  // register 0
  this.chrBank0Register = new Register8bit(); // register 1
  this.chrBank1Register = new Register8bit(); // register 2
  this.prgBankRegister = new Register8bit();  // register 3

  this.latch = new Register8bit();

  this.registerWriteCount = 0;

  this.controlRegister.store(0x0C);  // seems like 0xC would be default value
}

MMC1Mapper.prototype = Object.assign(Object.create(Mapper.prototype), {
  isMMC1Mapper: true,

  /**
   *
   */
  map: function(address) {
    var bank = 0;
    var offset = address & 0x3FFF;
    var bankNum = this.prgBankRegister.load() & 0x0F;

    switch(this.controlRegister.loadBits(2, 2)) {
      case 0:
      case 1:

        // switch 32KB at 0x8000, ignoring low bit of bank number

        // TODO: Fix me

        offset = offset | (address & 0x4000);
        bank = bankNum & 0x0E;
        break;

      case 2:

        // fix first bank at 0x8000 and switch 16KB bank at 0xC000

        bank = (address < 0xC000) ? 0 : bankNum;
        break;

      case 3:

        // fix last bank at 0xC000 and switch 16KB bank at 0x8000

        bank = (address >= 0xC000) ? this.prgBankNum - 1 : bankNum;
        break;
    }

    return bank * 0x4000 + offset + 0x8000;
  },

  /**
   *
   */
  mapForCHRROM: function(address) {
    var bank;
    var offset = address & 0x0FFF;

    if(this.controlRegister.loadBit(4) === 0) {

      // switch 8KB at a time

      bank = (this.chrBank0Register.load() & 0x1E);
      offset = offset | (address & 0x1000);
    } else {

      // switch two separate 4KB banks

      bank = ((address < 0x1000) ? this.chrBank0Register.load() : this.chrBank1Register.load()) & 0x1F;
    }

    return bank * 0x1000 + offset;
  },

  /**
   *
   */
  store: function(address, value) {
    if(value & 0x80) {
      this.registerWriteCount = 0;
      this.latch.clear();

      if((address & 0x6000) === 0)
        this.controlRegister.storeBits(2, 2, 3)
    } else {
      this.latch.store(((value & 1) << 4) | (this.latch.load() >> 1));
      this.registerWriteCount++;

      if(this.registerWriteCount >= 5) {
        var val = this.latch.load();

        switch(address & 0x6000) {
          case 0x0000:
            this.controlRegister.store(val);
            break;

          case 0x2000:
            this.chrBank0Register.store(val);
            break;

          case 0x4000:
            this.chrBank1Register.store(val);
            break;

          case 0x6000:
            this.prgBankRegister.store(val);
            break;
        }

        this.registerWriteCount = 0;
        this.latch.clear();
      }
    }
  },

  /**
   * TODO: Fix me
   */
  getMirroringType: function() {
    switch(this.controlRegister.loadBits(0, 2)) {
      case 0:
      case 1:
        return this.rom.MIRRORINGS.SINGLE_SCREEN;

      case 2:
        return this.rom.MIRRORINGS.VERTICAL;

      case 3:
        return this.rom.MIRRORINGS.HORIZONTAL;
    }
  }
});

/**
 *
 */
function UNROMMapper(rom) {
  Mapper.call(this, rom);
  this.reg = new Register8bit();
}

UNROMMapper.prototype = Object.assign(Object.create(Mapper.prototype), {
  isUNROMMapper: true,

  /**
   *
   */
  map: function(address) {
    var bank = (address < 0xC000) ? this.reg.load() : this.prgBankNum - 1;
    var offset = address & 0x3FFF;
    return 0x4000 * bank + offset + 0x8000;
  },

  /**
   *
   */
  store: function(address, value) {
    this.reg.store(value & 0xF);
  }
});

/**
 *
 */
function CNROMMapper(rom) {
  Mapper.call(this, rom);
  this.reg = new Register8bit();
}

CNROMMapper.prototype = Object.assign(Object.create(Mapper.prototype), {
  isCNROMMapper: true,

  /**
   *
   */
  mapForCHRROM: function(address) {
    return this.reg.load() * 0x2000 + (address & 0x1FFF);
  },

  /**
   *
   */
  store: function(address, value) {
    this.reg.store(value & 0xF);
  }
});

/**
 *
 */
function MMC3Mapper(rom) {
  Mapper.call(this, rom);
}

MMC3Mapper.prototype = Object.assign(Object.create(Mapper.prototype), {
  isMMC3Mapper: true,

  /**
   *
   */
  map: function(address) {
    // TODO: Fix me

    return address;
  },

  /**
   *
   */
  mapForCHRROM: function(address) {
    // TODO: Fix me

    return address;
  },

  /**
   *
   */
  store: function(address, value) {
    // TODO: Fix me

    address = address & 0xFFFF;  // just in case

    if(address >= 0x8000 && address < 0xA000) {
      if(address & 1 === 0) {

      } else {

      }
    } else if(address >= 0xA000 && address < 0xC000) {
      if(address & 1 === 0) {

      } else {

      }
    } else if(address >= 0xC000 && address < 0xE000) {
      if(address & 1 === 0) {

      } else {

      }
    } else {
      if(address & 1 === 0) {

      } else {

      }
    }
  }
});

/**
 *
 */
function Mapper76(rom) {
  Mapper.call(this, rom);
  this.addrReg = new Register8bit();
  this.chrReg0 = new Register8bit();
  this.chrReg1 = new Register8bit();
  this.chrReg2 = new Register8bit();
  this.chrReg3 = new Register8bit();
  this.prgReg0 = new Register8bit();
  this.prgReg1 = new Register8bit();
}

Mapper76.prototype = Object.assign(Object.create(Mapper.prototype), {
  isMapper76: true,

  /**
   *
   */
  map: function(address) {
    var bank;
    var offset = address & 0x1FFF;
    switch(address & 0x6000) {
      case 0x0000:
        bank = this.prgReg0.load();
        break;
      case 0x2000:
        bank = this.prgReg1.load();
        break;
      case 0x4000:
        bank = this.prgBankNum - 2;
        break;
      case 0x6000:
        bank = this.prgBankNum - 1;
        break;
    }
    return bank * 0x2000 + offset;
  },

  /**
   *
   */
  mapForCHRROM: function(address) {
    var bank;
    var offset = address & 0x7FF;
    switch(address & 0x1800) {
      case 0x0000:
        bank = this.chrReg0.load();
        break;
      case 0x0800:
        bank = this.chrReg1.load();
        break;
      case 0x1000:
        bank = this.chrReg2.load();
        break;
      case 0x1800:
        bank = this.chrReg3.load();
        break;
    }
    return bank * 0x800 + offset;
  },

  /**
   *
   */
  store: function(address, value) {
    if(address == 1) {
      var reg;
      switch(this.addrReg.load()) {
        case 0:
        case 1:
          return;
        case 2:
          reg = this.chrReg0;
          break;
        case 3:
          reg = this.chrReg1;
          break;
        case 4:
          reg = this.chrReg2;
          break;
        case 5:
          reg = this.chrReg3;
          break;
        case 6:
          reg = this.prgReg0;
          break;
        case 7:
          reg = this.prgReg1;
          break;
      }
      reg.store(value & 0x3F);
    } else {
      this.addrReg.store(value & 7);
    }
  }
});
<|endoftext|>