<commit_before>/**
 * @license
 * Custom types for use on the Grunt plugin.
 * Copyright 2013 Cláudio Manuel Brás da Silva
 * http://github.com/claudio-silva
 * Licensed under the MIT license.
 */
'use strict';

/* jshint unused: vars */

var NL = require ('./gruntUtil').NL;

/**
 * A module definition record.
 * Contains all javascript defining the module, read from one or more source files.
 * @constructor
 */
function ModuleDef ()
{
  this.bodies = [];
  this.filePaths = [];
}

ModuleDef.prototype = {
  /**
   * The module's name.
   * @type {!string}
   */
  name:      '',
  /**
   * Relative file paths to the source script files.
   * The first entry corresponds to the file that starts the module definition.
   * @type {string[]}
   */
  filePaths: null,
  /**
   * The content of the file that starts the module definition.
   * If null, the file was not yet read.
   * @type {?string}
   */
  head:      null,
  /**
   * The content of each additional file that appends definitions to the module.
   * If there are no additional files for the module, the value will be an empty array.
   * @type {string[]}
   */
  bodies:    null,
  /**
   * List with the names of the required modules.
   * If no modules are required, the value will be an empty array.
   * @type {string[]}
   */
  requires:  null,
  /**
   * When true, the module is not included in the build but it's possibly referenced in the source code.
   * @type {boolean}
   */
  external:  false,
  /**
   * @type {string|undefined}
   * Third parameter of a module declaration, if present.
   */
  configFn:  undefined
};

/**
 * @const
 * Defaults for task options.
 */
var TASK_OPTIONS = {
  /**
   * Main module name. Only this module and its dependencies will be exported.
   * @type {string}
   */
  main:                      '',
  /**
   * Name of the variable representing the angular module being defined, to be used inside self-invoked anonymous
   * functions.
   * You may select another identifier if the default one causes a conflict with existing code.
   * @type {string}
   */
  moduleVar:                 'module',
  /**
   * When true, angular module references passed as arguments to self-invoking functions will be renamed to
   * config.moduleVar.
   *
   * When false, if the module reference parameter has a name that is different from the one defined on
   * config.moduleVar,
   * a warning will be issued and the task may stop, unless the `--force` option is specified.
   * @type {boolean}
   */
  renameModuleRefs:          false,
  /**
   * When `false`, required assets are copied to the assets target directory.
   *
   * When `true`, symlinks are generated instead. This speeds up the build operation considerably, and also saves disk
   * space.
   *
   * If your operating system does not support symlinks, or if you want to archive or upload the build output, use
   * `false`.
   * @type {boolean}
   */
  symlinkAssets:             true,
  /**
   * Set to `true` to enable the assets builder.
   * @type {boolean}
   */
  buildAssets:               false,
  /**
   * Directory path that will be used as the reference point from where relative asset urls are calculated.
   * This determines where assets are exported to.
   * If you specify a relative path, it is resolved from the current filegroup's destination folder.
   * @type {string}
   */
  assetsTargetDir:           '',
  /**
   * Code packaging method.
   *
   * When false, generates a single optimized javascript file with all required source code in the correct
   * loading order.
   *
   * When true, generates a set of <script> tags to include all the required source files in the correct
   * loading order.
   *
   * Note: The use of this setting as an option is, probably, not what you want.
   * Use the `debug` task argument instead.
   * @type {boolean}
   */
  debug:                     false,
  /**
   * A list of module names to ignore when building.
   * This allows the source code to contain references to modules not present in the build (ex. 3rd party libraries that
   * are loaded independently).
   *
   * If a module reference (for module access or for declaring a dependency) is found in the source code, which targets
   * a module that is not declared anywhere in the build's source files, the build operation aborts when that module
   * name is not present on this list.
   * @type {string|string[]}
   */
  externalModules:           '',
  /**
   * A list of framework built-in modules (ex. 'ng') that will always be appended to the `externalModules` list when
   * running tasks, so that references to them are ignored by the builder.
   * This is reserved for internal use, but could be overridden if you wish to completely replace the built-in behavior.
   * @type {string[]}
   */
  builtinModules:            ['ng'],
  /**
   * Indentation white space for one level.
   * You may, for instance, configure it for tabs or additional spaces.
   * @type {string}
   */
  indent:                    '  ',
  /**
   * This string will be appended to each module definition block.
   * Use this to increase the readability of the generated script by visually separating each module from the previous
   * one.
   * @type {string}
   */
  moduleFooter:              NL + NL + NL,
  /**
   * Transform the generated debug URLs of the source files. It's an array of regexp match and replace records.
   * @type {{match:RegExp|string,replaceWith:string}[]|null}
   */
  rebaseDebugUrls:           null,
  /**
   * The name of the Gruntfile config property to where the list of required stylesheet paths will be exported.
   * These stylesheets are those required by javascript files included in the build via build-directives.
   * @type {string}
   */
  stylesheetsConfigProperty: 'requiredStylesheets',
  /**
   * The name of the Gruntfile config property to where the list of required template paths will be exported.
   * These HTML templates are those required by javascript files included in the build via build-directives.
   * @type {string}
   */
  templatesConfigProperty:   'requiredTemplates',
  /**
   * The name of the Gruntfile config property to where the list of required script paths will be exported.
   * These scripts are all those that are actually required by your project, including forced includes and
   * files included via build-directives.
   * @type {string}
   */
  scriptsConfigProperty:     'requiredScripts',
  /**
   * A list of file paths to prepend to the build output.
   * This forces the inclusion of specific script files, independently of any source file scanning performed
   * by Grunt.
   * @type {string[]}
   */
  require: [],
  /**
   * A list of external extension modules names to be loaded.
   * Use this to load 3rd party extensions.
   * @type {string[]|null}
   */
  extensions:                null,
  /**
   * Defines the list of extensions bundled with angular-builder.
   * This is a list of extension modules names to be loaded.
   * This is reserved for internal use, but could be overridden if you wish to completely replace the
   * built-in behavior.
   * WARNING: the order of the extensions listed here is important! If you change it, the build process
   * my fail!
   * @type {string[]}
   * @const
   */
  bundledExtensions:         [
    './extensions/exportPaths',
    './extensions/scripts',
    './extensions/NonAngularScripts',
    './extensions/debugBuild',
    './extensions/releaseBuild',
    './extensions/stylesheets',
    './extensions/templates',
    './extensions/assets'
  ]
};

/**
 * @name FILE_GROUP_OPTIONS
 * Extended options for Grunt file groups.
 *//**
 * @name FILE_GROUP_OPTIONS#forceInclude
 * @type {string|string[]|null}
 * A list of filenames or glob patterns that specify which javascript files should always be included in the build,
 * even if they have no module declarations.
 *
 * Warning: the files must also be matched by src to be included.
 *
 * Note: patterns without slashes will match against the basename of the path even if it contains slashes,
 * eg. pattern *.js will match filepath path/to/file.js.
 *
 * Usually, when a script file is found in the set of source files which doesn't contain a module declaration,
 * that file is ignored.
 * But, if the file name and path matches a file name or glob pattern specified here, it will still be included.
 *
 * Non-module files are output in the same order they were read, and before any module.
 *
 * Tip: You can append the current step's result script to another one that resulted from a previous build
 * step.
 * If you specify a target or file group exclusively for standalone script files and append the result to other built
 * files, you will have more control on the order of the assembled files.
 *//**
 * @name FILE_GROUP_OPTIONS#src
 * @type {string[]|null}
 *//**
 * @name FILE_GROUP_OPTIONS#dest
 * @type {string|null}
 */

/**
 * A function result composite value that includes a status value and optional data.
 * @name OperationResult
 *//**
 * Result status code. 0 = OK, other values depend on the context this is being used on.
 * @name OperationResult#status
 * @type {number}
 */
/**
 * Optional output data from the function that returned this record.
 * @name OperationResult#data
 * @type {*}
 */

/**
 * API for an Angular Builder plugin.
 * Note: implementing classes must have a compatible constructor.
 * @interface
 * @param grunt The Grunt API.
 * @param {TASK_OPTIONS} options Task configuration options.
 * @param {boolean} debugBuild Debug mode flag.
 */
function ExtensionInterface (grunt, options, debugBuild)
{}

ExtensionInterface.prototype = {
  /**
   * Scans a module for relevant information.
   * Invoked once for each required module in the application, in the order defined by
   * the dependency graph.
   * @param {ModuleDef} module Gives you access to the module's metadata and its source code.
   */
  trace: function (module) {},
  /**
   * Builds the compilation output.
   * Invoked once.
   * @param {string} targetScript Path to the output script.
   * @param {Array.<{path: string, content: string}>} standaloneScripts
   * A list of scripts that have no module definitions but that are forced to still being included in the build.
   * Each item contains the filename and the file content.
   */
  build: function (targetScript, standaloneScripts) {}
};

//------------------------------------------------------------------------------
// EXPORT
//------------------------------------------------------------------------------

module.exports = {
  ModuleDef:          ModuleDef,
  ExtensionInterface: ExtensionInterface,
  TASK_OPTIONS:       TASK_OPTIONS
};<commit_msg>Update types.js<commit_after>/**
 * @license
 * Custom types for use on the Grunt plugin.
 * Copyright 2013 Cláudio Manuel Brás da Silva
 * http://github.com/claudio-silva
 * Licensed under the MIT license.
 */
'use strict';

/* jshint unused: vars */

var NL = require ('./gruntUtil').NL;

/**
 * A module definition record.
 * Contains all javascript defining the module, read from one or more source files.
 * @constructor
 */
function ModuleDef ()
{
  this.bodies = [];
  this.filePaths = [];
}

ModuleDef.prototype = {
  /**
   * The module's name.
   * @type {!string}
   */
  name:      '',
  /**
   * Relative file paths to the source script files.
   * The first entry corresponds to the file that starts the module definition.
   * @type {string[]}
   */
  filePaths: null,
  /**
   * The content of the file that starts the module definition.
   * If null, the file was not yet read.
   * @type {?string}
   */
  head:      null,
  /**
   * The content of each additional file that appends definitions to the module.
   * If there are no additional files for the module, the value will be an empty array.
   * @type {string[]}
   */
  bodies:    null,
  /**
   * List with the names of the required modules.
   * If no modules are required, the value will be an empty array.
   * @type {string[]}
   */
  requires:  null,
  /**
   * When true, the module is not included in the build but it's possibly referenced in the source code.
   * @type {boolean}
   */
  external:  false,
  /**
   * @type {string|undefined}
   * Third parameter of a module declaration, if present.
   */
  configFn:  undefined
};

/**
 * @const
 * Defaults for task options.
 */
var TASK_OPTIONS = {
  /**
   * Main module name. Only this module and its dependencies will be exported.
   * @type {string}
   */
  main:                      '',
  /**
   * Name of the variable representing the angular module being defined, to be used inside self-invoked anonymous
   * functions.
   * You may select another identifier if the default one causes a conflict with existing code.
   * @type {string}
   */
  moduleVar:                 'module',
  /**
   * When true, angular module references passed as arguments to self-invoking functions will be renamed to
   * config.moduleVar.
   *
   * When false, if the module reference parameter has a name that is different from the one defined on
   * config.moduleVar,
   * a warning will be issued and the task may stop, unless the `--force` option is specified.
   * @type {boolean}
   */
  renameModuleRefs:          false,
  /**
   * When `false`, required assets are copied to the assets target directory.
   *
   * When `true`, symlinks are generated instead. This speeds up the build operation considerably, and also saves disk
   * space.
   *
   * If your operating system does not support symlinks, or if you want to archive or upload the build output, use
   * `false`.
   * @type {boolean}
   */
  symlinkAssets:             true,
  /**
   * Set to `true` to enable the assets builder.
   * @type {boolean}
   */
  buildAssets:               false,
  /**
   * Directory path that will be used as the reference point from where relative asset urls are calculated.
   * This determines where assets are exported to.
   * If you specify a relative path, it is resolved from the current filegroup's destination folder.
   * @type {string}
   */
  assetsTargetDir:           '',
  /**
   * Code packaging method.
   *
   * When false, generates a single optimized javascript file with all required source code in the correct
   * loading order.
   *
   * When true, generates a set of <script> tags to include all the required source files in the correct
   * loading order.
   *
   * Note: The use of this setting as an option is, probably, not what you want.
   * Use the `debug` task argument instead.
   * @type {boolean}
   */
  debug:                     false,
  /**
   * A list of module names to ignore when building.
   * This allows the source code to contain references to modules not present in the build (ex. 3rd party libraries that
   * are loaded independently).
   *
   * If a module reference (for module access or for declaring a dependency) is found in the source code, which targets
   * a module that is not declared anywhere in the build's source files, the build operation aborts when that module
   * name is not present on this list.
   * @type {string|string[]}
   */
  externalModules:           '',
  /**
   * A list of framework built-in modules (ex. 'ng') that will always be appended to the `externalModules` list when
   * running tasks, so that references to them are ignored by the builder.
   * This is reserved for internal use, but could be overridden if you wish to completely replace the built-in behavior.
   * @type {string[]}
   */
  builtinModules:            ['ng'],
  /**
   * Indentation white space for one level.
   * You may, for instance, configure it for tabs or additional spaces.
   * @type {string}
   */
  indent:                    '  ',
  /**
   * This string will be appended to each module definition block.
   * Use this to increase the readability of the generated script by visually separating each module from the previous
   * one.
   * @type {string}
   */
  moduleFooter:              NL + NL + NL,
  /**
   * Transform the generated debug URLs of the source files. It's an array of regexp match and replace records.
   * @type {{match:RegExp|string,replaceWith:string}[]|null}
   */
  rebaseDebugUrls:           null,
  /**
   * The name of the Gruntfile config property to where the list of required stylesheet paths will be exported.
   * These stylesheets are those required by javascript files included in the build via build-directives.
   * @type {string}
   */
  stylesheetsConfigProperty: 'requiredStylesheets',
  /**
   * The name of the Gruntfile config property to where the list of required template paths will be exported.
   * These HTML templates are those required by javascript files included in the build via build-directives.
   * @type {string}
   */
  templatesConfigProperty:   'requiredTemplates',
  /**
   * The name of the Gruntfile config property to where the list of required script paths will be exported.
   * These scripts are all those that are actually required by your project, including forced includes and
   * files included via build-directives.
   * @type {string}
   */
  scriptsConfigProperty:     'requiredScripts',
  /**
   * A list of file paths to prepend to the build output.
   * This forces the inclusion of specific script files, independently of any source file scanning performed
   * by Grunt.
   * @type {string[]}
   */
  require: [],
  /**
   * A list of external extension modules names to be loaded.
   * Use this to load 3rd party extensions.
   * @type {string[]|null}
   */
  extensions:                null,
  /**
   * Defines the list of extensions bundled with angular-builder.
   * This is a list of extension modules names to be loaded.
   * This is reserved for internal use, but could be overridden if you wish to completely replace the
   * built-in behavior.
   * WARNING: the order of the extensions listed here is important! If you change it, the build process
   * my fail!
   * @type {string[]}
   * @const
   */
  bundledExtensions:         [
    './extensions/exportPaths',
    './extensions/scripts',
    './extensions/nonAngularScripts',
    './extensions/debugBuild',
    './extensions/releaseBuild',
    './extensions/stylesheets',
    './extensions/templates',
    './extensions/assets'
  ]
};

/**
 * @name FILE_GROUP_OPTIONS
 * Extended options for Grunt file groups.
 *//**
 * @name FILE_GROUP_OPTIONS#forceInclude
 * @type {string|string[]|null}
 * A list of filenames or glob patterns that specify which javascript files should always be included in the build,
 * even if they have no module declarations.
 *
 * Warning: the files must also be matched by src to be included.
 *
 * Note: patterns without slashes will match against the basename of the path even if it contains slashes,
 * eg. pattern *.js will match filepath path/to/file.js.
 *
 * Usually, when a script file is found in the set of source files which doesn't contain a module declaration,
 * that file is ignored.
 * But, if the file name and path matches a file name or glob pattern specified here, it will still be included.
 *
 * Non-module files are output in the same order they were read, and before any module.
 *
 * Tip: You can append the current step's result script to another one that resulted from a previous build
 * step.
 * If you specify a target or file group exclusively for standalone script files and append the result to other built
 * files, you will have more control on the order of the assembled files.
 *//**
 * @name FILE_GROUP_OPTIONS#src
 * @type {string[]|null}
 *//**
 * @name FILE_GROUP_OPTIONS#dest
 * @type {string|null}
 */

/**
 * A function result composite value that includes a status value and optional data.
 * @name OperationResult
 *//**
 * Result status code. 0 = OK, other values depend on the context this is being used on.
 * @name OperationResult#status
 * @type {number}
 */
/**
 * Optional output data from the function that returned this record.
 * @name OperationResult#data
 * @type {*}
 */

/**
 * API for an Angular Builder plugin.
 * Note: implementing classes must have a compatible constructor.
 * @interface
 * @param grunt The Grunt API.
 * @param {TASK_OPTIONS} options Task configuration options.
 * @param {boolean} debugBuild Debug mode flag.
 */
function ExtensionInterface (grunt, options, debugBuild)
{}

ExtensionInterface.prototype = {
  /**
   * Scans a module for relevant information.
   * Invoked once for each required module in the application, in the order defined by
   * the dependency graph.
   * @param {ModuleDef} module Gives you access to the module's metadata and its source code.
   */
  trace: function (module) {},
  /**
   * Builds the compilation output.
   * Invoked once.
   * @param {string} targetScript Path to the output script.
   * @param {Array.<{path: string, content: string}>} standaloneScripts
   * A list of scripts that have no module definitions but that are forced to still being included in the build.
   * Each item contains the filename and the file content.
   */
  build: function (targetScript, standaloneScripts) {}
};

//------------------------------------------------------------------------------
// EXPORT
//------------------------------------------------------------------------------

module.exports = {
  ModuleDef:          ModuleDef,
  ExtensionInterface: ExtensionInterface,
  TASK_OPTIONS:       TASK_OPTIONS
};
<|endoftext|>


<commit_before>import React from 'react'
import { withRouter } from 'react-router-dom'
import Character from './character'
import SingleCharacterRolling from "./single-character-rolling";

class Game extends React.Component {
  constructor() {
    super()

    this.addCharacter = this.addCharacter.bind(this)

    this.state = {
      gameName: ''
    }
  }

  componentWillMount() {
    var path = this.props.history.location.pathname.split('/')
    this.setState({ gameName: path[path.length - 1]})
  }

  addCharacter(character) {
    const characters = {...this.props.games[this.state.gameName].characters}
    characters[character.name] = character
    this.props.addNewCharacter(this.state.gameName, character)
  }

  render() {
    return (

          {this.state.gameName}

            <button type="button" className="btn btn-primary" onClick={() => {this.props.history.push('/')} }>Game List -></button>
            <SingleCharacterRolling addCharacter={this.addCharacter}/>

              {
                Object.keys(this.props.games[this.state.gameName].characters)
                  .map(name => <Character key={name} character={this.props.games[this.state.gameName].characters[name]}/>)
              }

    );
  }
}

export default withRouter(Game)<commit_msg>Add list of characters in side bar<commit_after>import React from 'react'
import { withRouter } from 'react-router-dom'
import Character from './character'
import SingleCharacterRolling from "./single-character-rolling";

class Game extends React.Component {
  constructor() {
    super()

    this.addCharacter = this.addCharacter.bind(this)

    this.state = {
      gameName: ''
    }
  }

  componentWillMount() {
    var path = this.props.history.location.pathname.split('/')
    this.setState({ gameName: path[path.length - 1]})
  }

  addCharacter(character) {
    const characters = {...this.props.games[this.state.gameName].characters}
    characters[character.name] = character
    this.props.addNewCharacter(this.state.gameName, character)
  }

  render() {
    return (

          {this.state.gameName}

            <button type="button" className="btn btn-primary" onClick={() => {this.props.history.push('/')} }>Game List -></button>

              {
                Object.keys(this.props.games[this.state.gameName].characters)
                  .map(name =>
{name}
)
              }

            <SingleCharacterRolling addCharacter={this.addCharacter}/>

              {
                Object.keys(this.props.games[this.state.gameName].characters)
                  .map(name => <Character key={name} character={this.props.games[this.state.gameName].characters[name]}/>)
              }

    );
  }
}

export default withRouter(Game)<|endoftext|>


<commit_before>import React, {Component} from 'react'
import {connect} from 'react-redux'

class Home extends Component {
  render () {
    return (

Welcome to Login Flow!

This application demonstrates what a React-based register/login workflow might look like with redux-saga.

It's based on Max Stoiber's login-flow. See the full source code on GitHub!

Try logging in with username juan and password password, then try to register new users. They'll be saved in local storage so they'll persist across page reloads.

Features

Features will go here :-)

Authentication

Authentication happens in app/auth/index.js, using fakeRequest.js and fakeServer.js. fakeRequest is a fake XMLHttpRequest wrapper. fakeServer responds to the fake HTTP requests and pretends to be a real server, storing the current users in local storage with the passwords encrypted using bcrypt.

    )
  }
}

function select (state) {
  return {
    data: state
  }
}

export default connect(select)(Home)
<commit_msg>Remove features list<commit_after>import React, {Component} from 'react'
import {connect} from 'react-redux'

class Home extends Component {
  render () {
    return (

Welcome to Login Flow!

This application demonstrates what a React-based register/login workflow might look like with redux-saga.

It's based on Max Stoiber's login-flow. See the full source code on GitHub!

Try logging in with username juan and password password, then try to register new users. They'll be saved in local storage so they'll persist across page reloads.

Authentication

Authentication happens in app/auth/index.js, using fakeRequest.js and fakeServer.js. fakeRequest is a fake XMLHttpRequest wrapper. fakeServer responds to the fake HTTP requests and pretends to be a real server, storing the current users in local storage with the passwords encrypted using bcrypt.

    )
  }
}

function select (state) {
  return {
    data: state
  }
}

export default connect(select)(Home)
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Link } from 'react-router';
import styles from './Home.css';
import io from 'socket.io-client';
import jarvis from 'file!../jarvis-bkrd.png';
import RaisedButton from 'material-ui/lib/raised-button';
import ActionRecordVoiceOver from 'material-ui/lib/svg-icons/action/record-voice-over';
import * as Camera from '../actions/camera';
import Motion from '../actions/motion';
var mongoose = require('mongoose');

let socket = io(`http://10.104.100.41:8000`)

export default class Home extends Component {

  sendMessage = () => {
    Camera.takePicture();
    socket.emit('notifyBot', "I'M HERE", function (err) {
      if (err) {
        return console.error("Socket error" + err);
      }
      callback();
    });
  }

  checkForPendingVisitors = () => {

  }

  render() {
    return (

          <RaisedButton
            backgroundColor="#218EC1"
            className={styles.button}
            style={style}
            label="Let someone know I'm here"
            labelColor="#FFF"
            onClick={this.sendMessage}
            icon={<ActionRecordVoiceOver />}
          />

          <RaisedButton
            backgroundColor="#218EC1"
            className={styles.button}
            style={style}
            label="Check for pending visitors"
            labelColor="#FFF"
            onClick={this.checkForPendingVisitors}
            icon={<ActionRecordVoiceOver />}
          />

    );
  }
}
const style = {
  position: 'fixed',
  bottom: '0px',
  left: '0px',
  height: '60px',
  width: '300px'
}
<commit_msg>Installed mongoose. fixing raspicam image saving 2.<commit_after>import React, { Component } from 'react';
import { Link } from 'react-router';
import styles from './Home.css';
import io from 'socket.io-client';
import jarvis from 'file!../jarvis-bkrd.png';
import RaisedButton from 'material-ui/lib/raised-button';
import ActionRecordVoiceOver from 'material-ui/lib/svg-icons/action/record-voice-over';
import * as Camera from '../actions/camera';
import Motion from '../actions/motion';
var mongoose = require('mongoose');

let socket = io(`http://10.104.100.30:8000`)

export default class Home extends Component {

  sendMessage = () => {
    Camera.takePicture();
    socket.emit('notifyBot', "I'M HERE", function (err) {
      if (err) {
        return console.error("Socket error" + err);
      }
      callback();
    });
  }

  checkForPendingVisitors = () => {

  }

  render() {
    return (

          <RaisedButton
            backgroundColor="#218EC1"
            className={styles.button}
            style={style}
            label="Let someone know I'm here"
            labelColor="#FFF"
            onClick={this.sendMessage}
            icon={<ActionRecordVoiceOver />}
          />

          <RaisedButton
            backgroundColor="#218EC1"
            className={styles.button}
            style={style2}
            label="Check for pending visitors"
            labelColor="#FFF"
            onClick={this.checkForPendingVisitors}
            icon={<ActionRecordVoiceOver />}
          />

    );
  }
}
const style = {
  position: 'fixed',
  bottom: '0px',
  left: '0px',
  height: '60px',
  width: '300px'
}

const style2 = {
  position: 'fixed',
  bottom: '0px',
  right: '0px',
  height: '60px',
  width: '300px'
}
<|endoftext|>


<commit_before>// Closure
(function () {
  /**
   * Decimal adjustment of a number.
   *
   * @param {String}  type  The type of adjustment.
   * @param {Number}  value The number.
   * @param {Integer} exp   The exponent (the 10 logarithm of the adjustment base).
   * @returns {Number} The adjusted value.
   */
  function decimalAdjust(type, value, exp) {
    // If the exp is undefined or zero...
    if (typeof exp === 'undefined' || +exp === 0) {
      return Math[type](value)
    }
    value = +value
    exp = +exp
    // If the value is not a number or the exp is not an integer...
    if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
      return NaN
    }
    // If the value is negative...
    if (value < 0) {
      return -decimalAdjust(type, -value, exp)
    }
    // Shift
    value = value.toString().split('e')
    value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)))
    // Shift back
    value = value.toString().split('e')
    return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp))
  }

  // Decimal round
  if (!Math.round10) {
    Math.round10 = function (value, exp) {
      return decimalAdjust('round', value, exp)
    }
  }
  // Decimal floor
  if (!Math.floor10) {
    Math.floor10 = function (value, exp) {
      return decimalAdjust('floor', value, exp)
    }
  }
  // Decimal ceil
  if (!Math.ceil10) {
    Math.ceil10 = function (value, exp) {
      return decimalAdjust('ceil', value, exp)
    }
  }
})()

function Datum(id, name, ratings) {
  return ({
    id: id,
    name: name,
    ratings: ratings,
    strengthComments: [],
    improvementComments: []
  })
}

function Comment(num, text, author) {
  return {
    id: num,
    text: text,
    author: author
  }
}

function Ratings(peerArr, selfArr) {
  return [
    {
      label: 'peer',
      values: [{ x: 'C', y: peerArr[0] }, { x: 'N', y: peerArr[1] }, { x: 'P', y: peerArr[2] }, { x: 'I', y: peerArr[3] }, { x: 'O', y: peerArr[4] }]
    },
    {
      label: 'self',
      values: [{ x: 'C', y: selfArr[0] }, { x: 'N', y: selfArr[1] }, { x: 'P', y: selfArr[2] }, { x: 'I', y: selfArr[3] }, { x: 'O', y: selfArr[4] }]
    }
  ]
}

const randomSelf = (length, max) => [...new Array(length)]
  .map(() => Math.round(Math.random() * max))

const randomPeer = (length, max) => [...new Array(length)]
  .map(() => Math.round10(Math.random() * max, -1))

const randomRatings = () => new Ratings(randomPeer(5, 5), randomSelf(5, 5))

const weekNames = ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5', 'Week 6', 'Grace Shopper']

const classMates = ['Jodie', 'Rachel', 'Fish', 'Colleen', 'Mercedes', 'Ruth', 'Stefanie', 'Stefanie', 'Fanny', 'Arin', 'Allison', 'Elsa', 'Nitika', 'Keziyah', 'Cigdam', 'Sarah', 'Tina', 'Anonymous', 'Anonymous', 'Anonymous']

const improvementComments = [
  'Nothing! Maria is perfect in each and every way.',
  'For lack of a better way to say it, Maria can be difficult to work with. She insisted on driving AND navigating the entire time. I wish she had been open to some of my ideas',
  'Sometimes Maria had trouble articulating what she was trying to do.',
  'I don\'t think we took a break once in 6 hours ....',
  'As a pair, we were somewhat rudderless.',
  'Maria asked to take breaks every 15 minutes.',
  'Maria quickly gave up when working on CSS.',
  'She was often distracted by pigeons on the window sills.',
  'Her silence was often off-putting.',
  'She seemed to have a strong preference for driving -- I wanted to drive sometimes.',
  'Not much, I really enjoyed working with her!',
  'Often wanted to call a fellow over when we could have just googled the answer.',
  'she wanted to google everything and never ask for help',
  'she tried to explain everything to me all the time as though I had no clue what was going on',
  'working with her is fine, but I am worried about the amount of cereal she is eating',
  'Maria didn\'t seem to be taking things seriously enough.',
  'She just wanted to work on a codewars problem instead of the workshop.',
  'when navigating she wasn\'t very helpful',
  'As a driver, she seemed to think she was just a typist and did not think very much. As a navigator she acted as though I wasn\'t allowed to have ideas.',
  'sometimes her moodswings were a bit much',
  'she seemed sleep-deprived. GET SOME SLEEP GIRL'
]

const strengthComments = [
  'She is so focused and made me focused too. I don\'t think we took a break once in 6 hours! Also, her notes are out of this world.',
  'Maria\'s strong grasp of CSS really helped us get through the ShoeString workshop.',
  'She made sure that we both got to drive and navigate fairly.',
  'As a team, we went through the workshop at a steady pace --- slow enough to absorb things, but fast enough to get through most of the material!',
  'We balance each other out well.',
  'She had a great amount of independence, but also used help tickets appropriately.',
  'Maria never makes spelling mistakes.',
  'Maria has got Promises down cold.',
  'I enjoyed her sense of experimentation and wanting to just see if things work.',
  'She was great at using the workshop text and code to her advantage.',
  'She knew the Sequelize docs front and back so we could quickly find what we were looking for.',
  'She was great at being considerate and always asking my opnions on things when she was driving.',
  'Maria put in extra work after hours, but kept things on a separate branch so she could show me the next day.',
  'Maria didn\'t have a clue about SQL but she was a great student when I tried to get her up to speed.',
  'Maria is a really great navigator -- she has docs and references handy and thinks in terms of the big picture.',
  'Maria really knows her stuff. She clearly read and re-read the pre-reading and took detailed notes during the lecture. She was also able to communicate her ideas clearly',
  'Maria was super driven to finish the workshop even though we were lagging sometimes.',
  'her energy and optimism are wonderful!'
]

var data = weekNames.map((weekName, index) => {
  var datum = new Datum(index + 1, weekName, randomRatings())
  let counter = 0
  let idArr = [++counter, ++counter, ++counter]
  datum.strengthComments = idArr.map(id => new Comment(id, strengthComments[Math.round(Math.random() * 20)], classMates[Math.round(Math.random() * 20)]))
  idArr = [++counter, ++counter, ++counter]
  datum.improvementComments = idArr.map(id =>
    new Comment(id, improvementComments[Math.round(Math.random() * 20)], classMates[Math.round(Math.random() * 20)]))
  return datum
})

export default data
<commit_msg>randomized data<commit_after>// Closure
(function() {
  /**
   * Decimal adjustment of a number.
   *
   * @param {String}  type  The type of adjustment.
   * @param {Number}  value The number.
   * @param {Integer} exp   The exponent (the 10 logarithm of the adjustment base).
   * @returns {Number} The adjusted value.
   */
  function decimalAdjust(type, value, exp) {
    // If the exp is undefined or zero...
    if (typeof exp === 'undefined' || +exp === 0) {
      return Math[type](value)
    }
    value = +value
    exp = +exp
    // If the value is not a number or the exp is not an integer...
    if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
      return NaN
    }
    // If the value is negative...
    if (value < 0) {
      return -decimalAdjust(type, -value, exp)
    }
    // Shift
    value = value.toString().split('e')
    value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)))
    // Shift back
    value = value.toString().split('e')
    return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp))
  }

  // Decimal round
  if (!Math.round10) {
    Math.round10 = function(value, exp) {
      return decimalAdjust('round', value, exp)
    }
  }
  // Decimal floor
  if (!Math.floor10) {
    Math.floor10 = function(value, exp) {
      return decimalAdjust('floor', value, exp)
    }
  }
  // Decimal ceil
  if (!Math.ceil10) {
    Math.ceil10 = function(value, exp) {
      return decimalAdjust('ceil', value, exp)
    }
  }
})()

function Datum(id, name, ratings) {
  return ({
    id: id,
    name: name,
    ratings: ratings,
    strengthComments: [],
    improvementComments: []
  })
}

function Comment(num, text, author) {
  return {
    id: num,
    text: text,
    author: author
  }
}

function Ratings(peerArr, selfArr) {
  return [
    {
      label: 'peer',
      values: [{ x: 'C', y: peerArr[0] }, { x: 'N', y: peerArr[1] }, { x: 'P', y: peerArr[2] }, { x: 'I', y: peerArr[3] }, { x: 'O', y: peerArr[4] }]
    },
    {
      label: 'self',
      values: [{ x: 'C', y: selfArr[0] }, { x: 'N', y: selfArr[1] }, { x: 'P', y: selfArr[2] }, { x: 'I', y: selfArr[3] }, { x: 'O', y: selfArr[4] }]
    }
  ]
}

const randomSelf = (length, max) => [...new Array(length)]
  .map(() => Math.round(Math.random() * max))

const randomPeer = (length, max) => [...new Array(length)]
  .map(() => Math.round10(Math.random() * max, -1))

const randomRatings = () => new Ratings(randomPeer(5, 5), randomSelf(5, 5))

const weekNames = ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5', 'Week 6', 'Grace Shopper']

const classMates = ['Jodie', 'Rachel', 'Fish', 'Colleen', 'Mercedes', 'Ruth', 'Stefanie', 'Stefanie', 'Fanny', 'Arin', 'Allison', 'Elsa', 'Nitika', 'Keziyah', 'Cigdam', 'Sarah', 'Tina', 'Anonymous', 'Anonymous', 'Anonymous']

const improvementComments = [
  'Nothing! Maria is perfect in each and every way.',
  'For lack of a better way to say it, Maria can be difficult to work with. She insisted on driving AND navigating the entire time. I wish she had been open to some of my ideas',
  'Sometimes Maria had trouble articulating what she was trying to do.',
  'I don\'t think we took a break once in 6 hours ....',
  'As a pair, we were somewhat rudderless.',
  'Maria asked to take breaks every 15 minutes.',
  'Maria quickly gave up when working on CSS.',
  'She was often distracted by pigeons on the window sills.',
  'Her silence was often off-putting.',
  'She seemed to have a strong preference for driving -- I wanted to drive sometimes.',
  'Not much, I really enjoyed working with her!',
  'Often wanted to call a fellow over when we could have just googled the answer.',
  'she wanted to google everything and never ask for help',
  'she tried to explain everything to me all the time as though I had no clue what was going on',
  'working with her is fine, but I am worried about the amount of cereal she is eating',
  'Maria didn\'t seem to be taking things seriously enough.',
  'She just wanted to work on a codewars problem instead of the workshop.',
  'when navigating she wasn\'t very helpful',
  'As a driver, she seemed to think she was just a typist and did not think very much. As a navigator she acted as though I wasn\'t allowed to have ideas.',
  'sometimes her moodswings were a bit much',
  'she seemed sleep-deprived. GET SOME SLEEP GIRL'
]

const strengthComments = [
  'She is so focused and made me focused too. I don\'t think we took a break once in 6 hours! Also, her notes are out of this world.',
  'Maria\'s strong grasp of CSS really helped us get through the ShoeString workshop.',
  'She made sure that we both got to drive and navigate fairly.',
  'As a team, we went through the workshop at a steady pace --- slow enough to absorb things, but fast enough to get through most of the material!',
  'We balance each other out well.',
  'She had a great amount of independence, but also used help tickets appropriately.',
  'Maria never makes spelling mistakes.',
  'Maria has got Promises down cold.',
  'I enjoyed her sense of experimentation and wanting to just see if things work.',
  'She was great at using the workshop text and code to her advantage.',
  'She knew the Sequelize docs front and back so we could quickly find what we were looking for.',
  'She was great at being considerate and always asking my opnions on things when she was driving.',
  'Maria put in extra work after hours, but kept things on a separate branch so she could show me the next day.',
  'Maria didn\'t have a clue about SQL but she was a great student when I tried to get her up to speed.',
  'Maria is a really great navigator -- she has docs and references handy and thinks in terms of the big picture.',
  'Maria really knows her stuff. She clearly read and re-read the pre-reading and took detailed notes during the lecture. She was also able to communicate her ideas clearly',
  'Maria was super driven to finish the workshop even though we were lagging sometimes.',
  'her energy and optimism are wonderful!'
]

let counter = 0
var data = weekNames.map((weekName, index) => {
  var datum = new Datum(index + 1, weekName, randomRatings())
  let idArr = [++counter, ++counter, ++counter]
  datum.strengthComments = idArr.map(id => new Comment(id, strengthComments[Math.round(Math.random() * 20)], classMates[Math.round(Math.random() * 20)]))
  idArr = [++counter, ++counter, ++counter]
  datum.improvementComments = idArr.map(id =>
    new Comment(id, improvementComments[Math.round(Math.random() * 20)], classMates[Math.round(Math.random() * 20)]))
  return datum
})

let summaryRatings = new Ratings([0, 0, 0, 0, 0], [0, 0, 0, 0, 0])

data.forEach(datum => {
  datum.ratings[0].values.forEach((characterRating, index) => {
    summaryRatings[0].values[index]['y'] += characterRating['y']
  })
  datum.ratings[1].values.forEach((characterRating, index) => {
    summaryRatings[1].values[index]['y'] += characterRating['y']
  })
})

summaryRatings[0].values.forEach(rating => {
  rating['y'] = Math.round10(rating['y'] / data.length, -1)
})

summaryRatings[1].values.forEach(rating => {
  rating['y'] = Math.round10(rating['y'] / data.length, -1)
})

const summary = new Datum(data.length, 'summary', summaryRatings)

data.forEach(datum => {
  datum.strengthComments.forEach(comment => {
    summary.strengthComments.push(comment)
  })
  datum.improvementComments.forEach(comment => {
    summary.improvementComments.push(comment)
  })
})

export {data, summary}
<|endoftext|>


<commit_before>#!/usr/bin/env node

var fs   = require('fs');
var argv = require('optimist').usage('Usage: dogescript <file>').demand(1).argv;
var es   = require('event-stream');
var _    = require('lodash');

var indentLevel = 0;
var parser = function (line) {
    var keys = line.split(/[ \t]/);
    var valid = ['such', 'wow', 'plz', 'very', 'shh'];
    var statement = '';

    if (indentLevel > 0) {
        keys = _.remove(keys, function (key) { return key !== ''; });
        for (var i = 0; i < indentLevel; i++) {
            statement += ' ';
        }
    }

    for (var i = 0; i < keys.length; i++) {
        if ((keys[i].charAt(0) === '\'' || keys[i].charAt(0) === '[' || keys[i].charAt(0) === '{') && keys[i + 1]) {
            var dupe = keys.slice(0); // .slice(0) duplicates an array
            for (var j = i + 1; j < dupe.length; j++) {
                keys[i] += ' ' + dupe[j];
                keys.splice(j, 1);
            }
        } else {
            continue;
        }
    }

    // such function
    if (keys[0] === 'such') {
        indentLevel += 4;
        statement += 'function ' + keys[1];

        if (keys[2] === 'much') {
            statement += ' ('
            for (var i = 3; i < keys.length; i++) {
                statement += keys[i];
                if (i !== keys.length - 1) statement += ', '
            }
            statement += ') { \n';
        } else {
            statement += ' () { \n'
        }
    }

    // wow end function
    if (keys[0] === 'wow') {
        indentLevel -= 4;
        statement = statement.replace('    ', '');
        statement += '} \n'
    }

    // plz execute function
    if (keys[0] === 'plz') {
        if (keys[2] === 'with') {
            statement += keys[1] + '(';
            for (var i = 3; i < keys.length; i++) {
                statement += keys[i];
                if (i !== keys.length - 1) statement += ', '
            }
            statement += ');\n'
        } else {
            statement += keys[1] + '();\n';
        }
    }

    // very variable
    if (keys[0] === 'very') {
        statement += 'var ' + keys[1] + ' = ' + keys[3] + ';\n'
    }

    // shh comment
    if (keys[0] === 'shh') {
        statement += '// '
        for (var i = 1; i < keys.length; i++) {
            statement += keys[i] + ' ';
        }
        statement += '\n'
    }

    // not dogescript, such javascript
    if (valid.indexOf(keys[0]) === -1) return line.replace('	', '    ') + '\n';

    return statement;
}

fs.createReadStream(__dirname + '/' + argv._[0])
    .pipe(es.split())
    .pipe(es.mapSync(parser))
    .pipe(process.stdout);
<commit_msg>support console.loge<commit_after>#!/usr/bin/env node

var fs   = require('fs');
var argv = require('optimist').usage('Usage: dogescript <file>').demand(1).argv;
var es   = require('event-stream');
var _    = require('lodash');

var indentLevel = 0;
var parser = function (line) {
    var keys = line.split(/[ \t]/);
    var valid = ['such', 'wow', 'plz', 'very', 'shh'];
    var statement = '';

    if (indentLevel > 0) {
        keys = _.remove(keys, function (key) { return key !== ''; });
        for (var i = 0; i < indentLevel; i++) {
            statement += ' ';
        }
    }

    for (var i = 0; i < keys.length; i++) {
        if ((keys[i].charAt(0) === '\'' || keys[i].charAt(0) === '[' || keys[i].charAt(0) === '{') && keys[i + 1]) {
            var dupe = keys.slice(0); // .slice(0) duplicates an array
            for (var j = i + 1; j < dupe.length; j++) {
                keys[i] += ' ' + dupe[j];
                keys.splice(j, 1);
            }
        } else {
            continue;
        }
    }

    // such function
    if (keys[0] === 'such') {
        indentLevel += 4;
        statement += 'function ' + keys[1];

        if (keys[2] === 'much') {
            statement += ' ('
            for (var i = 3; i < keys.length; i++) {
                statement += keys[i];
                if (i !== keys.length - 1) statement += ', '
            }
            statement += ') { \n';
        } else {
            statement += ' () { \n'
        }
    }

    // wow end function
    if (keys[0] === 'wow') {
        indentLevel -= 4;
        statement = statement.replace('    ', '');
        statement += '} \n'
    }

    // plz execute function
    if (keys[0] === 'plz') {
        if (keys[1] === 'console.loge') keys[1] = 'console.log';
        if (keys[2] === 'with') {
            statement += keys[1] + '(';
            for (var i = 3; i < keys.length; i++) {
                statement += keys[i];
                if (i !== keys.length - 1) statement += ', '
            }
            statement += ');\n'
        } else {
            statement += keys[1] + '();\n';
        }
    }

    // very variable
    if (keys[0] === 'very') {
        statement += 'var ' + keys[1] + ' = ' + keys[3] + ';\n'
    }

    // shh comment
    if (keys[0] === 'shh') {
        statement += '// '
        for (var i = 1; i < keys.length; i++) {
            statement += keys[i] + ' ';
        }
        statement += '\n'
    }

    // not dogescript, such javascript
    if (valid.indexOf(keys[0]) === -1) return line.replace('	', '    ') + '\n';

    return statement;
}

fs.createReadStream(__dirname + '/' + argv._[0])
    .pipe(es.split())
    .pipe(es.mapSync(parser))
    .pipe(process.stdout);
<|endoftext|>


<commit_before>// CartoDB SQL API
//
// all requests expect the following URL args:
// - `sql` {String} SQL to execute
//
// for private (read/write) queries:
// - OAuth. Must have proper OAuth 1.1 headers. For OAuth 1.1 spec see Google
//
// eg. /api/v1/?sql=SELECT 1 as one (with a load of OAuth headers or URL arguments)
//
// for public (read only) queries:
// - sql only, provided the subdomain exists in CartoDB and the table's sharing options are public
//
// eg. vizzuality.cartodb.com/api/v1/?sql=SELECT * from my_table
var express = require('express')
    , app      = express.createServer(
    express.logger({
        buffer: true,
        format: '[:date] :req[X-Real-IP] \033[90m:method\033[0m \033[36m:req[Host]:url\033[0m \033[90m:status :response-time ms -> :res[Content-Type]\033[0m'
    }))
    , Step       = require('step')
    , csv        = require('csv')
    , Meta       = require(global.settings.app_root + '/app/models/metadata')
    , oAuth      = require(global.settings.app_root + '/app/models/oauth')
    , PSQL       = require(global.settings.app_root + '/app/models/psql')
    , ApiKeyAuth = require(global.settings.app_root + '/app/models/apikey_auth')
    , _        = require('underscore');

app.use(express.bodyParser());
app.enable('jsonp callback');

app.all('/api/v1/sql',  function(req, res) { handleQuery(req, res) } );
app.all('/api/v1/sql.:f',  function(req, res) { handleQuery(req, res) } );
function handleQuery(req, res){

    // sanitize input
    var body      = (req.body) ? req.body : {};
    var sql       = req.query.q || body.q; // get and post
    var api_key   = req.query.api_key || body.api_key;
    var database  = req.query.database; // deprecate this in future
    var limit     = parseInt(req.query.rows_per_page);
    var offset    = parseInt(req.query.page);
    var format    = (req.query.format) ? req.query.format : null;
    var dp        = (req.query.dp) ? req.query.dp: '15';

    // validate input slightly
    dp        = (dp=== "")        ? '15' : dp;
    format    = (format === "")   ? null : format;
    sql       = (sql === "")      ? null : sql;
    database  = (database === "") ? null : database;
    limit     = (_.isNumber(limit))  ? limit : null;
    offset    = (_.isNumber(offset)) ? offset * limit : null

    // setup step run
    var that  = this;
    var start = new Date().getTime();

    try {
        if (!_.isString(sql)) throw new Error("You must indicate a sql query");
        var pg;

        // 1. Get database from redis via the username stored in the host header subdomain
        // 2. Run the request through OAuth to get R/W user id if signed
        // 3. Run query with r/w or public user
        // 4. package results and send back
        Step(
            function getDatabaseName(){
                Meta.getDatabase(req, this);
            },
            function setDBGetUser(err, data) {
                if (err) throw err;
                database = (data == "" || _.isNull(data)) ? database : data;
                if(api_key) {
                    ApiKeyAuth.verifyRequest(req, this);
                } else {
                    oAuth.verifyRequest(req, this);
                }
            },
            function querySql(err, user_id){
                if (err) throw err;
                pg = new PSQL(user_id, database, limit, offset);

                // TODO: refactor formats to external object
                if (format === 'geojson'){
                    sql = ['SELECT *, ST_AsGeoJSON(the_geom,',dp,') as the_geom FROM (', sql, ') as foo'].join("");
                }

                pg.query(sql, this);
            },
            function setHeaders(err, result){
                if (err) throw err;

                // configure headers for geojson/CSV
                res.header("Content-Disposition", getContentDisposition(format));
                res.header("Content-Type", getContentType(format));

                // allow cross site post
                setCrossDomain(res);

                // set cache headers
                res.header('Last-Modified', new Date().toUTCString());
                res.header('Cache-Control', 'no-cache,max-age=3600,must-revalidate, public');
                res.header('X-Cache-Channel', database);

                return result;
            },
            function packageResults(err, result){
                if (err) throw err;

                // TODO: refactor formats to external object
                if (format === 'geojson'){
                    toGeoJSON(result, res, this);
                } else if (format === 'csv'){
                    toCSV(result, res, this);
                } else {
                    var end = new Date().getTime();
                    return {
                        'time' : ((end - start)/1000),
                        'total_rows': result.rows.length,
                        'rows'      : result.rows
                    };
                }
            },
            function sendResults(err, out){
                if (err) throw err;

                // return to browser
                res.send(out);
            },
            function errorHandle(err, result){
                handleException(err, res);
            }
        );
    } catch (err) {
        console.log('[ERROR]\n' + err);
        handleException(err, res);
    }
}

function toGeoJSON(data, res, callback){
    try{
        var out = {
            type: "FeatureCollection",
            features: []
        };

        _.each(data.rows, function(ele){
            var geojson = {
                type: "Feature",
                properties: { },
                geometry: { }
            };
            geojson.geometry = JSON.parse(ele["the_geom"]);
            delete ele["the_geom"];
            delete ele["the_geom_webmercator"];
            geojson.properties = ele;
            out.features.push(geojson);
        });

        // return payload
        callback(null, out);
    } catch (err) {
        callback(err,null);
    }
}

function toCSV(data, res, callback){
    try{
        // pull out keys for column headers
        var columns = _.keys(data.rows[0]);

        // stream the csv out over http
        csv()
          .from(data.rows)
          .toStream(res, {end: true, columns: columns, header: true});
        return true;
    } catch (err) {
        callback(err,null);
    }
}

function getContentDisposition(format){
    var ext = 'json';
    if (format === 'geojson'){
        ext = 'geojson';
    }
    if (format === 'csv'){
        ext = 'csv';
    }
    var time = new Date().toUTCString();
    return 'inline; filename=cartodb-query.' + ext + '; modification-date="' + time + '";';
}

function getContentType(format){
    var type = "application/json; charset=utf-8";
    if (format === 'csv'){
        type = "text/csv; charset=utf-8";
    }
    return type;
}

function setCrossDomain(res){
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
}

function handleException(err, res){
    var msg = (global.settings.environment == 'development') ? {error:[err.message], stack: err.stack} : {error:[err.message]}
    if (global.settings.environment !== 'test'){
        // TODO: email this Exception report
        console.log("EXCEPTION REPORT")
        console.log(err.message);
        console.log(err.stack);
    }

    // allow cross site post
    setCrossDomain(res);

    // if the exception defines a http status code, use that, else a 500
    if (!_.isUndefined(err.http_status)){
        res.send(msg, err.http_status);
    } else {
        res.send(msg, 400);
    }
}

module.exports = app;
<commit_msg>add specific cache key<commit_after>// CartoDB SQL API
//
// all requests expect the following URL args:
// - `sql` {String} SQL to execute
//
// for private (read/write) queries:
// - OAuth. Must have proper OAuth 1.1 headers. For OAuth 1.1 spec see Google
//
// eg. /api/v1/?sql=SELECT 1 as one (with a load of OAuth headers or URL arguments)
//
// for public (read only) queries:
// - sql only, provided the subdomain exists in CartoDB and the table's sharing options are public
//
// eg. vizzuality.cartodb.com/api/v1/?sql=SELECT * from my_table
var express = require('express')
    , app      = express.createServer(
    express.logger({
        buffer: true,
        format: '[:date] :req[X-Real-IP] \033[90m:method\033[0m \033[36m:req[Host]:url\033[0m \033[90m:status :response-time ms -> :res[Content-Type]\033[0m'
    }))
    , Step       = require('step')
    , csv        = require('csv')
    , Meta       = require(global.settings.app_root + '/app/models/metadata')
    , oAuth      = require(global.settings.app_root + '/app/models/oauth')
    , PSQL       = require(global.settings.app_root + '/app/models/psql')
    , ApiKeyAuth = require(global.settings.app_root + '/app/models/apikey_auth')
    , _        = require('underscore');

app.use(express.bodyParser());
app.enable('jsonp callback');

app.all('/api/v1/sql',  function(req, res) { handleQuery(req, res) } );
app.all('/api/v1/sql.:f',  function(req, res) { handleQuery(req, res) } );
function handleQuery(req, res){

    // sanitize input
    var body      = (req.body) ? req.body : {};
    var sql       = req.query.q || body.q; // get and post
    var api_key   = req.query.api_key || body.api_key;
    var database  = req.query.database; // deprecate this in future
    var limit     = parseInt(req.query.rows_per_page);
    var offset    = parseInt(req.query.page);
    var format    = (req.query.format) ? req.query.format : null;
    var dp        = (req.query.dp) ? req.query.dp: '15';

    // validate input slightly
    dp        = (dp === "")        ? '15' : dp;
    format    = (format === "")   ? null : format;
    sql       = (sql === "")      ? null : sql;
    database  = (database === "") ? null : database;
    limit     = (_.isNumber(limit))  ? limit : null;
    offset    = (_.isNumber(offset)) ? offset * limit : null

    // setup step run
    var start = new Date().getTime();

    try {
        if (!_.isString(sql)) throw new Error("You must indicate a sql query");
        var pg, explain_result;

        // 1. Get database from redis via the username stored in the host header subdomain
        // 2. Run the request through OAuth to get R/W user id if signed
        // 3. Get the list of tables affected by the query
        // 4. Run query with r/w or public user
        // 5. package results and send back
        Step(
            function getDatabaseName(){
                Meta.getDatabase(req, this);
            },
            function setDBGetUser(err, data) {
                if (err) throw err;
                database = (data == "" || _.isNull(data)) ? database : data;
                if(api_key) {
                    ApiKeyAuth.verifyRequest(req, this);
                } else {
                    oAuth.verifyRequest(req, this);
                }
            },
            function queryExplain(err, user_id){
                if (err) throw err;
                // store postgres connection
                pg = new PSQL(user_id, database, limit, offset);

                // get all the tables
                pg.query('SELECT CDB_QueryTables(\''+sql+'\')', this);
            },
            function queryResult(err, result){
                if (err) throw err;
                // store explain result
                explain_result = result;

                // TODO: refactor formats to external object
                if (format === 'geojson'){
                    sql = ['SELECT *, ST_AsGeoJSON(the_geom,',dp,') as the_geom FROM (', sql, ') as foo'].join("");
                }

                pg.query(sql, this);
            },
            function setHeaders(err, result){
                if (err) throw err;

                // configure headers for geojson/CSV
                res.header("Content-Disposition", getContentDisposition(format));
                res.header("Content-Type", getContentType(format));

                // allow cross site post
                setCrossDomain(res);

                // set cache headers
                res.header('Last-Modified', new Date().toUTCString());
                res.header('Cache-Control', 'no-cache,max-age=3600,must-revalidate, public');
                res.header('X-Cache-Channel', generateCacheKey(database,explain_result));

                return result;
            },
            function packageResults(err, result){
                if (err) throw err;

                // TODO: refactor formats to external object
                if (format === 'geojson'){
                    toGeoJSON(result, res, this);
                } else if (format === 'csv'){
                    toCSV(result, res, this);
                } else {
                    var end = new Date().getTime();
                    return {
                        'time' : ((end - start)/1000),
                        'total_rows': result.rows.length,
                        'rows'      : result.rows
                    };
                }
            },
            function sendResults(err, out){
                if (err) throw err;

                // return to browser
                res.send(out);
            },
            function errorHandle(err, result){
                handleException(err, res);
            }
        );
    } catch (err) {
        console.log('[ERROR]\n' + err);
        handleException(err, res);
    }
}

function toGeoJSON(data, res, callback){
    try{
        var out = {
            type: "FeatureCollection",
            features: []
        };

        _.each(data.rows, function(ele){
            var geojson = {
                type: "Feature",
                properties: { },
                geometry: { }
            };
            geojson.geometry = JSON.parse(ele["the_geom"]);
            delete ele["the_geom"];
            delete ele["the_geom_webmercator"];
            geojson.properties = ele;
            out.features.push(geojson);
        });

        // return payload
        callback(null, out);
    } catch (err) {
        callback(err,null);
    }
}

function toCSV(data, res, callback){
    try{
        // pull out keys for column headers
        var columns = _.keys(data.rows[0]);

        // stream the csv out over http
        csv()
          .from(data.rows)
          .toStream(res, {end: true, columns: columns, header: true});
        return true;
    } catch (err) {
        callback(err,null);
    }
}

function getContentDisposition(format){
    var ext = 'json';
    if (format === 'geojson'){
        ext = 'geojson';
    }
    if (format === 'csv'){
        ext = 'csv';
    }
    var time = new Date().toUTCString();
    return 'inline; filename=cartodb-query.' + ext + '; modification-date="' + time + '";';
}

function getContentType(format){
    var type = "application/json; charset=utf-8";
    if (format === 'csv'){
        type = "text/csv; charset=utf-8";
    }
    return type;
}

function setCrossDomain(res){
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
}

function generateCacheKey(database,tables){
    return database + ":" + tables.rows[0].cdb_querytables.split(/^\{(.*)\}$/)[1];
}

function handleException(err, res){
    var msg = (global.settings.environment == 'development') ? {error:[err.message], stack: err.stack} : {error:[err.message]}
    if (global.settings.environment !== 'test'){
        // TODO: email this Exception report
        console.log("EXCEPTION REPORT")
        console.log(err.message);
        console.log(err.stack);
    }

    // allow cross site post
    setCrossDomain(res);

    // if the exception defines a http status code, use that, else a 500
    if (!_.isUndefined(err.http_status)){
        res.send(msg, err.http_status);
    } else {
        res.send(msg, 400);
    }
}

module.exports = app;
<|endoftext|>


<commit_before>var args = arguments[0] || {};

var zoomedName = args.name;
var zoomColor = args.color;
var zoomLat = args.zoomlat;

var route;
var radius = 20;
//var MapModule = require('ti.map');
Alloy.Globals.MapModule = MapModule;

var infospotsNotVisible = true;
var hotspotsNotVisible = true;

var infospotsAnnotation;
var hotspotAnnotation;

var trailsCollection = getTrailsCollection();
var hotspotCollection = getHotspotCollection();
var jsonFileCollection = getJSONfiles();

//-----------------------------------------------------------
// Onload-funktioner för kartan
//-----------------------------------------------------------
// try {
showMap();
setRoutes();
displayTrailMarkers();
// } catch(e) {
// newError("Något gick fel när sidan skulle laddas, prova igen!", "Map - load page");
// }

//-----------------------------------------------------------
// Sätter ut alla vandringsleder på kartan
//-----------------------------------------------------------
function setRoutes() {
	try {
		trailsCollection.fetch({
			query : 'SELECT id, name, color FROM trailsModel'
		});

		var jsonObj = trailsCollection.toJSON();

		for (var i = 0; i < jsonObj.length; i++) {
			if (jsonObj[i].name != 'Båtleden') {
				var file = getFile(jsonObj[i].id);

				for (var u = 0; u < file.length; u++) {
					createMapRoutes(file[u].filename, jsonObj[i].name, jsonObj[i].color);
				}
			}
		}

	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "infoList - getInfoDetails");
	}
}

//-----------------------------------------------------------
// Hämtar JSON-fil för en vandringsled
//-----------------------------------------------------------
function getFile(id) {
	try {
		jsonFileCollection.fetch({
			query : 'SELECT filename FROM jsonFilesModel WHERE trailID ="' + id + '"'
		});

		var filename = jsonFileCollection.toJSON();
		return filename;
	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - getFile");
	}
}

//-----------------------------------------------------------
// Skapar en vandringsled på kartan
//-----------------------------------------------------------
function createMapRoutes(file, name, color) {
	try {
		var routes = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory + "/routes/" + file).read().text;
		var parsedRoute = JSON.parse(routes);

		var geoArray = [];
		geoArray.push(parsedRoute);

		for (var u = 0; u < geoArray.length; u++) {
			var coords = geoArray[0].features[0].geometry.paths[u];

			var points = new Array();

			for (var i = 0; i < coords.length; i++) {

				var c = {
					latitude : coords[i][1],
					longitude : coords[i][0]
				};
				points.push(c);
			}

			var route = {
				name : name,
				points : points,
				color : color,
				width : 3.0
			};
			baseMap.addRoute(MapModule.createRoute(route));
		}
	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - createMapRoutes");
	}
}

//-----------------------------------------------------------
// Läser in kartvyn
//-----------------------------------------------------------
function showMap() {
	try {
		baseMap = MapModule.createView({
			userLocation : true,
			mapType : MapModule.HYBRID_TYPE,
			animate : true,
			region : {
				latitude : 58.886775,
				longitude : 11.026024,
				latitudeDelta : 0.08,
				longitudeDelta : 0.08
			},
			height : '100%',
			width : Ti.UI.FILL
		});

		$.mapView.add(baseMap);

	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "Map - showMap");
	}
}

//-----------------------------------------------------------
// Visar markers för vandringslederna
//-----------------------------------------------------------
function displayTrailMarkers() {
	try {
		trailsCollection.fetch({
			query : 'SELECT name, pinLon, pinLat, area, length, color FROM trailsModel'
		});

		var jsonObjTrails = trailsCollection.toJSON();
		for (var i = 0; i < jsonObjTrails.length; i++) {

			color = jsonObjTrails[i].color.toUpperCase();
			Ti.API.info(JSON.stringify(color));

			var markerAnnotation = MapModule.createAnnotation({
				id : jsonObjTrails[i].name,
				latitude : jsonObjTrails[i].pinLat,
				longitude : jsonObjTrails[i].pinLon,
				title : jsonObjTrails[i].name,
				pincolor : MapModule.ANNOTATION_AZURE,
				subtitle : jsonObjTrails[i].area + ', ' + jsonObjTrails[i].length,
				rightButton : '/pins/androidarrow2.png',
				name : 'trail',
				color : '#000000',
				font : {
					fontFamily : 'Raleway-Light'
				}
			});

			// markerAnnotation.pincolor = Alloy.Globals.MapModule.ANNOTATION_GREEN;

			baseMap.addAnnotation(markerAnnotation);
		}
	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - displayTrailMarkers");
	}
}

//-----------------------------------------------------------
// Öppnar trailDetail med info om vald vandringsled
//-----------------------------------------------------------
function showTrail(myId) {
	try {
		trailsCollection.fetch({
			query : 'SELECT * FROM trailsModel where name ="' + myId + '"'
		});

		var jsonObjTr = trailsCollection.toJSON();

		var args = {
			id : jsonObjTr[0].id,
			title : myId,
			length : jsonObjTr[0].length,
			infoTxt : jsonObjTr[0].infoTxt,
			area : jsonObjTr[0].area,
			color : jsonObjTr[0].color,
			zoomlat : jsonObjTr[0].zoomLat,
			zoomlon : jsonObjTr[0].zoomLon
		};

		var trailDetail = Alloy.createController("trailDetail", args).getView();
		Alloy.CFG.tabs.activeTab.open(trailDetail);
	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - showTrail");
	}
}

//-----------------------------------------------------------
// Öppnar hotspotDetail med info om vald hotspot
//-----------------------------------------------------------
function showHotspot(myId) {
	try {
		hotspotCollection.fetch({
			query : 'SELECT id, infoTxt FROM hotspotModel where name = "' + myId + '"'
		});

		var jsonObjHot = hotspotCollection.toJSON();

		var hotspotTxt = {
			title : myId,
			infoTxt : jsonObjHot[0].infoTxt,
			id : jsonObjHot[0].id
		};

		var hotspotDetail = Alloy.createController("hotspotDetail", hotspotTxt).getView();
		Alloy.CFG.tabs.activeTab.open(hotspotDetail);
	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - showHotspot");
	}
}

//-----------------------------------------------------------
// Eventlistener för klick på trail eller hotspot
//-----------------------------------------------------------
baseMap.addEventListener('click', function(evt) {

	if (evt.clicksource == 'rightPane') {
		if (evt.annotation.name == 'hotspot') {
			showHotspot(evt.annotation.id);
		} else {
			showTrail(evt.annotation.id);
		}
	}
});

function showMapMenu() {
	Alloy.Globals.showMenuWidget();
}

<commit_msg>hgfds<commit_after>var args = arguments[0] || {};

var zoomedName = args.name;
var zoomColor = args.color;
var zoomLat = args.zoomlat;

var route;
var radius = 20;
//var MapModule = require('ti.map');
Alloy.Globals.MapModule = MapModule;

var infospotsNotVisible = true;
var hotspotsNotVisible = true;

var infospotsAnnotation;
var hotspotAnnotation;

var trailsCollection = getTrailsCollection();
var hotspotCollection = getHotspotCollection();
var jsonFileCollection = getJSONfiles();

//-----------------------------------------------------------
// Onload-funktioner för kartan
//-----------------------------------------------------------
// try {
showMap();
setRoutes();
displayTrailMarkers();
// } catch(e) {
// newError("Något gick fel när sidan skulle laddas, prova igen!", "Map - load page");
// }

//-----------------------------------------------------------
// Sätter ut alla vandringsleder på kartan
//-----------------------------------------------------------
function setRoutes() {
	try {
		trailsCollection.fetch({
			query : 'SELECT id, name, color FROM trailsModel'
		});

		var jsonObj = trailsCollection.toJSON();

		for (var i = 0; i < jsonObj.length; i++) {
			if (jsonObj[i].name != 'Båtleden') {
				var file = getFile(jsonObj[i].id);

				for (var u = 0; u < file.length; u++) {
					createMapRoutes(file[u].filename, jsonObj[i].name, jsonObj[i].color);
				}
			}
		}

	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "infoList - getInfoDetails");
	}
}

//-----------------------------------------------------------
// Hämtar JSON-fil för en vandringsled
//-----------------------------------------------------------
function getFile(id) {
	try {
		jsonFileCollection.fetch({
			query : 'SELECT filename FROM jsonFilesModel WHERE trailID ="' + id + '"'
		});

		var filename = jsonFileCollection.toJSON();
		return filename;
	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - getFile");
	}
}

//-----------------------------------------------------------
// Skapar en vandringsled på kartan
//-----------------------------------------------------------
function createMapRoutes(file, name, color) {
	try {
		var routes = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory + "/routes/" + file).read().text;
		var parsedRoute = JSON.parse(routes);

		var geoArray = [];
		geoArray.push(parsedRoute);

		for (var u = 0; u < geoArray.length; u++) {
			var coords = geoArray[0].features[0].geometry.paths[u];

			var points = new Array();

			for (var i = 0; i < coords.length; i++) {

				var c = {
					latitude : coords[i][1],
					longitude : coords[i][0]
				};
				points.push(c);
			}

			var route = {
				name : name,
				points : points,
				color : color,
				width : 3.0
			};
			baseMap.addRoute(MapModule.createRoute(route));
		}
	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - createMapRoutes");
	}
}

//-----------------------------------------------------------
// Läser in kartvyn
//-----------------------------------------------------------
function showMap() {
	try {
		baseMap = MapModule.createView({
			userLocation : true,
			mapType : MapModule.HYBRID_TYPE,
			animate : true,
			region : {
				latitude : 58.886775,
				longitude : 11.026024,
				latitudeDelta : 0.08,
				longitudeDelta : 0.08
			},
			height : '100%',
			width : Ti.UI.FILL
		});

		$.mapView.add(baseMap);

	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "Map - showMap");
	}
}

//-----------------------------------------------------------
// Visar markers för vandringslederna
//-----------------------------------------------------------
function displayTrailMarkers() {
	try {
		trailsCollection.fetch({
			query : 'SELECT name, pinLon, pinLat, area, length, color FROM trailsModel'
		});

		var jsonObjTrails = trailsCollection.toJSON();
		for (var i = 0; i < jsonObjTrails.length; i++) {

			color = jsonObjTrails[i].color.toUpperCase();
			Ti.API.info(JSON.stringify(color));

			var markerAnnotation = MapModule.createAnnotation({
				id : jsonObjTrails[i].name,
				latitude : jsonObjTrails[i].pinLat,
				longitude : jsonObjTrails[i].pinLon,
				title : jsonObjTrails[i].name,
				pincolor : MapModule.ANNOTATION_AZURE,
				color : '#000000',
				subtitle : jsonObjTrails[i].area + ', ' + jsonObjTrails[i].length,
				rightButton : '/pins/androidarrow2.png',
				name : 'trail',
				font : {
					fontFamily : 'Raleway-Light'
				}
			});

			// markerAnnotation.pincolor = Alloy.Globals.MapModule.ANNOTATION_GREEN;

			baseMap.addAnnotation(markerAnnotation);
		}
	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - displayTrailMarkers");
	}
}

//-----------------------------------------------------------
// Öppnar trailDetail med info om vald vandringsled
//-----------------------------------------------------------
function showTrail(myId) {
	try {
		trailsCollection.fetch({
			query : 'SELECT * FROM trailsModel where name ="' + myId + '"'
		});

		var jsonObjTr = trailsCollection.toJSON();

		var args = {
			id : jsonObjTr[0].id,
			title : myId,
			length : jsonObjTr[0].length,
			infoTxt : jsonObjTr[0].infoTxt,
			area : jsonObjTr[0].area,
			color : jsonObjTr[0].color,
			zoomlat : jsonObjTr[0].zoomLat,
			zoomlon : jsonObjTr[0].zoomLon
		};

		var trailDetail = Alloy.createController("trailDetail", args).getView();
		Alloy.CFG.tabs.activeTab.open(trailDetail);
	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - showTrail");
	}
}

//-----------------------------------------------------------
// Öppnar hotspotDetail med info om vald hotspot
//-----------------------------------------------------------
function showHotspot(myId) {
	try {
		hotspotCollection.fetch({
			query : 'SELECT id, infoTxt FROM hotspotModel where name = "' + myId + '"'
		});

		var jsonObjHot = hotspotCollection.toJSON();

		var hotspotTxt = {
			title : myId,
			infoTxt : jsonObjHot[0].infoTxt,
			id : jsonObjHot[0].id
		};

		var hotspotDetail = Alloy.createController("hotspotDetail", hotspotTxt).getView();
		Alloy.CFG.tabs.activeTab.open(hotspotDetail);
	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - showHotspot");
	}
}

//-----------------------------------------------------------
// Eventlistener för klick på trail eller hotspot
//-----------------------------------------------------------
baseMap.addEventListener('click', function(evt) {

	if (evt.clicksource == 'rightPane') {
		if (evt.annotation.name == 'hotspot') {
			showHotspot(evt.annotation.id);
		} else {
			showTrail(evt.annotation.id);
		}
	}
});

function showMapMenu() {
	Alloy.Globals.showMenuWidget();
}

<|endoftext|>


<commit_before>'use strict';

var drawChart = function(d3, svg, scope, iElement, iAttrs) {
    svg.selectAll("*").remove();

    if(scope.data == undefined) {
        return;
    }

    var height = scope.height,
        width = scope.width || d3.select(iElement[0])[0][0].offsetWidth - 20,
        translator = scope.labels;

    var barOrdering;
    if(scope.ordering) {
        barOrdering = scope.ordering.map(function(d) { return translator(d); });
    } else {
        barOrdering = dataset.map(function(d) { return translator(d.key); });
    }

    var factionNames = _.map(scope.data, function(f) { return f.faction;});

    var dataset = [];
    var scorecards = scope.data;
    var keys = _.keys(scorecards[0].simple);
    for(var i = 0; i < keys.length; i++) {
        var key = keys[i];
        if(_.contains(scope.ordering, key)) {
            var arr = [];
            for(var j = 0; j < scorecards.length; j++) {
                var sc = scorecards[j];
                arr.push({faction: sc.faction, points: sc.simple[key] || 0});
            }
            dataset.push({ source: key, factions: arr});
        }
    }

    svg.attr("width", width)
        .attr("height", height);

    var margin = { top: 30, bottom: 30, left: 100, right: 30};

    var barPadding = 5,
        oneLetterWidth = 15, // magic number, chosen from experience
        shortBarWidth = oneLetterWidth + 2*barPadding,
        yBottom = height - margin.bottom,
        yTop = margin.top,
        xLeft = margin.left,
        xRight = width - margin.right,
        textPadding = 5;

    // some numbers can be negative (e.g. leech). We'll take the absolute value
    // of all numbers for building the graphs, and use color styling to mark
    // these as negative

    var yScale = d3.scale.ordinal()
        .domain(barOrdering)
        .rangeRoundBands([yTop, yBottom], .1);

    var yScaleInner = d3.scale.ordinal()
        .domain(factionNames)
        .rangeRoundBands([0, yScale.rangeBand()], .1);

    var largestValue = d3.max(dataset, function(f) {
        return d3.max(f.factions, function(d) {
            return Math.abs(d.points);
        })
    });

    var xScale = d3.scale.linear()
        .domain([0, largestValue])
        .range([0, xRight - xLeft]);

    var barGroup = svg.selectAll("g")
        .data(dataset)
        .enter()
        .append("g")
        .attr("transform", function(d, i) {
            var y = yScale(translator(d.source));
            return "translate(" + xLeft + "," + y + ")";
        })
        // setting width/height on a group doesn't do anything as far as i can tell
        .attr("height", yScale.rangeBand())
        .attr("width", xRight - xLeft);

    var bars = barGroup.selectAll("g")
        .data(function(d) { return d.factions })
        .enter()
        .append("g");

    bars.append("rect")
        .attr("width", function(d) { return xScale(Math.abs(d.points)); })
        .attr("height", function(d) { return yScaleInner.rangeBand(); })
        .attr("y", function(d) { return yScaleInner(d.faction); })
        .attr("class", function(d) {
            if(d.faction.toUpperCase() == "CULTISTS" || d.faction.toUpperCase() == "HALFLINGS") {
                if(d.points >= 0) { return "bar-brown"; }
                else { return "bar-brown-negative"; }
            } else if(d.faction.toUpperCase() == "ENGINEERS" || d.faction.toUpperCase() == "DWARVES") {
                if(d.points >= 0) { return "bar-gray"; }
                else { return "bar-gray-negative"; }
            } else if(d.faction.toUpperCase() == "GIANTS" || d.faction.toUpperCase() == "CHAOSMAGICIANS") {
                if(d.points >= 0) { return "bar-red"; }
                else { return "bar-red-negative"; }
            } else if(d.faction.toUpperCase() == "MERMAIDS" || d.faction.toUpperCase() == "SWARMLINGS") {
                if(d.points >= 0) { return "bar-blue"; }
                else { return "bar-blue-negative"; }
            } else if(d.faction.toUpperCase() == "WITCHES" || d.faction.toUpperCase() == "AUREN") {
                if(d.points >= 0) { return "bar-green"; }
                else { return "bar-green-negative"; }
            } else if(d.faction.toUpperCase() == "NOMADS" || d.faction.toUpperCase() == "FAKIRS") {
                if(d.points >= 0) { return "bar-yellow"; }
                else { return "bar-yellow-negative"; }
            } else if(d.faction.toUpperCase() == "DARKLINGS" || d.faction.toUpperCase() == "ALCHEMISTS") {
                if(d.points >= 0) { return "bar-black"; }
                else { return "bar-black-negative"; }
            } else if(d.faction.toUpperCase() == "ICEMADIENS" || d.faction.toUpperCase() == "YETIS") {
                if(d.points >= 0) { return "bar-ice"; }
                else { return "bar-ice-negative"; }
            } else if(d.faction.toUpperCase() == "ACOLYTES" || d.faction.toUpperCase() == "DRAGONLORDS") {
                if(d.points >= 0) { return "bar-volcano"; }
                else { return "bar-volcano-negative"; }
            } else if(d.faction.toUpperCase() == "SHAPESHIFTERS" || d.faction.toUpperCase() == "RIVERWALKERS") {
                if(d.points >= 0) { return "bar-variable"; }
                else { return "bar-variable-negative"; }
            }
            // there shouldn't be another else
        });

    // score amount
    bars.append("text")
        .attr("x", function(d) { return xScale(Math.abs(d.points)) + 5; })
        .attr("y", function(d) {
            // +1 to move it down a bit
            return yScaleInner(d.faction) + (yScaleInner.rangeBand() / 2) + 1;
        })
        .text(function(d) { return d.points; })
        .attr("class", "bar-label");

    // faction names
    function clipText(d) {
        var self = d3.select(this),
            textLength = self.node().getComputedTextLength(),
            text = self.text();
        while ( ( textLength > self.attr('width') )&& text.length > 0) {
            text = text.slice(0, -1);
            self.text(text);
            textLength = self.node().getComputedTextLength();
        }
    }

    // IF the bar is long enough to fit at least 1 letter, paint the faction name
    // on top of the bar
    // ELSE paint the faction name on the right side of the score label
    bars.append("text")
    .attr("x", function(d) {
        var barWidth = xScale(Math.abs(d.points));
        if(barWidth >= shortBarWidth) {
            return barPadding;
        } else { // it's a short bar, paint beside the number
            return barWidth + 22; // magic number
        }
    })
    .attr("y", function(d) {
        // +1 to move it down a bit
        return yScaleInner(d.faction) + (yScaleInner.rangeBand() / 2) + 1;
    })
    .attr("width", function(d) {
        var barWidth = xScale(Math.abs(d.points));
        if(barWidth >= shortBarWidth) {
            return barWidth - 2*barPadding;
        } else {
            return width; // paint all, it's on the right side of the number
        }
    })
    .text(function(d) { return translator(d.faction); })
    .attr("class", function(d) {
        var barWidth = xScale(Math.abs(d.points));
        // a long bar, that's black (>0 points and darklings/alchemists)
        if(barWidth >= shortBarWidth && d.points > 0 &&
            (d.faction.toUpperCase() == "DARKLINGS" || d.faction.toUpperCase() == "ALCHEMISTS")) {
            return "bar-label-inverse";
        } else {
            return "bar-label";
        }
    })
    .each(clipText);

    var yAxis = d3.svg.axis()
        .scale(yScale)
        .orient("left");

    svg.append("g")
        .attr("class", "axis")
        .attr("transform", "translate(" + xLeft + ",0)")
        .call(yAxis)
        .selectAll("text");
}

angular.module('d3').directive('d3Scoregraph', ['d3', function(d3) {
    return {
        restrict: 'EA',
        scope: {
            data: '=', // binding to an angular object
            width: '@',    // static binding to a value
            height: '@',
            ordering: '=',
            labels: '='
        },
        link: function(scope, iElement, iAttrs) {
            var svg = d3.select(iElement[0])
                .append("svg");

            // use auto scaling for width
            if(scope.width == undefined) {
                svg.style("width", "100%");
            }

            // on window resize, re-render d3 canvas
            window.onresize = function() {
                return scope.$apply();
            };
            scope.$watch(function() {
                return angular.element(window)[0].innerWidth;
            }, function() {
                return scope.render();
            });

            // watch for data changes and re-render
            scope.$watch('data', function(newVals, oldVals) {
                return scope.render(newVals);
            }, true);

            // define render function
            scope.render = function() {
                drawChart(d3, svg, scope, iElement, iAttrs);
            };
        }
    };
}]);<commit_msg>Fixed Ice Maidens color not working correctly on horizontal graph (spelling typo)<commit_after>'use strict';

var drawChart = function(d3, svg, scope, iElement, iAttrs) {
    svg.selectAll("*").remove();

    if(scope.data == undefined) {
        return;
    }

    var height = scope.height,
        width = scope.width || d3.select(iElement[0])[0][0].offsetWidth - 20,
        translator = scope.labels;

    var barOrdering;
    if(scope.ordering) {
        barOrdering = scope.ordering.map(function(d) { return translator(d); });
    } else {
        barOrdering = dataset.map(function(d) { return translator(d.key); });
    }

    var factionNames = _.map(scope.data, function(f) { return f.faction;});

    var dataset = [];
    var scorecards = scope.data;
    var keys = _.keys(scorecards[0].simple);
    for(var i = 0; i < keys.length; i++) {
        var key = keys[i];
        if(_.contains(scope.ordering, key)) {
            var arr = [];
            for(var j = 0; j < scorecards.length; j++) {
                var sc = scorecards[j];
                arr.push({faction: sc.faction, points: sc.simple[key] || 0});
            }
            dataset.push({ source: key, factions: arr});
        }
    }

    svg.attr("width", width)
        .attr("height", height);

    var margin = { top: 30, bottom: 30, left: 100, right: 30};

    var barPadding = 5,
        oneLetterWidth = 15, // magic number, chosen from experience
        shortBarWidth = oneLetterWidth + 2*barPadding,
        yBottom = height - margin.bottom,
        yTop = margin.top,
        xLeft = margin.left,
        xRight = width - margin.right,
        textPadding = 5;

    // some numbers can be negative (e.g. leech). We'll take the absolute value
    // of all numbers for building the graphs, and use color styling to mark
    // these as negative

    var yScale = d3.scale.ordinal()
        .domain(barOrdering)
        .rangeRoundBands([yTop, yBottom], .1);

    var yScaleInner = d3.scale.ordinal()
        .domain(factionNames)
        .rangeRoundBands([0, yScale.rangeBand()], .1);

    var largestValue = d3.max(dataset, function(f) {
        return d3.max(f.factions, function(d) {
            return Math.abs(d.points);
        })
    });

    var xScale = d3.scale.linear()
        .domain([0, largestValue])
        .range([0, xRight - xLeft]);

    var barGroup = svg.selectAll("g")
        .data(dataset)
        .enter()
        .append("g")
        .attr("transform", function(d, i) {
            var y = yScale(translator(d.source));
            return "translate(" + xLeft + "," + y + ")";
        })
        // setting width/height on a group doesn't do anything as far as i can tell
        .attr("height", yScale.rangeBand())
        .attr("width", xRight - xLeft);

    var bars = barGroup.selectAll("g")
        .data(function(d) { return d.factions })
        .enter()
        .append("g");

    bars.append("rect")
        .attr("width", function(d) { return xScale(Math.abs(d.points)); })
        .attr("height", function(d) { return yScaleInner.rangeBand(); })
        .attr("y", function(d) { return yScaleInner(d.faction); })
        .attr("class", function(d) {
            if(d.faction.toUpperCase() == "CULTISTS" || d.faction.toUpperCase() == "HALFLINGS") {
                if(d.points >= 0) { return "bar-brown"; }
                else { return "bar-brown-negative"; }
            } else if(d.faction.toUpperCase() == "ENGINEERS" || d.faction.toUpperCase() == "DWARVES") {
                if(d.points >= 0) { return "bar-gray"; }
                else { return "bar-gray-negative"; }
            } else if(d.faction.toUpperCase() == "GIANTS" || d.faction.toUpperCase() == "CHAOSMAGICIANS") {
                if(d.points >= 0) { return "bar-red"; }
                else { return "bar-red-negative"; }
            } else if(d.faction.toUpperCase() == "MERMAIDS" || d.faction.toUpperCase() == "SWARMLINGS") {
                if(d.points >= 0) { return "bar-blue"; }
                else { return "bar-blue-negative"; }
            } else if(d.faction.toUpperCase() == "WITCHES" || d.faction.toUpperCase() == "AUREN") {
                if(d.points >= 0) { return "bar-green"; }
                else { return "bar-green-negative"; }
            } else if(d.faction.toUpperCase() == "NOMADS" || d.faction.toUpperCase() == "FAKIRS") {
                if(d.points >= 0) { return "bar-yellow"; }
                else { return "bar-yellow-negative"; }
            } else if(d.faction.toUpperCase() == "DARKLINGS" || d.faction.toUpperCase() == "ALCHEMISTS") {
                if(d.points >= 0) { return "bar-black"; }
                else { return "bar-black-negative"; }
            } else if(d.faction.toUpperCase() == "ICEMAIDENS" || d.faction.toUpperCase() == "YETIS") {
                if(d.points >= 0) { return "bar-ice"; }
                else { return "bar-ice-negative"; }
            } else if(d.faction.toUpperCase() == "ACOLYTES" || d.faction.toUpperCase() == "DRAGONLORDS") {
                if(d.points >= 0) { return "bar-volcano"; }
                else { return "bar-volcano-negative"; }
            } else if(d.faction.toUpperCase() == "SHAPESHIFTERS" || d.faction.toUpperCase() == "RIVERWALKERS") {
                if(d.points >= 0) { return "bar-variable"; }
                else { return "bar-variable-negative"; }
            }
            // there shouldn't be another else
        });

    // score amount
    bars.append("text")
        .attr("x", function(d) { return xScale(Math.abs(d.points)) + 5; })
        .attr("y", function(d) {
            // +1 to move it down a bit
            return yScaleInner(d.faction) + (yScaleInner.rangeBand() / 2) + 1;
        })
        .text(function(d) { return d.points; })
        .attr("class", "bar-label");

    // faction names
    function clipText(d) {
        var self = d3.select(this),
            textLength = self.node().getComputedTextLength(),
            text = self.text();
        while ( ( textLength > self.attr('width') )&& text.length > 0) {
            text = text.slice(0, -1);
            self.text(text);
            textLength = self.node().getComputedTextLength();
        }
    }

    // IF the bar is long enough to fit at least 1 letter, paint the faction name
    // on top of the bar
    // ELSE paint the faction name on the right side of the score label
    bars.append("text")
    .attr("x", function(d) {
        var barWidth = xScale(Math.abs(d.points));
        if(barWidth >= shortBarWidth) {
            return barPadding;
        } else { // it's a short bar, paint beside the number
            return barWidth + 22; // magic number
        }
    })
    .attr("y", function(d) {
        // +1 to move it down a bit
        return yScaleInner(d.faction) + (yScaleInner.rangeBand() / 2) + 1;
    })
    .attr("width", function(d) {
        var barWidth = xScale(Math.abs(d.points));
        if(barWidth >= shortBarWidth) {
            return barWidth - 2*barPadding;
        } else {
            return width; // paint all, it's on the right side of the number
        }
    })
    .text(function(d) { return translator(d.faction); })
    .attr("class", function(d) {
        var barWidth = xScale(Math.abs(d.points));
        // a long bar, that's black (>0 points and darklings/alchemists)
        if(barWidth >= shortBarWidth && d.points > 0 &&
            (d.faction.toUpperCase() == "DARKLINGS" || d.faction.toUpperCase() == "ALCHEMISTS")) {
            return "bar-label-inverse";
        } else {
            return "bar-label";
        }
    })
    .each(clipText);

    var yAxis = d3.svg.axis()
        .scale(yScale)
        .orient("left");

    svg.append("g")
        .attr("class", "axis")
        .attr("transform", "translate(" + xLeft + ",0)")
        .call(yAxis)
        .selectAll("text");
}

angular.module('d3').directive('d3Scoregraph', ['d3', function(d3) {
    return {
        restrict: 'EA',
        scope: {
            data: '=', // binding to an angular object
            width: '@',    // static binding to a value
            height: '@',
            ordering: '=',
            labels: '='
        },
        link: function(scope, iElement, iAttrs) {
            var svg = d3.select(iElement[0])
                .append("svg");

            // use auto scaling for width
            if(scope.width == undefined) {
                svg.style("width", "100%");
            }

            // on window resize, re-render d3 canvas
            window.onresize = function() {
                return scope.$apply();
            };
            scope.$watch(function() {
                return angular.element(window)[0].innerWidth;
            }, function() {
                return scope.render();
            });

            // watch for data changes and re-render
            scope.$watch('data', function(newVals, oldVals) {
                return scope.render(newVals);
            }, true);

            // define render function
            scope.render = function() {
                drawChart(d3, svg, scope, iElement, iAttrs);
            };
        }
    };
}]);<|endoftext|>


<commit_before>'use strict';

const Utils = require('./utils');
const Reporting = require('./reporting');

// Internal health checks and monitoring.

// Promise a bool, true if this is an ok time to reload.
function safeToReload() {
  return new Promise((resolve, reject) => {
    chrome.tabs.query({url: 'chrome-extension://blbompphddfibggfmmfcgjjoadebinem/*'}, Utils.unlessError(tabs => {
      resolve(tabs.length === 0);
    }, e => {
      reject(e);
    }));
  });
}

exports.handleDeauth = function handleDeauth() {
  safeToReload().then(isSafe => {
    if (isSafe) {
      console.warn('deauth reload in 10s!');
      Reporting.reportReload('success', 'deauth');
      setTimeout(chrome.runtime.reload, 10000);
    } else {
      console.info('deauth reload requested, but manager in use; not reloading');
      Reporting.reportReload('failure', 'deauth');
    }
  });
};
<commit_msg>don't reload within first 10m of startup [closes #166]<commit_after>'use strict';

const Utils = require('./utils');
const Reporting = require('./reporting');

const START_TIME_MS = new Date().getTime();
const MIN_RELOAD_TIME_MS = 1000 * 60 * 10;  // 10m

// Internal health checks and monitoring.

// Promise a bool, true if this is an ok time to reload.
function safeToReload() {
  return new Promise((resolve, reject) => {
    chrome.tabs.query({url: 'chrome-extension://blbompphddfibggfmmfcgjjoadebinem/*'}, Utils.unlessError(tabs => {
      let safe = true;
      const sessionTime = new Date().getTime() - START_TIME_MS;
      if (tabs.length !== 0) {
        console.info('not safe to reload: manager active');
        safe = false;
      } else if (sessionTime < MIN_RELOAD_TIME_MS) {
        console.info('not safe to reload: too soon after load', sessionTime / 1000);
        safe = false;
      }
      resolve(safe);
    }, e => {
      reject(e);
    }));
  });
}

exports.handleDeauth = function handleDeauth() {
  safeToReload().then(isSafe => {
    if (isSafe) {
      console.warn('deauth reload in 10s!');
      Reporting.reportReload('success', 'deauth');
      setTimeout(chrome.runtime.reload, 10000);
    } else {
      console.info('deauth reload requested, but not safe time; not reloading');
      Reporting.reportReload('failure', 'deauth');
    }
  });
};
<|endoftext|>