<commit_before>// Execute search in forum posts
//
// In:
//
// - params.query
// - params.sort
// - params.days
// - params.skip
// - params.limit
// - params.user_info
//
// Out:
//
// - count
// - results
// - users
//

'use strict';

const _                = require('lodash');
const Promise          = require('bluebird');
const sanitize_topic   = require('nodeca.forum/lib/sanitizers/topic');
const sanitize_section = require('nodeca.forum/lib/sanitizers/section');
const sanitize_post    = require('nodeca.forum/lib/sanitizers/post');
const sphinx_escape    = require('nodeca.search').escape;

module.exports = function (N, apiPath) {

  // Send sql query to sphinx, get a response
  //
  N.wire.on(apiPath, function* execute_search(locals) {
    locals.sandbox = locals.sandbox || {};

    let query  = 'SELECT object_id FROM forum_posts WHERE MATCH(?) AND public=1';
    let params = [ sphinx_escape(locals.params.query) ];

    if (locals.params.period > 0) {
      query += ' AND ts > ?';
      // round timestamp to the lowest whole day
      params.push(Math.floor(Date.now() / (24 * 60 * 60 * 1000) - locals.params.period) * 24 * 60 * 60);
    }

    // sort is either `date` or `rel`, sphinx searches by relevance by default
    if (locals.params.sort === 'date') {
      query += ' ORDER BY ts DESC';
    }

    query += ' LIMIT ?,?';
    params.push(locals.params.skip);
    params.push(locals.params.limit);

    let results = yield N.search.execute([
      [ query, params ],
      "SHOW META LIKE 'total_found'"
    ]);

    let posts = _.keyBy(
      yield N.models.forum.Post.find()
                .where('_id').in(_.map(results[0], 'object_id'))
                .lean(true),
      '_id'
    );

    // copy posts preserving order
    locals.sandbox.posts = results[0].map(result => posts[result.object_id]).filter(Boolean);

    locals.sandbox.topics = yield N.models.forum.Topic.find()
                                      .where('_id')
                                      .in(_.uniq(locals.sandbox.posts.map(post => String(post.topic))))
                                      .lean(true);

    locals.sandbox.sections = yield N.models.forum.Section.find()
                                        .where('_id')
                                        .in(_.uniq(locals.sandbox.topics.map(topic => String(topic.section))))
                                        .lean(true);

    locals.count = Number(results[1][0].Value);
  });

  // Check permissions for each post
  //
  N.wire.on(apiPath, function* check_permissions(locals) {
    let topics_by_id   = _.keyBy(locals.sandbox.topics, '_id');
    let sections_by_id = _.keyBy(locals.sandbox.sections, '_id');

    let topics_used   = {};
    let sections_used = {};

    locals.sandbox.posts = (yield Promise.map(locals.sandbox.posts, Promise.coroutine(function* (post) {
      let topic = topics_by_id[post.topic];
      if (!topic) return;

      let section = sections_by_id[topic.section];
      if (!section) return;

      topics_used[topic._id] = topic;
      sections_used[section._id] = section;

      let access_env = { params: {
        topic,
        posts: post,
        user_info: locals.params.user_info
      } };

      yield N.wire.emit('internal:forum.access.post', access_env);

      return access_env.data.access_read ? post : null;
    }))).filter(Boolean);

    locals.sandbox.topics   = _.values(topics_used);
    locals.sandbox.sections = _.values(sections_used);
  });

  // Sanitize results
  //
  N.wire.on(apiPath, function* sanitize(locals) {
    locals.sandbox.posts    = yield sanitize_post(N, locals.sandbox.posts, locals.params.user_info);
    locals.sandbox.topics   = yield sanitize_topic(N, locals.sandbox.topics, locals.params.user_info);
    locals.sandbox.sections = yield sanitize_section(N, locals.sandbox.sections, locals.params.user_info);
  });

  // Fill results
  //
  N.wire.on(apiPath, function fill_results(locals) {
    locals.results = [];

    let topics_by_id = _.keyBy(locals.sandbox.topics, '_id');
    let sections_by_id = _.keyBy(locals.sandbox.sections, '_id');

    locals.sandbox.posts.forEach(post => {
      let topic = topics_by_id[post.topic];
      if (!topic) return;

      let section = sections_by_id[topic.section];
      if (!section) return;

      locals.results.push({ post, topic, section });
    });
  });

  // Fill users
  //
  N.wire.on(apiPath, function fill_users(locals) {
    let users = {};

    locals.results.forEach(result => {
      let post = result.post;

      if (post.user) users[post.user] = true;
      if (post.to_user) users[post.to_user] = true;
      if (post.del_by) users[post.del_by] = true;
      if (post.import_users) post.import_users.forEach(id => { users[id] = true; });
    });

    locals.users = Object.keys(users);
  });

  // Generate snippets for each post
  //
  N.wire.on(apiPath, function* generate_snippets(locals) {
    if (!locals.results.length) return;

    let htmls = locals.results.map(result =>
      // workaround to display astral characters (e.g. smilies) properly;
      // `mysql2` module replaces them with 4 U+FFFD, `mysql` module works
      // correctly (tested with mysql@1.1.2, sphinx@2.3.3-id64-dev)
      result.post.html.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, ch => '&#x' + ch.codePointAt(0).toString(16) + ';'));

    let query = `
      CALL SNIPPETS(
        (?${',?'.repeat(htmls.length - 1)}),
        'forum_posts',
        ?,
        '' AS before_match,
        '' AS after_match,
        'retain' AS html_strip_mode,
        1 AS query_mode,
        0 AS limit
      )`.replace(/\n\s+/mg, '');

    let args = htmls.concat([ sphinx_escape(locals.params.query) ]);

    let snippets = yield N.search.execute(query, args);

    locals.results.forEach((result, i) => {
      result.post.html = snippets[i].snippet;
    });
  });
};
<commit_msg>Change workaround for sphinx returning UTF8_GENERAL_CI instead of UTF8MB4_GENERAL_CI<commit_after>// Execute search in forum posts
//
// In:
//
// - params.query
// - params.sort
// - params.days
// - params.skip
// - params.limit
// - params.user_info
//
// Out:
//
// - count
// - results
// - users
//

'use strict';

const _                = require('lodash');
const Promise          = require('bluebird');
const sanitize_topic   = require('nodeca.forum/lib/sanitizers/topic');
const sanitize_section = require('nodeca.forum/lib/sanitizers/section');
const sanitize_post    = require('nodeca.forum/lib/sanitizers/post');
const sphinx_escape    = require('nodeca.search').escape;

module.exports = function (N, apiPath) {

  // Send sql query to sphinx, get a response
  //
  N.wire.on(apiPath, function* execute_search(locals) {
    locals.sandbox = locals.sandbox || {};

    let query  = 'SELECT object_id FROM forum_posts WHERE MATCH(?) AND public=1';
    let params = [ sphinx_escape(locals.params.query) ];

    if (locals.params.period > 0) {
      query += ' AND ts > ?';
      // round timestamp to the lowest whole day
      params.push(Math.floor(Date.now() / (24 * 60 * 60 * 1000) - locals.params.period) * 24 * 60 * 60);
    }

    // sort is either `date` or `rel`, sphinx searches by relevance by default
    if (locals.params.sort === 'date') {
      query += ' ORDER BY ts DESC';
    }

    query += ' LIMIT ?,?';
    params.push(locals.params.skip);
    params.push(locals.params.limit);

    let results = yield N.search.execute([
      [ query, params ],
      "SHOW META LIKE 'total_found'"
    ]);

    let posts = _.keyBy(
      yield N.models.forum.Post.find()
                .where('_id').in(_.map(results[0], 'object_id'))
                .lean(true),
      '_id'
    );

    // copy posts preserving order
    locals.sandbox.posts = results[0].map(result => posts[result.object_id]).filter(Boolean);

    locals.sandbox.topics = yield N.models.forum.Topic.find()
                                      .where('_id')
                                      .in(_.uniq(locals.sandbox.posts.map(post => String(post.topic))))
                                      .lean(true);

    locals.sandbox.sections = yield N.models.forum.Section.find()
                                        .where('_id')
                                        .in(_.uniq(locals.sandbox.topics.map(topic => String(topic.section))))
                                        .lean(true);

    locals.count = Number(results[1][0].Value);
  });

  // Check permissions for each post
  //
  N.wire.on(apiPath, function* check_permissions(locals) {
    let topics_by_id   = _.keyBy(locals.sandbox.topics, '_id');
    let sections_by_id = _.keyBy(locals.sandbox.sections, '_id');

    let topics_used   = {};
    let sections_used = {};

    locals.sandbox.posts = (yield Promise.map(locals.sandbox.posts, Promise.coroutine(function* (post) {
      let topic = topics_by_id[post.topic];
      if (!topic) return;

      let section = sections_by_id[topic.section];
      if (!section) return;

      topics_used[topic._id] = topic;
      sections_used[section._id] = section;

      let access_env = { params: {
        topic,
        posts: post,
        user_info: locals.params.user_info
      } };

      yield N.wire.emit('internal:forum.access.post', access_env);

      return access_env.data.access_read ? post : null;
    }))).filter(Boolean);

    locals.sandbox.topics   = _.values(topics_used);
    locals.sandbox.sections = _.values(sections_used);
  });

  // Sanitize results
  //
  N.wire.on(apiPath, function* sanitize(locals) {
    locals.sandbox.posts    = yield sanitize_post(N, locals.sandbox.posts, locals.params.user_info);
    locals.sandbox.topics   = yield sanitize_topic(N, locals.sandbox.topics, locals.params.user_info);
    locals.sandbox.sections = yield sanitize_section(N, locals.sandbox.sections, locals.params.user_info);
  });

  // Fill results
  //
  N.wire.on(apiPath, function fill_results(locals) {
    locals.results = [];

    let topics_by_id = _.keyBy(locals.sandbox.topics, '_id');
    let sections_by_id = _.keyBy(locals.sandbox.sections, '_id');

    locals.sandbox.posts.forEach(post => {
      let topic = topics_by_id[post.topic];
      if (!topic) return;

      let section = sections_by_id[topic.section];
      if (!section) return;

      locals.results.push({ post, topic, section });
    });
  });

  // Fill users
  //
  N.wire.on(apiPath, function fill_users(locals) {
    let users = {};

    locals.results.forEach(result => {
      let post = result.post;

      if (post.user) users[post.user] = true;
      if (post.to_user) users[post.to_user] = true;
      if (post.del_by) users[post.del_by] = true;
      if (post.import_users) post.import_users.forEach(id => { users[id] = true; });
    });

    locals.users = Object.keys(users);
  });

  // Generate snippets for each post
  //
  N.wire.on(apiPath, function* generate_snippets(locals) {
    if (!locals.results.length) return;

    let htmls = locals.results.map(result => result.post.html);

    let query = `
      CALL SNIPPETS(
        (?${',?'.repeat(htmls.length - 1)}),
        'forum_posts',
        ?,
        '' AS before_match,
        '' AS after_match,
        'retain' AS html_strip_mode,
        1 AS query_mode,
        0 AS limit
      )`.replace(/\n\s+/mg, '');

    let args = htmls.concat([ sphinx_escape(locals.params.query) ]);

    let snippets = yield N.search.execute(query, args);

    locals.results.forEach((result, i) => {
      result.post.html = snippets[i].snippet;
    });
  });
};
<|endoftext|>


<commit_before>/**
 * DEVELOPMENT WEBPACK CONFIGURATION
 */

const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');
const logger = require('../../server/logger');
const cheerio = require('cheerio');
const pkg = require(path.resolve(process.cwd(), 'package.json'));
const dllPlugin = pkg.dllPlugin;
const CopyWebpackPlugin = require('copy-webpack-plugin');

const plugins = [
  new webpack.HotModuleReplacementPlugin(), // Tell webpack we want hot reloading
  new webpack.NoErrorsPlugin(),
  new HtmlWebpackPlugin({
    inject: true, // Inject all files that are generated by webpack, e.g. bundle.js
    templateContent: templateContent(), // eslint-disable-line no-use-before-define
  }),
  new CopyWebpackPlugin([{ from: 'static' }]),
  new CircularDependencyPlugin({
    exclude: /a\.js|node_modules/, // exclude node_modules
    failOnError: false, // show a warning when there is a circular dependency
  }),
];

module.exports = require('./webpack.base.babel')({
  // Add hot reloading in development
  entry: [
    'eventsource-polyfill', // Necessary for hot reloading with IE
    'webpack-hot-middleware/client?reload=true',
    path.join(process.cwd(), 'app/app.js'), // Start with js/app.js
  ],

  // Don't use hashes in dev mode for better performance
  output: {
    filename: '[name].js',
    chunkFilename: '[name].chunk.js',
  },

  // Add development plugins
  plugins: dependencyHandlers().concat(plugins), // eslint-disable-line no-use-before-define

  // Tell babel that we want to hot-reload
  babelQuery: {
    // require.resolve solves the issue of relative presets when dealing with
    // locally linked packages. This is an issue with babel and webpack.
    // See https://github.com/babel/babel-loader/issues/149 and
    // https://github.com/webpack/webpack/issues/1866
    presets: ['babel-preset-react-hmre'].map(require.resolve),
  },

  // Emit a source map for easier debugging
  devtool: 'cheap-module-eval-source-map',

  performance: {
    hints: false,
  },
});

/**
 * Select which plugins to use to optimize the bundle's handling of
 * third party dependencies.
 *
 * If there is a dllPlugin key on the project's package.json, the
 * Webpack DLL Plugin will be used.  Otherwise the CommonsChunkPlugin
 * will be used.
 *
 */
function dependencyHandlers() {
  // Don't do anything during the DLL Build step
  if (process.env.BUILDING_DLL) { return []; }

  // If the package.json does not have a dllPlugin property, use the CommonsChunkPlugin
  if (!dllPlugin) {
    return [
      new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor',
        children: true,
        minChunks: 2,
        async: true,
      }),
    ];
  }

  const dllPath = path.resolve(process.cwd(), dllPlugin.path || 'node_modules/react-boilerplate-dlls');

  /**
   * If DLLs aren't explicitly defined, we assume all production dependencies listed in package.json
   * Reminder: You need to exclude any server side dependencies by listing them in dllConfig.exclude
   */
  if (!dllPlugin.dlls) {
    const manifestPath = path.resolve(dllPath, 'reactBoilerplateDeps.json');

    if (!fs.existsSync(manifestPath)) {
      logger.error('The DLL manifest is missing. Please run `npm run build:dll`');
      process.exit(0);
    }

    return [
      new webpack.DllReferencePlugin({
        context: process.cwd(),
        manifest: require(manifestPath), // eslint-disable-line global-require
      }),
    ];
  }

  // If DLLs are explicitly defined, we automatically create a DLLReferencePlugin for each of them.
  const dllManifests = Object.keys(dllPlugin.dlls).map((name) => path.join(dllPath, `/${name}.json`));

  return dllManifests.map((manifestPath) => {
    if (!fs.existsSync(path)) {
      if (!fs.existsSync(manifestPath)) {
        logger.error(`The following Webpack DLL manifest is missing: ${path.basename(manifestPath)}`);
        logger.error(`Expected to find it in ${dllPath}`);
        logger.error('Please run: npm run build:dll');

        process.exit(0);
      }
    }

    return new webpack.DllReferencePlugin({
      context: process.cwd(),
      manifest: require(manifestPath), // eslint-disable-line global-require
    });
  });
}

/**
 * We dynamically generate the HTML content in development so that the different
 * DLL Javascript files are loaded in script tags and available to our application.
 */
function templateContent() {
  const html = fs.readFileSync(
    path.resolve(process.cwd(), 'app/index.html')
  ).toString();

  if (!dllPlugin) { return html; }

  const doc = cheerio(html);
  const body = doc.find('body');
  const dllNames = !dllPlugin.dlls ? ['reactBoilerplateDeps'] : Object.keys(dllPlugin.dlls);

  dllNames.forEach((dllName) => body.append(`<script data-dll='true' src='/${dllName}.dll.js'></script>`));

  return doc.toString();
}
<commit_msg>Fixed source map for dev mode<commit_after>/**
 * DEVELOPMENT WEBPACK CONFIGURATION
 */

const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');
const logger = require('../../server/logger');
const cheerio = require('cheerio');
const pkg = require(path.resolve(process.cwd(), 'package.json'));
const dllPlugin = pkg.dllPlugin;
const CopyWebpackPlugin = require('copy-webpack-plugin');

const plugins = [
  new webpack.HotModuleReplacementPlugin(), // Tell webpack we want hot reloading
  new webpack.NoErrorsPlugin(),
  new HtmlWebpackPlugin({
    inject: true, // Inject all files that are generated by webpack, e.g. bundle.js
    templateContent: templateContent(), // eslint-disable-line no-use-before-define
  }),
  new CopyWebpackPlugin([{ from: 'static' }]),
  new CircularDependencyPlugin({
    exclude: /a\.js|node_modules/, // exclude node_modules
    failOnError: false, // show a warning when there is a circular dependency
  }),
];

module.exports = require('./webpack.base.babel')({
  // Add hot reloading in development
  entry: [
    'eventsource-polyfill', // Necessary for hot reloading with IE
    'webpack-hot-middleware/client?reload=true',
    path.join(process.cwd(), 'app/app.js'), // Start with js/app.js
  ],

  // Don't use hashes in dev mode for better performance
  output: {
    filename: '[name].js',
    chunkFilename: '[name].chunk.js',
  },

  // Add development plugins
  plugins: dependencyHandlers().concat(plugins), // eslint-disable-line no-use-before-define

  // Tell babel that we want to hot-reload
  babelQuery: {
    // require.resolve solves the issue of relative presets when dealing with
    // locally linked packages. This is an issue with babel and webpack.
    // See https://github.com/babel/babel-loader/issues/149 and
    // https://github.com/webpack/webpack/issues/1866
    presets: ['babel-preset-react-hmre'].map(require.resolve),
  },

  // Emit a source map for easier debugging
  /* devtool: 'cheap-module-eval-source-map',*/
  devtool: 'inline-source-map',

  performance: {
    hints: false,
  },
});

/**
 * Select which plugins to use to optimize the bundle's handling of
 * third party dependencies.
 *
 * If there is a dllPlugin key on the project's package.json, the
 * Webpack DLL Plugin will be used.  Otherwise the CommonsChunkPlugin
 * will be used.
 *
 */
function dependencyHandlers() {
  // Don't do anything during the DLL Build step
  if (process.env.BUILDING_DLL) { return []; }

  // If the package.json does not have a dllPlugin property, use the CommonsChunkPlugin
  if (!dllPlugin) {
    return [
      new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor',
        children: true,
        minChunks: 2,
        async: true,
      }),
    ];
  }

  const dllPath = path.resolve(process.cwd(), dllPlugin.path || 'node_modules/react-boilerplate-dlls');

  /**
   * If DLLs aren't explicitly defined, we assume all production dependencies listed in package.json
   * Reminder: You need to exclude any server side dependencies by listing them in dllConfig.exclude
   */
  if (!dllPlugin.dlls) {
    const manifestPath = path.resolve(dllPath, 'reactBoilerplateDeps.json');

    if (!fs.existsSync(manifestPath)) {
      logger.error('The DLL manifest is missing. Please run `npm run build:dll`');
      process.exit(0);
    }

    return [
      new webpack.DllReferencePlugin({
        context: process.cwd(),
        manifest: require(manifestPath), // eslint-disable-line global-require
      }),
    ];
  }

  // If DLLs are explicitly defined, we automatically create a DLLReferencePlugin for each of them.
  const dllManifests = Object.keys(dllPlugin.dlls).map((name) => path.join(dllPath, `/${name}.json`));

  return dllManifests.map((manifestPath) => {
    if (!fs.existsSync(path)) {
      if (!fs.existsSync(manifestPath)) {
        logger.error(`The following Webpack DLL manifest is missing: ${path.basename(manifestPath)}`);
        logger.error(`Expected to find it in ${dllPath}`);
        logger.error('Please run: npm run build:dll');

        process.exit(0);
      }
    }

    return new webpack.DllReferencePlugin({
      context: process.cwd(),
      manifest: require(manifestPath), // eslint-disable-line global-require
    });
  });
}

/**
 * We dynamically generate the HTML content in development so that the different
 * DLL Javascript files are loaded in script tags and available to our application.
 */
function templateContent() {
  const html = fs.readFileSync(
    path.resolve(process.cwd(), 'app/index.html')
  ).toString();

  if (!dllPlugin) { return html; }

  const doc = cheerio(html);
  const body = doc.find('body');
  const dllNames = !dllPlugin.dlls ? ['reactBoilerplateDeps'] : Object.keys(dllPlugin.dlls);

  dllNames.forEach((dllName) => body.append(`<script data-dll='true' src='/${dllName}.dll.js'></script>`));

  return doc.toString();
}
<|endoftext|>


<commit_before>var test_string = "Label: Instruction $s1, $s2, $s3\n\
Label:Instruction $s1, $s2, $s3\n\
Instruction $s1, $s2, $s3\n\
Instruction $s1, 16\n\
JAL Lable\n\
J Lable\n\
LW $s1, 16( $sp )\n\
ADDI $s1, $s2, 16\n\
ADD $s1, $s2, $s3 #testing it out\n\
ADD $s1, $s2, $s3 # testing it out\n\
# This is just a comment\n\
Bad code that doesn't work cause it's written in english";
// console.log("Input:");
// console.log(test_string);
var ME = new mips_emulator({debug: true});
// ME.setCode(test_string);

// function isValidLine(string) {
// 	var line = new mips_line(string);
// 	return !line.error;
// }

module("Parsing");

test("General", function() {
	ok(ME.isValidLine("ADD $t0, $t1, $t2"), "ADD should have 3 registers as arguments.");
	ok(!ME.isValidLine("ADD $t0, $t1, 515"), "ADD should not be able to have an immediate as last argument.");
	ok(!ME.isValidLine("ADDI $t0, $t1, $t2"));
	ok(ME.isValidLine("ADDI $t0, $t1, 515"));
	ok(ME.isValidLine("ADDI $t0, $t1, -515"), "Immediates can be negative.");
	ok(ME.isValidLine("ADDI $t0, $t1, +515"), "Immediates can have plus sign.");
	ok(!ME.isValidLine("ADDI $t0, $t1, 1.5"), "Immediates must be integers.");
	// TODO: ADDI $t0, $t1, -  515
	// TODO: ADDI $t0, $t1,  +  515
	ok(!ME.isValidLine("ADD $z0, $t1, $t2"), "z0 is not a valid register.");
	ok(ME.isValidLine("adD $t0, $t1, $t2"), "instruction case doesn't matter.");
	ok(!ME.isValidLine("ADD $T0, $t1, $t2"), "register case DOES matter.");
	ok(!ME.isValidLine("FOO $t0, $t1, $t2"), "foo is not a valid instruction.");

	ok(ME.isValidLine("  "), "We can have whitespace lines.");
	ok(!ME.isValidLine("This is an english statement"), "We cannot have english phrases.");
});

test("Comments", function() {
	ok(ME.isValidLine("ADD $t0, $t1, $t2#comment here"), "we can have attached comments.");
	ok(ME.isValidLine("# Hello there"), "we can have single line comments.");
	ok(ME.isValidLine("mylabel: ADD $t0, $t1, $t2 # comment here"), "we can have labels and comments.");
});

test("Labels", function() {
	ok(ME.isValidLine("loop:"), "we can have single line labels.");
	ok(ME.isValidLine(" loop  :"), "A label can have whitespace between the text and the colon");
	ok(!ME.isValidLine("loop start:"), "A label cannot have more than one word");
	ok(ME.isValidLine("mylabel:ADD $t0, $t1, $t2"), "we can have attached labels.");
});

test("Set/Get Registers", function(){
    ME.setRegister('$t0', 10);
    equal( ME.getRegister('$t0'), 10);
    ME.setRegister('$s0', 10);
    equal(ME.getRegister('$s0'), 10);
    ME.setRegister('$a0', 10);
    equal(ME.getRegister('$a0'), 10);
});

module("Execution", {
	setup: function() {
		// fill up some of the registers with predictable, usable data
		ME.setRegister('$t0', 10);
		ME.setRegister('$t1', 11);
		ME.setRegister('$t2', 12);
		ME.setRegister('$t3', 13);
		ME.setRegister('$t4', 14);
	}
});

test("ADD", function() {
	ME.runLine("ADD $t0, $t1, $t2");
	equal(ME.getRegister('$t0'), 23, "11 + 12 = 23.");
	equal(ME.getRegister('$t1'), 11, "None of the other register's values should change.");
	equal(ME.getRegister('$t2'), 12, "None of the other register's values should change.");
});

test("ADDI", function() {
	ME.runLine("ADDI $t1, $t0, 505");
	equal(ME.getRegister('$t1'), 515, "10 + 505 = 515");
	ME.runLine("ADDI $t0, $t1, 2");
	equal(ME.getRegister('$t0'), 517, "515 + 2 = 517");
});

module("API");

test("OnChange called", function() {
	var onChangeCalled = false;
	ME.onChange('$t0', function() { onChangeCalled = true; });

	ok(!onChangeCalled, "Didn't change anything, so it should still be false.");
	ME.runLine("ADDI $t0, $t1, 2");
	ok(onChangeCalled, "On change should be called when t0 is changed.");

	// reset handler
	ME.onChange('$t0', null);
	onChangeCalled = false;
	ME.runLine("ADDI $t0, $t1, 2");
	ok(!onChangeCalled, "Should have removed the on change handler.");
});

<commit_msg>changed to test the optional $ in gets and sets for registers<commit_after>var test_string = "Label: Instruction $s1, $s2, $s3\n\
Label:Instruction $s1, $s2, $s3\n\
Instruction $s1, $s2, $s3\n\
Instruction $s1, 16\n\
JAL Lable\n\
J Lable\n\
LW $s1, 16( $sp )\n\
ADDI $s1, $s2, 16\n\
ADD $s1, $s2, $s3 #testing it out\n\
ADD $s1, $s2, $s3 # testing it out\n\
# This is just a comment\n\
Bad code that doesn't work cause it's written in english";
// console.log("Input:");
// console.log(test_string);
var ME = new mips_emulator({debug: true});
// ME.setCode(test_string);

// function isValidLine(string) {
// 	var line = new mips_line(string);
// 	return !line.error;
// }

module("Parsing");

test("General", function() {
	ok(ME.isValidLine("ADD $t0, $t1, $t2"), "ADD should have 3 registers as arguments.");
	ok(!ME.isValidLine("ADD $t0, $t1, 515"), "ADD should not be able to have an immediate as last argument.");
	ok(!ME.isValidLine("ADDI $t0, $t1, $t2"));
	ok(ME.isValidLine("ADDI $t0, $t1, 515"));
	ok(ME.isValidLine("ADDI $t0, $t1, -515"), "Immediates can be negative.");
	ok(ME.isValidLine("ADDI $t0, $t1, +515"), "Immediates can have plus sign.");
	ok(!ME.isValidLine("ADDI $t0, $t1, 1.5"), "Immediates must be integers.");
	// TODO: ADDI $t0, $t1, -  515
	// TODO: ADDI $t0, $t1,  +  515
	ok(!ME.isValidLine("ADD $z0, $t1, $t2"), "z0 is not a valid register.");
	ok(ME.isValidLine("adD $t0, $t1, $t2"), "instruction case doesn't matter.");
	ok(!ME.isValidLine("ADD $T0, $t1, $t2"), "register case DOES matter.");
	ok(!ME.isValidLine("FOO $t0, $t1, $t2"), "foo is not a valid instruction.");

	ok(ME.isValidLine("  "), "We can have whitespace lines.");
	ok(!ME.isValidLine("This is an english statement"), "We cannot have english phrases.");
});

test("Comments", function() {
	ok(ME.isValidLine("ADD $t0, $t1, $t2#comment here"), "we can have attached comments.");
	ok(ME.isValidLine("# Hello there"), "we can have single line comments.");
	ok(ME.isValidLine("mylabel: ADD $t0, $t1, $t2 # comment here"), "we can have labels and comments.");
});

test("Labels", function() {
	ok(ME.isValidLine("loop:"), "we can have single line labels.");
	ok(ME.isValidLine(" loop  :"), "A label can have whitespace between the text and the colon");
	ok(!ME.isValidLine("loop start:"), "A label cannot have more than one word");
	ok(ME.isValidLine("mylabel:ADD $t0, $t1, $t2"), "we can have attached labels.");
});

test("Set/Get Registers", function(){
    ME.setRegister('$t0', 10);
    equal( ME.getRegister('$t0'), 10);
    ME.setRegister('$s0', 10);
    equal(ME.getRegister('$s0'), 10);
    ME.setRegister('$a0', 10);
    equal(ME.getRegister('$a0'), 10);
});

module("Execution", {
	setup: function() {
		// fill up some of the registers with predictable, usable data
		ME.setRegister('t0', 10);
		ME.setRegister('t1', 11);
		ME.setRegister('$t2', 12);
		ME.setRegister('$t3', 13);
		ME.setRegister('$t4', 14);
	}
});

test("ADD", function() {
	ME.runLine("ADD $t0, $t1, $t2");
	equal(ME.getRegister('$t0'), 23, "11 + 12 = 23.");
	equal(ME.getRegister('$t1'), 11, "None of the other register's values should change.");
	equal(ME.getRegister('$t2'), 12, "None of the other register's values should change.");
});

test("ADDI", function() {
	ME.runLine("ADDI $t1, $t0, 505");
	equal(ME.getRegister('$t1'), 515, "10 + 505 = 515");
	ME.runLine("ADDI $t0, $t1, 2");
	equal(ME.getRegister('$t0'), 517, "515 + 2 = 517");
});

module("API");

test("OnChange called", function() {
	var onChangeCalled = false;
	ME.onChange('$t0', function() { onChangeCalled = true; });

	ok(!onChangeCalled, "Didn't change anything, so it should still be false.");
	ME.runLine("ADDI $t0, $t1, 2");
	ok(onChangeCalled, "On change should be called when t0 is changed.");

	// reset handler
	ME.onChange('$t0', null);
	onChangeCalled = false;
	ME.runLine("ADDI $t0, $t1, 2");
	ok(!onChangeCalled, "Should have removed the on change handler.");
});

<|endoftext|>


<commit_before>// Require the nodejs file system library
var fs = require('fs');
var path = require('path');
var math = require('mathjs'); //TODO: Install
var spherePath = path.resolve('public/json/spheres');
var mapPath = path.resolve('public/json/maps/map_spheres_44c2e9bdcaf4c29b.json');

var configPath = path.resolve('javascripts/preparation/config.json');
var fileReadOptions = {
    'encoding': 'utf-8'
};
var config;

exports.prepair = function() {
// Readdir reads a path and gives an array of filenames
// to the callback handleFiles.
    createConfig();
    var configJson = fs.readFileSync(configPath, fileReadOptions);
    config = JSON.parse(configJson);

    if(config.activate_preparation) {
        console.log('Prepair ...');
        fs.readdir(spherePath, handleSphereFiles);
    }
};

var handleSphereFiles = function(err, files) {
    if (err) throw err;
    var i;
    var jsonFilePattern = /\.[json]+$/i;
    var fileName;
    var filePath;
    // Tells fs to read an utf-8 file.
    var mapData = {};

    for (i = 0; i < files.length; ++i) {
        fileName = files[i];
        // Check if the file has a .json extension
        if (fileName.match(jsonFilePattern)) {
            filePath = spherePath + '/' + fileName;
            // Open the file as utf-8 and call handleJsonFile back
            // when done reading.
            var data = fs.readFileSync(filePath, fileReadOptions);

            var sphere = JSON.parse(data);

            if(config.generateMapJson) {
                checkMapJson(sphere, mapData);
            }
            if(config.generateCubemap) {
                checkCubemaps(sphere);
            }
            if(config.generateSpherePreview) {
                checkIcons(sphere);
            }
        }
    }

    //writes the generated newSphere object to the map_spheres....json file
    fs.writeFileSync(mapPath, JSON.stringify(mapData));

    console.log("Preparation done!");
};

var createConfig = function() {
    try {
        fs.lstatSync(configPath);
    } catch(e){
        console.log('No config found at \'' + configPath + '\'. Generating config ...');
        var config = {};
        config.activate_preparation = true;
        config.generateMapJson = true;
        config.generateCubemap = false;
        config.generateSpherePreview = false;

        fs.writeFileSync(configPath, JSON.stringify(config));
    }
};

var checkMapJson = function(sphere, mapData){
    var generateMapJson = require(path.resolve('javascripts/preparation/generatemapjson.js'));
    generateMapJson.generate(sphere, mapData);
};

var checkCubemaps = function(sphere) {
    var erect2cubemap = require(path.resolve('javascripts/preparation/generatecubemap.js'));
    for(var key in sphere.images.cubemaps) {
        var value = sphere.images.cubemaps[key];
        var cubemapPath = path.resolve('public'+value.path);
        try {
            fs.lstatSync(cubemapPath);
        } catch(e){
            var inputFile = path.resolve('public'+sphere.images.erect);
            erect2cubemap.generate(inputFile,cubemapPath,value.resolution);
        }
    }
};

var checkIcons = function(sphere) {
    var generateSpherePreview = require(path.resolve('javascripts/preparation/generatespherepreview.js'));
    for(var key in sphere.images.icons) {
        var value = sphere.images.icons[key];
        var iconPath = path.resolve('public'+value.path);
        try {
            fs.lstatSync(iconPath);
        } catch(e){
            var initial = 0;
            if(sphere.initialView.long !== undefined) {
                initial = -math.eval(sphere.initialView.long);
            }
            var inputFile = path.resolve('public'+sphere.images.erect);
            generateSpherePreview.generate(inputFile,iconPath,initial);
        }
    }

};<commit_msg>generate formated json<commit_after>// Require the nodejs file system library
var fs = require('fs');
var path = require('path');
var math = require('mathjs'); //TODO: Install
var spherePath = path.resolve('public/json/spheres');
var mapPath = path.resolve('public/json/maps/map_spheres_44c2e9bdcaf4c29b.json');

var configPath = path.resolve('javascripts/preparation/config.json');
var fileReadOptions = {
    'encoding': 'utf-8'
};
var config;

exports.prepair = function() {
// Readdir reads a path and gives an array of filenames
// to the callback handleFiles.
    createConfig();
    var configJson = fs.readFileSync(configPath, fileReadOptions);
    config = JSON.parse(configJson);

    if(config.activate_preparation) {
        console.log('Prepair ...');
        fs.readdir(spherePath, handleSphereFiles);
    }
};

var handleSphereFiles = function(err, files) {
    if (err) throw err;
    var i;
    var jsonFilePattern = /\.[json]+$/i;
    var fileName;
    var filePath;
    // Tells fs to read an utf-8 file.
    var mapData = {};

    for (i = 0; i < files.length; ++i) {
        fileName = files[i];
        // Check if the file has a .json extension
        if (fileName.match(jsonFilePattern)) {
            filePath = spherePath + '/' + fileName;
            // Open the file as utf-8 and call handleJsonFile back
            // when done reading.
            var data = fs.readFileSync(filePath, fileReadOptions);

            var sphere = JSON.parse(data);

            if(config.generateMapJson) {
                checkMapJson(sphere, mapData);
            }
            if(config.generateCubemap) {
                checkCubemaps(sphere);
            }
            if(config.generateSpherePreview) {
                checkIcons(sphere);
            }
        }
    }

    //writes the generated newSphere object to the map_spheres....json file
    fs.writeFileSync(mapPath, JSON.stringify(mapData, null,4));

    console.log("Preparation done!");
};

var createConfig = function() {
    try {
        fs.lstatSync(configPath);
    } catch(e){
        console.log('No config found at \'' + configPath + '\'. Generating config ...');
        var config = {};
        config.activate_preparation = true;
        config.generateMapJson = true;
        config.generateCubemap = false;
        config.generateSpherePreview = false;

        fs.writeFileSync(configPath, JSON.stringify(config,null,4));
    }
};

var checkMapJson = function(sphere, mapData){
    var generateMapJson = require(path.resolve('javascripts/preparation/generatemapjson.js'));
    generateMapJson.generate(sphere, mapData);
};

var checkCubemaps = function(sphere) {
    var erect2cubemap = require(path.resolve('javascripts/preparation/generatecubemap.js'));
    for(var key in sphere.images.cubemaps) {
        var value = sphere.images.cubemaps[key];
        var cubemapPath = path.resolve('public'+value.path);
        try {
            fs.lstatSync(cubemapPath);
        } catch(e){
            var inputFile = path.resolve('public'+sphere.images.erect);
            erect2cubemap.generate(inputFile,cubemapPath,value.resolution);
        }
    }
};

var checkIcons = function(sphere) {
    var generateSpherePreview = require(path.resolve('javascripts/preparation/generatespherepreview.js'));
    for(var key in sphere.images.icons) {
        var value = sphere.images.icons[key];
        var iconPath = path.resolve('public'+value.path);
        try {
            fs.lstatSync(iconPath);
        } catch(e){
            var initial = 0;
            if(sphere.initialView.long !== undefined) {
                initial = -math.eval(sphere.initialView.long);
            }
            var inputFile = path.resolve('public'+sphere.images.erect);
            generateSpherePreview.generate(inputFile,iconPath,initial);
        }
    }

};<|endoftext|>


<commit_before>// Copyright 2002-2015, University of Colorado Boulder

/**
 * This grunt task generates a markdown form of sherpa/third-party-licenses.json.
 *
 * @author Aaron Davis
 */

// modules
var child_process = require( 'child_process' );
var assert = require( 'assert' );

// constants
var OUTPUT_FILE = 'info.md';
var SHERPA = '../sherpa';

/**
 * @param grunt the grunt instance
 */
module.exports = function( grunt ) {
  'use strict';

  var json = grunt.file.readJSON( SHERPA + '/third-party-licenses.json' );
  var i;

  var columnHeaders = [ 'Library', 'Website', 'License', 'License URL (if different than project website)', 'Text', 'How is it used in sims?' ];
  var headerDelimiters = [];
  for ( i = 0; i < columnHeaders.length; i++ ) {
    headerDelimiters.push( '------' );
  }
  var output = columnHeaders.join( '|' ) + '\n' + headerDelimiters.join( '|' );

  var rows = [];

  for ( var library in json ) {
    var text = json[ library ].text.join( '
' );
    var license = json[ library ].license;
    var projectURL = json[ library ].projectURL;
    var notes = json[ library ].notes;
    var licenseURL = json[ library ].licenseURL;
    rows.push( [ library, projectURL ? projectURL : '', license, licenseURL ? licenseURL : '', text, notes ] );
  }

  for ( i = 0; i < rows.length; i++ ) {
    var row = rows[ i ];
    output += '\n' + row.join( '|' );
  }

  grunt.log.writeln( 'writing file ' + OUTPUT_FILE );
  grunt.file.write( SHERPA + '/' + OUTPUT_FILE, output );

  var done = grunt.task.current.async();

  // exec a command in the sherpa directory
  var exec = function( command, callback ) {
    child_process.exec( command, { cwd: SHERPA }, function( err, stdout, stderr ) {
      grunt.log.writeln( stdout );
      grunt.log.writeln( stderr );
      assert( !err, 'assertion error running ' + command );
      callback();
    } );
  };

  exec( 'git add ' + OUTPUT_FILE, function() {
    exec( 'git commit --message "updated info.md"', function() {
      exec( 'git push', function() {
        done();
      } );
    } );
  } );

};
<commit_msg>fix commit message, see https://github.com/phetsims/sherpa/issues/22<commit_after>// Copyright 2002-2015, University of Colorado Boulder

/**
 * This grunt task generates a markdown form of sherpa/third-party-licenses.json.
 *
 * @author Aaron Davis
 */

// modules
var child_process = require( 'child_process' );
var assert = require( 'assert' );

// constants
var OUTPUT_FILE = 'info.md';
var SHERPA = '../sherpa';

/**
 * @param grunt the grunt instance
 */
module.exports = function( grunt ) {
  'use strict';

  var json = grunt.file.readJSON( SHERPA + '/third-party-licenses.json' );
  var i;

  var columnHeaders = [ 'Library', 'Website', 'License', 'License URL (if different than project website)', 'Text', 'How is it used in sims?' ];
  var headerDelimiters = [];
  for ( i = 0; i < columnHeaders.length; i++ ) {
    headerDelimiters.push( '------' );
  }
  var output = columnHeaders.join( '|' ) + '\n' + headerDelimiters.join( '|' );

  var rows = [];

  for ( var library in json ) {
    var text = json[ library ].text.join( '
' );
    var license = json[ library ].license;
    var projectURL = json[ library ].projectURL;
    var notes = json[ library ].notes;
    var licenseURL = json[ library ].licenseURL;
    rows.push( [ library, projectURL ? projectURL : '', license, licenseURL ? licenseURL : '', text, notes ] );
  }

  for ( i = 0; i < rows.length; i++ ) {
    var row = rows[ i ];
    output += '\n' + row.join( '|' );
  }

  grunt.log.writeln( 'writing file ' + OUTPUT_FILE );
  grunt.file.write( SHERPA + '/' + OUTPUT_FILE, output );

  var done = grunt.task.current.async();

  // exec a command in the sherpa directory
  var exec = function( command, callback ) {
    child_process.exec( command, { cwd: SHERPA }, function( err, stdout, stderr ) {
      grunt.log.writeln( stdout );
      grunt.log.writeln( stderr );
      assert( !err, 'assertion error running ' + command );
      callback();
    } );
  };

  exec( 'git add ' + OUTPUT_FILE, function() {
    exec( 'git commit --message "update info.md"', function() {
      exec( 'git push', function() {
        done();
      } );
    } );
  } );

};
<|endoftext|>


<commit_before>define(["handlebars"], function(Handlebars) {
    Handlebars.registerHelper('openingHours', function(string) {
        if(string === "") {
            return ""
        }
        result = TimeDomain.evaluateInTime(string);
        if(result.value === true) {
            return " (open)";
        } else {
            return " (closed)";
        }
    });

    Handlebars.registerHelper('humaniseDistance', function(distance) {
        distance = parseFloat(distance);
        if(distance >= 1.0) {
            return Math.round(distance*10)/10 + " km";
        } else {
            return Math.round(distance*1000) + " m";
        }
    });
});
<commit_msg>Catch possible error evaluating opening hours<commit_after>define(["handlebars", "time_domain"], function(Handlebars, TimeDomain) {
    Handlebars.registerHelper('openingHours', function(string) {
        if(string === "") {
            return "";
        }
        try {
            result = TimeDomain.evaluateInTime(string);
        } catch (err) {
            console.log(err);
            return "";
        }
        if(result.value === true) {
            return " (open)";
        } else {
            return " (closed)";
        }
    });

    Handlebars.registerHelper('humaniseDistance', function(distance) {
        distance = parseFloat(distance);
        if(distance >= 1.0) {
            return Math.round(distance*10)/10 + " km";
        } else {
            return Math.round(distance*1000) + " m";
        }
    });
});
<|endoftext|>


<commit_before>/*jshint -W083 */
define([
  "generated/templates",
  "renderers/componentrenderer",
  "utils/dataformatter",
  "utils/numberformatter",
  "razorcharts/core/chart",
  "utils/tooltip",
  'vendor/lodash'
], function (JST, ComponentRenderer, DataFormatter, NumberFormatter, RazorChart, Tooltip, _) {
  function ChartRenderer() {
    ComponentRenderer.call(this);

    var self = this,
        base = {},
        Public,
        raw = self._raw,
        Protected,
        pro = self.pro,
        _bp = {};

    var chart,
        labels,
        data,
        series,
        displayValues,
        state = {},
        legendBools = {},
        firstDraw = true,
        legendVisible = true,
        firstAnimation = true,
        chartBaseColors = ["#5A9BD4", "#7AC36A", "#F15A60", "#FAA65B", "#9E67AB", "#D77FB4", "#CE7058", "#737373", "#333333"],
        numBaseColors = chartBaseColors.length,
        coreChartType = '',
        tooltip = new Tooltip(),
        axesTooltip = new Tooltip(),
        hasItemClickSubscribed = false;

    for(var i=-1; ++i<numBaseColors;) {
      var color = Raphael.color(chartBaseColors[i]);
      chartBaseColors[9 + i] = Raphael.hsl(color.h, color.s, color.l * 0.8);
      chartBaseColors[18 + i] = Raphael.hsl(color.h, color.s, color.l * 1.2);
    }
    Public = {
      setAnimation: function(b) {
        firstAnimation = b;
        if(pro.chart) {
          // pro.chart.setAnimation(b);
        }
      },
      itemClickSubscribed: function() {
        hasItemClickSubscribed = true;
      },
      setData: function (opts) {
        labels = opts.labels;
        data = opts.data;
        series = opts.series;
        displayValues = opts.displayValues;
      },
      setState: function(_state) {
        state = _state;
      },
      renderCore: function () {
        var tSeries = [], tData = [], tDisplayValues = [], i = 0;
        // Temp hack
        legendVisible = self.props.chart.showLegendFlag;
        self.$core.css({"padding" : "0px 10px"});
        var _series = [];
        if(series[0].displayType === 'pie') {
          for(i=-1; ++i<labels.length;) {
            _series[i] = {
              seriesName: labels[i],
              seriesHiddenFlag: false,
              seriesColor: chartBaseColors[i]
            };
          }
        }

        tooltip.config({
          core: self.$core,
          type: series[0].displayType === 'pie' ? 'value': 'popup',
          popupType: series[0].displayType === 'bar' ? 'left' : 'top'
        });

        axesTooltip.config({
          core: self.$core,
          type: 'value'
        });

        self.$core.html(JST.chart_base({
          displayType: series[0].displayType,
          series: series[0].displayType === 'pie' ? _series : series,
          legendVisible: legendVisible
        }));

        tooltip.renderTo($('body'));
        axesTooltip.renderTo($('body'));

        pro.$chartCore = self.$core.find('.chartCore');
        pro.$legendContainer = self.$core.find('.rfLegendContainer');
        attachLegendEventHandlers();
        for(i=0; i<series.length; i++) {
          if(!series[i].seriesHiddenFlag) {
            series[i].seriesIndex = i;
            tSeries.push(series[i]);
            tData.push(data[i]);
            tDisplayValues.push(displayValues[i]);
          }
        }

        selectAndCreateChart(labels, tData, tSeries, tDisplayValues);
        // pro.chart.renderTo(pro.$chartCore, 0, 0);
        pro.chart.renderTo(pro.$chartCore[0], 600, 600);
        firstDraw = true;
        attachItemEventHandler();
        if(state.isDrillDownable) {
          self.$header.html(JST.bread_crumb({
            drillLabelList: state.drillLabelList,
            startString: self.props.core.breadcrumbStartString
          }));
          self.$header.find('.rfBreadCrumb > ul > li:not(:last-child)').on('click', function() {
            pro.trigger('drillDownListClick', {index: +$(this).data('index')});
          });
          self.$core.find(".rc-plot-item").css({
            "cursor" : "pointer"
          });
        }
      },
      resizeCore: function (width, height) {
        var coreHeight = height;
        if(coreHeight > 0){
          coreHeight = height - ((legendVisible || !self.props.chart.showPieValues) ? pro.$legendContainer.height() : 0);
          // if(firstDraw) {
          //   pro.chart.renderTo(pro.$chartCore[0], width, coreHeight);
          // } else {
            pro.chart.resizeTo(width, coreHeight);
          // }
        }

        if (pro.$chartCore && pro.$chartCore.find('.rc-axis')[1]) {
          var legendLeft = Math.floor(pro.$chartCore.find('.rc-axis')[1].getBBox().width);
          pro.$legendContainer.css({
            "padding-left" : legendLeft - 1
          });
        }
        firstDraw = false;
        if(coreChartType === 'pie') {
          tLegendVisible = !pro.chart.callFunction('hasLabels');
          if(tLegendVisible !== legendVisible) {
            legendVisible = tLegendVisible;
            if(!legendVisible && self.props.chart.showPieValues) {
              pro.$legendContainer.hide();
            } else {
              pro.$legendContainer.show();
            }

            coreHeight = height - ((legendVisible || !self.props.chart.showPieValues) ? pro.$legendContainer.height() : 0);
            // setTimeout(function() {
            //   pro.$chartCore.find('.rc-chart').remove();
            pro.chart.resizeTo(width, coreHeight);
            // }, 300);

          }
        }
      },
      realignData: function (originalLabels, labels, seriesData, displayValues) {
        if (!firstDraw) {
          var realigned = DataFormatter.realignLabels (originalLabels, labels, seriesData, displayValues);
          // pro.chart.updateData(originalLabels, realigned.data, realigned.displayValues);
          pro.chart.updateSeries(seriesData);
        }
      },
      dispose: function () {
        base.dispose();
        // pro.chart.dispose();
        pro.$chartCore = null;
        pro.$legendContainer = null;
        tooltip.dispose();
        axesTooltip.dispose();
      }
    };

    Protected = {
      $chartCore: null,
      $legendContainer: null,
      chart: null,
      chartModal: null
    };

    var attachLegendEventHandlers = function() {
      // Get the seriesVisibleFlag and initialize them to legend bools
      for(var i=-1; ++i<series.length;) {

        legendBools[series[i].key] = series[i].seriesHiddenFlag;
      }
      pro.$legendContainer.find('.rfLegendKey').on('click', function() {
        var key = $(this).data('key');
        if(_.filter(legendBools, function(val) {return !val;}).length <= 1 && !legendBools[key]) {
          return;
        }

        legendBools[key] = !legendBools[key];
        if(legendBools[key]) {
          $(this).addClass('disabled');
        } else {
          $(this).removeClass('disabled');
        }
        pro.trigger('legendClick', {key: key, value: legendBools[key]});
      });
      pro.$legendContainer.find('.rfLegendKey').hover(function () {
        if(series[0].displayType === 'pie') {
          return;
        }
        $(this).addClass("disabled");
      },function () {
        $(this).removeClass("disabled");
      });

      pro.$legendContainer.find(".disabled").hover(function () {
        $(this).removeClass("disabled");
      },function () {
        $(this).addClass("disabled");
      });
    };

    var attachItemEventHandler = function(){
        pro.chart.on('plotItemClick', function(params) {
          self.trigger("plotItemActivate");
          pro.trigger('itemClick', params);
        });

        pro.chart.on('plotItemMouseOver', function(params) {
          pro.trigger("plotItemMouseOver", params);
        });

        pro.chart.on('plotItemMouseOut', function(params) {
          pro.trigger("plotItemMouseOut", params);
        });

        // pro.chart.on('labelActivate', function(params) {
        //   pro.trigger("labelActivate", params);
        // });

        pro.chart.on('plotItemActivate', function(params) {
          pro.trigger("plotItemActivate", params);
        });
    };

    var selectAndCreateChart = function (labels, data, series, displayValues) {
      var _series = [],
          customColors = [],
          dualY = self.props.chart.dualY,
          showLabelFlag = self.props.chart.showLabelFlag;
      coreChartType = series[0].displayType === 'pie' ? 'pie' : series[0].displayType === 'bar' ? 'bar' : 'linear';
      for(var i=-1; ++i<series.length;) {
        if(series) {
          _series[i] = {
            seriesIndex: series[i].seriesIndex,
            displayType: series[i].displayType,
            id: series[i].key,
            data: data[i],
            colors: coreChartType === 'pie' ? chartBaseColors : null,
            color: series[i].seriesColor,
            caption: series[i].seriesName,
            stacked: series[i].seriesStacked,
            yAxis: series[i].yAxis === 'primary' ? 'left' : 'right',
            format: (function(i) {
              return function(item) {
                var numberFormatter = new NumberFormatter();
                numberFormatter.setConfig(self.props.chart.series[series[i].key]);
                return numberFormatter.formatValue(item);
              };
            })(i)
          };
        }
      }

      var yConfig = self.props.chart.yaxis,
          syConfig = self.props.chart.secondaryYAxis,
          seriesConfig = self.props.chart.series[series[0].key];

      var yAxisFormatter = new NumberFormatter(),
          secondaryYAxisFormatter =  new NumberFormatter(),
          seriesFormatter = new NumberFormatter();

      yAxisFormatter.setConfig(NumberFormatter.pickFirstValid([
        yConfig,
        seriesConfig
      ]));
      secondaryYAxisFormatter.setConfig(NumberFormatter.pickFirstValid([
        syConfig,
        seriesConfig
      ]));
      seriesFormatter.setConfig(NumberFormatter.pickFirstValid([
        seriesConfig,
        yConfig
      ]));

      var yAxisFormatFunc = function(item) {
        return yAxisFormatter.formatValue(item);
      };
      var secondaryYFormatFunc= function(item) {
        return secondaryYAxisFormatter.formatValue(item);
      };
      var seriesFormatFunc = function(item) {
        return seriesFormatter.formatValue(item);
      };

      var yAxisConfig = {
        label: self.props.chart.yaxis.axisName,
        axisLine: false,
        axisTick: false,
        format: coreChartType === 'linear' ? yAxisFormatFunc : null
      };
      if(dualY) {
        yAxisConfig = [
          {
            type: 'left',
            label: self.props.chart.yaxis.axisName,
            axisLine: false,
            axisTick: false,
            format: coreChartType === 'linear' ? yAxisFormatFunc : null
          },
          {
            type: 'right',
            label: self.props.chart.secondaryYAxis.axisName,
            axisLine: false,
            axisTick: false,
            format: coreChartType === 'linear' ? secondaryYFormatFunc : null
          }
        ];
      }

      pro.chart = new RazorChart();
      pro.chart.config({
        labels: labels,
        type: coreChartType,
        grid: true,
        animateOnRender: false,
        dualAxis: dualY,
        showPieLabels: self.props.chart.showPieValues,
        plotItemClasses: hasItemClickSubscribed ? 'activate' : '',
        xAxis: {
          axisLine: true,
          axisTick: false,
          format: coreChartType === 'bar' ? formatFunction : null
        },
        yAxis: yAxisConfig,
        tooltip: {
          onShow: function(x, y, data) {
            var seriesIndex = data.seriesIndex[0] - 1;
            var tooltipFormatter = new NumberFormatter();
            tooltipFormatter.setConfig(NumberFormatter.pickFirstValid([
              self.props.chart.series[series[seriesIndex].key],
              yConfig
            ]));
            data.data[0] = tooltipFormatter.formatValue(data.data[0]);
            tooltip.show(x, y, data);
          },
          onHide: function() {
            tooltip.hide();
          }
        },
        axesTooltip: {
          onShow: function(x, y, data) {
            axesTooltip.show(x, y, data);
          },
          onHide: function() {
            axesTooltip.hide();
          }
        },
        series: coreChartType === 'pie' ? _series[0] : _series,
        showLabelFlag: showLabelFlag
      });

    };

    raw._registerClassName("ComponentRenderer");
    raw._registerPublic(base, Public);
    raw._registerProtected(_bp, Protected);
  }

  return ChartRenderer;
});
<commit_msg>Fix regression<commit_after>/*jshint -W083 */
define([
  "generated/templates",
  "renderers/componentrenderer",
  "utils/dataformatter",
  "utils/numberformatter",
  "razorcharts/core/chart",
  "utils/tooltip",
  'vendor/lodash'
], function (JST, ComponentRenderer, DataFormatter, NumberFormatter, RazorChart, Tooltip, _) {
  function ChartRenderer() {
    ComponentRenderer.call(this);

    var self = this,
        base = {},
        Public,
        raw = self._raw,
        Protected,
        pro = self.pro,
        _bp = {};

    var chart,
        labels,
        data,
        series,
        displayValues,
        state = {},
        legendBools = {},
        firstDraw = true,
        legendVisible = true,
        firstAnimation = true,
        chartBaseColors = ["#5A9BD4", "#7AC36A", "#F15A60", "#FAA65B", "#9E67AB", "#D77FB4", "#CE7058", "#737373", "#333333"],
        numBaseColors = chartBaseColors.length,
        coreChartType = '',
        tooltip = new Tooltip(),
        axesTooltip = new Tooltip(),
        hasItemClickSubscribed = false;

    for(var i=-1; ++i<numBaseColors;) {
      var color = Raphael.color(chartBaseColors[i]);
      chartBaseColors[9 + i] = Raphael.hsl(color.h, color.s, color.l * 0.8);
      chartBaseColors[18 + i] = Raphael.hsl(color.h, color.s, color.l * 1.2);
    }
    Public = {
      setAnimation: function(b) {
        firstAnimation = b;
        if(pro.chart) {
          // pro.chart.setAnimation(b);
        }
      },
      itemClickSubscribed: function() {
        hasItemClickSubscribed = true;
      },
      setData: function (opts) {
        labels = opts.labels;
        data = opts.data;
        series = opts.series;
        displayValues = opts.displayValues;
      },
      setState: function(_state) {
        state = _state;
      },
      renderCore: function () {
        var tSeries = [], tData = [], tDisplayValues = [], i = 0;
        // Temp hack
        legendVisible = self.props.chart.showLegendFlag;
        self.$core.css({"padding" : "0px 10px"});
        var _series = [];
        if(series[0].displayType === 'pie') {
          for(i=-1; ++i<labels.length;) {
            _series[i] = {
              seriesName: labels[i],
              seriesHiddenFlag: false,
              seriesColor: chartBaseColors[i]
            };
          }
        }

        tooltip.config({
          core: self.$core,
          type: series[0].displayType === 'pie' ? 'value': 'popup',
          popupType: series[0].displayType === 'bar' ? 'left' : 'top'
        });

        axesTooltip.config({
          core: self.$core,
          type: 'value'
        });

        self.$core.html(JST.chart_base({
          displayType: series[0].displayType,
          series: series[0].displayType === 'pie' ? _series : series,
          legendVisible: legendVisible
        }));

        tooltip.renderTo($('body'));
        axesTooltip.renderTo($('body'));

        pro.$chartCore = self.$core.find('.chartCore');
        pro.$legendContainer = self.$core.find('.rfLegendContainer');
        attachLegendEventHandlers();
        for(i=0; i<series.length; i++) {
          if(!series[i].seriesHiddenFlag) {
            series[i].seriesIndex = i;
            tSeries.push(series[i]);
            tData.push(data[i]);
            tDisplayValues.push(displayValues[i]);
          }
        }

        selectAndCreateChart(labels, tData, tSeries, tDisplayValues);
        // pro.chart.renderTo(pro.$chartCore, 0, 0);
        pro.chart.renderTo(pro.$chartCore[0], 600, 600);
        firstDraw = true;
        attachItemEventHandler();
        if(state.isDrillDownable) {
          self.$header.html(JST.bread_crumb({
            drillLabelList: state.drillLabelList,
            startString: self.props.core.breadcrumbStartString
          }));
          self.$header.find('.rfBreadCrumb > ul > li:not(:last-child)').on('click', function() {
            pro.trigger('drillDownListClick', {index: +$(this).data('index')});
          });
          self.$core.find(".rc-plot-item").css({
            "cursor" : "pointer"
          });
        }
      },
      resizeCore: function (width, height) {
        var coreHeight = height;
        if(coreHeight > 0){
          coreHeight = height - ((legendVisible || !self.props.chart.showPieValues) ? pro.$legendContainer.height() : 0);
          // if(firstDraw) {
          //   pro.chart.renderTo(pro.$chartCore[0], width, coreHeight);
          // } else {
            pro.chart.resizeTo(width, coreHeight);
          // }
        }

        if (pro.$chartCore && pro.$chartCore.find('.rc-axis')[1]) {
          var legendLeft = Math.floor(pro.$chartCore.find('.rc-axis')[1].getBBox().width);
          pro.$legendContainer.css({
            "padding-left" : legendLeft - 1
          });
        }
        firstDraw = false;
        if(coreChartType === 'pie') {
          tLegendVisible = !pro.chart.callFunction('hasLabels');
          if(tLegendVisible !== legendVisible) {
            legendVisible = tLegendVisible;
            if(!legendVisible && self.props.chart.showPieValues) {
              pro.$legendContainer.hide();
            } else {
              pro.$legendContainer.show();
            }

            coreHeight = height - ((legendVisible || !self.props.chart.showPieValues) ? pro.$legendContainer.height() : 0);
            // setTimeout(function() {
            //   pro.$chartCore.find('.rc-chart').remove();
            pro.chart.resizeTo(width, coreHeight);
            // }, 300);

          }
        }
      },
      realignData: function (originalLabels, labels, seriesData, displayValues) {
        if (!firstDraw) {
          var realigned = DataFormatter.realignLabels (originalLabels, labels, seriesData, displayValues);
          // pro.chart.updateData(originalLabels, realigned.data, realigned.displayValues);
          pro.chart.updateSeries(seriesData);
        }
      },
      dispose: function () {
        base.dispose();
        // pro.chart.dispose();
        pro.$chartCore = null;
        pro.$legendContainer = null;
        tooltip.dispose();
        axesTooltip.dispose();
      }
    };

    Protected = {
      $chartCore: null,
      $legendContainer: null,
      chart: null,
      chartModal: null
    };

    var attachLegendEventHandlers = function() {
      // Get the seriesVisibleFlag and initialize them to legend bools
      for(var i=-1; ++i<series.length;) {

        legendBools[series[i].key] = series[i].seriesHiddenFlag;
      }
      pro.$legendContainer.find('.rfLegendKey').on('click', function() {
        var key = $(this).data('key');
        if(_.filter(legendBools, function(val) {return !val;}).length <= 1 && !legendBools[key]) {
          return;
        }

        legendBools[key] = !legendBools[key];
        if(legendBools[key]) {
          $(this).addClass('disabled');
        } else {
          $(this).removeClass('disabled');
        }
        pro.trigger('legendClick', {key: key, value: legendBools[key]});
      });
      pro.$legendContainer.find('.rfLegendKey').hover(function () {
        if(series[0].displayType === 'pie') {
          return;
        }
        $(this).addClass("disabled");
      },function () {
        $(this).removeClass("disabled");
      });

      pro.$legendContainer.find(".disabled").hover(function () {
        $(this).removeClass("disabled");
      },function () {
        $(this).addClass("disabled");
      });
    };

    var attachItemEventHandler = function(){
        pro.chart.on('plotItemClick', function(params) {
          self.trigger("plotItemActivate");
          pro.trigger('itemClick', params);
        });

        pro.chart.on('plotItemMouseOver', function(params) {
          pro.trigger("plotItemMouseOver", params);
        });

        pro.chart.on('plotItemMouseOut', function(params) {
          pro.trigger("plotItemMouseOut", params);
        });

        // pro.chart.on('labelActivate', function(params) {
        //   pro.trigger("labelActivate", params);
        // });

        pro.chart.on('plotItemActivate', function(params) {
          pro.trigger("plotItemActivate", params);
        });
    };

    var selectAndCreateChart = function (labels, data, series, displayValues) {
      var _series = [],
          customColors = [],
          dualY = self.props.chart.dualY,
          showLabelFlag = self.props.chart.showLabelFlag;
      coreChartType = series[0].displayType === 'pie' ? 'pie' : series[0].displayType === 'bar' ? 'bar' : 'linear';
      for(var i=-1; ++i<series.length;) {
        if(series) {
          _series[i] = {
            seriesIndex: series[i].seriesIndex,
            displayType: series[i].displayType,
            id: series[i].key,
            data: data[i],
            colors: coreChartType === 'pie' ? chartBaseColors : null,
            color: series[i].seriesColor,
            caption: series[i].seriesName,
            stacked: series[i].seriesStacked,
            yAxis: series[i].yAxis === 'primary' ? 'left' : 'right',
            format: (function(i) {
              return function(item) {
                var numberFormatter = new NumberFormatter();
                numberFormatter.setConfig(self.props.chart.series[series[i].key]);
                return numberFormatter.formatValue(item);
              };
            })(i)
          };
        }
      }

      var yConfig = self.props.chart.yaxis,
          syConfig = self.props.chart.secondaryYAxis,
          seriesConfig = self.props.chart.series[series[0].key];

      var yAxisFormatter = new NumberFormatter(),
          secondaryYAxisFormatter =  new NumberFormatter(),
          seriesFormatter = new NumberFormatter();

      yAxisFormatter.setConfig(NumberFormatter.pickFirstValid([
        yConfig,
        seriesConfig
      ]));
      secondaryYAxisFormatter.setConfig(NumberFormatter.pickFirstValid([
        syConfig,
        seriesConfig
      ]));
      seriesFormatter.setConfig(NumberFormatter.pickFirstValid([
        seriesConfig,
        yConfig
      ]));

      var yAxisFormatFunc = function(item) {
        return yAxisFormatter.formatValue(item);
      };
      var secondaryYFormatFunc= function(item) {
        return secondaryYAxisFormatter.formatValue(item);
      };
      var seriesFormatFunc = function(item) {
        return seriesFormatter.formatValue(item);
      };

      var yAxisConfig = {
        label: self.props.chart.yaxis.axisName,
        axisLine: false,
        axisTick: false,
        format: coreChartType === 'linear' ? yAxisFormatFunc : null
      };
      if(dualY) {
        yAxisConfig = [
          {
            type: 'left',
            label: self.props.chart.yaxis.axisName,
            axisLine: false,
            axisTick: false,
            format: coreChartType === 'linear' ? yAxisFormatFunc : null
          },
          {
            type: 'right',
            label: self.props.chart.secondaryYAxis.axisName,
            axisLine: false,
            axisTick: false,
            format: coreChartType === 'linear' ? secondaryYFormatFunc : null
          }
        ];
      }

      pro.chart = new RazorChart();
      pro.chart.config({
        labels: labels,
        type: coreChartType,
        grid: true,
        animateOnRender: false,
        dualAxis: dualY,
        showPieLabels: self.props.chart.showPieValues,
        plotItemClasses: hasItemClickSubscribed ? 'activate' : '',
        xAxis: {
          axisLine: true,
          axisTick: false,
          format: coreChartType === 'bar' ? yAxisFormatFunc : null
        },
        yAxis: yAxisConfig,
        tooltip: {
          onShow: function(x, y, data) {
            var seriesIndex = data.seriesIndex[0] - 1;
            var tooltipFormatter = new NumberFormatter();
            tooltipFormatter.setConfig(NumberFormatter.pickFirstValid([
              self.props.chart.series[series[seriesIndex].key],
              yConfig
            ]));
            data.data[0] = tooltipFormatter.formatValue(data.data[0]);
            tooltip.show(x, y, data);
          },
          onHide: function() {
            tooltip.hide();
          }
        },
        axesTooltip: {
          onShow: function(x, y, data) {
            axesTooltip.show(x, y, data);
          },
          onHide: function() {
            axesTooltip.hide();
          }
        },
        series: coreChartType === 'pie' ? _series[0] : _series,
        showLabelFlag: showLabelFlag
      });

    };

    raw._registerClassName("ComponentRenderer");
    raw._registerPublic(base, Public);
    raw._registerProtected(_bp, Protected);
  }

  return ChartRenderer;
});
<|endoftext|>


<commit_before>tworpusApp
    // Route definition
    .config(['$routeProvider',
        function ($routeProvider) {
            $routeProvider.
                when('/createcorpus', {
                    templateUrl: '/static/views/create_corpus_content.html',
                    controller: 'CreateCorpusController'
                }).
                when('/corpora', {
                    templateUrl: '/static/views/corpora.html',
                    controller: 'CorporaController'
                }).
                when('/settings', {
                    templateUrl: '/static/views/settings.html',
                    controller: 'SettingsController'
                }).
                otherwise({
                    redirectTo: '/createcorpus'
                });
        }
    ])

    .controller('CreateCorpusController', ["$scope", "$rootScope", "$http", "urls", "corpusCreationService", "notify",
        function ($scope, $rootScope, $http, urls, corpusCreationService, notify) {

            $scope.corpus = {};

            var formValues = {} || JSON.parse(localStorage.getItem('formValues'));

            if (!formValues.endDate) {
                formValues.endDate = moment().add('days', 1).toDate();
            }
            if (!formValues.startDate) {
                formValues.startDate = moment().subtract('days', 10).toDate();
            }

            $scope.corpus.endDate = moment(formValues.endDate).toDate();
            $scope.corpus.startDate = moment(formValues.startDate).toDate();

            $scope.corpus.language = formValues.language;

            $('#input_slider_num_tweets').attr('data-slider-value', formValues.numTweets);
            $scope.corpus.numTweets = formValues.numTweets;

             $('#input_slider_min_chars').attr('data-slider-value', formValues.numMinWords);
            $scope.corpus.numMinWords = formValues.numMinWords;

            $('#input_slider_min_words').attr('data-slider-value', formValues.numMinWords);
            $scope.corpus.numMinChars = formValues.numMinChars;

            $scope.corpus.title = formValues.title;

            $scope.languages = [
                {name: "German", value: "de"},
                {name: "English", value: "en"},
                {name: "Spanish", value: "es"},
                {name: "French", value: "fr"},
                {name: "Italian", value: "it"},
                {name: "Dutch", value: "nl"},
                {name: "Portuguese", value: "pt"},
                {name: "Turkish", value: "tr"}
            ];

            $scope.startCreateCorpus = function () {
                // Starts corpus creation through corpusCreationService if form is valid
                var isValid = $("form").get(0).checkValidity();
                if (isValid === true) {
                    corpusCreationService.startCorpusCreation($scope.corpus)
                        .success(function (data, status) {
                            switch (status) {
                                case 206:
                                    notify("Corpus <b>" + $scope.corpus.title + " </b>is being created, " +
                                        "but there are not sufficient tweets available.", "info");
                                    break;
                                default:
                                    notify("Corpus <b>" + $scope.corpus.title + " </b>is being created.");
                                    break;
                            }
                            $rootScope.$emit("corpus:create:start");
                        }).error(function (data, status) {
                            switch(status) {
                                case 444:
                                    notify("No tweets found to fetch. Try to be less specific.", "error");
                                    break;
                                default:
                                    notify("Failed to fetch tweets.", "error");
                                    break;
                            }

                        });
                }
            };

        var saveIntoLocalStorage = function() {
            localStorage.setItem('formValues', JSON.stringify({
                endDate: $scope.corpus.endDate || null,
                startDate: $scope.corpus.startDate || null,
                language: $scope.corpus.language || "",
                numMinChars: $scope.corpus.numMinChars || 0,
                numMinWords: $scope.corpus.numMinWords || 0,
                numTweets: $scope.corpus.numTweets || 20,
                title: $scope.corpus.title || ""
            }));
        };

        $scope.$on("$destroy", function () {
            saveIntoLocalStorage();
        });

        window.onbeforeunload = function () {
            saveIntoLocalStorage();
        };
    }])

    .directive('ngBootstrapSlider', function () {
        // uses http://www.eyecon.ro/bootstrap-slider/
        return {
            restrict: 'A',
            scope: {
                ngModel: "="
            },
            require: 'ngModel',

            link: function ($scope, elm, attrs) {
                $scope.ngModel = parseInt(attrs.sliderValue) || 0;
                var slider = $(elm).slider({value: 0});
                $scope.slider = slider;

                slider.on('slide', function (e) {
                    var val = $(this).val();
                    $scope.ngModel = parseInt(val);
                    $scope.$apply();
                });
            },

            controller: function ($scope) {
                $scope.$watch('ngModel', function (newValue, oldValue) {
                    $scope.slider.slider('setValue', newValue);
                })
            }
        }
    })

    .directive('twDate', function () {
        return {
            restrict: 'A',
            scope: {
                ngModel: "=",
                minDate: "=",
                maxDate: "="
            },
            require: 'ngModel',

            link: function ($scope, elm, attrs) {
                var picker = new Pikaday({
                    field: elm[0],
                    bound: false,
                    onSelect: function (date) {
                        $scope.ngModel = date || new Date();
                        $scope.$apply();
                    }
                });

                $scope.$watch('ngModel', function (newValue, oldValue) {
                    picker.setDate(newValue, true);
                });

                $scope.$watch("minDate", function(newValue) {
                    picker.setMinDate(newValue);
                    picker.setDate($scope.ngModel, true); // need setDate to update Datepicker
                });

                $scope.$watch("maxDate", function(newValue) {
                    picker.setMaxDate(newValue);
                    picker.setDate($scope.ngModel, true); // need setDate to update Datepicker
                });
            }
        }
    })

    .controller('twDateRangeController', ["$scope",
        function ($scope) {
            $scope.$watch('corpus.startDate', function (newValue, oldValue) {
                if (!$scope.corpus) return;
                if (newValue > $scope.corpus.endDate) $scope.corpus.startDate = $scope.corpus.endDate;

                $scope.corpus.endDate.minDate = newValue;
            });

            $scope.$watch('corpus.endDate', function (newValue, oldValue) {
                if (!$scope.corpus) return;
                if (newValue < $scope.corpus.startDate) $scope.corpus.endDate = $scope.corpus.startDate;

                $scope.corpus.startDate.maxDate = newValue;
            });
        }]);<commit_msg>form values saved in local storage<commit_after>tworpusApp
    // Route definition
    .config(['$routeProvider',
        function ($routeProvider) {
            $routeProvider.
                when('/createcorpus', {
                    templateUrl: '/static/views/create_corpus_content.html',
                    controller: 'CreateCorpusController'
                }).
                when('/corpora', {
                    templateUrl: '/static/views/corpora.html',
                    controller: 'CorporaController'
                }).
                when('/settings', {
                    templateUrl: '/static/views/settings.html',
                    controller: 'SettingsController'
                }).
                otherwise({
                    redirectTo: '/createcorpus'
                });
        }
    ])

    .controller('CreateCorpusController', ["$scope", "$rootScope", "$http", "urls", "corpusCreationService", "notify",
        function ($scope, $rootScope, $http, urls, corpusCreationService, notify) {

            $scope.corpus = {};

            var formValues = JSON.parse(localStorage.getItem('formValues'));
            if (!formValues) formValues = {};
            if (!formValues.endDate)  formValues.endDate = moment().add('days', 1).toDate();
            if (!formValues.startDate) formValues.startDate = moment().subtract('days', 10).toDate();
            if (!formValues.numTweets) formValues.numTweets = 20;
            if (!formValues.numMinWords) formValues.numMinWords = 0;
            if (!formValues.numMinChars) formValues.numMinChars = 0;
            if (!formValues.language) formValues.language = "";
            if (!formValues.title) formValues.title = "";

            $scope.corpus.endDate = moment(formValues.endDate).toDate();
            $scope.corpus.startDate = moment(formValues.startDate).toDate();

            $scope.corpus.language = formValues.language;

            $('#input_slider_num_tweets').attr('data-slider-value', formValues.numTweets);
            $scope.corpus.numTweets = formValues.numTweets;

             $('#input_slider_min_chars').attr('data-slider-value', formValues.numMinWords);
            $scope.corpus.numMinWords = formValues.numMinWords;

            $('#input_slider_min_words').attr('data-slider-value', formValues.numMinChars);
            $scope.corpus.numMinChars = formValues.numMinChars;

            $scope.corpus.title = formValues.title;

            $scope.languages = [
                {name: "German", value: "de"},
                {name: "English", value: "en"},
                {name: "Spanish", value: "es"},
                {name: "French", value: "fr"},
                {name: "Italian", value: "it"},
                {name: "Dutch", value: "nl"},
                {name: "Portuguese", value: "pt"},
                {name: "Turkish", value: "tr"}
            ];

            $scope.startCreateCorpus = function () {
                // Starts corpus creation through corpusCreationService if form is valid
                var isValid = $("form").get(0).checkValidity();
                if (isValid === true) {
                    corpusCreationService.startCorpusCreation($scope.corpus)
                        .success(function (data, status) {
                            switch (status) {
                                case 206:
                                    notify("Corpus <b>" + $scope.corpus.title + " </b>is being created, " +
                                        "but there are not sufficient tweets available.", "info");
                                    break;
                                default:
                                    notify("Corpus <b>" + $scope.corpus.title + " </b>is being created.");
                                    break;
                            }
                            $rootScope.$emit("corpus:create:start");
                        }).error(function (data, status) {
                            switch(status) {
                                case 444:
                                    notify("No tweets found to fetch. Try to be less specific.", "error");
                                    break;
                                default:
                                    notify("Failed to fetch tweets.", "error");
                                    break;
                            }
                        });
                }
            };

        var saveIntoLocalStorage = function() {
            localStorage.setItem('formValues', JSON.stringify({
                endDate: $scope.corpus.endDate || null,
                startDate: $scope.corpus.startDate || null,
                language: $scope.corpus.language || "",
                numMinChars: $scope.corpus.numMinChars || 0,
                numMinWords: $scope.corpus.numMinWords || 0,
                numTweets: $scope.corpus.numTweets || 20,
                title: $scope.corpus.title || ""
            }));
        };

        $scope.$on("$destroy", function () {
            saveIntoLocalStorage();
        });

        window.onbeforeunload = function () {
            saveIntoLocalStorage();
        };
    }])

    .directive('ngBootstrapSlider', function () {
        // uses http://www.eyecon.ro/bootstrap-slider/
        return {
            restrict: 'A',
            scope: {
                ngModel: "="
            },
            require: 'ngModel',

            link: function ($scope, elm, attrs) {
                $scope.ngModel = parseInt(attrs.sliderValue) || 0;
                var slider = $(elm).slider({value: 0});
                $scope.slider = slider;

                slider.on('slide', function (e) {
                    var val = $(this).val();
                    $scope.ngModel = parseInt(val);
                    $scope.$apply();
                });
            },

            controller: function ($scope) {
                $scope.$watch('ngModel', function (newValue, oldValue) {
                    $scope.slider.slider('setValue', newValue);
                })
            }
        }
    })

    .directive('twDate', function () {
        return {
            restrict: 'A',
            scope: {
                ngModel: "=",
                minDate: "=",
                maxDate: "="
            },
            require: 'ngModel',

            link: function ($scope, elm, attrs) {
                var picker = new Pikaday({
                    field: elm[0],
                    bound: false,
                    onSelect: function (date) {
                        $scope.ngModel = date || new Date();
                        $scope.$apply();
                    }
                });

                $scope.$watch('ngModel', function (newValue, oldValue) {
                    picker.setDate(newValue, true);
                });

                $scope.$watch("minDate", function(newValue) {
                    picker.setMinDate(newValue);
                    picker.setDate($scope.ngModel, true); // need setDate to update Datepicker
                });

                $scope.$watch("maxDate", function(newValue) {
                    picker.setMaxDate(newValue);
                    picker.setDate($scope.ngModel, true); // need setDate to update Datepicker
                });
            }
        }
    })

    .controller('twDateRangeController', ["$scope",
        function ($scope) {
            $scope.$watch('corpus.startDate', function (newValue, oldValue) {
                if (!$scope.corpus) return;
                if (newValue > $scope.corpus.endDate) $scope.corpus.startDate = $scope.corpus.endDate;

                $scope.corpus.endDate.minDate = newValue;
            });

            $scope.$watch('corpus.endDate', function (newValue, oldValue) {
                if (!$scope.corpus) return;
                if (newValue < $scope.corpus.startDate) $scope.corpus.endDate = $scope.corpus.startDate;

                $scope.corpus.startDate.maxDate = newValue;
            });
        }]);<|endoftext|>


<commit_before>/*
 * JsUtils
 * https://github.com/axin/JsUtils
 * Author: Alexey Sazikin
 * Licensed under MIT license
 */

var JsUtils = (module && module.exports) || {};

(function (exports) {
    exports.isObject = isObject;
    exports.isNotEmptyString = isNotEmptyString;
    exports.isNotNullObject = isNotNullObject;
    exports.cloneObject = cloneObject;

    function isObject(val) {
        if (typeof val === 'object') {
            return true;
        }

        return false;
    }

    function isNotEmptyString(value) {
        if (value && typeof value === 'string') {
            return true;
        }

        return false;
    }

    function isNotNullObject(value) {
        if (value && typeof value === 'object') {
            return true;
        }

        return false;
    }

    function cloneObject(obj) {
        return JSON.parse(JSON.stringify(obj));
    }
}(JsUtils));
<commit_msg>Add isObjectButNotArray function<commit_after>/*
 * JsUtils
 * https://github.com/axin/JsUtils
 * Author: Alexey Sazikin
 * Licensed under MIT license
 */

var JsUtils = (module && module.exports) || {};

(function (exports) {
    exports.isObject = isObject;
    exports.isObjectButNotArray = isObjectButNotArray;
    exports.isNotEmptyString = isNotEmptyString;
    exports.isNotNullObject = isNotNullObject;
    exports.cloneObject = cloneObject;

    function isObject(val) {
        if (typeof val === 'object') {
            return true;
        }

        return false;
    }

    function isObjectButNotArray(val) {
        if (isObject(val) && !Array.isArray(val)) {
            return true;
        }

        return false;
    }

    function isNotEmptyString(value) {
        if (value && typeof value === 'string') {
            return true;
        }

        return false;
    }

    function isNotNullObject(value) {
        if (value && typeof value === 'object') {
            return true;
        }

        return false;
    }

    function cloneObject(obj) {
        return JSON.parse(JSON.stringify(obj));
    }
}(JsUtils));
<|endoftext|>


<commit_before>var ReactReduxContext = require('react-redux').ReactReduxContext
var useContext = require('react').useContext
var useEffect = require('react').useEffect
var useState = require('react').useState

function add (store, subscriptions) {
  if (!store.subscriptions) store.subscriptions = { }
  if (!store.subscribers) store.subscribers = { }

  return Promise.all(subscriptions.map(function (i) {
    var subscription = i[0]
    var json = i[1]
    if (!store.subscribers[json]) store.subscribers[json] = 0
    store.subscribers[json] += 1
    if (store.subscribers[json] === 1) {
      var action = Object.assign({ type: 'logux/subscribe' }, subscription)
      store.subscriptions[json] = store.log.add(action, { sync: true })
    }
    return store.subscriptions[json]
  }))
}

function remove (store, subscriptions) {
  subscriptions.forEach(function (i) {
    var subscription = i[0]
    var json = i[1]
    store.subscribers[json] -= 1
    if (store.subscribers[json] === 0) {
      var action = Object.assign({ type: 'logux/unsubscribe' }, subscription)
      store.log.add(action, { sync: true })
      delete store.subscriptions[json]
    }
  })
}

function useSubscription (channels, opts) {
  if (!opts) opts = { }

  var isSubscribing = useState(true)
  var store = useContext(opts.context || ReactReduxContext).store

  var subscriptions = channels.map(function (i) {
    var subscription = typeof i === 'string' ? { channel: i } : i
    return [subscription, JSON.stringify(subscription)]
  })

  var id = subscriptions.map(function (i) {
    return i[1]
  }).sort().join(' ')

  useEffect(function () {
    var updated = false
    add(store, subscriptions).then(function () {
      if (!updated) isSubscribing[1](false)
    })
    return function () {
      updated = true
      remove(store, subscriptions)
    }
  }, [id])

  return isSubscribing[0]
}

module.exports = useSubscription
<commit_msg>Fix tests<commit_after>var ReactReduxContext = require('react-redux').ReactReduxContext
var useContext = require('react').useContext
var useEffect = require('react').useEffect
var useState = require('react').useState

function add (store, subscriptions) {
  if (!store.subscriptions) store.subscriptions = { }
  if (!store.subscribers) store.subscribers = { }

  return Promise.all(subscriptions.map(function (i) {
    var subscription = i[0]
    var json = i[1]
    if (!store.subscribers[json]) store.subscribers[json] = 0
    store.subscribers[json] += 1
    if (store.subscribers[json] === 1) {
      var action = Object.assign({ type: 'logux/subscribe' }, subscription)
      store.subscriptions[json] = store.dispatch.sync(action)
    }
    return store.subscriptions[json]
  }))
}

function remove (store, subscriptions) {
  subscriptions.forEach(function (i) {
    var subscription = i[0]
    var json = i[1]
    store.subscribers[json] -= 1
    if (store.subscribers[json] === 0) {
      var action = Object.assign({ type: 'logux/unsubscribe' }, subscription)
      store.log.add(action, { sync: true })
      delete store.subscriptions[json]
    }
  })
}

function useSubscription (channels, opts) {
  if (!opts) opts = { }

  var isSubscribing = useState(true)
  var store = useContext(opts.context || ReactReduxContext).store

  var subscriptions = channels.map(function (i) {
    var subscription = typeof i === 'string' ? { channel: i } : i
    return [subscription, JSON.stringify(subscription)]
  })

  var id = subscriptions.map(function (i) {
    return i[1]
  }).sort().join(' ')

  useEffect(function () {
    var updated = false
    add(store, subscriptions).then(function () {
      if (!updated) isSubscribing[1](false)
    })
    return function () {
      updated = true
      remove(store, subscriptions)
    }
  }, [id])

  return isSubscribing[0]
}

module.exports = useSubscription
<|endoftext|>


<commit_before>(function() {

    var margin =
    {
      top: 50,
      bottom: 10,
      left:300,
      right: 40
    };

    var width = 900 - margin.left - margin.right;
    var height = 900 - margin.top - margin.bottom;

    var xScale = d3.scale.linear()
      .range([0, width]);
    var yScale = d3.scale.ordinal()
      //.domain(['Homer', 'Marge', 'Bart', 'Lisa', 'Maggie'])
      .rangeRoundBands([0, height], 0.8, 0);

    var barHeight = 15;

    var state = function(d) {
      return d.State;
    };

//    var stateButton =
//      '<input type="radio" name="order" value="state">';
//    stateButton += 'State';
//    var rateButton =
//      '<input type="radio" name="order" value="rate" checked>';
//    rateButton += 'Rate';

    var svg = d3.select("body").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom);

    var g = svg.append("g")
      .attr("transform", "translate("
        + margin.left + "," + margin.top + ")");

    g.append('text')
      .attr('x', 0)
      .attr('y', 0)
      .style('font-size', 18)
      .style('font-weight', 'bold')
      .text('Unemployment Rates for States');

    d3.tsv("unemp_states_us_nov_2013.tsv", function(data) {

      var max = d3.max(data, function(d) {
        return d.Rate;
      });
      var min = 0;

      xScale.domain([min, max]);
      yScale.domain(data.map(state));

      //console.log(yScale('ILLINOIS'));

      var groups = g.append("g")
        .selectAll("g")
        .data(data)
      .enter()
        .append("g")
        .attr("transform", function(d, i) {
          return "translate(0, " + yScale(d.State) +")";
        });

      var bars = groups
        .append("rect")
        .attr("width", function(d) {
          return xScale(d.Rate);
        })
        .attr("height", barHeight);

      // add rates to bars
      groups.append('text')
        .attr('x', function (d) {
          //return xScale(d.Rate);
          return xScale(d.Rate);
        })
        .attr('dx', -5)
        .attr('y', function (d) {
          return (barHeight / 2);
        })
        .attr('dy', 3)
        .attr('fill', '#ffffff')
        .attr('text-anchor', 'end')
        .text(function(d) {
          return d.Rate;
        });

      // add state names to bars
      groups.append('text')
        .attr('x', 0)
        .attr('dx', -10)
        .attr('y', function() {
          return barHeight / 2;
        })
        .attr('text-anchor', 'end')
        .text(function(d) {
          return d.State;
        });

     var button = d3.select('button')
       .on('click', function() {
         //console.log(bars.selectAll('g'));
       });

      //console.log(yScale('IOWA'));

      var reorder = function() {
        data.sort(function(a, b) {
          //console.log('compare a.State, b.State: ', a.State, b.State);
          // sort by state
          //if (document.getElementById('state').checked) {
          console.log(yScale('ILLINOIS'));
          return d3.ascending(a.State, b.State);
          //} else {
            //return d3.ascending(a.Rate, b.Rate);
          //}
        });

        bars
          .transition()
            .duration(750)
            .delay(function(d, i) {
              //console.log(d);
              return i * 10;
            })
            .attr('transform', function(d, i) {
              //console.log(d.State);
              console.log(yScale('ILLINOIS'));
              //console.log(i);
              return 'translate(0, ' + yScale(d.state) + ')';
            });
      }

      d3.selectAll('input')
        .on('change', reorder);

    });

})();
<commit_msg>muddles muddles muddles<commit_after>(function() {

    var margin =
    {
      top: 50,
      bottom: 10,
      left:300,
      right: 40
    };

    var width = 900 - margin.left - margin.right;
    var height = 900 - margin.top - margin.bottom;

    var xScale = d3.scale.linear()
      .range([0, width]);
    var yScale = d3.scale.ordinal()
      //.domain(['Homer', 'Marge', 'Bart', 'Lisa', 'Maggie'])
      .rangeRoundBands([0, height], 0.8, 0);

    var barHeight = 15;

    var state = function(d) {
      return d.State;
    };

//    var stateButton =
//      '<input type="radio" name="order" value="state">';
//    stateButton += 'State';
//    var rateButton =
//      '<input type="radio" name="order" value="rate" checked>';
//    rateButton += 'Rate';

    var svg = d3.select("body").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom);

    var g = svg.append("g")
      .attr("transform", "translate("
        + margin.left + "," + margin.top + ")");

    g.append('text')
      .attr('x', 0)
      .attr('y', 0)
      .style('font-size', 18)
      .style('font-weight', 'bold')
      .text('Unemployment Rates for States');

    d3.tsv("unemp_states_us_nov_2013.tsv", function(data) {

      var max = d3.max(data, function(d) {
        return d.Rate;
      });
      var min = 0;

      xScale.domain([min, max]);
      yScale.domain(data.map(state));

      //console.log(yScale('ILLINOIS'));

      var groups = g.append("g")
        .selectAll("g")
        .data(data)
      .enter()
        .append("g")
        .attr("transform", function(d, i) {
          return "translate(0, " + yScale(d.State) +")";
        });

      var bars = groups
        .append("rect")
        .attr("width", function(d) {
          return xScale(d.Rate);
        })
        .attr("height", barHeight);

      // add rates to bars
      groups.append('text')
        .attr('x', function (d) {
          //return xScale(d.Rate);
          return xScale(d.Rate);
        })
        .attr('dx', -5)
        .attr('y', function (d) {
          return (barHeight / 2);
        })
        .attr('dy', 3)
        .attr('fill', '#ffffff')
        .attr('text-anchor', 'end')
        .text(function(d) {
          return d.Rate;
        });

      // add state names to bars
      groups.append('text')
        .attr('x', 0)
        .attr('dx', -10)
        .attr('y', function() {
          return barHeight / 2;
        })
        .attr('text-anchor', 'end')
        .text(function(d) {
          return d.State;
        });

     var button = d3.select('button')
       .on('click', function() {
         //console.log(bars.selectAll('g'));
       });

      //console.log(yScale('IOWA'));

      var reorder = function() {
        data.sort(function(a, b) {
          //console.log('compare a.State, b.State: ', a.State, b.State);
          // sort by state
          //if (document.getElementById('state').checked) {
          console.log(yScale('ALABAMA'));
          return d3.ascending(a.State, b.State);
          //} else {
            //return d3.ascending(a.Rate, b.Rate);
          //}
        });

        // update yScale domain after sorting
        yScale.domain(data.map(state));

        bars
          .transition()
            .duration(5750)
            .delay(function(d, i) {
              //console.log(d);
              return i * 10;
            })
            .attr('transform', function(d, i) {
              //console.log(d.State);
              //console.log(i);
              console.log(i);
              console.log(this);
              console.log(d.State);
              return 'translate(0, ' + yScale(d.State)  + ')';
            });
      }

      d3.selectAll('input')
        .on('change', reorder);

    });

})();
<|endoftext|>