<commit_before>const { Octokit } = require('@octokit/rest');
const octokit = new Octokit();
var wget = require('node-wget');
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');
const readline = require('readline');

// Global generated from cli prompt
let versionToSign;

// Why can't I do this with 'fs'? :/
function deleteFolderRecursive(path) {
  if (fs.existsSync(path)) {
    fs.readdirSync(path).forEach(function(file, index) {
      var curPath = path + '/' + file;
      if (fs.lstatSync(curPath).isDirectory()) {
        // recurse
        deleteFolderRecursive(curPath);
      } else {
        // delete file
        fs.unlinkSync(curPath);
      }
    });
    fs.rmdirSync(path);
  }
}

// Initial setup
// Create a file to store the hashes (creates a new copy if one exists)
const downloadPath = path.resolve(__dirname, '../dist/releaseDownloads');
const fileToSign = path.resolve(downloadPath, '../hashes.txt');

fs.openSync(fileToSign, 'w');

if (!fs.existsSync(downloadPath)) {
  fs.mkdirSync(downloadPath);
} else {
  deleteFolderRecursive(downloadPath);
  fs.mkdirSync(downloadPath);
}

//
// Below is the actual code that downloads, hashes, and signs the release
//
function cleanUpAfterSigning() {
  fs.unlinkSync(fileToSign);
  deleteFolderRecursive(downloadPath);
}

function signFile() {
  console.log('Signing file with hashes using keybase...');
  // All files are hashed and added to hashes.txt
  // Sign it with keybase
  const fileName = `LBRY_${versionToSign}_sigs.asc`;

  const pathForSignedFile = path.resolve(__dirname, `../dist/${fileName}`);
  exec(`keybase pgp sign -i ${fileToSign} -c -o ${pathForSignedFile}`, err => {
    if (err) {
      console.log('Error signing file with keybase');
    }

    cleanUpAfterSigning();
  });
}

function hashFiles() {
  console.log('Hashing assets downloaded from github...');

  fs.readdir(downloadPath, function(err, items) {
    if (err) {
      console.log('Error signing files in ', downloadPath);
    }

    let count = 0;
    for (var i = 0; i < items.length; i++) {
      const file = items[i];
      const filePath = path.resolve(__dirname, '../dist/releaseDownloads/', file);
      exec(`sha256sum ${filePath}`, (err, stdout) => {
        if (err) {
          console.log('Error hashing ', filePath);
        }

        count += 1;
        const hash = stdout.split(' ')[0];
        const stringToAppend = `${hash} ${file}\n`;
        fs.appendFileSync(fileToSign, stringToAppend);

        if (count === items.length - 1) {
          signFile();
        }
      });
    }
  });
}

let downloadCount = 0;
let fileCountToDownload;
function downloadFile(fileName, url) {
  wget(
    {
      url: url,
      dest: `${downloadPath}/`,
    },
    (error, response, body) => {
      console.log(`Finished downloading `, fileName);
      downloadCount += 1;

      if (downloadCount === fileCountToDownload) {
        hashFiles();
      }
    }
  );
}

function downloadAssets() {
  console.log('Downloading release assets...');
  octokit.repos
    .getReleaseByTag({
      owner: 'lbryio',
      repo: 'lbry-desktop',
      tag: versionToSign,
    })
    .then(({ data }) => {
      const release_id = data.id;

      return octokit.repos.listAssetsForRelease({
        owner: 'lbryio',
        repo: 'lbry-desktop',
        release_id,
      });
    })
    .then(({ data }) => {
      fileCountToDownload = data.length;

      data
        .map(({ browser_download_url, name }) => ({ download_url: browser_download_url, name }))
        .forEach(({ name, download_url }) => {
          const fileName = path.resolve(__dirname, `../dist/releaseDownloads/${name}`);
          downloadFile(fileName, download_url);
        });
    })
    .catch(error => console.log('Error downloading releases ', error));
}

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

rl.question('Version to sign: ', function(version) {
  const tag = version.startsWith('v') ? version : `v${version}`;
  versionToSign = tag;
  downloadAssets();
});
<commit_msg>make sure script exits properly after it finishes signing build files<commit_after>const { Octokit } = require('@octokit/rest');
const octokit = new Octokit();
var wget = require('node-wget');
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');
const readline = require('readline');

// Global generated from cli prompt
let versionToSign;

// Why can't I do this with 'fs'? :/
function deleteFolderRecursive(path) {
  if (fs.existsSync(path)) {
    fs.readdirSync(path).forEach(function(file, index) {
      var curPath = path + '/' + file;
      if (fs.lstatSync(curPath).isDirectory()) {
        // recurse
        deleteFolderRecursive(curPath);
      } else {
        // delete file
        fs.unlinkSync(curPath);
      }
    });
    fs.rmdirSync(path);
  }
}

// Initial setup
// Create a file to store the hashes (creates a new copy if one exists)
const downloadPath = path.resolve(__dirname, '../dist/releaseDownloads');
const fileToSign = path.resolve(downloadPath, '../hashes.txt');

fs.openSync(fileToSign, 'w');

if (!fs.existsSync(downloadPath)) {
  fs.mkdirSync(downloadPath);
} else {
  deleteFolderRecursive(downloadPath);
  fs.mkdirSync(downloadPath);
}

//
// Below is the actual code that downloads, hashes, and signs the release
//
function cleanUpAfterSigning() {
  fs.unlinkSync(fileToSign);
  deleteFolderRecursive(downloadPath);
  console.log('Good to go captain');
  process.exit(0);
}

function signFile() {
  console.log('Signing file with hashes using keybase...');
  // All files are hashed and added to hashes.txt
  // Sign it with keybase
  const fileName = `LBRY_${versionToSign}_sigs.asc`;

  const pathForSignedFile = path.resolve(__dirname, `../dist/${fileName}`);
  exec(`keybase pgp sign -i ${fileToSign} -c -o ${pathForSignedFile}`, err => {
    if (err) {
      console.log('Error signing file with keybase');
    }

    cleanUpAfterSigning();
  });
}

function hashFiles() {
  console.log('Hashing assets downloaded from github...');

  fs.readdir(downloadPath, function(err, items) {
    if (err) {
      console.log('Error signing files in ', downloadPath);
    }

    let count = 0;
    for (var i = 0; i < items.length; i++) {
      const file = items[i];
      const filePath = path.resolve(__dirname, '../dist/releaseDownloads/', file);
      exec(`sha256sum ${filePath}`, (err, stdout) => {
        if (err) {
          console.log('Error hashing ', filePath);
        }

        count += 1;
        const hash = stdout.split(' ')[0];
        const stringToAppend = `${hash} ${file}\n`;
        fs.appendFileSync(fileToSign, stringToAppend);

        if (count === items.length - 1) {
          signFile();
        }
      });
    }
  });
}

let downloadCount = 0;
let fileCountToDownload;
function downloadFile(fileName, url) {
  wget(
    {
      url: url,
      dest: `${downloadPath}/`,
    },
    (error, response, body) => {
      console.log(`Finished downloading `, fileName);
      downloadCount += 1;

      if (downloadCount === fileCountToDownload) {
        hashFiles();
      }
    }
  );
}

function downloadAssets() {
  console.log('Downloading release assets...');
  octokit.repos
    .getReleaseByTag({
      owner: 'lbryio',
      repo: 'lbry-desktop',
      tag: versionToSign,
    })
    .then(({ data }) => {
      const release_id = data.id;

      return octokit.repos.listAssetsForRelease({
        owner: 'lbryio',
        repo: 'lbry-desktop',
        release_id,
      });
    })
    .then(({ data }) => {
      fileCountToDownload = data.length;

      data
        .map(({ browser_download_url, name }) => ({ download_url: browser_download_url, name }))
        .forEach(({ name, download_url }) => {
          const fileName = path.resolve(__dirname, `../dist/releaseDownloads/${name}`);
          downloadFile(fileName, download_url);
        });
    })
    .catch(error => console.log('Error downloading releases ', error));
}

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

rl.question('Version to sign: ', function(version) {
  const tag = version.startsWith('v') ? version : `v${version}`;
  versionToSign = tag;
  downloadAssets();
});
<|endoftext|>


<commit_before>
module.exports = function(grunt) {
    "use strict";

    var path = require('path'),
        jsDiff = require('diff'),
        colors = {
            'diff added': 42,
            'diff removed': 41
        }
    ;

    var color = function(type, str) {
      return '\u001b[' + colors[type] + 'm' + str + '\u001b[0m';
    };

    function inlineDiff(err, escape) {
        var msg = errorDiff(err, 'WordsWithSpace', escape);

        // linenos
        var lines = msg.split('\n');
        if (lines.length > 4) {
            var width = String(lines.length).length;
            msg = lines.map(function(str, i){
                return pad(++i, width) + ' |' + ' ' + str;
            }).join('\n');
        }

        // legend
        msg = '\n'
            + color('diff removed', 'actual')
            + ' '
            + color('diff added', 'expected')
            + '\n\n'
            + msg
            + '\n';

        // indent
        msg = msg.replace(/^/gm, '      ');
        return msg;
    }

    function errorDiff(err, type, escape) {
        var actual   = escape ? escapeInvisibles(err.actual)   : err.actual;
        var expected = escape ? escapeInvisibles(err.expected) : err.expected;
        return diff['diff' + type](actual, expected).map(function(str){
            if (str.added) return colorLines('diff added', str.value);
            if (str.removed) return colorLines('diff removed', str.value);
            return str.value;
        }).join('');
    }

    function escapeInvisibles(line) {
        return line.replace(/\t/g, '<tab>')
                   .replace(/\r/g, '<CR>')
                   .replace(/\n/g, '<LF>\n');
    }

    function colorLines(name, str) {
        return str.split('\n').map(function(str){
            return color(name, str);
        }).join('\n');
    }

    grunt.registerMultiTask('sasstest', 'Tests sass output is correct', function() {
        var tmpDir = 'tmp/sasstest',
            files = grunt.file.expand({ cwd: 'tests/css'}, '**/*.css'),
            diffs = []
        ;

        files.forEach(function(file) {
            var diff = jsDiff.diffLines(
                grunt.file.read(path.join('tests/css', file)),
                grunt.file.read(path.join('.build/sasstest', file))
            );

            diff.forEach(function(d) {
                if (d.added) {
                    grunt.log.writeln(colorLines('diff added', d.value));
                }

                if (d.removed) {
                    grunt.log.writeln(colorLines('diff removed', d.value));
                }
            });
        });
    });
};
<commit_msg>fix(tests): grunt should fail if sass tests fail<commit_after>
module.exports = function(grunt) {
    "use strict";

    var path = require('path'),
        jsDiff = require('diff'),
        colors = {
            'diff added': 42,
            'diff removed': 41
        }
    ;

    var color = function(type, str) {
      return '\u001b[' + colors[type] + 'm' + str + '\u001b[0m';
    };

    function inlineDiff(err, escape) {
        var msg = errorDiff(err, 'WordsWithSpace', escape);

        // linenos
        var lines = msg.split('\n');
        if (lines.length > 4) {
            var width = String(lines.length).length;
            msg = lines.map(function(str, i){
                return pad(++i, width) + ' |' + ' ' + str;
            }).join('\n');
        }

        // legend
        msg = '\n'
            + color('diff removed', 'actual')
            + ' '
            + color('diff added', 'expected')
            + '\n\n'
            + msg
            + '\n';

        // indent
        msg = msg.replace(/^/gm, '      ');
        return msg;
    }

    function errorDiff(err, type, escape) {
        var actual   = escape ? escapeInvisibles(err.actual)   : err.actual;
        var expected = escape ? escapeInvisibles(err.expected) : err.expected;
        return diff['diff' + type](actual, expected).map(function(str){
            if (str.added) return colorLines('diff added', str.value);
            if (str.removed) return colorLines('diff removed', str.value);
            return str.value;
        }).join('');
    }

    function escapeInvisibles(line) {
        return line.replace(/\t/g, '<tab>')
                   .replace(/\r/g, '<CR>')
                   .replace(/\n/g, '<LF>\n');
    }

    function colorLines(name, str) {
        return str.split('\n').map(function(str){
            return color(name, str);
        }).join('\n');
    }

    grunt.registerMultiTask('sasstest', 'Tests sass output is correct', function() {
        var tmpDir = 'tmp/sasstest',
            files = grunt.file.expand({ cwd: 'tests/css'}, '**/*.css'),
            failed = false
        ;

        files.forEach(function(file) {
            var diff = jsDiff.diffLines(
                grunt.file.read(path.join('tests/css', file)),
                grunt.file.read(path.join('.build/sasstest', file))
            );

            diff.forEach(function(d) {
                failed = failed || d.added || d.removed;

                if (d.added) {
                    grunt.log.writeln(colorLines('diff added', d.value));
                }

                if (d.removed) {
                    grunt.log.writeln(colorLines('diff removed', d.value));
                }

            });
        });

        if (failed) {
            grunt.fail.fatal('Unexpected output found');
        }
    });
};
<|endoftext|>


<commit_before><commit_msg>removed unnecesary console.logs<commit_after><|endoftext|>


<commit_before>{
    name: "level1",
    settings: {
        debugDraw: true,
        cameraAngularSpeed: 10 * Math.PI,
        cameraMovementSpeed: 1 * 1e3,
    },
    physics: {
        friction: 1,
        restitution: 0,
        linearDamping: 0.5,
        angularDamping: 1,
        gravity: -9.8,
    },
    terrain: {
        scale: 2000,
        texture: "Grass.jpg",
        repeatTexture: true,
        // If a model is provided, the texture above is ignored
        model: "objectTerrain.js",
    },
    skybox: {
        scale: 2000,
        textures: [
                "Content/Textures/Skybox/posX.png",
                "Content/Textures/Skybox/negX.png",
                "Content/Textures/Skybox/posY.png",
                "Content/Textures/Skybox/negY.png",
                "Content/Textures/Skybox/posZ.png",
                "Content/Textures/Skybox/negZ.png",
        ],
    },
    dynamics: [
        {
            type: "character",
            tags: [],
            id: "hero",
            model: "TestEight.js",
            pos: [-864, 192, 128],
            scale: 5,
        },
        {
            type: "character",
            tags: ["npc"],
            id: "thisguy",
            model: "TestEight.js",
            pos: [30, 0, 0],
            scale: 5,
        },
    ],
    statics: [

        {"type":"environment", tags: ["building"],"pos":[-393.82,0,51.73],"rot":[0,0,0],"scale":3.5,"model":"house_one.js"},{"type":"environment", tags: ["building"],"pos":[-331.03553178261245,0,-195.20226269285726],"rot":[0,-1.5577188540185378,0],"scale":3.5,"model":"house_one.js"},
        {"type":"environment", tags: ["building"],"pos":[90.60330488167114,0,120.77182926800373],"rot":[3.141592653589793,0.03779037061426142,3.141592653589793],"scale":3.5,"model":"house_one.js"},
        {"type":"environment", tags: ["building"],"pos":[-258.4222199467363,0,208.32359567890623],"rot":[3.141592653589793,-1.568557492105053,3.141592653589793],"scale":3.5,"model":"house_one.js"},
        {"type":"environment", tags: ["building"],"pos":[300.4222199467363,0,208.32359567890623],"rot":[3.141592653589793,20,3.141592653589793],"scale":3.5,"model":"house_one.js"},
        {"type":"environment", tags: ["building"],"pos":[100,0,-130],"rot":[0,130,0],"scale":3.5,"model":"house_two.js"},
        {"type":"environment", tags: ["building"],"pos":[0,0,-250],"rot":[0,90,0],"scale":3.5,"model":"house_two.js"},
        {"type":"environment", tags: ["building"],"pos":[-140,0,-10],"rot":[0,40,0],"scale":3.5,"model":"house_two.js"},
        {"type":"environment", tags: ["building"],"pos":[300,0,100],"rot":[0,70,0],"scale":3.5,"model":"house_two.js"},

    ],
}<commit_msg>Scene reset<commit_after>{
    name: "level1",
    settings: {
        debugDraw: true,
        cameraAngularSpeed: 10 * Math.PI,
        cameraMovementSpeed: 1 * 1e3,
    },
    physics: {
        friction: 1,
        restitution: 0,
        linearDamping: 0.5,
        angularDamping: 1,
        gravity: -9.8,
    },
    terrain: {
        scale: 2000,
        texture: "Grass.jpg",
        repeatTexture: true,
        // If a model is provided, the texture above is ignored
        model: "objectTerrain.js",
    },
    skybox: {
        scale: 2000,
        textures: [
                "Content/Textures/Skybox/posX.png",
                "Content/Textures/Skybox/negX.png",
                "Content/Textures/Skybox/posY.png",
                "Content/Textures/Skybox/negY.png",
                "Content/Textures/Skybox/posZ.png",
                "Content/Textures/Skybox/negZ.png",
        ],
    },
    dynamics: [
        {
            type: "character",
            tags: [],
            id: "hero",
            model: "TestEight.js",
            pos: [0, 0, 0],
            scale: 5,
        },
        {
            type: "character",
            tags: ["npc"],
            id: "thisguy",
            model: "TestEight.js",
            pos: [30, 0, 0],
            scale: 5,
        },
    ],
    statics: [

        {"type":"environment", tags: ["building"],"pos":[-393.82,0,51.73],"rot":[0,0,0],"scale":3.5,"model":"house_one.js"},{"type":"environment", tags: ["building"],"pos":[-331.03553178261245,0,-195.20226269285726],"rot":[0,-1.5577188540185378,0],"scale":3.5,"model":"house_one.js"},
        {"type":"environment", tags: ["building"],"pos":[90.60330488167114,0,120.77182926800373],"rot":[3.141592653589793,0.03779037061426142,3.141592653589793],"scale":3.5,"model":"house_one.js"},
        {"type":"environment", tags: ["building"],"pos":[-258.4222199467363,0,208.32359567890623],"rot":[3.141592653589793,-1.568557492105053,3.141592653589793],"scale":3.5,"model":"house_one.js"},
        {"type":"environment", tags: ["building"],"pos":[300.4222199467363,0,208.32359567890623],"rot":[3.141592653589793,20,3.141592653589793],"scale":3.5,"model":"house_one.js"},
        {"type":"environment", tags: ["building"],"pos":[100,0,-130],"rot":[0,130,0],"scale":3.5,"model":"house_two.js"},
        {"type":"environment", tags: ["building"],"pos":[0,0,-250],"rot":[0,90,0],"scale":3.5,"model":"house_two.js"},
        {"type":"environment", tags: ["building"],"pos":[-140,0,-10],"rot":[0,40,0],"scale":3.5,"model":"house_two.js"},
        {"type":"environment", tags: ["building"],"pos":[300,0,100],"rot":[0,70,0],"scale":3.5,"model":"house_two.js"},

    ],
}<|endoftext|>


<commit_before>// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later

app.views.Photos = app.views.InfScroll.extend({
  className: "clearfix row",

  postClass : app.views.Photo,

  initialize : function() {
    this.stream = this.model;
    this.collection = this.stream.items;

    // viable for extraction
    this.stream.fetch();
    this.setupInfiniteScroll();
  },

  postRenderTemplate: function(){
    var photoAttachments = $("#main-stream > div");
    if(photoAttachments.length > 0) {
      new app.views.Gallery({ el: photoAttachments });
    }
  }
});
// @license-end
<commit_msg>Do not recreate blueimp each time you're scrolling in the photos page, fixes #8118<commit_after>// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later

app.views.Photos = app.views.InfScroll.extend({
  className: "clearfix row",
  postClass : app.views.Photo,

  initialize : function() {
    this.stream = this.model;
    this.collection = this.stream.items;
    new app.views.Gallery({el: this.$el});

    // viable for extraction
    this.stream.fetch();
    this.setupInfiniteScroll();
  }
});
// @license-end
<|endoftext|>


<commit_before>import webpack from 'webpack'
import cssnano from 'cssnano'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import ExtractTextPlugin from 'extract-text-webpack-plugin'
import config from '../config'
import _debug from 'debug'

const debug = _debug('app:webpack:config')
const paths = config.utils_paths
const {__DEV__, __PROD__, __TEST__} = config.globals

debug('Create configuration.')
const webpackConfig = {
  name: 'client',
  target: 'web',
  devtool: config.compiler_devtool,
  resolve: {
    root: paths.base(config.dir_client),
    extensions: ['', '.js', '.jsx']
  },
  module: {}
}
// ------------------------------------
// Entry Points
// ------------------------------------
const APP_ENTRY_PATH = paths.base(config.dir_client) + '/main.js'

webpackConfig.entry = {
  app: __DEV__
    ? [APP_ENTRY_PATH, 'webpack-hot-middleware/client?path=/__webpack_hmr']
    : [APP_ENTRY_PATH],
  vendor: config.compiler_vendor
}

// ------------------------------------
// Bundle Output
// ------------------------------------
webpackConfig.output = {
  filename: `[name].[${config.compiler_hash_type}].js`,
  path: paths.base(config.dir_dist),
  publicPath: config.compiler_public_path
}

// ------------------------------------
// Plugins
// ------------------------------------
webpackConfig.plugins = [
  new webpack.DefinePlugin(config.globals),
  new HtmlWebpackPlugin({
    template: paths.client('index.html'),
    hash: false,
    favicon: paths.client('static/favicon.ico'),
    filename: 'index.html',
    inject: 'body',
    minify: {
      collapseWhitespace: true
    }
  })
]

if (__DEV__) {
  debug('Enable plugins for live development (HMR, NoErrors).')
  webpackConfig.plugins.push(
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  )
} else if (__PROD__) {
  debug('Enable plugins for production (OccurenceOrder, Dedupe & UglifyJS).')
  webpackConfig.plugins.push(
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        unused: true,
        dead_code: true,
        warnings: false
      }
    })
  )
}

// Don't split bundles during testing, since we only want import one bundle
if (!__TEST__) {
  webpackConfig.plugins.push(new webpack.optimize.CommonsChunkPlugin({
    names: ['vendor']
  }))
}

// ------------------------------------
// Pre-Loaders
// ------------------------------------
webpackConfig.module.preLoaders = [{
  test: /\.(js|jsx)$/,
  loader: 'eslint',
  exclude: /node_modules/
}]

webpackConfig.eslint = {
  configFile: paths.base('.eslintrc'),
  emitWarning: __DEV__
}

// ------------------------------------
// Loaders
// ------------------------------------
// JavaScript / JSON
webpackConfig.module.loaders = [{
  test: /\.(js|jsx)$/,
  exclude: /node_modules/,
  loader: 'babel',
  query: {
    cacheDirectory: true,
    plugins: ['transform-runtime'],
    presets: __DEV__
      ? ['es2015', 'react', 'stage-0', 'react-hmre']
      : ['es2015', 'react', 'stage-0']
  }
},
{
  test: /\.json$/,
  loader: 'json'
}]

// Styles
const cssLoader = !config.compiler_css_modules
  ? 'css?sourceMap'
  : [
    'css?modules',
    'sourceMap',
    'importLoaders=1',
    'localIdentName=[name]__[local]___[hash:base64:5]'
  ].join('&')

webpackConfig.module.loaders.push({
  test: /\.scss$/,
  include: /src/,
  loaders: [
    'style',
    cssLoader,
    'postcss',
    'sass?sourceMap'
  ]
})

webpackConfig.module.loaders.push({
  test: /\.css$/,
  include: /src/,
  loaders: [
    'style',
    cssLoader,
    'postcss'
  ]
})

// Don't treat global SCSS as modules
webpackConfig.module.loaders.push({
  test: /\.scss$/,
  exclude: /src/,
  loaders: [
    'style',
    'css?sourceMap',
    'postcss',
    'sass?sourceMap'
  ]
})

// Don't treat global, third-party CSS as modules
webpackConfig.module.loaders.push({
  test: /\.css$/,
  exclude: /src/,
  loaders: [
    'style',
    'css?sourceMap',
    'postcss'
  ]
})

webpackConfig.sassLoader = {
  includePaths: paths.client('styles')
}

webpackConfig.postcss = [
  cssnano({
    sourcemap: true,
    autoprefixer: {
      add: true,
      remove: true,
      browsers: ['last 2 versions']
    },
    safe: true,
    discardComments: {
      removeAll: true
    }
  })
]

// File loaders
/* eslint-disable */
webpackConfig.module.loaders.push(
  { test: /\.woff(\?.*)?$/,  loader: 'url?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/font-woff' },
  { test: /\.woff2(\?.*)?$/, loader: 'url?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/font-woff2' },
  { test: /\.otf(\?.*)?$/,   loader: 'file?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=font/opentype' },
  { test: /\.ttf(\?.*)?$/,   loader: 'url?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/octet-stream' },
  { test: /\.eot(\?.*)?$/,   loader: 'file?prefix=fonts/&name=[path][name].[ext]' },
  { test: /\.svg(\?.*)?$/,   loader: 'url?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=image/svg+xml' },
  { test: /\.(png|jpg)$/,    loader: 'url?limit=8192' }
)
/* eslint-enable */

// ------------------------------------
// Finalize Configuration
// ------------------------------------
// when we don't know the public path (we know it only when HMR is enabled [in development]) we
// need to use the extractTextPlugin to fix this issue:
// http://stackoverflow.com/questions/34133808/webpack-ots-parsing-error-loading-fonts/34133809#34133809
if (!__DEV__) {
  debug('Apply ExtractTextPlugin to CSS loaders.')
  webpackConfig.module.loaders.filter(loader =>
    loader.loaders && loader.loaders.find(name => /css/.test(name.split('?')[0]))
  ).forEach(loader => {
    const [first, ...rest] = loader.loaders
    loader.loader = ExtractTextPlugin.extract(first, rest.join('!'))
    delete loader.loaders
  })

  webpackConfig.plugins.push(
    new ExtractTextPlugin('[name].[contenthash].css', {
      allChunks: true
    })
  )
}

export default webpackConfig
<commit_msg>fix(webpack): load HMR using absolute rather than relative path.<commit_after>import webpack from 'webpack'
import cssnano from 'cssnano'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import ExtractTextPlugin from 'extract-text-webpack-plugin'
import config from '../config'
import _debug from 'debug'

const debug = _debug('app:webpack:config')
const paths = config.utils_paths
const {__DEV__, __PROD__, __TEST__} = config.globals

debug('Create configuration.')
const webpackConfig = {
  name: 'client',
  target: 'web',
  devtool: config.compiler_devtool,
  resolve: {
    root: paths.base(config.dir_client),
    extensions: ['', '.js', '.jsx']
  },
  module: {}
}
// ------------------------------------
// Entry Points
// ------------------------------------
const APP_ENTRY_PATH = paths.base(config.dir_client) + '/main.js'

webpackConfig.entry = {
  app: __DEV__
    ? [APP_ENTRY_PATH, `webpack-hot-middleware/client?path=${config.compiler_public_path}__webpack_hmr`]
    : [APP_ENTRY_PATH],
  vendor: config.compiler_vendor
}

// ------------------------------------
// Bundle Output
// ------------------------------------
webpackConfig.output = {
  filename: `[name].[${config.compiler_hash_type}].js`,
  path: paths.base(config.dir_dist),
  publicPath: config.compiler_public_path
}

// ------------------------------------
// Plugins
// ------------------------------------
webpackConfig.plugins = [
  new webpack.DefinePlugin(config.globals),
  new HtmlWebpackPlugin({
    template: paths.client('index.html'),
    hash: false,
    favicon: paths.client('static/favicon.ico'),
    filename: 'index.html',
    inject: 'body',
    minify: {
      collapseWhitespace: true
    }
  })
]

if (__DEV__) {
  debug('Enable plugins for live development (HMR, NoErrors).')
  webpackConfig.plugins.push(
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  )
} else if (__PROD__) {
  debug('Enable plugins for production (OccurenceOrder, Dedupe & UglifyJS).')
  webpackConfig.plugins.push(
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        unused: true,
        dead_code: true,
        warnings: false
      }
    })
  )
}

// Don't split bundles during testing, since we only want import one bundle
if (!__TEST__) {
  webpackConfig.plugins.push(new webpack.optimize.CommonsChunkPlugin({
    names: ['vendor']
  }))
}

// ------------------------------------
// Pre-Loaders
// ------------------------------------
webpackConfig.module.preLoaders = [{
  test: /\.(js|jsx)$/,
  loader: 'eslint',
  exclude: /node_modules/
}]

webpackConfig.eslint = {
  configFile: paths.base('.eslintrc'),
  emitWarning: __DEV__
}

// ------------------------------------
// Loaders
// ------------------------------------
// JavaScript / JSON
webpackConfig.module.loaders = [{
  test: /\.(js|jsx)$/,
  exclude: /node_modules/,
  loader: 'babel',
  query: {
    cacheDirectory: true,
    plugins: ['transform-runtime'],
    presets: __DEV__
      ? ['es2015', 'react', 'stage-0', 'react-hmre']
      : ['es2015', 'react', 'stage-0']
  }
},
{
  test: /\.json$/,
  loader: 'json'
}]

// Styles
const cssLoader = !config.compiler_css_modules
  ? 'css?sourceMap'
  : [
    'css?modules',
    'sourceMap',
    'importLoaders=1',
    'localIdentName=[name]__[local]___[hash:base64:5]'
  ].join('&')

webpackConfig.module.loaders.push({
  test: /\.scss$/,
  include: /src/,
  loaders: [
    'style',
    cssLoader,
    'postcss',
    'sass?sourceMap'
  ]
})

webpackConfig.module.loaders.push({
  test: /\.css$/,
  include: /src/,
  loaders: [
    'style',
    cssLoader,
    'postcss'
  ]
})

// Don't treat global SCSS as modules
webpackConfig.module.loaders.push({
  test: /\.scss$/,
  exclude: /src/,
  loaders: [
    'style',
    'css?sourceMap',
    'postcss',
    'sass?sourceMap'
  ]
})

// Don't treat global, third-party CSS as modules
webpackConfig.module.loaders.push({
  test: /\.css$/,
  exclude: /src/,
  loaders: [
    'style',
    'css?sourceMap',
    'postcss'
  ]
})

webpackConfig.sassLoader = {
  includePaths: paths.client('styles')
}

webpackConfig.postcss = [
  cssnano({
    sourcemap: true,
    autoprefixer: {
      add: true,
      remove: true,
      browsers: ['last 2 versions']
    },
    safe: true,
    discardComments: {
      removeAll: true
    }
  })
]

// File loaders
/* eslint-disable */
webpackConfig.module.loaders.push(
  { test: /\.woff(\?.*)?$/,  loader: 'url?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/font-woff' },
  { test: /\.woff2(\?.*)?$/, loader: 'url?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/font-woff2' },
  { test: /\.otf(\?.*)?$/,   loader: 'file?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=font/opentype' },
  { test: /\.ttf(\?.*)?$/,   loader: 'url?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/octet-stream' },
  { test: /\.eot(\?.*)?$/,   loader: 'file?prefix=fonts/&name=[path][name].[ext]' },
  { test: /\.svg(\?.*)?$/,   loader: 'url?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=image/svg+xml' },
  { test: /\.(png|jpg)$/,    loader: 'url?limit=8192' }
)
/* eslint-enable */

// ------------------------------------
// Finalize Configuration
// ------------------------------------
// when we don't know the public path (we know it only when HMR is enabled [in development]) we
// need to use the extractTextPlugin to fix this issue:
// http://stackoverflow.com/questions/34133808/webpack-ots-parsing-error-loading-fonts/34133809#34133809
if (!__DEV__) {
  debug('Apply ExtractTextPlugin to CSS loaders.')
  webpackConfig.module.loaders.filter(loader =>
    loader.loaders && loader.loaders.find(name => /css/.test(name.split('?')[0]))
  ).forEach(loader => {
    const [first, ...rest] = loader.loaders
    loader.loader = ExtractTextPlugin.extract(first, rest.join('!'))
    delete loader.loaders
  })

  webpackConfig.plugins.push(
    new ExtractTextPlugin('[name].[contenthash].css', {
      allChunks: true
    })
  )
}

export default webpackConfig
<|endoftext|>


<commit_before>var KrempelAirApp = angular.module('KrempelAirApp', ['ngRoute']);
var uri = "/api"

KrempelAirApp.config(['$locationProvider', function($locationProvider) {
  $locationProvider.hashPrefix('');
}]);

KrempelAirApp.config(function ($routeProvider) {
  $routeProvider
      .when('/', {
        templateUrl: '../views/air.html',
        controller: 'AirFlowController'
      })
      .when('/login', {
        templateUrl: '../views/login.html',
        controller: 'LoginCtrl'
      })
      .otherwise({
        redirectTo: '/'
      });
})

KrempelAirApp.directive('selectOnClick', ['$window', function ($window) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('click', function () {
                if (!$window.getSelection().toString()) {
                    // Required for mobile Safari
                    this.setSelectionRange(0, this.value.length)
                }
            });
        }
    };
}]);

KrempelAirApp.factory('Auth', function ($rootScope, $window, $http) {
  return {
    login: function (user, successHandler, errorHandler) {
      if (user.username == 'test' && user.password == 'test') {
        this.setLoggedInUser(user);
        successHandler(user);
      } else {
        alert("please use username/password as test/test to login");
        errorHandler(user);
      }

      // call the server side login restful api
//      $http.post('api/login', user).success(function(user) {
//        this.setLoggedInUser(user);
//        successHandler(user);
//      }).error(errorHandler);
    },
    getLoggedInUser: function () {
      if ($rootScope.user === undefined || $rootScope.user == null) {
        var userStr = $window.sessionStorage.getItem('user');
        if (userStr) {
          $rootScope.user = angular.fromJson(userStr);
        }
      }
      return $rootScope.user;
    },
    isLoggedIn: function () {
      return this.getLoggedInUser() != null;
    },
    setLoggedInUser: function (user) {
      $rootScope.user = user;
      if (user == null) {
        $window.sessionStorage.removeItem('user');
      } else {
        $window.sessionStorage.setItem('user', angular.toJson($rootScope.user));
      }
    }
  };
})

KrempelAirApp.run(['$window', '$rootScope', '$location', 'Auth', function ($window, $rootScope, $location, Auth) {

    $rootScope.$on("$routeChangeStart", function (event) {
      if (!Auth.isLoggedIn() &&
          $location.path() !== '/login') {
        $location.path('/login');
      }
    });
}]);

KrempelAirApp.controller('LoginCtrl', function ($scope, Auth, $location, $http) {
  $scope.user = {};

  $scope.login = function () {
    Auth.login($scope.user, function () {
      $location.path('/');
    }, function (e) {
      // do some error handling.
    });
  };
})

KrempelAirApp.controller('MainCtrl', function ($scope, Auth, $location) {

  $scope.logout = function () {
    Auth.setLoggedInUser(null);
    $location.path('/somewhere');
  };
})

KrempelAirApp.controller('AirFlowController', function AirFlowController($scope, $http, $timeout) {

    $scope.Refresh = function(){
        $http.get(uri+"/").then(function (response) {
            $scope.status = response.data;
        });
        $http.get(uri+"/stoerung").then(function (response) {
            $scope.stoerung = response.data;
        });
        $http.get(uri+"/lueftung/temperatur").then(function (response) {
            $scope.temperatur = response.data;

            // sollTemp
            if(!$scope.sollTemp){
              $scope.sollTemp = response.data["TempSoll"];
            }

            // sollTempNAK
            if(!$scope.sollTempNAK){
               $scope.sollTempNAK = response.data["TempSollNAK"];
            }
        });

        $timeout(function(){
         $scope.Refresh();
        },800);
    }
    $scope.Klick = function(Klick){
        $http.get(uri+"/lueftung/stufe/"+Klick);
        $scope.Refresh();
    }

    $scope.SolltempClick = function(){
      $http.get(uri+"/lueftung/temperatur/sollTemp/"+parseFloat($scope.sollTemp));
      alert("Gespeichert")
    }

    $scope.NAKClick = function(){
      $http.get(uri+"/lueftung/temperatur/sollTempNAK/"+parseFloat($scope.sollTempNAK));
      alert("Gespeichert")
    }

    $scope.updateNAK = function(){
      if($scope.NAK){
        $http.get(uri+"/lueftung/NAK/1");
      }else{
        $http.get(uri+"/lueftung/NAK/0");
      }
    }

    $scope.Refresh();
});
<commit_msg>Update main.js<commit_after>var KrempelAirApp = angular.module('KrempelAirApp', ['ngRoute']);
var uri = "api"

KrempelAirApp.config(['$locationProvider', function($locationProvider) {
  $locationProvider.hashPrefix('');
}]);

KrempelAirApp.config(function ($routeProvider) {
  $routeProvider
      .when('/', {
        templateUrl: 'views/air.html',
        controller: 'AirFlowController'
      })
      .when('/login', {
        templateUrl: 'views/login.html',
        controller: 'LoginCtrl'
      })
      .otherwise({
        redirectTo: '/'
      });
})

KrempelAirApp.directive('selectOnClick', ['$window', function ($window) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('click', function () {
                if (!$window.getSelection().toString()) {
                    // Required for mobile Safari
                    this.setSelectionRange(0, this.value.length)
                }
            });
        }
    };
}]);

KrempelAirApp.factory('Auth', function ($rootScope, $window, $http) {
  return {
    login: function (user, successHandler, errorHandler) {
      if (user.username == 'test' && user.password == 'test') {
        this.setLoggedInUser(user);
        successHandler(user);
      } else {
        alert("please use username/password as test/test to login");
        errorHandler(user);
      }

      // call the server side login restful api
//      $http.post('api/login', user).success(function(user) {
//        this.setLoggedInUser(user);
//        successHandler(user);
//      }).error(errorHandler);
    },
    getLoggedInUser: function () {
      if ($rootScope.user === undefined || $rootScope.user == null) {
        var userStr = $window.sessionStorage.getItem('user');
        if (userStr) {
          $rootScope.user = angular.fromJson(userStr);
        }
      }
      return $rootScope.user;
    },
    isLoggedIn: function () {
      return this.getLoggedInUser() != null;
    },
    setLoggedInUser: function (user) {
      $rootScope.user = user;
      if (user == null) {
        $window.sessionStorage.removeItem('user');
      } else {
        $window.sessionStorage.setItem('user', angular.toJson($rootScope.user));
      }
    }
  };
})

KrempelAirApp.run(['$window', '$rootScope', '$location', 'Auth', function ($window, $rootScope, $location, Auth) {

    $rootScope.$on("$routeChangeStart", function (event) {
      if (!Auth.isLoggedIn() &&
          $location.path() !== '/login') {
        $location.path('/login');
      }
    });
}]);

KrempelAirApp.controller('LoginCtrl', function ($scope, Auth, $location, $http) {
  $scope.user = {};

  $scope.login = function () {
    Auth.login($scope.user, function () {
      $location.path('/');
    }, function (e) {
      // do some error handling.
    });
  };
})

KrempelAirApp.controller('MainCtrl', function ($scope, Auth, $location) {

  $scope.logout = function () {
    Auth.setLoggedInUser(null);
    $location.path('/somewhere');
  };
})

KrempelAirApp.controller('AirFlowController', function AirFlowController($scope, $http, $timeout) {

    $scope.Refresh = function(){
        $http.get(uri+"/").then(function (response) {
            $scope.status = response.data;
        });
        $http.get(uri+"/stoerung").then(function (response) {
            $scope.stoerung = response.data;
        });
        $http.get(uri+"/lueftung/temperatur").then(function (response) {
            $scope.temperatur = response.data;

            // sollTemp
            if(!$scope.sollTemp){
              $scope.sollTemp = response.data["TempSoll"];
            }

            // sollTempNAK
            if(!$scope.sollTempNAK){
               $scope.sollTempNAK = response.data["TempSollNAK"];
            }
        });

        $timeout(function(){
         $scope.Refresh();
        },2000);
    }
    $scope.Klick = function(Klick){
        $http.get(uri+"/lueftung/stufe/"+Klick);
        $scope.Refresh();
    }

    $scope.SolltempClick = function(){
      $http.get(uri+"/lueftung/temperatur/sollTemp/"+parseFloat($scope.sollTemp));
      alert("Gespeichert")
    }

    $scope.NAKClick = function(){
      $http.get(uri+"/lueftung/temperatur/sollTempNAK/"+parseFloat($scope.sollTempNAK));
      alert("Gespeichert")
    }

    $scope.updateNAK = function(){
      if($scope.NAK){
        $http.get(uri+"/lueftung/NAK/1");
      }else{
        $http.get(uri+"/lueftung/NAK/0");
      }
    }

    $scope.Refresh();
});
<|endoftext|>


<commit_before>// ==UserScript==
// @name        KA Crowdin Translation Tools
// @namespace   kadeutsch.org/kacrowdintools
// @include     https://crowdin.com/translate/khanacademy/*
// @include     https://translate.khanacademy.org/translate/*
// @description Various keyboard shortcuts to make KA translation on crowdin a little bit easier
// @version     0.5.3
// @grant       none
// @author      Alain Schaefer & Uli Köhler
// @updateURL   https://raw.githubusercontent.com/ulikoehler/KATranslationTools/master/KATranslationTools.user.js
// ==/UserScript==

/*
 Alt + A : Show all excercises (only on translate.khanacadey.org)
 Alt + N : Move to next exercise (only on translate.khanacadey.org)
 Alt + P : Open all new Window with Strings in proofread modus on crowdin (only on translate.khanacadey.org)
 Alt + U : Replace all formulas with formulas from englisch original (works on crowin.net and translate.khanacademy.org)
 Alt + I : replace Image URLs and fix common german Bing-Translation Errors (works on crowin.net and translate.khanacademy.org)
 Alt + W : Auto-fix coordinates. Works only for coordinates WITHOUT operators.
 Alt + Q : Other fixes. Currently: Convert $\\$123$ to $123{\,}€$ ; Convert simple numbers with dot to comma
 Alt + L : Show images
 */

/**
 * Get the text value in the textbox.
 * For debugging purposes ONLY. The information where to replace
 * the value is lost!!
 */
function getTxtboxValue(regex, replacement) {
    var txtBox = document.getElementById('translation');
    return (txtBox.innerHTML || txtBox.value);
}

function replacePattern(expr,expr2){

    //find the propper Crowdin HTML Elements
    var myDoc = document.getElementById('source_phrase_container');
    var txtBox = document.getElementById('translation');

    //copy the HTML values
    var sourceStr = myDoc.innerText;
    var txtBoxValue = (txtBox.innerHTML || txtBox.value);

    var valueIsInValueProperty = (txtBox.innerHTML == "");

    var result;
    var newTextBoxValue = txtBoxValue;

    //replace every occurence of pattern with corresponding occurence in sourcestring e.g. 1st with 1st, 2nd with 2nd
    while (( result = expr.exec(sourceStr)) !== null  ) {
        txtBoxResult = expr2.exec(txtBoxValue);
        //console.log('replacing ' + txtBoxResult[0] + " with " + result[0]);
        newTextBoxValue = newTextBoxValue.replace(txtBoxResult[0], result[0]);
    }
    //Set new value
    if(valueIsInValueProperty) {txtBox.value = newTextBoxValue;}
    else {txtBox.innerHTML = newTextBoxValue;}
}

/**
 * Simple replace without looking at original (untranslated) string.
 */
function simpleReplaceInTxtbox(regex, replacement) {
    var txtBox = document.getElementById('translation');
    var valueIsInValueProperty = (txtBox.innerHTML == "");
    var txtBoxValue = (txtBox.innerHTML || txtBox.value);
    var newTxtBoxValue = txtBoxValue.replace(regex, replacement);
    //Set new value
    if(valueIsInValueProperty) {txtBox.value = newTxtBoxValue;}
    else {txtBox.innerHTML = newTxtBoxValue;}
}

var imagesShown = false;

/**
 * Simple replace without looking at original (untranslated) string.
 */
function showImages() {
  console.log("showimag");
    var txtBox = document.getElementById('translation');
    var myDoc = document.getElementById('source_phrase_container');
    var sourceStr = myDoc.innerText;
    var expr =  /!\[\]\(([^\)]+)\)/g;
    while (( result = expr.exec(sourceStr)) !== null  ) {
      var tag = "";
      console.log(tag);
        $("#translation_text_container").prepend(tag);
    }
}

function showAllQuestions() {
    var hint = $('#hint');
    while (!hint.is(":disabled")) {
        hint.click();
    }
}

/**
 * Experimental opening of URL in new tab.
 * DOES NOT WORK for Alt+P due to security restrictions.
 */
function chromeOpenURL(url) {
  var yourCustomJavaScriptCode = 'var win = window.open(\"' + url + '\", "_blank"); win.focus();';
  var script = document.createElement('script');
  var code = document.createTextNode('(function() {' + yourCustomJavaScriptCode + '})();');
  script.appendChild(code);
  (document.body || document.head).appendChild(script);

}
// TODO check on which host we are running, Alt+P and Alt+A only work on translate.khanacademy.org, the others on crowdin.com
function key_event(e) {
  var txtBox = document.getElementById('translation');

  // Alt+P open this exercise in the proofread modus, only works if you have proofread permission on crowdin
  if (e.altKey && e.keyCode == 80) {
      // extract the exercise name e.g. exercises=rounding-to-the-nearest-ten-or-hundred#xe9e1a3b9f44d9837
      var expr =  /.+=(.+)#.+/g
      var url = window.location.href;
      var result = expr.exec(url);

      // todo find out the language which is currently used on translate.khanacademy.org
      var proof = "https://crowdin.com/proofread/khanacademy/all/enus-de#q=e/";
      var url = proof + result[1]
      console.log(url);
      window.open(url,'_blank');
      if(chrome) {
        window.location.href = url;
      }
  }

  // Alt+A for showing all exercise questions
  if (e.altKey && e.keyCode == 65) {
    showAllQuestions();
  }

  // Alt+N to move to the next exercise on translate.khanacademy.org
  if (e.altKey && e.keyCode == 78) {
      var item = $("li:has(a.active)");
      item.parent().children("li:eq("+(item.index()+1)+")").children("a").click();
      showAllQuestions();
  }

  // match Alt+O replace coordinates in the form of ( 4.5 , 5.6 ) with ( 4.5 | 5.6 ), white spaces are not trimmed
  if (e.altKey && e.keyCode == 79) {
      txtBox.innerHTML = txtBox.innerHTML.replace( /\(([-+]?[0-9]*\.?[0-9]+),( ?[-+]?[0-9]*\.?[0-9]+)\)/g, '($1|$2)' );
  }
  // match Alt+I replace KA image urls & fix the Bing ImgURL error
  if (e.altKey && e.keyCode == 73) {

    //Fix the Bing ImgURL error
    txtBox.innerHTML = txtBox.innerHTML.replace('![] (','![](');
    txtBox.innerHTML = txtBox.innerHTML.replace('! [] (','![](');
    txtBox.innerHTML = txtBox.innerHTML.replace('Interaktive Grafik','interactive-graph');
    txtBox.innerHTML = txtBox.innerHTML.replace(/Radio/g,'radio');
    txtBox.innerHTML = txtBox.innerHTML.replace(/Eingabe-Zahl/,'input-number');
    txtBox.innerHTML = txtBox.innerHTML.replace(/Eingabe-Nummer/g,'input-number');
    txtBox.innerHTML = txtBox.innerHTML.replace(/numerische Eingabe/g,'numeric-input');
    txtBox.innerHTML = txtBox.innerHTML.replace(/numerische-Eingang/g,'numeric-input');
    txtBox.innerHTML = txtBox.innerHTML.replace(/☃ Bild/g,'☃ image');
    txtBox.innerHTML = txtBox.innerHTML.replace('**How','**Wie');
    txtBox.innerHTML = txtBox.innerHTML.replace('**What','**Was');
    txtBox.innerHTML = txtBox.textContent.replace(/\\text{ ones}}/g,'\\text{ Einer}}');
    txtBox.innerHTML = txtBox.textContent.replace(/\\text{ one}}/g,'\\text{ Einer}}');
    txtBox.innerHTML = txtBox.textContent.replace(/\\text{ tens}}/g,'\\text{ Zehner}}');
    txtBox.innerHTML = txtBox.textContent.replace(/\\text{ ten}}/g,'\\text{ Zehner}}');
    txtBox.innerHTML = txtBox.textContent.replace(/\\text{ hundred}}/g,'\\text{ Hunderter}}');
    txtBox.innerHTML = txtBox.textContent.replace(/\\text{ hundreds}}/g,'\\text{ Hunderter}}');

    //Not sure what alanis stuff above should do, but it doesn't work. This one does.
    simpleReplaceInTxtbox(/!\s+\[\]\s+\(/g, "![](");

    // on regex for english, and second for translation string
    var expr =  /!\[\]\((.+?)\)/g
    var expr2 =  /!\[\]\((.+?)\)/g

    replacePattern(expr,expr2); //causes exception.

  }
  // Alt+L: Show images in text
  if (e.altKey && e.keyCode == 76) {
    if(imagesShown) {
      $(".greasemonkey-image").remove();
      imagesShown = false;
    } else {
      showImages();
      imagesShown = true;
    }
  }
  // Replace math formulas contained in Dollar signs, Alt+U
  if (e.altKey && e.keyCode == 85) {
      // TODO: need to correctly handle escpade Dollar signs e.g. \$ should not be machted as start or end string works in Python and PHP \$.+?(?<!\\)\$ but no in javascript
        var expr = /(\$.+?\$)/g
        var expr2 = /(\$.+?\$)/g
        replacePattern(expr,expr2);
  }
  // Fix coordinates, Alt+W
  if (e.altKey && e.keyCode == 87) {
      var expr = /\$(\{?)\(\s*(-?\d+(([\.,]|\{,\})\d+)?|-?[a-z]|-?\\\\[a-z]+[A-Z]?\{\d+[.,]?\d*\})\s*[,;|]\s*(-?\d+(([\.,]|\{,\})\d+)?|-?[a-z]|-?\\\\[a-z]+[A-Z]?\{\d+[.,]?\d*\})\s*\)(\}?)\$/g;
      simpleReplaceInTxtbox(expr, "$$$1($2{\\,}|{\\,}$5)$8$$");
  }
  // Other fixes, Alt+Q
  if (e.altKey && e.keyCode == 81) {
      //Dollary
      simpleReplaceInTxtbox(/\$\\\\\$(-?\d+([.,]\d+)?)\$/g, "$$$1{\\,}€\$");
      //Decimal dot to comma
      simpleReplaceInTxtbox(/(-?\d+)\.(-?\d+)/g, "$1{,}$2");
      //In number: Need {\,} instead of {\ }
      simpleReplaceInTxtbox(/(\d+)\{\\ \}(\d+)/g, "$1{\\,}$2");
      //In number: Need percentage
      simpleReplaceInTxtbox(/\\*\s*%\s*\$/g, "{\\,}\\%$$");
      //daß -> dass
      simpleReplaceInTxtbox(/daß/g, "dass");
      //daß -> dass
      simpleReplaceInTxtbox(/\.\s*\*\s+\*/g, ".**");
      //40€ -> 40{\,}€ (simple cases)
      simpleReplaceInTxtbox(/\$(\d+)€/g, "$$$1{\\,}€");
      simpleReplaceInTxtbox(/(\d+)€$/g, "$1{\\,}€$$");
      //x-intercept / y-intercept
      simpleReplaceInTxtbox(/\$x\$-intercept/g, "Schnittpunkt mit der $$x$$-Achse");
      simpleReplaceInTxtbox(/\$y\$-intercept/g, "Schnittpunkt mit der $$y$$-Achse");
      //and -> und and other simple phrase replacements
      simpleReplaceInTxtbox(/Both ([A-Z][a-z]+) and ([A-Z][a-z]+)/g, "Sowohl $1 als auch $2");
      simpleReplaceInTxtbox(/Yes, (.*) is correct but (.*) is not(\.?)/g, "Ja, $1 liegt richtig, aber $2 nicht.");
      simpleReplaceInTxtbox(/^In conclusion, the equation has one solution:/g, "Zusammenfassend hat die Gleichung eine Lösung:");
      simpleReplaceInTxtbox(/Find the complex conjugate (.*) of/g, "Finde die Konjugierte $1 von");
      simpleReplaceInTxtbox(/Your answer should be a complex number in the form \$a\+bi\$ where \$a\$ and \$b\$ are real numbers./g, "Deine Antwort sollte eine Komplexe Zahl im Format $$a+bi$$ sein, wobei $$a$$ und $$b$$ reelle Zahlen sind.");
      simpleReplaceInTxtbox(/What are the real and imaginary parts of (\$[a-z]\$) ?\?/g, "Was ist der Real- und Imaginärteil von $1 ?");
      simpleReplaceInTxtbox(/Are( the)? vectors (\$.+\$) and (\$.+\$) equivalent ?\?/g, "Sind die Vektoren $2 und $3 äquivalent?");
      simpleReplaceInTxtbox(/Is the matrix (\$[A-Z]\$) invertible\?/g, "Ist die Matrix $1 invertierbar?");
      simpleReplaceInTxtbox(/The answer is:/g, "Die Antwort ist:");
      simpleReplaceInTxtbox(/The answer:?/g, "Die Antwort:");
      simpleReplaceInTxtbox(/ is not a factor of /g, " ist kein Faktor von ");
      simpleReplaceInTxtbox(/In conclusion,/g, "Zusammenfassend gilt:");
      simpleReplaceInTxtbox(/To conclude\s*[:,]?(\s*)/g, "Zusammenfassend gilt: ");
      simpleReplaceInTxtbox(/This is because/g, "Das gilt, weil");
      simpleReplaceInTxtbox(/What type of number is/g, "Welche Art Zahl ist");
      simpleReplaceInTxtbox(/Let's start by replacing (.*) (by|with)/g, "Beginnen wir mit dem Ersetzen von $1 durch");
      simpleReplaceInTxtbox(/Summary(:?) ?/g, "Zusammenfassung\1");
      simpleReplaceInTxtbox(/Conclusion(:?) ?/g, "Schlussfolgerung\1");
      simpleReplaceInTxtbox(/Express your answer in the form/g, "Schreibe deine Antwort in der Form");
      simpleReplaceInTxtbox(/ is real and complex/g, " ist eine reale und komplexe Zahl");
      simpleReplaceInTxtbox(/ is pure imaginary and complex/g, " ist rein imaginär und daher eine komplexe Zahl");
      simpleReplaceInTxtbox(/ is complex/g, " ist eine komplexe Zahl");
      simpleReplaceInTxtbox(/ unit /g, " Einheit");
      simpleReplaceInTxtbox(/ units /g, " Einheiten ");
      simpleReplaceInTxtbox(/ units$/g, " Einheiten");
      simpleReplaceInTxtbox(/ unit$/g, " Einheit");
      simpleReplaceInTxtbox(/ and so /g, ", also gilt: ");
      simpleReplaceInTxtbox(/ and /g, " und ");
      simpleReplaceInTxtbox(/ for /g, " für ");
      simpleReplaceInTxtbox(/ converges/g, " konvergiert");
      simpleReplaceInTxtbox(/ diverges/g, " divergiert");
      simpleReplaceInTxtbox(/Only/g, "Nur");

  }
}
document.addEventListener('keydown', key_event, true);
<commit_msg>Minor fixes<commit_after>// ==UserScript==
// @name        KA Crowdin Translation Tools
// @namespace   kadeutsch.org/kacrowdintools
// @include     https://crowdin.com/translate/khanacademy/*
// @include     https://translate.khanacademy.org/translate/*
// @description Various keyboard shortcuts to make KA translation on crowdin a little bit easier
// @version     0.5.3
// @grant       none
// @author      Alain Schaefer & Uli Köhler
// @updateURL   https://raw.githubusercontent.com/ulikoehler/KATranslationTools/master/KATranslationTools.user.js
// ==/UserScript==

/*
 Alt + A : Show all excercises (only on translate.khanacadey.org)
 Alt + N : Move to next exercise (only on translate.khanacadey.org)
 Alt + P : Open all new Window with Strings in proofread modus on crowdin (only on translate.khanacadey.org)
 Alt + U : Replace all formulas with formulas from englisch original (works on crowin.net and translate.khanacademy.org)
 Alt + I : replace Image URLs and fix common german Bing-Translation Errors (works on crowin.net and translate.khanacademy.org)
 Alt + W : Auto-fix coordinates. Works only for coordinates WITHOUT operators.
 Alt + Q : Other fixes. Currently: Convert $\\$123$ to $123{\,}€$ ; Convert simple numbers with dot to comma
 Alt + L : Show images
 */

/**
 * Get the text value in the textbox.
 * For debugging purposes ONLY. The information where to replace
 * the value is lost!!
 */
function getTxtboxValue(regex, replacement) {
    var txtBox = document.getElementById('translation');
    return (txtBox.innerHTML || txtBox.value);
}

function replacePattern(expr,expr2){

    //find the propper Crowdin HTML Elements
    var myDoc = document.getElementById('source_phrase_container');
    var txtBox = document.getElementById('translation');

    //copy the HTML values
    var sourceStr = myDoc.innerText;
    var txtBoxValue = (txtBox.innerHTML || txtBox.value);

    var valueIsInValueProperty = (txtBox.innerHTML == "");

    var result;
    var newTextBoxValue = txtBoxValue;

    //replace every occurence of pattern with corresponding occurence in sourcestring e.g. 1st with 1st, 2nd with 2nd
    while (( result = expr.exec(sourceStr)) !== null  ) {
        txtBoxResult = expr2.exec(txtBoxValue);
        //console.log('replacing ' + txtBoxResult[0] + " with " + result[0]);
        newTextBoxValue = newTextBoxValue.replace(txtBoxResult[0], result[0]);
    }
    //Set new value
    if(valueIsInValueProperty) {txtBox.value = newTextBoxValue;}
    else {txtBox.innerHTML = newTextBoxValue;}
}

/**
 * Simple replace without looking at original (untranslated) string.
 */
function simpleReplaceInTxtbox(regex, replacement) {
    var txtBox = document.getElementById('translation');
    var valueIsInValueProperty = (txtBox.innerHTML == "");
    var txtBoxValue = (txtBox.innerHTML || txtBox.value);
    var newTxtBoxValue = txtBoxValue.replace(regex, replacement);
    //Set new value
    if(valueIsInValueProperty) {txtBox.value = newTxtBoxValue;}
    else {txtBox.innerHTML = newTxtBoxValue;}
}

var imagesShown = false;

/**
 * Simple replace without looking at original (untranslated) string.
 */
function showImages() {
  console.log("showimag");
    var txtBox = document.getElementById('translation');
    var myDoc = document.getElementById('source_phrase_container');
    var sourceStr = myDoc.innerText;
    var expr =  /!\[\]\(([^\)]+)\)/g;
    while (( result = expr.exec(sourceStr)) !== null  ) {
      var tag = "";
      console.log(tag);
        $("#translation_text_container").prepend(tag);
    }
}

function showAllQuestions() {
    var hint = $('#hint');
    while (!hint.is(":disabled")) {
        hint.click();
    }
}

/**
 * Experimental opening of URL in new tab.
 * DOES NOT WORK for Alt+P due to security restrictions.
 */
function chromeOpenURL(url) {
  var yourCustomJavaScriptCode = 'var win = window.open(\"' + url + '\", "_blank"); win.focus();';
  var script = document.createElement('script');
  var code = document.createTextNode('(function() {' + yourCustomJavaScriptCode + '})();');
  script.appendChild(code);
  (document.body || document.head).appendChild(script);

}
// TODO check on which host we are running, Alt+P and Alt+A only work on translate.khanacademy.org, the others on crowdin.com
function key_event(e) {
  var txtBox = document.getElementById('translation');

  // Alt+P open this exercise in the proofread modus, only works if you have proofread permission on crowdin
  if (e.altKey && e.keyCode == 80) {
      // extract the exercise name e.g. exercises=rounding-to-the-nearest-ten-or-hundred#xe9e1a3b9f44d9837
      var expr =  /.+=(.+)#.+/g
      var url = window.location.href;
      var result = expr.exec(url);

      // todo find out the language which is currently used on translate.khanacademy.org
      var proof = "https://crowdin.com/proofread/khanacademy/all/enus-de#q=e/";
      var url = proof + result[1]
      console.log(url);
      window.open(url,'_blank');
      if(chrome) {
        window.location.href = url;
      }
  }

  // Alt+A for showing all exercise questions
  if (e.altKey && e.keyCode == 65) {
    showAllQuestions();
  }

  // Alt+N to move to the next exercise on translate.khanacademy.org
  if (e.altKey && e.keyCode == 78) {
      var item = $("li:has(a.active)");
      item.parent().children("li:eq("+(item.index()+1)+")").children("a").click();
      showAllQuestions();
  }

  // match Alt+O replace coordinates in the form of ( 4.5 , 5.6 ) with ( 4.5 | 5.6 ), white spaces are not trimmed
  if (e.altKey && e.keyCode == 79) {
      txtBox.innerHTML = txtBox.innerHTML.replace( /\(([-+]?[0-9]*\.?[0-9]+),( ?[-+]?[0-9]*\.?[0-9]+)\)/g, '($1|$2)' );
  }
  // match Alt+I replace KA image urls & fix the Bing ImgURL error
  if (e.altKey && e.keyCode == 73) {

    //Fix the Bing ImgURL error
    txtBox.innerHTML = txtBox.innerHTML.replace('![] (','![](');
    txtBox.innerHTML = txtBox.innerHTML.replace('! [] (','![](');
    txtBox.innerHTML = txtBox.innerHTML.replace('Interaktive Grafik','interactive-graph');
    txtBox.innerHTML = txtBox.innerHTML.replace(/Radio/g,'radio');
    txtBox.innerHTML = txtBox.innerHTML.replace(/Eingabe-Zahl/,'input-number');
    txtBox.innerHTML = txtBox.innerHTML.replace(/Eingabe-Nummer/g,'input-number');
    txtBox.innerHTML = txtBox.innerHTML.replace(/numerische Eingabe/g,'numeric-input');
    txtBox.innerHTML = txtBox.innerHTML.replace(/numerische-Eingang/g,'numeric-input');
    txtBox.innerHTML = txtBox.innerHTML.replace(/☃ Bild/g,'☃ image');
    txtBox.innerHTML = txtBox.innerHTML.replace('**How','**Wie');
    txtBox.innerHTML = txtBox.innerHTML.replace('**What','**Was');
    txtBox.innerHTML = txtBox.textContent.replace(/\\text{ ones}}/g,'\\text{ Einer}}');
    txtBox.innerHTML = txtBox.textContent.replace(/\\text{ one}}/g,'\\text{ Einer}}');
    txtBox.innerHTML = txtBox.textContent.replace(/\\text{ tens}}/g,'\\text{ Zehner}}');
    txtBox.innerHTML = txtBox.textContent.replace(/\\text{ ten}}/g,'\\text{ Zehner}}');
    txtBox.innerHTML = txtBox.textContent.replace(/\\text{ hundred}}/g,'\\text{ Hunderter}}');
    txtBox.innerHTML = txtBox.textContent.replace(/\\text{ hundreds}}/g,'\\text{ Hunderter}}');

    //Not sure what alanis stuff above should do, but it doesn't work. This one does.
    simpleReplaceInTxtbox(/!\s+\[\]\s+\(/g, "![](");

    // on regex for english, and second for translation string
    var expr =  /!\[\]\((.+?)\)/g
    var expr2 =  /!\[\]\((.+?)\)/g

    replacePattern(expr,expr2); //causes exception.

  }
  // Alt+L: Show images in text
  if (e.altKey && e.keyCode == 76) {
    if(imagesShown) {
      $(".greasemonkey-image").remove();
      imagesShown = false;
    } else {
      showImages();
      imagesShown = true;
    }
  }
  // Replace math formulas contained in Dollar signs, Alt+U
  if (e.altKey && e.keyCode == 85) {
      // TODO: need to correctly handle escpade Dollar signs e.g. \$ should not be machted as start or end string works in Python and PHP \$.+?(?<!\\)\$ but no in javascript
        var expr = /(\$.+?\$)/g
        var expr2 = /(\$.+?\$)/g
        replacePattern(expr,expr2);
  }
  // Fix coordinates, Alt+W
  if (e.altKey && e.keyCode == 87) {
      var expr = /\$(\{?)\(\s*(-?\d+(([\.,]|\{,\})\d+)?|-?[a-z]|-?\\\\[a-z]+[A-Z]?\{\d+[.,]?\d*\})\s*[,;|]\s*(-?\d+(([\.,]|\{,\})\d+)?|-?[a-z]|-?\\\\[a-z]+[A-Z]?\{\d+[.,]?\d*\})\s*\)(\}?)\$/g;
      simpleReplaceInTxtbox(expr, "$$$1($2{\\,}|{\\,}$5)$8$$");
  }
  // Other fixes, Alt+Q
  if (e.altKey && e.keyCode == 81) {
      //Dollary
      simpleReplaceInTxtbox(/\$\\\\\$(-?\d+([.,]\d+)?)\$/g, "$$$1{\\,}€\$");
      //Decimal dot to comma
      simpleReplaceInTxtbox(/(-?\d+)\.(-?\d+)/g, "$1{,}$2");
      //In number: Need {\,} instead of {\ }
      simpleReplaceInTxtbox(/(\d+)\{\\ \}(\d+)/g, "$1{\\,}$2");
      //In number: Need percentage
      simpleReplaceInTxtbox(/\\*\s*%\s*\$/g, "{\\,}\\%$$");
      //daß -> dass
      simpleReplaceInTxtbox(/daß/g, "dass");
      //daß -> dass
      simpleReplaceInTxtbox(/\.\s*\*\s+\*/g, ".**");
      //40€ -> 40{\,}€ (simple cases)
      simpleReplaceInTxtbox(/\$(\d+)€/g, "$$$1{\\,}€");
      simpleReplaceInTxtbox(/(\d+)€$/g, "$1{\\,}€$$");
      //x-intercept / y-intercept
      simpleReplaceInTxtbox(/\$x\$-intercept/g, "Schnittpunkt mit der $$x$$-Achse");
      simpleReplaceInTxtbox(/\$y\$-intercept/g, "Schnittpunkt mit der $$y$$-Achse");
      //and -> und and other simple phrase replacements
      simpleReplaceInTxtbox(/Both ([A-Z][a-z]+) and ([A-Z][a-z]+)/g, "Sowohl $1 als auch $2");
      simpleReplaceInTxtbox(/Yes, (.*) is correct but (.*) is not(\.?)/g, "Ja, $1 liegt richtig, aber $2 nicht.");
      simpleReplaceInTxtbox(/^In conclusion, the equation has one solution:/g, "Zusammenfassend hat die Gleichung eine Lösung:");
      simpleReplaceInTxtbox(/Find the complex conjugate (.*) of/g, "Finde die Konjugierte $1 von");
      simpleReplaceInTxtbox(/Your answer should be a complex number in the form \$a\+bi\$ where \$a\$ and \$b\$ are real numbers./g, "Deine Antwort sollte eine Komplexe Zahl im Format $$a+bi$$ sein, wobei $$a$$ und $$b$$ reelle Zahlen sind.");
      simpleReplaceInTxtbox(/What are the real and imaginary parts of (\$[a-z]\$) ?\?/g, "Was ist der Real- und Imaginärteil von $1 ?");
      simpleReplaceInTxtbox(/Are( the)? vectors (\$.+\$) and (\$.+\$) equivalent ?\?/g, "Sind die Vektoren $2 und $3 äquivalent?");
      simpleReplaceInTxtbox(/Is the matrix (\$[A-Z]\$) invertible\?/g, "Ist die Matrix $1 invertierbar?");
      simpleReplaceInTxtbox(/The answer is(:?)/g, "Die Antwort ist\1");
      simpleReplaceInTxtbox(/The answer(:?)/g, "Die Antwort\1");
      simpleReplaceInTxtbox(/ is not a factor of /g, " ist kein Faktor von ");
      simpleReplaceInTxtbox(/In conclusion,/g, "Zusammenfassend gilt:");
      simpleReplaceInTxtbox(/To conclude\s*[:,]?(\s*)/g, "Zusammenfassend gilt: ");
      simpleReplaceInTxtbox(/This is because/g, "Das gilt, weil");
      simpleReplaceInTxtbox(/What type of number is/g, "Welche Art Zahl ist");
      simpleReplaceInTxtbox(/Let's start by replacing (.*) (by|with)/g, "Beginnen wir mit dem Ersetzen von $1 durch");
      simpleReplaceInTxtbox(/Summary(:?) ?/g, "Zusammenfassung\1");
      simpleReplaceInTxtbox(/Conclusion(:?) ?/g, "Schlussfolgerung\1");
      simpleReplaceInTxtbox(/Express your answer in the form/g, "Schreibe deine Antwort in der Form");
      simpleReplaceInTxtbox(/ is real and complex/g, " ist eine reale und komplexe Zahl");
      simpleReplaceInTxtbox(/ is pure imaginary and complex/g, " ist rein imaginär und daher eine komplexe Zahl");
      simpleReplaceInTxtbox(/ is complex/g, " ist eine komplexe Zahl");
      simpleReplaceInTxtbox(/ unit /g, " Einheit");
      simpleReplaceInTxtbox(/ units /g, " Einheiten ");
      simpleReplaceInTxtbox(/ units$/g, " Einheiten");
      simpleReplaceInTxtbox(/ unit$/g, " Einheit");
      simpleReplaceInTxtbox(/ and so /g, ", also gilt: ");
      simpleReplaceInTxtbox(/ and /g, " und ");
      simpleReplaceInTxtbox(/ for /g, " für ");
      simpleReplaceInTxtbox(/ converges/g, " konvergiert");
      simpleReplaceInTxtbox(/ diverges/g, " divergiert");
      simpleReplaceInTxtbox(/Only/g, "Nur");

  }
}
document.addEventListener('keydown', key_event, true);
<|endoftext|>


<commit_before>$(function () {
  var $el, $ps, $up, totalHeight;
  function expandBox(elem){
    totalHeight = 30
    defaultHeight = 700

    $el = $(elem);
    $p  = $el.parent();
    $up = $p.parent();
    $ps = $up.find("div");

    // measure how tall inside should be by adding together heights of all inside paragraphs (except read-more paragraph)
    $ps.each(function() {
      totalHeight += $(elem).outerHeight();
    });

    // if the stacktrace is too big we should add a scrollbar
    if(totalHeight < defaultHeight){
      defaultHeight = totalHeight
    }
    else{
      $up.css({ "overflow": "auto" })
    }

    $up
      .css({
        // Set height to prevent instant jumpdown when max height is removed
        "height": $up.height(),
        "max-height": defaultHeight
      })
      .animate({
        "height": defaultHeight
      });

    // fade out read-more
    $p.fadeOut();

    // prevent jump-down
    return false;
  }

  document.addEventListener("turbolinks:load", function() {
    $(".expand-box .btn").click(function(event) {
      event.preventDefault();
      expandBox(this);
    });
  })
});<commit_msg>fixed bug with max-height<commit_after>$(function () {
  var $el, $ps, $up, totalHeight;
  function expandBox(elem){
    totalHeight = 30
    defaultHeight = 700

    $el = $(elem);
    $p  = $el.parent();
    $up = $p.parent();
    $ps = $up.find("div .accordion-group");

    // measure how tall inside should be by adding together heights of all inside paragraphs (except read-more paragraph)
    $ps.each(function() {
      totalHeight += $(elem).outerHeight();
    });

    // if the stacktrace is too big we should add a scrollbar
    if(totalHeight < defaultHeight){
      defaultHeight = totalHeight
    }
    else{
      $up.css({ "overflow": "auto" })
    }

    $up
      .css({
        // Set height to prevent instant jumpdown when max height is removed
        "height": $up.height(),
        "max-height": defaultHeight
      })
      .animate({
        "height": defaultHeight
      });

    // fade out read-more
    $p.fadeOut();

    // prevent jump-down
    return false;
  }

  document.addEventListener("turbolinks:load", function() {
    $(".expand-box .btn").click(function(event) {
      event.preventDefault();
      expandBox(this);
    });
  })
});<|endoftext|>


<commit_before>var Hapi = require( "hapi" );
var Good = require( "good" );

var server = new Hapi.Server( {
    connections : {
        routes : {
            cors : true
        }
    }
} );

server.connection( {
    host : "localhost",
    port : 9099
});

server.route( {
    method : "GET",
    path : "/",
    handler : function( request, reply ) {
        reply ( "
hello egjs fake server
" )
            .type( "text/html" );
    }
});

server.route( {
    method : "GET",
    path : "/infiniteGrid/items",
    handler : function( request, reply ) {
        var html = "";
        var limit = request.query.limit || 10;
        var offset = request.query.offset || 1;
        var end = offset + limit;

        var _random = function() {
            return Math.floor( ( Math.random() * 7 ) + 1 );
        }

        for ( ; offset < end; offset++) {
            html = html + "

테스트 " + offset + "

";
        }

        reply( html )
            .type( "text/html");
    }
});

server.register( {
    register : Good,
    options : {
        reporters: [{
            reporter: require( "good-console" ),
            events: {
                response: '*',
                log: '*'
            }
        }]
    }
}, function( err ) {
    if ( err ) {
        throw err;
    }

    server.start(function () {
        server.log('info', 'egjs fake server running at: ' + server.info.uri);
    });
});<commit_msg>test(infiniteGridService) : fix end value error<commit_after>var Hapi = require( "hapi" );
var Good = require( "good" );

var server = new Hapi.Server( {
    connections : {
        routes : {
            cors : true
        }
    }
} );

server.connection( {
    host : "localhost",
    port : 9099
});

server.route( {
    method : "GET",
    path : "/",
    handler : function( request, reply ) {
        reply ( "
hello egjs fake server
" )
            .type( "text/html" );
    }
});

server.route( {
    method : "GET",
    path : "/infiniteGrid/items",
    handler : function( request, reply ) {
        var html = "";

        var offset = request.query.offset || 1;
        offset = parseInt( offset, 10 );

        var limit = request.query.limit || 10;
        limit = parseInt( limit, 10 );

        var end = offset + limit;

        var _random = function() {
            return Math.floor( ( Math.random() * 7 ) + 1 );
        }

        for ( ; offset < end; offset ++ ) {
            html = html + "

테스트 " + offset + "

";
        }

        reply( html )
            .type( "text/html");
    }
});

server.register( {
    register : Good,
    options : {
        reporters: [{
            reporter: require( "good-console" ),
            events: {
                response: '*',
                log: '*'
            }
        }]
    }
}, function( err ) {
    if ( err ) {
        throw err;
    }

    server.start(function () {
        server.log('info', 'egjs fake server running at: ' + server.info.uri);
    });
});<|endoftext|>


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

// This function's role is to enable smooth transition to the brave new world of
// User-Agent Client Hints. If you have legacy code that relies on
// `navigator.userAgent` and which relies on entropy that will go away by
// default, you *need* to refactor it to use UA-CH. This function is to be used
// as a stop gap, to enable smooth transition during that period.

/**
* @param {string[]} hints
* @return {Promise<string|undefined>} A Promise that resolves to a string if a
*   UA could be synthesized from client hints, otherwise undefined.
*/
async function getUserAgentUsingClientHints(hints) {
  // Helper functions for platform specific strings
  const GetCrosSpecificString = values => {
    let osCPUFragment = '';
    if (values.bitness == '64') {
      if (values.architecture == 'x86') {
        osCPUFragment = 'x86_64'
      } else if (values.architecture == 'arm') {
        osCPUFragment = 'aarch64';
      }
    } else if (values.architecture == 'arm' && values.bitness == '32') {
      osCPUFragment = 'armv7l';
    }
    if (osCPUFragment == '') {
      return `X11; CrOS ${values.platformVersion}`;
    }
    return `X11; CrOS ${osCPUFragment} ${values.platformVersion}`;
  }

  const GetWindowsSpecificString = values => {
    let osCPUFragment = '';
    if (values.architecture == 'x86' && values.bitness == '64') {
      osCPUFragment = '; Win64; x64';
    } else if (values.architecture == 'arm'){
      osCPUFragment = '; ARM';
    }
    return `Windows NT ${values.platformVersion}${osCPUFragment}`;
  }

  const GetMacSpecificString = values => {
    let newUA = 'Macintosh; Intel Mac OS X ';
    let macVersion = values.platformVersion;
    if (macVersion.indexOf('.') > -1) {
      macVersion = macVersion.split('.').join('_');
    }
    newUA += macVersion;
    return newUA;
  }

  const GetAndroidSpecificString = values => {
    let newUA = 'Linux; Android ';
    newUA += values.platformVersion;
    if (values.model) {
      newUA += '; ';
      newUA += values.model;
    }
    return newUA;
  }

  const Initialize = (values) => {
    if (!values.architecture) {
      values.architecture = 'x86';
    }
    if (!values.bitness) {
      values.bitness = '64';
    }
    if (!values.model) {
      values.model = '';
    }
    if (!values.platform) {
      values.platform = 'Windows';
    }
    if (!values.platformVersion) {
      values.platformVersion = '10.0';
    }
    return values;
  }

  if (!navigator.userAgentData || Date.now() > 1640995199000) {
    return Promise.resolve();
  }

  // Verify that this is a Chromium-based browser
  let is_chromium = false;
  let chromium_version;
  const is_reduced_ua_pattern = new RegExp('AppleWebKit/539.36 \\(KHTML, like Gecko\\) Chrome/\\d+.0.0.0 (Mobile )?Safari/537.36$');
  navigator.userAgentData.brands.forEach(value => {
    if (value.brand == 'Chromium') {
      // Let's double check the UA string as well, so we don't accidentally
      // capture a headless browser or friendly bot (which should report as
      // HeadlessChrome or something entirely different).
      is_chromium = is_reduced_ua_pattern.test(navigator.userAgent);
      chromium_version = value.version;
    }
  });
  if (!is_chromium) {
    // If this is not a Chromium-based browser, the UA string should be very
    // different. So bailing...
    return Promise.resolve();
  }

  // Main logic
  return new Promise(resolve => {
    navigator.userAgentData.getHighEntropyValues(hints).then(values => {
      let initialValues = {
        platform: navigator.userAgentData?.platform,
        uaFullVersion: `${chromium_version}.0.0.0`,
      };
      values = Object.assign(initialValues, values);
      values = Initialize(values);
      let newUA = 'Mozilla/5.0 (';
      if (['Chrome OS', 'Chromium OS'].includes(values.platform)) {
        newUA += GetCrosSpecificString(values);
      } else if (values.platform == 'Windows') {
        newUA += GetWindowsSpecificString(values);
      } else if (values.platform == 'macOS') {
        newUA += GetMacSpecificString(values);
      } else if (values.platform == 'Android') {
        newUA += GetAndroidSpecificString(values);
      } else {
        newUA += 'X11; Linux x86_64';
      }
      newUA += ') AppleWebKit/537.36 (KHTML, like Gecko) Chrome/';
      newUA += values.uaFullVersion;
      if (navigator.userAgentData.mobile) {
        newUA += ' Mobile';
      }
      newUA += ' Safari/537.36';
      resolve(newUA);
    })
  })
}

/**
* @param {string[]} hints
* @return {Promise<string|undefined>} A Promise that resolves on overriding the
*   navigator.userAgent string.
*/
async function overrideUserAgentUsingClientHints(hints) {
  return new Promise(resolve => {
    getUserAgentUsingClientHints(hints).then(newUA => {
      // Got a new UA value. Now override `navigator.userAgent`.
      Object.defineProperty(navigator, 'userAgent', {
        value: newUA,
        writable: false,
        configurable: true
      });
      resolve();
    })
  });
}

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

// This function's role is to enable smooth transition to the brave new world of
// User-Agent Client Hints. If you have legacy code that relies on
// `navigator.userAgent` and which relies on entropy that will go away by
// default, you *need* to refactor it to use UA-CH. This function is to be used
// as a stop gap, to enable smooth transition during that period.

/**
* @param {string[]} hints
* @return {Promise<string|undefined>} A Promise that resolves to a string if a
*   UA could be synthesized from client hints, otherwise undefined.
*/
async function getUserAgentUsingClientHints(hints) {
  // Helper functions for platform specific strings
  const GetCrosSpecificString = values => {
    let osCPUFragment = '';
    if (values.bitness == '64') {
      if (values.architecture == 'x86') {
        osCPUFragment = 'x86_64'
      } else if (values.architecture == 'arm') {
        osCPUFragment = 'aarch64';
      }
    } else if (values.architecture == 'arm' && values.bitness == '32') {
      osCPUFragment = 'armv7l';
    }
    if (osCPUFragment == '') {
      return `X11; CrOS ${values.platformVersion}`;
    }
    return `X11; CrOS ${osCPUFragment} ${values.platformVersion}`;
  }

  const GetWindowsSpecificString = values => {
    let osCPUFragment = '';
    if (values.architecture == 'x86' && values.bitness == '64') {
      osCPUFragment = '; Win64; x64';
    } else if (values.architecture == 'arm'){
      osCPUFragment = '; ARM';
    }
    return `Windows NT ${values.platformVersion}${osCPUFragment}`;
  }

  const GetMacSpecificString = values => {
    let newUA = 'Macintosh; Intel Mac OS X ';
    let macVersion = values.platformVersion;
    if (macVersion.indexOf('.') > -1) {
      macVersion = macVersion.split('.').join('_');
    }
    newUA += macVersion;
    return newUA;
  }

  const GetAndroidSpecificString = values => {
    let newUA = 'Linux; Android ';
    newUA += values.platformVersion;
    if (values.model) {
      newUA += '; ';
      newUA += values.model;
    }
    return newUA;
  }

  const Initialize = (values) => {
    if (!values.architecture) {
      values.architecture = 'x86';
    }
    if (!values.bitness) {
      values.bitness = '64';
    }
    if (!values.model) {
      values.model = '';
    }
    if (!values.platform) {
      values.platform = 'Windows';
    }
    if (!values.platformVersion) {
      values.platformVersion = '10.0';
    }
    return values;
  }

  if (!navigator.userAgentData || Date.now() > 1640995199000) {
    return Promise.resolve();
  }

  // Verify that this is a Chromium-based browser
  let is_chromium = false;
  let chromium_version;
  const is_reduced_ua_pattern = new RegExp('AppleWebKit/537.36 \\(KHTML, like Gecko\\) Chrome/\\d+.0.0.0 (Mobile )?Safari/537.36$');
  navigator.userAgentData.brands.forEach(value => {
    if (value.brand == 'Chromium') {
      // Let's double check the UA string as well, so we don't accidentally
      // capture a headless browser or friendly bot (which should report as
      // HeadlessChrome or something entirely different).
      is_chromium = is_reduced_ua_pattern.test(navigator.userAgent);
      chromium_version = value.version;
    }
  });
  if (!is_chromium) {
    // If this is not a Chromium-based browser, the UA string should be very
    // different. So bailing...
    return Promise.resolve();
  }

  // Main logic
  return new Promise(resolve => {
    navigator.userAgentData.getHighEntropyValues(hints).then(values => {
      let initialValues = {
        platform: navigator.userAgentData?.platform,
        uaFullVersion: `${chromium_version}.0.0.0`,
      };
      values = Object.assign(initialValues, values);
      values = Initialize(values);
      let newUA = 'Mozilla/5.0 (';
      if (['Chrome OS', 'Chromium OS'].includes(values.platform)) {
        newUA += GetCrosSpecificString(values);
      } else if (values.platform == 'Windows') {
        newUA += GetWindowsSpecificString(values);
      } else if (values.platform == 'macOS') {
        newUA += GetMacSpecificString(values);
      } else if (values.platform == 'Android') {
        newUA += GetAndroidSpecificString(values);
      } else {
        newUA += 'X11; Linux x86_64';
      }
      newUA += ') AppleWebKit/537.36 (KHTML, like Gecko) Chrome/';
      newUA += values.uaFullVersion;
      if (navigator.userAgentData.mobile) {
        newUA += ' Mobile';
      }
      newUA += ' Safari/537.36';
      resolve(newUA);
    })
  })
}

/**
* @param {string[]} hints
* @return {Promise<string|undefined>} A Promise that resolves on overriding the
*   navigator.userAgent string.
*/
async function overrideUserAgentUsingClientHints(hints) {
  return new Promise(resolve => {
    getUserAgentUsingClientHints(hints).then(newUA => {
      // Got a new UA value. Now override `navigator.userAgent`.
      Object.defineProperty(navigator, 'userAgent', {
        value: newUA,
        writable: false,
        configurable: true
      });
      resolve();
    })
  });
}

export { getUserAgentUsingClientHints, overrideUserAgentUsingClientHints };
<|endoftext|>


<commit_before>// Common variables
var common = {};
common.cookieExpiry = 999; // 999 days

// All Players
common.allGuilds = [];

// Alchemists
common.allGuilds.push({});
L = common.allGuilds.length - 1;
common.allGuilds[L].name = 'alchemists';
common.allGuilds[L].players = [
  {name:'midas', hp:14, sponge:[5, 10], role:'c'},
  {name:'smoke', hp:16, sponge:[6, 12], role:'c'},
  {name:'flask', hp:10, sponge:[], role:'m'},
  {name:'naja', hp:7, sponge:[], role:'m'},
  {name:'calculus', hp:15, sponge:[5, 10]},
  {name:'compound', hp:20, sponge:[6, 12]},
  {name:'katalyst', hp:27, sponge:[9, 18]},
  {name:'katalyst', hp:29, sponge:[14, 24]},
  {name:'mercury', hp:15, sponge:[5, 10]},
  {name:'venin', hp:16, sponge:[5, 10]},
  {name:'vitriol', hp:12, sponge:[4, 8]},
];
common.allGuilds[L].union = [
  'avarisse',
  'decimate',
  'harry',
  'hemlocke',
  'mist',
  'snakeskin',
];

// Brewers
common.allGuilds.push({});
L = common.allGuilds.length - 1;
common.allGuilds[L].name = 'brewers';
common.allGuilds[L].players = [
  {name:'esters', hp:22, sponge:[8, 16], role:'c'},
  {name:'tapper', hp:18, sponge:[6, 12], role:'c'},
  {name:'quaff', hp:10, sponge:[], role:'m'},
  {name:'scum', hp:8, sponge:[], role:'m'},
  {name:'friday', hp:12, sponge:[4, 8]},
  {name:'hooper', hp:17, sponge:[6, 12]},
  {name:'mash', hp:17, sponge:[6, 12]},
  {name:'spigot', hp:16, sponge:[5, 10]},
  {name:'spigot-v', hp:16, sponge:[6,12]},
  {name:'stave', hp:23, sponge:[8, 16]},
  {name:'stoker', hp:18, sponge:[6, 12]},
];
common.allGuilds[L].union = [
  'avarisse',
  'fangtooth',
  'gutter',
  'harry',
  'hemlocke',
  'rage',
];

// Butchers

// Engineers

// Fishermen

// Hunters
common.allGuilds.push({});
L = common.allGuilds.length - 1;
common.allGuilds[L].name = 'hunters';
common.allGuilds[L].players = [
  {name:'theron', hp:18, sponge:[6, 12], role:'c'},
  {name:'fahad', hp:8, sponge:[], role:'m'},
  {name:'chaska', hp:16, sponge:[6, 12]},
  {name:'egret', hp:12, sponge:[4, 8]},
  {name:'hearne', hp:20, sponge:[7, 14]},
  {name:'jaecar', hp:14, sponge:[5, 10]},
  {name:'seenah', hp:21, sponge:[7, 14]},
  {name:'zarola', hp:12, sponge:[4, 8]},
];
common.allGuilds[L].union = [
  'avarisse',
  'hemlocke',
  'minx',
];

// Masons

// Morticians
common.allGuilds.push({});
L = common.allGuilds.length - 1;
common.allGuilds[L].name = 'morticians';
common.allGuilds[L].players = [
  {name:'obulus', hp:16, sponge:[5, 10], role:'c'},
  {name:'scalpel', hp:17, sponge:[6, 12], role:'c'},
  {name:'dirge', hp:5, sponge:[], role:'m'},
  {name:'vileswarm', hp:7, sponge:[], role:'m'},
  {name:'bonesaw', hp:13, sponge:[4, 8]},
  {name:'casket', hp:17, sponge:[6, 12]},
  {name:'cosset', hp:12, sponge:[4, 8]},
  {name:'ghast', hp:21, sponge:[7, 14]},
  {name:'graves', hp:14, sponge:[5, 10]},
  {name:'graves-v', hp:14, sponge:[5, 10]},
  {name:'silence', hp:15, sponge:[5, 10]},
];
common.allGuilds[L].union = [
  'avarisse',
  'fangtooth',
  'minx',
  'mist',
  'rage',
];

// Union
common.allGuilds.push({});
L = common.allGuilds.length - 1;
common.allGuilds[L].name = 'union';
common.allGuilds[L].players = [
  {name:'blackheart', hp:16, sponge:[5, 10], role:'c'},
  {name:'rage-v', hp:17, sponge:[6, 12], role:'c'},
  {name:'coin', hp:10, sponge:[], role:'m'},
  {name:'strongbox', hp:10, sponge:[], role:'m'},
  {name:'avarisse', hp:20, sponge:[7, 14]},
  {name:'greede', hp:4, sponge:[], role:'greede'},
  {name:'decimate', hp:14, sponge:[5, 10]},
  {name:'fangtooth', hp:29, sponge:[10, 20]},
  {name:'gutter', hp:14, sponge:[5, 10]},
  {name:'harry', hp:19, sponge:[7, 14]},
  {name:'hemlocke', hp:10, sponge:[3, 6]},
  {name:'minx', hp:12, sponge:[4, 8]},
  {name:'mist', hp:12, sponge:[4, 8]},
  {name:'rage', hp:17, sponge:[6, 12]},
  {name:'snakeskin', hp:12, sponge:[4, 8]},
];
common.allGuilds[L].union = [];

// Common functions
common.removeWhiteSpace = function removeWhiteSpace(someString) {
  // Replace multiple spaces with one, REMOVE leading and trailing spaces.
  return someString.replace( /[\s\n\r]+/g, ' ' ).replace( /^\s|\s$/g, '' );
  // This matches leading and trailing spaces of any number /^\s+|\s+$/g
};

common.findInArray = function findInArray(array, searchValue, searchKey, returnKey) {
  var returnObj = array.find(function(item) {
    return item[searchKey] == searchValue;
  });
  if (returnKey != undefined) {
    return returnObj[returnKey];
  } else {
    return returnObj;
  }
}

common.getThisID = function getThisID() {
  return location.pathname.replace(/^\//, '');
};

common.getThisSearch = function getThisSearch() {
  return location.search.replace(/^\?/, '');
};

common.parseRosterCookie = function parseRosterCookie(rosterCookie) {
  var guild = rosterCookie.match( /3([a-z])+2/ );
  if (guild) {
    guild = guild[0].replace( /\d/g, '' );
  }
  var players = rosterCookie.match( /1([a-z\-])+0/g );
  if (players) {
    for (var i = 0; i < players.length; i++) {
      players[i] = players[i].replace( /\d/g, '' );
    }
  }
  return {guild:guild, players:players};
}

common.playerButtonHTML = function playerButtonHTML(name, special) {
  var Name = common.capFirst(name).replace( /-v$/, ', Veteran' ) + special;
  if (name == 'avarisse') {
    Name = 'Avarisse & Greede';
  }
  if (name == 'harry') {
    Name = 'Harry ‘the Hat’';
  }
  return '<button id="' + name + '-butt" class="btn btn-default" type="button">' + Name + '</button>';
}

common.sumArray = function sumArray(someArray, useFloat) {
  // Sums all values in an array which may be strings. If a value cannot be parsed, it's skipped
  useFloat = useFloat || false;
  if (someArray && (someArray.length > 0)) {
    return someArray.reduce(function(prev, curr) {
      if (useFloat) {
        curr = parseFloat(curr);
      } else {
        curr = parseInt(curr);
      }
      if (isNaN(curr)) {
        curr = 0;
      };
      return prev + curr;
    });
  } else {
    return 0;
  }
}

// Adapted from http://stackoverflow.com/a/32501584
common.setSelectOnClick = function setSelectOnClick(selectorList) {
  for (var i = 0; i < selectorList.length; i++) {
    $(selectorList[i]).blur(function() {
      if ($(this).attr("data-selected-all")) {
        $(this).removeAttr("data-selected-all");
      }
    });
    $(selectorList[i]).click(function() {
      if (!$(this).attr("data-selected-all")) {
        try {
          $(this).selectionStart = 0;
          $(this).selectionEnd = $(this).value.length + 1;
          //add atribute allowing normal selecting post focus
          $(this).attr("data-selected-all", true);
        } catch (err) {
          $(this).select();
          //add atribute allowing normal selecting post focus
          $(this).attr("data-selected-all", true);
        }
      }
    });
  }
}

//From http://stackoverflow.com/a/7224605
common.capFirst = function capFirst(s) {
  return s && s[0].toUpperCase() + s.slice(1);
}

common.sortByKey = function sortByKey(array, key) {
  return array.sort(function getDelta(a, b) {
    var x = a[key];
    var y = b[key];

    if (typeof x == "string") {
      x = x.toLowerCase();
    }
    if (typeof y == "string") {
      y = y.toLowerCase();
    }
    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  });
}

//Adapted from http://stackoverflow.com/a/21152762
common.parseQueryString = function parseQueryString() {
  var qd = {};
  location.search.substr(1).split("&").forEach(function(item) {
    var parts = item.split("=");
    var k = parts[0];
    var v = decodeURIComponent(parts[1]);
    (k in qd) ? qd[k].push(v) : qd[k] = [v]
  });
  return qd;
}

common.allPlayers = [];
var unionIndex = 0;
for (var i = 0; i < common.allGuilds.length; i++) {
  if (common.allGuilds[i].name != 'union') {
    for (var j = 0; j < common.allGuilds[i].players.length; j++) {
      common.allPlayers.push(common.allGuilds[i].players[j]);
    }
  } else {
    unionIndex = i;
  }
  common.sortByKey(common.allGuilds[i].players, 'name');
  common.allGuilds[i].union.sort();
}
common.sortByKey(common.allPlayers, 'name');
for (var i = 0; i < common.allGuilds[unionIndex].players.length; i++) {
  common.allPlayers.push(common.allGuilds[unionIndex].players[i]);
}
<commit_msg>Fixed vKatalyst's name.<commit_after>// Common variables
var common = {};
common.cookieExpiry = 999; // 999 days

// All Players
common.allGuilds = [];

// Alchemists
common.allGuilds.push({});
L = common.allGuilds.length - 1;
common.allGuilds[L].name = 'alchemists';
common.allGuilds[L].players = [
  {name:'midas', hp:14, sponge:[5, 10], role:'c'},
  {name:'smoke', hp:16, sponge:[6, 12], role:'c'},
  {name:'flask', hp:10, sponge:[], role:'m'},
  {name:'naja', hp:7, sponge:[], role:'m'},
  {name:'calculus', hp:15, sponge:[5, 10]},
  {name:'compound', hp:20, sponge:[6, 12]},
  {name:'katalyst', hp:27, sponge:[9, 18]},
  {name:'katalyst-v', hp:29, sponge:[14, 24]},
  {name:'mercury', hp:15, sponge:[5, 10]},
  {name:'venin', hp:16, sponge:[5, 10]},
  {name:'vitriol', hp:12, sponge:[4, 8]},
];
common.allGuilds[L].union = [
  'avarisse',
  'decimate',
  'harry',
  'hemlocke',
  'mist',
  'snakeskin',
];

// Brewers
common.allGuilds.push({});
L = common.allGuilds.length - 1;
common.allGuilds[L].name = 'brewers';
common.allGuilds[L].players = [
  {name:'esters', hp:22, sponge:[8, 16], role:'c'},
  {name:'tapper', hp:18, sponge:[6, 12], role:'c'},
  {name:'quaff', hp:10, sponge:[], role:'m'},
  {name:'scum', hp:8, sponge:[], role:'m'},
  {name:'friday', hp:12, sponge:[4, 8]},
  {name:'hooper', hp:17, sponge:[6, 12]},
  {name:'mash', hp:17, sponge:[6, 12]},
  {name:'spigot', hp:16, sponge:[5, 10]},
  {name:'spigot-v', hp:16, sponge:[6,12]},
  {name:'stave', hp:23, sponge:[8, 16]},
  {name:'stoker', hp:18, sponge:[6, 12]},
];
common.allGuilds[L].union = [
  'avarisse',
  'fangtooth',
  'gutter',
  'harry',
  'hemlocke',
  'rage',
];

// Butchers

// Engineers

// Fishermen

// Hunters
common.allGuilds.push({});
L = common.allGuilds.length - 1;
common.allGuilds[L].name = 'hunters';
common.allGuilds[L].players = [
  {name:'theron', hp:18, sponge:[6, 12], role:'c'},
  {name:'fahad', hp:8, sponge:[], role:'m'},
  {name:'chaska', hp:16, sponge:[6, 12]},
  {name:'egret', hp:12, sponge:[4, 8]},
  {name:'hearne', hp:20, sponge:[7, 14]},
  {name:'jaecar', hp:14, sponge:[5, 10]},
  {name:'seenah', hp:21, sponge:[7, 14]},
  {name:'zarola', hp:12, sponge:[4, 8]},
];
common.allGuilds[L].union = [
  'avarisse',
  'hemlocke',
  'minx',
];

// Masons

// Morticians
common.allGuilds.push({});
L = common.allGuilds.length - 1;
common.allGuilds[L].name = 'morticians';
common.allGuilds[L].players = [
  {name:'obulus', hp:16, sponge:[5, 10], role:'c'},
  {name:'scalpel', hp:17, sponge:[6, 12], role:'c'},
  {name:'dirge', hp:5, sponge:[], role:'m'},
  {name:'vileswarm', hp:7, sponge:[], role:'m'},
  {name:'bonesaw', hp:13, sponge:[4, 8]},
  {name:'casket', hp:17, sponge:[6, 12]},
  {name:'cosset', hp:12, sponge:[4, 8]},
  {name:'ghast', hp:21, sponge:[7, 14]},
  {name:'graves', hp:14, sponge:[5, 10]},
  {name:'graves-v', hp:14, sponge:[5, 10]},
  {name:'silence', hp:15, sponge:[5, 10]},
];
common.allGuilds[L].union = [
  'avarisse',
  'fangtooth',
  'minx',
  'mist',
  'rage',
];

// Union
common.allGuilds.push({});
L = common.allGuilds.length - 1;
common.allGuilds[L].name = 'union';
common.allGuilds[L].players = [
  {name:'blackheart', hp:16, sponge:[5, 10], role:'c'},
  {name:'rage-v', hp:17, sponge:[6, 12], role:'c'},
  {name:'coin', hp:10, sponge:[], role:'m'},
  {name:'strongbox', hp:10, sponge:[], role:'m'},
  {name:'avarisse', hp:20, sponge:[7, 14]},
  {name:'greede', hp:4, sponge:[], role:'greede'},
  {name:'decimate', hp:14, sponge:[5, 10]},
  {name:'fangtooth', hp:29, sponge:[10, 20]},
  {name:'gutter', hp:14, sponge:[5, 10]},
  {name:'harry', hp:19, sponge:[7, 14]},
  {name:'hemlocke', hp:10, sponge:[3, 6]},
  {name:'minx', hp:12, sponge:[4, 8]},
  {name:'mist', hp:12, sponge:[4, 8]},
  {name:'rage', hp:17, sponge:[6, 12]},
  {name:'snakeskin', hp:12, sponge:[4, 8]},
];
common.allGuilds[L].union = [];

// Common functions
common.removeWhiteSpace = function removeWhiteSpace(someString) {
  // Replace multiple spaces with one, REMOVE leading and trailing spaces.
  return someString.replace( /[\s\n\r]+/g, ' ' ).replace( /^\s|\s$/g, '' );
  // This matches leading and trailing spaces of any number /^\s+|\s+$/g
};

common.findInArray = function findInArray(array, searchValue, searchKey, returnKey) {
  var returnObj = array.find(function(item) {
    return item[searchKey] == searchValue;
  });
  if (returnKey != undefined) {
    return returnObj[returnKey];
  } else {
    return returnObj;
  }
}

common.getThisID = function getThisID() {
  return location.pathname.replace(/^\//, '');
};

common.getThisSearch = function getThisSearch() {
  return location.search.replace(/^\?/, '');
};

common.parseRosterCookie = function parseRosterCookie(rosterCookie) {
  var guild = rosterCookie.match( /3([a-z])+2/ );
  if (guild) {
    guild = guild[0].replace( /\d/g, '' );
  }
  var players = rosterCookie.match( /1([a-z\-])+0/g );
  if (players) {
    for (var i = 0; i < players.length; i++) {
      players[i] = players[i].replace( /\d/g, '' );
    }
  }
  return {guild:guild, players:players};
}

common.playerButtonHTML = function playerButtonHTML(name, special) {
  var Name = common.capFirst(name).replace( /-v$/, ', Veteran' ) + special;
  if (name == 'avarisse') {
    Name = 'Avarisse & Greede';
  }
  if (name == 'harry') {
    Name = 'Harry ‘the Hat’';
  }
  return '<button id="' + name + '-butt" class="btn btn-default" type="button">' + Name + '</button>';
}

common.sumArray = function sumArray(someArray, useFloat) {
  // Sums all values in an array which may be strings. If a value cannot be parsed, it's skipped
  useFloat = useFloat || false;
  if (someArray && (someArray.length > 0)) {
    return someArray.reduce(function(prev, curr) {
      if (useFloat) {
        curr = parseFloat(curr);
      } else {
        curr = parseInt(curr);
      }
      if (isNaN(curr)) {
        curr = 0;
      };
      return prev + curr;
    });
  } else {
    return 0;
  }
}

// Adapted from http://stackoverflow.com/a/32501584
common.setSelectOnClick = function setSelectOnClick(selectorList) {
  for (var i = 0; i < selectorList.length; i++) {
    $(selectorList[i]).blur(function() {
      if ($(this).attr("data-selected-all")) {
        $(this).removeAttr("data-selected-all");
      }
    });
    $(selectorList[i]).click(function() {
      if (!$(this).attr("data-selected-all")) {
        try {
          $(this).selectionStart = 0;
          $(this).selectionEnd = $(this).value.length + 1;
          //add atribute allowing normal selecting post focus
          $(this).attr("data-selected-all", true);
        } catch (err) {
          $(this).select();
          //add atribute allowing normal selecting post focus
          $(this).attr("data-selected-all", true);
        }
      }
    });
  }
}

//From http://stackoverflow.com/a/7224605
common.capFirst = function capFirst(s) {
  return s && s[0].toUpperCase() + s.slice(1);
}

common.sortByKey = function sortByKey(array, key) {
  return array.sort(function getDelta(a, b) {
    var x = a[key];
    var y = b[key];

    if (typeof x == "string") {
      x = x.toLowerCase();
    }
    if (typeof y == "string") {
      y = y.toLowerCase();
    }
    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  });
}

//Adapted from http://stackoverflow.com/a/21152762
common.parseQueryString = function parseQueryString() {
  var qd = {};
  location.search.substr(1).split("&").forEach(function(item) {
    var parts = item.split("=");
    var k = parts[0];
    var v = decodeURIComponent(parts[1]);
    (k in qd) ? qd[k].push(v) : qd[k] = [v]
  });
  return qd;
}

common.allPlayers = [];
var unionIndex = 0;
for (var i = 0; i < common.allGuilds.length; i++) {
  if (common.allGuilds[i].name != 'union') {
    for (var j = 0; j < common.allGuilds[i].players.length; j++) {
      common.allPlayers.push(common.allGuilds[i].players[j]);
    }
  } else {
    unionIndex = i;
  }
  common.sortByKey(common.allGuilds[i].players, 'name');
  common.allGuilds[i].union.sort();
}
common.sortByKey(common.allPlayers, 'name');
for (var i = 0; i < common.allGuilds[unionIndex].players.length; i++) {
  common.allPlayers.push(common.allGuilds[unionIndex].players[i]);
}
<|endoftext|>