<commit_before>'use strict';
TG.Game = (function (that) {
  var state = {
    score: 0,
    lives: 3,
    chain: {
      chaining: false,
      Pos: {},
      Tick: 0,
      Count: 0
    },
    ticks: 0,
    difficulty: 1,
    projectiles: 0
  },
  chainDistanceInTicks = function () {
    return 40 / state.difficulty;
  },
  enemiesInChain = 10,
  difficultyTick = 5000,
  totalProjectileCount = 2;

  // Returns a random position.
  function _getRndPos() {
    var areaSize = TG.Engines.Render.getPlayAreaSize();

    return new TG.Objects.Position(Math.floor(Math.random() * areaSize.width), Math.floor(Math.random() * areaSize.height));
  };

  function _getRndNum(max) {
    return Math.floor(Math.random() * max);
  };

  function Tick(delta) {
    var i = 0;

    state.ticks++;

    if (that.Player().getState().Combat.HP <= 0) {
      state.lives--;

      if (state.lives <= 0) {
        // Game Over
        resetGame();
      } else {
        // Death
        resetLevel();
      }
    }

    if (state.ticks >= difficultyTick) {
      state.ticks = 0;
      state.difficulty++;
    }

    for (i = 0; i < BackgroundObjects.length; i++) {
      (function (i) {
        BackgroundObjects[i].Tick(delta);
      })(i);
    }

    var deleteIds = [];

    for (var i = 0; i < GameObjects.length; i++) {
      (function (i) {
        GameObjects[i]
            .Tick(delta);

        if (i != 0 && GameObjects[i].getDelete && GameObjects[i].getDelete()) {
          // if an object gives a score on destruction then set the score.
          if (GameObjects[i].getScore) {
            state.score += GameObjects[i].getScore();
          }

          // if the object is a projectile then reduce the number of projectiles on the screen.
          if (GameObjects[i] instanceof TG.Objects.Projectile) {
            state.projectiles--;
          }

          // mark the id to be deleted
          deleteIds.push(i);
        }
      })(i);
    }

    var deleteCount = 0;
    for (var d = 0; d < deleteIds.length; d++) {
      GameObjects.splice(deleteIds[d] - deleteCount, 1);
      deleteCount++;
    }

    GenerateNewObjects();
  };

  function resetGame() {
    state.score = 0;
    state.lives = 3;

    resetLevel();
  }

  function resetLevel() {
    state.chain = {
      chaining: false,
      Pos: {},
      Tick: 0,
      Count: 0
    };
    state.ticks = 0;
    state.difficulty = 4;
    state.projectiles = 0;

    GameObjects = [];

    GameObjects[0] = TG.Engines.Generate.Player('Player', { x: 100, y: 100 }, 4);
  }

  function GenerateNewObjects() {
    var areaSize = TG.Engines.Render.getPlayAreaSize();

    // Generate Background Objects
    if (_getRndNum(1) == 0) {
      var starSpeed = (_getRndNum(500) / 100) * -150;
      if (starSpeed < -1) {
        BackgroundObjects.push(
            new TG.Objects.Actor(
                'star',
                new TG.Objects.Position(areaSize.width - 5, _getRndPos().y),
                { horizontal: starSpeed, vertical: 0 },
                TG.Engines.Animation.Star
            )
        );
      }
    }

    // Generate Enemy Objects
    if (!state.chain.chaining) {
      state.chain.chaining = (_getRndNum((500 / state.difficulty)) == 0);
    } else {
      if (!state.chain.Pos.y) {
        state.chain.Pos.y = _getRndPos().y;
      }

      if (state.chain.Tick == 0) {
        state.chain.Count++;
        var npc = TG.Engines.Generate.NPC(GameObjects.length, { x: areaSize.width - 5, y: state.chain.Pos.y }, state.difficulty * 50);
        GameObjects.push(npc);
      }

      state.chain.Tick++;

      if (state.chain.Tick > chainDistanceInTicks()) {
        state.chain.Tick = 0;
      }
      if (state.chain.Count >= enemiesInChain) {
        state.chain.Count = 0;
        state.chain.chaining = false;
        state.chain.Pos = {};
      }
    }
  }

  that.Player = function () {
    return GameObjects[0];
  }

  that.CurrentState = function () {
    return {
      GameObjects: GameObjects || [],
      BackgroundObjects: BackgroundObjects || []
    };
  }

  that.AddObject = function (o) {
    GameObjects.push(o);
  }

  var GameObjects = [];
  var BackgroundObjects = [];

  resetGame();

  /*-- Register Keys --*/
  (function (i) {
    // enable keyboard but no other input method.
    i.Init({
      keyboard: true
    });

    // Up - E
    i.AddKey('Up', '69', function () {
      GameObjects[0].setMoving({ vertical: -50 });
    }, function () {
      GameObjects[0].setMoving({ vertical: 0 });
    });

    // Down - D
    i.AddKey('Down', '68', function () {
      GameObjects[0].setMoving({ vertical: 50 });
    }, function () {
      GameObjects[0].setMoving({ vertical: 0 });
    });

    // Right - F
    //TG.Engines.Input.AddKey('70', function () {
    //    GameObjects[0].setMoving({ horizontal: 1 });
    //}, function () {
    //    GameObjects[0].setMoving({ horizontal: 0 });
    //});

    // Left - S
    //TG.Engines.Input.AddKey('83', function () {
    //    GameObjects[0].setMoving({ horizontal: -1 });
    //}, function () {
    //    GameObjects[0].setMoving({ horizontal: 0 });
    //});

    // Attack - Space
    i.AddKey('Attack', '32', function () {
      if (state.projectiles <= totalProjectileCount) {
        state.projectiles++;

        var pos = that.Player().getPosition();

        pos = new TG.Objects.Position(pos.x, pos.y);

        GameObjects.push(new TG.Objects.Projectile('Arrow', pos, { horizontal: 1, vertical: 0 }, 1000, 1000, 50, that.Player()));
      }
    }, function () {

    });

    // Interact - R
    i.AddKey('Interact', '84', function () {
      that.Player().Interact.Perform();
    }, function () {

    });

    // PanRight - right
    i.AddKey('PanRight', '39', function () {
      TG.Engines.Render.MovePanLocation({ x: 20, y: 0 });
    }, function () {

    });
    // PanLeft - left
    i.AddKey('PanLeft', '37', function () {
      TG.Engines.Render.MovePanLocation({ x: -20, y: 0 });
    }, function () {

    });
    // PanDown - down
    i.AddKey('PanDown', '40', function () {
      TG.Engines.Render.MovePanLocation({ x: 0, y: 20 });
    }, function () {

    });
    // PanUp - up
    i.AddKey('PanUp', '38', function () {
      TG.Engines.Render.MovePanLocation({ x: 0, y: -20 });
    }, function () {

    });

    // Test - G
    i.AddKey('Test', '71', function () {
      TG.Test.Perform();
    }, function () {

    });

  }(TG.Engines.Input));

  /*-- Initialize Render Engine --*/
  (function (er, or) {
    // Initialize the Render Engine.
    er.Init([
        new or.Layer(function () { return BackgroundObjects || []; }, true),
        new or.Layer(function () { return GameObjects || []; }, false)
    ], [
        new or.Text(function () { return 'Score: ' + state.score; }, new TG.Objects.Position(50, 30)),
        new or.Text(function () { return 'Lives: ' + state.lives; }, new TG.Objects.Position(50, 50)),
        new or.Text(function () { return 'Health: ' + that.Player().getState().Combat.HP }, new TG.Objects.Position(50, 70)),
        new or.Text(function () { return 'Debug: ' + TG.Engines.Debug.debugString; }, new TG.Objects.Position(50, 90)),
    ],
    that.Player);
  }(TG.Engines.Render, TG.Objects.Render));

  /*-- Initialize Measure --*/
  (function (m) {
    m.Init(function () {
      return GameObjects || [];
    });
  }(TG.Engines.Measure));

  /*-- Main Loop --*/
  (function (core) {

    // set the speed of the udpate.
    core.Init(16);

    // Add input evaluation.
    core.AddTick(TG.Engines.Input.Tick);

    // Add main game loop.
    core.AddTick(Tick);

  }(TG.Engines.Core));

  return that;
})(TG.Engines.Game || {});
<commit_msg>remove old function<commit_after>'use strict';
TG.Game = (function (that) {
  var state = {
    score: 0,
    lives: 3,
    chain: {
      chaining: false,
      Pos: {},
      Tick: 0,
      Count: 0
    },
    ticks: 0,
    difficulty: 1,
    projectiles: 0
  },
  chainDistanceInTicks = function () {
    return 40 / state.difficulty;
  },
  enemiesInChain = 10,
  difficultyTick = 5000,
  totalProjectileCount = 2;

  // Returns a random position.
  function _getRndPos() {
    var areaSize = TG.Engines.Render.getPlayAreaSize();

    return new TG.Objects.Position(Math.floor(Math.random() * areaSize.width), Math.floor(Math.random() * areaSize.height));
  };

  function _getRndNum(max) {
    return Math.floor(Math.random() * max);
  };

  function Tick(delta) {
    var i = 0;

    state.ticks++;

    if (that.Player().getState().Combat.HP <= 0) {
      state.lives--;

      if (state.lives <= 0) {
        // Game Over
        resetGame();
      } else {
        // Death
        resetLevel();
      }
    }

    if (state.ticks >= difficultyTick) {
      state.ticks = 0;
      state.difficulty++;
    }

    for (i = 0; i < BackgroundObjects.length; i++) {
      (function (i) {
        BackgroundObjects[i].Tick(delta);
      })(i);
    }

    var deleteIds = [];

    for (var i = 0; i < GameObjects.length; i++) {
      (function (i) {
        GameObjects[i]
            .Tick(delta);

        if (i != 0 && GameObjects[i].getDelete && GameObjects[i].getDelete()) {
          // if an object gives a score on destruction then set the score.
          if (GameObjects[i].getScore) {
            state.score += GameObjects[i].getScore();
          }

          // if the object is a projectile then reduce the number of projectiles on the screen.
          if (GameObjects[i] instanceof TG.Objects.Projectile) {
            state.projectiles--;
          }

          // mark the id to be deleted
          deleteIds.push(i);
        }
      })(i);
    }

    var deleteCount = 0;
    for (var d = 0; d < deleteIds.length; d++) {
      GameObjects.splice(deleteIds[d] - deleteCount, 1);
      deleteCount++;
    }

    GenerateNewObjects();
  };

  function resetGame() {
    state.score = 0;
    state.lives = 3;

    resetLevel();
  }

  function resetLevel() {
    state.chain = {
      chaining: false,
      Pos: {},
      Tick: 0,
      Count: 0
    };
    state.ticks = 0;
    state.difficulty = 4;
    state.projectiles = 0;

    GameObjects = [];

    GameObjects[0] = TG.Engines.Generate.Player('Player', { x: 100, y: 100 }, 4);
  }

  function GenerateNewObjects() {
    var areaSize = TG.Engines.Render.getPlayAreaSize();

    // Generate Background Objects
    if (_getRndNum(1) == 0) {
      var starSpeed = (_getRndNum(500) / 100) * -150;
      if (starSpeed < -1) {
        BackgroundObjects.push(
            new TG.Objects.Actor(
                'star',
                new TG.Objects.Position(areaSize.width - 5, _getRndPos().y),
                { horizontal: starSpeed, vertical: 0 },
                TG.Engines.Animation.Star
            )
        );
      }
    }

    // Generate Enemy Objects
    if (!state.chain.chaining) {
      state.chain.chaining = (_getRndNum((500 / state.difficulty)) == 0);
    } else {
      if (!state.chain.Pos.y) {
        state.chain.Pos.y = _getRndPos().y;
      }

      if (state.chain.Tick == 0) {
        state.chain.Count++;
        var npc = TG.Engines.Generate.NPC(GameObjects.length, { x: areaSize.width - 5, y: state.chain.Pos.y }, state.difficulty * 50);
        GameObjects.push(npc);
      }

      state.chain.Tick++;

      if (state.chain.Tick > chainDistanceInTicks()) {
        state.chain.Tick = 0;
      }
      if (state.chain.Count >= enemiesInChain) {
        state.chain.Count = 0;
        state.chain.chaining = false;
        state.chain.Pos = {};
      }
    }
  }

  that.Player = function () {
    return GameObjects[0];
  }

  that.AddObject = function (o) {
    GameObjects.push(o);
  }

  var GameObjects = [];
  var BackgroundObjects = [];

  resetGame();

  /*-- Register Keys --*/
  (function (i) {
    // enable keyboard but no other input method.
    i.Init({
      keyboard: true
    });

    // Up - E
    i.AddKey('Up', '69', function () {
      GameObjects[0].setMoving({ vertical: -50 });
    }, function () {
      GameObjects[0].setMoving({ vertical: 0 });
    });

    // Down - D
    i.AddKey('Down', '68', function () {
      GameObjects[0].setMoving({ vertical: 50 });
    }, function () {
      GameObjects[0].setMoving({ vertical: 0 });
    });

    // Right - F
    //TG.Engines.Input.AddKey('70', function () {
    //    GameObjects[0].setMoving({ horizontal: 1 });
    //}, function () {
    //    GameObjects[0].setMoving({ horizontal: 0 });
    //});

    // Left - S
    //TG.Engines.Input.AddKey('83', function () {
    //    GameObjects[0].setMoving({ horizontal: -1 });
    //}, function () {
    //    GameObjects[0].setMoving({ horizontal: 0 });
    //});

    // Attack - Space
    i.AddKey('Attack', '32', function () {
      if (state.projectiles <= totalProjectileCount) {
        state.projectiles++;

        var pos = that.Player().getPosition();

        pos = new TG.Objects.Position(pos.x, pos.y);

        GameObjects.push(new TG.Objects.Projectile('Arrow', pos, { horizontal: 1, vertical: 0 }, 1000, 1000, 50, that.Player()));
      }
    }, function () {

    });

    // Interact - R
    i.AddKey('Interact', '84', function () {
      that.Player().Interact.Perform();
    }, function () {

    });

    // PanRight - right
    i.AddKey('PanRight', '39', function () {
      TG.Engines.Render.MovePanLocation({ x: 20, y: 0 });
    }, function () {

    });
    // PanLeft - left
    i.AddKey('PanLeft', '37', function () {
      TG.Engines.Render.MovePanLocation({ x: -20, y: 0 });
    }, function () {

    });
    // PanDown - down
    i.AddKey('PanDown', '40', function () {
      TG.Engines.Render.MovePanLocation({ x: 0, y: 20 });
    }, function () {

    });
    // PanUp - up
    i.AddKey('PanUp', '38', function () {
      TG.Engines.Render.MovePanLocation({ x: 0, y: -20 });
    }, function () {

    });

    // Test - G
    i.AddKey('Test', '71', function () {
      TG.Test.Perform();
    }, function () {

    });

  }(TG.Engines.Input));

  /*-- Initialize Render Engine --*/
  (function (er, or) {
    // Initialize the Render Engine.
    er.Init([
        new or.Layer(function () { return BackgroundObjects || []; }, true),
        new or.Layer(function () { return GameObjects || []; }, false)
    ], [
        new or.Text(function () { return 'Score: ' + state.score; }, new TG.Objects.Position(50, 30)),
        new or.Text(function () { return 'Lives: ' + state.lives; }, new TG.Objects.Position(50, 50)),
        new or.Text(function () { return 'Health: ' + that.Player().getState().Combat.HP }, new TG.Objects.Position(50, 70)),
        new or.Text(function () { return 'Debug: ' + TG.Engines.Debug.debugString; }, new TG.Objects.Position(50, 90)),
    ],
    that.Player);
  }(TG.Engines.Render, TG.Objects.Render));

  /*-- Initialize Measure --*/
  (function (m) {
    m.Init(function () {
      return GameObjects || [];
    });
  }(TG.Engines.Measure));

  /*-- Main Loop --*/
  (function (core) {

    // set the speed of the udpate.
    core.Init(16);

    // Add input evaluation.
    core.AddTick(TG.Engines.Input.Tick);

    // Add main game loop.
    core.AddTick(Tick);

  }(TG.Engines.Core));

  return that;
})(TG.Engines.Game || {});
<|endoftext|>


<commit_before>import 'babel-polyfill';

import fs from 'fs';
import Express from 'express';
import helmet from 'helmet';
import path from 'path';
import cookie from 'react-cookie';
import React from 'react';
import ReactDOM from 'react-dom/server';

import { Provider } from 'react-redux';
import { match } from 'react-router';
import { ReduxAsyncConnect, loadOnServer } from 'redux-async-connect';

import WebpackIsomorphicTools from 'webpack-isomorphic-tools';
import WebpackIsomorphicToolsConfig from 'webpack-isomorphic-tools-config';
import ServerHtml from 'core/containers/ServerHtml';

import config from 'config';
import { setLang, setJWT } from 'core/actions';
import log from 'core/logger';
import { getDirection, getLangFromRouter, langToLocale } from 'core/i18n/utils';
import I18nProvider from 'core/i18n/Provider';
import Jed from 'jed';

const env = config.util.getEnv('NODE_ENV');
const version = path.join(config.get('basePath'), 'version.json');
const isDeployed = config.get('isDeployed');
const isDevelopment = config.get('isDevelopment');

const errorString = 'Internal Server Error';
const appName = config.get('appName');

function logRequests(req, res, next) {
  const start = new Date();
  next();
  const finish = new Date();
  const elapsed = finish - start;
  log.info({ req, res, start, finish, elapsed });
}

function baseServer(routes, createStore, { appInstanceName = appName } = {}) {
  const app = new Express();
  app.disable('x-powered-by');

  app.use(logRequests);

  // Sets X-Frame-Options
  app.use(helmet.frameguard(config.get('frameGuard')));

  // Sets x-content-type-options:"nosniff"
  app.use(helmet.noSniff());

  // Sets x-xss-protection:"1; mode=block"
  app.use(helmet.xssFilter());

  // CSP configuration.
  app.use(helmet.contentSecurityPolicy(config.get('CSP')));

  app.use(Express.static(path.join(config.get('basePath'), 'dist')));

  // Return version information as json
  app.get('/__version__', (req, res) => {
    fs.stat(version, (err) => {
      if (err) {
        res.sendStatus(415);
      } else {
        res.setHeader('Content-Type', 'application/json');
        fs.createReadStream(version).pipe(res);
      }
    });
  });

  // Return 200 for csp reports - this will need to be overridden when deployed.
  app.post('/__cspreport__', (req, res) => res.status(200).end('ok'));

  // Redirect from / for the search app it's a 302 to prevent caching.
  if (appInstanceName === 'search') {
    app.get('/', (req, res) => res.redirect(302, '/search'));
  }

  app.use((req, res) => {
    if (isDevelopment) {
      log.info('Running in Development Mode');

      // clear require() cache if in development mode
      webpackIsomorphicTools.refresh();
    }

    match({ routes, location: req.url }, (err, redirectLocation, renderProps) => {
      cookie.plugToRequest(req, res);

      if (err) {
        log.error({ err, req });
        return res.status(500).end(errorString);
      }

      if (!renderProps) {
        return res.status(404).end('Not found.');
      }

      const store = createStore();
      const token = cookie.load(config.get('cookieName'));
      if (token) {
        store.dispatch(setJWT(token));
      }
      // Get SRI for deployed services only.
      const sriData = (isDeployed) ? JSON.parse(
        fs.readFileSync(path.join(config.get('basePath'), 'dist/sri.json'))
      ) : {};

      const lang = getLangFromRouter(renderProps);

      if (renderProps.params && renderProps.params.lang) {
        const origLang = renderProps.params.lang;
        if (lang !== origLang) {
          // If the original lang param (found via the router) matches
          // the first part of the original url path, redirect to the
          // normalized lang (which will be the default if invalid).
          // eslint-disable-next-line no-unused-vars
          const [_, firstPart, ...rest] = req.originalUrl.split('/');
          if (origLang === decodeURIComponent(firstPart)) {
            // The '' provides a leading /
            return res.redirect(301, ['', lang, ...rest].join('/'));
          }
        }
      }

      const dir = getDirection(lang);
      const locale = langToLocale(lang);
      store.dispatch(setLang(lang));

      function hydrateOnClient(props = {}) {
        const pageProps = {
          appName: appInstanceName,
          assets: webpackIsomorphicTools.assets(),
          htmlLang: lang,
          htmlDir: dir,
          includeSri: isDeployed,
          sriData,
          store,
          trackingEnabled: config.get('trackingEnabled'),
          ...props,
        };

        const HTML = ReactDOM.renderToString(
          <ServerHtml {...pageProps} />);
        res.send(`<!DOCTYPE html>\n${HTML}`);
      }

      // Set disableSSR to true to debug
      // client-side-only render.
      if (config.get('disableSSR') === true) {
        return Promise.resolve(hydrateOnClient());
      }

      return loadOnServer({ ...renderProps, store })
        .then(() => {
          // eslint-disable-next-line global-require
          let jedData = {};
          try {
            if (locale !== langToLocale(config.get('defaultLang'))) {
              // eslint-disable-next-line global-require
              jedData = require(`json!../../locale/${locale}/${appInstanceName}.json`);
            }
          } catch (e) {
            log.info(dedent`Locale not found or required for locale: "${locale}".
              Falling back to default lang: "${config.get('defaultLang')}"`);
          }
          const i18n = new Jed(jedData);
          const InitialComponent = (
            <I18nProvider i18n={i18n}>
              <Provider store={store} key="provider">
                <ReduxAsyncConnect {...renderProps} />
              </Provider>
            </I18nProvider>
          );

          return hydrateOnClient({ component: InitialComponent });
        })
        .catch((error) => {
          log.error({ err: error });
          res.status(500).end(errorString);
        });
    });
  });

  // eslint-disable-next-line no-unused-vars
  app.use((err, req, res, next) => {
    log.error({ err });
    res.status(500).end(errorString);
  });

  return app;
}

export function runServer({ listen = true, app = appName } = {}) {
  if (!app) {
    log.fatal(`Please specify a valid appName from ${config.get('validAppNames')}`);
    process.exit(1);
  }

  const port = config.get('serverPort');
  const host = config.get('serverHost');

  const isoMorphicServer = new WebpackIsomorphicTools(WebpackIsomorphicToolsConfig);
  return isoMorphicServer.development(isDevelopment)
    .server(config.get('basePath'))
    .then(() => {
      global.webpackIsomorphicTools = isoMorphicServer;
      // Webpack Isomorphic tools is ready
      // now fire up the actual server.
      return new Promise((resolve, reject) => {
        /* eslint-disable global-require */
        const routes = require(`${app}/routes`).default;
        const createStore = require(`${app}/store`).default;
        /* eslint-enable global-require */
        const server = baseServer(routes, createStore, { appInstanceName: app });
        if (listen === true) {
          server.listen(port, host, (err) => {
            if (err) {
              reject(err);
            }
            log.info(`🔥  Addons-frontend server is running [ENV:${env}] [APP:${app}] ` +
                     `[isDevelopment:${isDevelopment}] [isDeployed:${isDeployed}] ` +
                     `[apiHost:${config.get('apiHost')}] [apiPath:${config.get('apiPath')}]`);
            log.info(`👁  Open your browser at http://${host}:${port} to view it.`);
            resolve(server);
          });
        } else {
          resolve(server);
        }
      });
    })
    .catch((err) => {
      log.error({ err });
    });
}

export default baseServer;
<commit_msg>Always send an STS header on secure requests<commit_after>import 'babel-polyfill';

import fs from 'fs';
import Express from 'express';
import helmet from 'helmet';
import path from 'path';
import cookie from 'react-cookie';
import React from 'react';
import ReactDOM from 'react-dom/server';

import { Provider } from 'react-redux';
import { match } from 'react-router';
import { ReduxAsyncConnect, loadOnServer } from 'redux-async-connect';

import WebpackIsomorphicTools from 'webpack-isomorphic-tools';
import WebpackIsomorphicToolsConfig from 'webpack-isomorphic-tools-config';
import ServerHtml from 'core/containers/ServerHtml';

import config from 'config';
import { setLang, setJWT } from 'core/actions';
import log from 'core/logger';
import { getDirection, getLangFromRouter, langToLocale } from 'core/i18n/utils';
import I18nProvider from 'core/i18n/Provider';
import Jed from 'jed';

const env = config.util.getEnv('NODE_ENV');
const version = path.join(config.get('basePath'), 'version.json');
const isDeployed = config.get('isDeployed');
const isDevelopment = config.get('isDevelopment');

const errorString = 'Internal Server Error';
const appName = config.get('appName');

function logRequests(req, res, next) {
  const start = new Date();
  next();
  const finish = new Date();
  const elapsed = finish - start;
  log.info({ req, res, start, finish, elapsed });
}

function baseServer(routes, createStore, { appInstanceName = appName } = {}) {
  const app = new Express();
  app.disable('x-powered-by');

  app.use(logRequests);

  // Set HSTS, note: helmet uses ms not seconds.
  app.use(helmet.hsts({ maxAge: 31536000000 }));

  // Sets X-Frame-Options
  app.use(helmet.frameguard(config.get('frameGuard')));

  // Sets x-content-type-options:"nosniff"
  app.use(helmet.noSniff());

  // Sets x-xss-protection:"1; mode=block"
  app.use(helmet.xssFilter());

  // CSP configuration.
  app.use(helmet.contentSecurityPolicy(config.get('CSP')));

  app.use(Express.static(path.join(config.get('basePath'), 'dist')));

  // Return version information as json
  app.get('/__version__', (req, res) => {
    fs.stat(version, (err) => {
      if (err) {
        res.sendStatus(415);
      } else {
        res.setHeader('Content-Type', 'application/json');
        fs.createReadStream(version).pipe(res);
      }
    });
  });

  // Return 200 for csp reports - this will need to be overridden when deployed.
  app.post('/__cspreport__', (req, res) => res.status(200).end('ok'));

  // Redirect from / for the search app it's a 302 to prevent caching.
  if (appInstanceName === 'search') {
    app.get('/', (req, res) => res.redirect(302, '/search'));
  }

  app.use((req, res) => {
    if (isDevelopment) {
      log.info('Running in Development Mode');

      // clear require() cache if in development mode
      webpackIsomorphicTools.refresh();
    }

    match({ routes, location: req.url }, (err, redirectLocation, renderProps) => {
      cookie.plugToRequest(req, res);

      if (err) {
        log.error({ err, req });
        return res.status(500).end(errorString);
      }

      if (!renderProps) {
        return res.status(404).end('Not found.');
      }

      const store = createStore();
      const token = cookie.load(config.get('cookieName'));
      if (token) {
        store.dispatch(setJWT(token));
      }
      // Get SRI for deployed services only.
      const sriData = (isDeployed) ? JSON.parse(
        fs.readFileSync(path.join(config.get('basePath'), 'dist/sri.json'))
      ) : {};

      const lang = getLangFromRouter(renderProps);

      if (renderProps.params && renderProps.params.lang) {
        const origLang = renderProps.params.lang;
        if (lang !== origLang) {
          // If the original lang param (found via the router) matches
          // the first part of the original url path, redirect to the
          // normalized lang (which will be the default if invalid).
          // eslint-disable-next-line no-unused-vars
          const [_, firstPart, ...rest] = req.originalUrl.split('/');
          if (origLang === decodeURIComponent(firstPart)) {
            // The '' provides a leading /
            return res.redirect(301, ['', lang, ...rest].join('/'));
          }
        }
      }

      const dir = getDirection(lang);
      const locale = langToLocale(lang);
      store.dispatch(setLang(lang));

      function hydrateOnClient(props = {}) {
        const pageProps = {
          appName: appInstanceName,
          assets: webpackIsomorphicTools.assets(),
          htmlLang: lang,
          htmlDir: dir,
          includeSri: isDeployed,
          sriData,
          store,
          trackingEnabled: config.get('trackingEnabled'),
          ...props,
        };

        const HTML = ReactDOM.renderToString(
          <ServerHtml {...pageProps} />);
        res.send(`<!DOCTYPE html>\n${HTML}`);
      }

      // Set disableSSR to true to debug
      // client-side-only render.
      if (config.get('disableSSR') === true) {
        return Promise.resolve(hydrateOnClient());
      }

      return loadOnServer({ ...renderProps, store })
        .then(() => {
          // eslint-disable-next-line global-require
          let jedData = {};
          try {
            if (locale !== langToLocale(config.get('defaultLang'))) {
              // eslint-disable-next-line global-require
              jedData = require(`json!../../locale/${locale}/${appInstanceName}.json`);
            }
          } catch (e) {
            log.info(dedent`Locale not found or required for locale: "${locale}".
              Falling back to default lang: "${config.get('defaultLang')}"`);
          }
          const i18n = new Jed(jedData);
          const InitialComponent = (
            <I18nProvider i18n={i18n}>
              <Provider store={store} key="provider">
                <ReduxAsyncConnect {...renderProps} />
              </Provider>
            </I18nProvider>
          );

          return hydrateOnClient({ component: InitialComponent });
        })
        .catch((error) => {
          log.error({ err: error });
          res.status(500).end(errorString);
        });
    });
  });

  // eslint-disable-next-line no-unused-vars
  app.use((err, req, res, next) => {
    log.error({ err });
    res.status(500).end(errorString);
  });

  return app;
}

export function runServer({ listen = true, app = appName } = {}) {
  if (!app) {
    log.fatal(`Please specify a valid appName from ${config.get('validAppNames')}`);
    process.exit(1);
  }

  const port = config.get('serverPort');
  const host = config.get('serverHost');

  const isoMorphicServer = new WebpackIsomorphicTools(WebpackIsomorphicToolsConfig);
  return isoMorphicServer.development(isDevelopment)
    .server(config.get('basePath'))
    .then(() => {
      global.webpackIsomorphicTools = isoMorphicServer;
      // Webpack Isomorphic tools is ready
      // now fire up the actual server.
      return new Promise((resolve, reject) => {
        /* eslint-disable global-require */
        const routes = require(`${app}/routes`).default;
        const createStore = require(`${app}/store`).default;
        /* eslint-enable global-require */
        const server = baseServer(routes, createStore, { appInstanceName: app });
        if (listen === true) {
          server.listen(port, host, (err) => {
            if (err) {
              reject(err);
            }
            log.info(`🔥  Addons-frontend server is running [ENV:${env}] [APP:${app}] ` +
                     `[isDevelopment:${isDevelopment}] [isDeployed:${isDeployed}] ` +
                     `[apiHost:${config.get('apiHost')}] [apiPath:${config.get('apiPath')}]`);
            log.info(`👁  Open your browser at http://${host}:${port} to view it.`);
            resolve(server);
          });
        } else {
          resolve(server);
        }
      });
    })
    .catch((err) => {
      log.error({ err });
    });
}

export default baseServer;
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';

class HeaderBar extends React.Component {

  constructor(){

    super();
    this.enablePopoversAndTooltips();
  }

  // Enables the popover and tooltips to display their content when hovered over
  enablePopoversAndTooltips(){
    this.changeButton();
    // select all elements with the 'data-toggle = tooltip'
    $(function () {
      $('[data-toggle="tooltip"]').tooltip()
    });

    // select all elements with the 'data-toggle = popover'
    $(function () {
      $('[data-toggle="popover"]').popover()
    });
  }

  // Separately prevents the popovers on the page from displaying
  hidePopovers(){

    $(function () {
      $('[data-toggle="popover"]').popover('destroy')
    });
  }

  // Separately prevents the tooltips on the page from displaying
  hideTooltips(){

    $(function () {
      $('[data-toggle="tooltip"]').tooltip('destroy')
    });
  }

  // Calls both the functions that prevent the tooltips and popovers from displaying
  hidePopoversAndTooptips(){
    this.changeButton();
    this.hidePopovers();
    this.hideTooltips();
  }

  checkForEnter(str_expression) {

    if (str_expression.key == 'Enter') {
      this.props.update();
    }
  }

  //method to change button back and forth between on/off for tutorial
  changeButton(){
    $('.btn-toggle').click(function() {
      $(this).find('.btn').toggleClass('active');
      if ($(this).find('.btn-primary').size()>0) {
      	$(this).find('.btn').toggleClass('btn-primary');
      }
      $(this).find('.btn').toggleClass('btn-default');
    });

  }

  render(){
    return (

          <input type="text" className="form-control" placeholder="List item..." name="text" id="text" onKeyUp={this.checkForEnter.bind(this)} size="75" defaultValue={this.props.text}
           data-toggle="tooltip" data-placement="bottom" title="This is the new text we will add to the list!"/>

              <button type="button" className="btn btn-default" data-toggle="popover" data-container="body" data-placement="right" title="Add Item"
                data-content="This will add the item to the list!" data-trigger="hover" onClick={this.props.update}>
                Add!
              </button>

              <button type="button" className="btn btn-default" data-toggle="popover" data-container="body" data-placement="bottom" title="Remove Item"
                data-content="This remove the last item from the list" data-trigger="hover" onClick={this.props.remove}>
                Remove!
              </button>

                  <button className = "btn btn-default" id = "button_on" onClick = {this.enablePopoversAndTooltips.bind(this)} > ON </button>
                  <button className = "btn btn-primary active" id = "button_off" onClick = {this.hidePopoversAndTooptips.bind(this)} > OFF </button>

    );
  }
}

export default HeaderBar
<commit_msg>Single Click Toggle Added<commit_after>import React from 'react';
import ReactDOM from 'react-dom';

class HeaderBar extends React.Component {

  constructor(){

    super();
  }

  // Enables the popover and tooltips to display their content when hovered over
  enablePopoversAndTooltips(){

    this.enablePopovers();
    this.enableTooltips();
  }

  enablePopovers(){

    // select all elements with the 'data-toggle = popover'
    $(function () {
      $('[data-toggle="popover"]').popover()
    });
  }

  enableTooltips(){

    // select all elements with the 'data-toggle = tooltip'
      $(function () {
        $('[data-toggle="tooltip"]').tooltip()
      });
  }

  // Separately prevents the popovers on the page from displaying
  hidePopovers(){

    $(function () {
      $('[data-toggle="popover"]').popover('destroy')
    });
  }

  // Separately prevents the tooltips on the page from displaying
  hideTooltips(){

    $(function () {
      $('[data-toggle="tooltip"]').tooltip('destroy')
    });
  }

  // Calls both the functions that prevent the tooltips and popovers from displaying
  hidePopoversAndTooptips(){

    this.hidePopovers();
    this.hideTooltips();
  }

  checkForEnter(str_expression) {

    if (str_expression.key == 'Enter') {
      this.props.update();
    }
  }

  // Method to visually change button back and forth between on/off for tutorial
  changeButton(){

    var on = document.getElementById('button_on');
    var off = document.getElementById('button_off');

      if (on.className == "btn btn-default"){

        on.className = "btn btn-primary active";
        off.className = "btn btn-default";

      }else if (off.className == "btn btn-default") {

        off.className = "btn btn-primary active";
        on.className = "btn btn-default";
    }
  }

    toggle(){

      var on = document.getElementById('button_on');
      var off = document.getElementById('button_off');

      this.changeButton();

      if (on.className == "btn btn-primary active"){

        this.enablePopoversAndTooltips()

      }else if (off.className == "btn btn-primary active") {
        this.hidePopoversAndTooptips();
      }
    }

  render(){
    return (

          <input type="text" className="form-control" placeholder="List item..." name="text" id="text" onKeyUp={this.checkForEnter.bind(this)} size="75" defaultValue={this.props.text}
           data-toggle="tooltip" data-placement="bottom" title="This is the new text we will add to the list!"/>

              <button type="button" className="btn btn-default" data-toggle="popover" data-container="body" data-placement="right" title="Add Item"
                data-content="This will add the item to the list!" data-trigger="hover" onClick={this.props.update}>
                Add!
              </button>

              <button type="button" className="btn btn-default" data-toggle="popover" data-container="body" data-placement="bottom" title="Remove Item"
                data-content="This remove the last item from the list" data-trigger="hover" onClick={this.props.remove}>
                Remove!
              </button>

                  <button className = "btn btn-default" id = "button_on" onClick = {this.toggle.bind(this)} > ON </button>
                  <button className = "btn btn-primary active" id = "button_off" onClick = {this.toggle.bind(this)} > OFF </button>

    );
  }
}

export default HeaderBar
<|endoftext|>


<commit_before>function EventBlock(name, start, events) {
    this.name = name;
    this.start = start;
    this.events = events;

    this.recalculate();
};

function Event(event_id, category, name, duration) {
    this.name = name;
    this.category = category;
    this.event_id = event_id;
    this.duration = duration;
    this.active = true;
};

EventBlock.prototype = {
    recalculate: function() {
        var point = new Date(this.start);
        for(var i = 0; i < this.events.length; i++){
            var ev = this.events[i];
            if(ev.active){
                ev.start = new Date(point);
                point.setSeconds(point.getSeconds() + ev.duration);
            }
        }
    }
}

var BlockComponent = Vue.extend({
    created: function(){
        this.$on('event-changed', function(){
            console.log('Recalculating...');
            this.recalculate();
        });
    }
});

var EventComponent = Vue.extend({
    created: function() {
        this.$on('status-changed', function(ev_id, is_active){
            if(ev_id == this.event_id){
                this.active = is_active;
                console.log("Found on " + this.event_id);
                this.$dispatch('event-changed');
            }
        })
    }
});

Vue.component('event', EventComponent);
Vue.component('event-block', BlockComponent);
Vue.filter('hourmin', function(value){
    hour = value.getHours();
    minutes = value.getMinutes();

    return (hour < 10 ? "0" + hour : hour) + ":" +
           (minutes < 10 ? "0" + minutes : minutes)
})

/*
for(var i = 1; i < 10; i++){
    var new_events = []

    for(var a = 1; a < 31; a++){
        new_events.push(new Event(
            i + "_" + a,
            "Event #" + i + "-" + a,
            120))
    }
    event_blocks.push(new EventBlock(
        "Block #" + i,
        new Date(2014, 3, 30, 10 + i, 0, 0),
        new_events))
}
*/

function loadProgram(){
    var self = this;

    $.ajax('/performances/list/blocks', {
        success: function(blocks){
            self.blocks = {};
            for(var bl_id = 0; bl_id < blocks.length; bl_id++){
                self.blocks[blocks[bl_id].id] = blocks[bl_id];
            }

            $.ajax('/performances/list/categories', {
                success: function(categories){
                    self.categories = {};

                    for(var cat_id = 0; cat_id < categories.length; cat_id++){
                        self.categories[categories[cat_id].id] = categories[cat_id];
                    }

                    $.ajax('/performances/list/events', {
                        success: function(events){
                            self.events = {};
                            for(var i= 0; i < events.length; i++){
                                ev = events[i];
                                self.events[ev.id] = new Event(
                                    "event_" + ev.id,
                                    ev.category ? ev.category.name : "(неизвестно)",
                                    ev.description,
                                    ev.duration);
                            }
                            $.ajax('/performances/list/program', {
                                 success: function(by_blocks){
                                    event_blocks = [];
                                    var by_start_date = function(a, b){
                                        return a.start - b.start
                                    }
                                    for(key in by_blocks){
                                        if(by_blocks.hasOwnProperty(key)){
                                            console.log(key);
                                            block_def = self.blocks[key];
                                            var in_block = [];
                                            var event_ids = by_blocks[key];
                                            for(var b_i = 0; b_i < event_ids.length; b_i++){
                                                in_block.push(self.events[event_ids[b_i]]);
                                            }
                                            event_blocks.push(new EventBlock(
                                                block_def.name,
                                                block_def.start,
                                                in_block));
                                        }
                                    }
                                    event_blocks = event_blocks.sort(by_start_date);
                                    var roll = new Vue({
                                        el: "#roll",
                                        data: {
                                            blocks: event_blocks
                                        }});

                                }});
                        }
                    });
                    // $.ajax('/performances/list/program', {
                    //     success: function(program){
                    //         // var roll = new Vue({
                    //         //     el: "#roll",
                    //         //     data: {
                    //         //         blocks: event_blocks
                    //         //     },
                    //         //     methods: {
                    //         //         set_active: function(ev_id, is_active){
                    //         //             this.$broadcast('status-changed', ev_id, is_active)
                    //         //             //$('html,body').animate({scrollTop:$("#event-" + ev_id).offset().top}, 500);
                    //         //         }
                    //         //     }
                    //         // });

                    //     }});

                }
            });
        }
    });
}

loadProgram();<commit_msg>Removed placeholder for empty category name.<commit_after>function EventBlock(name,  start, events) {
    this.name = name;
    this.start = start;
    this.events = events;

    this.recalculate();
};

function Event(event_id, category, name, duration) {
    this.name = name;
    this.category = category;
    this.event_id = event_id;
    this.duration = duration;
    this.active = true;
};

EventBlock.prototype = {
    recalculate: function() {
        var point = new Date(this.start);
        for(var i = 0; i < this.events.length; i++){
            var ev = this.events[i];
            if(ev.active){
                ev.start = new Date(point);
                point.setSeconds(point.getSeconds() + ev.duration);
            }
        }
    }
}

var BlockComponent = Vue.extend({
    created: function(){
        this.$on('event-changed', function(){
            console.log('Recalculating...');
            this.recalculate();
        });
    }
});

var EventComponent = Vue.extend({
    created: function() {
        this.$on('status-changed', function(ev_id, is_active){
            if(ev_id == this.event_id){
                this.active = is_active;
                console.log("Found on " + this.event_id);
                this.$dispatch('event-changed');
            }
        })
    }
});

Vue.component('event', EventComponent);
Vue.component('event-block', BlockComponent);
Vue.filter('hourmin', function(value){
    hour = value.getHours();
    minutes = value.getMinutes();

    return (hour < 10 ? "0" + hour : hour) + ":" +
           (minutes < 10 ? "0" + minutes : minutes)
})

/*
for(var i = 1; i < 10; i++){
    var new_events = []

    for(var a = 1; a < 31; a++){
        new_events.push(new Event(
            i + "_" + a,
            "Event #" + i + "-" + a,
            120))
    }
    event_blocks.push(new EventBlock(
        "Block #" + i,
        new Date(2014, 3, 30, 10 + i, 0, 0),
        new_events))
}
*/

function loadProgram(){
    var self = this;

    $.ajax('/performances/list/blocks', {
        success: function(blocks){
            self.blocks = {};
            for(var bl_id = 0; bl_id < blocks.length; bl_id++){
                self.blocks[blocks[bl_id].id] = blocks[bl_id];
            }

            $.ajax('/performances/list/categories', {
                success: function(categories){
                    self.categories = {};

                    for(var cat_id = 0; cat_id < categories.length; cat_id++){
                        self.categories[categories[cat_id].id] = categories[cat_id];
                    }

                    $.ajax('/performances/list/events', {
                        success: function(events){
                            self.events = {};
                            for(var i= 0; i < events.length; i++){
                                ev = events[i];
                                self.events[ev.id] = new Event(
                                    "event_" + ev.id,
                                    ev.category ? ev.category.name : "",
                                    ev.description,
                                    ev.duration);
                            }
                            $.ajax('/performances/list/program', {
                                 success: function(by_blocks){
                                    event_blocks = [];
                                    var by_start_date = function(a, b){
                                        return a.start - b.start
                                    }
                                    for(key in by_blocks){
                                        if(by_blocks.hasOwnProperty(key)){
                                            console.log(key);
                                            block_def = self.blocks[key];
                                            var in_block = [];
                                            var event_ids = by_blocks[key];
                                            for(var b_i = 0; b_i < event_ids.length; b_i++){
                                                in_block.push(self.events[event_ids[b_i]]);
                                            }
                                            event_blocks.push(new EventBlock(
                                                block_def.name,
                                                block_def.start,
                                                in_block));
                                        }
                                    }
                                    event_blocks = event_blocks.sort(by_start_date);
                                    var roll = new Vue({
                                        el: "#roll",
                                        data: {
                                            blocks: event_blocks
                                        }});

                                }});
                        }
                    });
                    // $.ajax('/performances/list/program', {
                    //     success: function(program){
                    //         // var roll = new Vue({
                    //         //     el: "#roll",
                    //         //     data: {
                    //         //         blocks: event_blocks
                    //         //     },
                    //         //     methods: {
                    //         //         set_active: function(ev_id, is_active){
                    //         //             this.$broadcast('status-changed', ev_id, is_active)
                    //         //             //$('html,body').animate({scrollTop:$("#event-" + ev_id).offset().top}, 500);
                    //         //         }
                    //         //     }
                    //         // });

                    //     }});

                }
            });
        }
    });
}

loadProgram();<|endoftext|>


<commit_before>var fs = require('fs');

var $       = require('zepto-browserify').$,
    Ractive = require('ractive');

var ES  = require('../es'),
    API = require('../api');

module.exports = Ractive.extend({

  template: fs.readFileSync(__dirname + '/../../templates/score-template.html', 'utf-8'),

  data: {
    score: { a: 0, b: 0 },
    sets: { a: 0, b: 0 },
    started: false,
    palyeraclass: '',
    playerbclass: '',
    vsinvertedclass: '',
    ranking: []
  },

  init: function () {
    var self = this;
    ES.on('score', function (data) {
      self.set('score', data.score);
      self.set('sets', data.sets);
      self.set('winner', data.winner);
      self.set('players', data.players);
      self.set('draw', data.draw);
      self.set('time', data.time);
      self.set('showscore', data && (data.status === 'ready' || data.status === 'started' || data.status === 'stopped'));
      self.set('vsinvertedclass', data && data.sets && ((data.sets.a + data.sets.b) % 2 === 0 ? '' : 'vs-score-inverted'));
      self.set('playeraclass', data && (data.servingPlayer === 'a' ? 'serving-player' : ''));
      self.set('playerbclass', data && (data.servingPlayer === 'b' ? 'serving-player' : ''));
    });

    ES.on('ranking', function (ranking) {
      self.set('ranking', ranking);
    });

    ES.on('sound', function (filename) {
      new Audio(filename).play();
    });

    API.getRanking(function (ranking) {
      self.set('ranking', ranking);
    });
  }
});
<commit_msg>Fix file path for sounds<commit_after>var fs = require('fs');

var $       = require('zepto-browserify').$,
    Ractive = require('ractive');

var ES  = require('../es'),
    API = require('../api');

module.exports = Ractive.extend({

  template: fs.readFileSync(__dirname + '/../../templates/score-template.html', 'utf-8'),

  data: {
    score: { a: 0, b: 0 },
    sets: { a: 0, b: 0 },
    started: false,
    palyeraclass: '',
    playerbclass: '',
    vsinvertedclass: '',
    ranking: []
  },

  init: function () {
    var self = this;
    ES.on('score', function (data) {
      self.set('score', data.score);
      self.set('sets', data.sets);
      self.set('winner', data.winner);
      self.set('players', data.players);
      self.set('draw', data.draw);
      self.set('time', data.time);
      self.set('showscore', data && (data.status === 'ready' || data.status === 'started' || data.status === 'stopped'));
      self.set('vsinvertedclass', data && data.sets && ((data.sets.a + data.sets.b) % 2 === 0 ? '' : 'vs-score-inverted'));
      self.set('playeraclass', data && (data.servingPlayer === 'a' ? 'serving-player' : ''));
      self.set('playerbclass', data && (data.servingPlayer === 'b' ? 'serving-player' : ''));
    });

    ES.on('ranking', function (ranking) {
      self.set('ranking', ranking);
    });

    ES.on('sound', function (filename) {
      new Audio(`sounds/${filename}`).play();
    });

    API.getRanking(function (ranking) {
      self.set('ranking', ranking);
    });
  }
});
<|endoftext|>


<commit_before>import SwarmBase from 'swarm'
import swarmFactory from './swarmfactory'

let Swarm = swarmFactory(SwarmBase)

// TODO get rid of this and use the logged in user's name and session id
let app = {}
app.id = window.localStorage.getItem('localuser') || 'A' + Swarm.Spec.int2base((Math.random() * 10000) | 0)
window.localStorage.setItem('localuser', app.id)

// server host uri
app.wsServerUri = 'ws://' + window.location.host

let hash = window.location.hash || '#0'

// create Host
app.host = Swarm.env.localhost = new Swarm.Host(app.id + hash.replace('#', '~'))

// connect to server
app.host.connect(app.wsServerUri, {delay: 50})

//catch online/offline status changes
app.host.on('reon', function(spec, val) {  // eslint-disable-line no-unused-vars
  document.body.setAttribute('connected', app.host.isUplinked())
})
app.host.on('reoff', function(spec, val) { // eslint-disable-line no-unused-vars
  document.body.setAttribute('connected', app.host.isUplinked())
})
app.host.on('off', function(spec, val) { // eslint-disable-line no-unused-vars
  document.body.setAttribute('connected', app.host.isUplinked())
})

window.onbeforeunload = function() {
  // close host
  app.host.close()
}

export default Swarm
<commit_msg>Fix websocket support in IE10<commit_after>import SwarmBase from 'swarm'
import swarmFactory from './swarmfactory'

let Swarm = swarmFactory(SwarmBase)

// TODO get rid of this and use the logged in user's name and session id
let app = {}
app.id = window.localStorage.getItem('localuser') || 'A' + Swarm.Spec.int2base((Math.random() * 10000) | 0)
window.localStorage.setItem('localuser', app.id)

// server host uri (/websocket is appended because https://github.com/websockets/ws/issues/131)
app.wsServerUri = 'ws://' + window.location.host + '/websocket'

let hash = window.location.hash || '#0'

// create Host
app.host = Swarm.env.localhost = new Swarm.Host(app.id + hash.replace('#', '~'))

// connect to server
app.host.connect(app.wsServerUri, {delay: 50})

//catch online/offline status changes
app.host.on('reon', function(spec, val) {  // eslint-disable-line no-unused-vars
  document.body.setAttribute('connected', app.host.isUplinked())
})
app.host.on('reoff', function(spec, val) { // eslint-disable-line no-unused-vars
  document.body.setAttribute('connected', app.host.isUplinked())
})
app.host.on('off', function(spec, val) { // eslint-disable-line no-unused-vars
  document.body.setAttribute('connected', app.host.isUplinked())
})

window.onbeforeunload = function() {
  // close host
  app.host.close()
}

export default Swarm
<|endoftext|>


<commit_before>/*
 * Author : Max-Andre Zil
 * Version: 0.21
 * Date: 29.04.2014
 * Functions: numToScreen() - displays the number pressed in the appropriate text field
 *            signPressed() - displays the sign pressed in the appropriate text box and changes the value
 *                            of sign_used.
 *  */
/* GLOBAL VARIABLES */
var sign_used = 0;
/* GLOBAL VARIABLES */

//numToScreen - displays the number pressed in the appropriate text box based on whether or not a sign button has been pressed.
function numToScreen( num ){
    if( sign_used == 0 ){
        first_num.value += num;
    }else{
        second_num.value += num;
    }
}
<commit_msg>testing the commit<commit_after>/*
 * Author : Max-Andre Zils
 * Version: 0.21
 * Date: 29.04.2014
 * Functions: numToScreen() - displays the number pressed in the appropriate text field
 *            signPressed() - displays the sign pressed in the appropriate text box and changes the value
 *                            of sign_used.
 *  */
/* GLOBAL VARIABLES */
var sign_used = 0;
/* GLOBAL VARIABLES */

//numToScreen - displays the number pressed in the appropriate text box based on whether or not a sign button has been pressed.
function numToScreen( num ){
    if( sign_used == 0 ){
        first_num.value += num;
    }else{
        second_num.value += num;
    }
}
function clearAll(){
    var clear_inputs = confirm( "Are you sure you want clear all fields?" );
    if( clear_inputs ){
        first_num.value = null;
        second_num.value = null;

    }
}
<|endoftext|>


<commit_before>var express = require('express'),
	router = express.Router(),
	net = require('net'),
	fs = require('fs');

/* GET home page. */
router.post('/', function(req, res) {
	// console.log(req.body);
	// you can get commit information from request body

	var client = net.createConnection(socketPath);

	client.on('connect', function () {
		console.log('check connection');

		var turnoffCnt = 0;

		if (haproxyStat !== null) {

			for(var j=0; j<servers.count; j++) {
				var min = null;
				for(var i=0; i<haproxyStat.length; i++) {
					var status = haproxyStat[i];

					if (status.svname !== 'FRONTEND' && status.svname !== 'BACKEND') {

						if (min === null || status.scur < min.scur) {
							min = status;
						}
					}
				}

				if (min === null) {
					console.error('Server list is not valid');
					return;
				}else {
					var writeResult = client.write('disable server '+min['# pxname']+'/'+min['svname']+'\r\n');
				}
			}
		}

		client.on('data', function (data) {
			if (data === '\r\n') {
				turnoffCnt++;
			}else {
				console.error('Disable server failed');
				return;
			}
		});

		client.on('error', function (error) {
			console.log('Error Connection: '+error);
		});
	});

	res.send('complete');
});

module.exports = router;
<commit_msg>Add log to check command sending<commit_after>var express = require('express'),
	router = express.Router(),
	net = require('net'),
	fs = require('fs');

/* GET home page. */
router.post('/', function(req, res) {
	// console.log(req.body);
	// you can get commit information from request body

	var client = net.createConnection(socketPath);

	client.on('connect', function () {
		console.log('check connection');

		var turnoffCnt = 0;

		if (haproxyStat !== null) {
			for(var j=0; j<servers.count; j++) {
				var min = null;
				for(var i=0; i<haproxyStat.length; i++) {
					var status = haproxyStat[i];

					if (status.svname !== 'FRONTEND' && status.svname !== 'BACKEND') {

						if (min === null || status.scur < min.scur) {
							min = status;
						}
					}
				}

				if (min === null) {
					console.error('Server list is not valid');
					return;
				}else {
					console.log('SERVER: '+min.svname);
					var writeResult = client.write('disable server '+min['# pxname']+'/'+min['svname']+'\r\n');
				}
			}
		}

		client.on('data', function (data) {
			console.log('RECEIVED: '+data);
			if (data === '\r\n') {
				turnoffCnt++;
			}else {
				console.error('Disable server failed');
				return;
			}
		});

		client.on('error', function (error) {
			console.log('Error Connection: '+error);
		});
	});

	res.send('complete');
});

module.exports = router;
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import React, {Component} from 'react'
import {connect} from 'react-redux'
import {withRouter} from 'react-router-dom'
import SearchInput from 'components/SearchInput'
import {stringIsEmpty} from 'helpers/stringHelpers'
import {loadVideoPageFromClientSideAsync} from 'redux/actions/VideoActions'
import {clearSearchResults, searchContent} from 'redux/actions/ContentActions'
import {Color} from 'constants/css'
import {recordUserAction} from 'helpers/userDataHelpers'

@connect(
  state => ({
    searchResult: state.ContentReducer.searchResult,
    loggedIn: state.UserReducer.loggedIn
  }),
  {
    searchContent,
    loadVideoPage: loadVideoPageFromClientSideAsync,
    clearSearchResults
  }
)
@withRouter
export default class SearchBox extends Component {
  static propTypes = {
    history: PropTypes.object,
    searchResult: PropTypes.array,
    clearSearchResults: PropTypes.func,
    className: PropTypes.string,
    style: PropTypes.object,
    searchContent: PropTypes.func,
    loadVideoPage: PropTypes.func,
    loggedIn: PropTypes.bool
  }

  constructor() {
    super()
    this.state = {
      searchText: ''
    }
    this.onContentSearch = this.onContentSearch.bind(this)
    this.onSelect = this.onSelect.bind(this)
  }

  render() {
    const {searchResult, clearSearchResults, className, style} = this.props
    const {searchText} = this.state
    return (
      <form className={className} style={style}>
        <SearchInput
          placeholder="Search for Videos and Links"
          onChange={this.onContentSearch}
          value={searchText}
          searchResults={searchResult}
          renderItemLabel={
            item =>

                [{item.type === 'video' ? 'Video' : 'Link'}]
                 {item.label}

          }
          onClickOutSide={() => {
            this.setState({searchText: ''})
            clearSearchResults()
          }}
          onSelect={this.onSelect}
        />
      </form>
    )
  }

  onContentSearch(event) {
    const {searchContent, clearSearchResults} = this.props
    const text = event.target.value
    this.setState({searchText: text})
    if (stringIsEmpty(text)) {
      return clearSearchResults()
    }
    searchContent(text)
  }

  onSelect(item) {
    const {clearSearchResults, loadVideoPage, history, loggedIn} = this.props
    this.setState({searchText: ''})
    clearSearchResults()
    if (loggedIn) recordUserAction({action: 'search', target: item.type, subTarget: item.id})
    return loadVideoPage(item.id).then(
      () => history.push(`/${item.type}s/${item.id}`)
    )
  }
}
<commit_msg>search box now properly directs users to links<commit_after>import PropTypes from 'prop-types'
import React, {Component} from 'react'
import {connect} from 'react-redux'
import {withRouter} from 'react-router-dom'
import SearchInput from 'components/SearchInput'
import {stringIsEmpty} from 'helpers/stringHelpers'
import {loadVideoPageFromClientSideAsync} from 'redux/actions/VideoActions'
import {loadLinkPage} from 'redux/actions/LinkActions'
import {clearSearchResults, searchContent} from 'redux/actions/ContentActions'
import {Color} from 'constants/css'
import {recordUserAction} from 'helpers/userDataHelpers'

@connect(
  state => ({
    searchResult: state.ContentReducer.searchResult,
    loggedIn: state.UserReducer.loggedIn
  }),
  {
    searchContent,
    loadVideoPage: loadVideoPageFromClientSideAsync,
    loadLinkPage,
    clearSearchResults
  }
)
@withRouter
export default class SearchBox extends Component {
  static propTypes = {
    history: PropTypes.object,
    searchResult: PropTypes.array,
    clearSearchResults: PropTypes.func,
    className: PropTypes.string,
    style: PropTypes.object,
    searchContent: PropTypes.func,
    loadVideoPage: PropTypes.func,
    loadLinkPage: PropTypes.func,
    loggedIn: PropTypes.bool
  }

  constructor() {
    super()
    this.state = {
      searchText: ''
    }
    this.onContentSearch = this.onContentSearch.bind(this)
    this.onSelect = this.onSelect.bind(this)
  }

  render() {
    const {searchResult, clearSearchResults, className, style} = this.props
    const {searchText} = this.state
    return (
      <form className={className} style={style}>
        <SearchInput
          placeholder="Search for Videos and Links"
          onChange={this.onContentSearch}
          value={searchText}
          searchResults={searchResult}
          renderItemLabel={
            item =>

                [{item.type === 'video' ? 'Video' : 'Link'}]
                 {item.label}

          }
          onClickOutSide={() => {
            this.setState({searchText: ''})
            clearSearchResults()
          }}
          onSelect={this.onSelect}
        />
      </form>
    )
  }

  onContentSearch(event) {
    const {searchContent, clearSearchResults} = this.props
    const text = event.target.value
    this.setState({searchText: text})
    if (stringIsEmpty(text)) {
      return clearSearchResults()
    }
    searchContent(text)
  }

  onSelect(item) {
    const {clearSearchResults, loadVideoPage, loadLinkPage, history, loggedIn} = this.props
    this.setState({searchText: ''})
    clearSearchResults()
    if (loggedIn) recordUserAction({action: 'search', target: item.type, subTarget: item.id})
    if (item.type === 'video') {
      return loadVideoPage(item.id).then(
        () => history.push(`/${item.type}s/${item.id}`)
      )
    } else {
      return loadLinkPage(item.id).then(
        () => history.push(`/${item.type}s/${item.id}`)
      )
    }
  }
}
<|endoftext|>


<commit_before>export { decoder };

const base64String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

const BITS_ONES_0_5 = Number.parseInt("00111111", 2);  // 00111111 = 0x3F
const BITS_ONES_6_7 = Number.parseInt("11000000", 2);  // 11000000 = 0xC0
const BITS_ONES_6_6 = Number.parseInt("01000000", 2);  // 01000000 = 0x40

// Mapping table for base64 (as Uint8) to index.
//
// The value of decoded base64 is between [0, 63]. It uses only lowest 6 bits.
// The highest 2 bits can be used to store the byte count to advance.
// It is 0 for illegal base64 codes, and 1 for legal base64 codes.
//
let table_base64_Uint8_to_index = new Uint8Array( new ArrayBuffer(256) );
{
  // For all non-base64 codes, the 6th bit always 0.
  for (let i = 0; i < table_base64_Uint8_to_index.length; ++i)
    table_base64_Uint8_to_index[ i ] = 0;

  // For all legal base64 codes, the 6th bit always 1.
  {
    for (let i = 0; i < base64String.length; ++i) {
      let codePoint = base64String.codePointAt(i);
      table_base64_Uint8_to_index[ codePoint ] = i | BITS_ONES_6_6;
    }

    // Support decoding URL-safe base64 strings, as Node.js does.
    // See: https://en.wikipedia.org/wiki/Base64#URL_applications
    table_base64_Uint8_to_index['-'.charCodeAt(0)] = 62 | BITS_ONES_6_6;
    table_base64_Uint8_to_index['_'.charCodeAt(0)] = 63 | BITS_ONES_6_6;
  }
}

/**
 *
 * @param {ArrayBuffer} sourceBase64ArrayBuffer
 *   The input base64 data as ArrayBuffer. If the last bytes not enough 4 bytes, they will be discarded (will
 * not be decoded). If an input byte is not a legal base64 code (i.e. not A..Z, a..z, 0..0, +, /), the byte
 * will be skipped (as if it does not exist). So the input bytes can be separated by new line.
 *
 * @param {Uint32} skipLineCount
 *   Skip how many lines in the source before decoding.
 *
 * @param {ValueMax.Percentage.Aggregate} progressToYield
 *   Return this when every time yield.
 *
 * @param {ValueMax.Percentage.Concrete}  progressToAdvance
 *   Increase this when every time advanced.
 *
 * @param {Uint32} suspendByteCount
 *   Everytime so many bytes decoded, yield for releasing CPU time (and reporting progress).
 *   Default is 1024 bytes.
 *
 * @yield {ValueMax.Percentage.Aggregate or Uint8Array}
 *   Yield ( value = progressYield ) when ( done = false ).
 *   Yield ( value = decoded data as Uint8Array ) when ( done = true ).
 */
function* decoder(
  sourceBase64ArrayBuffer, skipLineCount, progressToYield, progressToAdvance, suspendByteCount) {

  // 0. Initialize.

  // If undefined or null or negative or zero or less than 1, set to default.
  if ((suspendByteCount | 0) <= 0)
    suspendByteCount = 1024;

  let sourceByteLength = sourceBase64ArrayBuffer.byteLength;
  let sourceBytes = new Uint8Array( sourceBase64ArrayBuffer );

  // Initialize progress.
  progressToAdvance.accumulation = 0;
  progressToAdvance.total = sourceByteLength;

  let nextYieldAccumulation = suspendByteCount;

  // 1. Skip specified lines.
  {
    let skippedLineCount = 0;

    while (progressToAdvance.accumulation < sourceByteLength) {
      if (skippedLineCount >= skipLineCount)
        break;                 // Already skip enough lines.

      let rawByte = sourceBytes[ progressToAdvance.accumulation++ ];

      if (13 == rawByte) {     // "\r" (carriage return; CR)
        ++skippedLineCount;    // One line is skipped.

        // If a LF follows a CR, it is considered as CRLF sequence and viewed as the same one line.
        if (   (progressToAdvance.accumulation < sourceByteLength)
            && (10 == sourceBytes[ progressToAdvance.accumulation ])
           ) {
          ++progressToAdvance.accumulation; // Skip it.
        }

      } else {
        if (10 == rawByte)    // "\n" (new line; LF)
          ++skippedLineCount; // One line is skipped.
      }

      // Every suspendByteCount, release CPU time (and report progress).
      if (progressToAdvance.accumulation >= nextYieldAccumulation) {
        nextYieldAccumulation = progressToAdvance.accumulation + suspendByteCount;
        yield progressToYield;
      }
    }
  }

  // 2. Decode.

  // Decoding base64 will result in a shorter data (about 75% (= 3 / 4) in size).
  let possibleBase64ByteLength = (sourceByteLength - progressToAdvance.accumulation);  // Forget the skipped lines.
  let targetByteLength = Math.ceil(possibleBase64ByteLength * 0.75);
  let targetArrayBuffer = new ArrayBuffer( targetByteLength );
  let targetBytes = new Uint8Array( targetArrayBuffer );

  let resultByteCount = 0;  // Accumulate the real result byte count.

  {
    const BYTES_PER_DECODE_UNIT = 4; // A decode unit consists of 4 base64 encoded source bytes.
    let encodedBytes = new Uint8Array( new ArrayBuffer( BYTES_PER_DECODE_UNIT ) );

    while (progressToAdvance.accumulation < sourceByteLength) {

      // Extract 4 source bytes.
      let j = 0;
      while (j < BYTES_PER_DECODE_UNIT) {
        if (progressToAdvance.accumulation >= sourceByteLength)
          break; // Decoding is done. (Ignore last non-4-bytes.)
// !!! (2019/06/14) Remarked for use 6th bit the advance byte count.
//         encodedBytes[ j ] = table_base64_Uint8_to_index[ sourceBytes[ progressToAdvance.accumulation++ ] ];
//
//         if (255 === encodedBytes[ j ])
//           continue; // Skip any non-base64 bytes.
//
//         ++j;

// !!! (2019/06/14) Remarked for use 6th bit the advance byte count.
//         let oneByte = table_base64_Uint8_to_index[ sourceBytes[ progressToAdvance.accumulation++ ] ];
//
//         encodedBytes[ j ] = oneByte & BITS_ONES_0_5; // Remove the highest two bits.
//
//         // The highest two bits is:
//         //   1 for legal base64 code. So the byte count is increased.
//         //   0 for non-base64 code. So the code is skipped (i.e. the byte count is kept).
//         //
//         // This trick control the byte count (i.e. variable j) without using if-condition.
//         // Hope for increasing parsing performance.
//         j += ( oneByte & BITS_ONES_6_7 ) >>> 6;

// !!! (2019/06/14) Remarked for use 6th bit the advance byte count.
//         let oneByte = table_base64_Uint8_to_index[ sourceBytes[ progressToAdvance.accumulation++ ] ];
//
//         encodedBytes[ j ] = oneByte & 0x3F; // Remove the highest two bits. (0x3F = BITS_ONES_0_5)
//
//         // The highest two bits is:
//         //   1 for legal base64 code. So the byte count is increased.
//         //   0 for non-base64 code. So the code is skipped (i.e. the byte count is kept).
//         //
//         // This trick control the byte count (i.e. variable j) without using if-condition.
//         // Hope for increasing parsing performance.
//         j += ( oneByte & 0xC0 ) >>> 6; // (0xC0 = BITS_ONES_6_7)

        let oneByte = table_base64_Uint8_to_index[ sourceBytes[ progressToAdvance.accumulation++ ] ];

        encodedBytes[ j ] = oneByte << 2 >>> 2; // Remove the highest two bits. (0x3F = BITS_ONES_0_5)

        // The highest two bits is:
        //   1 for legal base64 code. So the byte count is increased.
        //   0 for non-base64 code. So the code is skipped (i.e. the byte count is kept).
        //
        // This trick control the byte count (i.e. variable j) without using if-condition.
        // Hope for increasing parsing performance.
        j += ( oneByte << 1 ) >>> 6; // (0xC0 = BITS_ONES_6_7)
      }

      if (j != BYTES_PER_DECODE_UNIT)
        break; // Decoding is done. (Ignore last non-4-bytes.)

      targetBytes[resultByteCount++] =  (encodedBytes[ 0 ]       << 2) | (encodedBytes[ 1 ] >> 4);
      targetBytes[resultByteCount++] = ((encodedBytes[ 1 ] & 15) << 4) | (encodedBytes[ 2 ] >> 2);
      targetBytes[resultByteCount++] = ((encodedBytes[ 2 ] &  3) << 6) | (encodedBytes[ 3 ] & 63);

      // Every suspendByteCount, release CPU time (and report progress).
      if (progressToAdvance.accumulation >= nextYieldAccumulation) {
        nextYieldAccumulation = progressToAdvance.accumulation + suspendByteCount;
        yield progressToYield;
      }
    }
  }

  // 3. Result.

  // The resultBytes is a sub-range of target buffer.
  //
  // Because the source may have some non-base64 codes which will be ignored,
  // the result data may be less than target length.
  let resultBytes = new Uint8Array( targetArrayBuffer, 0, resultByteCount );

  if (   // Never yield (i.e. never report progress), report at least once for done.
         (nextYieldAccumulation == suspendByteCount)

         // Or, some advance has been made after last progress report, report for done.
      || ((nextYieldAccumulation - progressToAdvance.accumulation) < suspendByteCount)
     )
    yield progressToYield; // Report the progress has been done (100%).
  else
    ; // The last progress report is (just luckily) 100%. No need to report the progress again.

  return resultBytes;
}
<commit_msg>Update Base64ArrayBufferToUint8Array.js<commit_after>export { decoder };

const base64String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

const BITS_ONES_0_5 = Number.parseInt("00111111", 2);  // 00111111 = 0x3F
const BITS_ONES_6_7 = Number.parseInt("11000000", 2);  // 11000000 = 0xC0
const BITS_ONES_6_6 = Number.parseInt("01000000", 2);  // 01000000 = 0x40

//!!! (2019/06/14) Remarked for performance testing.
// // Mapping table for base64 (as Uint8) to index.
// let table_base64_Uint8_to_index = new Uint8Array( new ArrayBuffer(256) );
// {
//   // For all non-base64 codes, using value greater than 63 (i.e. impossible base64) for identifying them.
//   for (let i = 0; i < table_base64_Uint8_to_index.length; ++i)
//     table_base64_Uint8_to_index[ i ] = 255;
//
//   // For all legal base64 codes, using value between [0, 63].
//   {
//     for (let i = 0; i < base64String.length; ++i) {
//       let codePoint = base64String.codePointAt(i);
//       table_base64_Uint8_to_index[ codePoint ] = i;
//     }
//
//     // Support decoding URL-safe base64 strings, as Node.js does.
//     // See: https://en.wikipedia.org/wiki/Base64#URL_applications
//     table_base64_Uint8_to_index['-'.charCodeAt(0)] = 62;
//     table_base64_Uint8_to_index['_'.charCodeAt(0)] = 63;
//   }
// }

//!!! (2019/06/14) Remarked for performance testing.
// // Mapping table for base64 (as Uint8) to index.
// //
// // The value of decoded base64 is between [0, 63]. It uses only lowest 6 bits.
// // The highest 2 bits can be used to store the byte count to advance.
// // It is 0 for illegal base64 codes, and 1 for legal base64 codes.
// //
// let table_base64_Uint8_to_index = new Uint8Array( new ArrayBuffer(256) );
// {
//   // For all non-base64 codes, the 6th bit always 0.
//   for (let i = 0; i < table_base64_Uint8_to_index.length; ++i)
//     table_base64_Uint8_to_index[ i ] = 0;
//
//   // For all legal base64 codes, the 6th bit always 1.
//   {
//     for (let i = 0; i < base64String.length; ++i) {
//       let codePoint = base64String.codePointAt(i);
//       table_base64_Uint8_to_index[ codePoint ] = i | BITS_ONES_6_6;
//     }
//
//     // Support decoding URL-safe base64 strings, as Node.js does.
//     // See: https://en.wikipedia.org/wiki/Base64#URL_applications
//     table_base64_Uint8_to_index['-'.charCodeAt(0)] = 62 | BITS_ONES_6_6;
//     table_base64_Uint8_to_index['_'.charCodeAt(0)] = 63 | BITS_ONES_6_6;
//   }
// }

// Mapping table for base64 (as Uint8) to index.
let table_arrayBuffer512 = new ArrayBuffer(512);
let table_base64_Uint8_to_index = new Uint8Array( table_arrayBuffer512,   0, 256 );
let table_base64_Uint8_to_advanceByteCount = new Uint8Array( table_arrayBuffer512, 255, 256 );
{
  // For all non-base64 codes, the advanceByteCount is 0.
  for (let i = 0; i < table_base64_Uint8_to_index.length; ++i) {
    table_base64_Uint8_to_index[ i ] = 255;
    table_base64_Uint8_to_advanceByteCount[ i ] = 0;
  }

  // All legal base64 codes.
  {
    for (let i = 0; i < base64String.length; ++i)
      table_base64_Uint8_to_index[ base64String.codePointAt(i) ] = i;

    // Support decoding URL-safe base64 strings, as Node.js does.
    // See: https://en.wikipedia.org/wiki/Base64#URL_applications
    table_base64_Uint8_to_index['-'.charCodeAt(0)] = 62;
    table_base64_Uint8_to_index['_'.charCodeAt(0)] = 63;

    // For all legal base64 codes, the advanceByteCount is 1.
    for (let i = 0; i < table_base64_Uint8_to_index.length; ++i) {
      if (255 != table_base64_Uint8_to_index[ i ])
        table_base64_Uint8_to_advanceByteCount[ i ] = 1;
    }
  }
}

/**
 *
 * @param {ArrayBuffer} sourceBase64ArrayBuffer
 *   The input base64 data as ArrayBuffer. If the last bytes not enough 4 bytes, they will be discarded (will
 * not be decoded). If an input byte is not a legal base64 code (i.e. not A..Z, a..z, 0..0, +, /), the byte
 * will be skipped (as if it does not exist). So the input bytes can be separated by new line.
 *
 * @param {Uint32} skipLineCount
 *   Skip how many lines in the source before decoding.
 *
 * @param {ValueMax.Percentage.Aggregate} progressToYield
 *   Return this when every time yield.
 *
 * @param {ValueMax.Percentage.Concrete}  progressToAdvance
 *   Increase this when every time advanced.
 *
 * @param {Uint32} suspendByteCount
 *   Everytime so many bytes decoded, yield for releasing CPU time (and reporting progress).
 *   Default is 1024 bytes.
 *
 * @yield {ValueMax.Percentage.Aggregate or Uint8Array}
 *   Yield ( value = progressYield ) when ( done = false ).
 *   Yield ( value = decoded data as Uint8Array ) when ( done = true ).
 */
function* decoder(
  sourceBase64ArrayBuffer, skipLineCount, progressToYield, progressToAdvance, suspendByteCount) {

  // 0. Initialize.

  // If undefined or null or negative or zero or less than 1, set to default.
  if ((suspendByteCount | 0) <= 0)
    suspendByteCount = 1024;

  let sourceByteLength = sourceBase64ArrayBuffer.byteLength;
  let sourceBytes = new Uint8Array( sourceBase64ArrayBuffer );

  // Initialize progress.
  progressToAdvance.accumulation = 0;
  progressToAdvance.total = sourceByteLength;

  let nextYieldAccumulation = suspendByteCount;

  // 1. Skip specified lines.
  {
    let skippedLineCount = 0;

    while (progressToAdvance.accumulation < sourceByteLength) {
      if (skippedLineCount >= skipLineCount)
        break;                 // Already skip enough lines.

      let rawByte = sourceBytes[ progressToAdvance.accumulation++ ];

      if (13 == rawByte) {     // "\r" (carriage return; CR)
        ++skippedLineCount;    // One line is skipped.

        // If a LF follows a CR, it is considered as CRLF sequence and viewed as the same one line.
        if (   (progressToAdvance.accumulation < sourceByteLength)
            && (10 == sourceBytes[ progressToAdvance.accumulation ])
           ) {
          ++progressToAdvance.accumulation; // Skip it.
        }

      } else {
        if (10 == rawByte)    // "\n" (new line; LF)
          ++skippedLineCount; // One line is skipped.
      }

      // Every suspendByteCount, release CPU time (and report progress).
      if (progressToAdvance.accumulation >= nextYieldAccumulation) {
        nextYieldAccumulation = progressToAdvance.accumulation + suspendByteCount;
        yield progressToYield;
      }
    }
  }

  // 2. Decode.

  // Decoding base64 will result in a shorter data (about 75% (= 3 / 4) in size).
  let possibleBase64ByteLength = (sourceByteLength - progressToAdvance.accumulation);  // Forget the skipped lines.
  let targetByteLength = Math.ceil(possibleBase64ByteLength * 0.75);
  let targetArrayBuffer = new ArrayBuffer( targetByteLength );
  let targetBytes = new Uint8Array( targetArrayBuffer );

  let resultByteCount = 0;  // Accumulate the real result byte count.

  {
    const BYTES_PER_DECODE_UNIT = 4; // A decode unit consists of 4 base64 encoded source bytes.
    let encodedBytes = new Uint8Array( new ArrayBuffer( BYTES_PER_DECODE_UNIT ) );

    while (progressToAdvance.accumulation < sourceByteLength) {

      // Extract 4 source bytes.
      let j = 0;
      while (j < BYTES_PER_DECODE_UNIT) {
        if (progressToAdvance.accumulation >= sourceByteLength)
          break; // Decoding is done. (Ignore last non-4-bytes.)
// !!! (2019/06/14) Remarked for use 6th bit the advance byte count.
//         encodedBytes[ j ] = table_base64_Uint8_to_index[ sourceBytes[ progressToAdvance.accumulation++ ] ];
//
//         if (255 === encodedBytes[ j ])
//           continue; // Skip any non-base64 bytes.
//
//         ++j;

// !!! (2019/06/14) Remarked for use 6th bit the advance byte count.
//         let oneByte = table_base64_Uint8_to_index[ sourceBytes[ progressToAdvance.accumulation++ ] ];
//
//         encodedBytes[ j ] = oneByte & BITS_ONES_0_5; // Remove the highest two bits.
//
//         // The highest two bits is:
//         //   1 for legal base64 code. So the byte count is increased.
//         //   0 for non-base64 code. So the code is skipped (i.e. the byte count is kept).
//         //
//         // This trick control the byte count (i.e. variable j) without using if-condition.
//         // Hope for increasing parsing performance.
//         j += ( oneByte & BITS_ONES_6_7 ) >>> 6;

// !!! (2019/06/14) Remarked for use 6th bit the advance byte count.
//         let oneByte = table_base64_Uint8_to_index[ sourceBytes[ progressToAdvance.accumulation++ ] ];
//
//         encodedBytes[ j ] = oneByte & 0x3F; // Remove the highest two bits. (0x3F = BITS_ONES_0_5)
//
//         // The highest two bits is:
//         //   1 for legal base64 code. So the byte count is increased.
//         //   0 for non-base64 code. So the code is skipped (i.e. the byte count is kept).
//         //
//         // This trick control the byte count (i.e. variable j) without using if-condition.
//         // Hope for increasing parsing performance.
//         j += ( oneByte & 0xC0 ) >>> 6; // (0xC0 = BITS_ONES_6_7)

        let encodedByte = sourceBytes[ progressToAdvance.accumulation++ ];

        encodedBytes[ j ] = table_base64_Uint8_to_index[ encodedByte ];  // Base64 to index.

        // Base64 to advanceByteCount.
        //
        // This trick control the byte count (i.e. variable j) without using if-condition.
        // Hope for increasing parsing performance.
        j += table_base64_Uint8_to_advanceByteCount[ encodedByte ];
      }

      if (j != BYTES_PER_DECODE_UNIT)
        break; // Decoding is done. (Ignore last non-4-bytes.)

      targetBytes[resultByteCount++] =  (encodedBytes[ 0 ]       << 2) | (encodedBytes[ 1 ] >> 4);
      targetBytes[resultByteCount++] = ((encodedBytes[ 1 ] & 15) << 4) | (encodedBytes[ 2 ] >> 2);
      targetBytes[resultByteCount++] = ((encodedBytes[ 2 ] &  3) << 6) | (encodedBytes[ 3 ] & 63);

      // Every suspendByteCount, release CPU time (and report progress).
      if (progressToAdvance.accumulation >= nextYieldAccumulation) {
        nextYieldAccumulation = progressToAdvance.accumulation + suspendByteCount;
        yield progressToYield;
      }
    }
  }

  // 3. Result.

  // The resultBytes is a sub-range of target buffer.
  //
  // Because the source may have some non-base64 codes which will be ignored,
  // the result data may be less than target length.
  let resultBytes = new Uint8Array( targetArrayBuffer, 0, resultByteCount );

  if (   // Never yield (i.e. never report progress), report at least once for done.
         (nextYieldAccumulation == suspendByteCount)

         // Or, some advance has been made after last progress report, report for done.
      || ((nextYieldAccumulation - progressToAdvance.accumulation) < suspendByteCount)
     )
    yield progressToYield; // Report the progress has been done (100%).
  else
    ; // The last progress report is (just luckily) 100%. No need to report the progress again.

  return resultBytes;
}
<|endoftext|>