<commit_before>(function(root, attach) {
  if (typeof define === 'function' && define.amd) {
    define(['hlf/core', 'hlf/hover-intent'], attach);
  } else if (typeof exports === 'object') {
    module.exports = attach(require('hlf/core'), require('hlf/hover-intent'));
  } else {
    attach(hlf);
  }
})(this, function(hlf, hoverIntent) {
  hlf.tip = {
    debug: true,
    defaults: {
      autoDirection: true,
      cursorHeight: 12,
      defaultDirection: ['bottom', 'right'],
      doDispatchEvents: true,
      doFollow: true,
      doStem: true,
      snapToTrigger: true,
      snapToXAxis: false,
      snapToYAxis: false,
      tipTemplate({ containerClass }) {
        let stemHtml = '';
        if (this.doStem) {
          stemHtml = `<div class="${this.className('stem')}"></div>`;
        }
        return (
`

    ${stemHtml}

`
        );
      },
      triggerContent: null,
      viewportElement: document.body,
    },
    toString(context) {
      switch (context) {
        case 'event': return 'hlftip';
        case 'data': return 'hlf-tip';
        case 'class': return 'tips';
        default: return 'hlf-tip';
      }
    },
  };
  class Tip {
    constructor(elements, options, contextElement) {
      this._state = {
        name: null,
        sleepCountdown: null,
        wakeCountdown: null,
      };
    }
    init() {
      this.element = document.createElement('div');
      this._updateState('asleep');
      this._currentTriggerElement = null;
    }
    deinit() {
    }
    _dispatchStateEvent() {
      if (!this.doDispatchEvents) { return; }
      let triggerElement = this._currentTriggerElement;
      if (!triggerElement) { return; }
      let eventName = (() => {
        switch (this._state.name) {
          case 'asleep': return 'hidden';
          case 'awake': return 'shown';
          case 'sleeping': return 'hide';
          case 'waking': return 'show';
        }
      }());
      triggerElement.dispatchEvent(this.createCustomEvent(eventName));
    }
    _toggleElementPositionTransition(toggled) {
      this.element.style.transition = toggled ? 'transform 0.1s linear' : '';
    }
    _updateState(name) {
      let state = this._state;
      if (name === state.name) { return; }
      state.name = name;
      this.debugLog(name);

      this._dispatchStateEvent();
      if (state.name === 'asleep' || state.name === 'awake') {
        setTimeout(() => {
          this._toggleElementPositionTransition(false);
        }, 0);
      } else if (state.name === 'sleeping') {
        clearTimeout(state.wakeCountdown);
        state.wakeCountdown = null;
      } else if (state.name === 'waking') {
        clearTimeout(state.sleepCountdown);
        state.sleepCountdown = null;
      }
    }
  }
  return hlf.createExtension({
    name: 'tip',
    namespace: hlf.tip,
    apiClass: Tip,
    asSharedInstance: true,
    autoBind: true,
    autoListen: true,
    baseMethodGroups: ['css', 'selection'],
    compactOptions: true,
  });
});
<commit_msg>Continue tip port: render, events, and related.<commit_after>(function(root, attach) {
  if (typeof define === 'function' && define.amd) {
    define(['hlf/core', 'hlf/hover-intent'], attach);
  } else if (typeof exports === 'object') {
    module.exports = attach(require('hlf/core'), require('hlf/hover-intent'));
  } else {
    attach(hlf);
  }
})(this, function(hlf, hoverIntent) {
  hlf.tip = {
    debug: true,
    defaults: {
      cursorHeight: 12,
      defaultDirection: ['bottom', 'right'],
      doDispatchEvents: true,
      doFollow: true,
      doStem: true,
      snapToTrigger: true,
      snapToXAxis: false,
      snapToYAxis: false,
      template({ containerClass }) {
        let stemHtml = '';
        if (this.doStem) {
          stemHtml = `<div class="${this.className('stem')}"></div>`;
        }
        return (
`

    ${stemHtml}

`
        );
      },
      triggerContent: null,
      viewportElement: document.body,
    },
    toString(context) {
      switch (context) {
        case 'event': return 'hlftip';
        case 'data': return 'hlf-tip';
        case 'class': return 'tips';
        default: return 'hlf-tip';
      }
    },
  };
  class Tip {
    constructor(elements, options, contextElement) {
      this._bounds = null;
      this._state = {
        name: null,
        sleepCountdown: null,
        wakeCountdown: null,
      };
    }
    init() {
      this.element = document.createElement('div');
      this._updateState('asleep');
      this._currentTriggerElement = null;
      this._renderElement();
      this._toggleContextMutationObserver(true);
      this._toggleElementEventListeners(true);
      this._updateTriggerElements();
      window.addEventListener('resize', this._onWindowResize);
    }
    deinit() {
      this.element.parentNode.removeChild(this.element);
      this._toggleContextMutationObserver(false);
      this._toggleElementEventListeners(false);
      window.removeEventListener('resize', this._onWindowResize);
    }
    performSleep({ triggerElement, event }) {
    }
    performWake({ triggerElement, event }) {
    }
    _dispatchStateEvent() {
      if (!this.doDispatchEvents) { return; }
      let triggerElement = this._currentTriggerElement;
      if (!triggerElement) { return; }
      let eventName = (() => {
        switch (this._state.name) {
          case 'asleep': return 'hidden';
          case 'awake': return 'shown';
          case 'sleeping': return 'hide';
          case 'waking': return 'show';
        }
      }());
      triggerElement.dispatchEvent(this.createCustomEvent(eventName));
    }
    _onContextMutation(mutations) {
      let triggerElements = [];
      mutations
        // TODO: Limited.
        .filter(m => m.target.classList.contains(this.className('content')))
        .forEach((mutation) => {
          triggerElements = triggerElements.concat(
            Array.from(mutation.addedNodes).querySelectorAll('[title],[alt]')
          );
        });
      this._updateTriggerElements(triggerElements);
      this.triggerElements = this.triggerElements.concat(triggerElements);
    }
    _onElementMouseEnter(event) {
      this.debugLog('enter tip');
      let triggerElement = this._currentTriggerElement;
      if (!triggerElement) { return; }
      this.performWake({ triggerElement, event });
    }
    _onElementMouseLeave(event) {
      this.debugLog('leave tip');
      let triggerElement = this._currentTriggerElement;
      if (!triggerElement) { return; }
      this.performSleep({ triggerElement, event });
    }
    _onWindowResize(event) {
      const delay = 300;
      const now = Date.now();
      if (this._ran && now < this._ran + delay) { return; }
      this._ran = now;
      this._updateMetrics();
    }
    _renderElement() {
      if (this.element.innerHTML.length) { return; }
      let directionClass = this.defaultDirection.reduce(
        (memo, component) => { return `${memo} ${this.className(component)}`; },
      '').trim();
      this.element.innerHTML = this.template({
        containerClass: `${this.className('tip')} ${this.className('follow')} ${directionClass}`,
      });

      let contentElement = this.element.querySelector(this.className('content'));
      contentElement.style.transition = 'width 0.3s ease-in-out, height 0.3s ease-in-out';

      this.viewportElement.insertBefore(this.element, this.viewportElement.firstChild);
    }
    _toggleContextMutationObserver(on) {
      if (!this._contextObserver) {
        this._contextObserver = new MutationObserver(this._onContextMutation);
        this._contextObserver.connect = () => {
          this._contextObserver.observe(this.contextElement,
            { childList: true, subtree: true }
          );
        };
      }
      if (on) {
        this._contextObserver.connect();
      } else {
        this._contextObserver.disconnect();
      }
    }
    _toggleElementEventListeners(on) {
      this.toggleEventListeners(on, {
        'mouseenter': this._onElementMouseEnter,
        'mouseleave': this._onElementMouseLeave,
      }, this.element);
    }
    _toggleElementPositionTransition(toggled) {
      this.element.style.transition = toggled ? 'transform 0.1s linear' : '';
    }
    _updateMetrics() {
    }
    _updateState(name) {
      let state = this._state;
      if (name === state.name) { return; }
      state.name = name;
      this.debugLog(name);

      this._dispatchStateEvent();
      if (state.name === 'asleep' || state.name === 'awake') {
        if (this._currentTriggerElement) {
          this._currentTriggerElement.setAttribute(
            this.attrName('has-tip-focus'), state.name === 'awake'
          );
        }
        setTimeout(() => {
          this._toggleElementPositionTransition(false);
        }, 0);
      } else if (state.name === 'sleeping') {
        clearTimeout(state.wakeCountdown);
        state.wakeCountdown = null;
      } else if (state.name === 'waking') {
        clearTimeout(state.sleepCountdown);
        state.sleepCountdown = null;
      }
    }
    _updateTriggerElements(triggerElements) {
    }
  }
  return hlf.createExtension({
    name: 'tip',
    namespace: hlf.tip,
    apiClass: Tip,
    asSharedInstance: true,
    autoBind: true,
    autoListen: true,
    baseMethodGroups: ['css', 'selection'],
    compactOptions: true,
  });
});
<|endoftext|>


<commit_before>import HTML5Kinvey from 'kinvey-html5-sdk';
import Device from './device';
import Popup from './popup';
import Push from './push';
import assign from 'lodash/assign';

export default class Kinvey extends HTML5Kinvey {
  static init(options = {}) {
    options = assign({
      deviceClass: Device,
      popupClass: Popup
    }, options);

    // Initialize Kinvey
    const client = super.init(options);

    // // Add Push module to Kinvey
    this.Push = new Push({ client: client });

    // Return the client
    return client;
  }
}
<commit_msg>Make push module a singleton<commit_after>import HTML5Kinvey from 'kinvey-html5-sdk';
import Device from './device';
import Popup from './popup';
import Push from './push';
import assign from 'lodash/assign';

class Kinvey extends HTML5Kinvey {
  static init(options = {}) {
    options = assign({
      deviceClass: Device,
      popupClass: Popup
    }, options);

    // Initialize Kinvey
    return super.init(options);
  }
}

// Add Push module
Kinvey.Push = Push;

// Export
export default Kinvey;
<|endoftext|>


<commit_before>import { is as isObject } from './module/object'
import css from './module/css'
import insert from './element/insert'

/**
 *
 */
class Layout {
  /**
   * [constructor description]
   * @param  {?} schema    [description]
   * @param  {?} container [description]
   * @return {?}           [description]
   */
  constructor (schema, container) {
    this.component = this.create(schema, container)

    return this
  }

  /**
   * [create description]
   * @param  {?} schema    [description]
   * @param  {?} container [description]
   * @param  {?} structure [description]
   * @return {?}           [description]
   */
  create (schema, container, structure, level) {
    level = level || 0
    level++

    structure = structure || {}
    let component

    // if (level === 1)
    //   console.log('level', level);

    for (var i = 0; i < schema.length; i++) {
      var name
      var options = {}

      if (schema[i] instanceof Object &&
        typeof schema[i] === 'function') {
        if (isObject(schema[i + 2])) {
          options = schema[i + 2]
        }

        if (typeof schema[i + 1] === 'string') {
          name = schema[i + 1]
          options.name = name
        }

        component = new schema[i](options)

        if (name) {
          structure[name] = component
        }

        if (component) {
          this.display(component.wrapper, options)
          this.style(component, options)
        }

        // if (level === 1) console.log('insert', component, container);
        if (component && container) {
          if (component.insert) component.insert(container)
          else insert(component, container)
        }
      } else if (Array.isArray(schema[i])) {
        this.create(schema[i], component, structure, level)
      }
    }

    return structure
  }

  isClass (F) {
    try {
      var object = new F()
    } catch (err) {
      // verify err is the expected error and then
      return false
    }
    return object
  }

  /**
   * [_initFlexDirection description]
   * @param  {Element} container Init direction for the given container
   * @param  {string} direction (horizontal,vertical)
   */
  display (element, options) {
    var display = options.display
    var direction = options.direction || 'horizontal'

    if (!element || !display) return

    if (direction === 'horizontal') {
      element.className += ' ' + 'flex-raw'
    } else if (direction === 'vertical') {
      element.className += ' ' + 'flex-column'
    }
  }

  /**
   * [style description]
   * @param  {?} component [description]
   * @return {?}           [description]
   */
  style (component) {
    var options = component.options || {}

    // console.log('component', component);

    if (options.flex) {
      css.add(component.wrapper, 'flex-' + options.flex)
    } else {
      var size = options.size
      if (options.size && options.width) {
        component.wrapper.width = size + 'px'
      } else if (options.size && options.height) {
        component.wrapper.height = size + 'px'
      }
    }

    if (options.hide) {
      component.wrapper.display = 'none'
    }

    if (options.theme) {
      css.add(component.wrapper, 'theme' + '-' + options.theme)
    }
  }

  /**
   * [get description]
   * @param  {?} name [description]
   * @return {?}      [description]
   */
  get (name) {
    if (name) return this.component[name]
    else return this.component
  }
}

export default Layout
<commit_msg>remove isClass<commit_after>import { is as isObject } from './module/object'
import css from './module/css'
import insert from './element/insert'

/**
 *
 */
class Layout {
  /**
   * [constructor description]
   * @param  {?} schema    [description]
   * @param  {?} container [description]
   * @return {?}           [description]
   */
  constructor (schema, container) {
    this.component = this.create(schema, container)

    return this
  }

  /**
   * [create description]
   * @param  {?} schema    [description]
   * @param  {?} container [description]
   * @param  {?} structure [description]
   * @return {?}           [description]
   */
  create (schema, container, structure, level) {
    level = level || 0
    level++

    structure = structure || {}
    let component

    // if (level === 1)
    //   console.log('level', level);

    for (var i = 0; i < schema.length; i++) {
      var name
      var options = {}

      if (schema[i] instanceof Object &&
        typeof schema[i] === 'function') {
        if (isObject(schema[i + 2])) {
          options = schema[i + 2]
        }

        if (typeof schema[i + 1] === 'string') {
          name = schema[i + 1]
          options.name = name
        }

        component = new schema[i](options)

        if (name) {
          structure[name] = component
        }

        if (component) {
          this.display(component.wrapper, options)
          this.style(component, options)
        }

        // if (level === 1) console.log('insert', component, container);
        if (component && container) {
          if (component.insert) component.insert(container)
          else insert(component, container)
        }
      } else if (Array.isArray(schema[i])) {
        this.create(schema[i], component, structure, level)
      }
    }

    return structure
  }

  /**
   * [_initFlexDirection description]
   * @param  {Element} container Init direction for the given container
   * @param  {string} direction (horizontal,vertical)
   */
  display (element, options) {
    var display = options.display
    var direction = options.direction || 'horizontal'

    if (!element || !display) return

    if (direction === 'horizontal') {
      element.className += ' ' + 'flex-row'
    } else if (direction === 'vertical') {
      element.className += ' ' + 'flex-column'
    }
  }

  /**
   * [style description]
   * @param  {?} component [description]
   * @return {?}           [description]
   */
  style (component) {
    var options = component.options || {}

    // console.log('component', component);

    if (options.flex) {
      css.add(component.wrapper, 'flex-' + options.flex)
    } else {
      var size = options.size
      if (options.size && options.width) {
        component.wrapper.width = size + 'px'
      } else if (options.size && options.height) {
        component.wrapper.height = size + 'px'
      }
    }

    if (options.hide) {
      component.wrapper.display = 'none'
    }

    if (options.theme) {
      css.add(component.wrapper, 'theme' + '-' + options.theme)
    }
  }

  /**
   * [get description]
   * @param  {?} name [description]
   * @return {?}      [description]
   */
  get (name) {
    if (name) return this.component[name]
    else return this.component
  }
}

export default Layout
<|endoftext|>


<commit_before>'use strict';

(function() {
	var _         = require('lodash')
	  , moment    = require('moment')
	  , sprintf   = require('sprintf')
	  , qtmrt     = require('./qtmrt')
	  , Packet    = require('./packet')
	  , Component = require('./component')
	;

	class Logger {
		timestamp() {
			return '[' + moment().format('HH:mm:ss') + ']';
		}

		log(message, color, style) {
			if (arguments.length < 2)
				color = 'white';

			if (message && message[color]) {
				message = message[color];

				if (message) {
					if (!_.isUndefined(style) && message[style])
						message = message[style];

					console.log(this.timestamp() + ' ' + message);
				}
			}
		}

		logPacket(packet) {
			var typeColors = { };

			typeColors[qtmrt.ERROR]            = 'red';
			typeColors[qtmrt.COMMAND]          = 'cyan';
			typeColors[qtmrt.XML]              = 'green';
			typeColors[qtmrt.DATA]             = 'white';
			typeColors[qtmrt.NO_MORE_DATA]     = 'grey';
			typeColors[qtmrt.C3D_FILE]         = 'grey';
			typeColors[qtmrt.EVENT]            = 'yellow';
			typeColors[qtmrt.DISCOVER]         = 'grey';
			typeColors[qtmrt.QTM_FILE]         = 'cyan';
			typeColors[qtmrt.COMMAND_RESPONSE] = 'green';

			var typeColor = packet.isResponse ? typeColors[packet.type] : typeColors[qtmrt.COMMAND]
			  , value     = packet.data
			  , suffix    = ''
			;

			// XXX: Move value stuff to toString on packets.
			if (packet.type === qtmrt.EVENT) {
				value = packet.eventName;
			}
			else if (packet.type === qtmrt.XML) {
				value = packet.data.substr(0, 50).replace(/\r?\n|\r|\s+/g, '') + ' ...';
			}
			else if (packet.type === qtmrt.DISCOVER) {
				if (packet.size === 10)
					value = 'QTM Discovery broadcast'.white;
				else {
					value  = packet.serverInfo;
					suffix = (' (' + packet.srcAddress + ':' + packet.srcPort + ')').cyan;
				}
			}
			else if (packet.type === qtmrt.DATA) {
				var componentTypes = '[' + _.keys(packet.components).map(Component.typeToPrettyString).join(', ') + ']';

				value = 'Frame: '      + packet.frameNumber
					+ ', Components: ' + componentTypes
					+ ', Size: '       + packet.size;
			}
			else if (packet.type === qtmrt.C3D) {
				value = '<C3D file> (' + (packet.size - qtmrt.HEADER_SIZE) + ' bytes)';
			}
			else if (packet.type === qtmrt.QTM) {
				value = '<QTM file> (' + (packet.size - qtmrt.HEADER_SIZE) + ' bytes)';
			}

			this.log(
				(sprintf('%-20s', '<' + Packet.typeToString(packet.type) + '>')
				+ value)[typeColor] + suffix
			);
		}
	}

	module.exports = Logger;
})();<commit_msg>Require colors.<commit_after>'use strict';

(function() {
	var _         = require('lodash')
	  , colors    = require('colors')
	  , moment    = require('moment')
	  , sprintf   = require('sprintf')
	  , qtmrt     = require('./qtmrt')
	  , Packet    = require('./packet')
	  , Component = require('./component')
	;

	class Logger {
		timestamp() {
			return '[' + moment().format('HH:mm:ss') + ']';
		}

		log(message, color, style) {
			if (arguments.length < 2)
				color = 'white';

			if (message && message[color]) {
				message = message[color];

				if (message) {
					if (!_.isUndefined(style) && message[style])
						message = message[style];

					console.log(this.timestamp() + ' ' + message);
				}
			}
		}

		logPacket(packet) {
			var typeColors = { };

			typeColors[qtmrt.ERROR]            = 'red';
			typeColors[qtmrt.COMMAND]          = 'cyan';
			typeColors[qtmrt.XML]              = 'green';
			typeColors[qtmrt.DATA]             = 'white';
			typeColors[qtmrt.NO_MORE_DATA]     = 'grey';
			typeColors[qtmrt.C3D_FILE]         = 'grey';
			typeColors[qtmrt.EVENT]            = 'yellow';
			typeColors[qtmrt.DISCOVER]         = 'grey';
			typeColors[qtmrt.QTM_FILE]         = 'cyan';
			typeColors[qtmrt.COMMAND_RESPONSE] = 'green';

			var typeColor = packet.isResponse ? typeColors[packet.type] : typeColors[qtmrt.COMMAND]
			  , value     = packet.data
			  , suffix    = ''
			;

			// XXX: Move value stuff to toString on packets.
			if (packet.type === qtmrt.EVENT) {
				value = packet.eventName;
			}
			else if (packet.type === qtmrt.XML) {
				value = packet.data.substr(0, 50).replace(/\r?\n|\r|\s+/g, '') + ' ...';
			}
			else if (packet.type === qtmrt.DISCOVER) {
				if (packet.size === 10)
					value = 'QTM Discovery broadcast'.white;
				else {
					value  = packet.serverInfo;
					suffix = (' (' + packet.srcAddress + ':' + packet.srcPort + ')').cyan;
				}
			}
			else if (packet.type === qtmrt.DATA) {
				var componentTypes = '[' + _.keys(packet.components).map(Component.typeToPrettyString).join(', ') + ']';

				value = 'Frame: '      + packet.frameNumber
					+ ', Components: ' + componentTypes
					+ ', Size: '       + packet.size;
			}
			else if (packet.type === qtmrt.C3D) {
				value = '<C3D file> (' + (packet.size - qtmrt.HEADER_SIZE) + ' bytes)';
			}
			else if (packet.type === qtmrt.QTM) {
				value = '<QTM file> (' + (packet.size - qtmrt.HEADER_SIZE) + ' bytes)';
			}

			this.log(
				(sprintf('%-20s', '<' + Packet.typeToString(packet.type) + '>')
				+ value)[typeColor] + suffix
			);
		}
	}

	module.exports = Logger;
})();<|endoftext|>


<commit_before>"use strict";

/**
 * @constructor
 * @param {number} memory_size
 */
function Memory(memory_size, no_alloc)
{
    this.size = memory_size;

    // this only supports a 32 bit address space
    var size = 1 << (32 - MMAP_BLOCK_BITS);
    var memory_map_registered = new Uint8Array(size);

    // managed by IO() in io.js
    this.memory_map_registered = memory_map_registered;
    /** @const */ this.memory_map_read8 = [];
    /** @const */ this.memory_map_write8 = [];
    /** @const */ this.memory_map_read32 = [];
    /** @const */ this.memory_map_write32 = [];

    // use by dynamic translator
    //if(OP_TRANSLATION) this.mem_page_infos = new Uint8Array(1 << 20);

    dbg_assert((memory_size & MMAP_BLOCK_SIZE - 1) === 0);

    if(no_alloc)
    {
        var buffer = new ArrayBuffer(0);

        this.mem8 = new Uint8Array(buffer);
        this.mem16 = new Uint16Array(buffer);
        this.mem32s = new Int32Array(buffer);
    }
    else
    {
        var buffer = new ArrayBuffer(memory_size);

        this.mem8 = new Uint8Array(buffer);
        this.mem16 = new Uint16Array(buffer);
        this.mem32s = new Int32Array(buffer);
    }
};

Memory.prototype.get_state = function()
{
    return [
        this.size,
        this.mem8,
    ];
}

Memory.prototype.set_state = function(state)
{
    this.size = state[0];

    this.mem8 = state[1];
    this.mem16 = new Uint16Array(this.mem8.buffer, this.mem8.byteOffset, this.mem8.length >> 1);
    this.mem32s = new Int32Array(this.mem8.buffer, this.mem8.byteOffset, this.mem8.length >> 2);
};

// called by all memory reads and writes
Memory.prototype.debug_write = function(addr, size, value)
{
    if(!DEBUG)
    {
        return;
    }

    dbg_assert(typeof value === "number" && !isNaN(value));
    dbg_assert(value >= -0x80000000 && addr < 0x80000000);

    this.debug_read(addr, size, true);
}

/**
 * @param {boolean=} is_write
 */
Memory.prototype.debug_read = function(addr, size, is_write)
{
    if(!DEBUG)
    {
        return;
    }

    dbg_assert(typeof addr === "number");
    dbg_assert(!isNaN(addr));
};

Memory.prototype.mmap_read8 = function(addr)
{
    return this.memory_map_read8[addr >>> MMAP_BLOCK_BITS](addr);
};

Memory.prototype.mmap_write8 = function(addr, value)
{
    this.memory_map_write8[addr >>> MMAP_BLOCK_BITS](addr, value);
};

Memory.prototype.mmap_read16 = function(addr)
{
    var fn = this.memory_map_read8[addr >>> MMAP_BLOCK_BITS];

    return fn(addr) | fn(addr + 1 | 0) << 8;
};

Memory.prototype.mmap_write16 = function(addr, value)
{
    var fn = this.memory_map_write8[addr >>> MMAP_BLOCK_BITS];

    fn(addr, value & 0xFF);
    fn(addr + 1 | 0, value >> 8 & 0xFF);
};

Memory.prototype.mmap_read32 = function(addr)
{
    var aligned_addr = addr >>> MMAP_BLOCK_BITS;

    return this.memory_map_read32[aligned_addr](addr);
}

Memory.prototype.mmap_write32 = function(addr, value)
{
    var aligned_addr = addr >>> MMAP_BLOCK_BITS;

    this.memory_map_write32[aligned_addr](addr, value);
}

/**
 * @param {number} addr
 */
Memory.prototype.read8 = function(addr)
{
    this.debug_read(addr, 1);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS])
    {
        return this.mmap_read8(addr);
    }
    else
    {
        return this.mem8[addr];
    }
};

/**
 * @param {number} addr
 */
Memory.prototype.read16 = function(addr)
{
    this.debug_read(addr, 2);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS])
    {
        return this.mmap_read16(addr);
    }
    else
    {
        return this.mem8[addr] | this.mem8[addr + 1 | 0] << 8;
    }
};

/**
 * @param {number} addr
 */
Memory.prototype.read_aligned16 = function(addr)
{
    dbg_assert(addr >= 0 && addr < 0x80000000);
    this.debug_read(addr << 1, 2);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS - 1])
    {
        return this.mmap_read16(addr << 1);
    }
    else
    {
        return this.mem16[addr];
    }
};

/**
 * @param {number} addr
 */
Memory.prototype.read32s = function(addr)
{
    this.debug_read(addr, 4);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS])
    {
        return this.mmap_read32(addr);
    }
    else
    {
        return this.mem8[addr] | this.mem8[addr + 1 | 0] << 8 |
            this.mem8[addr + 2 | 0] << 16 | this.mem8[addr + 3 | 0] << 24;
    }
};

/**
 * @param {number} addr
 */
Memory.prototype.read_aligned32 = function(addr)
{
    dbg_assert(addr >= 0 && addr < 0x40000000);
    this.debug_read(addr << 2, 4);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS - 2])
    {
        return this.mmap_read32(addr << 2);
    }
    else
    {
        return this.mem32s[addr];
    }
};

/**
 * @param {number} addr
 * @param {number} value
 */
Memory.prototype.write8 = function(addr, value)
{
    this.debug_write(addr, 1, value);

    var page = addr >>> MMAP_BLOCK_BITS;

    //if(OP_TRANSLATION) this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;

    if(this.memory_map_registered[page])
    {
        this.mmap_write8(addr, value);
    }
    else
    {
        this.mem8[addr] = value;
    }
};

/**
 * @param {number} addr
 * @param {number} value
 */
Memory.prototype.write16 = function(addr, value)
{
    this.debug_write(addr, 2, value);

    var page = addr >>> MMAP_BLOCK_BITS;

    //if(OP_TRANSLATION)
    //{
    //    this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
    //    this.mem_page_infos[addr + 1 >>> MMAP_BLOCK_BITS] |= MEM_PAGE_WRITTEN;
    //}

    if(this.memory_map_registered[page])
    {
        this.mmap_write16(addr, value);
    }
    else
    {
        this.mem8[addr] = value;
        this.mem8[addr + 1 | 0] = value >> 8;
    }
};

/**
 * @param {number} addr
 * @param {number} value
 */
Memory.prototype.write_aligned16 = function(addr, value)
{
    dbg_assert(addr >= 0 && addr < 0x80000000);
    this.debug_write(addr << 1, 2, value);

    var page = addr >>> MMAP_BLOCK_BITS - 1;

    //if(OP_TRANSLATION) this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;

    if(this.memory_map_registered[page])
    {
        this.mmap_write16(addr << 1, value);
    }
    else
    {
        this.mem16[addr] = value;
    }
};

/**
 * @param {number} addr
 * @param {number} value
 */
Memory.prototype.write32 = function(addr, value)
{
    this.debug_write(addr, 4, value);

    var page = addr >>> MMAP_BLOCK_BITS;

    //if(OP_TRANSLATION)
    //{
    //    this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
    //    this.mem_page_infos[addr + 3 >>> MMAP_BLOCK_BITS] |= MEM_PAGE_WRITTEN;
    //}

    if(this.memory_map_registered[page])
    {
        this.mmap_write32(addr, value);
    }
    else
    {
        this.mem8[addr] = value;
        this.mem8[addr + 1 | 0] = value >> 8;
        this.mem8[addr + 2 | 0] = value >> 16;
        this.mem8[addr + 3 | 0] = value >> 24;
    }
};

Memory.prototype.write_aligned32 = function(addr, value)
{
    dbg_assert(addr >= 0 && addr < 0x40000000);
    this.debug_write(addr << 2, 4, value);

    var page = addr >>> MMAP_BLOCK_BITS - 2;

    //if(OP_TRANSLATION) this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;

    if(this.memory_map_registered[page])
    {
        this.mmap_write32(addr << 2, value);
    }
    else
    {
        this.mem32s[addr] = value;
    }
};

/**
 * @param {number} offset
 * @param {Array.<number>} blob
 */
Memory.prototype.write_blob = function(blob, offset)
{
    dbg_assert(blob && blob.length);

    this.mem8.set(blob, offset);

    //var page = offset >>> 12;
    //var end = (offset + blob) >>> 12;

    //if(OP_TRANSLATION)
    //{
    //    for(; page <= end; page++)
    //    {
    //        this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
    //    }
    //}
};

/**
 * zero byte terminated string
 */
Memory.prototype.read_string = function(addr)
{
    var str = "",
        data_byte;

    while(data_byte = this.read8(addr))
    {
        str += String.fromCharCode(data_byte);
        addr++;
    }

    return str;
};

Memory.prototype.write_string = function(str, addr)
{
    for(var i = 0; i < str.length; i++)
    {
        this.write8(addr + i, str.charCodeAt(i));
    }
};

<commit_msg>a20 implementation (disabled by default)<commit_after>"use strict";

/** @const */
var A20_MASK = ~(1 << 20);
/** @const */
var A20_MASK16 = ~(1 << 20 - 1);
/** @const */
var A20_MASK32 = ~(1 << 20 - 2);

/** @const */
var USE_A20 = false;

/**
 * @constructor
 * @param {number} memory_size
 */
function Memory(memory_size, no_alloc)
{
    this.size = memory_size;

    // this only supports a 32 bit address space
    var size = 1 << (32 - MMAP_BLOCK_BITS);
    var memory_map_registered = new Uint8Array(size);

    // managed by IO() in io.js
    this.memory_map_registered = memory_map_registered;
    /** @const */ this.memory_map_read8 = [];
    /** @const */ this.memory_map_write8 = [];
    /** @const */ this.memory_map_read32 = [];
    /** @const */ this.memory_map_write32 = [];

    // use by dynamic translator
    //if(OP_TRANSLATION) this.mem_page_infos = new Uint8Array(1 << 20);

    dbg_assert((memory_size & MMAP_BLOCK_SIZE - 1) === 0);

    if(no_alloc)
    {
        var buffer = new ArrayBuffer(0);

        this.mem8 = new Uint8Array(buffer);
        this.mem16 = new Uint16Array(buffer);
        this.mem32s = new Int32Array(buffer);
    }
    else
    {
        var buffer = new ArrayBuffer(memory_size);

        this.mem8 = new Uint8Array(buffer);
        this.mem16 = new Uint16Array(buffer);
        this.mem32s = new Int32Array(buffer);
    }

    this.a20_enabled = true;
};

Memory.prototype.get_state = function()
{
    return [
        this.size,
        this.mem8,
    ];
}

Memory.prototype.set_state = function(state)
{
    this.size = state[0];

    this.mem8 = state[1];
    this.mem16 = new Uint16Array(this.mem8.buffer, this.mem8.byteOffset, this.mem8.length >> 1);
    this.mem32s = new Int32Array(this.mem8.buffer, this.mem8.byteOffset, this.mem8.length >> 2);
};

// called by all memory reads and writes
Memory.prototype.debug_write = function(addr, size, value)
{
    if(!DEBUG)
    {
        return;
    }

    dbg_assert(typeof value === "number" && !isNaN(value));
    dbg_assert(value >= -0x80000000 && addr < 0x80000000);

    this.debug_read(addr, size, true);
}

/**
 * @param {boolean=} is_write
 */
Memory.prototype.debug_read = function(addr, size, is_write)
{
    if(!DEBUG)
    {
        return;
    }

    dbg_assert(typeof addr === "number");
    dbg_assert(!isNaN(addr));
};

Memory.prototype.mmap_read8 = function(addr)
{
    return this.memory_map_read8[addr >>> MMAP_BLOCK_BITS](addr);
};

Memory.prototype.mmap_write8 = function(addr, value)
{
    this.memory_map_write8[addr >>> MMAP_BLOCK_BITS](addr, value);
};

Memory.prototype.mmap_read16 = function(addr)
{
    var fn = this.memory_map_read8[addr >>> MMAP_BLOCK_BITS];

    return fn(addr) | fn(addr + 1 | 0) << 8;
};

Memory.prototype.mmap_write16 = function(addr, value)
{
    var fn = this.memory_map_write8[addr >>> MMAP_BLOCK_BITS];

    fn(addr, value & 0xFF);
    fn(addr + 1 | 0, value >> 8 & 0xFF);
};

Memory.prototype.mmap_read32 = function(addr)
{
    var aligned_addr = addr >>> MMAP_BLOCK_BITS;

    return this.memory_map_read32[aligned_addr](addr);
}

Memory.prototype.mmap_write32 = function(addr, value)
{
    var aligned_addr = addr >>> MMAP_BLOCK_BITS;

    this.memory_map_write32[aligned_addr](addr, value);
}

/**
 * @param {number} addr
 */
Memory.prototype.read8 = function(addr)
{
    this.debug_read(addr, 1);
    if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS])
    {
        return this.mmap_read8(addr);
    }
    else
    {
        return this.mem8[addr];
    }
};

/**
 * @param {number} addr
 */
Memory.prototype.read16 = function(addr)
{
    this.debug_read(addr, 2);
    if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS])
    {
        return this.mmap_read16(addr);
    }
    else
    {
        return this.mem8[addr] | this.mem8[addr + 1 | 0] << 8;
    }
};

/**
 * @param {number} addr
 */
Memory.prototype.read_aligned16 = function(addr)
{
    dbg_assert(addr >= 0 && addr < 0x80000000);
    this.debug_read(addr << 1, 2);
    if(USE_A20 && !this.a20_enabled) addr &= A20_MASK16;

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS - 1])
    {
        return this.mmap_read16(addr << 1);
    }
    else
    {
        return this.mem16[addr];
    }
};

/**
 * @param {number} addr
 */
Memory.prototype.read32s = function(addr)
{
    this.debug_read(addr, 4);
    if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS])
    {
        return this.mmap_read32(addr);
    }
    else
    {
        return this.mem8[addr] | this.mem8[addr + 1 | 0] << 8 |
            this.mem8[addr + 2 | 0] << 16 | this.mem8[addr + 3 | 0] << 24;
    }
};

/**
 * @param {number} addr
 */
Memory.prototype.read_aligned32 = function(addr)
{
    dbg_assert(addr >= 0 && addr < 0x40000000);
    this.debug_read(addr << 2, 4);

    if(this.memory_map_registered[addr >>> MMAP_BLOCK_BITS - 2])
    {
        return this.mmap_read32(addr << 2);
    }
    else
    {
        return this.mem32s[addr];
    }
};

/**
 * @param {number} addr
 * @param {number} value
 */
Memory.prototype.write8 = function(addr, value)
{
    this.debug_write(addr, 1, value);
    if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;

    var page = addr >>> MMAP_BLOCK_BITS;

    //if(OP_TRANSLATION) this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;

    if(this.memory_map_registered[page])
    {
        this.mmap_write8(addr, value);
    }
    else
    {
        this.mem8[addr] = value;
    }
};

/**
 * @param {number} addr
 * @param {number} value
 */
Memory.prototype.write16 = function(addr, value)
{
    this.debug_write(addr, 2, value);
    if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;

    var page = addr >>> MMAP_BLOCK_BITS;

    //if(OP_TRANSLATION)
    //{
    //    this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
    //    this.mem_page_infos[addr + 1 >>> MMAP_BLOCK_BITS] |= MEM_PAGE_WRITTEN;
    //}

    if(this.memory_map_registered[page])
    {
        this.mmap_write16(addr, value);
    }
    else
    {
        this.mem8[addr] = value;
        this.mem8[addr + 1 | 0] = value >> 8;
    }
};

/**
 * @param {number} addr
 * @param {number} value
 */
Memory.prototype.write_aligned16 = function(addr, value)
{
    dbg_assert(addr >= 0 && addr < 0x80000000);
    this.debug_write(addr << 1, 2, value);
    if(USE_A20 && !this.a20_enabled) addr &= A20_MASK16;

    var page = addr >>> MMAP_BLOCK_BITS - 1;

    //if(OP_TRANSLATION) this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;

    if(this.memory_map_registered[page])
    {
        this.mmap_write16(addr << 1, value);
    }
    else
    {
        this.mem16[addr] = value;
    }
};

/**
 * @param {number} addr
 * @param {number} value
 */
Memory.prototype.write32 = function(addr, value)
{
    this.debug_write(addr, 4, value);
    if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;

    var page = addr >>> MMAP_BLOCK_BITS;

    //if(OP_TRANSLATION)
    //{
    //    this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
    //    this.mem_page_infos[addr + 3 >>> MMAP_BLOCK_BITS] |= MEM_PAGE_WRITTEN;
    //}

    if(this.memory_map_registered[page])
    {
        this.mmap_write32(addr, value);
    }
    else
    {
        this.mem8[addr] = value;
        this.mem8[addr + 1 | 0] = value >> 8;
        this.mem8[addr + 2 | 0] = value >> 16;
        this.mem8[addr + 3 | 0] = value >> 24;
    }
};

Memory.prototype.write_aligned32 = function(addr, value)
{
    dbg_assert(addr >= 0 && addr < 0x40000000);
    this.debug_write(addr << 2, 4, value);
    if(USE_A20 && !this.a20_enabled) addr &= A20_MASK32;

    var page = addr >>> MMAP_BLOCK_BITS - 2;

    //if(OP_TRANSLATION) this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;

    if(this.memory_map_registered[page])
    {
        this.mmap_write32(addr << 2, value);
    }
    else
    {
        this.mem32s[addr] = value;
    }
};

/**
 * @param {number} offset
 * @param {Array.<number>} blob
 */
Memory.prototype.write_blob = function(blob, offset)
{
    dbg_assert(blob && blob.length);

    this.mem8.set(blob, offset);

    //var page = offset >>> 12;
    //var end = (offset + blob) >>> 12;

    //if(OP_TRANSLATION)
    //{
    //    for(; page <= end; page++)
    //    {
    //        this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
    //    }
    //}
};

/**
 * zero byte terminated string
 */
Memory.prototype.read_string = function(addr)
{
    var str = "",
        data_byte;

    while(data_byte = this.read8(addr))
    {
        str += String.fromCharCode(data_byte);
        addr++;
    }

    return str;
};

Memory.prototype.write_string = function(str, addr)
{
    for(var i = 0; i < str.length; i++)
    {
        this.write8(addr + i, str.charCodeAt(i));
    }
};

<|endoftext|>


<commit_before>/**
 * Contains all the models (data stores) we need.
 */
$(function(){

	window.Plant = Backbone.Model.extend({
		/**
		 * A power plant.
		 *
		 * Static fields:
		 * 	String name			the internal name.
		 * 	String slug			the short form used for retrieving images. Usually it's the name minus spaces, and lowercased.
		 * 	String powerName	the name for the kind of power that's produced.
		 * 	String plantName	the name for the actual plant.
		 * 	int researchCost	Cost (in dollars) to research this plant type
		 * 	int constructionCost	Cost (in dollars) to build the plant or upgrade it
		 * 	int constructionYears	How many years it takes to build the plant (min. 1).
		 * 	int income			how much money you earn each year from this plant.
		 * 	int powerProduction	how much power this generates.
		 * Dynamic fields:
		 * 	int level			up to 3. //TODO make income/powerprod change as level changes
		 * 	int hp				how much endurance this plant has; wears down over time. Max 100 (full health); min 0.
		 */

		defaults: {
			level:	1,
			hp:		100
		},

		getDestructionCost: function(){
			return this.get('constructionCost')/2;
		},

		levelUp: function(){
			this.set('level', this.get('level') + 1);
		}
	});

	var Career = Backbone.Model.extend({
		/**
		 * Information about you, the player.
		 *
		 * Fields:
		 * 	int money
		 * 	int year					the current round (known as a year.) Starts at 1.
		 * 	String name
		 * 	Collection<Plant> plants	a list of plant types the user has researched. NOT the same as the Plants enum.
		 *  Cities cities				the list of all cities. Will be modified as they develop.
		 */

		 defaults: {
			 money:	100000,
			 year:	1,
			 name:	"Neel",

			 plants: new Backbone.Collection
		 },

		 /* Functions */

		/**
		 * Changes the amount of money you have (whether positive or negative.)
		 */
		changeMoney: function(amount){
			this.set('money',this.get('money') + amount);
		},

		/**
		 * Increments the year.
		 */
		nextYear: function(){
			this.set('year',this.get('year')+1);
			this.changeMoney(this.getIncome()); //+cash for this year
		},

		/**
		 * Returns the amount of money you earn each year from all of your plants/cities.
		 */
		getIncome: function(){
			return cities.reduce(function(sum, city){
				return sum + city.getIncome();
			}, 0);
		},

		/**
		 * Returns the amount of power, in GWh, that are produced by all the cities/plants put together.
		 */
		getPower: function(){
			return cities.reduce(function(sum, city){
				return sum + city.getPower();
			}, 0);
		},

		/**
		 * Returns - as an int from 0 to 100 - what percent of the power that is needed to win is currently being generated.
		 */
		getPowerPercent: function(){
			//TODO make constant
			return Math.round(this.getPower()/1000*100);
		},

		/*
		 * Adds the given plant type to the list of plants we can build.
		 */
		researchPlantType: function(plant){
			this.get('plants').add(plant);
			this.changeMoney(-plant.get('researchCost'));
		},

		/**
		 * Takes ownership of the given city.
		 */
		expandToCity: function(city){
			city.set('owned', true);
			this.changeMoney(-city.get('expansionCost'));
		},

	});

	var Map = Backbone.Model.extend({
		/*
		 * Houses information about the map's current state.
		 *
		 * Fields:
		 * 	Region region	(active region)
		 * 	City city		(active city)
		 * 	ViewType viewType	the part of the map the user is currently looking at: nation, region, city.
		 */
	});

	var City = Backbone.Model.extend({
		/*
		 * Data for an individual city, where you can build plants.
		 * Fields:
		 *  String name
		 * 	bool owned (by player)
		 *  bool headquarters
		 * 	Collection<Plant> plants	(up to 3) plants in this city.
		 * 	int expansionCost			how much money it costs to unlock this city.
		 *	Region region (see Regions enum)
		 * 	int[] nationalCoords		coordinates of city on the national map in form [x,y] where x and y are in percents from top left (in decimal form)
		 * int[] regionalCoords			coordinates for the region they're in. Same format as national.
		 *
		 * In constructor, pass:
		 * 	String name
		 * 	String regionName ("Northeast", "West", etc.)
		 * 	int[] nationalCoords
		 * 	int[] regionalCoords
		 */

		defaults: function(){
			return {
			 owned: 	false,
			 headquarters: false,
			 plants:	new Backbone.Collection,
			 expansionCost:	20000
			};
		},

		constructor: function(){
			Backbone.Model.prototype.constructor.apply(this, arguments);

			if(this.get('regionName')){
				this.set('region', Regions[this.get('regionName')]);
			}
		},

		/**
		 * Returns the annual income of the sum of this city's power plants.
		 */
		getIncome: function(){
			return _.reduce(this.get('plants').pluck('income'), function(sum, x){ return sum + x; }, 0);
		},

		/**
		 * Returns the amount of power (in GWh) generated by the sum of this city's power plants.
		 */
		getPower: function(){
			return _.reduce(this.get('plants').pluck('powerProduction'), function(sum, x){ return sum + x; }, 0);
		},

		/**
		 * Returns how much money it would take to make this city your headquarters.
		 */
		getHeadquarterCost: function(){
			return this.get('expansionCost') * 2;
		},

		/*
		 * Constructs the given plant in this city NOW.
		 */
		buildPlant: function(plant){
			this.get('plants').add(plant);
			career.changeMoney(-plant.get('constructionCost'));
		},

		/*
		 * Destroys the given plant in this city NOW.
		 */
		destroyPlant: function(plant){
			this.get('plants').remove(plant);
			career.changeMoney(-plant.getDestructionCost());
		}
	});

	var Cities = Backbone.Collection.extend({
		/*
		 * List of cities.
		 */

		model: City,

		url: 'res/stats/cities.json',

		//TODO do the headquarters fns make more sense as part of career?
		/**
		 * Returns the City object representing the player's headquarters
		 */
		getHeadquarters: function(){
			return this.findWhere({ headquarters: true });
		},

		/**
		 * Changes the player's headquarters. The old headquarters will be removed.
 		 * @param {City} city	the new headquarters.
		 */
		setHeadquarters: function(city){
			this.findWhere({ headquarters: true }).set('headquarters', false);
			city.set('headquarters', true);
			career.changeMoney(-city.getHeadquarterCost());
		}
	});

	//instantiating models
	window.map = new Map();
	window.career = new Career();

	window.cities = new Cities();
	cities.fetch({
		success: function(model, response, options){
			cities.reset(response);

			cities.url = null; //prevent accidentally saving to server later

			//TEMP
			cities.each(function(c){
				if(c.get('region') === Regions.Northeast){
					c.set('owned',true);
				}
			});
			cities.findWhere({"name": "New York"}).set('headquarters',true);

			appView.render();
		},
		error: function(model, response, options){
		}
	});
	career.set('cities',cities);
});
<commit_msg>changes hp each year<commit_after>/**
 * Contains all the models (data stores) we need.
 */
$(function(){

	window.Plant = Backbone.Model.extend({
		/**
		 * A power plant.
		 *
		 * Static fields:
		 * 	String name			the internal name.
		 * 	String slug			the short form used for retrieving images. Usually it's the name minus spaces, and lowercased.
		 * 	String powerName	the name for the kind of power that's produced.
		 * 	String plantName	the name for the actual plant.
		 * 	int researchCost	Cost (in dollars) to research this plant type
		 * 	int constructionCost	Cost (in dollars) to build the plant or upgrade it
		 * 	int constructionYears	How many years it takes to build the plant (min. 1).
		 * 	int income			how much money you earn each year from this plant.
		 * 	int powerProduction	how much power this generates.
		 * Dynamic fields:
		 * 	int level			up to 3. //TODO make income/powerprod change as level changes
		 * 	int hp				how much endurance this plant has; wears down over time. Max 100 (full health); min 0.
		 */

		defaults: {
			level:	1,
			hp:		100
		},

		getDestructionCost: function(){
			return this.get('constructionCost')/2;
		},

		levelUp: function(){
			this.set('level', this.get('level') + 1);
		}
	});

	var Career = Backbone.Model.extend({
		/**
		 * Information about you, the player.
		 *
		 * Fields:
		 * 	int money
		 * 	int year					the current round (known as a year.) Starts at 1.
		 * 	String name
		 * 	Collection<Plant> plants	a list of plant types the user has researched. NOT the same as the Plants enum.
		 *  Cities cities				the list of all cities. Will be modified as they develop.
		 */

		 defaults: {
			 money:	100000,
			 year:	1,
			 name:	"Neel",

			 plants: new Backbone.Collection
		 },

		 /* Functions */

		/**
		 * Changes the amount of money you have (whether positive or negative.)
		 */
		changeMoney: function(amount){
			this.set('money',this.get('money') + amount);
		},

		/**
		 * Increments the year.
		 */
		nextYear: function(){
			this.set('year',this.get('year')+1);
			this.changeMoney(this.getIncome()); //+cash for this year
			cities.each(function(city){
				cities.get('plants')
				plants.each(function(plant){
					plant.set("hp", plant.get("hp") - 5 ;)
				})

				/**
				 * Loop through array
				 * array.each(function(x){
				 * 	x.set('y', 5)
				 * }
				 *
				 * ===
				 *
				 * for Item x in array{
				 *  x.setY(5);
				 * }
				 * /

			});
		},

		/**
		 * Returns the amount of money you earn each year from all of your plants/cities.
		 */
		getIncome: function(){
			return cities.reduce(function(sum, city){
				return sum + city.getIncome();
			}, 0);
		},

		/**
		 * Returns the amount of power, in GWh, that are produced by all the cities/plants put together.
		 */
		getPower: function(){
			return cities.reduce(function(sum, city){
				return sum + city.getPower();
			}, 0);
		},

		/**
		 * Returns - as an int from 0 to 100 - what percent of the power that is needed to win is currently being generated.
		 */
		getPowerPercent: function(){
			//TODO make constant
			return Math.round(this.getPower()/1000*100);
		},

		/*
		 * Adds the given plant type to the list of plants we can build.
		 */
		researchPlantType: function(plant){
			this.get('plants').add(plant);
			this.changeMoney(-plant.get('researchCost'));
		},

		/**
		 * Takes ownership of the given city.
		 */
		expandToCity: function(city){
			city.set('owned', true);
			this.changeMoney(-city.get('expansionCost'));
		},

	});

	var Map = Backbone.Model.extend({
		/*
		 * Houses information about the map's current state.
		 *
		 * Fields:
		 * 	Region region	(active region)
		 * 	City city		(active city)
		 * 	ViewType viewType	the part of the map the user is currently looking at: nation, region, city.
		 */
	});

	var City = Backbone.Model.extend({
		/*
		 * Data for an individual city, where you can build plants.
		 * Fields:
		 *  String name
		 * 	bool owned (by player)
		 *  bool headquarters
		 * 	Collection<Plant> plants	(up to 3) plants in this city.
		 * 	int expansionCos		how much money it costs to unlock this city.
		 *	Region region (see Regions enum)
		 * 	int[] nationalCoords		coordinates of city on the national map in form [x,y] where x and y are in percents from top left (in decimal form)
		 * int[] regionalCoords			coordinates for the region they're in. Same format as national.
		 *
		 * In constructor, pass:
		 * 	String name
		 * 	String regionName ("Northeast", "West", etc.)
		 * 	int[] nationalCoords
		 * 	int[] regionalCoords
		 */

		defaults: function(){
			return {
			 owned: 	false,
			 headquarters: false,
			 plants:	new Backbone.Collection,
			 expansionCost:	20000
			};
		},

		constructor: function(){
			Backbone.Model.prototype.constructor.apply(this, arguments);

			if(this.get('regionName')){
				this.set('region', Regions[this.get('regionName')]);
			}
		},

		/**
		 * Returns the annual income of the sum of this city's power plants.
		 */
		getIncome: function(){
			return _.reduce(this.get('plants').pluck('income'), function(sum, x){ return sum + x; }, 0);
		},

		/**
		 * Returns the amount of power (in GWh) generated by the sum of this city's power plants.
		 */
		getPower: function(){
			return _.reduce(this.get('plants').pluck('powerProduction'), function(sum, x){ return sum + x; }, 0);
		},

		/**
		 * Returns how much money it would take to make this city your headquarters.
		 */
		getHeadquarterCost: function(){
			return this.get('expansionCost') * 2;
		},

		/*
		 * Constructs the given plant in this city NOW.
		 */
		buildPlant: function(plant){
			this.get('plants').add(plant);
			career.changeMoney(-plant.get('constructionCost'));
		},

		/*
		 * Destroys the given plant in this city NOW.
		 */
		destroyPlant: function(plant){
			this.get('plants').remove(plant);
			career.changeMoney(-plant.getDestructionCost());
		}
	});

	var Cities = Backbone.Collection.extend({
		/*
		 * List of cities.
		 */

		model: City,

		url: 'res/stats/cities.json',

		//TODO do the headquarters fns make more sense as part of career?
		/**
		 * Returns the City object representing the player's headquarters
		 */
		getHeadquarters: function(){
			return this.findWhere({ headquarters: true });
		},

		/**
		 * Changes the player's headquarters. The old headquarters will be removed.
 		 * @param {City} city	the new headquarters.
		 */
		setHeadquarters: function(city){
			this.findWhere({ headquarters: true }).set('headquarters', false);
			city.set('headquarters', true);
			career.changeMoney(-city.getHeadquarterCost());
		}
	});

	//instantiating models
	window.map = new Map();
	window.career = new Career();

	window.cities = new Cities();
	cities.fetch({
		success: function(model, response, options){
			cities.reset(response);

			cities.url = null; //prevent accidentally saving to server later

			//TEMP
			cities.each(function(c){
				if(c.get('region') === Regions.Northeast){
					c.set('owned',true);
				}
			});
			cities.findWhere({"name": "New York"}).set('headquarters',true);

			appView.render();
		},
		error: function(model, response, options){
		}
	});
	career.set('cities',cities);
});
<|endoftext|>


<commit_before>import {Record, List, Map, fromJS} from 'immutable';
import {MODE_IDLE} from './constants';
import {SNAP_MASK} from './utils/snap';

let safeLoadMapList = (mapList, Model, defaultMap) => {
  return mapList
    ? new Map(mapList).map(m => new Model(m)).toMap()
    : (defaultMap || new Map());
};

export class Guide extends Record({
  id: '',
  type: '',
  properties: Map()
}, 'Guide') {
  constructor(json = {}) {
    super({
      ...json,
      properties: fromJS(json.properties || {})
    });
  }
}

export const DefaultGuides = new Map({
  'h1': new Guide({
    id: 'h1',
    type: 'horizontal-streak',
    properties: {
      step: 20,
      colors: ['#808080', '#ddd', '#ddd', '#ddd', '#ddd']
    }
  }),
  'v1': new Guide({
    id: 'v1',
    type: 'vertical-streak',
    properties: {
      step: 20,
      colors: ['#808080', '#ddd', '#ddd', '#ddd', '#ddd']
    }
  })
});

export class ElementsSet extends Record({
  vertices: new List(),
  lines: new List(),
  holes: new List(),
  areas: new List(),
  items: new List(),
}, 'ElementsSet') {
  constructor(json = {}) {
    super({
      vertices: new List(json.vertices || []),
      lines: new List(json.lines || []),
      holes: new List(json.holes || []),
      areas: new List(json.areas || []),
      items: new List(json.items || [])
    })
  }
}

export class Vertex extends Record({
  id: '',
  x: -1,
  y: -1,
  prototype: 'vertices',
  name: '',
  selected: false,
  lines: new List(),
  areas: new List(),
  misc: new Map()
}, 'Vertex') {
  constructor(json = {}) {
    super({
      ...json,
      lines: new List(json.lines || []),
      areas: new List(json.areas || [])
    })
  }
}

export class Line extends Record({
  id: '',
  type: '',
  prototype: 'lines',
  name: '',
  vertices: new List(),
  holes: new List(),
  selected: false,
  properties: new Map(),
  misc: new Map()
}, 'Line') {
  constructor(json = {}) {
    super({
      ...json,
      properties: fromJS(json.properties || {}),
      vertices: new List(json.vertices || []),
      holes: new List(json.holes || []),
    })
  }
}

export class Hole extends Record({
  id: '',
  type: '',
  prototype: 'holes',
  name: '',
  offset: -1,
  line: '',
  selected: false,
  properties: new Map(),
  misc: new Map()
}, 'Hole') {
  constructor(json = {}) {
    super({
      ...json,
      properties: fromJS(json.properties || {})
    })
  }
}

export class Area extends Record({
  id: '',
  type: '',
  prototype: 'areas',
  name: '',
  vertices: new List(),
  holes: new List(),
  selected: false,
  properties: new Map(),
  misc: new Map()
}, 'Area') {
  constructor(json = {}) {
    super({
      ...json,
      properties: fromJS(json.properties || {}),
      vertices: new List(json.vertices || [])
    })
  }
}

export class Item extends Record({
  id: '',
  prototype: 'items',
  name: '',
  type: '',
  properties: new Map(),
  selected: false,
  x: 0,
  y: 0,
  rotation: 0,
  misc: new Map()
}, 'Item') {
  constructor(json = {}) {
    super({
      ...json,
      properties: fromJS(json.properties || {})
    })
  }
}

export class Layer extends Record({
  id: '',
  altitude: 0,
  order: 0,
  opacity: 1,
  name: '',
  visible: true,
  vertices: new Map(),
  lines: new Map(),
  holes: new Map(),
  areas: new Map(),
  items: new Map(),
  selected: new ElementsSet(),
}, 'Layer') {
  constructor(json = {}) {
    super({
      ...json,
      vertices: safeLoadMapList(json.vertices, Vertex),
      lines: safeLoadMapList(json.lines, Line),
      holes: safeLoadMapList(json.holes, Hole),
      areas: safeLoadMapList(json.areas, Area),
      items: safeLoadMapList(json.items, Item),
      selected: new ElementsSet(json.selected)
    });
  }
}

export const DefaultLayers = new Map({
  'layer-1': new Layer({id: 'layer-1', name: 'default'})
});

export class Scene extends Record({
  unit: 'cm',
  layers: new Map(),
  guides: new Map(),
  selectedLayer: null,
  width: 3000,
  height: 2000,
  meta: new Map()   //additional info
}, 'Scene') {
  constructor(json = {}) {
    let layers = safeLoadMapList(json.layers, Layer, DefaultLayers);
    super({
      ...json,
      guides: safeLoadMapList(json.guides, Guide, DefaultGuides),
      layers,
      selectedLayer: layers.first().id,
      meta: json.meta ? fromJS(json.meta) : new Map()
    })
  }
}

export class CatalogElement extends Record({
  name: '',
  prototype: '',
  info: new Map(),
  properties: new Map(),
}, 'CatalogElement') {
  constructor(json = {}) {
    super({
      ...json,
      info: fromJS(json.info),
      properties: fromJS(json.properties)
    });
  }
}

export class Catalog extends Record({
  ready: false,
  page: "root",
  path: new List(),
  elements: new Map(),
}, 'Catalog') {
  constructor(json = {}) {
    let elements = safeLoadMapList(json.elements, CatalogElement);
    super({
      elements,
      ready: !elements.isEmpty()
    })
  }

  factoryElement(type, options, initialProperties = {}) {
    if (!this.elements.has(type)) {
      let catList = this.elements.map(element => element.name).toArray();
      throw new Error(`Element ${type} does not exist in catalog ${catList}`);
    }

    let element = this.elements.get(type);
    let properties = element.properties.map((value, key) => initialProperties[key] || value.get('defaultValue'));

    switch (element.prototype) {
      case 'lines':
        return new Line(options).merge({properties});

      case 'holes':
        return new Hole(options).merge({properties});

      case 'areas':
        return new Area(options).merge({properties});

      case 'items':
        return new Item(options).merge({properties});

      default:
        throw new Error('prototype not valid');
    }
  }
}

export class State extends Record({
  mode: MODE_IDLE,
  scene: new Scene(),
  sceneHistory: new List([new Scene()]),
  catalog: new Catalog(),
  viewer2D: new Map(),
  mouse: new Map({x: 0, y: 0}),
  zoom: 0,
  snapMask: SNAP_MASK,
  snapElements: new List(),
  activeSnapElement: null,
  drawingSupport: new Map(),
  draggingSupport: new Map(),
  rotatingSupport: new Map(),
  errors: new List(),
  warnings: new List(),
  misc: new Map()   //additional info
}, 'State') {
  constructor(json = {}) {
    let scene = new Scene(json.scene);
    super({
      ...json,
      scene,
      sceneHistory: json.sceneHistory ? json.sceneHistory : new List([scene]),
      catalog: new Catalog(json.catalog || {}),
      viewer2D: new Map(json.viewer2D || {}),
      drawingSupport: new Map(json.drawingSupport || {}),
      draggingSupport: new Map(json.draggingSupport || {}),
      rotatingSupport: new Map(json.rotatingSupport || {}),
      misc: json.misc ? fromJS(json.misc) : new Map()
    })
  }
}

<commit_msg>added clipboardProperties to global state<commit_after>import {Record, List, Map, fromJS} from 'immutable';
import {MODE_IDLE} from './constants';
import {SNAP_MASK} from './utils/snap';

let safeLoadMapList = (mapList, Model, defaultMap) => {
  return mapList
    ? new Map(mapList).map(m => new Model(m)).toMap()
    : (defaultMap || new Map());
};

export class Guide extends Record({
  id: '',
  type: '',
  properties: Map()
}, 'Guide') {
  constructor(json = {}) {
    super({
      ...json,
      properties: fromJS(json.properties || {})
    });
  }
}

export const DefaultGuides = new Map({
  'h1': new Guide({
    id: 'h1',
    type: 'horizontal-streak',
    properties: {
      step: 20,
      colors: ['#808080', '#ddd', '#ddd', '#ddd', '#ddd']
    }
  }),
  'v1': new Guide({
    id: 'v1',
    type: 'vertical-streak',
    properties: {
      step: 20,
      colors: ['#808080', '#ddd', '#ddd', '#ddd', '#ddd']
    }
  })
});

export class ElementsSet extends Record({
  vertices: new List(),
  lines: new List(),
  holes: new List(),
  areas: new List(),
  items: new List(),
}, 'ElementsSet') {
  constructor(json = {}) {
    super({
      vertices: new List(json.vertices || []),
      lines: new List(json.lines || []),
      holes: new List(json.holes || []),
      areas: new List(json.areas || []),
      items: new List(json.items || [])
    })
  }
}

export class Vertex extends Record({
  id: '',
  x: -1,
  y: -1,
  prototype: 'vertices',
  name: '',
  selected: false,
  lines: new List(),
  areas: new List(),
  misc: new Map()
}, 'Vertex') {
  constructor(json = {}) {
    super({
      ...json,
      lines: new List(json.lines || []),
      areas: new List(json.areas || [])
    })
  }
}

export class Line extends Record({
  id: '',
  type: '',
  prototype: 'lines',
  name: '',
  vertices: new List(),
  holes: new List(),
  selected: false,
  properties: new Map(),
  misc: new Map()
}, 'Line') {
  constructor(json = {}) {
    super({
      ...json,
      properties: fromJS(json.properties || {}),
      vertices: new List(json.vertices || []),
      holes: new List(json.holes || []),
    })
  }
}

export class Hole extends Record({
  id: '',
  type: '',
  prototype: 'holes',
  name: '',
  offset: -1,
  line: '',
  selected: false,
  properties: new Map(),
  misc: new Map()
}, 'Hole') {
  constructor(json = {}) {
    super({
      ...json,
      properties: fromJS(json.properties || {})
    })
  }
}

export class Area extends Record({
  id: '',
  type: '',
  prototype: 'areas',
  name: '',
  vertices: new List(),
  holes: new List(),
  selected: false,
  properties: new Map(),
  misc: new Map()
}, 'Area') {
  constructor(json = {}) {
    super({
      ...json,
      properties: fromJS(json.properties || {}),
      vertices: new List(json.vertices || [])
    })
  }
}

export class Item extends Record({
  id: '',
  prototype: 'items',
  name: '',
  type: '',
  properties: new Map(),
  selected: false,
  x: 0,
  y: 0,
  rotation: 0,
  misc: new Map()
}, 'Item') {
  constructor(json = {}) {
    super({
      ...json,
      properties: fromJS(json.properties || {})
    })
  }
}

export class Layer extends Record({
  id: '',
  altitude: 0,
  order: 0,
  opacity: 1,
  name: '',
  visible: true,
  vertices: new Map(),
  lines: new Map(),
  holes: new Map(),
  areas: new Map(),
  items: new Map(),
  selected: new ElementsSet(),
}, 'Layer') {
  constructor(json = {}) {
    super({
      ...json,
      vertices: safeLoadMapList(json.vertices, Vertex),
      lines: safeLoadMapList(json.lines, Line),
      holes: safeLoadMapList(json.holes, Hole),
      areas: safeLoadMapList(json.areas, Area),
      items: safeLoadMapList(json.items, Item),
      selected: new ElementsSet(json.selected)
    });
  }
}

export const DefaultLayers = new Map({
  'layer-1': new Layer({id: 'layer-1', name: 'default'})
});

export class Scene extends Record({
  unit: 'cm',
  layers: new Map(),
  guides: new Map(),
  selectedLayer: null,
  width: 3000,
  height: 2000,
  meta: new Map()   //additional info
}, 'Scene') {
  constructor(json = {}) {
    let layers = safeLoadMapList(json.layers, Layer, DefaultLayers);
    super({
      ...json,
      guides: safeLoadMapList(json.guides, Guide, DefaultGuides),
      layers,
      selectedLayer: layers.first().id,
      meta: json.meta ? fromJS(json.meta) : new Map()
    })
  }
}

export class CatalogElement extends Record({
  name: '',
  prototype: '',
  info: new Map(),
  properties: new Map(),
}, 'CatalogElement') {
  constructor(json = {}) {
    super({
      ...json,
      info: fromJS(json.info),
      properties: fromJS(json.properties)
    });
  }
}

export class Catalog extends Record({
  ready: false,
  page: "root",
  path: new List(),
  elements: new Map(),
}, 'Catalog') {
  constructor(json = {}) {
    let elements = safeLoadMapList(json.elements, CatalogElement);
    super({
      elements,
      ready: !elements.isEmpty()
    })
  }

  factoryElement(type, options, initialProperties = {}) {
    if (!this.elements.has(type)) {
      let catList = this.elements.map(element => element.name).toArray();
      throw new Error(`Element ${type} does not exist in catalog ${catList}`);
    }

    let element = this.elements.get(type);
    let properties = element.properties.map((value, key) => initialProperties[key] || value.get('defaultValue'));

    switch (element.prototype) {
      case 'lines':
        return new Line(options).merge({properties});

      case 'holes':
        return new Hole(options).merge({properties});

      case 'areas':
        return new Area(options).merge({properties});

      case 'items':
        return new Item(options).merge({properties});

      default:
        throw new Error('prototype not valid');
    }
  }
}

export class State extends Record({
  mode: MODE_IDLE,
  scene: new Scene(),
  sceneHistory: new List([new Scene()]),
  catalog: new Catalog(),
  viewer2D: new Map(),
  mouse: new Map({x: 0, y: 0}),
  zoom: 0,
  snapMask: SNAP_MASK,
  snapElements: new List(),
  activeSnapElement: null,
  drawingSupport: new Map(),
  draggingSupport: new Map(),
  rotatingSupport: new Map(),
  errors: new List(),
  warnings: new List(),
  clipboardProperties: null,
  misc: new Map()   //additional info
}, 'State') {
  constructor(json = {}) {
    let scene = new Scene(json.scene);
    super({
      ...json,
      scene,
      sceneHistory: json.sceneHistory ? json.sceneHistory : new List([scene]),
      catalog: new Catalog(json.catalog || {}),
      viewer2D: new Map(json.viewer2D || {}),
      drawingSupport: new Map(json.drawingSupport || {}),
      draggingSupport: new Map(json.draggingSupport || {}),
      rotatingSupport: new Map(json.rotatingSupport || {}),
      misc: json.misc ? fromJS(json.misc) : new Map()
    })
  }
}

<|endoftext|>


<commit_before>;
(function(mag) {

  "use strict";

  var mod = {
    modules: [],
    promises: [],
    deferreds: [],
    controllers: [],
    elements: []
  }

  mod.getController = function(module, element, fill) {
    var controller

    // FireFox support only
    // Removing since we are now native with Object.observe which is only Chrome & Opera

    if (typeof Proxy !== 'undefined') {
      controller = new Proxy(new module.controller, {
        get: function(target, prop) {
          //more default props like willload, didload, willupdate, didupdate, isupdate
          if (target[prop] === undefined && ['watchers', 'toJSON', 'called', 'onload', 'onunload'].indexOf(prop) === -1) {
            var a = fill.find(element, prop),
              greedy = prop[0] === '$',
              v, // can be an array, object or string
              // for each
              tmp = []
            a.forEach(function(item, index) {
              if (a[index]) {
                if (a[index].value && a[index].value.length > 0) {
                  v = a[index].value
                  if (a[index].type && (a[index].type == 'checkbox' || a[index].type == 'radio')) {
                    v = {
                      _text: v,
                      _checked: a[index].checked
                    }
                    tmp.push(v)
                  }
                } else if (a[index].innerText && a[index].innerText.length > 0) {
                  v = a[index].innerText
                } else if (a[0].innerHTML && a[index].innerHTML.length > 0) {
                  v = a[index].innerHTML
                }
              }
            })
            if (tmp.length > 0 && greedy) return tmp
            return v
          }
          return target[prop]
        }
      })
    } else {
      controller = new module.controller
    }

    return controller
  }

  // function deepFreeze(o) {
  //   var prop, propKey;
  //   Object.freeze(o); // First freeze the object.
  //   for (propKey in o) {
  //     prop = o[propKey];
  //     if (!o.hasOwnProperty(propKey) || !(typeof prop === 'object') || Object.isFrozen(prop)) {
  //       // If the object is on the prototype, not an object, or is already frozen,
  //       // skip it. Note that this might leave an unfrozen reference somewhere in the
  //       // object if there is an already frozen object containing an unfrozen object.
  //       continue;
  //     }

  //     deepFreeze(prop); // Recursively call deepFreeze.
  //   }
  // }

  mod.submodule = function(module, args) {
    // do we need/want this? view/controller will always get the same args
    // difference is that that can't be changed within those functions - does that matter?
    //deepFreeze(args)

    var controller = function() {
        return (module.controller || function() {}).apply(this, args) || this
      },
      view = function(ctrl, ele) {

        if (arguments.length > 1) var nargs = args.concat([].slice.call(arguments, 1))
        module.view.apply(module, nargs ? [ctrl].concat(nargs) : [ctrl])

      },
      output = {
        controller: controller,
        view: view
      }
      // why do we need these?

    //controller.$original = module.controller
    //view.$original = module.view
    controller.$$args = args
    return output
  }

  mod.getArgs = function(i) {
    var args = mod.modules[i] && mod.modules[i].controller && mod.modules[i].controller.$$args ? [mod.controllers[i]].concat(mod.modules[i].controller.$$args) : [mod.controllers[i]]
      // args that contaian circular references will throw an exception up the chain

    attachToArgs(i, args[0], this.elements[i]);

    return args
  }

  var added = [];
  var attacher = function(i, k, obj, element) {
    var oval = obj[k];
    // only for user input fields
    var found = mag.fill.find(element, k);

    if (typeof oval == 'function' || !found[0] || ['INPUT', 'SELECT', 'TEXTAREA'].indexOf(found[0].tagName) === -1) return;

    Object.defineProperty(obj, k, {
      get: function() {
        var found = mag.fill.find(element, k);

        if (found[0] && found[0].value && found[0].value !== oval) {
          oval = found[0].value;
          return found[0].value;
        }
        return oval;
      }
    });
  };

  function attachToArgs(i, args, element) {

    // for each property set accessor property

    // get notification when accessed

    // call fill to get and assign

    if (!added[i]) added[i] = [];

    for (var k in args) {

      if (typeof args[k] === 'object') {
        // recurse
        attachToArgs(i, args[k], element);
      } else {

        if (!added[i][k]) {
          attacher(i, k, args, element);
          added[i][k] = true;
        }
      }
    }
  }

  mag.mod = mod

})(window.mag || {})
<commit_msg>Update module.js<commit_after>;
(function(mag) {

  "use strict";

  var mod = {
    modules: [],
    promises: [],
    deferreds: [],
    controllers: [],
    elements: []
  }

  mod.getController = function(module, element, fill) {
    var controller

    // FireFox support only
    // Removing since we are now native with Object.observe which is only Chrome & Opera

    if (typeof Proxy !== 'undefined') {
      controller = new Proxy(new module.controller, {
        get: function(target, prop) {
          //more default props like willload, didload, willupdate, didupdate, isupdate
          if (target[prop] === undefined && ['watchers', 'toJSON', 'called', 'onload', 'onunload'].indexOf(prop) === -1) {
            var a = fill.find(element, prop),
              greedy = prop[0] === '$',
              v, // can be an array, object or string
              // for each
              tmp = []
            a.forEach(function(item, index) {
              if (a[index]) {
                if (a[index].value && a[index].value.length > 0) {
                  v = a[index].value
                  if (a[index].type && (a[index].type == 'checkbox' || a[index].type == 'radio')) {
                    v = {
                      _text: v,
                      _checked: a[index].checked
                    }
                    tmp.push(v)
                  }
                } else if (a[index].innerText && a[index].innerText.length > 0) {
                  v = a[index].innerText
                } else if (a[0].innerHTML && a[index].innerHTML.length > 0) {
                  v = a[index].innerHTML
                }
              }
            })
            if (tmp.length > 0 && greedy) return tmp
            return v
          }
          return target[prop]
        }
      })
    } else {
      controller = new module.controller
    }

    return controller
  }

  // function deepFreeze(o) {
  //   var prop, propKey;
  //   Object.freeze(o); // First freeze the object.
  //   for (propKey in o) {
  //     prop = o[propKey];
  //     if (!o.hasOwnProperty(propKey) || !(typeof prop === 'object') || Object.isFrozen(prop)) {
  //       // If the object is on the prototype, not an object, or is already frozen,
  //       // skip it. Note that this might leave an unfrozen reference somewhere in the
  //       // object if there is an already frozen object containing an unfrozen object.
  //       continue;
  //     }

  //     deepFreeze(prop); // Recursively call deepFreeze.
  //   }
  // }

  mod.submodule = function(module, args) {
    // do we need/want this? view/controller will always get the same args
    // difference is that that can't be changed within those functions - does that matter?
    //deepFreeze(args)

    var controller = function() {
        return (module.controller || function() {}).apply(this, args) || this
      },
      view = function(ctrl, ele) {

        if (arguments.length > 1) var nargs = args.concat([].slice.call(arguments, 1))
        module.view.apply(module, nargs ? [ctrl].concat(nargs) : [ctrl])

      },
      output = {
        controller: controller,
        view: view
      }
      // why do we need these?

    //controller.$original = module.controller
    //view.$original = module.view
    controller.$$args = args
    return output
  }

  mod.getArgs = function(i) {
    var args = mod.modules[i] && mod.modules[i].controller && mod.modules[i].controller.$$args ? [mod.controllers[i]].concat(mod.modules[i].controller.$$args) : [mod.controllers[i]]
      // args that contaian circular references will throw an exception up the chain

    attachToArgs(i, args[0], this.elements[i]);

    return args
  }

  var added = [];
  var attacher = function(i, k, obj, element) {
    var oval = obj[k];
    // only for user input fields
    var found = mag.fill.find(element, k);

    if (typeof oval == 'function' || !found[0] || ['INPUT', 'SELECT', 'TEXTAREA'].indexOf(found[0].tagName) === -1) return;

    var found = mag.fill.find(element, k);
    var founder = found[0];
    if (founder && !founder.eventOnFocus) {

      var onfocus = function() {
        if (!this.classList.contains('mag-dirty')) {
          this.classList.add('mag-dirty');
        }
      }

      founder.addEventListener("focus", onfocus, false);
      founder.eventOnFocus = true;
    }
    Object.defineProperty(obj, k, {
      get: function() {
        // set on focus listener once
        if (founder && founder.value !== 'undefined' && founder.classList.contains('mag-dirty') && founder.value !== oval) {
          oval = founder.value;
          return founder.value;
        }
        return oval;
      }
    });
  };

  function attachToArgs(i, args, element) {

    // for each property set accessor property

    // get notification when accessed

    // call fill to get and assign

    if (!added[i]) added[i] = [];

    for (var k in args) {

      if (typeof args[k] === 'object') {
        // recurse
        attachToArgs(i, args[k], element);
      } else {

        if (!added[i][k]) {
          attacher(i, k, args, element);
          added[i][k] = true;
        }
      }
    }
  }

  mag.mod = mod

})(window.mag || {})
<|endoftext|>


<commit_before>/* global _:true */

moment.yesterday = function() {return moment.utc().subtract(1, 'day').startOf('day')}
moment.today = function() {return moment.utc().startOf('day')}
moment.now = function() {return moment.utc()}
moment.tomorrow = function() {return moment.utc().add(1, 'day').startOf('day')}

moment.between = function(start, end) {
  return moment().range(start, end)
}

moment.$today = function() {
  return moment.$between(moment.today())
}

moment.$between = function(fromTime, toTime) {
  toTime = toTime || moment.now()
  return {
    '$gte': fromTime.toDate(),
    '$lte': toTime.toDate()
  }
}

moment.$inDay = function(aDay) {
  return {
    '$gte': moment(aDay).startOf('day').toDate(),
    '$lte': moment(aDay).endOf('day').toDate()
  }
}

;(function() {
  Number.prototype.years = Number.prototype.year = function() {return moment.duration(this.valueOf(), 'years')}
  Number.prototype.months = Number.prototype.month = function() {return moment.duration(this.valueOf(), 'months')}
  Number.prototype.days = Number.prototype.day = function() {return moment.duration(this.valueOf(), 'days')}
  Number.prototype.minutes = Number.prototype.minute = function() {return moment.duration(this.valueOf(), 'minutes')}
  Number.prototype.seconds = Number.prototype.second = function() {return moment.duration(this.valueOf(), 'seconds')}
})()

;(function(Moment) {

  Moment.prototype.toString = function() {
    return this.clone().utc().format('YYYY-MM-DDTHH:mm:ss.SSS[Z]')
  }

  Moment.prototype.tojson = function() {
    return '"' + this.toString() + '"'
  }

})(moment().constructor)

;(function(Duration) {

  Duration.prototype.startingNow = function() {
    return this.startingAt(moment.now())
  }

  Duration.prototype.endingNow = function() {
    return this.endingAt(moment.now())
  }

  Duration.prototype.startingAt = function(momentInTime) {
    momentInTime = momentInTime || moment.now()
    return moment().range(momentInTime, moment(momentInTime).add(this))
  }

  Duration.prototype.endingAt = function(momentInTime) {
    momentInTime = momentInTime || moment.now()
    return moment().range(moment(momentInTime).subtract(this), momentInTime)
  }

  Duration.prototype.since = function(momentInTime) {
    return moment(momentInTime ? moment(momentInTime) : moment.now()).add(this)
  }

  Duration.prototype.ago = function(momentInTime) {
    return moment(momentInTime ? moment(momentInTime) : moment.now()).subtract(this)
  }

  Duration.prototype.toString = Duration.prototype.humanize
  Duration.prototype.tojson = function() {
    return '"' + this.toString.apply(this, arguments) + '"'
  }

})(moment.duration().constructor)

;(function(DateRange) {

  DateRange.prototype.forEach = function(duration, callback) {
    duration = (typeof duration === 'string') ? moment.duration(1, duration) : duration
    this.by(duration.startingAt(this.start), callback)
  }

  DateRange.prototype.toString = function() {
    return [this.start.toString(), this.end.toString()].join('/')
  }

  DateRange.prototype.tojson = function() {
    return '"' + this.toString() + '"'
  }

})(moment().range().constructor)
<commit_msg>For since and ago the implicit parameter is now<commit_after>/* global _:true */

moment.yesterday = function() {return moment.utc().subtract(1, 'day').startOf('day')}
moment.today = function() {return moment.utc().startOf('day')}
moment.now = function() {return moment.utc()}
moment.tomorrow = function() {return moment.utc().add(1, 'day').startOf('day')}

moment.between = function(start, end) {
  return moment().range(start, end)
}

moment.$today = function() {
  return moment.$between(moment.today())
}

moment.$between = function(fromTime, toTime) {
  toTime = toTime || moment.now()
  return {
    '$gte': fromTime.toDate(),
    '$lte': toTime.toDate()
  }
}

moment.$inDay = function(aDay) {
  return {
    '$gte': moment(aDay).startOf('day').toDate(),
    '$lte': moment(aDay).endOf('day').toDate()
  }
}

;(function() {
  Number.prototype.years = Number.prototype.year = function() {return moment.duration(this.valueOf(), 'years')}
  Number.prototype.months = Number.prototype.month = function() {return moment.duration(this.valueOf(), 'months')}
  Number.prototype.days = Number.prototype.day = function() {return moment.duration(this.valueOf(), 'days')}
  Number.prototype.minutes = Number.prototype.minute = function() {return moment.duration(this.valueOf(), 'minutes')}
  Number.prototype.seconds = Number.prototype.second = function() {return moment.duration(this.valueOf(), 'seconds')}
})()

;(function(Moment) {

  Moment.prototype.toString = function() {
    return this.clone().utc().format('YYYY-MM-DDTHH:mm:ss.SSS[Z]')
  }

  Moment.prototype.tojson = function() {
    return '"' + this.toString() + '"'
  }

})(moment().constructor)

;(function(Duration) {

  Duration.prototype.startingNow = function() {
    return this.startingAt(/* now is implicit */)
  }

  Duration.prototype.endingNow = function() {
    return this.endingAt(/* now is implicit */)
  }

  Duration.prototype.startingAt = function(momentInTime) {
    momentInTime = (momentInTime ? moment(momentInTime) : moment.now())
    return moment().range(momentInTime, moment(momentInTime).add(this))
  }

  Duration.prototype.endingAt = function(momentInTime) {
    momentInTime = (momentInTime ? moment(momentInTime) : moment.now())
    return moment().range(momentInTime.subtract(this), momentInTime)
  }

  Duration.prototype.since = function() {
    return this.after(/* now is implicit */)
  }

  Duration.prototype.ago = function() {
    return this.before(/* now is implicit */)
  }

  Duration.prototype.after = function(momentInTime) {
    momentInTime = (momentInTime ? moment(momentInTime) : moment.now())
    return momentInTime.add(this)
  }

  Duration.prototype.before = function(momentInTime) {
    momentInTime = (momentInTime ? moment(momentInTime) : moment.now())
    return momentInTime.subtract(this)
  }

  Duration.prototype.toString = Duration.prototype.humanize
  Duration.prototype.tojson = function() {
    return '"' + this.toString.apply(this, arguments) + '"'
  }

})(moment.duration().constructor)

;(function(DateRange) {

  DateRange.prototype.forEach = function(duration, callback) {
    duration = (typeof duration === 'string') ? moment.duration(1, duration) : duration
    this.by(duration.startingAt(this.start), callback)
  }

  DateRange.prototype.toString = function() {
    return [this.start.toString(), this.end.toString()].join('/')
  }

  DateRange.prototype.tojson = function() {
    return '"' + this.toString() + '"'
  }

})(moment().range().constructor)
<|endoftext|>