<commit_before>// Copyright 2018 Robert Adams
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/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';

// holds the controls context for this threejs instance

import GP from 'GP';
import Config from 'xConfig';
import { BItem, BItemType, BItemState } from 'xBItem';

import * as Eventing from 'xEventing';

// Classes that implement different types of UI controls
import * as UIControls from './UIControls.js';

export class Controls extends BItem {
  constructor() {
    GP.DebugLog('Controls: constructor');
    super('org.basil.b.controls', undefined, BItemType.CONTROLS);

    // Make all 'class=clickable' page items create events
    Array.from(document.getElementsByClassName('clickable')).forEach( nn => {
        nn.addEventListener('click', this._onClickable.bind(this));
        // nn.onClick = OnClickable;
    });

    // Whether debug output window is initially displayed can be set in the configuration file
    this.ShowDebug(Config.page.showDebug);

    // Update the camera position for debugging
    this.infoCameraCoord = new UIControls.UI_Coord('div[b-info=camPosition]');
    if (this.infoCameraCoord) {
      this.eventCameraInfo = new Eventing.subscribe('display.cameraInfo', function(camInfo) {
        if (camInfo && camInfo.position && this.infoCameraCoord) {
          this.infoCameraCoord.Update(camInfo.position);
        }
      }.bind(this));
    }

    // UPdate the renderer info
    this.infoFPS = new UIControls.UI_Text('div[b-info=infoFPS]');
    this.infoDrawCalls = new UIControls.UI_Text('div[b-info=infoDrawCalls]');
    this.infoVertices = new UIControls.UI_Text('div[b-info=infoVertices]');
    this.infoTriangles = new UIControls.UI_Text('div[b-info=infoTriangles]');
    // this.infoPoints = new UIControls.UI_Text('div[b-info=infoPoints]');
    this.infoTextureMem = new UIControls.UI_Text('div[b-info=infoTextureMem]');
    this.infoGeometryMem = new UIControls.UI_Text('div[b-info=infoGeometryMem]');
    if (this.infoDrawCalls) {
        this.eventDisplayInfo = new Eventing.subscribe('display.info', function(info) {
            if (info && info.render && this.infoDrawCalls) {
                this.infoFPS.Update(Math.round(info.render.fps));
                this.infoDrawCalls.Update(info.render.calls);
                this.infoVertices.Update(info.render.vertices);
                this.infoTriangles.Update(info.render.faces);
                // this.infoPoints.Update(info.render.points);
            }
            if (info && info.memory && this.infoTextureMem) {
                this.infoTextureMem.Update(info.memory.textures);
                this.infoGeometryMem.Update(info.memory.geometries);
            }
        }.bind(this));
    }
  };

  ControlsStart() {
  };

  // Call to set debug window to specified state. Pass state that is should be in
  ShowDebug(onOff) {
    if (onOff) {   // want it on
      // var showMS = Config.page.DebugShowMS ? Config.page.DebugShowMS : 800;
      document.getElementById('DEBUGG').style.visibility = 'visible';
    }
    else {
      // var hideMS = Config.page.DebugHideMS ? Config.page.DebugHideMS : 400;
      document.getElementById('DEBUGG').style.visibility = 'hidden';
    }
  };

  // Process the HTML element that has class 'clickable'
  // The attribute 'op' says what to do when the element is clicked.
  _onClickable(evnt) {
    // var buttonOp = document.querySelector(evnt.target).getAttribute('op');
    var buttonOp = evnt.target.getAttribute('op');
    switch (buttonOp) {
      case 'addTestObject':  // DEBUG DEBUG
        GP.GR.AddTestObject();  // DEBUG DEBUG
        break;  // DEBUG DEBUG
      case 'showDebug':
        // Make the state to the opposite of what it is now
        ShowDebug(!(document.getElementById('DEBUGG').style.visibility !== 'hidden'));
        break;
      /*
      case 'loadGltf':
        var url = Config.assets.gltfURLBase + document.querySelector$('#SelectGltf').val();
        GP.DebugLog('Controls: OnLoadButton: loading ' + url);
        DoLoadMultiple([ [ url, [0,0,0] ] ]);
        break;
      case 'loadAtropia':
        GP.DebugLog('Controls: OnLoadAtropia');
        let atropiaValue = Config.Atropia;
        if (atropiaValue) {
            GP.DebugLog('Getting value for regions from HTML')
            let parsedInput = JSON.parse(atropiaValue);
            // Add the url base for GLTF files (since it changes with the GLTF version)
            atropiaRegions = parsedInput.map(oneRegionInfo => {
                return [ Config.assets.gltfURLBase + oneRegionInfo[0], oneRegionInfo[1] ];
            });
            DoLoadMultiple(atropiaRegions);
        }
        break;
      */
      default:
        GP.ReportError('Controls: Unknown button op: ' + buttonOp);
        break;
    }
  };

  /*
  function DoLoadMultiple(urlsAndLocations) {
      Graphics.ClearScene();
      Graphics.LoadSceneMultiple(urlsAndLocations, function() {

          // DEBUG DEBUG -- initially point camera at one of the objects in the scene
          var aPlace;
          if (GP.GR.scene.children) {
              // ThreeJS
              // Walk down the tree until we find something not at <9,9<
              var anObject = GP.GR.scene.children[0];
              while (anObject && anObject.position.x == 0 && anObject.position.y == 0) {
                  let nextObj = anObject.children.find(xx => { return xx.type == 'Group'});
                  if (nextObj == undefined) {
                      nextObj = anObject.children.find(xx => { return xx.type == 'Object3D'});
                  }
                  anObject = nextObj;
              }
              if (anObject) {
                  let pos = anObject.position;
                  aPlace = [pos.x, pos.y, pos.z];
              }
          }
          else {
              if (GP.GR.scene.meshes) {
                  // for BabylonJS
                  let ppos = GP.GR.scene.meshes[0].position;
                  aPlace = [ ppos.x, ppos.y, ppos.z ];
              }
          }
          // The position is passed as an array because not using some libary's Vector3
          if (aPlace != undefined) {
              var cameraPlace = [aPlace[0] + 40, aPlace[1] + 40, aPlace[2] + 40];
              Graphics.SetCameraPosition(cameraPlace);
              Graphics.PointCameraAt([aPlace[0], aPlace[1], aPlace[2]]);
          }
          // end DEBUG DEBUG
          Graphics.GraphicsStart(); // ClearScene possibly shuts down rendering
      });
  };
  */
}
<commit_msg>Fix exception when using 'ShowDebug' button.<commit_after>// Copyright 2018 Robert Adams
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/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';

// holds the controls context for this threejs instance

import GP from 'GP';
import Config from 'xConfig';
import { BItem, BItemType, BItemState } from 'xBItem';

import * as Eventing from 'xEventing';

// Classes that implement different types of UI controls
import * as UIControls from './UIControls.js';

export class Controls extends BItem {
  constructor() {
    GP.DebugLog('Controls: constructor');
    super('org.basil.b.controls', undefined, BItemType.CONTROLS);

    // Make all 'class=clickable' page items create events
    Array.from(document.getElementsByClassName('clickable')).forEach( nn => {
        nn.addEventListener('click', this._onClickable.bind(this));
        // nn.onClick = OnClickable;
    });

    // Whether debug output window is initially displayed can be set in the configuration file
    this.ShowDebug(Config.page.showDebug);

    // Update the camera position for debugging
    this.infoCameraCoord = new UIControls.UI_Coord('div[b-info=camPosition]');
    if (this.infoCameraCoord) {
      this.eventCameraInfo = new Eventing.subscribe('display.cameraInfo', function(camInfo) {
        if (camInfo && camInfo.position && this.infoCameraCoord) {
          this.infoCameraCoord.Update(camInfo.position);
        }
      }.bind(this));
    }

    // UPdate the renderer info
    this.infoFPS = new UIControls.UI_Text('div[b-info=infoFPS]');
    this.infoDrawCalls = new UIControls.UI_Text('div[b-info=infoDrawCalls]');
    this.infoVertices = new UIControls.UI_Text('div[b-info=infoVertices]');
    this.infoTriangles = new UIControls.UI_Text('div[b-info=infoTriangles]');
    // this.infoPoints = new UIControls.UI_Text('div[b-info=infoPoints]');
    this.infoTextureMem = new UIControls.UI_Text('div[b-info=infoTextureMem]');
    this.infoGeometryMem = new UIControls.UI_Text('div[b-info=infoGeometryMem]');
    if (this.infoDrawCalls) {
        this.eventDisplayInfo = new Eventing.subscribe('display.info', function(info) {
            if (info && info.render && this.infoDrawCalls) {
                this.infoFPS.Update(Math.round(info.render.fps));
                this.infoDrawCalls.Update(info.render.calls);
                this.infoVertices.Update(info.render.vertices);
                this.infoTriangles.Update(info.render.faces);
                // this.infoPoints.Update(info.render.points);
            }
            if (info && info.memory && this.infoTextureMem) {
                this.infoTextureMem.Update(info.memory.textures);
                this.infoGeometryMem.Update(info.memory.geometries);
            }
        }.bind(this));
    }
  };

  ControlsStart() {
  };

  // Call to set debug window to specified state. Pass state that is should be in
  ShowDebug(onOff) {
    if (onOff) {   // want it on
      // var showMS = Config.page.DebugShowMS ? Config.page.DebugShowMS : 800;
      document.getElementById('DEBUGG').style.visibility = 'visible';
    }
    else {
      // var hideMS = Config.page.DebugHideMS ? Config.page.DebugHideMS : 400;
      document.getElementById('DEBUGG').style.visibility = 'hidden';
    }
  };

  // Process the HTML element that has class 'clickable'
  // The attribute 'op' says what to do when the element is clicked.
  _onClickable(evnt) {
    // var buttonOp = document.querySelector(evnt.target).getAttribute('op');
    var buttonOp = evnt.target.getAttribute('op');
    switch (buttonOp) {
      case 'addTestObject':  // DEBUG DEBUG
        GP.GR.AddTestObject();  // DEBUG DEBUG
        break;  // DEBUG DEBUG
      case 'showDebug':
        // Make the state to the opposite of what it is now
        this.ShowDebug(!(document.getElementById('DEBUGG').style.visibility !== 'hidden'));
        break;
      /*
      case 'loadGltf':
        var url = Config.assets.gltfURLBase + document.querySelector$('#SelectGltf').val();
        GP.DebugLog('Controls: OnLoadButton: loading ' + url);
        DoLoadMultiple([ [ url, [0,0,0] ] ]);
        break;
      case 'loadAtropia':
        GP.DebugLog('Controls: OnLoadAtropia');
        let atropiaValue = Config.Atropia;
        if (atropiaValue) {
            GP.DebugLog('Getting value for regions from HTML')
            let parsedInput = JSON.parse(atropiaValue);
            // Add the url base for GLTF files (since it changes with the GLTF version)
            atropiaRegions = parsedInput.map(oneRegionInfo => {
                return [ Config.assets.gltfURLBase + oneRegionInfo[0], oneRegionInfo[1] ];
            });
            DoLoadMultiple(atropiaRegions);
        }
        break;
      */
      default:
        GP.ReportError('Controls: Unknown button op: ' + buttonOp);
        break;
    }
  };

  /*
  function DoLoadMultiple(urlsAndLocations) {
      Graphics.ClearScene();
      Graphics.LoadSceneMultiple(urlsAndLocations, function() {

          // DEBUG DEBUG -- initially point camera at one of the objects in the scene
          var aPlace;
          if (GP.GR.scene.children) {
              // ThreeJS
              // Walk down the tree until we find something not at <9,9<
              var anObject = GP.GR.scene.children[0];
              while (anObject && anObject.position.x == 0 && anObject.position.y == 0) {
                  let nextObj = anObject.children.find(xx => { return xx.type == 'Group'});
                  if (nextObj == undefined) {
                      nextObj = anObject.children.find(xx => { return xx.type == 'Object3D'});
                  }
                  anObject = nextObj;
              }
              if (anObject) {
                  let pos = anObject.position;
                  aPlace = [pos.x, pos.y, pos.z];
              }
          }
          else {
              if (GP.GR.scene.meshes) {
                  // for BabylonJS
                  let ppos = GP.GR.scene.meshes[0].position;
                  aPlace = [ ppos.x, ppos.y, ppos.z ];
              }
          }
          // The position is passed as an array because not using some libary's Vector3
          if (aPlace != undefined) {
              var cameraPlace = [aPlace[0] + 40, aPlace[1] + 40, aPlace[2] + 40];
              Graphics.SetCameraPosition(cameraPlace);
              Graphics.PointCameraAt([aPlace[0], aPlace[1], aPlace[2]]);
          }
          // end DEBUG DEBUG
          Graphics.GraphicsStart(); // ClearScene possibly shuts down rendering
      });
  };
  */
}
<|endoftext|>


<commit_before>// BOTTOM TAB BAR

var win = Titanium.UI.currentWindow;

var bottomView = Titanium.UI.createView({
	bottom:0,
	height:58,
	backgroundImage:'images/toolbar/toolbar_bg.png'
});

var storiesTab = Titanium.UI.createButton({
	value:false,
	bottom:5,
	left:30,
	height:41,
	width:49,
	backgroundImage:'images/toolbar/books_ico.png'
});

var usersTab = Titanium.UI.createButton({
	value:false,
	bottom:7,
	right:23,
	height:37,
	width:69,
	backgroundImage:'images/toolbar/users_ico.png'
});

var recordTab = Titanium.UI.createButton({
	value:false,
	bottom:0,
	height:69,
	width:122,
	backgroundImage:'images/toolbar/newstory_btn.png'
});

win.add(bottomView);
win.add(storiesTab);
win.add(usersTab);
win.add(recordTab);<commit_msg>comment<commit_after>// BOTTOM TAB BAR

// var win = Titanium.UI.currentWindow;
//
// var bottomView = Titanium.UI.createView({
// 	bottom:0,
// 	height:58,
// 	backgroundImage:'images/toolbar/toolbar_bg.png'
// });
//
// var storiesTab = Titanium.UI.createButton({
// 	value:false,
// 	bottom:5,
// 	left:30,
// 	height:41,
// 	width:49,
// 	backgroundImage:'images/toolbar/books_ico.png'
// });
//
// var usersTab = Titanium.UI.createButton({
// 	value:false,
// 	bottom:7,
// 	right:23,
// 	height:37,
// 	width:69,
// 	backgroundImage:'images/toolbar/users_ico.png'
// });
//
// var recordTab = Titanium.UI.createButton({
// 	value:false,
// 	bottom:0,
// 	height:69,
// 	width:122,
// 	backgroundImage:'images/toolbar/newstory_btn.png'
// });
//
// win.add(bottomView);
// win.add(storiesTab);
// win.add(usersTab);
// win.add(recordTab);<|endoftext|>


<commit_before>/**
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

module.exports = {
    moduleType: 'locale',
    name: 'pt-BR',
    dictionary: {},
    format: {
        days: [
            'Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira',
            'Quinta-feira', 'Sexta-feira', 'Sábado'
        ],
        shortDays: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'],
        months: [
            'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
            'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'
        ],
        shortMonths: [
            'Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun',
            'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'
        ],
        date: '%d/%m/%Y'
    }
};
<commit_msg>Brazilian portuguese translation.<commit_after>/**
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

module.exports = {
    moduleType: 'locale',
    name: 'pt-BR',
    dictionary: {
            'Autoscale': 'Escala automática',
            'Box Select': 'Seleção retangular',
            'Click to enter Colorscale title': 'Clique para editar o título da escala de cor',
            'Click to enter Component A title': 'Clique para editar o título do Componente A',
            'Click to enter Component B title': 'Clique para editar o título do Componente B',
            'Click to enter Component C title': 'Clique para editar o título do Componente C',
            'Click to enter Plot title': 'Clique para editar o título do Gráfico',
            'Click to enter X axis title': 'Clique para editar o título do eixo X',
            'Click to enter Y axis title': 'Clique para editar o título do eixo Y',
            'Compare data on hover': 'Comparar dados ao pairar',
            'Double-click on legend to isolate one trace': 'Duplo clique na legenda para isolar uma serie',
            'Double-click to zoom back out': 'Duplo clique para reverter zoom',
            'Download plot as a png': 'Fazer download do gráfico como imagem (png)',
            'Edit in Chart Studio': 'Editar no Chart Studio',
            'IE only supports svg.  Changing format to svg.': 'IE suporta apenas svg. Alterando formato para svg',
            'Lasso Select': 'Seleção de laço',
            'Orbital rotation': 'Rotação orbital',
            'Pan': 'Mover',
            'Produced with Plotly': 'Produzido com o Plotly',
            'Reset': 'Restaurar',
            'Reset axes': 'Restaurar eixos',
            'Reset camera to default': 'Restaurar câmera para padrão',
            'Reset camera to last save': 'Restaurar câmera para última salva',
            'Reset view': 'Restaurar visão',
            'Reset views': 'Restaurar visões',
            'Show closest data on hover': 'Exibir dado mais próximo ao passar ao pairar',
            'Snapshot succeeded': 'Captura instantânea completa',
            'Sorry, there was a problem downloading your snapshot!': 'Desculpe, houve um problema no download de sua captura instantânea!',
            'Taking snapshot - this may take a few seconds': 'Efetuando captura instantânea - isso pode levar alguns instantes',
            'Toggle Spike Lines': 'Habilitar/desabilitar triangulação de linhas',
            'Toggle show closest data on hover': 'Habilitar/desabilitar exibição de dado mais próximo ao pairar',
            'Turntable rotation': 'Rotação de mesa',
            'Zoom': 'Zoom',
            'Zoom in': 'Ampliar zoom',
            'Zoom out': 'Reduzir zoom',
            'close': 'fechamento',
            'high': 'alta',
            'incoming flow count': 'contagem de fluxo de entrada',
            'lat': 'latitude',
            'lon': 'longitude',
            'low': 'baixa',
            'lower fence': 'limite inferior',
            'max': 'máximo',
            'mean ± σ': 'mediana ± σ',
            'mean': 'mediana',
            'median': 'mediana',
            'min': 'mínimo',
            'open': 'abertura',
            'outgoing flow count': 'contagem de fluxo de saída',
            'q1': 'q1',
            'q3': 'q3',
            'source': 'origem',
            'target': 'destino',
            'trace': 'série',
            'upper fence': 'limite superior'
    },
    format: {
        days: [
            'Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira',
            'Quinta-feira', 'Sexta-feira', 'Sábado'
        ],
        shortDays: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'],
        months: [
            'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
            'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'
        ],
        shortMonths: [
            'Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun',
            'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'
        ],
        date: '%d/%m/%Y'
    }
};
<|endoftext|>


<commit_before>import Stamp from "relativity";
import Event from "relativity/event";
import ID from "relativity/id";

module("Stamp");

test("create", function() {
  ok((new Stamp()) instanceof Stamp, "Created a stamp with new");
  ok(Stamp() instanceof Stamp, "Created a stamp without new");
});

test("event", function() {
  var examples = [
    {withId: [1,0], from: [[1,0,0], 1, 1], to: 2},
    {withId: 1, from: [1, 0, 0], to: 1},
    {withId: [1, [1, 0]], from: [0, [0, 2, 5], 7], to: 14}
    //{withId: [0,1], from: 2, to: 3},
    //{withId: 0, from: [1, 0, 0], to: [1, 0, 0]},
  ];
  expect(examples.length);
  examples.forEach(function(example) {
    var s = new Stamp(new ID(example.withId), new Event(example.from));
    deepEqual(s.event().flatten(), [example.withId, example.to]);
  });
});
<commit_msg>more tests<commit_after>import Stamp from "relativity";
import Event from "relativity/event";
import ID from "relativity/id";

module("Stamp");

test("create", function() {
  ok((new Stamp()) instanceof Stamp, "Created a stamp with new");
  ok(Stamp() instanceof Stamp, "Created a stamp without new");
});

test("event", function() {
  var examples = [
    {withId: [1,0], from: [[1,0,0], 1, 1], to: 2},
    {withId: 1, from: [1, 0, 0], to: 1},
    {withId: [1, [1, 0]], from: [0, [0, 2, 5], 7], to: 14},
    {withId: [[1,0], 1], from: [[0, 1, 31], [0, 2, 5], 7], to: 39},
    {
      withId: [[1, [1, 0]], [[1,0], 1]],
      from: [[0, [0, 2, 5], 7], [[0, 1, 31], [0, 2, 5], 7], 17],
      to: [0, 39-14, 17+14]
    },
    //{withId: [0,1], from: 2, to: 3},
    //{withId: 0, from: [1, 0, 0], to: [1, 0, 0]},
  ];
  expect(examples.length);
  examples.forEach(function(example) {
    var s = new Stamp(new ID(example.withId), new Event(example.from));
    deepEqual(s.event().flatten(), [example.withId, example.to]);
  });
});
<|endoftext|>


<commit_before>'use strict';

var React = require('react');
var VariableStore = require('../stores/variable-store');
var ModalStore = require('../stores/modal-store');
var ImportModal = require('./modal/import-modal');
var ExportModal = require('./modal/export-modal');

var Navigation = React.createClass({
  export: function () {
    ModalStore.action('open', ExportModal);
  },

  import: function () {
    ModalStore.action('open', ImportModal);
  },

  reset: function () {
    var r = window.confirm('Are you sure you want to reset your variables?' +
      'If you click OK, you will lose all your variables.');
    if (r) {
      VariableStore.action('reset');
    } else {
      console.log('Canceled!');
    }
  },

  preview: function () {
    VariableStore.action('requestPreview');
  },

  toggleDropdownSizes: function () {
    this.setState({
      dropdownSizesActive: !this.state.dropdownSizesActive
    });
  },

  getInitialState: function() {
    return {
      dropdownSizesActive: false
    };
  },

  render: function () {
    var self = this;

    var frameSizes = this.props.frameSizes.map(function (size) {
      return (

          {size.name}

      );
    });

    return (

            <button type='button' className='navbar-toggle collapsed'>
              Toggle navigation

            </button>

Import

Export

Reset

                  Screen Sizes ({self.props.currentFrameSize.name})

                  {frameSizes}

Preview

    );
  }
});

module.exports = Navigation;
<commit_msg>Fix tests<commit_after>'use strict';

var React = require('react');
var VariableStore = require('../stores/variable-store');
var ModalStore = require('../stores/modal-store');
var ImportModal = require('./modal/import-modal');
var ExportModal = require('./modal/export-modal');

var Navigation = React.createClass({
  export: function () {
    ModalStore.action('open', ExportModal);
  },

  import: function () {
    ModalStore.action('open', ImportModal);
  },

  reset: function () {
    var r = window.confirm('Are you sure you want to reset your variables?' +
      'If you click OK, you will lose all your variables.');
    if (r) {
      VariableStore.action('reset');
    } else {
      console.log('Canceled!');
    }
  },

  preview: function () {
    VariableStore.action('requestPreview');
  },

  toggleDropdownSizes: function () {
    this.setState({
      dropdownSizesActive: !this.state.dropdownSizesActive
    });
  },

  getInitialState: function () {
    return {
      dropdownSizesActive: false
    };
  },

  render: function () {
    var self = this;

    var frameSizes = this.props.frameSizes.map(function (size) {
      return (

          {size.name}

      );
    });

    return (

            <button type='button' className='navbar-toggle collapsed'>
              Toggle navigation

            </button>

Import

Export

Reset

                  Screen Sizes ({self.props.currentFrameSize.name})

                  {frameSizes}

Preview

    );
  }
});

module.exports = Navigation;
<|endoftext|>


<commit_before>/* Copyright (c) 1997-2013, SalesLogix, NA., LLC. All rights reserved.*/

/**
 * @class Mobile.SalesLogix.Views._GroupListMixin
 *
 * Mixin for slx group list layouts.
 *
 * @since 3.0
 *
 *
 */
define('Mobile/SalesLogix/Views/_GroupListMixin', [
    'dojo/_base/declare',
    'dojo/_base/array',
    'dojo/string',
    'dojo/json',
    'dojo/dom-style',
    'dojo/dom-class',
    'Sage/Platform/Mobile/Format',
    'Sage/Platform/Mobile/Utility',
    'Mobile/SalesLogix/GroupUtility',
    'dojo/when',
    'dojo/_base/lang',
    'Sage/Platform/Mobile/Store/SData'
], function(
    declare,
    array,
    string,
    json,
    domStyle,
    domClass,
    format,
    utility,
    GroupUtility,
    when,
    lang,
    SDataStore
) {
    var mixinName = 'Mobile.SalesLogix.Views._GroupListMixin';

    return declare('Mobile.SalesLogix.Views._GroupListMixin', null, {
        noDefaultGroupText: 'No default group set. Open the right menu and press configure under the groups section to setup groups.',
        currentGroupNotFoundText: 'The current group was not found.',
        noDefaultGroupTemplate: new Simplate([
            '
',
            '
{%= $$._getNoDefaultGroupMessage() %}
',
            '
'
        ]),
        currentGoupNotFoundTemplate: new Simplate([
           '
',
           '
{%= $$._getCurrentGroupNotFoundMessage() %}
',
           '
'
        ]),
        _getNoDefaultGroupMessage: function() {
            var mixin = lang.getObject(mixinName);
            if (mixin) {
                return mixin.prototype.noDefaultGroupText;
            }
        },
        _getCurrentGroupNotFoundMessage: function() {
            var mixin = lang.getObject(mixinName);
            if (mixin) {
                return mixin.prototype.currentGroupNotFoundText;
            }
        },
        groupsModeText: 'You are currently in groups mode. Perform a search or click a hashtag to exit groups mode.',
        //View Properties
        entityName: null,
        groupsEnabled: false,
        groupsMode: false,
        currentGroupId: null,
        _currentGroup: null,
        _groupInitalized: false,
        _originalProps: null,

        selectedColumns: null,
        layout: null,

        postMixInProperties: function() {
            if (!App.enableGroups) {
                this.groupsMode = false;
                this.groupsEnabled = false;
            }

            if (this.groupsEnabled) {
                this.groupsMode = true;
            }

            this.inherited(arguments);
        },

        requestData: function() {
            try {
                if (!this._groupInitalized && this.groupsMode) {
                    domClass.add(this.domNode, 'list-loading');
                    this.listLoading = true;
                    this.initGroup();
                } else {
                    this.inherited(arguments);
                }
            } catch (e) {
                console.error(e);
            }
        },

        joinFields: function(sep, fields) {
            return utility.joinFields(sep, fields);
        },
        getDescriptor: function(entity) {
            return entity.$descriptor || entity.$key || "unknown";
        },
        getCurrentGroup: function() {
            return this._currentGroup;
        },
        setCurrentGroup: function(group) {
            if (group) {
                if (this.currentGroupId !== group.$key) {
                    this._groupInitalized = false;
                    this._currentGroup = group;
                    this.currentGroupId = group.$key;
                    GroupUtility.setDefaultGroupPreference(this.entityName, group.name);
                }
            }
        },
        getDefaultGroup: function() {
            var defaultGroup = null,
                defaultGroupName = null;

            defaultGroup = GroupUtility.getDefaultGroup(this.entityName);

            if (defaultGroup) {
                return defaultGroup;
            } else {
                defaultGroupName = GroupUtility.getDefaultGroupPreference(this.entityName);
                if (defaultGroupName) {
                    this._requestGroup(defaultGroupName);
                } else {
                    // No default group preference
                    this.set('listContent', this.noDefaultGroupTemplate.apply(this));
                }
            }

            return null;
        },
        initGroup: function() {
            var group;
            group = this.getCurrentGroup();

            if (!group) {
                group = this.getDefaultGroup();
                this.setCurrentGroup(group);
            }

            if (group) {
                this._onApplyGroup(group);
            }
        },
        _onApplyGroup: function(group) {
            var template = [], layout, selectColumns, title;

            if (!group) {
                throw new Error("Group not found.");
            }

            this._startGroupMode();

            // Set the toolbar title to the current group displayName
            title = this.getGroupTitle(group);
            App.setPrimaryTitle(title);
            this.set('title', title);

            if (this._groupInitalized) {
                return;
            }

            this.layout = GroupUtility.getLayout(group);
            this.selectColumns = GroupUtility.getColumnNames(this.layout);

            template = array.map(this.layout, this.getItemLayoutTemplate);
            this.itemTemplate = new Simplate(template);

            // Create a custom request that the store will use to execute the group query
            this.request = GroupUtility.createGroupRequest({
                groupId: group.$key,
                connection: this.getConnection()
            });

            // Try to select the entity id as well
            this.selectColumns.push(group.family + 'ID');
            this.querySelect = this.selectColumns;
            this.queryOrderBy = '';
            this.idProperty = group.family.toUpperCase() + 'ID';
            this.labelProperty = group.family.toUpperCase();
            this.store = null;
            this.clear(true);
            this.refreshRequired = true;
            this._groupInitalized = true;
            this.requestData();
        },
        _requestGroup: function(groupName, onSuccess) {
            var store = null, queryResults;

            if (typeof groupName === 'string' && groupName !== '') {
                store = new SDataStore({
                    service: App.services.crm,
                    resourceKind: 'groups',
                    contractName: 'system',
                    where: "((upper(family) eq '" + this.entityName.toUpperCase() + "') and (upper(Name) eq '" + groupName.toUpperCase() + "'))",
                    include: ['layout', 'tableAliases'],
                    idProperty: '$key',
                    applicationName: 'slx',
                    scope: this
                });
            }

            if (store) {
                queryResults = store.query();

                (function(context, queryResults) {
                    try {
                        when(queryResults, lang.hitch(context, function(groupFeed) {
                            if (typeof onSuccess === 'function') {
                                onSuccess.apply(this, arguments);
                            } else {
                                this._onGroupRequestSuccess(groupFeed);
                            }
                        }));
                    }
                    catch (error) {
                        console.log('Error fetching group data:' + error);
                    }
                })(this, queryResults);

            }
        },
        _onGroupRequestSuccess: function(result) {
            var group, title;
            if (result.length > 0) {
                group = result[0];
                this.setCurrentGroup(group);
                GroupUtility.addToGroupPreferences([group], this.entityName);
                this._onApplyGroup(group);
            } else {
                title = this.getGroupTitle();
                App.setPrimaryTitle(title);
                this.set('title', title);
                this._selectGroups();
            }

            // Reload the right menu
            this.onTransitionAway();
            this.loadRightDrawer();

            domClass.remove(this.domNode, 'list-loading');
            this.listLoading = false;
        },
        _onGroupRequestFaild: function(result) {

        },
        getGroupTitle: function(group) {
            var title = '';
            if (group && typeof group.displayName === 'string') {
                title = group.displayName;
            }

            return group.displayName;
        },
        getItemLayoutTemplate: function(item) {
            var template, jsonString;
            jsonString = json.stringify(item);

            if (item.index === 0) {
                template = ["
", item.caption, " : {%= $$.getFormatterByLayout(" + jsonString + ")($[$$.getFieldNameByLayout(" + jsonString + ")]) %}", "
"].join('');
            } else {
                template = ["
", item.caption, " : {%= $$.getFormatterByLayout(" + jsonString + ")($[$$.getFieldNameByLayout(" + jsonString + ")]) %}", "
"].join('');
            }

            return template;

        },
        getFormatterByLayout: function(layoutItem) {
            return GroupUtility.getFormatterByLayout(layoutItem);
        },
        getFieldNameByLayout: function(layoutItem) {
            return GroupUtility.getFieldNameByLayout(layoutItem);
        },
        _startGroupMode: function() {
            if (this._originalProps) {
                return;
            }

            this._originalProps = {};

            var original = this._originalProps;

            original.request = this.request ? this.request.clone() : null;
            original.querySelect = this.querySelect;
            original.queryOrderBy = this.queryOrderBy;
            original.idProperty = this.idProperty;
            original.labelProperty = this.labelProperty;
            original.store = this.store;
            original.rowTemplate = this.rowTemplate;
            original.itemTemplate = this.itemTemplate;
            original.itemFooterTemplate = this.itemFooterTemplate;
            original.relatedViews = this.relatedViews;
            original.title = this.get('title');

            this.itemFooterTemplate = new Simplate(['

']);

            this.groupsMode = true;
        },
        _clearGroupMode: function() {
            var original = this._originalProps;

            this.groupsMode = false;

            if (!original) {
                return;
            }

            this.request = original.request || null;
            this.querySelect = original.querySelect;
            this.queryOrderBy = original.queryOrderBy;
            this.idProperty = original.idProperty;
            this.labelProperty = original.labelProperty;
            this.set('store', original.store);
            this.rowTemplate = original.rowTemplate;
            this.itemTemplate = original.itemTemplate;
            this.relatedViews = original.relatedViews;
            this.itemFooterTemplate =  original.itemFooterTemplate;

            this._originalProps = null;

            this._groupInitalized = false;
            this._currentGroup = null;
            this.currentGroupId = null;
            App.setPrimaryTitle(original.title);
            this.set('title', original.title);

            this.clear();
            this.refreshRequired = true;
        },
        onProcessRelatedViews: function(entry, rowNode, entries) {
            if (this.groupsEnabled) {
                return;
            }

            this.inherited(arguments);
        },
        _onQueryError: function(queryOptions, error) {
            try {
                if (this._groupInitalized && this.groupsMode) {
                    if(error.status === 404){
                        this._onGroupNotFound();

                    }else{

                        this.inherited(arguments);
                    }
                } else {
                    this.inherited(arguments);
                }
            } catch (e) {
                console.error(e);
            }
        },
        _onGroupNotFound: function() {
            domClass.remove(this.domNode, 'list-loading');
            //GroupUtility.removeGroupPreferences(this._currentGroup.$key, this.entityName);
            this.set('listContent', this.currentGoupNotFoundTemplate.apply(this));

        }
    });
});

<commit_msg>Refractor  OnQueryError<commit_after>/* Copyright (c) 1997-2013, SalesLogix, NA., LLC. All rights reserved.*/

/**
 * @class Mobile.SalesLogix.Views._GroupListMixin
 *
 * Mixin for slx group list layouts.
 *
 * @since 3.0
 *
 *
 */
define('Mobile/SalesLogix/Views/_GroupListMixin', [
    'dojo/_base/declare',
    'dojo/_base/array',
    'dojo/string',
    'dojo/json',
    'dojo/dom-style',
    'dojo/dom-class',
    'Sage/Platform/Mobile/Format',
    'Sage/Platform/Mobile/Utility',
    'Mobile/SalesLogix/GroupUtility',
    'dojo/when',
    'dojo/_base/lang',
    'Sage/Platform/Mobile/Store/SData'
], function(
    declare,
    array,
    string,
    json,
    domStyle,
    domClass,
    format,
    utility,
    GroupUtility,
    when,
    lang,
    SDataStore
) {
    var mixinName = 'Mobile.SalesLogix.Views._GroupListMixin';

    return declare('Mobile.SalesLogix.Views._GroupListMixin', null, {
        noDefaultGroupText: 'No default group set. Open the right menu and press configure under the groups section to setup groups.',
        currentGroupNotFoundText: 'The current group was not found.',
        noDefaultGroupTemplate: new Simplate([
            '
',
            '
{%= $$._getNoDefaultGroupMessage() %}
',
            '
'
        ]),
        currentGoupNotFoundTemplate: new Simplate([
           '
',
           '
{%= $$._getCurrentGroupNotFoundMessage() %}
',
           '
'
        ]),
        _getNoDefaultGroupMessage: function() {
            var mixin = lang.getObject(mixinName);
            if (mixin) {
                return mixin.prototype.noDefaultGroupText;
            }
        },
        _getCurrentGroupNotFoundMessage: function() {
            var mixin = lang.getObject(mixinName);
            if (mixin) {
                return mixin.prototype.currentGroupNotFoundText;
            }
        },
        groupsModeText: 'You are currently in groups mode. Perform a search or click a hashtag to exit groups mode.',
        //View Properties
        entityName: null,
        groupsEnabled: false,
        groupsMode: false,
        currentGroupId: null,
        _currentGroup: null,
        _groupInitalized: false,
        _originalProps: null,

        selectedColumns: null,
        layout: null,

        postMixInProperties: function() {
            if (!App.enableGroups) {
                this.groupsMode = false;
                this.groupsEnabled = false;
            }

            if (this.groupsEnabled) {
                this.groupsMode = true;
            }

            this.inherited(arguments);
        },

        requestData: function() {
            try {
                if (!this._groupInitalized && this.groupsMode) {
                    domClass.add(this.domNode, 'list-loading');
                    this.listLoading = true;
                    this.initGroup();
                } else {
                    this.inherited(arguments);
                }
            } catch (e) {
                console.error(e);
            }
        },

        joinFields: function(sep, fields) {
            return utility.joinFields(sep, fields);
        },
        getDescriptor: function(entity) {
            return entity.$descriptor || entity.$key || "unknown";
        },
        getCurrentGroup: function() {
            return this._currentGroup;
        },
        setCurrentGroup: function(group) {
            if (group) {
                if (this.currentGroupId !== group.$key) {
                    this._groupInitalized = false;
                    this._currentGroup = group;
                    this.currentGroupId = group.$key;
                    GroupUtility.setDefaultGroupPreference(this.entityName, group.name);
                }
            }
        },
        getDefaultGroup: function() {
            var defaultGroup = null,
                defaultGroupName = null;

            defaultGroup = GroupUtility.getDefaultGroup(this.entityName);

            if (defaultGroup) {
                return defaultGroup;
            } else {
                defaultGroupName = GroupUtility.getDefaultGroupPreference(this.entityName);
                if (defaultGroupName) {
                    this._requestGroup(defaultGroupName);
                } else {
                    // No default group preference
                    this.set('listContent', this.noDefaultGroupTemplate.apply(this));
                }
            }

            return null;
        },
        initGroup: function() {
            var group;
            group = this.getCurrentGroup();

            if (!group) {
                group = this.getDefaultGroup();
                this.setCurrentGroup(group);
            }

            if (group) {
                this._onApplyGroup(group);
            }
        },
        _onApplyGroup: function(group) {
            var template = [], layout, selectColumns, title;

            if (!group) {
                throw new Error("Group not found.");
            }

            this._startGroupMode();

            // Set the toolbar title to the current group displayName
            title = this.getGroupTitle(group);
            App.setPrimaryTitle(title);
            this.set('title', title);

            if (this._groupInitalized) {
                return;
            }

            this.layout = GroupUtility.getLayout(group);
            this.selectColumns = GroupUtility.getColumnNames(this.layout);

            template = array.map(this.layout, this.getItemLayoutTemplate);
            this.itemTemplate = new Simplate(template);

            // Create a custom request that the store will use to execute the group query
            this.request = GroupUtility.createGroupRequest({
                groupId: group.$key,
                connection: this.getConnection()
            });

            // Try to select the entity id as well
            this.selectColumns.push(group.family + 'ID');
            this.querySelect = this.selectColumns;
            this.queryOrderBy = '';
            this.idProperty = group.family.toUpperCase() + 'ID';
            this.labelProperty = group.family.toUpperCase();
            this.store = null;
            this.clear(true);
            this.refreshRequired = true;
            this._groupInitalized = true;
            this.requestData();
        },
        _requestGroup: function(groupName, onSuccess) {
            var store = null, queryResults;

            if (typeof groupName === 'string' && groupName !== '') {
                store = new SDataStore({
                    service: App.services.crm,
                    resourceKind: 'groups',
                    contractName: 'system',
                    where: "((upper(family) eq '" + this.entityName.toUpperCase() + "') and (upper(Name) eq '" + groupName.toUpperCase() + "'))",
                    include: ['layout', 'tableAliases'],
                    idProperty: '$key',
                    applicationName: 'slx',
                    scope: this
                });
            }

            if (store) {
                queryResults = store.query();

                (function(context, queryResults) {
                    try {
                        when(queryResults, lang.hitch(context, function(groupFeed) {
                            if (typeof onSuccess === 'function') {
                                onSuccess.apply(this, arguments);
                            } else {
                                this._onGroupRequestSuccess(groupFeed);
                            }
                        }));
                    }
                    catch (error) {
                        console.log('Error fetching group data:' + error);
                    }
                })(this, queryResults);

            }
        },
        _onGroupRequestSuccess: function(result) {
            var group, title;
            if (result.length > 0) {
                group = result[0];
                this.setCurrentGroup(group);
                GroupUtility.addToGroupPreferences([group], this.entityName);
                this._onApplyGroup(group);
            } else {
                title = this.getGroupTitle();
                App.setPrimaryTitle(title);
                this.set('title', title);
                this._selectGroups();
            }

            // Reload the right menu
            this.onTransitionAway();
            this.loadRightDrawer();

            domClass.remove(this.domNode, 'list-loading');
            this.listLoading = false;
        },
        _onGroupRequestFaild: function(result) {

        },
        getGroupTitle: function(group) {
            var title = '';
            if (group && typeof group.displayName === 'string') {
                title = group.displayName;
            }

            return group.displayName;
        },
        getItemLayoutTemplate: function(item) {
            var template, jsonString;
            jsonString = json.stringify(item);

            if (item.index === 0) {
                template = ["
", item.caption, " : {%= $$.getFormatterByLayout(" + jsonString + ")($[$$.getFieldNameByLayout(" + jsonString + ")]) %}", "
"].join('');
            } else {
                template = ["
", item.caption, " : {%= $$.getFormatterByLayout(" + jsonString + ")($[$$.getFieldNameByLayout(" + jsonString + ")]) %}", "
"].join('');
            }

            return template;

        },
        getFormatterByLayout: function(layoutItem) {
            return GroupUtility.getFormatterByLayout(layoutItem);
        },
        getFieldNameByLayout: function(layoutItem) {
            return GroupUtility.getFieldNameByLayout(layoutItem);
        },
        _startGroupMode: function() {
            if (this._originalProps) {
                return;
            }

            this._originalProps = {};

            var original = this._originalProps;

            original.request = this.request ? this.request.clone() : null;
            original.querySelect = this.querySelect;
            original.queryOrderBy = this.queryOrderBy;
            original.idProperty = this.idProperty;
            original.labelProperty = this.labelProperty;
            original.store = this.store;
            original.rowTemplate = this.rowTemplate;
            original.itemTemplate = this.itemTemplate;
            original.itemFooterTemplate = this.itemFooterTemplate;
            original.relatedViews = this.relatedViews;
            original.title = this.get('title');

            this.itemFooterTemplate = new Simplate(['

']);

            this.groupsMode = true;
        },
        _clearGroupMode: function() {
            var original = this._originalProps;

            this.groupsMode = false;

            if (!original) {
                return;
            }

            this.request = original.request || null;
            this.querySelect = original.querySelect;
            this.queryOrderBy = original.queryOrderBy;
            this.idProperty = original.idProperty;
            this.labelProperty = original.labelProperty;
            this.set('store', original.store);
            this.rowTemplate = original.rowTemplate;
            this.itemTemplate = original.itemTemplate;
            this.relatedViews = original.relatedViews;
            this.itemFooterTemplate =  original.itemFooterTemplate;

            this._originalProps = null;

            this._groupInitalized = false;
            this._currentGroup = null;
            this.currentGroupId = null;
            App.setPrimaryTitle(original.title);
            this.set('title', original.title);

            this.clear();
            this.refreshRequired = true;
        },
        onProcessRelatedViews: function(entry, rowNode, entries) {
            if (this.groupsEnabled) {
                return;
            }

            this.inherited(arguments);
        },
        _onQueryError: function(queryOptions, error) {
                if (this.groupsEnabled && this.groupsMode) {
                    if (error.status === 404) {
                        try{
                            this._onGroupNotFound();
                            return;
                        } catch (e) {
                            console.error(e);
                        }
                    }
                }
                this.inherited(arguments);
        },
        _onGroupNotFound: function() {
            domClass.remove(this.domNode, 'list-loading');
            this.set('listContent', this.currentGoupNotFoundTemplate.apply(this));

        }
    });
});

<|endoftext|>


<commit_before>var https = require('https')
  , querystring = require('querystring')
  , crypto = require('crypto')

  // tokbox constants:
  , TOKEN_SENTINEL = "T1=="
  , SDK_VERSION = "tbjs-0.91.2011-03-16"
  , TOKBOX_HOST = "staging.tokbox.com"
  , SESSION_API_ENDPOINT = "/hl/session/create";

// Session Properties definition:
var SessionProperties = exports.SessionProperties = function(){
  return {
    'echoSuppression.enabled' : null,
    'multiplexer.numOutputStreams' : null,
    'multiplexer.switchType' : null,
    'multiplexer.switchTimeout' : null
  }
}

var RoleConstants = exports.Roles = function(){
  return {
    'SUBSCRIBER': "subscriber",
    'PUBLISHER': "publisher",
    'MODERATOR': "moderator"
  }
}

// Just the session
var OpenTokSession = function(sessionId){
  this.sessionId = sessionId
}

// The SDK
var OpenTokSDK = exports.OpenTokSDK = function(partnerId, partnerSecret){
  this.partnerId = partnerId
  this.partnerSecret = partnerSecret
}

OpenTokSDK.prototype.setEnvironment = function(host){
  TOKBOX_HOST = host
}

OpenTokSDK.prototype.generateToken = function(ops){
  ops = ops || {}

  // grab options or use defaults:
  var sessionId = (ops.session) ? ops.session.sessionId : this.sessionId;

  var createTime = OpenTokSDK.prototype._getUTCDate()
    , sig
    , tokenString
    , tokenParams
    , tokenBuffer
    , dataString
    , dataParams = {
        session_id: sessionId,
        create_time: createTime,
        nonce: Math.floor(Math.random()*999999),
        role: RoleConstants.PUBLISHER // will be overriden below if passed in
      };

  // pass through any other tokbox parameters:
  for(var op in ops){
    if(ops.hasOwnProperty(op)){
      dataParams[op] = ops[op]
    }
  }

  dataString = querystring.stringify(dataParams)
  sig = this._signString(dataString, this.partnerSecret)
  tokenParams = ["partner_id=",this.partnerId,"&sdk_version=",SDK_VERSION,"&sig=",sig,":",dataString].join("")
  tokenBuffer = new Buffer(tokenParams,"utf8");
  return TOKEN_SENTINEL + tokenBuffer.toString('base64');

}

OpenTokSDK.prototype.createSession = function(ipPassthru, properties, callback){
  var sessionId
    , params = {
        partner_id: this.partnerId,
        location_hint: ipPassthru
      };

  for(var p in properties){
    params[p] = properties[p]
  }

  sessionId = this._doRequest(params, function(sessionId){
    callback(new OpenTokSession(sessionId))
  })

}

OpenTokSDK.prototype._signString = function(string, secret){
  var hmac = crypto.createHmac('sha1',secret)
  hmac.update(string)
  return hmac.digest(encoding='hex')
}

OpenTokSDK.prototype._doRequest = function(params, callback){
  var dataString = querystring.stringify(params)
    , reqOptions;

  options = {
    host: TOKBOX_HOST,
    path: SESSION_API_ENDPOINT,
    method: 'POST',
    headers: {
      'Content-Type': 'application-xml',
      'Content-Length': dataString.length,
      'X-TB-PARTNER-AUTH': this.partnerId + ":" + this.partnerSecret
    }
  }

  req = https.request(options, function(res){
    var chunks = '';

    res.setEncoding('utf8')

    res.on('data', function(chunk){
      chunks += chunk
    })

    res.on('end', function(){
      var start = chunks.match('<session_id>')
        , end = chunks.match('</session_id>');

      if(start && end){
        var session = chunks.substr(start.index + 12, (end.index - start.index - 12))
        callback(session)
      } else {
        callback()
      }
    })
  })
  req.write(dataString)
  req.end()

}

OpenTokSDK.prototype._getUTCDate = function(){
  var D= new Date();
  return Date.UTC(D.getUTCFullYear(), D.getUTCMonth(), D.getUTCDate(), D.getUTCHours(),
    D.getUTCMinutes(), D.getUTCSeconds()).toString().substr(0,10)
}

<commit_msg>Added p2p.preference session property<commit_after>var https = require('https')
  , querystring = require('querystring')
  , crypto = require('crypto')

  // tokbox constants:
  , TOKEN_SENTINEL = "T1=="
  , SDK_VERSION = "tbjs-0.91.2011-03-16"
  , TOKBOX_HOST = "staging.tokbox.com"
  , SESSION_API_ENDPOINT = "/hl/session/create";

// Session Properties definition:
var SessionProperties = exports.SessionProperties = function(){
  return {
    'echoSuppression.enabled' : null,
    'multiplexer.numOutputStreams' : null,
    'multiplexer.switchType' : null,
    'multiplexer.switchTimeout' : null,
    'p2p.preference' : null
  }
}

var RoleConstants = exports.Roles = function(){
  return {
    'SUBSCRIBER': "subscriber",
    'PUBLISHER': "publisher",
    'MODERATOR': "moderator"
  }
}

// Just the session
var OpenTokSession = function(sessionId){
  this.sessionId = sessionId
}

// The SDK
var OpenTokSDK = exports.OpenTokSDK = function(partnerId, partnerSecret){
  this.partnerId = partnerId
  this.partnerSecret = partnerSecret
}

OpenTokSDK.prototype.setEnvironment = function(host){
  TOKBOX_HOST = host
}

OpenTokSDK.prototype.generateToken = function(ops){
  ops = ops || {}

  // grab options or use defaults:
  var sessionId = (ops.session) ? ops.session.sessionId : this.sessionId;

  var createTime = OpenTokSDK.prototype._getUTCDate()
    , sig
    , tokenString
    , tokenParams
    , tokenBuffer
    , dataString
    , dataParams = {
        session_id: sessionId,
        create_time: createTime,
        nonce: Math.floor(Math.random()*999999),
        role: RoleConstants.PUBLISHER // will be overriden below if passed in
      };

  // pass through any other tokbox parameters:
  for(var op in ops){
    if(ops.hasOwnProperty(op)){
      dataParams[op] = ops[op]
    }
  }

  dataString = querystring.stringify(dataParams)
  sig = this._signString(dataString, this.partnerSecret)
  tokenParams = ["partner_id=",this.partnerId,"&sdk_version=",SDK_VERSION,"&sig=",sig,":",dataString].join("")
  tokenBuffer = new Buffer(tokenParams,"utf8");
  return TOKEN_SENTINEL + tokenBuffer.toString('base64');

}

OpenTokSDK.prototype.createSession = function(ipPassthru, properties, callback){
  var sessionId
    , params = {
        partner_id: this.partnerId,
        location_hint: ipPassthru
      };

  for(var p in properties){
    params[p] = properties[p]
  }

  sessionId = this._doRequest(params, function(sessionId){
    callback(new OpenTokSession(sessionId))
  })

}

OpenTokSDK.prototype._signString = function(string, secret){
  var hmac = crypto.createHmac('sha1',secret)
  hmac.update(string)
  return hmac.digest(encoding='hex')
}

OpenTokSDK.prototype._doRequest = function(params, callback){
  var dataString = querystring.stringify(params)
    , reqOptions;

  options = {
    host: TOKBOX_HOST,
    path: SESSION_API_ENDPOINT,
    method: 'POST',
    headers: {
      'Content-Type': 'application-xml',
      'Content-Length': dataString.length,
      'X-TB-PARTNER-AUTH': this.partnerId + ":" + this.partnerSecret
    }
  }

  req = https.request(options, function(res){
    var chunks = '';

    res.setEncoding('utf8')

    res.on('data', function(chunk){
      chunks += chunk
    })

    res.on('end', function(){
      var start = chunks.match('<session_id>')
        , end = chunks.match('</session_id>');

      if(start && end){
        var session = chunks.substr(start.index + 12, (end.index - start.index - 12))
        callback(session)
      } else {
        callback()
      }
    })
  })
  req.write(dataString)
  req.end()

}

OpenTokSDK.prototype._getUTCDate = function(){
  var D= new Date();
  return Date.UTC(D.getUTCFullYear(), D.getUTCMonth(), D.getUTCDate(), D.getUTCHours(),
    D.getUTCMinutes(), D.getUTCSeconds()).toString().substr(0,10)
}

<|endoftext|>


<commit_before>import React from 'react';
import {shallow} from 'enzyme';

import {createPullRequestResult} from '../fixtures/factories/pull-request-result';
import Issueish from '../../lib/models/issueish';
import {BareIssueishListController} from '../../lib/controllers/issueish-list-controller';

describe('IssueishListController', function() {
  function buildApp(overrideProps = {}) {
    return (
      <BareIssueishListController
        title="title"
        results={null}
        repository={null}

        isLoading={false}

        onOpenIssueish={() => {}}
        onOpenMore={() => {}}

        {...overrideProps}
      />
    );
  }

  it('renders an IssueishListView in a loading state', function() {
    const wrapper = shallow(buildApp({isLoading: true}));

    const view = wrapper.find('IssueishListView');
    assert.isTrue(view.prop('isLoading'));
    assert.strictEqual(view.prop('total'), 0);
    assert.lengthOf(view.prop('issueishes'), 0);
  });

  it('renders an IssueishListView with issueish results', function() {
    const mockPullRequest = createPullRequestResult({number: 1});

    const onOpenIssueish = sinon.stub();
    const onOpenMore = sinon.stub();

    const wrapper = shallow(buildApp({
      results: [mockPullRequest],
      total: 1,
      onOpenIssueish,
      onOpenMore,
    }));

    const view = wrapper.find('IssueishListView');
    assert.isFalse(view.prop('isLoading'));
    assert.strictEqual(view.prop('total'), 1);
    assert.lengthOf(view.prop('issueishes'), 1);
    assert.deepEqual(view.prop('issueishes'), [
      new Issueish(mockPullRequest),
    ]);

    const payload = Symbol('payload');
    view.prop('onIssueishClick')(payload);
    assert.isTrue(onOpenIssueish.calledWith(payload));

    view.prop('onMoreClick')(payload);
    assert.isTrue(onOpenMore.calledWith(payload));
  });

  it('applies a resultFilter to limit its results', function() {
    const wrapper = shallow(buildApp({
      resultFilter: issueish => issueish.getNumber() > 10,
      results: [0, 11, 13, 5, 12].map(number => createPullRequestResult({number})),
      total: 5,
    }));

    const view = wrapper.find('IssueishListView');
    assert.strictEqual(view.prop('total'), 5);
    assert.deepEqual(view.prop('issueishes').map(issueish => issueish.getNumber()), [11, 13, 12]);
  });
});
<commit_msg>Test passing an Error to an IssueishListController<commit_after>import React from 'react';
import {shallow} from 'enzyme';

import {createPullRequestResult} from '../fixtures/factories/pull-request-result';
import Issueish from '../../lib/models/issueish';
import {BareIssueishListController} from '../../lib/controllers/issueish-list-controller';

describe('IssueishListController', function() {
  function buildApp(overrideProps = {}) {
    return (
      <BareIssueishListController
        title="title"
        results={null}
        repository={null}

        isLoading={false}

        onOpenIssueish={() => {}}
        onOpenMore={() => {}}

        {...overrideProps}
      />
    );
  }

  it('renders an IssueishListView in a loading state', function() {
    const wrapper = shallow(buildApp({isLoading: true}));

    const view = wrapper.find('IssueishListView');
    assert.isTrue(view.prop('isLoading'));
    assert.strictEqual(view.prop('total'), 0);
    assert.lengthOf(view.prop('issueishes'), 0);
  });

  it('renders an IssueishListView in an error state', function() {
    const error = new Error("d'oh");
    error.rawStack = error.stack;
    const wrapper = shallow(buildApp({error}));

    const view = wrapper.find('IssueishListView');
    assert.strictEqual(view.prop('error'), error);
  });

  it('renders an IssueishListView with issueish results', function() {
    const mockPullRequest = createPullRequestResult({number: 1});

    const onOpenIssueish = sinon.stub();
    const onOpenMore = sinon.stub();

    const wrapper = shallow(buildApp({
      results: [mockPullRequest],
      total: 1,
      onOpenIssueish,
      onOpenMore,
    }));

    const view = wrapper.find('IssueishListView');
    assert.isFalse(view.prop('isLoading'));
    assert.strictEqual(view.prop('total'), 1);
    assert.lengthOf(view.prop('issueishes'), 1);
    assert.deepEqual(view.prop('issueishes'), [
      new Issueish(mockPullRequest),
    ]);

    const payload = Symbol('payload');
    view.prop('onIssueishClick')(payload);
    assert.isTrue(onOpenIssueish.calledWith(payload));

    view.prop('onMoreClick')(payload);
    assert.isTrue(onOpenMore.calledWith(payload));
  });

  it('applies a resultFilter to limit its results', function() {
    const wrapper = shallow(buildApp({
      resultFilter: issueish => issueish.getNumber() > 10,
      results: [0, 11, 13, 5, 12].map(number => createPullRequestResult({number})),
      total: 5,
    }));

    const view = wrapper.find('IssueishListView');
    assert.strictEqual(view.prop('total'), 5);
    assert.deepEqual(view.prop('issueishes').map(issueish => issueish.getNumber()), [11, 13, 12]);
  });
});
<|endoftext|>


<commit_before>/*global  jQuery, i, j, ii*/

'use strict';

(function() {
  var root = this;

  // save previous data for 'genev'
  var prevGenev = root.genev;

  var genev = function(CHROMO_STRUCTURE, options) {

    // Create our own extend function
    var extend = function() {
      var opt,
      prop,
      source,
      newcopy,
      original = arguments[0] || {},
      i = 1,
      length = arguments.length;
      // Handle case when original is a string or something
      if (typeof original !== 'object') {
        original = {};
      }
      // if only one argument is passed, we return it back
      if (i === length) {
        return original;
      }
      for (; i < length; i++) {
        // Only deal with non-null/undefined values
        if ((opt = arguments[i]) != null) {
          // Extend the base object
          for (prop in opt) {
            source = original[prop];
            newcopy = opt[prop];
            // Prevent never-ending loop
            if (original === newcopy) {
              continue;
            }
            // Recurse if we're merging plain objects or arrays
            if (newcopy !== undefined) {
              original[prop] = newcopy;
            }
          }
        }
      }
      return original;
    };

    // Check for invalid parameter CHROMO_STRUCTURE
    if ((typeof CHROMO_STRUCTURE === 'undefined') || (typeof CHROMO_STRUCTURE !== 'object')) {
      // console.error("Invalid parameter passed to GF. You need to pass a chromosome structure.");
      return null;
    }

    // Accept both genes object or chromo->genes object
    if ((typeof CHROMO_STRUCTURE.genes === 'undefined')) {
      var genes = JSON.parse(JSON.stringify(CHROMO_STRUCTURE));
      CHROMO_STRUCTURE = {genes: genes};
    }

    ///////////////////////////////////////////////////////////
    //      START OF PRIVATE CLASS METHODS/PROPERTIES
    ///////////////////////////////////////////////////////////

    /** Object that represents all of the class private methods and properties. */
    var gfprivate = {};

    /** Chromosome structure */
    gfprivate.CHROMO_STRUCTURE = CHROMO_STRUCTURE;

    /** Default options */
    gfprivate.DEFAULT_OPTIONS = {
      maxPopulation: 45,
      maxGenerations: 1000,
      mutationProb: 0.05,
      numToSelect: 10,
      elitism: true,
      exitScore: -1 // -1 always runs until maxGenerations is reached
    };

    /** Maximum population size */
    gfprivate.maxPopulation = 45; // default to 45

    /** Maximum number of generations */
    gfprivate.maxGenerations = 100; // default to 100

    /** Mutation probability */
    gfprivate.mutationProb = 0.05; // default to 5%

    /** Selection number (a.k.a. tournament winners) */
    gfprivate.numToSelect = 10; // default to 10 tributes (they volunteer)

    /** If true, ensures that the top chromosome always survives to next generation */
    gfprivate.elitism = true; // default to true

    /** Holds the elite chromosome */
    gfprivate.elite = {};

    /** Chromosome atrributes */
    gfprivate.chromosome = {
      genes: {},
      score: 0,
      generation: 0
    };

    /** Generation Population Array */
    gfprivate.population = [];

    /** Sort (descending) chromosomes based on score */
    gfprivate.sortPopulation = function() {
      gfprivate.population.sort(function(a, b) {
        return b.score - a.score; // descending score order
      });
    };

    /** Crossover Xgene and Ygene and return crossover */
    gfprivate.crossover = function(Xchromo, Ychromo) {
      var crossedChromo = extend({},gfprivate.chromosome), // create new chromosome
          property; // holds the looped property
      for (property in Xchromo.genes) { // loop through all weights
        if (Xchromo.genes.hasOwnProperty(property)) {
          // 50/50 chance of picking a gene from either
          crossedChromo.genes[property] = ((Math.random() > 0.5) ? Xchromo.genes[property] : Ychromo.genes[property]);
        }
      }
      // increase generation
      crossedChromo.generation = Xchromo.generation + 1;
      return extend({},crossedChromo);
    };

    /** Mutate individual chromosomes */
    gfprivate.getMutated = function(chromo) {
      var mutatedChromo = extend({},chromo),
          property;
      for (property in chromo.genes) {
        if (chromo.genes.hasOwnProperty(property)) {
          mutatedChromo.genes[property] = ((Math.random() < gfprivate.mutationProb) ? Math.random() : chromo.genes[property]);
        }
      }
      return mutatedChromo;
    };

    /** Generates a new random chromosome using the structure provided */
    gfprivate.newChromosome = function() {
      var newChromosome = extend({},gfprivate.chromosome),
          property;
      newChromosome.genes = gfprivate.CHROMO_STRUCTURE.genes;
      for (property in newChromosome.genes) {
        if (newChromosome.genes.hasOwnProperty(property)) {
          newChromosome.genes[property] = Math.random();
        }
      }
      return newChromosome;
    };

    /** Default fitness function (should be replaced with custom function by framework user) */
    gfprivate.fitnessFunction = function(genes) {
      var property;
      for (property in genes) {
        if (genes.hasOwnProperty(property)) {
          return genes[property];
        }
      }
    };

    /** Evaluate scores of all chromosomes and sets their score property */
    gfprivate.evaluate = function() {
      for (var i = 0; i < gfprivate.population.length; i += 1) {
        var score = {score: gfprivate.fitnessFunction(gfprivate.population[i].genes)};
        extend(gfprivate.population[i],score);
      }
      gfprivate.sortPopulation();
    };

    /** Selects the most fit numToSelect in the population */
    gfprivate.selectFittest = function() {
      if (gfprivate.numToSelect > 0) {
        gfprivate.population.splice(gfprivate.numToSelect);
      } else {
        gfprivate.population.splice(1); // If numToSelect is 0 for somereason, we select 1
      }
      // Clone the elite and save it
      gfprivate.elite = JSON.parse(JSON.stringify(gfprivate.population[0]));
      gfprivate.elite.generation += 1;
    };

    /** Selects random chromosomes in a given population,
     * and then pushes those selected to the main population (which is emptied before hand)
     * @param selectionPop a population to select from */
    gfprivate.selectRandom = function(selectionPop) {
      // The number of chromosomes to randomly select should be the least of the two
      var numToSelect = selectionPop.length < gfprivate.maxPopulation ? selectionPop.length : gfprivate.maxPopulation;
      gfprivate.population = [];
      // TODO Avoid re-adding the same randomly selected chromosome
      for (var i = 0; i < numToSelect; i += 1) {
        var selector = Math.floor(Math.random() * selectionPop.length); // Random number from 0 to selectionPop.length
        gfprivate.population.push(JSON.parse(JSON.stringify(extend({},selectionPop[selector])))); // add the selected value to the population, TODO Hack solution, replace
      }
      // We then fill the rest of it with random chromosomes,
      var restNum = gfprivate.maxPopulation - selectionPop.length;
      for (var i = 0; i < restNum; i += 1) {
        gfprivate.population.push(JSON.parse(JSON.stringify(gfprivate.newChromosome())));
      }
    };

    /** The method to be used when extending gfprivate with any options,
     * It just checks for any invalid option values that essentially break everything, and fallsback to
     * some safe (probably default values, or not)
     * etc. */
    gfprivate.extend = function(options) {
      extend(gfprivate, options); // first we set whatever we were given
      // Then we check, and fix them if need be
      if (gfprivate.maxPopulation < 10) {
        gfprivate.maxPopulation = 10;
      } else if (gfprivate.numToSelect < 1) {
        gfprivate.numToSelect = 1;
      }
    };

    /** Crossover the entire population in gfprivate.population
   * This method has the efficiency class of O(n^2) but is usually run on the fittest
   * chromosomes selected (which are only 10 by default). Keep this in mind when changing the
   * default ```numToSelect``` option.
   */
    gfprivate.crossPopulation = function() {
      var crossoverPopulation = [];
      // Crosses all n chromosomes with all other n-1 chromosomes
      for (var i = 0; i < gfprivate.population.length; i += 1) {
        for (var ii = 1; ii < gfprivate.population.length - i; ii += 1) {
          // 50/50 chance for selecting genes
          var crossoverChromosome = extend({},gfprivate.crossover(gfprivate.population[i], gfprivate.population[ii]));
          crossoverPopulation.push(JSON.parse(JSON.stringify(crossoverChromosome))); // HACK SOLUTION FOR REFERENCE PROBLEM, TODO REPLACE THIS
        }
        gfprivate.population[i].generation += 1; // increase the generation
        crossoverPopulation.push(JSON.parse(JSON.stringify(gfprivate.population[i]))); // Re-add all chromosomes used in crossing
      }
      gfprivate.selectRandom(crossoverPopulation); // randomly select chromosomes in the crossoverPopulation and place them in the population
    };

    /** Mutates the entire population */
    gfprivate.mutatePopulation = function() {
      for (var i = 0; i < gfprivate.population.length; i += 1) {
        gfprivate.population[i] = JSON.parse(JSON.stringify(gfprivate.getMutated(gfprivate.population[i]))); // HACK, TODO FIX
      }
    };

    /** Initializes the population array with a random set of chromosomes. */
    gfprivate.initRandomPop = function() {
      /* CREATE RANDOM POPULATION */
      for (var i = 0; i < gfprivate.maxPopulation; i += 1) {
        // Create new random chromosome
        var newChromosome = extend(true, {}, gfprivate.newChromosome());
        // Add it to the population
        gfprivate.population.push(newChromosome);
      }
    };

    /** Checks if the exit score has been reached
     * @returns boolean */
    gfprivate.exitScoreReached = function() {
      if (gfprivate.exitScore !== -1) {
        if (gfprivate.population[0].score >= gfprivate.exitScore) {
          return true;
        }
      }
      return false;
    };

    /** Runs at the beginning of every generation loop. A.k.a. when the generation is born (and evaluated).
     * This should be changed to fit the special needs of every user.
     * If you want to print/log/view the data after every generation, you would do it here.
     * @param population Array containing all chromosomes in the population
     */
    gfprivate.onNewGen = function(population) {
      // default does nothing
      return;
    };

    ///////////////////////////////////////////////////////////
    //             START OF PUBLIC METHODS/API
    ///////////////////////////////////////////////////////////

    /** Class public methods/properties */
    var gfpublic = {};

    /** Initializes the population with either user provided chromosomes or randomly generates them
     * @param initpop (optional) User provided array of initial chromosomes
     * @param validate (optional) Set true if you want genev to validate your array. It is optional as it could be an expensive process.
     * @returns boolean If you provided ```validate``` as true, it will return false when initialization has failed because of invalid data.
     */
    gfpublic.initPopulation = function(initpop, validate) {
      if (typeof initpop !== 'undefined') {
        if (typeof validate !== 'undefined' && validate === true) {
          // validate that all objects in input initpop contain correct properties (CHROMO_STRUCTURE)
          for (var i = 0; i < initpop; i += 1) {
            var property;
            if (typeof initpop[i].genes === 'undefined') {
              // chromosomes not built properly, they need to have a genes properties
              // TODO need some kind of error handler
              return;
            }
            for (property in gfprivate.CHROMO_STRUCTURE) {
              if (typeof initpop[i].genes[property] === 'undefined') {
                // Missing property discovered one of initpop's chromosomes
                return;
              }
            }
          }
        }
        /* Initialize with provided population */
        gfprivate.population = [];
        gfprivate.population.push(initpop);
      }
      /* Init random if one is not provided */
      gfprivate.initRandomPop();
    };

    /** Evolves the population
   * @param evolveOptions object that accepts options (optional)
   * @param fitfunc a fitness function (optional)
   * @returns void
   */
    gfpublic.evolve = function(fitfunc, evolveOptions) {
      // Update options again.
      gfprivate.extend(evolveOptions);

      // The generation counter
      var generationCount = gfprivate.maxGenerations;

      // Set the fitness function if it was passed in
      if (typeof fitfunc === 'function') {
        gfprivate.fitnessFunction = fitfunc;
      }

      // Abort
      // If the population is not initialized
      if (gfprivate.population.length == 0) {
        // console.error("No population initialized. Hint: Use .initPopulation before .evolve");
        return;
      }

      // Loops for each generation
      while (generationCount--) {
        /* START EVOLUTION */

        /* EVALUATION PHASE */

        gfprivate.evaluate(); // Test all chromosomes and score them

        /* AFTER EVALUATION CALLBACK */

        if (typeof gfprivate.onNewGen === 'function') {
          gfprivate.onNewGen(gfprivate.population); // run default, or custom function if specified in the options
        }

        /* SELECTION PHASE */

        gfprivate.selectFittest(); // Select most fit chromosomes in terms of score attribute

        /* BREAK CONDITION/SCORE CHECK */

        if (gfprivate.exitScoreReached()) {
          break;
        }

        /* CROSSOVER PHASE */

        gfprivate.crossPopulation();

        /* MUTATION PHASE */

        gfprivate.mutatePopulation();

        /* ELITISM PHASE */

        gfprivate.population.push(gfprivate.elite);

        /* REPEAT UNTIL LAST GENERATION */
      }

      /* END EVOLUTION */
      gfprivate.evaluate();
      gfprivate.selectFittest();
    };

    /** Resets all options to the defaults */
    gfpublic.resetOptions = function() {
      gfprivate.extend(gfprivate.DEFAULT_OPTIONS);
    };

    /** Returns the population currently in gfprivate.population
   * @returns array Array of chromosomes
   */
    gfpublic.getPopulation = function() {
      return gfprivate.population;
    };

    ///////////////////////////////////////////////////////////
    //                INIT SETUP
    ///////////////////////////////////////////////////////////

    /** Setting default options */
    gfpublic.resetOptions();

    /* Options merging
    This also adds extra flexibility to users who want more control over
    genev as it also allows them to replace private methods/properties. (so they're not completely private...)
    TODO Decide if we want to keep it this way */
    gfprivate.extend(options);

    // Return class public methods (a.k.a. make them available for use)
    return gfpublic;
  };

  genev.noConflict = function() {
    root.genev = prevGenev;
    return genev;
  };

  if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
      exports = module.exports = genev;
    }
    exports.genev = genev;
  } else {
    root.genev = genev;
  }

}).call(this);
<commit_msg>Add clone, repalce JSON.stringify/parse hack<commit_after>/*global  jQuery, i, j, ii*/

'use strict';

(function() {
  var root = this;

  // save previous data for 'genev'
  var prevGenev = root.genev;

  var genev = function(CHROMO_STRUCTURE, options) {

    /* Makes me gag, but this'll be my solution for now */
    var clone = function(obj) {
        return JSON.parse(JSON.stringify(obj));
    }

    // Create our own extend function
    var extend = function() {
      var opt,
      prop,
      source,
      newcopy,
      original = arguments[0] || {},
      i = 1,
      length = arguments.length;
      // Handle case when original is a string or something
      if (typeof original !== 'object') {
        original = {};
      }
      // if only one argument is passed, we return it back
      if (i === length) {
        return original;
      }
      for (; i < length; i++) {
        // Only deal with non-null/undefined values
        if ((opt = arguments[i]) != null) {
          // Extend the base object
          for (prop in opt) {
            source = original[prop];
            newcopy = opt[prop];
            // Prevent never-ending loop
            if (original === newcopy) {
              continue;
            }
            // Recurse if we're merging plain objects or arrays
            if (newcopy !== undefined) {
              original[prop] = newcopy;
            }
          }
        }
      }
      return original;
    };

    // Check for invalid parameter CHROMO_STRUCTURE
    if ((typeof CHROMO_STRUCTURE === 'undefined') || (typeof CHROMO_STRUCTURE !== 'object')) {
      // console.error("Invalid parameter passed to GF. You need to pass a chromosome structure.");
      return null;
    }

    // Accept both genes object or chromo->genes object
    if ((typeof CHROMO_STRUCTURE.genes === 'undefined')) {
      var genes = clone(CHROMO_STRUCTURE);
      CHROMO_STRUCTURE = {genes: genes};
    }

    ///////////////////////////////////////////////////////////
    //      START OF PRIVATE CLASS METHODS/PROPERTIES
    ///////////////////////////////////////////////////////////

    /** Object that represents all of the class private methods and properties. */
    var gfprivate = {};

    /** Chromosome structure */
    gfprivate.CHROMO_STRUCTURE = CHROMO_STRUCTURE;

    /** Default options */
    gfprivate.DEFAULT_OPTIONS = {
      maxPopulation: 45,
      maxGenerations: 1000,
      mutationProb: 0.05,
      numToSelect: 10,
      elitism: true,
      exitScore: -1 // -1 always runs until maxGenerations is reached
    };

    /** Maximum population size */
    gfprivate.maxPopulation = 45; // default to 45

    /** Maximum number of generations */
    gfprivate.maxGenerations = 100; // default to 100

    /** Mutation probability */
    gfprivate.mutationProb = 0.05; // default to 5%

    /** Selection number (a.k.a. tournament winners) */
    gfprivate.numToSelect = 10; // default to 10 tributes (they volunteer)

    /** If true, ensures that the top chromosome always survives to next generation */
    gfprivate.elitism = true; // default to true

    /** Holds the elite chromosome */
    gfprivate.elite = {};

    /** Chromosome atrributes */
    gfprivate.chromosome = {
      genes: {},
      score: 0,
      generation: 0
    };

    /** Generation Population Array */
    gfprivate.population = [];

    /** Sort (descending) chromosomes based on score */
    gfprivate.sortPopulation = function() {
      gfprivate.population.sort(function(a, b) {
        return b.score - a.score; // descending score order
      });
    };

    /** Crossover Xgene and Ygene and return crossover */
    gfprivate.crossover = function(Xchromo, Ychromo) {
      var crossedChromo = extend({},gfprivate.chromosome), // create new chromosome
          property; // holds the looped property
      for (property in Xchromo.genes) { // loop through all weights
        if (Xchromo.genes.hasOwnProperty(property)) {
          // 50/50 chance of picking a gene from either
          crossedChromo.genes[property] = ((Math.random() > 0.5) ? Xchromo.genes[property] : Ychromo.genes[property]);
        }
      }
      // increase generation
      crossedChromo.generation = Xchromo.generation + 1;
      return extend({},crossedChromo);
    };

    /** Mutate individual chromosomes */
    gfprivate.getMutated = function(chromo) {
      var mutatedChromo = extend({},chromo),
          property;
      for (property in chromo.genes) {
        if (chromo.genes.hasOwnProperty(property)) {
          mutatedChromo.genes[property] = ((Math.random() < gfprivate.mutationProb) ? Math.random() : chromo.genes[property]);
        }
      }
      return mutatedChromo;
    };

    /** Generates a new random chromosome using the structure provided */
    gfprivate.newChromosome = function() {
      var newChromosome = extend({},gfprivate.chromosome),
          property;
      newChromosome.genes = gfprivate.CHROMO_STRUCTURE.genes;
      for (property in newChromosome.genes) {
        if (newChromosome.genes.hasOwnProperty(property)) {
          newChromosome.genes[property] = Math.random();
        }
      }
      return newChromosome;
    };

    /** Default fitness function (should be replaced with custom function by framework user) */
    gfprivate.fitnessFunction = function(genes) {
      var property;
      for (property in genes) {
        if (genes.hasOwnProperty(property)) {
          return genes[property];
        }
      }
    };

    /** Evaluate scores of all chromosomes and sets their score property */
    gfprivate.evaluate = function() {
      for (var i = 0; i < gfprivate.population.length; i += 1) {
        var score = {score: gfprivate.fitnessFunction(gfprivate.population[i].genes)};
        extend(gfprivate.population[i],score);
      }
      gfprivate.sortPopulation();
    };

    /** Selects the most fit numToSelect in the population */
    gfprivate.selectFittest = function() {
      if (gfprivate.numToSelect > 0) {
        gfprivate.population.splice(gfprivate.numToSelect);
      } else {
        gfprivate.population.splice(1); // If numToSelect is 0 for somereason, we select 1
      }
      // Clone the elite and save it
      gfprivate.elite = clone(gfprivate.population[0]);
      gfprivate.elite.generation += 1;
    };

    /** Selects random chromosomes in a given population,
     * and then pushes those selected to the main population (which is emptied before hand)
     * @param selectionPop a population to select from */
    gfprivate.selectRandom = function(selectionPop) {
      // The number of chromosomes to randomly select should be the least of the two
      var numToSelect = selectionPop.length < gfprivate.maxPopulation ? selectionPop.length : gfprivate.maxPopulation;
      gfprivate.population = [];
      // TODO Avoid re-adding the same randomly selected chromosome
      for (var i = 0; i < numToSelect; i += 1) {
        var selector = Math.floor(Math.random() * selectionPop.length); // Random number from 0 to selectionPop.length
        gfprivate.population.push(clone(extend({},selectionPop[selector]))); // add the selected value to the population, TODO Hack solution, replace
      }
      // We then fill the rest of it with random chromosomes,
      var restNum = gfprivate.maxPopulation - selectionPop.length;
      for (var i = 0; i < restNum; i += 1) {
        gfprivate.population.push(clone(gfprivate.newChromosome()));
      }
    };

    /** The method to be used when extending gfprivate with any options,
     * It just checks for any invalid option values that essentially break everything, and fallsback to
     * some safe (probably default values, or not)
     * etc. */
    gfprivate.extend = function(options) {
      extend(gfprivate, options); // first we set whatever we were given
      // Then we check, and fix them if need be
      if (gfprivate.maxPopulation < 10) {
        gfprivate.maxPopulation = 10;
      } else if (gfprivate.numToSelect < 1) {
        gfprivate.numToSelect = 1;
      }
    };

    /** Crossover the entire population in gfprivate.population
   * This method has the efficiency class of O(n^2) but is usually run on the fittest
   * chromosomes selected (which are only 10 by default). Keep this in mind when changing the
   * default ```numToSelect``` option.
   */
    gfprivate.crossPopulation = function() {
      var crossoverPopulation = [];
      // Crosses all n chromosomes with all other n-1 chromosomes
      for (var i = 0; i < gfprivate.population.length; i += 1) {
        for (var ii = 1; ii < gfprivate.population.length - i; ii += 1) {
          // 50/50 chance for selecting genes
          var crossoverChromosome = extend({},gfprivate.crossover(gfprivate.population[i], gfprivate.population[ii]));
          crossoverPopulation.push(clone(crossoverChromosome)); // HACK SOLUTION FOR REFERENCE PROBLEM, TODO REPLACE THIS
        }
        gfprivate.population[i].generation += 1; // increase the generation
        crossoverPopulation.push(clone(gfprivate.population[i])); // Re-add all chromosomes used in crossing
      }
      gfprivate.selectRandom(crossoverPopulation); // randomly select chromosomes in the crossoverPopulation and place them in the population
    };

    /** Mutates the entire population */
    gfprivate.mutatePopulation = function() {
      for (var i = 0; i < gfprivate.population.length; i += 1) {
        gfprivate.population[i] = clone(gfprivate.getMutated(gfprivate.population[i])); // HACK, TODO FIX
      }
    };

    /** Initializes the population array with a random set of chromosomes. */
    gfprivate.initRandomPop = function() {
      /* CREATE RANDOM POPULATION */
      for (var i = 0; i < gfprivate.maxPopulation; i += 1) {
        // Create new random chromosome
        var newChromosome = extend(true, {}, gfprivate.newChromosome());
        // Add it to the population
        gfprivate.population.push(newChromosome);
      }
    };

    /** Checks if the exit score has been reached
     * @returns boolean */
    gfprivate.exitScoreReached = function() {
      if (gfprivate.exitScore !== -1) {
        if (gfprivate.population[0].score >= gfprivate.exitScore) {
          return true;
        }
      }
      return false;
    };

    /** Runs at the beginning of every generation loop. A.k.a. when the generation is born (and evaluated).
     * This should be changed to fit the special needs of every user.
     * If you want to print/log/view the data after every generation, you would do it here.
     * @param population Array containing all chromosomes in the population
     */
    gfprivate.onNewGen = function(population) {
      // default does nothing
      return;
    };

    ///////////////////////////////////////////////////////////
    //             START OF PUBLIC METHODS/API
    ///////////////////////////////////////////////////////////

    /** Class public methods/properties */
    var gfpublic = {};

    /** Initializes the population with either user provided chromosomes or randomly generates them
     * @param initpop (optional) User provided array of initial chromosomes
     * @param validate (optional) Set true if you want genev to validate your array. It is optional as it could be an expensive process.
     * @returns boolean If you provided ```validate``` as true, it will return false when initialization has failed because of invalid data.
     */
    gfpublic.initPopulation = function(initpop, validate) {
      if (typeof initpop !== 'undefined') {
        if (typeof validate !== 'undefined' && validate === true) {
          // validate that all objects in input initpop contain correct properties (CHROMO_STRUCTURE)
          for (var i = 0; i < initpop; i += 1) {
            var property;
            if (typeof initpop[i].genes === 'undefined') {
              // chromosomes not built properly, they need to have a genes properties
              // TODO need some kind of error handler
              return;
            }
            for (property in gfprivate.CHROMO_STRUCTURE) {
              if (typeof initpop[i].genes[property] === 'undefined') {
                // Missing property discovered one of initpop's chromosomes
                return;
              }
            }
          }
        }
        /* Initialize with provided population */
        gfprivate.population = [];
        gfprivate.population.push(initpop);
      }
      /* Init random if one is not provided */
      gfprivate.initRandomPop();
    };

    /** Evolves the population
   * @param evolveOptions object that accepts options (optional)
   * @param fitfunc a fitness function (optional)
   * @returns void
   */
    gfpublic.evolve = function(fitfunc, evolveOptions) {
      // Update options again.
      gfprivate.extend(evolveOptions);

      // The generation counter
      var generationCount = gfprivate.maxGenerations;

      // Set the fitness function if it was passed in
      if (typeof fitfunc === 'function') {
        gfprivate.fitnessFunction = fitfunc;
      }

      // Abort
      // If the population is not initialized
      if (gfprivate.population.length == 0) {
        // console.error("No population initialized. Hint: Use .initPopulation before .evolve");
        return;
      }

      // Loops for each generation
      while (generationCount--) {
        /* START EVOLUTION */

        /* EVALUATION PHASE */

        gfprivate.evaluate(); // Test all chromosomes and score them

        /* AFTER EVALUATION CALLBACK */

        if (typeof gfprivate.onNewGen === 'function') {
          gfprivate.onNewGen(gfprivate.population); // run default, or custom function if specified in the options
        }

        /* SELECTION PHASE */

        gfprivate.selectFittest(); // Select most fit chromosomes in terms of score attribute

        /* BREAK CONDITION/SCORE CHECK */

        if (gfprivate.exitScoreReached()) {
          break;
        }

        /* CROSSOVER PHASE */

        gfprivate.crossPopulation();

        /* MUTATION PHASE */

        gfprivate.mutatePopulation();

        /* ELITISM PHASE */

        gfprivate.population.push(gfprivate.elite);

        /* REPEAT UNTIL LAST GENERATION */
      }

      /* END EVOLUTION */
      gfprivate.evaluate();
      gfprivate.selectFittest();
    };

    /** Resets all options to the defaults */
    gfpublic.resetOptions = function() {
      gfprivate.extend(gfprivate.DEFAULT_OPTIONS);
    };

    /** Returns the population currently in gfprivate.population
   * @returns array Array of chromosomes
   */
    gfpublic.getPopulation = function() {
      return gfprivate.population;
    };

    ///////////////////////////////////////////////////////////
    //                INIT SETUP
    ///////////////////////////////////////////////////////////

    /** Setting default options */
    gfpublic.resetOptions();

    /* Options merging
    This also adds extra flexibility to users who want more control over
    genev as it also allows them to replace private methods/properties. (so they're not completely private...)
    TODO Decide if we want to keep it this way */
    gfprivate.extend(options);

    // Return class public methods (a.k.a. make them available for use)
    return gfpublic;
  };

  genev.noConflict = function() {
    root.genev = prevGenev;
    return genev;
  };

  if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
      exports = module.exports = genev;
    }
    exports.genev = genev;
  } else {
    root.genev = genev;
  }

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