<commit_before>import React from 'react';

const questions = {
  what: {
    question: 'Was ist CosmoWiki.de überhaupt?',
    answer:

          CosmoWiki.de ist ein nichtkommerzielles Projekt zur Verbreitung von Wissen über die Bereiche Astronomie und Raumfahrt.

          Auf Plattformen wie z.B. Wikipedia existiert ein gewaltiger Wissensschatz, der von Enthusiasten mit größter Sorgfalt für jedermann erstellt und gepflegt wird.
          Doch warum sollte dieser phantastische Speicher nicht über seine eigentlichen Grenzen hinaus genutzt werden?

          Wir recherchieren unzählige Informationen aus Wikipedia und anderen Quellen, sammeln, veknüpfen und bereiten sie hier in möglichst übersichtlicher Weise auf.
          Cosmowiki.de ist also im Grunde ein Hybride aus Enzyklopädie und Aggregator - ein zentraler Platz im Netz,
          an dem der Nutzer zwei der faszinierendsten Gebiete aus Wissenschaft und Technik auf neue Weise entdecken kann.

  },
  who: {
    question: 'Wem nützt CosmoWiki.de, für wen wurde es geschaffen?',
    answer:

          CosmoWiki.de dient uns allen - interessierten Laien ebenso wie begeisterten Amateuren und allen anderen Space-Fans.
          Jeder Nutzer kann hier frei das gewaltige Universum der Astronomie und Raumfahrt unter einem Dach entdecken, die Geschichte dieser zwei wohl bedeutendsten Bereiche menschlichen Schaffens
          erkunden und zielgerichtet Informationen über Personen, Orte oder Objekte finden.

          Selbst sind wir natürlich auch fasziniert von allem, was mit dem Weltall zu tun hat. So lautet unser Motto: Nutzer arbeiten für Nutzer!

  },
  license: {
    question: 'Darf ich Inhalte von CosmoWiki.de verwenden? Unter welcher Lizenz steht CosmoWiki.de?',
    answer:

          Alle Inhalte von CosmoWiki.de und die von Wikipedia eingebundenen Inhalte stehen unter der
           Creative-Commons-Lizenz Attribution-ShareAlike 3.0 Unported (CC-by-sa-3.0), wenn nichts anderes ausgewiesen wird.

          Gemäß den Bestimmungen der von Wikipedia verwendeten Lizenz
           Creative-Commons-Lizenz Attribution-ShareAlike 3.0 Unported (CC-by-sa-3.0) weisen wir darauf hin,
          dass CosmoWiki.de Artikel oder Teile von Artikeln von Wikipedia verwendet und einbindet.
          Dadurch steht CosmoWiki.de ebenfalls unter der  Creative Commons Lizenz CC BY-SA 3.0.

          Sie dürfen:
Teilen — das Material in jedwedem Format oder Medium vervielfältigen und weiterverbreiten.
Bearbeiten — das Material remixen, verändern und darauf aufbauen
          und zwar für beliebige Zwecke, sogar kommerziell.

          Weitere Informationen zu der verwendeten Lizenz erhalten sie hier:
          http://creativecommons.org/licenses/by-sa/3.0/de/

  },
  future: {
    question: 'Wie geht es weiter? Wie sieht die Zukunft von CosmoWiki.de aus?',
    answer:

          Dieses Projekt wird nie fertiggestellt sein, da sich auch Astronomie und Raumfahrt permanent weiterentwickeln. Unsere Datenbank wächst ständig um neue Inhalte an,
          bestehende Einträge werden um interessante Fakten ergänzt. Zusätzlich wird auch die Seite selbst weiterentwickelt, neue Funktionen werden das Nutzererlebnis verbessern.
          Wir hoffen auch, CosmoWiki.de bald auch in anderen Sprachen anbieten zu können.

          Die Community ist das Zentrum dieser Seite. Wir setzen auf den Enthusiasmus von Amateuren genauso wie auf die Fachkenntnisse von Naturwissenschaftlern und Historikern um ein Werk zu schaffen,
          das auch kritischen Analysen standhält.

  },
  contribute: {
    question: 'Wie kann ich helfen CosmoWiki.de zu verbessern?',
    answer:

          Wenn Sie etwas zu CosmoWiki.de beitragen und das Projekt unterstützen möchten, lassen Sie es uns wissen.
          Sie sind Hobby-Astronom oder Professor der Astrophysik, Historiker oder interessierter Laie, Raumfahrt-Begeisterter oder Astronaut, dann
          kontaktieren Sie uns bitte hier.

          Für Software-Entwickler und Programmierer ist CosmoWiki.de auch auf Github zu finden.

          Wir sind stets offen für Ihre Anregungen und Ideen, jede Hilfe ist willkommen.

  },
  thx: {
    question: 'Danke!',
    answer:

          An dieser Stelle möchten wir uns ganz herzlich bei Wikimedia,
        der Online-Enzyklopädie Wikipedia.org und seinen vielen freiwilligen Mitarbeitern
        für das größte Lexikon der Welt bedanken! Sie alle haben die Welt der Lexika in das 21. jahrhundert katapultiert und der Menschheit damit einen unschätzbaren Dienst erwiesen.

          Weiterhin bedanken wir uns sehr bei Wolfram Kriesing
        für die Kartenanwendung auf der "Orte"-Seite, unzählige andere Hilfestellungen rund um die Webprogrammierung
        und die generelle Unterstützung des Projektes.

  }
};

export default class AboutComponent extends React.Component {

  constructor() {
    super();
    this.state = {visibleSection: ''};
  }

  render() {
    const {appUrl} = this.props;

    const toggleSection = name => this.state.visibleSection === name ? this.setState({visibleSection: ''}) : this.setState({visibleSection: name});
    const classNames = sectionName => this.state.visibleSection === sectionName ? 'answer visible' : 'answer hidden';
    const toggleOnClick = name => toggleSection.bind(null, name);

    return (

Wir über uns

Ohne Idee keine Entwicklung

          <Question which="what" toggleOnClick={toggleOnClick} classNames={classNames} />
          <Question which="who" toggleOnClick={toggleOnClick} classNames={classNames} />
          <Question which="license" toggleOnClick={toggleOnClick} classNames={classNames} />
          <Question which="future" toggleOnClick={toggleOnClick} classNames={classNames} />
          <Question which="contribute" toggleOnClick={toggleOnClick} classNames={classNames} />
          <Question which="thx" toggleOnClick={toggleOnClick} classNames={classNames} />

    )
  }
}

class Question {

  render() {
    const {toggleOnClick, classNames, which} = this.props;
    const {question, answer} = questions[which];

    return (

         {' ' + question}

{answer}

    );

  }

}<commit_msg>Link to my twitter.<commit_after>import React from 'react';

const questions = {
  what: {
    question: 'Was ist CosmoWiki.de überhaupt?',
    answer:

          CosmoWiki.de ist ein nichtkommerzielles Projekt zur Verbreitung von Wissen über die Bereiche Astronomie und Raumfahrt.

          Auf Plattformen wie z.B. Wikipedia existiert ein gewaltiger Wissensschatz, der von Enthusiasten mit größter Sorgfalt für jedermann erstellt und gepflegt wird.
          Doch warum sollte dieser phantastische Speicher nicht über seine eigentlichen Grenzen hinaus genutzt werden?

          Wir recherchieren unzählige Informationen aus Wikipedia und anderen Quellen, sammeln, veknüpfen und bereiten sie hier in möglichst übersichtlicher Weise auf.
          Cosmowiki.de ist also im Grunde ein Hybride aus Enzyklopädie und Aggregator - ein zentraler Platz im Netz,
          an dem der Nutzer zwei der faszinierendsten Gebiete aus Wissenschaft und Technik auf neue Weise entdecken kann.

  },
  who: {
    question: 'Wem nützt CosmoWiki.de, für wen wurde es geschaffen?',
    answer:

          CosmoWiki.de dient uns allen - interessierten Laien ebenso wie begeisterten Amateuren und allen anderen Space-Fans.
          Jeder Nutzer kann hier frei das gewaltige Universum der Astronomie und Raumfahrt unter einem Dach entdecken, die Geschichte dieser zwei wohl bedeutendsten Bereiche menschlichen Schaffens
          erkunden und zielgerichtet Informationen über Personen, Orte oder Objekte finden.

          Selbst sind wir natürlich auch fasziniert von allem, was mit dem Weltall zu tun hat. So lautet unser Motto: Nutzer arbeiten für Nutzer!

  },
  license: {
    question: 'Darf ich Inhalte von CosmoWiki.de verwenden? Unter welcher Lizenz steht CosmoWiki.de?',
    answer:

          Alle Inhalte von CosmoWiki.de und die von Wikipedia eingebundenen Inhalte stehen unter der
           Creative-Commons-Lizenz Attribution-ShareAlike 3.0 Unported (CC-by-sa-3.0), wenn nichts anderes ausgewiesen wird.

          Gemäß den Bestimmungen der von Wikipedia verwendeten Lizenz
           Creative-Commons-Lizenz Attribution-ShareAlike 3.0 Unported (CC-by-sa-3.0) weisen wir darauf hin,
          dass CosmoWiki.de Artikel oder Teile von Artikeln von Wikipedia verwendet und einbindet.
          Dadurch steht CosmoWiki.de ebenfalls unter der  Creative Commons Lizenz CC BY-SA 3.0.

          Sie dürfen:
Teilen — das Material in jedwedem Format oder Medium vervielfältigen und weiterverbreiten.
Bearbeiten — das Material remixen, verändern und darauf aufbauen
          und zwar für beliebige Zwecke, sogar kommerziell.

          Weitere Informationen zu der verwendeten Lizenz erhalten sie hier:
          http://creativecommons.org/licenses/by-sa/3.0/de/

  },
  future: {
    question: 'Wie geht es weiter? Wie sieht die Zukunft von CosmoWiki.de aus?',
    answer:

          Dieses Projekt wird nie fertiggestellt sein, da sich auch Astronomie und Raumfahrt permanent weiterentwickeln. Unsere Datenbank wächst ständig um neue Inhalte an,
          bestehende Einträge werden um interessante Fakten ergänzt. Zusätzlich wird auch die Seite selbst weiterentwickelt, neue Funktionen werden das Nutzererlebnis verbessern.
          Wir hoffen auch, CosmoWiki.de bald auch in anderen Sprachen anbieten zu können.

          Die Community ist das Zentrum dieser Seite. Wir setzen auf den Enthusiasmus von Amateuren genauso wie auf die Fachkenntnisse von Naturwissenschaftlern und Historikern um ein Werk zu schaffen,
          das auch kritischen Analysen standhält.

  },
  contribute: {
    question: 'Wie kann ich helfen CosmoWiki.de zu verbessern?',
    answer:

          Wenn Sie etwas zu CosmoWiki.de beitragen und das Projekt unterstützen möchten, lassen Sie es uns wissen.
          Sie sind Hobby-Astronom oder Professor der Astrophysik, Historiker oder interessierter Laie, Raumfahrt-Begeisterter oder Astronaut, dann
          kontaktieren Sie uns bitte hier.

          Für Software-Entwickler und Programmierer ist CosmoWiki.de auch auf Github zu finden.

          Wir sind stets offen für Ihre Anregungen und Ideen, jede Hilfe ist willkommen.

  },
  thx: {
    question: 'Danke!',
    answer:

          An dieser Stelle möchten wir uns ganz herzlich bei Wikimedia,
        der Online-Enzyklopädie Wikipedia.org und seinen vielen freiwilligen Mitarbeitern
        für das größte Lexikon der Welt bedanken! Sie alle haben die Welt der Lexika in das 21. jahrhundert katapultiert und der Menschheit damit einen unschätzbaren Dienst erwiesen.

          Weiterhin bedanken wir uns sehr bei Wolfram Kriesing
        für die Kartenanwendung auf der "Orte"-Seite, unzählige andere Hilfestellungen rund um die Webprogrammierung
        und die generelle Unterstützung des Projektes.

  }
};

export default class AboutComponent extends React.Component {

  constructor() {
    super();
    this.state = {visibleSection: ''};
  }

  render() {
    const {appUrl} = this.props;

    const toggleSection = name => this.state.visibleSection === name ? this.setState({visibleSection: ''}) : this.setState({visibleSection: name});
    const classNames = sectionName => this.state.visibleSection === sectionName ? 'answer visible' : 'answer hidden';
    const toggleOnClick = name => toggleSection.bind(null, name);

    return (

Wir über uns

Ohne Idee keine Entwicklung

          <Question which="what" toggleOnClick={toggleOnClick} classNames={classNames} />
          <Question which="who" toggleOnClick={toggleOnClick} classNames={classNames} />
          <Question which="license" toggleOnClick={toggleOnClick} classNames={classNames} />
          <Question which="future" toggleOnClick={toggleOnClick} classNames={classNames} />
          <Question which="contribute" toggleOnClick={toggleOnClick} classNames={classNames} />
          <Question which="thx" toggleOnClick={toggleOnClick} classNames={classNames} />

    )
  }
}

class Question {

  render() {
    const {toggleOnClick, classNames, which} = this.props;
    const {question, answer} = questions[which];

    return (

         {' ' + question}

{answer}

    );

  }

}<|endoftext|>


<commit_before>import React from 'react'
import {Provider} from 'react-redux'
import {Router} from 'react-router'
import Top from './Top'
import Header from './Header'
import MyPage from './MyPage.js'
import './style'

const Root = ({children}) =>

    {children}

const routes = [
  {
    path: '/',
    component: Root,
    indexRoute: {
      component: Top
    },
    childRoutes: [
      {
        path: '/mypage',
        component: MyPage
      }
	]
  }
]

const App = ({store, history}) =>
  <Provider store={store}>
    <Router history={history} routes={routes} />
  </Provider>

export default App
<commit_msg>Add route<commit_after>import React from 'react'
import {Provider} from 'react-redux'
import {Router} from 'react-router'
import Top from './Top'
import Header from './Header'
import MyPage from './MyPage.js'
import FavoriteAnimeConfig from './FavoriteAnimeConfig.js'
import './style'

const Root = ({children}) =>

    {children}

const routes = [
  {
    path: '/',
    component: Root,
    indexRoute: {
      component: Top
    },
    childRoutes: [
      {
        path: '/mypage',
        component: MyPage
      }, {
        path: 'favorite-anime-config',
        component: FavoriteAnimeConfig
      }
    ]
  }
]

const App = ({store, history}) =>
  <Provider store={store}>
    <Router history={history} routes={routes} />
  </Provider>

export default App
<|endoftext|>


<commit_before>var registerComponent = require('../core/register-component').registerComponent;
var THREE = require('../../lib/three');

// Used to detect whether light type has changed.
// TODO: use update() diff once that is implemented.
var LIGHT_TYPES = {
  'ambient': 'AmbientLight',
  'directional': 'DirectionalLight',
  'hemisphere': 'HemisphereLight',
  'point': 'PointLight',
  'spot': 'SpotLight'
};

/**
 * Light component.
 *
 * @namespace light
 * @param {number} [angle=PI / 3] - maximum extent of light from its direction,
          in radians. For spot lights.
 * @param {string} [color=#FFF] - light color. For every light.
 * @param {number} [decay=1] - amount the light dims along the distance of the
          light. For point and spot lights.
 * @param {number} [exponent=10.0] - rapidity of falloff of light from its
          target direction. For spot lights.
 * @param {string} [groundColor=#FFF] - ground light color. For hemisphere
          lights.
 * @param {number} [intensity=1.0] - light strength. For every light except
          ambient.
 * @param {string} [type=directional] - light type (ambient, directional,
          hemisphere, point, spot).
 */
module.exports.Component = registerComponent('light', {
  defaults: {
    value: {
      angle: Math.PI / 3,
      color: '#FFF',
      groundColor: '#FFF',
      decay: 1,
      distance: 0.0,
      exponent: 10.0,
      intensity: 1.0,
      type: 'directional'
    }
  },

  /**
   * Notifies scene a light has been added to remove default lighting.
   */
  init: {
    value: function () {
      var el = this.el;
      this.light = null;
      el.sceneEl.registerLight(el);
    }
  },

  update: {
    value: function () {
      var data = this.data;
      var el = this.el;
      var light = this.light;

      // Existing light.
      if (light) {
        // Light type has changed. Recreate light.
        if (LIGHT_TYPES[data.type] !== light.type) {
          var newLight = this.getLight();
          el.object3D.remove(light);
          el.object3D.add(newLight);
          this.light = newLight;
          return;
        }
        // Light type has not changed. Update light.
        Object.keys(this.defaults).forEach(function (key) {
          var value = data[key];
          if (['color', 'groundColor'].indexOf(key) !== -1) {
            value = new THREE.Color(value);
          }
          light[key] = value;
        });
        return;
      }

      // No light yet. Create and add light.
      this.light = this.getLight();
      el.object3D.add(this.light);
    }
  },

  /**
   * Remove light on remove (callback).
   */
  remove: {
    value: function () {
      if (this.light) { this.el.object3D.remove(this.light); }
    }
  },

  /**
   * Creates a new three.js light object given the current attributes of the
   * component.
   *
   * @namespace light
   */
  getLight: {
    value: function () {
      var data = this.data;
      var color = new THREE.Color(data.color).getHex();
      var intensity = data.intensity;
      var type = data.type;

      if (type) {
        type = type.toLowerCase();
      }
      switch (type) {
        case 'ambient': {
          return new THREE.AmbientLight(color);
        }
        case 'directional': {
          return new THREE.DirectionalLight(color, intensity);
        }
        case 'hemisphere': {
          return new THREE.HemisphereLight(
            color, this.data.groundColor, intensity);
        }
        case 'point': {
          return new THREE.PointLight(color, intensity, data.distance,
                                      data.decay);
        }
        case 'spot': {
          return new THREE.SpotLight(color, intensity, data.distance,
                                     data.angle, data.exponent, data.decay);
        }
        default: {
          return new THREE.DirectionalLight(color, intensity);
        }
      }
    }
  }
});
<commit_msg>use diffing on light component<commit_after>var diff = require('../utils').diff;
var debug = require('../utils/debug');
var registerComponent = require('../core/register-component').registerComponent;
var THREE = require('../../lib/three');

var warn = debug('components:light:warn');

/**
 * Light component.
 *
 * @namespace light
 * @param {number} [angle=PI / 3] - maximum extent of light from its direction,
          in radians. For spot lights.
 * @param {string} [color=#FFF] - light color. For every light.
 * @param {number} [decay=1] - amount the light dims along the distance of the
          light. For point and spot lights.
 * @param {number} [exponent=10.0] - rapidity of falloff of light from its
          target direction. For spot lights.
 * @param {string} [groundColor=#FFF] - ground light color. For hemisphere
          lights.
 * @param {number} [intensity=1.0] - light strength. For every light except
          ambient.
 * @param {string} [type=directional] - light type (ambient, directional,
          hemisphere, point, spot).
 */
module.exports.Component = registerComponent('light', {
  defaults: {
    value: {
      angle: Math.PI / 3,
      color: '#FFF',
      groundColor: '#FFF',
      decay: 1,
      distance: 0.0,
      exponent: 10.0,
      intensity: 1.0,
      type: 'directional'
    }
  },

  /**
   * Notifies scene a light has been added to remove default lighting.
   */
  init: {
    value: function () {
      var el = this.el;
      this.light = null;
      el.sceneEl.registerLight(el);
    }
  },

  /**
   * (Re)create or update light.
   */
  update: {
    value: function (oldData) {
      var data = this.data;
      var diffData = diff(data, oldData || {});
      var el = this.el;
      var light = this.light;

      // Existing light.
      if (light) {
        // Light type has changed. Recreate light.
        if ('type' in diffData) {
          var newLight = getLight(data);
          el.object3D.remove(light);
          el.object3D.add(newLight);
          this.light = newLight;
          return;
        }
        // Light type has not changed. Update light.
        Object.keys(diffData).forEach(function (key) {
          var value = data[key];
          if (['color', 'groundColor'].indexOf(key) !== -1) {
            value = new THREE.Color(value);
          }
          light[key] = value;
        });
        return;
      }

      // No light yet. Create and add light.
      this.light = getLight(data);
      el.object3D.add(this.light);
    }
  },

  /**
   * Remove light on remove (callback).
   */
  remove: {
    value: function () {
      if (this.light) { this.el.object3D.remove(this.light); }
    }
  }
});

/**
 * Creates a new three.js light object given data object defining the light.
 *
 * @param {object} data
 */
function getLight (data) {
  var angle = data.angle;
  var color = new THREE.Color(data.color).getHex();
  var decay = data.decay;
  var distance = data.distance;
  var groundColor = new THREE.Color(data.groundColor).getHex();
  var intensity = data.intensity;
  var type = data.type || '';

  switch (type.toLowerCase()) {
    case 'ambient': {
      return new THREE.AmbientLight(color);
    }
    case 'directional': {
      return new THREE.DirectionalLight(color, intensity);
    }
    case 'hemisphere': {
      return new THREE.HemisphereLight(color, groundColor, intensity);
    }
    case 'point': {
      return new THREE.PointLight(color, intensity, distance, decay);
    }
    case 'spot': {
      return new THREE.SpotLight(color, intensity, distance, angle, data.exponent, decay);
    }
    default: {
      warn('%s is not a valid light type. ' +
           'Choose from ambient, directional, hemisphere, point, spot.', type);
      return new THREE.DirectionalLight(color, intensity);
    }
  }
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name         ConCon Rare List Maker
// @namespace    http://www.TakeAsh.net/
// @version      0.1.201511242330
// @description  make ConCon Rare List source
// @author       take-ash
// @match        http://c4.concon-collector.com/help/alllist
// @grant        none
// ==/UserScript==
/* jshint -W097 */
'use strict';

(function() {
    var forceName = ['－', '炎', '光', '風'];
    var types = ['狐魂生成', 'ショップ', '初期開始時', 'シリアル', '換毛', 'イベント', '生成装置'];
    var bgColors = ['BGCOLOR(#7F7F7F):', 'BGCOLOR(#580000):', 'BGCOLOR(#505000):', 'BGCOLOR(#004000):'];
    var viewUrlBase = 'http://c4.concon-collector.com/view/default/';
    var rareListBasePage = 'レア狐魂一覧';
    var numOfLotGroup = 10; /**< 1ページにまとめる弾数 */
    var numOfFurBasePage = '換毛が多い狐魂';
    var numOfFurMin = 3; /**< 最低換毛数 */
    var tableHeader = '|~名前|~勢力|~元|~換毛数|~換毛|h';
    var br = '
\n';

    var lastModified = br + 'データ更新日: ' + new Date(window.document.lastModified)
        .toLocaleString() + br;
    var textarea = document.getElementsByTagName('textarea')[0];
    var csv = textarea.textContent || textarea.innerText;
    var lines = csv.split(/\n/);
    var fields = lines.shift()
        .replace(/"/g, '')
        .split(',');
    var rares = {};
    for (var i = 0, line; line = lines[i]; ++i) {
        var rareCC = new RareCC(line);
        if (rares[rareCC.same_id]) {
            rares[rareCC.same_id].ids.push(rareCC.id);
        } else {
            rares[rareCC.same_id] = rareCC;
        }
    }
    var lots = {};
    for (var id in rares) {
        var rareCC = rares[id];
        if (!lots[rareCC.lot_id]) {
            lots[rareCC.lot_id] = {};
        }
        if (!lots[rareCC.lot_id][rareCC.rarity]) {
            lots[rareCC.lot_id][rareCC.rarity] = {};
        }
        if (!lots[rareCC.lot_id][rareCC.rarity][rareCC.id]) {
            lots[rareCC.lot_id][rareCC.rarity][rareCC.id] = rareCC;
        }
    }
    var lotGroups = [];
    var groupTitles = [];
    for (var lot in lots) {
        var index = lot <= 0 ?
            0 :
            Math.floor((lot - 1) / numOfLotGroup) + 1;
        var lotHeader = lot <= 0 ?
            types[-lot] :
            '第' + lot + '弾';
        if (!lotGroups[index]) {
            lotGroups[index] = '- [[' + rareListBasePage + ']]' + br + '#contents' + br + br;
            groupTitles[index] = [];
        }
        lotGroups[index] += '* ' + lotHeader + br;
        groupTitles[index].push(lotHeader);
        for (var rarity in lots[lot]) {
            lotGroups[index] += '- レア度' + rarity + br;
            lotGroups[index] += tableHeader + br;
            for (var id in lots[lot][rarity]) {
                lotGroups[index] += lots[lot][rarity][id].ToTableItem();
            }
            lotGroups[index] += br;
        }
    }

    var indexPage = '';
    PrintNewWin(lotGroups[0]);
    indexPage += '- [[' + groupTitles[0] + '>' + rareListBasePage + '/0' + ']]' + br;
    for (var i = 1, group; group = lotGroups[i]; ++i) {
        PrintNewWin(group);
        var first = groupTitles[i][0];
        var last = groupTitles[i][groupTitles[i].length - 1];
        var title = first == last ?
            first :
            first + ' - ' + last;
        indexPage += '- [[' + title + '>' + rareListBasePage + '/' + i + ']]' + br;
    }
    indexPage += '- [[' + numOfFurBasePage + ']]' + br;
    PrintNewWin(indexPage);

    var furSortedRares = [];
    for (var id in rares) {
        if (rares[id].ids.length < numOfFurMin) {
            continue;
        }
        furSortedRares.push(rares[id]);
    }
    furSortedRares.sort(function(a, b) {
        return b.ids.length - a.ids.length;
    });
    var furSortedPage = '';
    furSortedPage += '- [[' + rareListBasePage + ']]' + br + '#contents' + br + br;
    furSortedPage += tableHeader + br;
    for (var i = 0, rare; rare = furSortedRares[i]; ++i) {
        furSortedPage += rare.ToTableItem();
    }
    PrintNewWin(furSortedPage);

    function RareCC(line) {
        var items = ('",' + line + ',"')
            .split(/","/);
        for (var i = 0, field; field = fields[i]; ++i) {
            this[field] = items[i + 1];
        }
        if (this.lot_id == 0) {
            this.lot_id = -this.type;
        }
        this.ids = [];
        this.ToTableItem = function() {
            var bgColor = bgColors[this.force_id];
            var furs = [];
            for (var i = 0, id; id = this.ids[i]; ++i) {
                furs.push('[[' + id + '>' + viewUrlBase + id + ']]');
            }
            var fur = furs.join(', ');
            return '|COLOR(white):' + bgColor + this.title + this.name +
                '|COLOR(white):' + bgColor + forceName[this.force_id] +
                '|' + bgColor + '[[' + this.id + '>' + viewUrlBase + this.id + ']]' +
                '|COLOR(white):' + bgColor + (this.ids.length ? this.ids.length : '') +
                '|' + bgColor + fur +
                '|' + br;
        };
    }

    function PrintNewWin(text) {
        var docNew = window.open('', '_blank')
            .document;
        docNew.open('text/html');
        docNew.write('\n' + text + lastModified + '');
        docNew.close();
    }
})();

// EOF
<commit_msg>version 更新<commit_after>// ==UserScript==
// @name         ConCon Rare List Maker
// @namespace    http://www.TakeAsh.net/
// @version      0.1.201511250000
// @description  make ConCon Rare List source
// @author       take-ash
// @match        http://c4.concon-collector.com/help/alllist
// @grant        none
// ==/UserScript==
/* jshint -W097 */
'use strict';

(function() {
    var forceName = ['－', '炎', '光', '風'];
    var types = ['狐魂生成', 'ショップ', '初期開始時', 'シリアル', '換毛', 'イベント', '生成装置'];
    var bgColors = ['BGCOLOR(#7F7F7F):', 'BGCOLOR(#580000):', 'BGCOLOR(#505000):', 'BGCOLOR(#004000):'];
    var viewUrlBase = 'http://c4.concon-collector.com/view/default/';
    var rareListBasePage = 'レア狐魂一覧';
    var numOfLotGroup = 10; /**< 1ページにまとめる弾数 */
    var numOfFurBasePage = '換毛が多い狐魂';
    var numOfFurMin = 3; /**< 最低換毛数 */
    var tableHeader = '|~名前|~勢力|~元|~換毛数|~換毛|h';
    var br = '
\n';

    var lastModified = br + 'データ更新日: ' + new Date(window.document.lastModified)
        .toLocaleString() + br;
    var textarea = document.getElementsByTagName('textarea')[0];
    var csv = textarea.textContent || textarea.innerText;
    var lines = csv.split(/\n/);
    var fields = lines.shift()
        .replace(/"/g, '')
        .split(',');
    var rares = {};
    for (var i = 0, line; line = lines[i]; ++i) {
        var rareCC = new RareCC(line);
        if (rares[rareCC.same_id]) {
            rares[rareCC.same_id].ids.push(rareCC.id);
        } else {
            rares[rareCC.same_id] = rareCC;
        }
    }
    var lots = {};
    for (var id in rares) {
        var rareCC = rares[id];
        if (!lots[rareCC.lot_id]) {
            lots[rareCC.lot_id] = {};
        }
        if (!lots[rareCC.lot_id][rareCC.rarity]) {
            lots[rareCC.lot_id][rareCC.rarity] = {};
        }
        if (!lots[rareCC.lot_id][rareCC.rarity][rareCC.id]) {
            lots[rareCC.lot_id][rareCC.rarity][rareCC.id] = rareCC;
        }
    }
    var lotGroups = [];
    var groupTitles = [];
    for (var lot in lots) {
        var index = lot <= 0 ?
            0 :
            Math.floor((lot - 1) / numOfLotGroup) + 1;
        var lotHeader = lot <= 0 ?
            types[-lot] :
            '第' + lot + '弾';
        if (!lotGroups[index]) {
            lotGroups[index] = '- [[' + rareListBasePage + ']]' + br + '#contents' + br + br;
            groupTitles[index] = [];
        }
        lotGroups[index] += '* ' + lotHeader + br;
        groupTitles[index].push(lotHeader);
        for (var rarity in lots[lot]) {
            lotGroups[index] += '- レア度' + rarity + br;
            lotGroups[index] += tableHeader + br;
            for (var id in lots[lot][rarity]) {
                lotGroups[index] += lots[lot][rarity][id].ToTableItem();
            }
            lotGroups[index] += br;
        }
    }

    var indexPage = '';
    PrintNewWin(lotGroups[0]);
    indexPage += '- [[' + groupTitles[0] + '>' + rareListBasePage + '/0' + ']]' + br;
    for (var i = 1, group; group = lotGroups[i]; ++i) {
        PrintNewWin(group);
        var first = groupTitles[i][0];
        var last = groupTitles[i][groupTitles[i].length - 1];
        var title = first == last ?
            first :
            first + ' - ' + last;
        indexPage += '- [[' + title + '>' + rareListBasePage + '/' + i + ']]' + br;
    }
    indexPage += '- [[' + numOfFurBasePage + ']]' + br;
    PrintNewWin(indexPage);

    var furSortedRares = [];
    for (var id in rares) {
        if (rares[id].ids.length < numOfFurMin) {
            continue;
        }
        furSortedRares.push(rares[id]);
    }
    furSortedRares.sort(function(a, b) {
        return b.ids.length - a.ids.length;
    });
    var furSortedPage = '';
    furSortedPage += '- [[' + rareListBasePage + ']]' + br + '#contents' + br + br;
    furSortedPage += tableHeader + br;
    for (var i = 0, rare; rare = furSortedRares[i]; ++i) {
        furSortedPage += rare.ToTableItem();
    }
    PrintNewWin(furSortedPage);

    function RareCC(line) {
        var items = ('",' + line + ',"')
            .split(/","/);
        for (var i = 0, field; field = fields[i]; ++i) {
            this[field] = items[i + 1];
        }
        if (this.lot_id == 0) {
            this.lot_id = -this.type;
        }
        this.ids = [];
        this.ToTableItem = function() {
            var bgColor = bgColors[this.force_id];
            var furs = [];
            for (var i = 0, id; id = this.ids[i]; ++i) {
                furs.push('[[' + id + '>' + viewUrlBase + id + ']]');
            }
            var fur = furs.join(', ');
            return '|COLOR(white):' + bgColor + this.title + this.name +
                '|COLOR(white):' + bgColor + forceName[this.force_id] +
                '|' + bgColor + '[[' + this.id + '>' + viewUrlBase + this.id + ']]' +
                '|COLOR(white):' + bgColor + (this.ids.length ? this.ids.length : '') +
                '|' + bgColor + fur +
                '|' + br;
        };
    }

    function PrintNewWin(text) {
        var docNew = window.open('', '_blank')
            .document;
        docNew.open('text/html');
        docNew.write('\n' + text + lastModified + '');
        docNew.close();
    }
})();

// EOF
<|endoftext|>


<commit_before>$(function() {
	$('body').on('change', '.filter', function() {
		var originalFilter = $(this);
		$(originalFilter.attr('data-filter-container')).children('.filterable').each(function(index, filterable) {
			var filters = $('body').find(".filter[data-filter-container='" + originalFilter.attr('data-filter-container') + "']");
			var hide = false;
			$.each(filters, function(i, element) {
				var filter = $(element);
				var filterVal = $(filterable).attr('data-' + $(filter).attr('data-filter')).toLowerCase();
				if (filter.is('input')) {
					if (filter.is('input[type=checkbox]')) {
						if (filterVal !== filter.is(':checked').toString()) {
							hide = true;
						}
					}else {
						if (filterVal.indexOf(filter.val().toLowerCase()) === -1 && filter.val() !== '') {
							hide = true;
						}
					}
				}else if (filter.is('select')) {
					if (filter.children(':selected').is('option[data-filter-ignore]')) {
						return;
					}
					if (filter.children(':selected').is('option[data-filter-value]')) {
						if (filterVal !== filter.children(':selected').attr('data-filter-value').toLowerCase()) {
							hide = true;
						}
					}else {
						if (filterVal !== filter.children(':selected').html().toLowerCase()) {
							hide = true;
						}
					}
				}
			});
			if (hide) {
				$(filterable).fadeOut();
			}else {
				$(filterable).fadeIn();
			}
		});
	});

	$('body').on('click', '.reset-filter', function() {
		$('.filter').each(function(index, element) {
			if ($(element).is('input')) {
				$(element).val('');
			}else if ($(element).is('select')) {
				$(element).prop('selectedIndex', 0);
			}
		});
		$('.filterable').fadeIn();
	});
});<commit_msg>Allow one filter to affect multiple containers and search for filterables with find instead of children<commit_after>$(function() {
	$('body').on('change', '.filter', function() {
		var originalFilter = $(this);
		$(originalFilter.attr('data-filter-container')).each(function(i, container) {
			$(container).find('.filterable').each(function(index, filterable) {
				var filters = $('body').find(".filter[data-filter-container='" + originalFilter.attr('data-filter-container') + "']");
				var hide = false;
				$.each(filters, function(i, element) {
					var filter = $(element);
					var filterVal = $(filterable).attr('data-' + $(filter).attr('data-filter')).toLowerCase();
					if (filter.is('input')) {
						if (filter.is('input[type=checkbox]')) {
							if (filterVal !== filter.is(':checked').toString()) {
								hide = true;
							}
						}else {
							if (filterVal.indexOf(filter.val().toLowerCase()) === -1 && filter.val() !== '') {
								hide = true;
							}
						}
					}else if (filter.is('select')) {
						if (filter.children(':selected').is('option[data-filter-ignore]')) {
							return;
						}
						if (filter.children(':selected').is('option[data-filter-value]')) {
							if (filterVal !== filter.children(':selected').attr('data-filter-value').toLowerCase()) {
								hide = true;
							}
						}else {
							if (filterVal !== filter.children(':selected').html().toLowerCase()) {
								hide = true;
							}
						}
					}
				});
				if (hide) {
					$(filterable).fadeOut();
				}else {
					$(filterable).fadeIn();
				}
			});
		});
	});

	$('body').on('click', '.reset-filter', function() {
		$('.filter').each(function(index, element) {
			if ($(element).is('input')) {
				$(element).val('');
			}else if ($(element).is('select')) {
				$(element).prop('selectedIndex', 0);
			}
		});
		$('.filterable').fadeIn();
	});
});<|endoftext|>


<commit_before>module.exports = {
    files: [
        "src",
        "tools",
        "config",
        "README.md",
        ".eslintrc.js",
        ".eslintignore",
        ".stylelintrc.js",
        ".gitignore",
    ],
    options: [
        {
            type: 'input',
            name: 'webserver',
            message: 'html url(//localhost:9000/)',
            default: "//localhost:9000/",
        },
        {
            type: 'input',
            name: 'cdn',
            message: 'cdn url(//localhost:8000/)',
            default: "//localhost:8000/",
        },
        {
            type: 'input',
            name: 'port',
            message: 'development server port(9000)',
            default: '9000',
        },
        {
            type: 'input',
            name: 'route',
            message: 'development server directory(/news/)',
            default: '/news/',
        }
    ]
};<commit_msg>improve steamer config<commit_after>module.exports = {
    files: [
        "src",
        "tools",
        "config",
        "README.md",
        ".eslintrc.js",
        ".eslintignore",
        ".stylelintrc.js",
        ".gitignore",
        ".babelrc",
    ],
    options: [
        {
            type: 'input',
            name: 'webserver',
            message: 'html url(//localhost:9000/)',
            default: "//localhost:9000/",
        },
        {
            type: 'input',
            name: 'cdn',
            message: 'cdn url(//localhost:8000/)',
            default: "//localhost:8000/",
        },
        {
            type: 'input',
            name: 'port',
            message: 'development server port(9000)',
            default: '9000',
        },
        {
            type: 'input',
            name: 'route',
            message: 'development server directory(/news/)',
            default: '/news/',
        }
    ]
};<|endoftext|>


<commit_before>import $ from 'jquery';

var url = window.location.href;
var customCSSParam = url.match(/(custom_css=(.+))&/);
var param = '';
var file = '';
var loadedCss = '';

if (customCSSParam) {
    param = customCSSParam[1];
    file = customCSSParam[2].replace(/%2F/g, '/').replace(/%3D/g, '=');
    if (loadedCss !== file) {
        $('head').append('<link rel="stylesheet" type="text/css" href="https://' + file + '">');
        loadedCss = file;
    }
}

<commit_msg>Adjusts custom_css pattern to find every occurence in the url<commit_after>import $ from 'jquery';

var url = window.location.href;
var customCSSParam = url.match(/(custom_css=(.+))/);
var param = '';
var file = '';
var loadedCss = '';

if (customCSSParam) {
    param = customCSSParam[1];
    file = customCSSParam[2].replace(/%2F/g, '/').replace(/%3D/g, '=');
    if (loadedCss !== file) {
        $('head').append('<link rel="stylesheet" type="text/css" href="https://' + file + '">');
        loadedCss = file;
    }
}

<|endoftext|>


<commit_before>import { createSelector, createStructuredSelector } from 'reselect';
import moment from 'moment';
import { format } from 'd3-format';
import isEmpty from 'lodash/isEmpty';
import sortBy from 'lodash/sortBy';
import groupBy from 'lodash/groupBy';
import max from 'lodash/max';
import maxBy from 'lodash/maxBy';
import min from 'lodash/min';
import findLastIndex from 'lodash/findLastIndex';

import { getColorPalette } from 'utils/data';
import {
  getCumulativeStatsData,
  getDatesData,
  getPeriodVariance,
  getChartConfig
} from 'components/widgets/utils/data';

const getAlerts = state => state.data && state.data.alerts;
const getLatest = state => state.data && state.data.latest;
const getColors = state => state.colors || null;
const getCompareYear = state => state.settings.compareYear || null;
const getDataset = state => state.settings.dataset || null;
const getStartIndex = state => state.settings.startIndex || 0;
const getEndIndex = state => state.settings.endIndex || null;
const getSentences = state => state.sentence || null;
const getLocationName = state => state.locationLabel;

export const getData = createSelector(
  [getAlerts, getLatest],
  (data, latest) => {
    if (!data || isEmpty(data)) return null;
    const parsedData = data.map(d => ({
      ...d,
      count: d.alert__count,
      week: parseInt(d.alert__week, 10),
      year: parseInt(d.alert__year, 10)
    }));
    const groupedByYear = groupBy(sortBy(parsedData, ['year', 'week']), 'year');
    const hasAlertsByYears = Object.values(groupedByYear).reduce(
      (acc, next) => {
        const { year } = next[0];
        return {
          ...acc,
          [year]: next.some(item => item.alerts > 0)
        };
      },
      {}
    );

    const dataYears = Object.keys(hasAlertsByYears).filter(
      key => hasAlertsByYears[key] === true
    );
    const minYear = Math.min(...dataYears.map(el => parseInt(el, 10)));
    const startYear =
      minYear === moment().year() ? moment().year() - 1 : minYear;

    const years = [];
    const latestWeek = moment(latest);
    const lastWeek = {
      isoWeek: latestWeek.isoWeek(),
      year: latestWeek.year()
    };

    for (let i = startYear; i <= lastWeek.year; i += 1) {
      years.push(i);
    }

    const yearLengths = {};
    years.forEach(y => {
      if (moment(`${y}-12-31`).isoWeek() === 1) {
        yearLengths[y] = moment(`${y}-12-31`)
          .subtract('week', 1)
          .isoWeek();
      } else {
        yearLengths[y] = moment(`${y}-12-31`).isoWeek();
      }
    });

    const zeroFilledData = [];

    years.forEach(d => {
      let acc = 0;
      const yearDataByWeek = groupBy(groupedByYear[d], 'week');
      for (let i = 1; i <= yearLengths[d]; i += 1) {
        const weekData = yearDataByWeek[i]
          ? yearDataByWeek[i][0]
          : { count: 0, week: i, year: parseInt(d, 10) };
        acc += weekData.count;
        if (parseInt(d, 10) === lastWeek.year && i > lastWeek.isoWeek) {
          zeroFilledData.push({
            ...weekData,
            count: null
          });
        } else {
          zeroFilledData.push({
            ...weekData,
            count: acc
          });
        }
      }
    });
    return zeroFilledData;
  }
);

export const getStats = createSelector([getData], data => {
  if (!data) return null;
  return getCumulativeStatsData(data);
});

export const getDates = createSelector([getStats], data => {
  if (!data) return null;
  return getDatesData(data);
});

export const getMaxMinDates = createSelector(
  [getData, getDates],
  (data, currentData) => {
    if (!data || !currentData) return {};
    const minYear = min(data.map(d => d.year));
    const maxYear = max(data.map(d => d.year));

    return {
      min: minYear,
      max: maxYear
    };
  }
);

export const parseData = createSelector(
  [getData, getDates, getMaxMinDates, getCompareYear],
  (data, currentData, maxminYear, compareYears) => {
    if (!data || !currentData) return null;

    return currentData.map(d => {
      const yearDifference = maxminYear.max - d.year;
      const week = d.week;

      if (compareYears) {
        const compareYearData = compareYears.reduce((acc, year) => {
          const compareWeek = data.find(
            dt => dt.year === year - yearDifference && dt.week === week
          );

          return {
            ...acc,
            [year]: compareWeek ? compareWeek.count : null
          };
        }, {});

        return {
          ...d,
          ...compareYearData
        };
      }

      return d;
    });
  }
);

export const parseBrushedData = createSelector(
  [parseData, getStartIndex, getEndIndex],
  (data, startIndex, endIndex) => {
    if (!data) return null;

    const start = startIndex || 0;
    const end = endIndex || data.length - 1;

    return data.slice(start, end + 1);
  }
);

export const getLegend = createSelector(
  [parseBrushedData, getColors, getCompareYear, getMaxMinDates],
  (data, colors, compareYears, maxminYear) => {
    if (!data) return {};

    const end = data[data.length - 1];
    const yearsArray =
      compareYears && compareYears.filter(y => y !== maxminYear.max).sort();
    return {
      current: {
        label: `${moment(end.date).format('YYYY')}`,
        color: colors.main
      },
      ...(yearsArray && {
        compare: {
          label:
            yearsArray.length > 1
              ? `${yearsArray[0]}-${yearsArray[yearsArray.length - 1]}`
              : `${yearsArray}`,
          color: '#49b5e3'
        }
      }),
      average: {
        label: 'Average Range',
        color: 'rgba(85,85,85, 0.15)'
      },
      unusual: {
        label: 'Above/Below Average Range',
        color: 'rgba(85,85,85, 0.25)'
      }
    };
  }
);

export const parseConfig = createSelector(
  [
    getDates,
    getLegend,
    getColors,
    getLatest,
    getMaxMinDates,
    getCompareYear,
    getDataset,
    getStartIndex,
    getEndIndex
  ],
  (
    currentData,
    legend,
    colors,
    latest,
    maxminYear,
    compareYears,
    dataset,
    startIndex,
    endIndex
  ) => {
    if (!currentData) return null;

    const tooltip = [
      {
        label: 'Fire alerts'
      },
      {
        key: 'count',
        labelKey: 'date',
        labelFormat: value => moment(value).format('YYYY-MM-DD'),
        unit: ` ${dataset} alerts`,
        color: colors.main,
        nullValue: 'No data available',
        unitFormat: value =>
          (Number.isInteger(value) ? format(',')(value) : value)
      }
    ];
    const compareYearsLines = {};
    if (compareYears && compareYears.length > 0) {
      const colorRange = getColorPalette(
        colors.compareYearRamp,
        compareYears.length
      );
      const yearsArray = compareYears
        .filter(y => y !== maxminYear.max)
        .sort()
        .reverse();
      yearsArray.forEach((year, i) => {
        tooltip.push({
          key: year,
          labelKey: 'date',
          labelFormat: value => {
            const date = moment(value);
            const yearDifference = maxminYear.max - date.year();
            date.set('year', year - yearDifference);

            return date.format('YYYY-MM-DD');
          },
          unit: ` ${dataset} alerts`,
          color: compareYears.length === 1 ? colors.compareYear : colorRange[i],
          nullValue: 'No data available',
          unitFormat: value =>
            (Number.isInteger(value) ? format(',')(value) : value)
        });
        compareYearsLines[year] = {
          stroke:
            compareYears.length === 1 ? colors.compareYear : colorRange[i],
          isAnimationActive: false
        };
      });
    }
    const presentDayIndex = findLastIndex(
      currentData,
      d => typeof d.count === 'number'
    );
    const presentDay = currentData[presentDayIndex].date;
    return {
      ...getChartConfig(colors, moment(latest), compareYearsLines),
      xAxis: {
        tickCount: 12,
        interval: 4,
        tickFormatter: t => moment(t).format('MMM'),
        ...(typeof endIndex === 'number' &&
          typeof startIndex === 'number' &&
          endIndex - startIndex < 12 && {
          tickCount: 5,
          interval: 0,
          tickFormatter: t => moment(t).format('MMM-DD')
        })
      },
      legend,
      tooltip,
      referenceLine: {
        x: presentDay,
        stroke: '#CCC',
        strokeWidth: 2,
        strokeDasharray: '20 5',
        label: {
          position: 'top',
          value: 'Latest data',
          fill: '#333',
          fontSize: 11
        }
      },
      brush: {
        width: '100%',
        height: 60,
        margin: {
          top: 0,
          right: 10,
          left: 48,
          bottom: 12
        },
        minimumGap: 4,
        dataKey: 'date',
        startIndex,
        endIndex,
        config: {
          margin: {
            top: 5,
            right: 0,
            left: 42,
            bottom: 20
          },
          yKeys: {
            lines: {
              count: {
                stroke: colors.main,
                isAnimationActive: false
              },
              compareCount: {
                stroke: '#49b5e3',
                isAnimationActive: false
              },
              ...(Object.keys(compareYearsLines).length, compareYearsLines)
            }
          },
          xAxis: {
            hide: true
          },
          yAxis: {
            hide: true
          },
          cartesianGrid: {
            horizontal: false,
            vertical: false
          },
          height: 60
        }
      }
    };
  }
);

export const parseSentence = createSelector(
  [
    getData,
    parseData,
    getColors,
    getSentences,
    getDataset,
    getLocationName,
    getStartIndex,
    getEndIndex
  ],
  (
    raw_data,
    data,
    colors,
    sentence,
    dataset,
    location,
    startIndex
    // endIndex //broken?
  ) => {
    if (!data) return null;

    const start = startIndex;
    const latestYear = maxBy(data, 'year').year;
    const lastDate =
      maxBy(
        data.filter(d => d.year === latestYear && d.count !== null),
        'date'
      ) || {};
    const firstDate = data[start] || {};

    const slicedData = data.filter(
      el => el.date >= firstDate.date && el.date <= lastDate.date
    );
    const variance = getPeriodVariance(slicedData, raw_data);

    const maxWeek = maxBy(raw_data, 'count');
    const maxTotal = maxWeek.count;
    const maxYear = maxWeek.year;
    const total = maxBy(slicedData, 'count').count || 0;

    const colorRange = colors.ramp;
    let statusColor = colorRange[8];
    const { date } = lastDate || {};

    let status = 'unusually low';
    if (variance > 2) {
      status = 'unusually high';
      statusColor = colorRange[0];
    } else if (variance <= 2 && variance > 1) {
      status = 'high';
      statusColor = colorRange[2];
    } else if (variance <= 1 && variance > -1) {
      status = 'average';
      statusColor = colorRange[4];
    } else if (variance <= -1 && variance > -2) {
      status = 'low';
      statusColor = colorRange[6];
    }

    const formattedData = moment(date).format('Do of MMMM YYYY');
    const params = {
      location,
      date: formattedData,
      latestYear,
      dataset_start_year: dataset === 'viirs' ? 2012 : 2001,
      maxYear,
      maxTotal: {
        value: maxTotal ? format(',')(maxTotal) : 0,
        color: colors.main
      },
      dataset: dataset.toUpperCase(),
      count: {
        value: total ? format(',')(total) : 0,
        color: colors.main
      },
      status: {
        value: status,
        color: statusColor
      }
    };
    return { sentence, params };
  }
);

export default createStructuredSelector({
  originalData: parseData,
  data: parseBrushedData,
  config: parseConfig,
  sentence: parseSentence
});
<commit_msg>Fixed crash on empty chart/brush<commit_after>import { createSelector, createStructuredSelector } from 'reselect';
import moment from 'moment';
import { format } from 'd3-format';
import isEmpty from 'lodash/isEmpty';
import sortBy from 'lodash/sortBy';
import groupBy from 'lodash/groupBy';
import max from 'lodash/max';
import maxBy from 'lodash/maxBy';
import min from 'lodash/min';
import findLastIndex from 'lodash/findLastIndex';

import { getColorPalette } from 'utils/data';
import {
  getCumulativeStatsData,
  getDatesData,
  getPeriodVariance,
  getChartConfig
} from 'components/widgets/utils/data';

const getAlerts = state => state.data && state.data.alerts;
const getLatest = state => state.data && state.data.latest;
const getColors = state => state.colors || null;
const getCompareYear = state => state.settings.compareYear || null;
const getDataset = state => state.settings.dataset || null;
const getStartIndex = state => state.settings.startIndex || 0;
const getEndIndex = state => state.settings.endIndex || null;
const getSentences = state => state.sentence || null;
const getLocationName = state => state.locationLabel;

export const getData = createSelector(
  [getAlerts, getLatest],
  (data, latest) => {
    if (!data || isEmpty(data)) return null;
    const parsedData = data.map(d => ({
      ...d,
      count: d.alert__count,
      week: parseInt(d.alert__week, 10),
      year: parseInt(d.alert__year, 10)
    }));
    const groupedByYear = groupBy(sortBy(parsedData, ['year', 'week']), 'year');
    const hasAlertsByYears = Object.values(groupedByYear).reduce(
      (acc, next) => {
        const { year } = next[0];
        return {
          ...acc,
          [year]: next.some(item => item.alerts > 0)
        };
      },
      {}
    );

    const dataYears = Object.keys(hasAlertsByYears).filter(
      key => hasAlertsByYears[key] === true
    );
    const minYear = Math.min(...dataYears.map(el => parseInt(el, 10)));
    const startYear =
      minYear === moment().year() ? moment().year() - 1 : minYear;

    const years = [];
    const latestWeek = moment(latest);
    const lastWeek = {
      isoWeek: latestWeek.isoWeek(),
      year: latestWeek.year()
    };

    for (let i = startYear; i <= lastWeek.year; i += 1) {
      years.push(i);
    }

    const yearLengths = {};
    years.forEach(y => {
      if (moment(`${y}-12-31`).isoWeek() === 1) {
        yearLengths[y] = moment(`${y}-12-31`)
          .subtract('week', 1)
          .isoWeek();
      } else {
        yearLengths[y] = moment(`${y}-12-31`).isoWeek();
      }
    });

    const zeroFilledData = [];

    years.forEach(d => {
      let acc = 0;
      const yearDataByWeek = groupBy(groupedByYear[d], 'week');
      for (let i = 1; i <= yearLengths[d]; i += 1) {
        const weekData = yearDataByWeek[i]
          ? yearDataByWeek[i][0]
          : { count: 0, week: i, year: parseInt(d, 10) };
        acc += weekData.count;
        if (parseInt(d, 10) === lastWeek.year && i > lastWeek.isoWeek) {
          zeroFilledData.push({
            ...weekData,
            count: null
          });
        } else {
          zeroFilledData.push({
            ...weekData,
            count: acc
          });
        }
      }
    });
    return zeroFilledData;
  }
);

export const getStats = createSelector([getData], data => {
  if (!data) return null;
  return getCumulativeStatsData(data);
});

export const getDates = createSelector([getStats], data => {
  if (!data) return null;
  return getDatesData(data);
});

export const getMaxMinDates = createSelector(
  [getData, getDates],
  (data, currentData) => {
    if (!data || !currentData) return {};
    const minYear = min(data.map(d => d.year));
    const maxYear = max(data.map(d => d.year));

    return {
      min: minYear,
      max: maxYear
    };
  }
);

export const parseData = createSelector(
  [getData, getDates, getMaxMinDates, getCompareYear],
  (data, currentData, maxminYear, compareYears) => {
    if (!data || !currentData) return null;

    return currentData.map(d => {
      const yearDifference = maxminYear.max - d.year;
      const week = d.week;

      if (compareYears) {
        const compareYearData = compareYears.reduce((acc, year) => {
          const compareWeek = data.find(
            dt => dt.year === year - yearDifference && dt.week === week
          );

          return {
            ...acc,
            [year]: compareWeek ? compareWeek.count : null
          };
        }, {});

        return {
          ...d,
          ...compareYearData
        };
      }

      return d;
    });
  }
);

export const parseBrushedData = createSelector(
  [parseData, getStartIndex, getEndIndex],
  (data, startIndex, endIndex) => {
    if (!data) return null;

    const start = startIndex || 0;
    const end = endIndex || data.length - 1;

    return data.slice(start, end + 1);
  }
);

export const getLegend = createSelector(
  [parseBrushedData, getColors, getCompareYear, getMaxMinDates],
  (data, colors, compareYears, maxminYear) => {
    if (!data) return {};

    const end = data[data.length - 1];
    const yearsArray =
      compareYears && compareYears.filter(y => y !== maxminYear.max).sort();
    return {
      current: {
        label: `${moment(end.date).format('YYYY')}`,
        color: colors.main
      },
      ...(yearsArray && {
        compare: {
          label:
            yearsArray.length > 1
              ? `${yearsArray[0]}-${yearsArray[yearsArray.length - 1]}`
              : `${yearsArray}`,
          color: '#49b5e3'
        }
      }),
      average: {
        label: 'Average Range',
        color: 'rgba(85,85,85, 0.15)'
      },
      unusual: {
        label: 'Above/Below Average Range',
        color: 'rgba(85,85,85, 0.25)'
      }
    };
  }
);

export const parseConfig = createSelector(
  [
    getDates,
    getLegend,
    getColors,
    getLatest,
    getMaxMinDates,
    getCompareYear,
    getDataset,
    getStartIndex,
    getEndIndex
  ],
  (
    currentData,
    legend,
    colors,
    latest,
    maxminYear,
    compareYears,
    dataset,
    startIndex,
    endIndex
  ) => {
    if (!currentData) return null;

    const tooltip = [
      {
        label: 'Fire alerts'
      },
      {
        key: 'count',
        labelKey: 'date',
        labelFormat: value => moment(value).format('YYYY-MM-DD'),
        unit: ` ${dataset} alerts`,
        color: colors.main,
        nullValue: 'No data available',
        unitFormat: value =>
          (Number.isInteger(value) ? format(',')(value) : value)
      }
    ];
    const compareYearsLines = {};
    if (compareYears && compareYears.length > 0) {
      const colorRange = getColorPalette(
        colors.compareYearRamp,
        compareYears.length
      );
      const yearsArray = compareYears
        .filter(y => y !== maxminYear.max)
        .sort()
        .reverse();
      yearsArray.forEach((year, i) => {
        tooltip.push({
          key: year,
          labelKey: 'date',
          labelFormat: value => {
            const date = moment(value);
            const yearDifference = maxminYear.max - date.year();
            date.set('year', year - yearDifference);

            return date.format('YYYY-MM-DD');
          },
          unit: ` ${dataset} alerts`,
          color: compareYears.length === 1 ? colors.compareYear : colorRange[i],
          nullValue: 'No data available',
          unitFormat: value =>
            (Number.isInteger(value) ? format(',')(value) : value)
        });
        compareYearsLines[year] = {
          stroke:
            compareYears.length === 1 ? colors.compareYear : colorRange[i],
          isAnimationActive: false
        };
      });
    }
    const presentDayIndex = findLastIndex(
      currentData,
      d => typeof d.count === 'number'
    );
    const presentDay = currentData[presentDayIndex].date;
    return {
      ...getChartConfig(colors, moment(latest), compareYearsLines),
      xAxis: {
        tickCount: 12,
        interval: 4,
        tickFormatter: t => moment(t).format('MMM'),
        ...(typeof endIndex === 'number' &&
          typeof startIndex === 'number' &&
          endIndex - startIndex < 12 && {
          tickCount: 5,
          interval: 0,
          tickFormatter: t => moment(t).format('MMM-DD')
        })
      },
      legend,
      tooltip,
      referenceLine: {
        x: presentDay,
        stroke: '#CCC',
        strokeWidth: 2,
        strokeDasharray: '20 5',
        label: {
          position: 'top',
          value: 'Latest data',
          fill: '#333',
          fontSize: 11
        }
      },
      brush: {
        width: '100%',
        height: 60,
        margin: {
          top: 0,
          right: 10,
          left: 48,
          bottom: 12
        },
        minimumGap: 4,
        dataKey: 'date',
        startIndex,
        endIndex,
        config: {
          margin: {
            top: 5,
            right: 0,
            left: 42,
            bottom: 20
          },
          yKeys: {
            lines: {
              count: {
                stroke: colors.main,
                isAnimationActive: false
              },
              compareCount: {
                stroke: '#49b5e3',
                isAnimationActive: false
              },
              ...(Object.keys(compareYearsLines).length, compareYearsLines)
            }
          },
          xAxis: {
            hide: true
          },
          yAxis: {
            hide: true
          },
          cartesianGrid: {
            horizontal: false,
            vertical: false
          },
          height: 60
        }
      }
    };
  }
);

export const parseSentence = createSelector(
  [
    getData,
    parseData,
    getColors,
    getSentences,
    getDataset,
    getLocationName,
    getStartIndex,
    getEndIndex
  ],
  (
    raw_data,
    data,
    colors,
    sentence,
    dataset,
    location,
    startIndex
    // endIndex //broken?
  ) => {
    if (!data) return null;

    const start = startIndex;
    const latestYear = maxBy(data, 'year').year;
    const lastDate =
      maxBy(
        data.filter(d => d.year === latestYear && d.count !== null),
        'date'
      ) || {};
    const firstDate = data[start] || {};

    const slicedData = data.filter(
      el => el.date >= firstDate.date && el.date <= lastDate.date
    );
    const variance = getPeriodVariance(slicedData, raw_data);

    const maxWeek = maxBy(raw_data, 'count');
    const maxTotal = maxWeek.count;
    const maxYear = maxWeek.year;
    const maxCount = maxBy(slicedData, 'count');
    const total = maxCount ? maxCount.count : 0;

    const colorRange = colors.ramp;
    let statusColor = colorRange[8];
    const { date } = lastDate || {};

    let status = 'unusually low';
    if (variance > 2) {
      status = 'unusually high';
      statusColor = colorRange[0];
    } else if (variance <= 2 && variance > 1) {
      status = 'high';
      statusColor = colorRange[2];
    } else if (variance <= 1 && variance > -1) {
      status = 'average';
      statusColor = colorRange[4];
    } else if (variance <= -1 && variance > -2) {
      status = 'low';
      statusColor = colorRange[6];
    }

    const formattedData = moment(date).format('Do of MMMM YYYY');
    const params = {
      location,
      date: formattedData,
      latestYear,
      dataset_start_year: dataset === 'viirs' ? 2012 : 2001,
      maxYear,
      maxTotal: {
        value: maxTotal ? format(',')(maxTotal) : 0,
        color: colors.main
      },
      dataset: dataset.toUpperCase(),
      count: {
        value: total ? format(',')(total) : 0,
        color: colors.main
      },
      status: {
        value: status,
        color: statusColor
      }
    };
    return { sentence, params };
  }
);

export default createStructuredSelector({
  originalData: parseData,
  data: parseBrushedData,
  config: parseConfig,
  sentence: parseSentence
});
<|endoftext|>


<commit_before>var GPU_jsStrToWebclglStr = (function() {

	/// @returns  the default state paramater set, used across the parser
	function jison_defaultStateParam(funcStr, inParamObj) {
		return {
			// The source code rows array
			src : funcStr,
			srcArr : funcStr.split("\n"),

			// The compiler parameter options
			paramObj : inParamObj,

			// Original main function naming
			customMainFunctionName : null,

			// Reserved namespace used for GPU.js code
			reservedNamespace : "gpu_",

			// Current function state, being processed
			currentFunctionNamespace : null,

			// Annoymous function number tracking
			annoymousFunctionNumber : 0
		};
	}

	/// Parses the source code string
	///
	/// @param  funcStr      the input function string
	/// @param  stateParam   the compiled state tracking
	///
	/// @returns the parsed json obj
	function jison_parseFuncStr( funcStr, stateParam ) {
		var mainObj = parser.parse( "var main = "+funcStr+";" );
		if( mainObj == null ) {
			throw "Failed to parse JS code via JISON";
		}

		// take out the function object, outside the main var declarations
		var mainAst = mainObj.body[0].declarations[0].init;

		// Capture the original statment code
		stateParam.customMainFunctionName = mainAst.id;
		mainAst.id = "main";

		return mainAst;
	}

	/// the AST error, with its location. To throw (@TODO add location support)
	///
	/// @param error        the error message output
	/// @param ast          the AST object where the error is
	/// @param stateParam   the compiled state tracking
	function ast_errorOutput(error, ast, stateParam) {
		console.error(error, ast, stateParam);
		return error;
	}

	/// Prases the abstract syntax tree, genericially to its respective function
	///
	/// @param ast          the AST object to parse
	/// @param retArr       return array string
	/// @param stateParam   the compiled state tracking
	///
	/// @returns  the prased openclgl string array
	function ast_generic(ast, retArr, stateParam) {
		switch(ast.type) {
			case "FunctionExpression":
				return ast_FunctionExpression(ast, retArr, stateParam);
			case "ReturnStatement":
				return ast_ReturnStatement(ast, retArr, stateParam);
			case "Literal":
				return ast_Literal(ast, retArr,  stateParam);
			case "BinaryExpression":
				return ast_BinaryExpression(ast, retArr,  stateParam);
			case "MemberExpression":
				return ast_MemberExpression(ast, retArr,  stateParam);
		}

		throw ast_errorOutput("Unknown ast type : "+ast.type, ast, stateParam);
	}

	/// Prases the abstract syntax tree, to its named function
	///
	/// @param ast   the AST object to parse
	/// @param retArr       return array string
	/// @param stateParam   the compiled state tracking
	///
	/// @returns  the appened retArr
	function ast_FunctionExpression(ast, retArr, stateParam) {

		// Setup the main function
		if( ast.id == "main" ) {
			retArr.push("void main(");
		} else {
			// @TODO : Suuport return type values
			retArr.push("void ");

			// Its an Annoymous function, handle it
			if(ast.id == null) {
				ast.id = stateParam.reservedNamespace+"a"+stateParam.annoymousFunctionNumber;
				stateParam.annoymousFunctionNumber++;
			}

			//Function name
			retArr.push(ast.id);
			retArr.push("(");
		}
		stateParam.currentFunctionNamespace = ast.id;

		// Handle parameters tokens
		var paramsNode = ast.params;
		if(paramsNode) {
			for(var i=0; i<paramsNode.length; ++i) {
				if( paramsNode[i].type != "Identifier" ) {
					throw ast_errorOutput(
						"Unexpected function parameter identifier"+paramsNode[i].type,
						paramsNode[i], stateParam
					);
				}

				retArr.push(" float* ");
				retArr.push(paramsNode[i].name);

				if(i+1 < paramsNode.length) {
					retArr.push(", ");
				}
			}
		}

		// Function opening bracket
		retArr.push(") { ");

		// Body statement iteration
		for(var i=0; i<ast.body.length; ++i) {
			ast_generic(ast.body[i], retArr, stateParam);
		}

		// Function closing
		retArr.push("}");
		return retArr;
	}

	/// Prases the abstract syntax tree, to return function
	///
	/// @param ast          the AST object to parse
	/// @param retArr       return array string
	/// @param stateParam   the compiled state tracking
	///
	/// @returns  the appened retArr
	function ast_ReturnStatement(ast, retArr, stateParam) {
		if( stateParam.currentFunctionNamespace == "main" ) {
			retArr.push("out_float = ");
			ast_generic(ast.argument, retArr, stateParam);
			retArr.push("; ");
		} else {
			throw ast_errorOutput(
				"Non main function return, is not supported : "+stateParam.currentFunctionNamespace,
				ast, stateParam
			);
		}

		return retArr;
	}

	/// Prases the abstract syntax tree, literal value
	///
	/// @param ast          the AST object to parse
	/// @param retArr       return array string
	/// @param stateParam   the compiled state tracking
	///
	/// @returns  the appened retArr
	function ast_Literal(ast, retArr, stateParam) {

		// Reject non numeric literals
		if( isNaN(ast.value) ) {
			throw ast_errorOutput(
				"Non-numeric literal not supported : "+ast.value,
				ast, stateParam
			);
		}

		// Push the literal value as a float/int
		retArr.push( ast.value );

		// If it was an int, node made a float
		if( Number.isInteger(ast.value) ) {
			retArr.push(".0");
		}

		return retArr;
	}

	/// Prases the abstract syntax tree, binary expression
	///
	/// @param ast          the AST object to parse
	/// @param retArr       return array string
	/// @param stateParam   the compiled state tracking
	///
	/// @returns  the appened retArr
	function ast_BinaryExpression(ast, retArr, stateParam) {
		if(
			ast.operator == "+" ||
			ast.operator == "-" ||
			ast.operator == "*" ||
			ast.operator == "/"
		) {
			ast_generic(ast.left, retArr, stateParam);
			retArr.push( " "+ast.operator+" " );
			ast_generic(ast.right, retArr, stateParam);
		} else if(ast.operator == "%") {
			ast_generic(ast.left, retArr, stateParam);
			retArr.push( " , " );
			ast_generic(ast.right, retArr, stateParam);
			retArr.push( ")" );
		} else {
			throw ast_errorOutput("Unsupported BinaryExpression: "+ast.operator, ast, stateParam);
		}

		return retArr;
	}

	/// Prases the abstract syntax tree, member expression
	///
	/// @param ast          the AST object to parse
	/// @param retArr       return array string
	/// @param stateParam   the compiled state tracking
	///
	/// @returns  the appened retArr
	function ast_MemberExpression(ast, retArr, stateParam) {

		// Name identifier support
		if( ast.object && ast.object.type == "Identifier" && ast.object.name ) {
			retArr.push( ast.object.name );
			retArr.push("[");
			ast_generic(ast.property, retArr, stateParam);
			retArr.push("]");
		}

		throw ast_errorOutput("Unsupported MemberExpression: "+ast.name+"["+ast.property+"]", ast, stateParam);
		return retArr;
	}

	/*

	/// Prases the abstract syntax tree, genericially to its respective function
	///
	/// @param ast   the AST object to parse
	///
	/// @returns  the prased openclgl string
	function ast_ForStatement(forNode, retArr) {
		if (forNode.type != "ForStatement") {
			throw "error";
		}
		retArr.push("for (");
		ast_generic(forNode.init, retArr);
		ast_generic(forNode.test, retArr);
		ast_generic(forNode.update, retArr);
		retArr.push(")");
		ast_generic(forNode.body, retArr);
		return retArr;
	}

	function ast_ExpressionStatement(expNode, retArr) {
		if (expNode.type != "ExpressionStatement") {
			throw "error";
		}
		ast_generic(expNode.expression, retArr);
		retArr.push(";");
		return retArr;
	}

	function ast_AssignmentExpression(assNode, retArr) {
		if (assNode.type != "AssignmentExpression") {
			throw "error";
		}

		retArr.push("float");
		ast_generic(assNode.left, retArr);
		retArr.push(assNode.operator);
		ast_generic(assNode.right, retArr);
	}
	*/

	/// The function string to openslgl code generator
	function jsStrToWebclglStr( funcStr, _threadDim, _blockDim, paramObj ) {

		var stateObj = jison_defaultStateParam(funcStr, paramObj);
		var astOutputObj = jison_parseFuncStr(funcStr, stateObj);

		var retArr = ast_generic( astOutputObj, [], stateObj );
		return retArr.join("");
	}

	return jsStrToWebclglStr;
})();

var GPU_jsToWebclgl = (function() {

	///----------------------------------------------------------------------------------------
	/// Misc utility functions, copy pasta from somewhere >_>
	///----------------------------------------------------------------------------------------
	var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
	var ARGUMENT_NAMES = /([^\s,]+)/g;
	function getParamNames(func) {
		var fnStr = func.toString().replace(STRIP_COMMENTS, '');
		var result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES);
		if(result === null)
			result = [];
		return result;
	}

	///----------------------------------------------------------------------------------------
	/// Actual SHIT
	///----------------------------------------------------------------------------------------

	/// Does simple validation of the provided function string if it is a function
	/// this is a basic sanity testing before Jison conversion
	///
	/// @param funcStr  the input function string
	///
	/// @returns boolean
	function validateStringIsFunction( funcStr ) {
		if( funcStr != null ) {
			return (funcStr.slice(0, "function".length).toLowerCase() == "function")
		}
		return false;;
	}

	/// Does the core conversion of a basic Javascript function into a webclgl
	/// and returns a callable function if valid
	///
	/// @param inputFunction   The calling to perform the conversion
	/// @param _threadDim      The thread dim array configuration
	/// @param _blockDim       The block dim array configuration
	/// @param paramObj        The parameter object
	///
	/// @returns callable function if converted, else returns null
	function jsToWebclgl( inputFunction, _threadDim, _blockDim, paramObj ) {

		//
		// Webclgl String generation and basic checks
		//--------------------------------------------

		//
		// Function stringify, and basic validation
		//
		var funcStr = inputFunction.toString();
		if( !validateStringIsFunction(funcStr) ) {
			return null;
		}

		//
		// JS String to Webclgl String
		//
		var webclglStr = GPU_jsStrToWebclglStr( funcStr, _threadDim, _blockDim, paramObj );

		//
		// Webclgl String to function conversion
		//--------------------------------------------

		//
		// Fetching arguments name
		//
		var argNames = getParamNames(inputFunction);

		//
		// Normalizing threadDim & blockDim
		//
		var threadDim = _threadDim.slice(0);
		var blockDim  = _blockDim.slice(0);
		while (threadDim.length < 3) {
			threadDim.push(1);
		}
		while (blockDim.length < 3) {
			blockDim.push(1);
		}

		//
		// Global dim, and total size
		//
		var globalDim = [
			threadDim[0] * blockDim[0],
			threadDim[1] * blockDim[1],
			threadDim[2] * blockDim[2]
		];
		var totalSize = globalDim[0] * globalDim[1] * globalDim[2];

		//
		// Return function caller
		//--------------------------------------------
		var retFunc = function webclglCaller() {
			//
			// Argument safety check
			//
			if(argNames.length != arguments.length) {
				throw "Invalid argument count ("+arguments.length+") expected ("+argNames.length+")";
			}

			//
			// webclgl core class setup
			// @TODO: Consider precreating the object as optimization?, check if this crashses shit
			//
			var webCLGL = new WebCLGL();

			//
			// Float offset and result buffer setup
			//
			var floatOffset = paramObj.floatOffset || 65535.0;
			var resultBuffer = webCLGL.createBuffer(totalSize, "FLOAT", floatOffset);

			//
			// Argument buffer handling
			//
			var argBuffers = [];
			for (var i=0; i<argNames.length; i++) {
				argBuffers[i] = webCLGL.createBuffer(arguments[i].length, "FLOAT", floatOffset);
				webCLGL.enqueueWriteBuffer(argBuffers[i], arguments[i]);
			}

			//
			// Compile the kernal code
			// @TODO: Consider precreating the object as optimization?, check if this crashses shit
			//
			var kernel = webCLGL.createKernel(webclglStr);

			//
			// Link up the argument and result buffer
			//
			for (var i=0; i<argNames.length; i++) {
				kernel.setKernelArg(i, argBuffers[i]);
			}

			// Does not need the kernel.compile optimiztion, as code is recompiled on each run
			// @TODO: consider this ??
			//kernel.compile();

			webCLGL.enqueueNDRangeKernel(kernel, resultBuffer);

			//
			// Fetch the result
			// @TODO : Async support????
			//
			var result = webCLGL.enqueueReadBuffer_Float(resultBuffer);
			result = Array.prototype.slice.call(result[0]);

			if (_threadDim.length == 1) {
				return result[0];
			} else if (_threadDim.length == 2) {
				//ret = ret[0];
			}

			return result;
		};

		//
		// async extension ???
		//
		//retFunc.async()???

		return retFunc;
	}

	return jsToWebclgl;
})();
<commit_msg>generateBoilerCode template<commit_after>var GPU_jsStrToWebclglStr = (function() {

	/// @returns  the default state paramater set, used across the parser
	function jison_defaultStateParam(funcStr, inParamObj, inArgStateObj) {
		return {
			// The source code rows array
			src : funcStr,
			srcArr : funcStr.split("\n"),

			// The compiler parameter options
			paramObj : inParamObj,

			// The argument state object
			argStateObj : inArgStateObj,

			// Original main function naming
			customMainFunctionName : null,

			// Reserved namespace used for GPU.js code
			reservedNamespace : "gpu_",

			// Current function state, being processed
			currentFunctionNamespace : null,

			// Annoymous function number tracking
			annoymousFunctionNumber : 0
		};
	}

	/// Parses the source code string
	///
	/// @param  funcStr      the input function string
	/// @param  stateParam   the compiled state tracking
	///
	/// @returns the parsed json obj
	function jison_parseFuncStr( funcStr, stateParam ) {
		var mainObj = parser.parse( "var main = "+funcStr+";" );
		if( mainObj == null ) {
			throw "Failed to parse JS code via JISON";
		}

		// take out the function object, outside the main var declarations
		var mainAst = mainObj.body[0].declarations[0].init;

		// Capture the original statment code
		stateParam.customMainFunctionName = mainAst.id;
		mainAst.id = "main";

		return mainAst;
	}

	/// the AST error, with its location. To throw (@TODO add location support)
	///
	/// @param error        the error message output
	/// @param ast          the AST object where the error is
	/// @param stateParam   the compiled state tracking
	function ast_errorOutput(error, ast, stateParam) {
		console.error(error, ast, stateParam);
		return error;
	}

	/// Prases the abstract syntax tree, genericially to its respective function
	///
	/// @param ast          the AST object to parse
	/// @param retArr       return array string
	/// @param stateParam   the compiled state tracking
	///
	/// @returns  the prased openclgl string array
	function ast_generic(ast, retArr, stateParam) {
		switch(ast.type) {
			case "FunctionExpression":
				return ast_FunctionExpression(ast, retArr, stateParam);
			case "ReturnStatement":
				return ast_ReturnStatement(ast, retArr, stateParam);
			case "Literal":
				return ast_Literal(ast, retArr,  stateParam);
			case "BinaryExpression":
				return ast_BinaryExpression(ast, retArr,  stateParam);
			case "MemberExpression":
				return ast_MemberExpression(ast, retArr,  stateParam);
		}

		throw ast_errorOutput("Unknown ast type : "+ast.type, ast, stateParam);
	}

	/// Prases the abstract syntax tree, to its named function
	///
	/// @param ast   the AST object to parse
	/// @param retArr       return array string
	/// @param stateParam   the compiled state tracking
	///
	/// @returns  the appened retArr
	function ast_FunctionExpression(ast, retArr, stateParam) {

		// Setup the main function
		if( ast.id == "main" ) {
			retArr.push("void main(");
		} else {
			// @TODO : Suuport return type values
			retArr.push("void ");

			// Its an Annoymous function, handle it
			if(ast.id == null) {
				ast.id = stateParam.reservedNamespace+"a"+stateParam.annoymousFunctionNumber;
				stateParam.annoymousFunctionNumber++;
			}

			//Function name
			retArr.push(ast.id);
			retArr.push("(");
		}
		stateParam.currentFunctionNamespace = ast.id;

		// Handle parameters tokens
		var paramsNode = ast.params;
		if(paramsNode) {
			for(var i=0; i<paramsNode.length; ++i) {
				if( paramsNode[i].type != "Identifier" ) {
					throw ast_errorOutput(
						"Unexpected function parameter identifier"+paramsNode[i].type,
						paramsNode[i], stateParam
					);
				}

				retArr.push(" float* ");
				retArr.push(paramsNode[i].name);

				if(i+1 < paramsNode.length) {
					retArr.push(", ");
				}
			}
		}

		// Function opening bracket
		retArr.push(") { ");

		// Body statement iteration
		for(var i=0; i<ast.body.length; ++i) {
			ast_generic(ast.body[i], retArr, stateParam);
		}

		// Function closing
		retArr.push("}");
		return retArr;
	}

	/// Prases the abstract syntax tree, to return function
	///
	/// @param ast          the AST object to parse
	/// @param retArr       return array string
	/// @param stateParam   the compiled state tracking
	///
	/// @returns  the appened retArr
	function ast_ReturnStatement(ast, retArr, stateParam) {
		if( stateParam.currentFunctionNamespace == "main" ) {
			retArr.push("out_float = ");
			ast_generic(ast.argument, retArr, stateParam);
			retArr.push("; ");
		} else {
			throw ast_errorOutput(
				"Non main function return, is not supported : "+stateParam.currentFunctionNamespace,
				ast, stateParam
			);
		}

		return retArr;
	}

	/// Prases the abstract syntax tree, literal value
	///
	/// @param ast          the AST object to parse
	/// @param retArr       return array string
	/// @param stateParam   the compiled state tracking
	///
	/// @returns  the appened retArr
	function ast_Literal(ast, retArr, stateParam) {

		// Reject non numeric literals
		if( isNaN(ast.value) ) {
			throw ast_errorOutput(
				"Non-numeric literal not supported : "+ast.value,
				ast, stateParam
			);
		}

		// Push the literal value as a float/int
		retArr.push( ast.value );

		// If it was an int, node made a float
		if( Number.isInteger(ast.value) ) {
			retArr.push(".0");
		}

		return retArr;
	}

	/// Prases the abstract syntax tree, binary expression
	///
	/// @param ast          the AST object to parse
	/// @param retArr       return array string
	/// @param stateParam   the compiled state tracking
	///
	/// @returns  the appened retArr
	function ast_BinaryExpression(ast, retArr, stateParam) {
		if(
			ast.operator == "+" ||
			ast.operator == "-" ||
			ast.operator == "*" ||
			ast.operator == "/"
		) {
			ast_generic(ast.left, retArr, stateParam);
			retArr.push( " "+ast.operator+" " );
			ast_generic(ast.right, retArr, stateParam);
		} else if(ast.operator == "%") {
			ast_generic(ast.left, retArr, stateParam);
			retArr.push( " , " );
			ast_generic(ast.right, retArr, stateParam);
			retArr.push( ")" );
		} else {
			throw ast_errorOutput("Unsupported BinaryExpression: "+ast.operator, ast, stateParam);
		}

		return retArr;
	}

	/// Prases the abstract syntax tree, member expression
	///
	/// @param ast          the AST object to parse
	/// @param retArr       return array string
	/// @param stateParam   the compiled state tracking
	///
	/// @returns  the appened retArr
	function ast_MemberExpression(ast, retArr, stateParam) {

		// Name identifier support
		if( ast.object && ast.object.type == "Identifier" && ast.object.name ) {
			retArr.push( ast.object.name );
			retArr.push("[");
			ast_generic(ast.property, retArr, stateParam);
			retArr.push("]");
		}

		throw ast_errorOutput("Unsupported MemberExpression: "+ast.name+"["+ast.property+"]", ast, stateParam);
		return retArr;
	}

	/*

	/// Prases the abstract syntax tree, genericially to its respective function
	///
	/// @param ast   the AST object to parse
	///
	/// @returns  the prased openclgl string
	function ast_ForStatement(forNode, retArr) {
		if (forNode.type != "ForStatement") {
			throw "error";
		}
		retArr.push("for (");
		ast_generic(forNode.init, retArr);
		ast_generic(forNode.test, retArr);
		ast_generic(forNode.update, retArr);
		retArr.push(")");
		ast_generic(forNode.body, retArr);
		return retArr;
	}

	function ast_ExpressionStatement(expNode, retArr) {
		if (expNode.type != "ExpressionStatement") {
			throw "error";
		}
		ast_generic(expNode.expression, retArr);
		retArr.push(";");
		return retArr;
	}

	function ast_AssignmentExpression(assNode, retArr) {
		if (assNode.type != "AssignmentExpression") {
			throw "error";
		}

		retArr.push("float");
		ast_generic(assNode.left, retArr);
		retArr.push(assNode.operator);
		ast_generic(assNode.right, retArr);
	}
	*/

	/// Boiler plate code generation
	function generateBoilerCode( retArr, funcStr, _threadDim, _blockDim, paramObj, argStateObj ) {
		//
		// @TODO
		//
		//  #####  #   # #####
		//  #      #   #    #
		//  #####  #   #   #
		//  #      #   #  #
		//  #      ##### #####
		//
	}

	/// The function string to openslgl code generator
	function jsStrToWebclglStr( funcStr, _threadDim, _blockDim, paramObj, argStateObj ) {

		var stateObj = jison_defaultStateParam(funcStr, paramObj, argStateObj);
		var astOutputObj = jison_parseFuncStr(funcStr, stateObj);
		var retArr = [];

		// Boiler plate code, only if argStateObj is passed
		if( argStateObj != null ) {
			generateBoilerCode( retArr, funcStr, _threadDim, _blockDim, paramObj, argStateObj );
		}

		ast_generic( astOutputObj, retArr, stateObj );
		return retArr.join("");
	}

	return jsStrToWebclglStr;
})();

var GPU_jsToWebclgl = (function() {

	///----------------------------------------------------------------------------------------
	/// Misc utility functions, copy pasta from somewhere >_>
	///----------------------------------------------------------------------------------------
	var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
	var ARGUMENT_NAMES = /([^\s,]+)/g;
	function getParamNames(func) {
		var fnStr = func.toString().replace(STRIP_COMMENTS, '');
		var result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES);
		if(result === null)
			result = [];
		return result;
	}

	///----------------------------------------------------------------------------------------
	/// Actual SHIT
	///----------------------------------------------------------------------------------------

	/// Does simple validation of the provided function string if it is a function
	/// this is a basic sanity testing before Jison conversion
	///
	/// @param funcStr  the input function string
	///
	/// @returns boolean
	function validateStringIsFunction( funcStr ) {
		if( funcStr != null ) {
			return (funcStr.slice(0, "function".length).toLowerCase() == "function")
		}
		return false;;
	}

	/// Does the core conversion of a basic Javascript function into a webclgl
	/// and returns a callable function if valid
	///
	/// @param inputFunction   The calling to perform the conversion
	/// @param _threadDim      The thread dim array configuration
	/// @param _blockDim       The block dim array configuration
	/// @param paramObj        The parameter object
	///
	/// @returns callable function if converted, else returns null
	function jsToWebclgl( inputFunction, _threadDim, _blockDim, paramObj ) {

		//
		// Webclgl String generation and basic checks
		//--------------------------------------------

		//
		// Function stringify, and basic validation
		//
		var funcStr = inputFunction.toString();
		if( !validateStringIsFunction(funcStr) ) {
			return null;
		}

		//
		// Precalculating some of the vars
		//--------------------------------------------

		//
		// Fetching arguments name
		//
		var argNames = getParamNames(inputFunction);

		//
		// Normalizing threadDim & blockDim
		//
		var threadDim = _threadDim.slice(0);
		var blockDim  = _blockDim.slice(0);
		while (threadDim.length < 3) {
			threadDim.push(1);
		}
		while (blockDim.length < 3) {
			blockDim.push(1);
		}

		//
		// Global dim, and total size
		//
		var globalDim = [
			threadDim[0] * blockDim[0],
			threadDim[1] * blockDim[1],
			threadDim[2] * blockDim[2]
		];
		var totalSize = globalDim[0] * globalDim[1] * globalDim[2];

		//
		// Return function caller
		//--------------------------------------------
		var retFunc = function webclglCaller() {

			//
			// Argument safety check
			//----------------------------------
			if(argNames.length != arguments.length) {
				throw "Invalid argument count ("+arguments.length+") expected ("+argNames.length+")";
			}

			//
			// Argument State obj init
			//----------------------------------
			var argStateObj = {

			};

			//
			// String conversion and exec
			//----------------------------------

			//
			// webclgl core class setup
			// @TODO: Consider precreating the object as optimization?, check if this crashses shit
			//
			var webCLGL = new WebCLGL();

			//
			// Float offset and result buffer setup
			//
			var floatOffset = paramObj.floatOffset || 65535.0;
			var resultBuffer = webCLGL.createBuffer(totalSize, "FLOAT", floatOffset);

			argStateObj.result_w = resultBuffer.W;
			argStateObj.result_h = resultBuffer.H;

			//
			// Argument buffer handling
			//
			var argBuffers = [];
			for (var i=0; i<argNames.length; i++) {
				argBuffers[i] = webCLGL.createBuffer(arguments[i].length, "FLOAT", floatOffset);
				webCLGL.enqueueWriteBuffer(argBuffers[i], arguments[i]);
			}

			//
			// Compile the kernal code, from JS, to webclgl, to Shader (via unknown vodoo)
			// @TODO: Consider precreating the object as optimization?, check if this crashses shit
			//
			var webclglStr = GPU_jsStrToWebclglStr( funcStr, _threadDim, _blockDim, paramObj, argStateObj );
			var kernel = webCLGL.createKernel(webclglStr);

			//
			// Link up the argument and result buffer
			//
			for (var i=0; i<argNames.length; i++) {
				kernel.setKernelArg(i, argBuffers[i]);
			}

			// Does not need the kernel.compile optimiztion, as code is recompiled on each run
			// @TODO: consider this ??
			//kernel.compile();

			webCLGL.enqueueNDRangeKernel(kernel, resultBuffer);

			//
			// Fetch the result
			// @TODO : Async support????
			//
			var result = webCLGL.enqueueReadBuffer_Float(resultBuffer);
			result = Array.prototype.slice.call(result[0]);

			if (_threadDim.length == 1) {
				return result[0];
			} else if (_threadDim.length == 2) {
				//ret = ret[0];
			}

			return result;
		};

		//
		// async extension ???
		//
		//retFunc.async()???

		return retFunc;
	}

	return jsToWebclgl;
})();
<|endoftext|>


<commit_before>// jQuery
var $renderPort = $('#renderPort');

// SocketIO
var socket = io();
var connected = false;

// Phone variables
var vX = 0, vY = 0, vZ = 0,
  sX = 0, sY = 0, sZ = 0,
  alpha = 0, beta = 0, gamma = 0;

// 3D Scene variables
var scene, camera, renderer, cube;
var ambientlight, hemispherelight, dirlight, pointlight;

// Setup 3D scene
function setupScene() {
  // Scene object
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera( 75, $renderPort.width()/$renderPort.height(), 0.1, 10000);

  // Create renderer
  renderer = new THREE.WebGLRenderer( { alpha: true } );
  renderer.setSize( $renderPort.width(), $renderPort.height());

  // Light
  ambientlight = new THREE.AmbientLight( 0x404040 );
  scene.add( ambientlight );

  dirLight = new THREE.DirectionalLight(0xffffff, 1);
  dirLight.position.set(400, 500, 50);
  scene.add(dirLight);

  hemispherelight = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 );
  hemispherelight.position.set(0, 500, 0);
  hemispherelight.color.setHSL( 0.6, 1, 0.6 );
  hemispherelight.groundColor.setHSL( 0.095, 1, 0.75 );
  scene.add( hemispherelight );

  // Add renderer
  $renderPort.append( renderer.domElement );

  // Cam position
  camera.position.z = 900;
  camera.position.y = 0;
  camera.position.x = 0;
  camera.up = new THREE.Vector3( 0, 1, 0 );

  scene.add( new THREE.AxisHelper( 600 ));

  // Add cube
  addCube();

  camera.lookAt( cube.position );
  scene.add( camera );
}

function addCube() {
  var geometry = new THREE.BoxGeometry( 300,300,300 );
  var material = new THREE.MeshPhongMaterial( { color: 0x47d1d1 });
  cube = new THREE.Mesh( geometry, material );
  cube.castShadow = true;
  scene.add( cube );
}

var render = function () {
  // cube.rotation.x += gamma*2;
  cube.rotation.y += gamma*2;
  cube.rotation.z += alpha*2;

  requestAnimationFrame( render );
  renderer.render( scene, camera );
}

window.addEventListener('resize', function() {
  renderer.setSize( $renderPort.width(), $renderPort.height());
  camera.aspect = $renderPort.width()/$renderPort.height();
  camera.updateProjectionMatrix();
});

// Kickstart
setupScene();
render();

// Check connection
socket.on('connection', function() {
  connected = true;
});

// If client has accelerometer and gyro data
if (window.DeviceMotionEvent) {
  window.addEventListener('devicemotion', function (data) {
    var acc = data.accelerationIncludingGravity;
    var vel = { vX: vX, vY: vY, vZ: vZ };
    var disp = { sX: sX, sY: sY, sZ: sZ };

    var phoneData = {
      accelerometer: acc,
      velocity: vel,
      displacement: disp,
      rotationRate: data.rotationRate,
      interval: data.interval
    };

    // Tell server
    socket.emit('phone-data', phoneData);
  }, false);
}

socket.on('phone-data', function (data) {
    vX = data.velocity.vX;
    vY = data.velocity.vY;
    vZ = data.velocity.vZ;

    sX = data.displacement.sX;
    sY = data.displacement.sY;
    sZ = data.displacement.sZ;

  // Check and update angle
  if (aboveAbsThreshold(data.rotationRate.alpha, 0.1) || aboveAbsThreshold(data.rotationRate.beta, 0.1) || aboveAbsThreshold(data.rotationRate.gamma, 0.1)) {
    var scalar = 100;
    alpha = data.rotationRate.alpha*data.interval/scalar;
    beta = data.rotationRate.beta*data.interval/scalar;
    gamma = data.rotationRate.gamma*data.interval/scalar;
  }

});
function aboveAbsThreshold(input, threshold) {
  return Math.abs(input) > threshold ? true : false;
}<commit_msg>Fixing axes.<commit_after>// jQuery
var $renderPort = $('#renderPort');

// SocketIO
var socket = io();
var connected = false;

// Phone variables
var vX = 0, vY = 0, vZ = 0,
  sX = 0, sY = 0, sZ = 0,
  alpha = 0, beta = 0, gamma = 0;

// 3D Scene variables
var scene, camera, renderer, cube;
var ambientlight, hemispherelight, dirlight, pointlight;

// Setup 3D scene
function setupScene() {
  // Scene object
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera( 75, $renderPort.width()/$renderPort.height(), 0.1, 10000);

  // Create renderer
  renderer = new THREE.WebGLRenderer( { alpha: true } );
  renderer.setSize( $renderPort.width(), $renderPort.height());

  // Light
  ambientlight = new THREE.AmbientLight( 0x404040 );
  scene.add( ambientlight );

  dirLight = new THREE.DirectionalLight(0xffffff, 1);
  dirLight.position.set(400, 500, 50);
  scene.add(dirLight);

  hemispherelight = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 );
  hemispherelight.position.set(0, 500, 0);
  hemispherelight.color.setHSL( 0.6, 1, 0.6 );
  hemispherelight.groundColor.setHSL( 0.095, 1, 0.75 );
  scene.add( hemispherelight );

  // Add renderer
  $renderPort.append( renderer.domElement );

  // Cam position
  camera.position.z = 900;
  camera.position.y = 0;
  camera.position.x = 0;
  camera.up = new THREE.Vector3( 0, 1, 0 );

  scene.add( new THREE.AxisHelper( 600 ));

  // Add cube
  addCube();

  camera.lookAt( cube.position );
  scene.add( camera );
}

function addCube() {
  var geometry = new THREE.BoxGeometry( 300,300,300 );
  var material = new THREE.MeshPhongMaterial( { color: 0x47d1d1 });
  cube = new THREE.Mesh( geometry, material );
  cube.castShadow = true;
  scene.add( cube );
}

var render = function () {
  // cube.rotation.x += gamma*2;
  cube.rotation.y += beta*2;
  cube.rotation.z += alpha*2;

  requestAnimationFrame( render );
  renderer.render( scene, camera );
}

window.addEventListener('resize', function() {
  renderer.setSize( $renderPort.width(), $renderPort.height());
  camera.aspect = $renderPort.width()/$renderPort.height();
  camera.updateProjectionMatrix();
});

// Kickstart
setupScene();
render();

// Check connection
socket.on('connection', function() {
  connected = true;
});

// If client has accelerometer and gyro data
if (window.DeviceMotionEvent) {
  window.addEventListener('devicemotion', function (data) {
    var acc = data.accelerationIncludingGravity;
    var vel = { vX: vX, vY: vY, vZ: vZ };
    var disp = { sX: sX, sY: sY, sZ: sZ };

    var phoneData = {
      accelerometer: acc,
      velocity: vel,
      displacement: disp,
      rotationRate: data.rotationRate,
      interval: data.interval
    };

    // Tell server
    socket.emit('phone-data', phoneData);
  }, false);
}

socket.on('phone-data', function (data) {
    vX = data.velocity.vX;
    vY = data.velocity.vY;
    vZ = data.velocity.vZ;

    sX = data.displacement.sX;
    sY = data.displacement.sY;
    sZ = data.displacement.sZ;

  // Check and update angle
  if (aboveAbsThreshold(data.rotationRate.alpha, 0.1) || aboveAbsThreshold(data.rotationRate.beta, 0.1) || aboveAbsThreshold(data.rotationRate.gamma, 0.1)) {
    var scalar = 100;
    alpha = data.rotationRate.alpha*data.interval/scalar;
    beta = data.rotationRate.beta*data.interval/scalar;
    gamma = data.rotationRate.gamma*data.interval/scalar;
  }

});
function aboveAbsThreshold(input, threshold) {
  return Math.abs(input) > threshold ? true : false;
}<|endoftext|>