<commit_before>var WOLF_AMOUNT = 1;
var WOLF_SIZE;
var WOLF_SPEED = 75;

var WOLF_STATE_ATTACKING = 1;
var WOLF_STATE_HUNTING = 2;
var WOLF_STATE_RETREAT = 3;

var WOLF_EATING_TIME = 3000;
var KILL_DISTANCE;

var WOLF_SPAWN_DISTANCE;
var WOLF_SPAWN_TIME = 3;
var WOLF_WIMP_COOLDOWN_RESET = 2;
var WOLF_STRESS_MIN = 0;
var WOLF_STRESS_MAX = 15;
var WOLF_STRESS_THRESHOLD = 10.0;
var WOLF_STRESS_RUN_SPEED = 150;
var WOLF_STRESS_DOG_PROXIMITY_RANGE;
var WOLF_STRESS_RANGE_CONTRIB_PER_SECOND = 2.0;
var WOLF_STRESS_COOLDOWN_PER_SECOND = WOLF_STRESS_RANGE_CONTRIB_PER_SECOND * 0.15

var wolfs;
var wolfNextRespawn = WOLF_SPAWN_TIME;

function wolf_init()
{
    wolfs = [];
    WOLF_SIZE = TILE_SIZE * 0.25;
    KILL_DISTANCE = SHEEP_SIZE * 3.0;
    WOLF_SPAWN_DISTANCE = TILE_SIZE * MAP_SIZE * 0.5;
    WOLF_STRESS_DOG_PROXIMITY_RANGE = DOG_SIZE * 8.0;

    for (var i = 0; i < WOLF_AMOUNT; i++)
    {
        wolf_spawn();
    }
}

function wolf_create(wolfPos)
{
    var wolf = {
        dir: 'e',
        position: new Vector2(wolfPos),
        state: WOLF_STATE_HUNTING,
        size: WOLF_SIZE,
        stress: WOLF_STRESS_MIN,
        target: null,
        retreatPosition: new Vector2(0,0),
        wimperCoolDown: 0,
        renderFn: wolf_render,
        fearFactor: 10
    };

    wolf.spriteAnim = playSpriteAnim("wolf.spriteanim", "run_e");

    return wolf;
}

function wolf_render(wolf)
{
//    SpriteBatch.drawSprite(null, wolf.position, Color.BLACK, 0, 20);
    SpriteBatch.drawSpriteAnim(wolf.spriteAnim, wolf.position);
}

function wolf_spawn()
{
    var wolfTryPos = Random.randCircleEdge(MAP_CENTER, WOLF_SPAWN_DISTANCE);
    var wolf = wolf_create(wolfTryPos)
    wolfs.push(wolf);
    pushers.push(wolf);
    renderables.push(wolf);
}

function wolfs_update(dt)
{
    if (sheeps.length > 0)
    {
        wolfNextRespawn -= dt;
        if (wolfNextRespawn < 0)
        {
            wolf_spawn();
            wolfNextRespawn = WOLF_SPAWN_TIME;
        }
    }
    for (var i = 0; i < wolfs.length; ++i)
    {
        var wolf = wolfs[i];
        wolf_update(wolf, dt);
    }
}

function wolf_targetAcquisition(wolf, sheep)
{
    if (!sheep || !sheep_isAlive(sheep)) return;
    if (!wolf.target)
    {
        wolf.target = sheep;
        return;
    }

    var distance = Vector2.distance(sheep.position, wolf.position);
    var currentTargetDistance = Vector2.distance(wolf.target.position, wolf.position);
    if (distance < currentTargetDistance)
    {
        wolf.target = sheep;
    }
}

function wolf_moveToward(wolf, targetPosition, speed, dt)
{
    var distance = Vector2.distance(targetPosition, wolf.position);
    if (distance > 0)
    {
        distance -= speed * dt;
        if (distance < 0)
        {
            distance = 0;
            wolf.position = targetPosition;
            return true;
        }
        var dir = targetPosition.sub(wolf.position).normalize();
        wolf.position = wolf.position.add(dir.mul(speed * dt));
        if (dir.x > .1) wolf.spriteAnim.play("run_e");
        else if (dir.x < -.1) wolf.spriteAnim.play("run_w");
    }
    return true;
}

function wolf_calculateStress(wolf, dt)
{
    for (var i = 0; i < dogs.length; ++i)
    {
        var dog = dogs[i];

        var distance = Vector2.distance(wolf.position, dog.position);

        // barking dogs only stress the wolves if the dog is close enough.
        if (distance <= WOLF_STRESS_DOG_PROXIMITY_RANGE)
        {
            wolf.stress = Math.min(wolf.stress + (dog.fearFactor * WOLF_STRESS_RANGE_CONTRIB_PER_SECOND * dt), WOLF_STRESS_MAX);

            if (wolf.stress > WOLF_STRESS_THRESHOLD)
            {
                // running away 1000 miles away from the dog. Wolf will most likely never reach this destination because the wolf
                // will turn around as soon as the wolf's stress level comes back to normal.
                var factor = new Vector2(TILE_SIZE);
                wolf.retreatPosition = wolf.position.add(factor.mul(wolf.position.sub(cameraPos)));

                if (wolf.wimperCoolDown <= 0)
                {
                    playSound("SFX_dog_wimper_" + Random.randInt(1, 2) + ".wav", 0.5);
                    wolf.wimperCoolDown = WOLF_WIMP_COOLDOWN_RESET;
                }
            }
        }
    }
}

function wolf_update(wolf, dt)
{
    WOLF_SPAWN_TIME = Math.max(3 - ((20 - sheeps.length)/5), 0.5);
    wolf_calculateStress(wolf, dt);

    if (wolf.stress > WOLF_STRESS_THRESHOLD &&
        wolf.state != WOLF_STATE_ATTACKING)
    {
        wolf.state = WOLF_STATE_RETREAT;
    }

    switch (wolf.state)
    {
        case WOLF_STATE_HUNTING:
            if (wolf.target && !sheep_isAlive(wolf.target)) // If the target was killed by another wolf
            {
                wolf.target = null; // We need to redo the aquisition
            }
            // Make sure we have to closest sheep
            for (var i = 0; i < sheeps.length; i++)
            {
                wolf_targetAcquisition(wolf, sheeps[i]);
            }
            if (!wolf.target) break;
            wolf_moveToward(wolf, wolf.target.position, WOLF_SPEED, dt);
            var targetDistance = +Vector2.distance(wolf.target.position, wolf.position);
            if (targetDistance <= KILL_DISTANCE)
            {
                wolf.state = WOLF_STATE_ATTACKING;
                wolf.position = wolf.target.position;
                sheep_attackedByWolf(wolf.target);
                wolf.spriteAnim.play("eat_" + wolf.dir);
                wolf.attackTime = 2;
                for (var i = 0; i < 3; ++i)
                {
                    setTimeout(function ()
                    {
                        var emitter = emitParticles(getParticleSystem("blood.pfx"), new Vector3(wolf.position.x, wolf.position.y, 0));
                        emitter.setRenderEnabled(false);
                        particles.push(emitter);
                        playSound("SFX_Dog_Growl_" + Random.randInt(1, 11) + ".wav");
                        splat_spawn(
                            Random.randVector2(
                                new Vector2(wolf.position.x - TILE_SIZE / 2, wolf.position.y - TILE_SIZE / 2),
                                new Vector2(wolf.position.x + TILE_SIZE / 2, wolf.position.y + TILE_SIZE / 2)));
                    }, 500 * (i));
                }
            }
            break;
        case WOLF_STATE_ATTACKING:
            wolf.attackTime -= dt;
            if (wolf.attackTime <= 0)
            {
                if (wolf.target) sheep_kill_instantly(wolf.target);
                wolf.state = WOLF_STATE_HUNTING;
                wolf.spriteAnim.play("run_" + wolf.dir);
            }
            break;
        case WOLF_STATE_RETREAT:
            wolf.wimperCoolDown -= dt;
            wolf_moveToward(wolf, wolf.retreatPosition, WOLF_STRESS_RUN_SPEED, dt);
            if (wolf.stress <= WOLF_STRESS_THRESHOLD && sheeps.length > 0)
            {
                wolf.state = WOLF_STATE_HUNTING;
            }
            break;
    }

    // wolf's stress level cools down over time.
    wolf.stress = Math.max(wolf.stress-(WOLF_STRESS_COOLDOWN_PER_SECOND*dt), WOLF_STRESS_MIN);

}<commit_msg>more difficulty balancing<commit_after>var WOLF_AMOUNT = 1;
var WOLF_SIZE;
var WOLF_SPEED = 75;

var WOLF_STATE_ATTACKING = 1;
var WOLF_STATE_HUNTING = 2;
var WOLF_STATE_RETREAT = 3;

var WOLF_EATING_TIME = 3000;
var KILL_DISTANCE;

var WOLF_SPAWN_DISTANCE;
var WOLF_SPAWN_TIME = 3;
var WOLF_WIMP_COOLDOWN_RESET = 2;
var WOLF_STRESS_MIN = 0;
var WOLF_STRESS_MAX = 15;
var WOLF_STRESS_THRESHOLD = 10.0;
var WOLF_STRESS_RUN_SPEED = 150;
var WOLF_STRESS_DOG_PROXIMITY_RANGE;
var WOLF_STRESS_RANGE_CONTRIB_PER_SECOND = 2.0;
var WOLF_STRESS_COOLDOWN_PER_SECOND = WOLF_STRESS_RANGE_CONTRIB_PER_SECOND * 0.15

var wolfs;
var wolfNextRespawn = WOLF_SPAWN_TIME;

function wolf_init()
{
    wolfs = [];
    WOLF_SPEED = 75;
    WOLF_SIZE = TILE_SIZE * 0.25;
    KILL_DISTANCE = SHEEP_SIZE * 3.0;
    WOLF_SPAWN_DISTANCE = TILE_SIZE * MAP_SIZE * 0.5;
    WOLF_STRESS_DOG_PROXIMITY_RANGE = DOG_SIZE * 4.0;

    for (var i = 0; i < WOLF_AMOUNT; i++)
    {
        wolf_spawn();
    }
}

function wolf_create(wolfPos)
{
    var wolf = {
        dir: 'e',
        position: new Vector2(wolfPos),
        state: WOLF_STATE_HUNTING,
        size: WOLF_SIZE,
        stress: WOLF_STRESS_MIN,
        target: null,
        retreatPosition: new Vector2(0,0),
        wimperCoolDown: 0,
        renderFn: wolf_render,
        fearFactor: 10
    };

    wolf.spriteAnim = playSpriteAnim("wolf.spriteanim", "run_e");

    return wolf;
}

function wolf_render(wolf)
{
//    SpriteBatch.drawSprite(null, wolf.position, Color.BLACK, 0, 20);
    SpriteBatch.drawSpriteAnim(wolf.spriteAnim, wolf.position);
}

function wolf_spawn()
{
    var wolfTryPos = Random.randCircleEdge(MAP_CENTER, WOLF_SPAWN_DISTANCE);
    var wolf = wolf_create(wolfTryPos)
    wolfs.push(wolf);
    pushers.push(wolf);
    renderables.push(wolf);
}

function wolfs_update(dt)
{
    if (sheeps.length > 0)
    {
        wolfNextRespawn -= dt;
        if (wolfNextRespawn < 0)
        {
            wolf_spawn();
            wolfNextRespawn = WOLF_SPAWN_TIME;
        }
    }
    for (var i = 0; i < wolfs.length; ++i)
    {
        var wolf = wolfs[i];
        wolf_update(wolf, dt);
    }
}

function wolf_targetAcquisition(wolf, sheep)
{
    if (!sheep || !sheep_isAlive(sheep)) return;
    if (!wolf.target)
    {
        wolf.target = sheep;
        return;
    }

    var distance = Vector2.distance(sheep.position, wolf.position);
    var currentTargetDistance = Vector2.distance(wolf.target.position, wolf.position);
    if (distance < currentTargetDistance)
    {
        wolf.target = sheep;
    }
}

function wolf_moveToward(wolf, targetPosition, speed, dt)
{
    var distance = Vector2.distance(targetPosition, wolf.position);
    if (distance > 0)
    {
        distance -= speed * dt;
        if (distance < 0)
        {
            distance = 0;
            wolf.position = targetPosition;
            return true;
        }
        var dir = targetPosition.sub(wolf.position).normalize();
        wolf.position = wolf.position.add(dir.mul(speed * dt));
        if (dir.x > .1) wolf.spriteAnim.play("run_e");
        else if (dir.x < -.1) wolf.spriteAnim.play("run_w");
    }
    return true;
}

function wolf_calculateStress(wolf, dt)
{
    for (var i = 0; i < dogs.length; ++i)
    {
        var dog = dogs[i];

        var distance = Vector2.distance(wolf.position, dog.position);

        // barking dogs only stress the wolves if the dog is close enough.
        if (distance <= WOLF_STRESS_DOG_PROXIMITY_RANGE)
        {
            wolf.stress = Math.min(wolf.stress + (dog.fearFactor*3 * WOLF_STRESS_RANGE_CONTRIB_PER_SECOND * dt), WOLF_STRESS_MAX);

            if (wolf.stress > WOLF_STRESS_THRESHOLD)
            {
                // running away 1000 miles away from the dog. Wolf will most likely never reach this destination because the wolf
                // will turn around as soon as the wolf's stress level comes back to normal.
                var factor = new Vector2(TILE_SIZE);
                wolf.retreatPosition = wolf.position.add(factor.mul(wolf.position.sub(cameraPos)));

                if (wolf.wimperCoolDown <= 0)
                {
                    playSound("SFX_dog_wimper_" + Random.randInt(1, 2) + ".wav", 0.5);
                    wolf.wimperCoolDown = WOLF_WIMP_COOLDOWN_RESET;
                }
            }
        }
    }
}

function wolf_update(wolf, dt)
{
    WOLF_SPAWN_TIME = Math.max(3 - ((20 - sheeps.length)/5), 0.5);
    WOLF_SPEED = 75 + ((20 - sheeps.length)*5);
    wolf_calculateStress(wolf, dt);

    if (wolf.stress > WOLF_STRESS_THRESHOLD &&
        wolf.state != WOLF_STATE_ATTACKING)
    {
        wolf.state = WOLF_STATE_RETREAT;
    }

    switch (wolf.state)
    {
        case WOLF_STATE_HUNTING:
            if (wolf.target && !sheep_isAlive(wolf.target)) // If the target was killed by another wolf
            {
                wolf.target = null; // We need to redo the aquisition
            }
            // Make sure we have to closest sheep
            for (var i = 0; i < sheeps.length; i++)
            {
                wolf_targetAcquisition(wolf, sheeps[i]);
            }
            if (!wolf.target) break;
            wolf_moveToward(wolf, wolf.target.position, WOLF_SPEED, dt);
            var targetDistance = +Vector2.distance(wolf.target.position, wolf.position);
            if (targetDistance <= KILL_DISTANCE)
            {
                wolf.state = WOLF_STATE_ATTACKING;
                wolf.position = wolf.target.position;
                sheep_attackedByWolf(wolf.target);
                wolf.spriteAnim.play("eat_" + wolf.dir);
                wolf.attackTime = 2;
                for (var i = 0; i < 3; ++i)
                {
                    setTimeout(function ()
                    {
                        var emitter = emitParticles(getParticleSystem("blood.pfx"), new Vector3(wolf.position.x, wolf.position.y, 0));
                        emitter.setRenderEnabled(false);
                        particles.push(emitter);
                        playSound("SFX_Dog_Growl_" + Random.randInt(1, 11) + ".wav");
                        splat_spawn(
                            Random.randVector2(
                                new Vector2(wolf.position.x - TILE_SIZE / 2, wolf.position.y - TILE_SIZE / 2),
                                new Vector2(wolf.position.x + TILE_SIZE / 2, wolf.position.y + TILE_SIZE / 2)));
                    }, 500 * (i));
                }
            }
            break;
        case WOLF_STATE_ATTACKING:
            wolf.attackTime -= dt;
            if (wolf.attackTime <= 0)
            {
                if (wolf.target) sheep_kill_instantly(wolf.target);
                wolf.state = WOLF_STATE_HUNTING;
                wolf.spriteAnim.play("run_" + wolf.dir);
            }
            break;
        case WOLF_STATE_RETREAT:
            wolf.wimperCoolDown -= dt;
            wolf_moveToward(wolf, wolf.retreatPosition, WOLF_STRESS_RUN_SPEED, dt);
            if (wolf.stress <= WOLF_STRESS_THRESHOLD && sheeps.length > 0)
            {
                wolf.state = WOLF_STATE_HUNTING;
            }
            break;
    }

    // wolf's stress level cools down over time.
    wolf.stress = Math.max(wolf.stress-(WOLF_STRESS_COOLDOWN_PER_SECOND*dt), WOLF_STRESS_MIN);

}<|endoftext|>


<commit_before>function runTest()
{
    FBTest.sysout("issue5130.START");
    FBTest.openNewTab(basePath + "commandLine/5130/issue5130.html", function(win)
    {
        FBTest.openFirebug();
        FBTest.clearCache();
        FBTest.enableConsolePanel(function(win)
        {
            var tasks = new FBTest.TaskList();

            var expr = "console.dir([0,1,2,3,4,5,6,7,8,9,10]);";
            var expected = /\s*00\s*11\s*22\s*33\s*44\s*55\s*66\s*77\s*88\s*99\s*1010/;
            tasks.push(FBTest.executeCommandAndVerify, expr, expected,
                "div", "logRow logRow-dir");

            tasks.run(function() {
                FBTest.testDone("issue5130.DONE");
            });
        });
    });
}
<commit_msg>Fixed FBTest commandLine/5130/issue5130.js<commit_after>function runTest()
{
    FBTest.sysout("issue5130.START");
    FBTest.openNewTab(basePath + "commandLine/5130/issue5130.html", function(win)
    {
        FBTest.openFirebug();
        FBTest.clearCache();
        FBTest.enableConsolePanel(function(win)
        {
            var tasks = new FBTest.TaskList();

            var expr = "console.dir([0,1,2,3,4,5,6,7,8,9,10]);";
            var expected = new RegExp("0\\s*0\\s*1\\s*1\\s*2\\s*2\\s*3\\s*3\\s*4\\s*4\\s*5\\s*5" +
                "\\s*6\\s*6\\s*7\\s*7\\s*8\\s*8\\s*9\\s*9\\s*10\\s*10");
            tasks.push(FBTest.executeCommandAndVerify, expr, expected,
                "div", "logRow logRow-dir");

            tasks.run(function() {
                FBTest.testDone("issue5130.DONE");
            });
        });
    });
}
<|endoftext|>


<commit_before>"use strict";

/*
 * Sir Trevor Editor
 * --
 * Represents one Sir Trevor editor instance (with multiple blocks)
 * Each block references this instance.
 * BlockTypes are global however.
 */

var _ = require('./lodash');
var config = require('./config');
var utils = require('./utils');
var Dom = require('./packages/dom');

var Events = require('./events');
var EventBus = require('./event-bus');
var FormEvents = require('./form-events');
var BlockControls = require('./block-controls');
var BlockAddition = require('./block-addition');
var BlockAdditionTop = require('./block-addition-top');
var BlockManager = require('./block-manager');
var FormatBar = require('./format-bar');
var EditorStore = require('./extensions/editor-store');
var ErrorHandler = require('./error-handler');

var Editor = function(options) {
  this.initialize(options);
};

Object.assign(Editor.prototype, require('./function-bind'), require('./events'), {

  bound: ['onFormSubmit', 'hideAllTheThings', 'changeBlockPosition',
    'removeBlockDragOver', 'blockLimitReached', 'blockOrderUpdated'],

  events: {
    'block:reorder:dragend': 'removeBlockDragOver',
    'block:reorder:dropped': 'removeBlockDragOver',
    'block:content:dropped': 'removeBlockDragOver'
  },

  initialize: function(options) {
    utils.log("Init SirTrevor.Editor");

    this.options = Object.assign({}, config.defaults, options || {});
    this.ID = _.uniqueId('st-editor-');

    if (!this._ensureAndSetElements()) { return false; }

    if(!_.isUndefined(this.options.onEditorRender) &&
       _.isFunction(this.options.onEditorRender)) {
      this.onEditorRender = this.options.onEditorRender;
    }

    // Mediated events for *this* Editor instance
    this.mediator = Object.assign({}, Events);

    this._bindFunctions();

    config.instances.push(this);

    this.build();

    FormEvents.bindFormSubmit(this.form);
  },

  /*
   * Build the Editor instance.
   * Check to see if we've been passed JSON already, and if not try and
   * create a default block.
   * If we have JSON then we need to build all of our blocks from this.
   */
  build: function() {
    Dom.hide(this.el);

    this.errorHandler = new ErrorHandler(this.outer, this.mediator, this.options.errorsContainer);
    this.store = new EditorStore(this.el.value, this.mediator);

    this.blockManager = new BlockManager(this);
    this.blockAddition = BlockAddition.create(this);
    this.BlockAdditionTop = BlockAdditionTop.create(this);
    this.blockControls = BlockControls.create(this);

    this.formatBar = new FormatBar(this.options.formatBar, this.mediator, this);

    this.mediator.on('block:changePosition', this.changeBlockPosition);
    this.mediator.on('block:limitReached', this.blockLimitReached);

    // Apply specific classes when block order is updated
    this.mediator.on('block:rerender', this.blockOrderUpdated);
    this.mediator.on('block:create', this.blockOrderUpdated);
    this.mediator.on('block:remove', this.blockOrderUpdated);
    this.mediator.on('block:replace', this.blockOrderUpdated);

    this.dataStore = "Please use store.retrieve();";

    this._setEvents();

    // External event listeners
    window.addEventListener('click', this.hideAllTheThings);
    document.body.addEventListener('keydown', this.disableBackButton);

    this.createBlocks();
    this.wrapper.classList.add('st-ready');

    if(!_.isUndefined(this.onEditorRender)) {
      this.onEditorRender();
    }
  },

  createBlocks: function() {
    var store = this.store.retrieve();

    if (store.data.length > 0) {
      store.data.forEach(function(block) {
        this.mediator.trigger('block:create', block.type, block.data);
      }, this);
    } else if (this.options.defaultType !== false) {
      this.mediator.trigger('block:create', this.options.defaultType, {});

      if (this.options.focusOnInit) {
        var blockElement = this.wrapper.querySelectorAll('.st-block')[0];

        if (blockElement) {
          var block = this.blockManager.findBlockById(blockElement.getAttribute('id'));
          block.focus();
        }
      }
    }
  },

  destroy: function() {
    // Destroy the rendered sub views
    this.formatBar.destroy();
    this.blockAddition.destroy();
    this.blockControls.destroy();

    // Destroy all blocks
    this.blockManager.blocks.forEach(function(block) {
      this.mediator.trigger('block:remove', block.blockID);
    }, this);

    // Stop listening to events
    this.mediator.stopListening();
    this.stopListening();

    // Remove instance
    config.instances = config.instances.filter(function(instance) {
      return instance.ID !== this.ID;
    }, this);

    // Remove external event listeners
    window.removeEventListener('click', this.hideAllTheThings);
    document.body.removeEventListener('keydown', this.disableBackButton);

    // Clear the store
    this.store.reset();
    Dom.replaceWith(this.outer, this.el);
  },

  reinitialize: function(options) {
    this.destroy();
    this.initialize(options || this.options);
  },

  blockLimitReached: function(toggle) {
    this.wrapper.classList.toggle('st--block-limit-reached', toggle);
  },

  blockOrderUpdated: function() {
    // Detect first block and decide whether to hide top controls
    var blockElement = this.wrapper.querySelectorAll('.st-block')[0];
    var hideTopControls = false;

    if (blockElement) {
      var block = this.blockManager.findBlockById(
        blockElement.getAttribute('id')
      );
      hideTopControls = block && block.textable;
    }

    this._toggleHideTopControls(hideTopControls);
  },

  _toggleHideTopControls: function(toggle) {
    this.wrapper.classList.toggle('st--hide-top-controls', toggle);
  },

  _setEvents: function() {
    Object.keys(this.events).forEach(function(type) {
      EventBus.on(type, this[this.events[type]], this);
    }, this);
  },

  hideAllTheThings: function(e) {
    this.blockControls.hide();
    this.blockAddition.hide();

    if (document.activeElement.getAttribute('contenteditable') === null) {
      this.formatBar.hide();
    }

    var popupSelectors = '.st-block__ui-delete-controls';
    Array.prototype.forEach.call(this.wrapper.querySelectorAll(popupSelectors), function(el) {
      el.classList.remove('active');
    });
  },

  store: function(method, options){
    utils.log("The store method has been removed, please call store[methodName]");
    return this.store[method].call(this, options || {});
  },

  removeBlockDragOver: function() {
    var dragOver = this.outer.querySelector('.st-drag-over');
    if (!dragOver) { return; }
    dragOver.classList.remove('st-drag-over');
  },

  changeBlockPosition: function(block, selectedPosition) {
    selectedPosition = selectedPosition - 1;

    var blockPosition = this.blockManager.getBlockPosition(block),
    blockBy = this.wrapper.querySelectorAll('.st-block')[selectedPosition];

    if(blockBy && blockBy.getAttribute('id') !== block.getAttribute('id')) {
      this.hideAllTheThings();
      if (blockPosition > selectedPosition) {
        blockBy.parentNode.insertBefore(block, blockBy);
      } else {
        Dom.insertAfter(block, blockBy);
      }
    }
  },

  /*
   * Handle a form submission of this Editor instance.
   * Validate all of our blocks, and serialise all data onto the JSON objects
   */
  onFormSubmit: function(shouldValidate) {
    // if undefined or null or anything other than false - treat as true
    shouldValidate = (shouldValidate === false) ? false : true;

    utils.log("Handling form submission for Editor " + this.ID);

    this.mediator.trigger('errors:reset');
    this.store.reset();

    this.validateBlocks(shouldValidate);
    this.blockManager.validateBlockTypesExist(shouldValidate);

    this.mediator.trigger('errors:render');
    this.el.value = this.store.toString();

    return this.errorHandler.errors.length;
  },

  /*
   * Call `validateAndSaveBlock` on each block found in the dom.
   */

  validateBlocks: function(shouldValidate) {
    Array.prototype.forEach.call(this.wrapper.querySelectorAll('.st-block'), (block, idx) => {
      var _block = this.blockManager.findBlockById(block.getAttribute('id'));
      if (!_.isUndefined(_block)) {
        this.validateAndSaveBlock(_block, shouldValidate);
      }
    });
  },

  /*
   * If block should be validated and is not valid then register an error.
   * Empty text blocks should be ignored.
   * Save any other valid blocks to the editor data store.
   */

  validateAndSaveBlock: function(block, shouldValidate) {
    if (!config.skipValidation && shouldValidate && !block.valid()) {
      this.mediator.trigger('errors:add', { text: _.result(block, 'validationFailMsg') });
      utils.log("Block " + block.blockID + " failed validation");
      return;
    }

    if (block.type === 'text' && block.isEmpty()) {
      return;
    }

    var blockData = block.getData();
    utils.log("Adding data for block " + block.blockID + " to block store:",
              blockData);
    this.store.addData(blockData);
  },

  /*
   * Disable back button so when a block loses focus the user
   * pressing backspace multiple times doesn't close the page.
   */
  disableBackButton: function(e) {
    var target = e.target || e.srcElement;
    if (e.keyCode === 8) {
      if (target.getAttribute('contenteditable') ||
          target.tagName === 'INPUT' ||
          target.tagName === 'TEXTAREA') {
        return;
      }

      e.preventDefault();
    }
  },

  findBlockById: function(block_id) {
    return this.blockManager.findBlockById(block_id);
  },

  getBlocksByType: function(block_type) {
    return this.blockManager.getBlocksByType(block_type);
  },

  getBlocksByIDs: function(block_ids) {
    return this.blockManager.getBlocksByIDs(block_ids);
  },

  getBlockPosition: function(block) {
    utils.log("This method has been moved to blockManager.getBlockPosition()");
    return this.blockManager.getBlockPosition(block);
  },

  /*
   * Set all dom elements required for the editor.
   */

  _ensureAndSetElements: function() {
    if(_.isUndefined(this.options.el)) {
      utils.log("You must provide an el");
      return false;
    }

    this.el = this.options.el;
    this.form = Dom.getClosest(this.el, 'form');

    var outer = Dom.createElement("div", {
                  'id': this.ID,
                  'class': 'st-outer notranslate',
                  'dropzone': 'copy link move'});

    var wrapper = Dom.createElement("div", {'class': 'st-blocks'});

    // Wrap our element in lots of containers *eww*

    Dom.wrap(Dom.wrap(this.el, outer), wrapper);

    this.outer = this.form.querySelector('#' + this.ID);
    this.wrapper = this.outer.querySelector('.st-blocks');

    return true;
  }

});

module.exports = Editor;
<commit_msg>Adds an easy way to get instance's data using js.<commit_after>"use strict";

/*
 * Sir Trevor Editor
 * --
 * Represents one Sir Trevor editor instance (with multiple blocks)
 * Each block references this instance.
 * BlockTypes are global however.
 */

var _ = require('./lodash');
var config = require('./config');
var utils = require('./utils');
var Dom = require('./packages/dom');

var Events = require('./events');
var EventBus = require('./event-bus');
var FormEvents = require('./form-events');
var BlockControls = require('./block-controls');
var BlockAddition = require('./block-addition');
var BlockAdditionTop = require('./block-addition-top');
var BlockManager = require('./block-manager');
var FormatBar = require('./format-bar');
var EditorStore = require('./extensions/editor-store');
var ErrorHandler = require('./error-handler');

var Editor = function(options) {
  this.initialize(options);
};

Object.assign(Editor.prototype, require('./function-bind'), require('./events'), {

  bound: ['onFormSubmit', 'hideAllTheThings', 'changeBlockPosition',
    'removeBlockDragOver', 'blockLimitReached', 'blockOrderUpdated'],

  events: {
    'block:reorder:dragend': 'removeBlockDragOver',
    'block:reorder:dropped': 'removeBlockDragOver',
    'block:content:dropped': 'removeBlockDragOver'
  },

  initialize: function(options) {
    utils.log("Init SirTrevor.Editor");

    this.options = Object.assign({}, config.defaults, options || {});
    this.ID = _.uniqueId('st-editor-');

    if (!this._ensureAndSetElements()) { return false; }

    if(!_.isUndefined(this.options.onEditorRender) &&
       _.isFunction(this.options.onEditorRender)) {
      this.onEditorRender = this.options.onEditorRender;
    }

    // Mediated events for *this* Editor instance
    this.mediator = Object.assign({}, Events);

    this._bindFunctions();

    config.instances.push(this);

    this.build();

    FormEvents.bindFormSubmit(this.form);
  },

  /*
   * Build the Editor instance.
   * Check to see if we've been passed JSON already, and if not try and
   * create a default block.
   * If we have JSON then we need to build all of our blocks from this.
   */
  build: function() {
    Dom.hide(this.el);

    this.errorHandler = new ErrorHandler(this.outer, this.mediator, this.options.errorsContainer);
    this.store = new EditorStore(this.el.value, this.mediator);

    this.blockManager = new BlockManager(this);
    this.blockAddition = BlockAddition.create(this);
    this.BlockAdditionTop = BlockAdditionTop.create(this);
    this.blockControls = BlockControls.create(this);

    this.formatBar = new FormatBar(this.options.formatBar, this.mediator, this);

    this.mediator.on('block:changePosition', this.changeBlockPosition);
    this.mediator.on('block:limitReached', this.blockLimitReached);

    // Apply specific classes when block order is updated
    this.mediator.on('block:rerender', this.blockOrderUpdated);
    this.mediator.on('block:create', this.blockOrderUpdated);
    this.mediator.on('block:remove', this.blockOrderUpdated);
    this.mediator.on('block:replace', this.blockOrderUpdated);

    this.dataStore = "Please use store.retrieve();";

    this._setEvents();

    // External event listeners
    window.addEventListener('click', this.hideAllTheThings);
    document.body.addEventListener('keydown', this.disableBackButton);

    this.createBlocks();
    this.wrapper.classList.add('st-ready');

    if(!_.isUndefined(this.onEditorRender)) {
      this.onEditorRender();
    }
  },

  createBlocks: function() {
    var store = this.store.retrieve();

    if (store.data.length > 0) {
      store.data.forEach(function(block) {
        this.mediator.trigger('block:create', block.type, block.data);
      }, this);
    } else if (this.options.defaultType !== false) {
      this.mediator.trigger('block:create', this.options.defaultType, {});

      if (this.options.focusOnInit) {
        var blockElement = this.wrapper.querySelectorAll('.st-block')[0];

        if (blockElement) {
          var block = this.blockManager.findBlockById(blockElement.getAttribute('id'));
          block.focus();
        }
      }
    }
  },

  destroy: function() {
    // Destroy the rendered sub views
    this.formatBar.destroy();
    this.blockAddition.destroy();
    this.blockControls.destroy();

    // Destroy all blocks
    this.blockManager.blocks.forEach(function(block) {
      this.mediator.trigger('block:remove', block.blockID);
    }, this);

    // Stop listening to events
    this.mediator.stopListening();
    this.stopListening();

    // Remove instance
    config.instances = config.instances.filter(function(instance) {
      return instance.ID !== this.ID;
    }, this);

    // Remove external event listeners
    window.removeEventListener('click', this.hideAllTheThings);
    document.body.removeEventListener('keydown', this.disableBackButton);

    // Clear the store
    this.store.reset();
    Dom.replaceWith(this.outer, this.el);
  },

  getData: function() {
    this.onFormSubmit();
    return this.store.retrieve();
  },

  reinitialize: function(options) {
    this.destroy();
    this.initialize(options || this.options);
  },

  blockLimitReached: function(toggle) {
    this.wrapper.classList.toggle('st--block-limit-reached', toggle);
  },

  blockOrderUpdated: function() {
    // Detect first block and decide whether to hide top controls
    var blockElement = this.wrapper.querySelectorAll('.st-block')[0];
    var hideTopControls = false;

    if (blockElement) {
      var block = this.blockManager.findBlockById(
        blockElement.getAttribute('id')
      );
      hideTopControls = block && block.textable;
    }

    this._toggleHideTopControls(hideTopControls);
  },

  _toggleHideTopControls: function(toggle) {
    this.wrapper.classList.toggle('st--hide-top-controls', toggle);
  },

  _setEvents: function() {
    Object.keys(this.events).forEach(function(type) {
      EventBus.on(type, this[this.events[type]], this);
    }, this);
  },

  hideAllTheThings: function(e) {
    this.blockControls.hide();
    this.blockAddition.hide();

    if (document.activeElement.getAttribute('contenteditable') === null) {
      this.formatBar.hide();
    }

    var popupSelectors = '.st-block__ui-delete-controls';
    Array.prototype.forEach.call(this.wrapper.querySelectorAll(popupSelectors), function(el) {
      el.classList.remove('active');
    });
  },

  store: function(method, options){
    utils.log("The store method has been removed, please call store[methodName]");
    return this.store[method].call(this, options || {});
  },

  removeBlockDragOver: function() {
    var dragOver = this.outer.querySelector('.st-drag-over');
    if (!dragOver) { return; }
    dragOver.classList.remove('st-drag-over');
  },

  changeBlockPosition: function(block, selectedPosition) {
    selectedPosition = selectedPosition - 1;

    var blockPosition = this.blockManager.getBlockPosition(block),
    blockBy = this.wrapper.querySelectorAll('.st-block')[selectedPosition];

    if(blockBy && blockBy.getAttribute('id') !== block.getAttribute('id')) {
      this.hideAllTheThings();
      if (blockPosition > selectedPosition) {
        blockBy.parentNode.insertBefore(block, blockBy);
      } else {
        Dom.insertAfter(block, blockBy);
      }
    }
  },

  /*
   * Handle a form submission of this Editor instance.
   * Validate all of our blocks, and serialise all data onto the JSON objects
   */
  onFormSubmit: function(shouldValidate) {
    // if undefined or null or anything other than false - treat as true
    shouldValidate = (shouldValidate === false) ? false : true;

    utils.log("Handling form submission for Editor " + this.ID);

    this.mediator.trigger('errors:reset');
    this.store.reset();

    this.validateBlocks(shouldValidate);
    this.blockManager.validateBlockTypesExist(shouldValidate);

    this.mediator.trigger('errors:render');
    this.el.value = this.store.toString();

    return this.errorHandler.errors.length;
  },

  /*
   * Call `validateAndSaveBlock` on each block found in the dom.
   */

  validateBlocks: function(shouldValidate) {
    Array.prototype.forEach.call(this.wrapper.querySelectorAll('.st-block'), (block, idx) => {
      var _block = this.blockManager.findBlockById(block.getAttribute('id'));
      if (!_.isUndefined(_block)) {
        this.validateAndSaveBlock(_block, shouldValidate);
      }
    });
  },

  /*
   * If block should be validated and is not valid then register an error.
   * Empty text blocks should be ignored.
   * Save any other valid blocks to the editor data store.
   */

  validateAndSaveBlock: function(block, shouldValidate) {
    if (!config.skipValidation && shouldValidate && !block.valid()) {
      this.mediator.trigger('errors:add', { text: _.result(block, 'validationFailMsg') });
      utils.log("Block " + block.blockID + " failed validation");
      return;
    }

    if (block.type === 'text' && block.isEmpty()) {
      return;
    }

    var blockData = block.getData();
    utils.log("Adding data for block " + block.blockID + " to block store:",
              blockData);
    this.store.addData(blockData);
  },

  /*
   * Disable back button so when a block loses focus the user
   * pressing backspace multiple times doesn't close the page.
   */
  disableBackButton: function(e) {
    var target = e.target || e.srcElement;
    if (e.keyCode === 8) {
      if (target.getAttribute('contenteditable') ||
          target.tagName === 'INPUT' ||
          target.tagName === 'TEXTAREA') {
        return;
      }

      e.preventDefault();
    }
  },

  findBlockById: function(block_id) {
    return this.blockManager.findBlockById(block_id);
  },

  getBlocksByType: function(block_type) {
    return this.blockManager.getBlocksByType(block_type);
  },

  getBlocksByIDs: function(block_ids) {
    return this.blockManager.getBlocksByIDs(block_ids);
  },

  getBlockPosition: function(block) {
    utils.log("This method has been moved to blockManager.getBlockPosition()");
    return this.blockManager.getBlockPosition(block);
  },

  /*
   * Set all dom elements required for the editor.
   */

  _ensureAndSetElements: function() {
    if(_.isUndefined(this.options.el)) {
      utils.log("You must provide an el");
      return false;
    }

    this.el = this.options.el;
    this.form = Dom.getClosest(this.el, 'form');

    var outer = Dom.createElement("div", {
                  'id': this.ID,
                  'class': 'st-outer notranslate',
                  'dropzone': 'copy link move'});

    var wrapper = Dom.createElement("div", {'class': 'st-blocks'});

    // Wrap our element in lots of containers *eww*

    Dom.wrap(Dom.wrap(this.el, outer), wrapper);

    this.outer = this.form.querySelector('#' + this.ID);
    this.wrapper = this.outer.querySelector('.st-blocks');

    return true;
  }

});

module.exports = Editor;
<|endoftext|>


<commit_before>function createUi() {
    return new SimpleUi();
}

function createDefaultLevel(ui) {

    var points = [
        [0, 0],
        [1, 0],
        [1, 1],
        [1, 2],
        [2, 2],
        [3, 2],
        [3, 3],
        [3, 4],
        [4, 4],
        [5, 4],
        [5, 3],
        [5, 2],
        [6, 2],
        [7, 2],
        [8, 2],
        [9, 2]
    ];

	var nodes = generateNodes(points);
	var map = new Map(nodes, ui);
	var van = new Van(nodes[0], nodes[1], ui);
	return new Level(map, van, nodes[nodes.length - 1], ui);
}

function generateNodes(points){
	var previousNode = null;
	var nodes = [];
	for (var i = 0; i < points.length; i++) {
	      var p = points[i];
	      var coordinate = new Coordinate(p[0], p[1]);
	      var node = new Node(coordinate);
	      if (previousNode) {
	          node.addConnectedNodeWithBacklink(previousNode);
	      }
	      previousNode = node;
	      nodes.push(node);
	}
	return nodes;
}

function generateRandomPathPoints(source, seed) {
	var points = [];
	var visited = initialiseVisited();
	var current = source;
	var decision = null;
	var possibleNext = null;
	var orientation = null;
	while (!isOutOfBounds(current)) {
		visited[current[0]][current[1]] = true;
		if (Math.random() < seed && orientation != null) {
			points.push(current);
			current = getNextBasedOnOrientation(current, orientation);
			console.debug(current);
		} else {
			possibleNext = getPossibleNextMoves(current, visited);
			if (possibleNext.length == 0) {
				if(isOnBorder(current)) {
					points.push(current);
					return points;
				}
				current = points.pop();
			} else {
				decision = Math.floor((Math.random() * possibleNext.length));
				points.push(current);
				next = possibleNext[decision];
				orientation =  (2 * (next[0] - current[0]) + (next[1] - current[1]));
				console.debug('orientation: ' + next.x)
				current = possibleNext[decision];
			}
		}
	}
	return points;

	function getNextBasedOnOrientation(point, orientation) {
		var result = null;
		switch(orientation) {
			case 1:
				result = [point[0], point[1] + 1];
				break;
			case -1:
				result = [point[0], point[1] - 1];
				break;
			case 2:
				result = [point[0] + 1, point[1]];
				break;
			case -2:
				result = [point[0] - 1, point[1]];
				break;
		}
		console.debug('result: ' + result + ", point: " + point + ', orientation: ' + orientation);
		return result;
	}

	function isOutOfBounds(point) {
		return point[0] < 0 || point[0] >= GRID_WIDTH || point[1] < 0 || point[1] >= GRID_HEIGHT;
	}

	function isOnBorder(point) {
		return point[0] == 0 || point[0] == GRID_WIDTH || point[1] == 0 || point[1] == GRID_HEIGHT;
	}

	function isFree(point, visited) {
		return !visited[point[0]][point[1]];
	}

	function getPossibleNextMoves(point, visited) {
		var possible = [];
		var possiblePoint = null;
		var considered = [[point[0], point[1] + 1], [point[0] + 1, point[1]],
			[point[0] - 1, point[1]], [point[0], point[1] - 1]];
		for (var i= 0; i < 4; i++) {
			possiblePoint = considered[i];
			if(!isOutOfBounds(possiblePoint) && isFree(possiblePoint, visited)) {
				possible.push(possiblePoint);
			}
		}
		return possible;
	}

	function initialiseVisited() {
		var visited = new Array(GRID_WIDTH);
		for (var i = 0; i < GRID_WIDTH; i++) {
			visited[i] = new Array(GRID_HEIGHT);
		}
		return visited;
	}
}

function defaultProgram(level) {
	  var program = new Program(
	          [TURN_LEFT,
	              FORWARD,
	              TURN_RIGHT,
	              FORWARD,
	              TURN_LEFT,
	              FORWARD,
	              TURN_RIGHT,
	              FORWARD,
	              TURN_RIGHT,
	              FORWARD,
	              TURN_LEFT,
	              FORWARD,
	              FORWARD,
	              FORWARD
	          ]);

	  level.play(program);
}

function trackDevelopment(level) {
	var program = new Program([]);

	$('#moveForward').click(function() {
		program.instructions.push(FORWARD);
    });

    $('#turnLeft').click(function() {
    	program.instructions.push(TURN_LEFT);
    });

    $('#turnRight').click(function() {
		program.instructions.push(TURN_RIGHT);
	});

    $('#play').click(function() {
    	level.play(program);
	});

	$('#randomRoad').click(function() {
		var ui = createUi();
		var points = generateRandomPathPoints([0,1], 0.5);
		var nodes = generateNodes(points);
		var van = new Van(nodes[0], nodes[1], ui);
		var map = new Map(nodes, ui);
	})
}

$(function() {
    'use strict';

    var ui = createUi();

    var level = createDefaultLevel(ui);

    $('#runDefaultProgram').click(function() {
    	defaultProgram(level);
	});

    trackDevelopment(level);
});
<commit_msg>Fixed the initial point to always appear come from outside of the map (if, indeed, starting point is the border point)." ;<commit_after>function createUi() {
    return new SimpleUi();
}

function createDefaultLevel(ui) {

    var points = [
        [0, 0],
        [1, 0],
        [1, 1],
        [1, 2],
        [2, 2],
        [3, 2],
        [3, 3],
        [3, 4],
        [4, 4],
        [5, 4],
        [5, 3],
        [5, 2],
        [6, 2],
        [7, 2],
        [8, 2],
        [9, 2]
    ];

	var nodes = generateNodes(points);
	var map = new Map(nodes, ui);
	var van = new Van(nodes[0], nodes[1], ui);
	return new Level(map, van, nodes[nodes.length - 1], ui);
}

function generateNodes(points){
	var previousNode = null;
	var nodes = [];
	for (var i = 0; i < points.length; i++) {
	      var p = points[i];
	      var coordinate = new Coordinate(p[0], p[1]);
	      var node = new Node(coordinate);
	      if (previousNode) {
	          node.addConnectedNodeWithBacklink(previousNode);
	      }
	      previousNode = node;
	      nodes.push(node);
	}
	return nodes;
}

/**
  * Generates a random road given a starting point and seed from the range <0, 1>,
  * where 1 creates a completely straight road and 0 does not influence the way
  * the next road element is chosen at all.
  */
function generateRandomPathPoints(current, seed) {
	var points = [];
	var visited = initialiseVisited();
	var possibleNext = null;
	var orientation = current[1] == 0 ? -1 : 2;
	var possibleStaight = null;

	points.push(current);
	visited[current[0]][current[1]] = true;
	current = getNextBasedOnOrientation(current, orientation);

	while (!isOutOfBounds(current)) {

		visited[current[0]][current[1]] = true;
		possibleNext = getPossibleNextMoves(current, visited);
		possibleStraight = getNextBasedOnOrientation(current, orientation);

		if (Math.random() < seed && possibleStraight != -1
			&& isFree(possibleStraight, visited)) {
			points.push(current);
			current = possibleStraight;
			console.debug(current);

		} else {

			if (possibleNext.length == 0) {
				if(isOnBorder(current)) {
					points.push(current);
					return points;
				}
				current = points.pop();

			} else {

				var decision = Math.floor((Math.random() * possibleNext.length));
				points.push(current);
				next = possibleNext[decision];
				orientation =  (2 * (next[0] - current[0]) + (next[1] - current[1]));
				current = possibleNext[decision];
			}
		}
	}
	console.debug("blah");
	for (var i = 0; i < points.length; i++) {
		console.debug(points[i]);
	}
	console.debug("blah2");
	return points;

	/*						*(1, 0) 1
	 *
	 *      *(-1,0) -2     	x(0, 0)      	*(1, 0) 2
	 *
	 *						*(-1, 0) -1
	 *
	 * Returns next point in the same orientation or -1 if it would go out of bounds.
	 */
	function getNextBasedOnOrientation(point, orientation) {
		var result = null;
		switch(orientation) {
			case 1:
				result = [point[0], point[1] + 1];
				break;
			case -1:
				result = [point[0], point[1] - 1];
				break;
			case 2:
				result = [point[0] + 1, point[1]];
				break;
			case -2:
				result = [point[0] - 1, point[1]];
				break;
		}
		return isOutOfBounds(result) ? -1 : result;
	}

	function isOutOfBounds(point) {
		return point[0] < 0 || point[0] >= GRID_WIDTH || point[1] < 0 || point[1] >= GRID_HEIGHT;
	}

	function isOnBorder(point) {
		return point[0] == 0 || point[0] == GRID_WIDTH || point[1] == 0 || point[1] == GRID_HEIGHT;
	}

	function isFree(point, visited) {
		return !visited[point[0]][point[1]];
	}

	function getPossibleNextMoves(point, visited) {
		var possible = [];
		var possiblePoint = null;
		var considered = [[point[0], point[1] + 1], [point[0] + 1, point[1]],
			[point[0] - 1, point[1]], [point[0], point[1] - 1]];
		for (var i= 0; i < 4; i++) {
			possiblePoint = considered[i];
			if(!isOutOfBounds(possiblePoint) && isFree(possiblePoint, visited)) {
				possible.push(possiblePoint);
			}
		}
		return possible;
	}

	function initialiseVisited() {
		var visited = new Array(GRID_WIDTH);
		for (var i = 0; i < GRID_WIDTH; i++) {
			visited[i] = new Array(GRID_HEIGHT);
		}
		return visited;
	}
}

function defaultProgram(level) {
	  var program = new Program(
	          [TURN_LEFT,
	              FORWARD,
	              TURN_RIGHT,
	              FORWARD,
	              TURN_LEFT,
	              FORWARD,
	              TURN_RIGHT,
	              FORWARD,
	              TURN_RIGHT,
	              FORWARD,
	              TURN_LEFT,
	              FORWARD,
	              FORWARD,
	              FORWARD
	          ]);

	  level.play(program);
}

function trackDevelopment(level) {
	var program = new Program([]);

	$('#moveForward').click(function() {
		program.instructions.push(FORWARD);
    });

    $('#turnLeft').click(function() {
    	program.instructions.push(TURN_LEFT);
    });

    $('#turnRight').click(function() {
		program.instructions.push(TURN_RIGHT);
	});

    $('#play').click(function() {
    	level.play(program);
	});

	$('#randomRoad').click(function() {
		var ui = createUi();
		var points = generateRandomPathPoints([0,4], 0);
		var nodes = generateNodes(points);
		var van = new Van(nodes[0], nodes[1], ui);
		var map = new Map(nodes, ui);
	})
}

$(function() {
    'use strict';

    var ui = createUi();

    var level = createDefaultLevel(ui);

    $('#runDefaultProgram').click(function() {
    	defaultProgram(level);
	});

    trackDevelopment(level);
});
<|endoftext|>


<commit_before>/**
 * WordPress dependencies
 */
import {
	activatePlugin,
	deactivatePlugin,
} from '@wordpress/e2e-test-utils';

/**
 * Internal depedencies
 */
import {
	activateAMPWithMode,
	deactivateUtilityPlugins,
	setupSiteKit,
} from '../../utils';

describe( 'AMP Homepage', () => {
	beforeAll( async () => {
		await setupSiteKit();
		await activatePlugin( 'e2e-tests-admin-bar-visibility' );
		await activateAMPWithMode( 'standard' );
	} );

	afterAll( async () => {
		await deactivatePlugin( 'amp' );
		await deactivateUtilityPlugins();
	} );

	describe( 'Logged-in user', () => {
		it( 'has no validation errors', async () => {
			await expect( '/' ).toHaveValidAMPForUser();
		} );
	} );
	describe( 'Non-logged-in user', () => {
		it( 'has no validation errors', async () => {
			await expect( '/' ).toHaveValidAMPForVistor();
	} );
} );
<commit_msg>Fix syntax error.<commit_after>/**
 * WordPress dependencies
 */
import {
	activatePlugin,
	deactivatePlugin,
} from '@wordpress/e2e-test-utils';

/**
 * Internal depedencies
 */
import {
	activateAMPWithMode,
	deactivateUtilityPlugins,
	setupSiteKit,
} from '../../utils';

describe( 'AMP Homepage', () => {
	beforeAll( async () => {
		await setupSiteKit();
		await activatePlugin( 'e2e-tests-admin-bar-visibility' );
		await activateAMPWithMode( 'standard' );
	} );

	afterAll( async () => {
		await deactivatePlugin( 'amp' );
		await deactivateUtilityPlugins();
	} );

	describe( 'Logged-in user', () => {
		it( 'has no validation errors', async () => {
			await expect( '/' ).toHaveValidAMPForUser();
		} );
	} );
	describe( 'Non-logged-in user', () => {
		it( 'has no validation errors', async () => {
			await expect( '/' ).toHaveValidAMPForVisitor();
		} );
	} );
} );
<|endoftext|>


<commit_before>"use strict";

function Model() {
    this.level = undefined;
    this.player = undefined;
    this.goal = undefined;
    this.mobs = [];
}

Model.prototype = {

	"setLevel": function(lvlData) {
            this.player = lvlData.start;

	    console.log(lvlData);
	}
}

var MODEL = new Model();

function Engine() {

}

Engine.prototype = {

	"loadLevel": function(lvl) {
		$.getJSON("data/lvl" + lvl + ".json", function(response) {
			MODEL.setLevel(response);
		}).error(function() { alert("Could not load level " + lvl); });

	},

	"showMenu": function() {

	}

}

$.ajaxSetup({beforeSend: function(xhr){
  if (xhr.overrideMimeType)
  {
    xhr.overrideMimeType("application/json");
  }
}
});

var e = new Engine();
e.loadLevel(1);
<commit_msg>Created Mob class and finished setLevel in Model<commit_after>"use strict";

function Mob()
{
    this.DEBUG = true;

    this.path = undefined;
    this.position = 0;
}

Mob.prototype =
{
    "getPos": function()
    {
        if (this.DEBUG)
        {
            console.log("get postion");
        }

        return this.path[this.position];
    },

    "move": function()
    {
        if (this.DEBUG)
        {
            console.log("move mob");
        }

        this.position++;

        if (this.position == this.path.length)
        {
            this.position = 0;
        }
    }
}

function Model()
{
    this.DEBUG = true;

    this.level = undefined;
    this.player = undefined;
    this.goal = undefined;
    this.mobs = [];
}

Model.prototype =
{
    /*
     * Set up a new level from JSON data object.
     */
    "setLevel": function(lvlData)
    {
        if (!lvlData)
        {
            console.log("lvlData object is false in Model setLevel");
        }

        this.level = lvlData.level;
        this.player = lvlData.start;
        this.goal = lvlData.goal;

        // Create the mobs
        for (var i in lvlData.enemies)
        {
            if (this.DEBUG)
            {
	        console.log(lvlData.enemies[i].type);
	        console.log(lvlData.enemies[i].layer);
	        console.log(lvlData.enemies[i].path);
            }

            var mob = new Mob();

            var path = lvlData.enemies[i].path;

            // Convert bounce path to loop path
            if (lvlData.enemies[i].type == "Bounce")
            {
                var tmp = path.slice(0);
                tmp.pop();
                tmp = tmp.reverse();
                tmp.pop();
                path = path.concat(tmp);
            }

            // Add layer to coordinates.
            mob.path = path.map(function(pos)
            {
                return pos.unshift(lvlData.enemies[i].layer);
            });

            this.mobs.push(mob);
        }

        if (this.DEBUG)
        {
	    console.log(lvlData);
            console.log(this.level);
            console.log(this.player);
            console.log(this.goal);
            console.log(this.mobs);
        }
    }
}

var MODEL = new Model();

function Engine() {

}

Engine.prototype = {

	"loadLevel": function(lvl) {
		$.getJSON("data/lvl" + lvl + ".json", function(response) {
			MODEL.setLevel(response);
		}).error(function() { alert("Could not load level " + lvl); });

	},

	"showMenu": function() {

	}

}

$.ajaxSetup({beforeSend: function(xhr){
  if (xhr.overrideMimeType)
  {
    xhr.overrideMimeType("application/json");
  }
}
});

var e = new Engine();
e.loadLevel(1);
<|endoftext|>


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

    /**
    * Represents an entity in the game. Usually a character or enemy.
    * @class Entity
    * @constructor
    * @param {Game} game - Game instance this obj is attached to.
    * @param {String} type - Type of entity. When created this object is merged with the value of Entity.Types[type].
    */
    var Entity = function Entity(game, type) {
        this.game = game;
        this.type = type;
        var typeData = Entity.Types[type];
        if(!typeData){
            throw new Error('EntityType "' + type + '" not found.');
        }
        for(var key in typeData){
            this[key] = typeData[key];
        }

    };

    Entity.prototype = {
        constructor: Entity,

        /**
        * Game instance this object is attached to.
        * @property game
        * @type Game
        */
        game: null,

        /**
        * The type of entity this is.
        * When created this object is merged with the value of Entity.Types[type].
        * @property type
        * @type String
        */
        type: null,

        /**
        * Name used when referencing or describing this entity.
        * Used in console messages.
        * @property name
        * @type String
        */
        name: null,

        /**
        * The x map tile coord of this entity.
        * @property x
        * @type Number
        */
        x: null,

        /**
        * The y map tile coord of this entity.
        * @property y
        * @type Number
        */
        y: null,

        /**
        * The character displayed when rendering this entity.
        * @property char
        * @type String
        */
        char: 'x',

        /**
        * The color of the character displayed when rendering this entity. Not rendered if false.
        * @property color
        * @type String|bool
        */
        color: '#fff',

        /**
        * The background color the character displayed when rendering this entity. Not rendered if false.
        * @property bgColor
        * @type String|bool
        */
        bgColor: false,

        /**
        * Determines if this entity has been killed and needs to be removed.
        * @property dead
        * @type bool
        */
        dead: false,

        /**
        * Determines if this entity can be pushed by the player.
        * @property pushable
        * @type bool
        */
        pushable: false,

        /**
        * Called after a player action has been resolved. Resolves this entities turn.
        * @method update
        */
        update: function() {

        },

        /**
        * Checks if this entity can move to the specified map tile
        * @method canMoveTo
        * @param {Number} x - The tile map x coord to check if this entity can move to.
        * @param {Number} y - The tile map y coord to check if this entity can move to.
        * @return {Bool}
        */
        canMoveTo: function(x, y){
            var entity = this.game.entityManager.get(x, y);
            if(entity){
                return false;
            }
            return this.game.map.canMoveThrough(x, y);
        },

        /**
        * Changes the position of this entity on the map.
        * @method moveTo
        * @param {Number} x - The tile map x coord to move to.
        * @param {Number} y - The tile map y coord to move to.
        */
        moveTo: function(x, y) {
            this.game.entityManager.move(x, y, this);
        },

        /**
        * Handles the behavior of a player or other entity attempting to move into the tile coord this entity is currently occupying.
        * @method bump
        * @param {Entity} entity - The player or entity attemplting to move into this entity's tile.
        */
        bump: function(entity){
            // if this entity can be pushed and the pushing entity is the player
            if(this.pushable && entity === this.game.player){
                var pusherX = entity.x,
                    pusherY = entity.y,
                    directionX = this.x - pusherX,
                    directionY = this.y - pusherY,
                    targetX = this.x + directionX,
                    targetY = this.y + directionY;

                var targetPushEnt = this.game.entityManager.get(targetX, targetY);
                if(!targetPushEnt){
                    var targetPushTile = this.game.map.get(targetX, targetY);
                    if(targetPushTile.passable){
                        var prevX = this.x,
                            prevY = this.y;
                        // push target entity into tile
                        this.moveTo(targetX, targetY);
                        // move player into previously occupied tile
                        entity.moveTo(prevX, prevY);
                    }
                }
            }
        }
    };

    /**
    * Describes different types of entities. Used by the Entity constructor 'type' param.
    *
    *     Entity.Types = {
    *         zombie: {
    *            name: 'Zombie',
    *            char: 'z',
    *            color: 'red',
    *            bgColor: '#222',
    *            pushable: false
    *         },
    *         // ...
    *     }
    *
    * @class Entity.Types
    * @static
    */
    Entity.Types = {
        zombie: {
            name: 'Zombie',
            char: 'z',
            color: 'red',
            bgColor: '#222',
            pushable: false,
        },
        statue: {
            name: 'Statue',
            char: 's',
            color: '#808080',
            bgColor: '#222',
            pushable: true
        }
    };

    root.RL.Entity = Entity;

}(this));
<commit_msg>Entity (entity.js)  - added initialize method  - fixed this.game.map.canMoveThrough(x, y);<commit_after>(function(root) {
    'use strict';

    /**
    * Represents an entity in the game. Usually a character or enemy.
    * @class Entity
    * @constructor
    * @param {Game} game - Game instance this obj is attached to.
    * @param {String} type - Type of entity. When created this object is merged with the value of Entity.Types[type].
    */
    var Entity = function Entity(game, type) {
        this.game = game;
        this.type = type;
        var typeData = Entity.Types[type];
        if(!typeData){
            throw new Error('EntityType "' + type + '" not found.');
        }
        for(var key in typeData){
            this[key] = typeData[key];
        }

        if(this.initialize){
            this.initialize();
        }
    };

    Entity.prototype = {
        constructor: Entity,

        /**
        * Game instance this object is attached to.
        * @property game
        * @type Game
        */
        game: null,

        /**
        * The type of entity this is.
        * When created this object is merged with the value of Entity.Types[type].
        * @property type
        * @type String
        */
        type: null,

        /**
        * Called when the entity is first created. Intended to be assigned by Entity.Types.
        * @method initialize
        */
        initialize: function(){

        },

        /**
        * Name used when referencing or describing this entity.
        * Used in console messages.
        * @property name
        * @type String
        */
        name: null,

        /**
        * The x map tile coord of this entity.
        * @property x
        * @type Number
        */
        x: null,

        /**
        * The y map tile coord of this entity.
        * @property y
        * @type Number
        */
        y: null,

        /**
        * The character displayed when rendering this entity.
        * @property char
        * @type String
        */
        char: 'x',

        /**
        * The color of the character displayed when rendering this entity. Not rendered if false.
        * @property color
        * @type String|bool
        */
        color: '#fff',

        /**
        * The background color the character displayed when rendering this entity. Not rendered if false.
        * @property bgColor
        * @type String|bool
        */
        bgColor: false,

        /**
        * Determines if this entity has been killed and needs to be removed.
        * @property dead
        * @type bool
        */
        dead: false,

        /**
        * Determines if this entity can be pushed by the player.
        * @property pushable
        * @type bool
        */
        pushable: false,

        /**
        * Called after a player action has been resolved. Resolves this entities turn.
        * @method update
        */
        update: function() {

        },

        /**
        * Checks if this entity can move to the specified map tile
        * @method canMoveTo
        * @param {Number} x - The tile map x coord to check if this entity can move to.
        * @param {Number} y - The tile map y coord to check if this entity can move to.
        * @return {Bool}
        */
        canMoveTo: function(x, y){
            var entity = this.game.entityManager.get(x, y);
            if(entity){
                return false;
            }
            return this.game.map.canMoveThroughTile(x, y);
        },

        /**
        * Changes the position of this entity on the map.
        * @method moveTo
        * @param {Number} x - The tile map x coord to move to.
        * @param {Number} y - The tile map y coord to move to.
        */
        moveTo: function(x, y) {
            this.game.entityManager.move(x, y, this);
        },

        /**
        * Handles the behavior of a player or other entity attempting to move into the tile coord this entity is currently occupying.
        * @method bump
        * @param {Entity} entity - The player or entity attemplting to move into this entity's tile.
        */
        bump: function(entity){
            // if this entity can be pushed and the pushing entity is the player
            if(this.pushable && entity === this.game.player){
                var pusherX = entity.x,
                    pusherY = entity.y,
                    directionX = this.x - pusherX,
                    directionY = this.y - pusherY,
                    targetX = this.x + directionX,
                    targetY = this.y + directionY;

                var targetPushEnt = this.game.entityManager.get(targetX, targetY);
                if(!targetPushEnt){
                    var targetPushTile = this.game.map.get(targetX, targetY);
                    if(targetPushTile.passable){
                        var prevX = this.x,
                            prevY = this.y;
                        // push target entity into tile
                        this.moveTo(targetX, targetY);
                        // move player into previously occupied tile
                        entity.moveTo(prevX, prevY);
                    }
                }
            }
        }
    };

    /**
    * Describes different types of entities. Used by the Entity constructor 'type' param.
    *
    *     Entity.Types = {
    *         zombie: {
    *            name: 'Zombie',
    *            char: 'z',
    *            color: 'red',
    *            bgColor: '#222',
    *            pushable: false
    *         },
    *         // ...
    *     }
    *
    * @class Entity.Types
    * @static
    */
    Entity.Types = {
        zombie: {
            name: 'Zombie',
            char: 'z',
            color: 'red',
            bgColor: '#222',
            pushable: false,
        },
        statue: {
            name: 'Statue',
            char: 's',
            color: '#808080',
            bgColor: '#222',
            pushable: true
        }
    };

    root.RL.Entity = Entity;

}(this));
<|endoftext|>


<commit_before>function DbError (message) {
  this.message = message
  this.stack = new Error().stack
  this.code = 500
  this.errorType = this.name
}

DbError.prototype = Object.create(Error.prototype)
DbError.prototype.name = 'DatabaseError'

export {
  DbError
}
<commit_msg>add NotFoundError<commit_after>function DbError (message) {
  this.message = message
  this.stack = new Error().stack
  this.code = 500
  this.errorType = this.name
}
DbError.prototype = Object.create(Error.prototype)
DbError.prototype.name = 'DatabaseError'

function NotFoundError (message) {
  this.message = message
  this.stack = new Error().stack
  this.code = 404
  this.errorType = this.name
}
DbError.prototype = Object.create(Error.prototype)
DbError.prototype.name = 'NotFoundError'

export {
  DbError,
  NotFoundError
}
<|endoftext|>


<commit_before>// 20: spread - with-arrays
// To do: make all tests pass, leave the assert lines unchanged!
// Follow the hints of the failure messages!

describe('Spread syntax with arrays', () => {
  describe('basically', () => {
    it('expands the items of an array by prefixing it with `...`', function() {
      const middle = [1, 2, 3];
      //// const arr = [0, middle, 4];
      const arr = [0, ...middle, 4];
      assert.deepEqual(arr, [0, 1, 2, 3, 4]);
    });
  });
  describe('is (in a way) the opposite to the rest syntax', function() {
    it('both use `...` to either expand all items and collect them', function() {
      //// const [...rest] = [...[,1, 2, 3, 4, 5]];
      const [...rest] = [...[1, 2, 3, 4, 5]];
      assert.deepEqual(rest, [1, 2, 3, 4, 5]);
    });
    it('rest syntax must be last in an array, spread can be used in any place', function() {
      //// const [a, b, ...rest] = [1, [2, 3], 4, 5];
      const [a, b, ...rest] = [1, ...[2, 3], 4, 5];
      assert.equal(a, 1);
      assert.equal(b, 2);
      assert.deepEqual(rest, [3, 4, 5]);
    });
  });
  describe('used as function parameter', () => {
    it('prefix with `...` to spread as function params', function() {
      const magicNumbers = [1, 2];
      const fn = (magicA, magicB) => {
        assert.deepEqual(magicNumbers[0], magicA);
        assert.deepEqual(magicNumbers[1], magicB);
      };
      //// fn(magicNumbers);
      fn(...magicNumbers);
    });
    it('pass an array of numbers to Math.max()', function() {
      //// const max = Math.max(...[23, 0, 42, 43]);
      const max = Math.max(...[23, 0, 42]);
      assert.equal(max, 42);
    });
  });
  describe('used as constructor parameter', () => {
    // TODO
  });
});
<commit_msg>One more explanatory kata.<commit_after>// 20: spread - with-arrays
// To do: make all tests pass, leave the assert lines unchanged!
// Follow the hints of the failure messages!

describe('Spread syntax with arrays', () => {
  describe('basically', () => {
    it('expands the items of an array by prefixing it with `...`', function() {
      const middle = [1, 2, 3];
      //// const arr = [0, middle, 4];
      const arr = [0, ...middle, 4];
      assert.deepEqual(arr, [0, 1, 2, 3, 4]);
    });
    it('an empty array expanded is no item', function() {
      //// const arr = [0, [], 1];
      const arr = [0, ...[], 1];
      assert.deepEqual(arr, [0, 1]);
    });
  });
  describe('is (in a way) the opposite to the rest syntax', function() {
    it('both use `...` to either expand all items and collect them', function() {
      //// const [...rest] = [...[,1, 2, 3, 4, 5]];
      const [...rest] = [...[1, 2, 3, 4, 5]];
      assert.deepEqual(rest, [1, 2, 3, 4, 5]);
    });
    it('rest syntax must be last in an array, spread can be used in any place', function() {
      //// const [a, b, ...rest] = [1, [2, 3], 4, 5];
      const [a, b, ...rest] = [1, ...[2, 3], 4, 5];
      assert.equal(a, 1);
      assert.equal(b, 2);
      assert.deepEqual(rest, [3, 4, 5]);
    });
  });
  describe('used as function parameter', () => {
    it('prefix with `...` to spread as function params', function() {
      const magicNumbers = [1, 2];
      const fn = (magicA, magicB) => {
        assert.deepEqual(magicNumbers[0], magicA);
        assert.deepEqual(magicNumbers[1], magicB);
      };
      //// fn(magicNumbers);
      fn(...magicNumbers);
    });
    it('pass an array of numbers to Math.max()', function() {
      //// const max = Math.max(...[23, 0, 42, 43]);
      const max = Math.max(...[23, 0, 42]);
      assert.equal(max, 42);
    });
  });
  describe('used as constructor parameter', () => {
    // TODO
  });
});
<|endoftext|>