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

  var SimuStore = $.extend({
    _initialized: false,
    _context: null,
    _current: null,
    _ghost: null,
    _field: new C.Field(),
    _hold: new C.Hold(),
    _histories: new C.Histories(),
    _nexts: new C.Nexts(),
    _nextsVisibled: new C.NextsVisibled(),
    _description: new C.Description(),
    _nextGenerator: new C.NextGenerator(),
    _steps: new C.Steps(),
    _seed: 0,
    _urlParameters: '',

    initialize: function(action, force) {
      if (this._initialized && !action.context.force) {
        this._context.before = action.context.before;
        return;
      }

      this._initialized = true;
      this._context = action.context
      this._seed = this._context.seed == null ? C.Random.nextInt(1000000) : this._context.seed;
      this._nextsVisibled.deserialize(this._context.nextsVisibled);

      this._init(action.context);
      this.emit(C.Constants.Event.Change);
    },

    _init: function(context) {
      var prevs;

      this._current = null,
      this._ghost = null,
      this._field = new C.Field(),
      this._hold = new C.Hold(),
      this._histories = new C.Histories(),
      this._nexts = new C.Nexts(),
      this._description = new C.Description(),
      this._nextGenerator = new C.NextGenerator(),
      this._steps = new C.Steps(),
      this._currentStep = null;

      C.Random.setSeed(this._seed);

      this._hold.deserialize(context.hold);
      this._field.deserialize(context.field);
      this._nexts.deserialize(context.nexts);

      prevs = C.NextsDeserializer.deserialize(context.prevs);
      this._nexts.setAndComplementTypes(this._nexts.types(), prevs, this._nextGenerator);
      while (this._nexts.nextsLength() < 5) {
        this._nexts.push(this._nextGenerator.next());
      }

      this._forwardCurrent();

      this._histories.push(this._current, this._field, this._nexts, this._hold, this._description);
    },

    context: function() {
      return this._context;
    },

    retry: function(action) {
      if (action.isSuperRetry) {
        this._seed = C.Random.nextInt(1000000);
      }

      this._init(this._context);
      this.emit(C.Constants.Event.Change);
    },

    fieldTypes: function() {
      return this._field.innerTypes();
    },

    holdType: function() {
      return this._hold.type();
    },

    nexts: function() {
      return this._nexts.nextTypes();
    },

    nextsFixed: function() {
      return this._nexts.nextTypesFixed();
    },

    nextsVisibled: function() {
      return this._nextsVisibled.status();
    },

    current: function() {
      return this._current;
    },

    ghost: function() {
      return this._ghost;
    },

    canHold: function() {
      return this._hold.canExchange();
    },

    descriptionData: function() {
      return this._description.data();
    },

    seed: function() {
      return this._seed;
    },

    urlParameters: function() {
      return this._urlParameters;
    },

    _forwardCurrent: function() {
      this._current = C.TetriminoFactory.create(this._nexts.next(), this._field.startPivot());
      if (this._nexts.nextsLength() < 5) {
        this._nexts.push(this._nextGenerator.next());
      }

      this._updateGhost();
    },

    hardDrop: function(action) {
      var clearLineNum
        , prevPivotY = this._current.pivot().y
        , canHardDropFromStart;

      this._current.hardDrop(this._field);
      canHardDropFromStart = this._canHardDropFromStart(this._current);
      this._field.settle(this._current);

      if (prevPivotY !== this._current.pivot().y) {
        // 落下があったのでスピン無しに戻す
        this._description.spinType(C.Constants.SpinType.None);
      }

      // 戻っているかもしれないので、その分を忘れてから次の譜を積む
      this._steps.forgetAfter();
      this._steps.pushTetrimino(this._current, this._description.spinType(), canHardDropFromStart);
      this._steps.forward();

      var clearLineNum = this._field.clearLine()
      this._description.clearLineNum(clearLineNum);

      if (clearLineNum > 0) {
        this._description.ren(this._description.ren() + 1);
      } else {
        this._description.ren(0);
      }
      this._description.perfectCleared(this._field.isPerfectCleared());

      this._forwardCurrent();
      this._hold.release();
      this._histories.push(this._current, this._field, this._nexts, this._hold, this._description);

      this._description.fixData();
      this.emit(C.Constants.Event.Change);
    },

    _canHardDropFromStart: function(current) {
      var testCurrent = current.copy()
        , pivot = testCurrent.pivot()
        , currentPivot = current.pivot()
        , hardDropPivot;

      // 開始Y座標からハードドロップでcurrentの座標に落とせるかどうかを判定する
      pivot.y = this._field.startPivot().y;
      testCurrent.pivot(pivot);
      testCurrent.hardDrop(this._field);
      hardDropPivot = testCurrent.pivot();

      return hardDropPivot.x === currentPivot.x && hardDropPivot.y === currentPivot.y;
    },

    softDrop: function(action) {
      if (!this._field.isGround(this._current)) {
        this._current.move({
          x: 0,
          y: -1
        });

        this._description.spinType(C.Constants.SpinType.None);
      }

      this.emit(C.Constants.Event.Change);
    },

    move: function(action) {
      if (this._current.canMove(this._field, { x: action.sign, y: 0 })) {
        this._current.move({
          x: action.sign,
          y: 0
        });

        this._description.spinType(C.Constants.SpinType.None);
        this._updateGhost();

        this.emit(C.Constants.Event.Change);
      }
    },

    hold: function(action) {
      var current;

      if (!this._hold.canExchange()) {
        return;
      }

      // 戻っているかもしれないので、その分を忘れてから次の譜を積む
      this._steps.forgetAfter();
      this._steps.pushHold(this._current.type());
      this._steps.forward();
      current = this._hold.exchange(this._current.type());
      if (current == C.CellType.None) {
        this._forwardCurrent();
      } else {
        this._current = C.TetriminoFactory.create(current, this._field.startPivot());
      }
      this._histories.push(this._current, this._field, this._nexts, this._hold, this._description);

      this._description.spinType(C.Constants.SpinType.None);
      this._updateGhost();
      this.emit(C.Constants.Event.Change);
    },

    turnLeft: function(action) {
      var specialInfo = {};

      if (this._current.turnLeftIfPossible(this._field, specialInfo)
        || this._current.turnLeftSuperlyIfPossible(this._field, specialInfo)) {

        this._description.spinType(specialInfo.spinType);
        this._updateGhost();
        this.emit(C.Constants.Event.Change);
      }
    },

    turnRight: function(action) {
      var specialInfo = {};

      if (this._current.turnRightIfPossible(this._field, specialInfo)
        || this._current.turnRightSuperlyIfPossible(this._field, specialInfo)) {

        this._description.spinType(specialInfo.spinType);
        this._updateGhost();
        this.emit(C.Constants.Event.Change);
      }
    },

    forward: function(action) {
      var history;

      if (!this._histories.canForward()) {
        return;
      }

      this._histories.forward();
      this._steps.forward();
      history = this._histories.current();

      this._current = C.TetriminoFactory.create(history.current(), this._field.startPivot());
      this._field.deserialize(history.field());
      this._nexts.no(history.nextNo());
      this._hold.deserialize(history.hold());
      this._description.current(history.description());

      this._updateGhost();
      this.emit(C.Constants.Event.Change);
    },

    back: function(action) {
      var history;

      if (!this._histories.canBack()) {
        return;
      }

      this._histories.back();
      this._steps.back();
      history = this._histories.current();

      this._current = C.TetriminoFactory.create(history.current(), this._field.startPivot());
      this._field.deserialize(history.field());
      this._nexts.no(history.nextNo());
      this._hold.deserialize(history.hold());
      this._description.current(history.description());

      this._updateGhost();
      this.emit(C.Constants.Event.Change);
    },

    _updateGhost: function() {
      this._ghost = this._current.copy();
      this._ghost.hardDrop(this._field);
    },

    createUrlParameters: function(action) {
      var context = this._context
        , parameters = []
        , f = context.field
        , ns = this._nexts.serialize()
        , nv = this._nextsVisibled.serialize()
        , ss = this._steps.serialize()
        , h = context.hold
        , seed = this._seed;

      if (!!f) {
        parameters.push('f=' + f);
      }

      if (!!ns) {
        parameters.push('ns=' + ns);
      }

      if (!!nv && nv != 'v') {
        parameters.push('nv=' + nv);
      }

      if (!!ss) {
        parameters.push('ss=' + ss);
      }

      if (!!h) {
        parameters.push('h=' + h);
      }

      parameters.push('m=' + C.Constants.Mode.Replay);
      parameters.push('s=' + seed);
      parameters.push('v=' + C.Constants.Version);

      this._urlParameters = parameters.join('&');
      this.emit(C.Constants.Event.SetUrl);
    },

    changeModeToEdit: function(action) {
      var mode = C.Constants.Mode.Edit
        , nexts = new C.Nexts()
        , nextTypes = this.nexts();

      nextTypes.unshift(this._current.type());
      nexts.types(nextTypes);

      var params = {
        before: C.Constants.Mode.Simu,
        field: this._field.serialize(),
        force: true,
        hold: this._hold.serialize(),
        nexts: nexts.serialize(),
        nextsVisibled: this._nextsVisibled.serialize(),
        prevs: '',
      };
      this.emit(C.Constants.Event.ChangeMode, mode, params);
    },

    backToEditMode: function(action) {
      var mode = C.Constants.Mode.Edit
      this.emit(C.Constants.Event.ChangeMode, mode, {
        before: C.Constants.Mode.Simu
      });
    },

    changeModeToReplay: function(action) {
      var mode = C.Constants.Mode.Replay
        , allNextsTypes = this._nexts.types()
        , allNexts = new C.Nexts();

      allNexts.types(allNextsTypes);

      var params = {
        before: C.Constants.Mode.Simu,
        field: this._context.field,
        hold: this._context.hold,
        nexts: allNexts.serialize(),
        nextsVisibled: this._nextsVisibled.serialize(),
        prevs: '',
        steps: this._steps.serialize()
      };
      this.emit(C.Constants.Event.ChangeMode, mode, params);
    },

    clear: function(action) {
      var mode = C.Constants.Mode.Simu
        , params = {
        force: true,
        field: '',
        hold: '',
        nexts: '',
        nextsVisibled: this._nextsVisibled.serialize(),
        prevs: '',
        steps: ''
      };

      this.emit(C.Constants.Event.ChangeMode, mode, params);
    },

    toggleNextVisible: function(action) {
      this._nextsVisibled.toggleVisible(action.index);
      this.emit(C.Constants.Event.Change);
    },

    addChangeListener: function(callback) {
      this.addListener(C.Constants.Event.Change, callback);
    },

    removeChangeListener: function(callback) {
      this.removeListener(C.Constants.Event.Change, callback);
    },

    addSetUrlListener: function(callback) {
      this.addListener(C.Constants.Event.SetUrl, callback);
    },

    removeSetUrlListener: function(callback) {
      this.removeListener(C.Constants.Event.SetUrl, callback);
    },

    addChangeModeListener: function(callback) {
      this.addListener(C.Constants.Event.ChangeMode, callback);
    },

    removeChangeModeListener: function(callback) {
      this.removeListener(C.Constants.Event.ChangeMode, callback);
    },
  }, C.StoreBase);

  C.AppDispatcher.register(function(payload) {
    var action = payload.action;

    switch (action.actionType) {
      case C.Constants.Action.Simu.Initialize:
        SimuStore.initialize(action);
        break;
      case C.Constants.Action.Simu.HardDrop:
        SimuStore.hardDrop(action);
        break;
      case C.Constants.Action.Simu.SoftDrop:
        SimuStore.softDrop(action);
        break;
      case C.Constants.Action.Simu.Move:
        SimuStore.move(action);
        break;
      case C.Constants.Action.Simu.Hold:
        SimuStore.hold(action);
        break;
      case C.Constants.Action.Simu.TurnRight:
        SimuStore.turnRight(action);
        break;
      case C.Constants.Action.Simu.TurnLeft:
        SimuStore.turnLeft(action);
        break;
      case C.Constants.Action.Simu.Retry:
        SimuStore.retry(action);
        break;
      case C.Constants.Action.Simu.Forward:
        SimuStore.forward(action);
        break;
      case C.Constants.Action.Simu.Back:
        SimuStore.back(action);
        break;
      case C.Constants.Action.Simu.Clear:
        SimuStore.clear(action);
        break;
      case C.Constants.Action.Simu.CreateUrlParameters:
        SimuStore.createUrlParameters(action);
        break;
      case C.Constants.Action.Simu.ChangeModeToEdit:
        SimuStore.changeModeToEdit(action);
        break;
      case C.Constants.Action.Simu.ChangeModeToReplay:
        SimuStore.changeModeToReplay(action);
        break;
      case C.Constants.Action.Simu.BackToEditMode:
        SimuStore.backToEditMode(action);
        break;
      case C.Constants.Action.Simu.ToggleNextVisible:
        SimuStore.toggleNextVisible(action);
        break;

      default:
        break;
    }

    return true;
  });

  C.SimuStore = SimuStore;
})();

<commit_msg>seedはURL出力しないようにする<commit_after>(function() {
  'use strict';

  var SimuStore = $.extend({
    _initialized: false,
    _context: null,
    _current: null,
    _ghost: null,
    _field: new C.Field(),
    _hold: new C.Hold(),
    _histories: new C.Histories(),
    _nexts: new C.Nexts(),
    _nextsVisibled: new C.NextsVisibled(),
    _description: new C.Description(),
    _nextGenerator: new C.NextGenerator(),
    _steps: new C.Steps(),
    _seed: 0,
    _urlParameters: '',

    initialize: function(action, force) {
      if (this._initialized && !action.context.force) {
        this._context.before = action.context.before;
        return;
      }

      this._initialized = true;
      this._context = action.context
      this._seed = this._context.seed == null ? C.Random.nextInt(1000000) : this._context.seed;
      this._nextsVisibled.deserialize(this._context.nextsVisibled);

      this._init(action.context);
      this.emit(C.Constants.Event.Change);
    },

    _init: function(context) {
      var prevs;

      this._current = null,
      this._ghost = null,
      this._field = new C.Field(),
      this._hold = new C.Hold(),
      this._histories = new C.Histories(),
      this._nexts = new C.Nexts(),
      this._description = new C.Description(),
      this._nextGenerator = new C.NextGenerator(),
      this._steps = new C.Steps(),
      this._currentStep = null;

      C.Random.setSeed(this._seed);

      this._hold.deserialize(context.hold);
      this._field.deserialize(context.field);
      this._nexts.deserialize(context.nexts);

      prevs = C.NextsDeserializer.deserialize(context.prevs);
      this._nexts.setAndComplementTypes(this._nexts.types(), prevs, this._nextGenerator);
      while (this._nexts.nextsLength() < 5) {
        this._nexts.push(this._nextGenerator.next());
      }

      this._forwardCurrent();

      this._histories.push(this._current, this._field, this._nexts, this._hold, this._description);
    },

    context: function() {
      return this._context;
    },

    retry: function(action) {
      if (action.isSuperRetry) {
        this._seed = C.Random.nextInt(1000000);
      }

      this._init(this._context);
      this.emit(C.Constants.Event.Change);
    },

    fieldTypes: function() {
      return this._field.innerTypes();
    },

    holdType: function() {
      return this._hold.type();
    },

    nexts: function() {
      return this._nexts.nextTypes();
    },

    nextsFixed: function() {
      return this._nexts.nextTypesFixed();
    },

    nextsVisibled: function() {
      return this._nextsVisibled.status();
    },

    current: function() {
      return this._current;
    },

    ghost: function() {
      return this._ghost;
    },

    canHold: function() {
      return this._hold.canExchange();
    },

    descriptionData: function() {
      return this._description.data();
    },

    seed: function() {
      return this._seed;
    },

    urlParameters: function() {
      return this._urlParameters;
    },

    _forwardCurrent: function() {
      this._current = C.TetriminoFactory.create(this._nexts.next(), this._field.startPivot());
      if (this._nexts.nextsLength() < 5) {
        this._nexts.push(this._nextGenerator.next());
      }

      this._updateGhost();
    },

    hardDrop: function(action) {
      var clearLineNum
        , prevPivotY = this._current.pivot().y
        , canHardDropFromStart;

      this._current.hardDrop(this._field);
      canHardDropFromStart = this._canHardDropFromStart(this._current);
      this._field.settle(this._current);

      if (prevPivotY !== this._current.pivot().y) {
        // 落下があったのでスピン無しに戻す
        this._description.spinType(C.Constants.SpinType.None);
      }

      // 戻っているかもしれないので、その分を忘れてから次の譜を積む
      this._steps.forgetAfter();
      this._steps.pushTetrimino(this._current, this._description.spinType(), canHardDropFromStart);
      this._steps.forward();

      var clearLineNum = this._field.clearLine()
      this._description.clearLineNum(clearLineNum);

      if (clearLineNum > 0) {
        this._description.ren(this._description.ren() + 1);
      } else {
        this._description.ren(0);
      }
      this._description.perfectCleared(this._field.isPerfectCleared());

      this._forwardCurrent();
      this._hold.release();
      this._histories.push(this._current, this._field, this._nexts, this._hold, this._description);

      this._description.fixData();
      this.emit(C.Constants.Event.Change);
    },

    _canHardDropFromStart: function(current) {
      var testCurrent = current.copy()
        , pivot = testCurrent.pivot()
        , currentPivot = current.pivot()
        , hardDropPivot;

      // 開始Y座標からハードドロップでcurrentの座標に落とせるかどうかを判定する
      pivot.y = this._field.startPivot().y;
      testCurrent.pivot(pivot);
      testCurrent.hardDrop(this._field);
      hardDropPivot = testCurrent.pivot();

      return hardDropPivot.x === currentPivot.x && hardDropPivot.y === currentPivot.y;
    },

    softDrop: function(action) {
      if (!this._field.isGround(this._current)) {
        this._current.move({
          x: 0,
          y: -1
        });

        this._description.spinType(C.Constants.SpinType.None);
      }

      this.emit(C.Constants.Event.Change);
    },

    move: function(action) {
      if (this._current.canMove(this._field, { x: action.sign, y: 0 })) {
        this._current.move({
          x: action.sign,
          y: 0
        });

        this._description.spinType(C.Constants.SpinType.None);
        this._updateGhost();

        this.emit(C.Constants.Event.Change);
      }
    },

    hold: function(action) {
      var current;

      if (!this._hold.canExchange()) {
        return;
      }

      // 戻っているかもしれないので、その分を忘れてから次の譜を積む
      this._steps.forgetAfter();
      this._steps.pushHold(this._current.type());
      this._steps.forward();
      current = this._hold.exchange(this._current.type());
      if (current == C.CellType.None) {
        this._forwardCurrent();
      } else {
        this._current = C.TetriminoFactory.create(current, this._field.startPivot());
      }
      this._histories.push(this._current, this._field, this._nexts, this._hold, this._description);

      this._description.spinType(C.Constants.SpinType.None);
      this._updateGhost();
      this.emit(C.Constants.Event.Change);
    },

    turnLeft: function(action) {
      var specialInfo = {};

      if (this._current.turnLeftIfPossible(this._field, specialInfo)
        || this._current.turnLeftSuperlyIfPossible(this._field, specialInfo)) {

        this._description.spinType(specialInfo.spinType);
        this._updateGhost();
        this.emit(C.Constants.Event.Change);
      }
    },

    turnRight: function(action) {
      var specialInfo = {};

      if (this._current.turnRightIfPossible(this._field, specialInfo)
        || this._current.turnRightSuperlyIfPossible(this._field, specialInfo)) {

        this._description.spinType(specialInfo.spinType);
        this._updateGhost();
        this.emit(C.Constants.Event.Change);
      }
    },

    forward: function(action) {
      var history;

      if (!this._histories.canForward()) {
        return;
      }

      this._histories.forward();
      this._steps.forward();
      history = this._histories.current();

      this._current = C.TetriminoFactory.create(history.current(), this._field.startPivot());
      this._field.deserialize(history.field());
      this._nexts.no(history.nextNo());
      this._hold.deserialize(history.hold());
      this._description.current(history.description());

      this._updateGhost();
      this.emit(C.Constants.Event.Change);
    },

    back: function(action) {
      var history;

      if (!this._histories.canBack()) {
        return;
      }

      this._histories.back();
      this._steps.back();
      history = this._histories.current();

      this._current = C.TetriminoFactory.create(history.current(), this._field.startPivot());
      this._field.deserialize(history.field());
      this._nexts.no(history.nextNo());
      this._hold.deserialize(history.hold());
      this._description.current(history.description());

      this._updateGhost();
      this.emit(C.Constants.Event.Change);
    },

    _updateGhost: function() {
      this._ghost = this._current.copy();
      this._ghost.hardDrop(this._field);
    },

    createUrlParameters: function(action) {
      var context = this._context
        , parameters = []
        , f = context.field
        , ns = this._nexts.serialize()
        , nv = this._nextsVisibled.serialize()
        , ss = this._steps.serialize()
        , h = context.hold;

      if (!!f) {
        parameters.push('f=' + f);
      }

      if (!!ns) {
        parameters.push('ns=' + ns);
      }

      if (!!nv && nv != 'v') {
        parameters.push('nv=' + nv);
      }

      if (!!ss) {
        parameters.push('ss=' + ss);
      }

      if (!!h) {
        parameters.push('h=' + h);
      }

      parameters.push('m=' + C.Constants.Mode.Replay);
      parameters.push('v=' + C.Constants.Version);

      this._urlParameters = parameters.join('&');
      this.emit(C.Constants.Event.SetUrl);
    },

    changeModeToEdit: function(action) {
      var mode = C.Constants.Mode.Edit
        , nexts = new C.Nexts()
        , nextTypes = this.nexts();

      nextTypes.unshift(this._current.type());
      nexts.types(nextTypes);

      var params = {
        before: C.Constants.Mode.Simu,
        field: this._field.serialize(),
        force: true,
        hold: this._hold.serialize(),
        nexts: nexts.serialize(),
        nextsVisibled: this._nextsVisibled.serialize(),
        prevs: '',
      };
      this.emit(C.Constants.Event.ChangeMode, mode, params);
    },

    backToEditMode: function(action) {
      var mode = C.Constants.Mode.Edit
      this.emit(C.Constants.Event.ChangeMode, mode, {
        before: C.Constants.Mode.Simu
      });
    },

    changeModeToReplay: function(action) {
      var mode = C.Constants.Mode.Replay
        , allNextsTypes = this._nexts.types()
        , allNexts = new C.Nexts();

      allNexts.types(allNextsTypes);

      var params = {
        before: C.Constants.Mode.Simu,
        field: this._context.field,
        hold: this._context.hold,
        nexts: allNexts.serialize(),
        nextsVisibled: this._nextsVisibled.serialize(),
        prevs: '',
        steps: this._steps.serialize()
      };
      this.emit(C.Constants.Event.ChangeMode, mode, params);
    },

    clear: function(action) {
      var mode = C.Constants.Mode.Simu
        , params = {
        force: true,
        field: '',
        hold: '',
        nexts: '',
        nextsVisibled: this._nextsVisibled.serialize(),
        prevs: '',
        steps: ''
      };

      this.emit(C.Constants.Event.ChangeMode, mode, params);
    },

    toggleNextVisible: function(action) {
      this._nextsVisibled.toggleVisible(action.index);
      this.emit(C.Constants.Event.Change);
    },

    addChangeListener: function(callback) {
      this.addListener(C.Constants.Event.Change, callback);
    },

    removeChangeListener: function(callback) {
      this.removeListener(C.Constants.Event.Change, callback);
    },

    addSetUrlListener: function(callback) {
      this.addListener(C.Constants.Event.SetUrl, callback);
    },

    removeSetUrlListener: function(callback) {
      this.removeListener(C.Constants.Event.SetUrl, callback);
    },

    addChangeModeListener: function(callback) {
      this.addListener(C.Constants.Event.ChangeMode, callback);
    },

    removeChangeModeListener: function(callback) {
      this.removeListener(C.Constants.Event.ChangeMode, callback);
    },
  }, C.StoreBase);

  C.AppDispatcher.register(function(payload) {
    var action = payload.action;

    switch (action.actionType) {
      case C.Constants.Action.Simu.Initialize:
        SimuStore.initialize(action);
        break;
      case C.Constants.Action.Simu.HardDrop:
        SimuStore.hardDrop(action);
        break;
      case C.Constants.Action.Simu.SoftDrop:
        SimuStore.softDrop(action);
        break;
      case C.Constants.Action.Simu.Move:
        SimuStore.move(action);
        break;
      case C.Constants.Action.Simu.Hold:
        SimuStore.hold(action);
        break;
      case C.Constants.Action.Simu.TurnRight:
        SimuStore.turnRight(action);
        break;
      case C.Constants.Action.Simu.TurnLeft:
        SimuStore.turnLeft(action);
        break;
      case C.Constants.Action.Simu.Retry:
        SimuStore.retry(action);
        break;
      case C.Constants.Action.Simu.Forward:
        SimuStore.forward(action);
        break;
      case C.Constants.Action.Simu.Back:
        SimuStore.back(action);
        break;
      case C.Constants.Action.Simu.Clear:
        SimuStore.clear(action);
        break;
      case C.Constants.Action.Simu.CreateUrlParameters:
        SimuStore.createUrlParameters(action);
        break;
      case C.Constants.Action.Simu.ChangeModeToEdit:
        SimuStore.changeModeToEdit(action);
        break;
      case C.Constants.Action.Simu.ChangeModeToReplay:
        SimuStore.changeModeToReplay(action);
        break;
      case C.Constants.Action.Simu.BackToEditMode:
        SimuStore.backToEditMode(action);
        break;
      case C.Constants.Action.Simu.ToggleNextVisible:
        SimuStore.toggleNextVisible(action);
        break;

      default:
        break;
    }

    return true;
  });

  C.SimuStore = SimuStore;
})();

<|endoftext|>


<commit_before>/**
 * T'SoundSystem for JavaScript
 */

/**
 * MasterChannel prototype
 *
 * This prototype provide main audio generation loop.
 * @author Takashi Toyoshima <toyoshim@gmail.com>
 */
function MasterChannel () {
    this.channels = new Array();
    this.buffers = null;
    this.buffer = null;
    this.bufferLength = 0;
    this.player = null;
    this.intervalLength = 0;
    this.intervalRestLength = 0;
    this.volume = MasterChannel.DEFAULT_VOLUME;
}

MasterChannel.SAMPLE_FREQUENCY = 44100;
MasterChannel.MAX_WAVE_VALUE = 32767;
MasterChannel.MIN_WAVE_VALUE = -32767;
MasterChannel.MSEC_PER_SEC = 1000;
MasterChannel.DEFAULT_VOLUME = 8;

/**
 * Reconstruct slave buffer references.
 */
MasterChannel.prototype.reconstructBuffers = function () {
    var newBuffers = new Array(this.channels.length);
    for (var i = 0; i < this.channels.length; i++) {
        newBuffers[i] = this.channels[i].getBuffer();
    }
    this.buffers = newBuffers;
}

/**
 * Set mixing volume.
 * Every device sets maximum volume of each sound channel
 * as one sixteenth to avoid sound saturation.
 * If you want to maximize sounds set sixteen as volume.
 * It is the default value.
 * @param newVolume volume
 */
MasterChannel.prototype.setVolume = function (newVolume) {
    this.volume = newVolume;
}

/**
 * Add channel to audio play back loop.
 * @param channel channel to add
 * @return result
 */
MasterChannel.prototype.addChannel = function (channel) {
    if (0 != this.bufferLength) {
        this.buffers = null;
        channel.setBufferLength(this.bufferLength);
        this.reconstructBuffers();
    }
    return this.channels.push(channel);
}

/**
 * Remove channel from audio play back loop.
 * @param channel channel to remove
 * @return result
 */
MasterChannel.prototype.removeChannel = function (channel) {
    for (var i = 0; i < this.channels.length; i++) {
        if (channel == this.channels[i]) {
            this.buffers = null;
            this.channels.splice(i, 1);
            this.reconstructBuffers();
            return true;
        }
    }
    return false;
}

/**
 * Remove all channels from audio play back loop.
 */
MasterChannel.prototype.clearChannel = function () {
    this.buffers = null;
    this.channels = new Array();
    this.reconstructBuffers();
}

/**
 * Set player object to control devices periodically.
 * @param newPlayer player to call back
 */
MasterChannel.prototype.setPlayer = function (newPlayer) {
    this.player = newPlayer;
}

/**
 * Set time interval to call back player periodically.
 * @param msec time interval
 */
MasterChannel.prototype.setPlayerInterval = function (msec) {
    this.intervalLength = (MasterChannel.SAMPLE_FREQUENCY * msec) /
            MasterChannel.MSEC_PER_SEC;
    this.intervalRestLength = this.intervalLength;
}

/**
 * Do partial slave channel audio mixing.
 * @param base base offset to generate
 * @param length buffer length to generate
 */
MasterChannel.prototype.generateInternal = function (base, length) {
    var size = this.channels.length;
    for (var i = 0; i < size; i++) {
        this.channels[i].generate(length);
    }
    for (var offset = 0; offset < length; offset++) {
        var value = 0;
        for (var channel = 0; channel < size; channel++) {
            value += this.buffers[channel][offset];
        }
        value *= this.volume;
        if (value > MasterChannel.MAX_WAVE_VALUE) {
            value = MasterChannel.MAX_WAVE_VALUE;
        }
        if (value < MasterChannel.MIN_WAVE_VALUE) {
            value = MasterChannel.MIN_WAVE_VALUE;
        }
        this.buffer[base + offset] = value;
    }
}

/**
 * Set internal buffer length.
 * @param length buffer length or size in shorts
 */
MasterChannel.prototype.setBufferLength = function (length) {
    this.buffers = null;
    this.buffer = new Int32Array(length);
    this.bufferLength = length;
    for (var i = 0; i < this.channels.length; i++) {
        this.channels[i].setBufferLength(length);
    }
    this.reconstructBuffers();
}

/**
 * Get internal buffer.
 * @return audio stream buffer
 */
MasterChannel.prototype.getBuffer = function () {
    return this.buffer;
}

/**
 * Generate audio stream to internal buffer.
 * @param length buffer length or size in shorts to generate audio stream
 */
MasterChannel.prototype.generate = function (length) {
    if (null == this.buffers) {
        return;
    }
    if ((null == this.player) || (0 == this.intervalLength)) {
        this.generateInternal(0, length);
    } else {
        var restLength = length;
        var offset = 0;
        while (restLength > this.intervalRestLength) {
            this.generateInternal(offset, this.intervalRestLength);
            restLength -= this.intervalRestLength;
            offset += this.intervalRestLength;
            this.intervalRestLength = this.intervalLength;
            this.player.updateDevice();
        }
        if (0 != restLength) {
            this.generateInternal(offset, restLength);
            this.intervalRestLength -= restLength;
        }
    }
}
<commit_msg>Fix mal coding style.<commit_after>/**
 * T'SoundSystem for JavaScript
 */

/**
 * MasterChannel prototype
 *
 * This prototype provide main audio generation loop.
 * @author Takashi Toyoshima <toyoshim@gmail.com>
 */
function MasterChannel () {
    this.channels = new Array();
    this.buffers = null;
    this.buffer = null;
    this.bufferLength = 0;
    this.player = null;
    this.intervalLength = 0;
    this.intervalRestLength = 0;
    this.volume = MasterChannel.DEFAULT_VOLUME;
}

MasterChannel.SAMPLE_FREQUENCY = 44100;
MasterChannel.MAX_WAVE_VALUE = 32767;
MasterChannel.MIN_WAVE_VALUE = -32767;
MasterChannel.MSEC_PER_SEC = 1000;
MasterChannel.DEFAULT_VOLUME = 8;

/**
 * Reconstruct slave buffer references.
 */
MasterChannel.prototype.reconstructBuffers = function () {
    var newBuffers = new Array(this.channels.length);
    for (var i = 0; i < this.channels.length; i++) {
        newBuffers[i] = this.channels[i].getBuffer();
    }
    this.buffers = newBuffers;
};

/**
 * Set mixing volume.
 * Every device sets maximum volume of each sound channel
 * as one sixteenth to avoid sound saturation.
 * If you want to maximize sounds set sixteen as volume.
 * It is the default value.
 * @param newVolume volume
 */
MasterChannel.prototype.setVolume = function (newVolume) {
    this.volume = newVolume;
};

/**
 * Add channel to audio play back loop.
 * @param channel channel to add
 * @return result
 */
MasterChannel.prototype.addChannel = function (channel) {
    if (0 != this.bufferLength) {
        this.buffers = null;
        channel.setBufferLength(this.bufferLength);
        this.reconstructBuffers();
    }
    return this.channels.push(channel);
};

/**
 * Remove channel from audio play back loop.
 * @param channel channel to remove
 * @return result
 */
MasterChannel.prototype.removeChannel = function (channel) {
    for (var i = 0; i < this.channels.length; i++) {
        if (channel == this.channels[i]) {
            this.buffers = null;
            this.channels.splice(i, 1);
            this.reconstructBuffers();
            return true;
        }
    }
    return false;
};

/**
 * Remove all channels from audio play back loop.
 */
MasterChannel.prototype.clearChannel = function () {
    this.buffers = null;
    this.channels = new Array();
    this.reconstructBuffers();
};

/**
 * Set player object to control devices periodically.
 * @param newPlayer player to call back
 */
MasterChannel.prototype.setPlayer = function (newPlayer) {
    this.player = newPlayer;
};

/**
 * Set time interval to call back player periodically.
 * @param msec time interval
 */
MasterChannel.prototype.setPlayerInterval = function (msec) {
    this.intervalLength = (MasterChannel.SAMPLE_FREQUENCY * msec) /
            MasterChannel.MSEC_PER_SEC;
    this.intervalRestLength = this.intervalLength;
};

/**
 * Do partial slave channel audio mixing.
 * @param base base offset to generate
 * @param length buffer length to generate
 */
MasterChannel.prototype.generateInternal = function (base, length) {
    var size = this.channels.length;
    for (var i = 0; i < size; i++) {
        this.channels[i].generate(length);
    }
    for (var offset = 0; offset < length; offset++) {
        var value = 0;
        for (var channel = 0; channel < size; channel++) {
            value += this.buffers[channel][offset];
        }
        value *= this.volume;
        if (value > MasterChannel.MAX_WAVE_VALUE) {
            value = MasterChannel.MAX_WAVE_VALUE;
        }
        if (value < MasterChannel.MIN_WAVE_VALUE) {
            value = MasterChannel.MIN_WAVE_VALUE;
        }
        this.buffer[base + offset] = value;
    }
};

/**
 * Set internal buffer length.
 * @param length buffer length or size in shorts
 */
MasterChannel.prototype.setBufferLength = function (length) {
    this.buffers = null;
    this.buffer = new Int32Array(length);
    this.bufferLength = length;
    for (var i = 0; i < this.channels.length; i++) {
        this.channels[i].setBufferLength(length);
    }
    this.reconstructBuffers();
};

/**
 * Get internal buffer.
 * @return audio stream buffer
 */
MasterChannel.prototype.getBuffer = function () {
    return this.buffer;
};

/**
 * Generate audio stream to internal buffer.
 * @param length buffer length or size in shorts to generate audio stream
 */
MasterChannel.prototype.generate = function (length) {
    if (null == this.buffers) {
        return;
    }
    if ((null == this.player) || (0 == this.intervalLength)) {
        this.generateInternal(0, length);
    } else {
        var restLength = length;
        var offset = 0;
        while (restLength > this.intervalRestLength) {
            this.generateInternal(offset, this.intervalRestLength);
            restLength -= this.intervalRestLength;
            offset += this.intervalRestLength;
            this.intervalRestLength = this.intervalLength;
            this.player.updateDevice();
        }
        if (0 != restLength) {
            this.generateInternal(offset, restLength);
            this.intervalRestLength -= restLength;
        }
    }
};
<|endoftext|>


<commit_before>$(document).ready(function () {

  window.addClickListeners = function (app) {
    // map DOM element ID to click handler
    var clickListeners = {
      'mpQuickStartS': app.startRandomGame,
      'mpLeaderBoardS': app.leaderBoard,
      'mpChoosePhotoS': app.photosPage,
      'helpButton': app.helpClicked,
      'puzzleContainer': app.pausePopout,
      'qsPause': app.pausePopout,
      'qsInfo': app.newPopout,
      'qsPopupScoresTableCellEasy': function () {
        app.newPopoutObj.switchDifficulty('1');
      },
      'qsPopupScoresTableCellHard': function () {
        app.newPopoutObj.switchDifficulty('2');
      },
      'qsPopupScoresTableCellBrutal': function () {
        app.newPopoutObj.switchDifficulty('3');
      },
      'qsNpPlayAgain': app.playAgain,
      'qsNpNewPhoto': app.newPhoto,
      'qsNpClose': app.closePopout,
      'qsPpClose': app.closePausePopout,
      'qsPpLeaderBoard': app.leaderBoardPause,
      'qsFpSaveResultS': app.saveResult,
      'qsFpCloseResultS': app.closeFinishNoSave,
      'lbMoves': function () {
        app.leaderBoardPageObj.switchView();
        return false;
      },
      'lbTimes': function () {
        app.leaderBoardPageObj.switchView();
        return false;
      },
      'lbCloseButton': app.closeLeaderBoard,
      'lbPopUpPlayButton': app.startGameLb,
      'lbPopUpCloseButton': app.closeLeaderBoardPagePopup,
      'ppGame': function () {
        app.photosPageObj.switchView();
        return false;
      },
      'ppCloseButton': app.closePhotosPage,
      'ppPopUpPlayButton': function () {
        app.startGame(2);
      },
      'ppPopUpCloseButton': app.closePhotosPagePopup,
      'closeHelpButton': app.closeHelp
    };

    for (var id in clickListeners) {
      $(document).delegate('#' + id, 'click', clickListeners[id]);
    }
  };
});
<commit_msg>Add copyright header to new JS file<commit_after>/*
 * Copyright (c) 2012, Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 */

$(document).ready(function () {

  window.addClickListeners = function (app) {
    // map DOM element ID to click handler
    var clickListeners = {
      'mpQuickStartS': app.startRandomGame,
      'mpLeaderBoardS': app.leaderBoard,
      'mpChoosePhotoS': app.photosPage,
      'helpButton': app.helpClicked,
      'puzzleContainer': app.pausePopout,
      'qsPause': app.pausePopout,
      'qsInfo': app.newPopout,
      'qsPopupScoresTableCellEasy': function () {
        app.newPopoutObj.switchDifficulty('1');
      },
      'qsPopupScoresTableCellHard': function () {
        app.newPopoutObj.switchDifficulty('2');
      },
      'qsPopupScoresTableCellBrutal': function () {
        app.newPopoutObj.switchDifficulty('3');
      },
      'qsNpPlayAgain': app.playAgain,
      'qsNpNewPhoto': app.newPhoto,
      'qsNpClose': app.closePopout,
      'qsPpClose': app.closePausePopout,
      'qsPpLeaderBoard': app.leaderBoardPause,
      'qsFpSaveResultS': app.saveResult,
      'qsFpCloseResultS': app.closeFinishNoSave,
      'lbMoves': function () {
        app.leaderBoardPageObj.switchView();
        return false;
      },
      'lbTimes': function () {
        app.leaderBoardPageObj.switchView();
        return false;
      },
      'lbCloseButton': app.closeLeaderBoard,
      'lbPopUpPlayButton': app.startGameLb,
      'lbPopUpCloseButton': app.closeLeaderBoardPagePopup,
      'ppGame': function () {
        app.photosPageObj.switchView();
        return false;
      },
      'ppCloseButton': app.closePhotosPage,
      'ppPopUpPlayButton': function () {
        app.startGame(2);
      },
      'ppPopUpCloseButton': app.closePhotosPagePopup,
      'closeHelpButton': app.closeHelp
    };

    for (var id in clickListeners) {
      $(document).delegate('#' + id, 'click', clickListeners[id]);
    }
  };
});
<|endoftext|>


<commit_before>/*global jsonpfu */

/**
 * Name: Plixi
 * Desc: Used to query the Plixi JSONP API (http://groups.google.com/group/plixi/web)
 * Usage:
 *	jfu.lib('plixi').api_category.api_method(opts, callback);
 *
 * Example:
 *	jfu.lib('plixi').user.show({user: 'meltingice'}, function (data) {
 *		console.log(data);
 *	});
 */

jsonpfu.extend('typepad', function (opts, script) {
	// API helper methods for validation and querying
	var API = {
		query: function (url, data, callback) {
			var	query_url,
				route = /:([A-Za-z_]+)/gi,
				matches, i;

			// Check for routing
			if (route.test(url)) {
				matches = url.match(route);
				if (matches.length > 0) {
					for (i = 0; i < matches.length; i++) {
						if (data[matches[i].substr(1)]) {
							url = url.replace(matches[i], data[matches[i].substr(1)]);
							delete data[matches[i].substr(1)];
						}
					}
				}
			}

			/*
			 * This is a bit of a crude way to check to see if all arguments are
			 * present but it works. Instead of throwing an error, we just silently
			 * return because some methods have multiple different routes.
			 */
			if (route.test(url)) {
				return;
			}

			query_url = 'http://api.typepad.com/' + url + '.js';

			script.jsonp_query({
				url: query_url,
				data: data,
				success: function (data) {
					callback(data);
				}
			});

			return true;
		}
	};

	return {
		api_keys: {
			show: function (args, callback) {
				API.query('api-keys/:id', args, callback);
			}
		},

		applications: {
			show: function (args, callback) {
				API.query('applications/:id', args, callback);
			},

			badges: {
				show: function (args, callback) {
					API.query('applications/:id/badges', args, callback);
				},

				learning: function (args, callback) {
					API.query('applications/:id/badges/@learning', args, callback);
				},

				public: function (args, callback) {
					API.query('applications/:id/badges/@public', args, callback);
				}
			},

			external_feed_subscriptions: function (args, callback) {
				API.query('applications/:id/external-feed-subscriptions', args, callback);
			},

			groups: function (args, callback) {
				API.query('applications/:id/groups', args, callback);
			}
		},

		assets: {
			search: function (args, callback) {
				API.query('assets', args, callback);
			},

			show: function (args, callback) {
				API.query('assets/:id', args, callback);
			},

			categories: function (args, callback) {
				API.query('assets/:id/categories', args, callback);
			},

			comment_tree: function (args, callback) {
				API.query('assets/:id/comment-tree', args, callback);
			},

			comments: function (args, callback) {
				API.query('assets/:id/comments', args, callback);
			},

			extended_content: function (args, callback) {
				API.query('assets/:id/extended-content', args, callback);
			},

			favorites: function (args, callback) {
				API.query('assets/:id/favorites', args, callback);
			},

			feedback_status: function (args, callback) {
				API.query('assets/:id/feedback-status', args, callback);
			},

			media: function (args, callback) {
				API.query('assets/:id/media-assets', args, callback);
			},

			publication_status: function (args, callback) {
				API.query('assets/:id/publication-status', args, callback);
			},

			reblogs: function (args, callback) {
				API.query('assets/:id/reblogs', args, callback);
			},

			trending: function (args, callback) {
				API.query('assets/trending', args, callback);
			}
		},

		auth_tokens: {
			show: function (args, callback) {
				API.query('auth-tokens/:id', args, callback);
			}
		},

		badges: {
			show: function (args, callback) {
				API.query('badges/:id', args, callback);
			}
		},

		blogs: {
			show: function (args, callback) {
				API.query('blogs/:id', args, callback);
			},

			categories: function (args, callback) {
				API.query('blogs/:id/categories', args, callback);
			},

			commenting_settings: function (args, callback) {
				API.query('blogs/:id/commenting-settings', args, callback);
			},

			comments: {
				published: function (args, callback) {
					API.query('blogs/:id/comments/@published', args, callback);
				},

				recent: function (args, callback) {
					API.query('blogs/:id/comments/@published/@recent', args, callback);
				}
			},

			crosspost_accounts: function (args, callback) {
				API.query('blogs/:id/crosspost-accounts', args, callback);
			},

			page_assets: function (args, callback) {
				API.query('blogs/:id/page-assets', args, callback);
			},

			post_assets: {
				show: function (args, callback) {
					API.query('blogs/:id/post-assets', args, callback);
				},

				by_category: function (args, callback) {
					API.query('blogs/:id/post-assets/@by-category/:category', args, callback);
				},

				by_filename: function (args, callback) {
					API.query('blogs/:id/post-assets/@by-filename/:filename', args, callback);
				},

				by_month: function (args, callback) {
					API.query('blogs/:id/post-assets/@by-month/:month', args, callback);
				},

				published: {
					by_category: function (args, callback) {
						API.query('/blogs/:id/post-assets/@published/@by-category/:category', args, callback);
					},

					by_month: function (args, callback) {
						API.query('blogs/:id/post-assets/@published/@by-month/:month', args, callback);
					},

					recent: function (args, callback) {
						API.query('blogs/:id/post-assets/@published/@recent', args, callback);
					}
				},

				recent: function (args, callback) {
					API.query('blogs/:id/post-assets/@recent', args, callback);
				}
			},

			post_by_email_settings: function (args, callback) {
				API.query('blogs/:id/post-by-email-settings/@by-user/:user', args, callback);
			},

			stats: function (args, callback) {
				API.query('blogs/:id/stats', args, callback);
			}
		},

		client_library_helpers: {
			method_mappings: function (args, callback) {
				API.query('client-library-helpers/method-mappings', args, callback);
			},

			object_types: function (args, callback) {
				API.query('client-library-helpers/object-types', args, callback);
			}
		},

		conversations: {
			list: function (args, callback) {
				API.query('conversations', args, callback);
			},

			show: function (args, callback) {
				API.query('conversations/:id', args, callback);
			}
		},

		domains: {
			show: function (args, callback) {
				API.query('domains/:id', args, callback);
			}
		},

		events: {
			show: function (args, callback) {
				API.query('events/:id', args, callback);
			}
		},

		external_feed_subscriptions: {
			show: function (args, callback) {
				API.query('external-feed-subscriptions/:id', args, callback);
			},

			feeds: function (args, callback) {
				API.query('external-feed-subscriptions/:id/feeds', args, callback);
			}
		},

		favorites: {
			show: function (args, callback) {
				API.query('favorites/:id', args, callback);
			}
		},

		groups: {
			show: function (args, callback) {
				API.query('groups/:id', args, callback);
			},

			audio_assets: function (args, callback) {
				API.query('groups/:id/audio-assets', args, callback);
			},

			events: function (args, callback) {
				API.query('groups/:id/events', args, callback);
			},

			extenal_feed_subscriptions: function (args, callback) {
				API.query('groups/:id/external-feed-subscriptions', args, callback);
			},

			link_assets: function (args, callback) {
				API.query('groups/:id/link-assets', args, callback);
			},

			memberships: {
				list: function (args, callback) {
					API.query('groups/:id/memberships', args, callback);
				},

				admin: function (args, callback) {
					API.query('groups/:id/memberships/@admin', args, callback);
				},

				blocked: function (args, callback) {
					API.query('groups/:id/memberships/@blocked', args, callback);
				},

				member: function (args, callback) {
					API.query('groups/:id/memberships/@member', args, callback);
				}
			},

			photo_assets: function (args, callback) {
				API.query('groups/:id/photo-assets', args, callback);
			},

			post_assets: function (args, callback) {
				API.query('groups/:id/post-assets', args, callback);
			},

			video_assets: function (args, callback) {
				API.query('groups/:id/video-assets', args, callback);
			}
		},

		import_jobs: {
			show: function (args, callback) {
				API.query('import-jobs/:id', args, callback);
			}
		},

		relationships: {
			show: function (args, callback) {
				API.query('relationships/:id', args, callback);
			},

			status: function (args, callback) {
				API.query('relationships/:id/status', args, callback);
			}
		},

		request_properties: function (args, callback) {
			API.query('request-properties', args, callback);
		},

		users: {
			show: function (args, callback) {
				API.query('users/:id', args, callback);
			},

			badges: {
				list: function (args, callback) {
					API.query('users/:id/badges', args, callback);
				},

				learning: function (args, callback) {
					API.query('users/:id/badges/@learning', args, callback);
				},

				public: function (args, callback) {
					API.query('users/:id/badges/@public', args, callback);
				}
			},

			blogs: function (args, callback) {
				API.query('user/:id/blogs', args, callback);
			},

			elsewhere_accounts: function (args, callback) {
				API.query('users/:id/elsewhere-accounts', args, callback);
			},

			events: {
				list: function (args, callback) {
					API.query('users/:id/events', args, callback);
				},

				by_group: function (args, callback) {
					API.query('users/:id/events/@by-group/:group', args, callback);
				}
			},

			favorites: function (args, callback) {
				API.query('users/:id/favorites', args, callback);
			},

			memberships: {
				list: function (args, callback) {
					API.query('users/:id/memberships', args, callback);
				},

				admin: function (args, callback) {
					API.query('users/:id/memberships/@admin', args, callback);
				},

				by_group: function (args, callback) {
					API.query('users/:id/memberships/@by-group/:group', args, callback);
				},

				member: function (args, callback) {
					API.query('users/:id/memberships/@member', args, callback);
				}
			},

			notifications: {
				list: function (args, callback) {
					API.query('users/:id/notifications', args, callback);
				},

				by_group: function (args, callback) {
					API.query('users/:id/notifications/@by-group/:group', args, callback);
				}
			},

			profile: function (args, callback) {
				API.query('users/:id/profile', args, callback);
			},

			relationships: {
				list: function (args, callback) {
					API.query('users/:id/relationships', args, callback);
				},

				by_group: function (args, callback) {
					API.query('users/:id/relationships/@by-group/:group', args, callback);
				},

				by_user: function (args, callback) {
					API.query('users/:id/relationships/@by-user/:user', args, callback);
				},

				follower: {
					list: function (args, callback) {
						API.query('/users/:id/relationships/@follower', args, callback);
					},

					by_group: function (args, callback) {
						API.query('users/:id/relationships/@follower/@by-group/:group', args, callback);
					}
				},

				following: {
					list: function (args, callback) {
						API.query('users/:id/relationships/@following', args, callback);
					},

					by_group: function (args, callback) {
						API.query('users/:id/relationships/@following/@by-group/:group', args, callback);
					}
				}
			}
		},

		verticals: {
			list: function (args, callback) {
				API.query('verticals', args, callback);
			},

			show: function (args, callback) {
				API.query('verticals/:id', args, callback);
			},

			tags: function (args, callback) {
				API.query('verticals/:id/tags', args, callback);
			}
		}
	};

});<commit_msg>Updated documentation for TypePad API<commit_after>/*global jsonpfu */

/**
 * Name: TypePad
 * Desc: Used to query the TypePad JSONP API (http://www.typepad.com/services/apidocs)
 * Usage:
 *	jfu.lib('typepad').api_category.api_method(opts, callback);
 *
 * Example:
 *	jfu.lib('typepad').api_keys.show({id:'3d20424ed60e58e1'}, function (data) {
 *		console.log(data);
 *	});
 */

jsonpfu.extend('typepad', function (opts, script) {
	// API helper methods for validation and querying
	var API = {
		query: function (url, data, callback) {
			var	query_url,
				route = /:([A-Za-z_]+)/gi,
				matches, i;

			// Check for routing
			if (route.test(url)) {
				matches = url.match(route);
				if (matches.length > 0) {
					for (i = 0; i < matches.length; i++) {
						if (data[matches[i].substr(1)]) {
							url = url.replace(matches[i], data[matches[i].substr(1)]);
							delete data[matches[i].substr(1)];
						}
					}
				}
			}

			/*
			 * This is a bit of a crude way to check to see if all arguments are
			 * present but it works. Instead of throwing an error, we just silently
			 * return because some methods have multiple different routes.
			 */
			if (route.test(url)) {
				return;
			}

			query_url = 'http://api.typepad.com/' + url + '.js';

			script.jsonp_query({
				url: query_url,
				data: data,
				success: function (data) {
					callback(data);
				}
			});

			return true;
		}
	};

	return {
		api_keys: {
			show: function (args, callback) {
				API.query('api-keys/:id', args, callback);
			}
		},

		applications: {
			show: function (args, callback) {
				API.query('applications/:id', args, callback);
			},

			badges: {
				show: function (args, callback) {
					API.query('applications/:id/badges', args, callback);
				},

				learning: function (args, callback) {
					API.query('applications/:id/badges/@learning', args, callback);
				},

				public: function (args, callback) {
					API.query('applications/:id/badges/@public', args, callback);
				}
			},

			external_feed_subscriptions: function (args, callback) {
				API.query('applications/:id/external-feed-subscriptions', args, callback);
			},

			groups: function (args, callback) {
				API.query('applications/:id/groups', args, callback);
			}
		},

		assets: {
			search: function (args, callback) {
				API.query('assets', args, callback);
			},

			show: function (args, callback) {
				API.query('assets/:id', args, callback);
			},

			categories: function (args, callback) {
				API.query('assets/:id/categories', args, callback);
			},

			comment_tree: function (args, callback) {
				API.query('assets/:id/comment-tree', args, callback);
			},

			comments: function (args, callback) {
				API.query('assets/:id/comments', args, callback);
			},

			extended_content: function (args, callback) {
				API.query('assets/:id/extended-content', args, callback);
			},

			favorites: function (args, callback) {
				API.query('assets/:id/favorites', args, callback);
			},

			feedback_status: function (args, callback) {
				API.query('assets/:id/feedback-status', args, callback);
			},

			media: function (args, callback) {
				API.query('assets/:id/media-assets', args, callback);
			},

			publication_status: function (args, callback) {
				API.query('assets/:id/publication-status', args, callback);
			},

			reblogs: function (args, callback) {
				API.query('assets/:id/reblogs', args, callback);
			},

			trending: function (args, callback) {
				API.query('assets/trending', args, callback);
			}
		},

		auth_tokens: {
			show: function (args, callback) {
				API.query('auth-tokens/:id', args, callback);
			}
		},

		badges: {
			show: function (args, callback) {
				API.query('badges/:id', args, callback);
			}
		},

		blogs: {
			show: function (args, callback) {
				API.query('blogs/:id', args, callback);
			},

			categories: function (args, callback) {
				API.query('blogs/:id/categories', args, callback);
			},

			commenting_settings: function (args, callback) {
				API.query('blogs/:id/commenting-settings', args, callback);
			},

			comments: {
				published: function (args, callback) {
					API.query('blogs/:id/comments/@published', args, callback);
				},

				recent: function (args, callback) {
					API.query('blogs/:id/comments/@published/@recent', args, callback);
				}
			},

			crosspost_accounts: function (args, callback) {
				API.query('blogs/:id/crosspost-accounts', args, callback);
			},

			page_assets: function (args, callback) {
				API.query('blogs/:id/page-assets', args, callback);
			},

			post_assets: {
				show: function (args, callback) {
					API.query('blogs/:id/post-assets', args, callback);
				},

				by_category: function (args, callback) {
					API.query('blogs/:id/post-assets/@by-category/:category', args, callback);
				},

				by_filename: function (args, callback) {
					API.query('blogs/:id/post-assets/@by-filename/:filename', args, callback);
				},

				by_month: function (args, callback) {
					API.query('blogs/:id/post-assets/@by-month/:month', args, callback);
				},

				published: {
					by_category: function (args, callback) {
						API.query('/blogs/:id/post-assets/@published/@by-category/:category', args, callback);
					},

					by_month: function (args, callback) {
						API.query('blogs/:id/post-assets/@published/@by-month/:month', args, callback);
					},

					recent: function (args, callback) {
						API.query('blogs/:id/post-assets/@published/@recent', args, callback);
					}
				},

				recent: function (args, callback) {
					API.query('blogs/:id/post-assets/@recent', args, callback);
				}
			},

			post_by_email_settings: function (args, callback) {
				API.query('blogs/:id/post-by-email-settings/@by-user/:user', args, callback);
			},

			stats: function (args, callback) {
				API.query('blogs/:id/stats', args, callback);
			}
		},

		client_library_helpers: {
			method_mappings: function (args, callback) {
				API.query('client-library-helpers/method-mappings', args, callback);
			},

			object_types: function (args, callback) {
				API.query('client-library-helpers/object-types', args, callback);
			}
		},

		conversations: {
			list: function (args, callback) {
				API.query('conversations', args, callback);
			},

			show: function (args, callback) {
				API.query('conversations/:id', args, callback);
			}
		},

		domains: {
			show: function (args, callback) {
				API.query('domains/:id', args, callback);
			}
		},

		events: {
			show: function (args, callback) {
				API.query('events/:id', args, callback);
			}
		},

		external_feed_subscriptions: {
			show: function (args, callback) {
				API.query('external-feed-subscriptions/:id', args, callback);
			},

			feeds: function (args, callback) {
				API.query('external-feed-subscriptions/:id/feeds', args, callback);
			}
		},

		favorites: {
			show: function (args, callback) {
				API.query('favorites/:id', args, callback);
			}
		},

		groups: {
			show: function (args, callback) {
				API.query('groups/:id', args, callback);
			},

			audio_assets: function (args, callback) {
				API.query('groups/:id/audio-assets', args, callback);
			},

			events: function (args, callback) {
				API.query('groups/:id/events', args, callback);
			},

			extenal_feed_subscriptions: function (args, callback) {
				API.query('groups/:id/external-feed-subscriptions', args, callback);
			},

			link_assets: function (args, callback) {
				API.query('groups/:id/link-assets', args, callback);
			},

			memberships: {
				list: function (args, callback) {
					API.query('groups/:id/memberships', args, callback);
				},

				admin: function (args, callback) {
					API.query('groups/:id/memberships/@admin', args, callback);
				},

				blocked: function (args, callback) {
					API.query('groups/:id/memberships/@blocked', args, callback);
				},

				member: function (args, callback) {
					API.query('groups/:id/memberships/@member', args, callback);
				}
			},

			photo_assets: function (args, callback) {
				API.query('groups/:id/photo-assets', args, callback);
			},

			post_assets: function (args, callback) {
				API.query('groups/:id/post-assets', args, callback);
			},

			video_assets: function (args, callback) {
				API.query('groups/:id/video-assets', args, callback);
			}
		},

		import_jobs: {
			show: function (args, callback) {
				API.query('import-jobs/:id', args, callback);
			}
		},

		relationships: {
			show: function (args, callback) {
				API.query('relationships/:id', args, callback);
			},

			status: function (args, callback) {
				API.query('relationships/:id/status', args, callback);
			}
		},

		request_properties: function (args, callback) {
			API.query('request-properties', args, callback);
		},

		users: {
			show: function (args, callback) {
				API.query('users/:id', args, callback);
			},

			badges: {
				list: function (args, callback) {
					API.query('users/:id/badges', args, callback);
				},

				learning: function (args, callback) {
					API.query('users/:id/badges/@learning', args, callback);
				},

				public: function (args, callback) {
					API.query('users/:id/badges/@public', args, callback);
				}
			},

			blogs: function (args, callback) {
				API.query('user/:id/blogs', args, callback);
			},

			elsewhere_accounts: function (args, callback) {
				API.query('users/:id/elsewhere-accounts', args, callback);
			},

			events: {
				list: function (args, callback) {
					API.query('users/:id/events', args, callback);
				},

				by_group: function (args, callback) {
					API.query('users/:id/events/@by-group/:group', args, callback);
				}
			},

			favorites: function (args, callback) {
				API.query('users/:id/favorites', args, callback);
			},

			memberships: {
				list: function (args, callback) {
					API.query('users/:id/memberships', args, callback);
				},

				admin: function (args, callback) {
					API.query('users/:id/memberships/@admin', args, callback);
				},

				by_group: function (args, callback) {
					API.query('users/:id/memberships/@by-group/:group', args, callback);
				},

				member: function (args, callback) {
					API.query('users/:id/memberships/@member', args, callback);
				}
			},

			notifications: {
				list: function (args, callback) {
					API.query('users/:id/notifications', args, callback);
				},

				by_group: function (args, callback) {
					API.query('users/:id/notifications/@by-group/:group', args, callback);
				}
			},

			profile: function (args, callback) {
				API.query('users/:id/profile', args, callback);
			},

			relationships: {
				list: function (args, callback) {
					API.query('users/:id/relationships', args, callback);
				},

				by_group: function (args, callback) {
					API.query('users/:id/relationships/@by-group/:group', args, callback);
				},

				by_user: function (args, callback) {
					API.query('users/:id/relationships/@by-user/:user', args, callback);
				},

				follower: {
					list: function (args, callback) {
						API.query('/users/:id/relationships/@follower', args, callback);
					},

					by_group: function (args, callback) {
						API.query('users/:id/relationships/@follower/@by-group/:group', args, callback);
					}
				},

				following: {
					list: function (args, callback) {
						API.query('users/:id/relationships/@following', args, callback);
					},

					by_group: function (args, callback) {
						API.query('users/:id/relationships/@following/@by-group/:group', args, callback);
					}
				}
			}
		},

		verticals: {
			list: function (args, callback) {
				API.query('verticals', args, callback);
			},

			show: function (args, callback) {
				API.query('verticals/:id', args, callback);
			},

			tags: function (args, callback) {
				API.query('verticals/:id/tags', args, callback);
			}
		}
	};

});<|endoftext|>


<commit_before>var Promise = require('bluebird');
var http = require('superagent');
var qs = require('qs');
var _ = require('lodash');
var RiftError = require('./rift_error');
var ValidationError = require('./validation_error');

module.exports = function() {
  // core definition.
  // protect the 'config' property via a getter method
  var api = Object.create({}, {
    config: {
      get: function() {
        return setConfig;
      },
      enumerable: false,
      configurable: false
    }
  });

  /*
   *  accessor for config values
   */
  var config = {
    'defaults': {
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest'
    },
    before: [],
    after: []
  };
  var setConfig = {
    set: function(key, value) {
      // ensure that 'before' and 'after' are arrays of functions
      if (key === 'before' || key === 'after') {
        value = _.chain([value]).flatten().filter(_.isFunction).value();
      }
      config[key] = value;
    },
    get: function(key) {
      return config[key];
    },
    define: function(definition) {
      setDefinition(api, definition);
    },
    delegate: function(delegate) {
      setDelegate(api, delegate);
    },
    middleware: function(app) {
      createRoutes(api, app);
    }
  };
  Object.freeze(setConfig);

  /*
   *  createRoutes(endpoints, app)
   */
  var createRoutes = function(endpoints, app) {
    var endpoint;
    for (var key in endpoints) {
      if (!endpoints.hasOwnProperty(key)) { continue; }
      endpoint = endpoints[key];
      if (endpoint.config && endpoint.config.url && endpoint.config.method) {
        app[endpoint.config.method].call(app, (config['base'] || '') + endpoint.config.url, (function(endpoint) {
          return createRoute(endpoint);
        })(endpoint));
      } else {
        createRoutes(endpoint, app);
      }
    }
  };

  var createRoute = function(endpoint) {
    return function(req, res, next) {
      var params = _.extend({}, req.query, req.body, req.params);
      endpoint(params, req)
      .then(function(response) {
        if (!req.xhr) {
          return res.redirect(endpoint.redirectUrl || '/');
        }
        return res.json(response);
      }).catch(function(err) {
        next(err);
      });
    };
  };

  var setDelegate = function(endpoints, delegate) {
    var endpoint, config;
    for (var key in delegate) {
      if (!delegate.hasOwnProperty(key) || !endpoints.hasOwnProperty(key)) { continue; }
      endpoint = delegate[key];
      if (typeof endpoint === 'function') {
        endpoint.config = endpoints[key] ? endpoints[key].config : {};
        endpoints[key] = endpoint;
      } else {
        setDelegate(endpoints[key], endpoint);
      }
    }
  };

  /*
   *  setDefinition(endpoints, definition)
   */
  var setDefinition = function(endpoints, definition) {
    var endpoint;
    for (var key in definition) {
      if (!definition.hasOwnProperty(key) || key === 'config') { continue; }
      endpoint = definition[key];

      if (!endpoint.url) {
        endpoints[key] = {};
        setDefinition(endpoints[key], endpoint);
      } else {
        endpoints[key] = (function(definition) {
          var delegate = exec.bind(api, definition);
          delegate.config = definition;
          delegate.config.method = (delegate.config.method || 'get').toLowerCase().trim();
          if (delegate.config.before) {
            delegate.config.before = _.isArray(delegate.config.before) ? delegate.config.before : [delegate.config.before];
          } else {
            delegate.config.before = [];
          }
          if (delegate.config.after) {
            delegate.config.after = _.isArray(delegate.config.after) ? delegate.config.after : [delegate.config.after];
          } else {
            delegate.config.after = [];
          }
          if (delegate.config.catch) {
            delegate.config.catch = _.isArray(delegate.config.catch) ? delegate.config.catch : [delegate.config.catch];
          } else {
            delegate.config.catch = [];
          }
          return delegate;
        })(definition[key]);
      }
    }
  };

  /*
   *  urlify(url, params)
   *    @param url: string url optionally containing regex matchers
   *    @param params: object literal representing params
   *    @returns string url with matchers replaced by value of params
   *
   *    example:
   *    /user/:userId/post/:postId {userId:1, postId: 2}
   *    => /user/1/post/2
   */
  var urlify = function(url, params) {
    var valid = true;
    var urlified = url.replace(/:(\/?)(\w+)(\??)/g, function(_, slash, param, optional) {
      var value;
      if (!(param in params)) {
        if (optional) {
          return slash;
        }
        valid = false;
        return slash + param;
      }
      value = params[param];
      delete params[param];
      return slash + encodeURIComponent(value);
    });
    return valid ? urlified : null;
  };

  /*
   *  exec(endpoint, params, ctx)
   *    @returns: Promise that will resolve/reject based on xhr status
   */
  var exec = function(endpoint, params, ctx) {
    return new Promise(function(resolve, reject) {
      var rejectValue, resolveValue, ix;
      ctx = _.extend(ctx || {}, {
        reject: function(value) {
          rejectValue = value;
        },
        resolve: function(value) {
          resolveValue = value;
        },
        headers: config.defaults || {},
        ctx: ctx || {},
        params: params,
        url: urlify((config['base'] || '') + endpoint.url, params),
        method: endpoint.method
      });

      // optional 'before' filters
      for (ix = 0; ix < config.before.length; ix++) {
        config.before[ix](ctx);
        if (typeof rejectValue !== 'undefined') {
          return reject(rejectValue);
        }
        if (typeof resolveValue !== 'undefined') {
          return resolve(resolveValue);
        }
      }

      if (!ctx.url || !ctx.method) {
        return reject(new RiftError('No url/method'));
      }

      xhr = http[ctx.method](ctx.url);
      xhr.set(ctx.headers);
      if (config['csrf']) {
        xhr.set('X-CSRF-Token', config['csrf']);
      }

      if (ctx.method === 'post' || ctx.method === 'put') {
        xhr.send(ctx.params);
      } else {
        xhr.query(qs.stringify(ctx.params));
      }
      xhr.end(function(err, response) {
        var ix;

        if (err) {
          ctx.error = err;
        } else if (!response.ok || response.error) {
          ctx.error = new RiftError('not ok/has error', {
            error: response.error || {},
            clientError: response.clientError,
            serverError: response.serverError,
            accepted: response.accepted,
            noContent: response.noContent,
            unauthorized: response.unauthorized,
            notAcceptable: response.notAcceptable,
            forbidden: response.forbidden,
            notFound: response.notFound,
            status: response.status,
            statusCode: response.statusCode,
            domain: response.req.domain,
            method: response.req.method,
            path: response.req.path,
            text: response.text
          });
        } else {
          ctx.body = response.body;
        }

        // optional 'after' filters
        for (ix = 0; ix < config.after.length; ix++) {
          config.after[ix](ctx);
          if (typeof rejectValue !== 'undefined') {
            return reject(rejectValue);
          }
          if (typeof resolveValue !== 'undefined') {
            return resolve(resolveValue);
          }
        }
        if (ctx.error) {
          return reject(ctx.error);
        }
        resolve(ctx.body);
      });
    });
  };

  return api;
};
<commit_msg>allow setting host variable via config/filter<commit_after>var Promise = require('bluebird');
var http = require('superagent');
var qs = require('qs');
var _ = require('lodash');
var RiftError = require('./rift_error');
var ValidationError = require('./validation_error');

module.exports = function() {
  // core definition.
  // protect the 'config' property via a getter method
  var api = Object.create({}, {
    config: {
      get: function() {
        return setConfig;
      },
      enumerable: false,
      configurable: false
    }
  });

  /*
   *  accessor for config values
   */
  var config = {
    'defaults': {
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest'
    },
    before: [],
    after: []
  };
  var setConfig = {
    set: function(key, value) {
      // ensure that 'before' and 'after' are arrays of functions
      if (key === 'before' || key === 'after') {
        value = _.chain([value]).flatten().filter(_.isFunction).value();
      }
      config[key] = value;
    },
    get: function(key) {
      return config[key];
    },
    define: function(definition) {
      setDefinition(api, definition);
    },
    delegate: function(delegate) {
      setDelegate(api, delegate);
    },
    middleware: function(app) {
      createRoutes(api, app);
    }
  };
  Object.freeze(setConfig);

  /*
   *  createRoutes(endpoints, app)
   */
  var createRoutes = function(endpoints, app) {
    var endpoint;
    for (var key in endpoints) {
      if (!endpoints.hasOwnProperty(key)) { continue; }
      endpoint = endpoints[key];
      if (endpoint.config && endpoint.config.url && endpoint.config.method) {
        app[endpoint.config.method].call(app, (config['base'] || '') + endpoint.config.url, (function(endpoint) {
          return createRoute(endpoint);
        })(endpoint));
      } else {
        createRoutes(endpoint, app);
      }
    }
  };

  var createRoute = function(endpoint) {
    return function(req, res, next) {
      var params = _.extend({}, req.query, req.body, req.params);
      endpoint(params, req)
      .then(function(response) {
        if (!req.xhr) {
          return res.redirect(endpoint.redirectUrl || '/');
        }
        return res.json(response);
      }).catch(function(err) {
        next(err);
      });
    };
  };

  var setDelegate = function(endpoints, delegate) {
    var endpoint, config;
    for (var key in delegate) {
      if (!delegate.hasOwnProperty(key) || !endpoints.hasOwnProperty(key)) { continue; }
      endpoint = delegate[key];
      if (typeof endpoint === 'function') {
        endpoint.config = endpoints[key] ? endpoints[key].config : {};
        endpoints[key] = endpoint;
      } else {
        setDelegate(endpoints[key], endpoint);
      }
    }
  };

  /*
   *  setDefinition(endpoints, definition)
   */
  var setDefinition = function(endpoints, definition) {
    var endpoint;
    for (var key in definition) {
      if (!definition.hasOwnProperty(key) || key === 'config') { continue; }
      endpoint = definition[key];

      if (!endpoint.url) {
        endpoints[key] = {};
        setDefinition(endpoints[key], endpoint);
      } else {
        endpoints[key] = (function(definition) {
          var delegate = exec.bind(api, definition);
          delegate.config = definition;
          delegate.config.method = (delegate.config.method || 'get').toLowerCase().trim();
          if (delegate.config.before) {
            delegate.config.before = _.isArray(delegate.config.before) ? delegate.config.before : [delegate.config.before];
          } else {
            delegate.config.before = [];
          }
          if (delegate.config.after) {
            delegate.config.after = _.isArray(delegate.config.after) ? delegate.config.after : [delegate.config.after];
          } else {
            delegate.config.after = [];
          }
          if (delegate.config.catch) {
            delegate.config.catch = _.isArray(delegate.config.catch) ? delegate.config.catch : [delegate.config.catch];
          } else {
            delegate.config.catch = [];
          }
          return delegate;
        })(definition[key]);
      }
    }
  };

  /*
   *  urlify(url, params)
   *    @param url: string url optionally containing regex matchers
   *    @param params: object literal representing params
   *    @returns string url with matchers replaced by value of params
   *
   *    example:
   *    /user/:userId/post/:postId {userId:1, postId: 2}
   *    => /user/1/post/2
   */
  var urlify = function(url, params) {
    var valid = true;
    var urlified = url.replace(/:(\/?)(\w+)(\??)/g, function(_, slash, param, optional) {
      var value;
      if (!(param in params)) {
        if (optional) {
          return slash;
        }
        valid = false;
        return slash + param;
      }
      value = params[param];
      delete params[param];
      return slash + encodeURIComponent(value);
    });
    return valid ? urlified : null;
  };

  /*
   *  exec(endpoint, params, ctx)
   *    @returns: Promise that will resolve/reject based on xhr status
   */
  var exec = function(endpoint, params, ctx) {
    return new Promise(function(resolve, reject) {
      var rejectValue, resolveValue, ix;
      ctx = _.extend(ctx || {}, {
        reject: function(value) {
          rejectValue = value;
        },
        resolve: function(value) {
          resolveValue = value;
        },
        headers: config.defaults || {},
        ctx: ctx || {},
        params: params,
        host: config.host || '',
        url: urlify((config['base'] || '') + endpoint.url, params),
        method: endpoint.method
      });

      // optional 'before' filters
      for (ix = 0; ix < config.before.length; ix++) {
        config.before[ix](ctx);
        if (typeof rejectValue !== 'undefined') {
          return reject(rejectValue);
        }
        if (typeof resolveValue !== 'undefined') {
          return resolve(resolveValue);
        }
      }

      if (!ctx.url || !ctx.method) {
        return reject(new RiftError('No url/method'));
      }

      xhr = http[ctx.method](ctx.host + ctx.url);
      xhr.set(ctx.headers);
      if (config['csrf']) {
        xhr.set('X-CSRF-Token', config['csrf']);
      }

      if (ctx.method === 'post' || ctx.method === 'put') {
        xhr.send(ctx.params);
      } else {
        xhr.query(qs.stringify(ctx.params));
      }
      xhr.end(function(err, response) {
        var ix;

        if (err) {
          ctx.error = err;
        } else if (!response.ok || response.error) {
          ctx.error = new RiftError('not ok/has error', {
            error: response.error || {},
            clientError: response.clientError,
            serverError: response.serverError,
            accepted: response.accepted,
            noContent: response.noContent,
            unauthorized: response.unauthorized,
            notAcceptable: response.notAcceptable,
            forbidden: response.forbidden,
            notFound: response.notFound,
            status: response.status,
            statusCode: response.statusCode,
            domain: response.req.domain,
            method: response.req.method,
            path: response.req.path,
            text: response.text
          });
        } else {
          ctx.body = response.body;
        }

        // optional 'after' filters
        for (ix = 0; ix < config.after.length; ix++) {
          config.after[ix](ctx);
          if (typeof rejectValue !== 'undefined') {
            return reject(rejectValue);
          }
          if (typeof resolveValue !== 'undefined') {
            return resolve(resolveValue);
          }
        }
        if (ctx.error) {
          return reject(ctx.error);
        }
        resolve(ctx.body);
      });
    });
  };

  return api;
};
<|endoftext|>


<commit_before>/**
 * Created by Kenta Iwasaki on 10/22/2016.
 */

import {Link} from "react-router";
import "../tile.css";
import "../flex.css";

Timeline({
    created() {

    },
    destroyed() {
    },
    rendered() {
        $.StartScreen = function () {
            var plugin = this;
            var width = (window.innerWidth > 0) ? window.innerWidth : screen.width;

            plugin.init = function () {
                setTilesAreaSize();
                if (width > 640) addMouseWheel();
            };

            var setTilesAreaSize = function () {
                var groups = $(".tile-group");
                var tileAreaWidth = 80;
                $.each(groups, function (i, t) {
                    if (width <= 640) {
                        tileAreaWidth = width;
                    } else {
                        tileAreaWidth += $(t).outerWidth() + 80;
                    }
                });
                $(".tile-area").css({
                    width: tileAreaWidth
                });
            };

            var addMouseWheel = function () {
                $("body").mousewheel(function (event, delta, deltaX, deltaY) {
                    var page = $(document);
                    var scroll_value = delta * 50;
                    page.scrollLeft(page.scrollLeft() - scroll_value);
                    return false;
                });
            };

            plugin.init();
        }

        $.StartScreen();

        var tiles = $(".tile, .tile-small, .tile-square, .tile-wide, .tile-large, .tile-big, .tile-super");

        $.each(tiles, function () {
            var tile = $(this);
            setTimeout(function () {
                tile.css({
                    opacity: 1,
                    "-webkit-transform": "scale(1)",
                    "transform": "scale(1)",
                    "-webkit-transition": ".3s",
                    "transition": ".3s"
                });
            }, Math.floor(Math.random() * 500));
        });

        $(".tile-group").animate({
            left: 0
        });

        $("body").children().children().css("height", "100%");
    },
    render() {

<Link to={"/"}></Link> Your Timeline.

                <button class="image-button icon-right bg-transparent fg-white bg-grayDark bg-hover-dark no-border">
                    Kenta Iwasaki </button>
                <button class="square-button bg-transparent fg-white bg-grayDark bg-hover-dark no-border"></button>
                <button class="square-button bg-transparent fg-white bg-grayDark bg-hover-dark no-border"></button>
                <Link to={'/logout'}
                      class="square-button bg-transparent fg-white bg-grayDark bg-hover-dark no-border"></Link>

                Times

                        Sleep

                        Shopping

                Meals

                        Meal #1

                        Meal #2

    }
})
<commit_msg>Add timeline prefernces<commit_after>/**
 * Created by Kenta Iwasaki on 10/22/2016.
 */

import {Link} from "react-router";
import "../tile.css";
import "../flex.css";

Timeline({
    created() {

    },
    destroyed() {
    },
    rendered() {
        $.StartScreen = function () {
            var plugin = this;
            var width = (window.innerWidth > 0) ? window.innerWidth : screen.width;

            plugin.init = function () {
                setTilesAreaSize();
                if (width > 640) addMouseWheel();
            };

            var setTilesAreaSize = function () {
                var groups = $(".tile-group");
                var tileAreaWidth = 80;
                $.each(groups, function (i, t) {
                    if (width <= 640) {
                        tileAreaWidth = width;
                    } else {
                        tileAreaWidth += $(t).outerWidth() + 80;
                    }
                });
                $(".tile-area").css({
                    width: tileAreaWidth
                });
            };

            var addMouseWheel = function () {
                $("body").mousewheel(function (event, delta, deltaX, deltaY) {
                    var page = $(document);
                    var scroll_value = delta * 50;
                    page.scrollLeft(page.scrollLeft() - scroll_value);
                    return false;
                });
            };

            plugin.init();
        }

        $.StartScreen();

        var tiles = $(".tile, .tile-small, .tile-square, .tile-wide, .tile-large, .tile-big, .tile-super");

        $.each(tiles, function () {
            var tile = $(this);
            setTimeout(function () {
                tile.css({
                    opacity: 1,
                    "-webkit-transform": "scale(1)",
                    "transform": "scale(1)",
                    "-webkit-transition": ".3s",
                    "transition": ".3s"
                });
            }, Math.floor(Math.random() * 500));
        });

        $(".tile-group").animate({
            left: 0
        });

        $("body").children().children().css("height", "100%");
    },
    render() {

<Link to={"/"}></Link> Your Timeline.

                <button class="image-button icon-right bg-transparent fg-white bg-grayDark bg-hover-dark no-border">
                    Kenta Iwasaki </button>
                <button class="square-button bg-transparent fg-white bg-grayDark bg-hover-dark no-border"></button>
                <button class="square-button bg-transparent fg-white bg-grayDark bg-hover-dark no-border"></button>
                <Link to={'/logout'}
                      class="square-button bg-transparent fg-white bg-grayDark bg-hover-dark no-border"></Link>

                Times

                        Sleep

                          <select>
                              <option selected>Select..</option>
                              <option>No sleep</option>
                              <option>Halal</option>
                              <option>None</option>
                          </select>

                        Shopping

                          <select>
                              <option selected>Select..</option>
                              <option>Duty-free</option>
                              <option>Luxury items</option>
                              <option value="">None</option>
                          </select>

                Meals

                        Meal #1

                          <select>
                              <option selected>Select..</option>
                              <option>Vegetarian</option>
                              <option>Halal</option>
                              <option value="">None</option>
                          </select>

                        Meal #2

                          <select>
                              <option selected>Select..</option>
                              <option>Vegetarian</option>
                              <option>Halal</option>
                              <option value="">None</option>
                          </select>

    }
})
<|endoftext|>


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

"use strict";

const csv = require("@fast-csv/format");
const { db } = require("./common/context");

async function exportCsv(req, res) {
  const { project: projectId, layer: layerId } = req.query;
  const project = await db.fetchProject(projectId);
  if (!project.exists) {
    res.status(404).send("Project not found");
    return;
  }
  console.log(`Exporting project '${projectId}', layer '${layerId}'`);

  const layers = project.get("layers") || {};
  const layer = layers[layerId] || {};
  const forms = layer["forms"] || {};
  const form = Object.values(forms)[0] || {};
  const elementMap = form["elements"] || {};
  const elements = Object.keys(elementMap)
    .map((elementId) => ({ id: elementId, ...elementMap[elementId] }))
    .sort((a, b) => a.index - b.index);

  const headers = [];
  headers.push("Place ID");
  headers.push("Place name");
  headers.push("Latitude");
  headers.push("Longitude");
  elements.forEach((element) => {
    const labelMap = element["label"] || {};
    const label = Object.values(labelMap)[0] || "Unnamed field";
    headers.push(label);
  });

  res.type("text/csv");
  const csvStream = csv.format({
    delimiter: ",",
    headers,
    includeEndRowDelimiter: true,
    rowDelimiter: "\n",
    quoteColumns: true,
    quote: '"',
  });
  csvStream.pipe(res);

  const features = await db.fetchFeaturesByLayerId(project.id, layerId);
  const observations = await db.fetchObservationsByLayerId(project.id, layerId);

  // Index observations by feature id in memory. This consumes more
  // memory than iterating over and streaming both feature and observation`
  // collections simultaneously, but it's easier to read and maintain. This will
  // likely need to be optimized to scale to larger datasets.
  const observationsByFeature = {};
  observations.forEach((observation) => {
    const featureId = observation.get("featureId");
    const arr = observationsByFeature[featureId] || [];
    arr.push(observation.data());
    observationsByFeature[featureId] = arr;
  });

  features.forEach((feature) => {
    const featureId = feature.id;
    const location = feature.get("location") || {};
    (observationsByFeature[featureId] || []).forEach((observation) => {
      const row = [];
      row.push(feature.get("id") || "");
      row.push(feature.get("caption") || "");
      row.push(location["_latitude"] || "");
      row.push(location["_longitude"] || "");
      const responses = observation["responses"] || {};
      elements.forEach((element) => {
        console.log(element.id, observation);
        row.push(responses[element.id] || "");
      });
      csvStream.write(row);
    });
  });
  csvStream.end();
}

module.exports = exportCsv;
<commit_msg>Export features without observations<commit_after>/**
 * @license
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

"use strict";

const csv = require("@fast-csv/format");
const { db } = require("./common/context");

async function exportCsv(req, res) {
  const { project: projectId, layer: layerId } = req.query;
  const project = await db.fetchProject(projectId);
  if (!project.exists) {
    res.status(404).send("Project not found");
    return;
  }
  console.log(`Exporting project '${projectId}', layer '${layerId}'`);

  const layers = project.get("layers") || {};
  const layer = layers[layerId] || {};
  const forms = layer["forms"] || {};
  const form = Object.values(forms)[0] || {};
  const elementMap = form["elements"] || {};
  const elements = Object.keys(elementMap)
    .map((elementId) => ({ id: elementId, ...elementMap[elementId] }))
    .sort((a, b) => a.index - b.index);

  const headers = [];
  headers.push("Place ID");
  headers.push("Place name");
  headers.push("Latitude");
  headers.push("Longitude");
  elements.forEach((element) => {
    const labelMap = element["label"] || {};
    const label = Object.values(labelMap)[0] || "Unnamed field";
    headers.push(label);
  });

  res.type("text/csv");
  const csvStream = csv.format({
    delimiter: ",",
    headers,
    includeEndRowDelimiter: true,
    rowDelimiter: "\n",
    quoteColumns: true,
    quote: '"',
  });
  csvStream.pipe(res);

  const features = await db.fetchFeaturesByLayerId(project.id, layerId);
  const observations = await db.fetchObservationsByLayerId(project.id, layerId);

  // Index observations by feature id in memory. This consumes more
  // memory than iterating over and streaming both feature and observation`
  // collections simultaneously, but it's easier to read and maintain. This will
  // likely need to be optimized to scale to larger datasets.
  const observationsByFeature = {};
  observations.forEach((observation) => {
    const featureId = observation.get("featureId");
    const arr = observationsByFeature[featureId] || [];
    arr.push(observation.data());
    observationsByFeature[featureId] = arr;
  });

  features.forEach((feature) => {
    const featureId = feature.id;
    const location = feature.get("location") || {};
    const observations = observationsByFeature[featureId] || [{}];
    observations.forEach((observation) => {
      const row = [];
      row.push(feature.get("id") || "");
      row.push(feature.get("caption") || "");
      row.push(location["_latitude"] || "");
      row.push(location["_longitude"] || "");
      const responses = observation["responses"] || {};
      elements.forEach((element) => {
        console.log(element.id, observation);
        row.push(responses[element.id] || "");
      });
      csvStream.write(row);
    });
  });
  csvStream.end();
}

module.exports = exportCsv;
<|endoftext|>