<commit_before>var ejs = require('elastic.js'),
    nc = require('elastic.js/elastic-node-client'),
    express = require('express'),
    app = express();

ejs.client = nc.NodeClient('localhost', '9200');

app.use(express.json());

app.get('/', function (req, res) {
    var termQuery = ejs.TermQuery("message", "hello");

    /* a function to display results */
    var resultsCallBack = function(results) {
        if (results.hits) {
            var hits = results.hits.hits;
            for (var i = 0; i > hits.length; i++) {
                var hit = hits[i];
                console.log(hit._source.message);
            }
        }
    };

    /* execute the request */
    var r = ejs.Request()
        .collections("twitter")
        .types("tweet")
        .query(termQuery);

    r.doSearch(resultsCallBack);

    res.json('boom');
});

app.use(express.logger('dev'));

var allowCrossDomain = function (req, res, next) {
    if (!req.get('Origin')) {
        return next();
    }

    res.set('Access-Control-Allow-Origin', '*');
    res.set('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.set('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
    // res.set('Access-Control-Allow-Max-Age', 3600);

    if ('OPTIONS' == req.method) {
        return res.send(200);
    }

    next();
};

app.listen(3000);
<commit_msg>Cleaning up Petter's awful code<commit_after>var ejs = require('elastic.js'),
    nc = require('elastic.js/elastic-node-client'),
    express = require('express'),
    app = express();

ejs.client = nc.NodeClient('localhost', '9200');

app.use(express.json());

app.get('/', function (req, res) {
    var termQuery = ejs.TermQuery('message', 'hello'),

        /* a function to display results */
        resultsCallBack = function (results) {
            if (results.hits) {
                var hits = results.hits.hits;

                hits.forEach(function (hit) {
                    console.log(hit._source.message);
                });
            }
        },

        /* execute the request */
        r = ejs.Request()
                .collections('twitter')
                .types('tweet')
                .query(termQuery);

    r.doSearch(resultsCallBack);

    res.json('boom');
});

app.use(express.logger('dev'));

var allowCrossDomain = function (req, res, next) {
    if (!req.get('Origin')) {
        return next();
    }

    res.set('Access-Control-Allow-Origin', '*');
    res.set('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.set('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
    // res.set('Access-Control-Allow-Max-Age', 3600);

    if ('OPTIONS' == req.method) {
        return res.send(200);
    }

    next();
};

app.listen(3000);
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import { storiesOf, action } from '@kadira/storybook'
import RealSettingOption from '.'

class SettingOption extends React.Component {
  static propTypes = {
    id: PropTypes.any.isRequired,
    label: PropTypes.string.isRequired,
    active: PropTypes.bool.isRequired,
    updateSetting: PropTypes.func.isRequired
  }
  constructor (props) {
    super(props)
    this.state = {active:props.active}
  }
  updateSetting = (id, active) => {
    // record the check state in the wrapper
    this.setState({ active:active })
    // call the real one that was passed in
    this.props.updateSetting( id, active)
  }
  render () {
    return (
        <RealSettingOption
            updateSetting={this.updateSetting}
            id={this.props.id}
            label={this.props.label}
            active={this.state.active} />
    )
  }
}

const updateSetting = action('updateSetting')

storiesOf('SettingOption', module)
  .add('default', () => (
      <SettingOption
          id='list-item-1'
          label='List item 1'
          active
          updateSetting={action('updateSetting')} />
  ))
<commit_msg>Update SettingOption.story.js<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import { storiesOf, action } from '@kadira/storybook'
import RealSettingOption from '.'

class SettingOption extends React.Component {
  static propTypes = {
    id: PropTypes.any.isRequired,
    label: PropTypes.string.isRequired,
    active: PropTypes.bool.isRequired,
    updateSetting: PropTypes.func.isRequired
  }
  constructor (props) {
    super(props)
    this.state = {active:props.active}
  }
  updateSetting = (id, active) => {
    // record the check state in the wrapper
    this.setState({ active:active })
    // call the real one that was passed in
    this.props.updateSetting( id, active)
  }
  render () {
    return (
        <RealSettingOption
            updateSetting={this.updateSetting}
            id={this.props.id}
            label={this.props.label}
            active={this.state.active} />
    )
  }
}

storiesOf('SettingOption', module)
  .add('default', () => (
      <SettingOption
          id='list-item-1'
          label='List item 1'
          active
          updateSetting={action('updateSetting')} />
  ))
<|endoftext|>


<commit_before>'use strict';

Physijs.scripts.worker = 'evo_js/physijs/physijs_worker.js';
Physijs.scripts.ammo = 'ammo.js';

function simulator() {

	var Robot;

	var ground_material, projector, renderer, render_stats,
		scene, ground, light, camera, box, steps, MAX_STEPS = 1000,
		scale_factor = 1, reset_counter = 0;

	// Origin Ball Material
	var origin_ball_material = new THREE.MeshLambertMaterial();

	// var breadcrumb_ball_material = new THREE.MeshLambertMaterial();
	// breadcrumb_ball_material.color = new THREE.Color("rgb(0,255,255)");

	// Ball at the origin.
	var origin_ball = new THREE.Mesh(new THREE.SphereGeometry(1,12,12), origin_ball_material);
	origin_ball_material.color = new THREE.Color("rgb(0,0,255)");

	// var breadcrumb_balls = [];
	// for (var i = 0; i < 10; ++i ) {
	// 	breadcrumb_balls.push(new THREE.Mesh(new THREE.SphereGeometry(0.5,12,12), breadcrumb_ball_material));
	// 	breadcrumb_balls[i].position.set( 0,0,0 );
	// }

	var ground_material = Physijs.createMaterial(
				new THREE.MeshLambertMaterial( ),
				.99, // high friction
				.4 // low restitution
			);
	var ground_geometry = new THREE.CubeGeometry(4000, 0.2, 4000);

	var radius   = 1,
    	segments = 64;
    var floor_mesh = new THREE.Mesh( new THREE.CircleGeometry( radius, segments ),
    								 new THREE.LineBasicMaterial( { transparent: true, opacity: 0.1, color: 0x0000ff } ) );
    floor_mesh.rotation.x = -Math.PI/2;
    floor_mesh.position.set ( 0,0.11,0 );

    // Check for stalling
    var stalled_counter = 100;

    this.scene = function() {
    	return scene;
    }

	this.initScene = function( div_to_place , robot) {

		var container_width = document.getElementById(div_to_place).offsetWidth;
		var container_height = 0.5 * document.getElementById(div_to_place).offsetHeight;

		Robot = robot;

		projector = new THREE.Projector;

		var canvas = document.createElement('canvas');
		canvas.id     = "Evolution_Canvas";
		canvas.width  = container_width;
		canvas.height = container_height;

		renderer = new THREE.WebGLRenderer({canvas: canvas, antialias: true });
		renderer.setSize( container_width, container_height );
		renderer.shadowMapEnabled = true;
		renderer.shadowMapSoft = true;
		document.getElementById( div_to_place ).insertBefore( renderer.domElement , document.getElementById( div_to_place ).childNodes[0]);

		initScene(true);
	};

	var initScene = function(full_init) {
		if (!scene) {
			scene = new Physijs.Scene;
			scene.addEventListener(
				'update',
				function() {

					// Check for stalled condition.
					if(Robot.is_stalled()) {
						stalled_counter -= 1;
					} else {
						stalled_counter = 100;
					}

					// Set the camera to follow the center body of the robot.
					var pos = Robot.position();

					camera.position.set(60+pos.x,50,60+pos.z);
					light.position.set( 20+pos.x, 40, 15+pos.z );
					light.target.position.set( scene.position.x+pos.x,scene.position.y+pos.y,scene.position.z+pos.z );

					// Update the breadcrumb trail.
					// if (steps % 100 == 0 && steps/100 < breadcrumb_balls.length) {
					// 	breadcrumb_balls[steps/100].position.set( pos.x,0,pos.z );
					// }

					// Update the robot.
					Robot.update(steps);

					steps += 1;

					if (steps > MAX_STEPS || stalled_counter == 0) {
						// Get the position of the robot
						var pos = Robot.position();

						Robot.setGenome(EvoInterface.GA.newRobot(pos.x,pos.y,pos.z));

						// Reset simulation parameters.
						steps = 0;
						resetBodies();
						stalled_counter = 100;
					}

					scene.simulate( 0.005, 1 );
				}
			);

			camera = new THREE.PerspectiveCamera(
				35,
				document.getElementById("Evolution_Canvas").width / document.getElementById("Evolution_Canvas").height,
				1,
				1000
			);
			camera.position.set( 60, 50, 60 );
			camera.lookAt( scene.position );
			scene.add( camera );

			// Light
			light = new THREE.DirectionalLight( 0xFFFFFF );
			light.position.set( 20, 40, -15 );
			light.target.position.copy( scene.position );
			light.castShadow = true;
			light.shadowCameraLeft = -60;
			light.shadowCameraTop = -60;
			light.shadowCameraRight = 60;
			light.shadowCameraBottom = 60;
			light.shadowCameraNear = 20;
			light.shadowCameraFar = 200;
			light.shadowBias = -.0001
			light.shadowMapWidth = light.shadowMapHeight = 2048;
			light.shadowDarkness = .7;
			scene.add( light );

			// Grid on ground.
			var grid = new THREE.GridHelper(4000, 10);
			grid.position = new THREE.Vector3(0,0.51,0);
			scene.add(grid);

			// Ball at the origin.
			scene.add(origin_ball);

			// // Add breadcrumbs.
			// for (var i = 0; i < 10; ++i ) {
			// 	scene.add( breadcrumb_balls[i] );
			// }

			// Circle to indicate how far the best individual has gone.
			scene.add( floor_mesh );

			// Initialize the first genome for the robot.
			Robot.setGenome(EvoInterface.GA.getGenome());
		}
		if (full_init) {
			// Ground
			ground = new Physijs.BoxMesh(
				ground_geometry,
				ground_material,
				0 // mass
			);

			// Set the collision flag and mask for the ground.
			ground._physijs.collision_type = 1;
			ground._physijs.collision_masks = 4;

			ground.receiveShadow = true;
			scene.add( ground );

			scene.setFixedTimestep = 0.005;
			scene.setGravity(new THREE.Vector3( 0, -12, 0 ));

			EvoInterface.Environment.createTerrain(false);
		}

		Robot.createRobot(false);

		steps = 0;
	}

	this.launchSimulation = function(gen) {
		Robot.setGenome(gen);

		requestAnimationFrame( render );
		scene.simulate( 0.005, 1);
	};

	// Reset the physics worker.  Needed as ammo.js is
	// leaky.  This allows for prolonged runs.
	var resetWorker = function() {
		// Remove the ground as we reset it.
		scene.remove(ground);

		scene.replaceWorker();
	};

	// Remove an object and all associated THREE.JS objects
	// during a resetWorker situation.
	var disposeObject = function(obj) {
	    if (obj instanceof THREE.Mesh) {
	        if (obj.material.map instanceof THREE.Texture) {
	            obj.material.map.dispose();
	        }
	        obj.material.dispose();
	        if (!obj.isConnector) {
	            obj.geometry.dispose();
	        }
	    } else if (obj instanceof THREE.AxisHelper) {
	        obj.material.dispose();
	        obj.geometry.dispose();
	    }
	    if (obj.children) {
	        for (var i = 0; i < obj.children.length; i++) {
	            disposeObject(obj.children[i]);
	        }
	    }
	};

	// Remove an object from the simulation.
	var removeObject = function(obj) {
		scene.remove(obj);
        obj.removeAllEvents && obj.removeAllEvents();
        disposeObject(obj);
	}

	// Only clear objects with associated physics when resetting the
	// worker.
	var clearObjects = function() {
		for (var i = 0; i < scene.children.length; ++i) {
			var o = scene.children[i];
			if (!(o instanceof THREE.Mesh) &&
				!(o instanceof THREE.PerspectiveCamera) &&
				!(o instanceof THREE.OrthographicCamera) &&
				!(o instanceof THREE.DirectionalLight) &&
				!(o instanceof THREE.Object3D) &&
				!(o instanceof THREE.GridHelper)) {
		        removeObject(o);
		    }
		}
	};

	// Reset the state of the simulation.
	var resetBodies = function() {

		// // Reset the position of the breadcrumb trail.
		// for ( var i = 0; i < breadcrumb_balls.length; ++i ) {
		// 	breadcrumb_balls[i].position.set( 0,0,0 );
		// }

		// Remove the robot.
		Robot.removeRobot();

		// Update the floor circle to the best individual.
		floor_mesh.scale.x = 1/scale_factor;
		floor_mesh.scale.y = 1/scale_factor;
		scale_factor = EvoInterface.GA.requestBestFitness();
		floor_mesh.scale.x = scale_factor;
		floor_mesh.scale.y = scale_factor;

		if (reset_counter == 1000) {
			clearObjects();
			resetWorker();
			reset_counter = 0;
			initScene(true);
		} else {
			initScene(false);
		}
		reset_counter += 1;
	};

	var render = function() {
		// console.log(renderer.domElement);
		window.requestAnimationFrame( render );
		renderer.render( scene, camera );
	};
}

var Simulator = Simulator || new simulator();<commit_msg>Fixed issue with width and border sizing on canvas causing graphical error.<commit_after>'use strict';

Physijs.scripts.worker = 'evo_js/physijs/physijs_worker.js';
Physijs.scripts.ammo = 'ammo.js';

function simulator() {

	var Robot;

	var ground_material, projector, renderer, render_stats,
		scene, ground, light, camera, box, steps, MAX_STEPS = 1000,
		scale_factor = 1, reset_counter = 0;

	// Origin Ball Material
	var origin_ball_material = new THREE.MeshLambertMaterial();

	// var breadcrumb_ball_material = new THREE.MeshLambertMaterial();
	// breadcrumb_ball_material.color = new THREE.Color("rgb(0,255,255)");

	// Ball at the origin.
	var origin_ball = new THREE.Mesh(new THREE.SphereGeometry(1,12,12), origin_ball_material);
	origin_ball_material.color = new THREE.Color("rgb(0,0,255)");

	// var breadcrumb_balls = [];
	// for (var i = 0; i < 10; ++i ) {
	// 	breadcrumb_balls.push(new THREE.Mesh(new THREE.SphereGeometry(0.5,12,12), breadcrumb_ball_material));
	// 	breadcrumb_balls[i].position.set( 0,0,0 );
	// }

	var ground_material = Physijs.createMaterial(
				new THREE.MeshLambertMaterial( ),
				.99, // high friction
				.4 // low restitution
			);
	var ground_geometry = new THREE.CubeGeometry(4000, 0.2, 4000);

	var radius   = 1,
    	segments = 64;
    var floor_mesh = new THREE.Mesh( new THREE.CircleGeometry( radius, segments ),
    								 new THREE.LineBasicMaterial( { transparent: true, opacity: 0.1, color: 0x0000ff } ) );
    floor_mesh.rotation.x = -Math.PI/2;
    floor_mesh.position.set ( 0,0.11,0 );

    // Check for stalling
    var stalled_counter = 100;

    this.scene = function() {
    	return scene;
    }

	this.initScene = function( div_to_place , robot) {

		var container_width = document.getElementById(div_to_place).offsetWidth - 8;
		var container_height = 0.5 * document.getElementById(div_to_place).offsetHeight;

		Robot = robot;

		projector = new THREE.Projector;

		var canvas = document.createElement('canvas');
		canvas.id     = "Evolution_Canvas";
		canvas.width  = container_width;
		canvas.height = container_height;

		renderer = new THREE.WebGLRenderer({canvas: canvas, antialias: true });
		renderer.setSize( container_width, container_height );
		renderer.shadowMapEnabled = true;
		renderer.shadowMapSoft = true;
		document.getElementById( div_to_place ).insertBefore( renderer.domElement , document.getElementById( div_to_place ).childNodes[0]);

		initScene(true);
	};

	var initScene = function(full_init) {
		if (!scene) {
			scene = new Physijs.Scene;
			scene.addEventListener(
				'update',
				function() {

					// Check for stalled condition.
					if(Robot.is_stalled()) {
						stalled_counter -= 1;
					} else {
						stalled_counter = 100;
					}

					// Set the camera to follow the center body of the robot.
					var pos = Robot.position();

					camera.position.set(60+pos.x,50,60+pos.z);
					light.position.set( 20+pos.x, 40, 15+pos.z );
					light.target.position.set( scene.position.x+pos.x,scene.position.y+pos.y,scene.position.z+pos.z );

					// Update the breadcrumb trail.
					// if (steps % 100 == 0 && steps/100 < breadcrumb_balls.length) {
					// 	breadcrumb_balls[steps/100].position.set( pos.x,0,pos.z );
					// }

					// Update the robot.
					Robot.update(steps);

					steps += 1;

					if (steps > MAX_STEPS || stalled_counter == 0) {
						// Get the position of the robot
						var pos = Robot.position();

						Robot.setGenome(EvoInterface.GA.newRobot(pos.x,pos.y,pos.z));

						// Reset simulation parameters.
						steps = 0;
						resetBodies();
						stalled_counter = 100;
					}

					scene.simulate( 0.005, 1 );
				}
			);

			camera = new THREE.PerspectiveCamera(
				35,
				document.getElementById("Evolution_Canvas").width / document.getElementById("Evolution_Canvas").height,
				1,
				1000
			);
			camera.position.set( 60, 50, 60 );
			camera.lookAt( scene.position );
			scene.add( camera );

			// Light
			light = new THREE.DirectionalLight( 0xFFFFFF );
			light.position.set( 20, 40, -15 );
			light.target.position.copy( scene.position );
			light.castShadow = true;
			light.shadowCameraLeft = -60;
			light.shadowCameraTop = -60;
			light.shadowCameraRight = 60;
			light.shadowCameraBottom = 60;
			light.shadowCameraNear = 20;
			light.shadowCameraFar = 200;
			light.shadowBias = -.0001
			light.shadowMapWidth = light.shadowMapHeight = 2048;
			light.shadowDarkness = .7;
			scene.add( light );

			// Grid on ground.
			var grid = new THREE.GridHelper(4000, 10);
			grid.position = new THREE.Vector3(0,0.51,0);
			scene.add(grid);

			// Ball at the origin.
			scene.add(origin_ball);

			// // Add breadcrumbs.
			// for (var i = 0; i < 10; ++i ) {
			// 	scene.add( breadcrumb_balls[i] );
			// }

			// Circle to indicate how far the best individual has gone.
			scene.add( floor_mesh );

			// Initialize the first genome for the robot.
			Robot.setGenome(EvoInterface.GA.getGenome());
		}
		if (full_init) {
			// Ground
			ground = new Physijs.BoxMesh(
				ground_geometry,
				ground_material,
				0 // mass
			);

			// Set the collision flag and mask for the ground.
			ground._physijs.collision_type = 1;
			ground._physijs.collision_masks = 4;

			ground.receiveShadow = true;
			scene.add( ground );

			scene.setFixedTimestep = 0.005;
			scene.setGravity(new THREE.Vector3( 0, -12, 0 ));

			EvoInterface.Environment.createTerrain(false);
		}

		Robot.createRobot(false);

		steps = 0;
	}

	this.launchSimulation = function(gen) {
		Robot.setGenome(gen);

		requestAnimationFrame( render );
		scene.simulate( 0.005, 1);
	};

	// Reset the physics worker.  Needed as ammo.js is
	// leaky.  This allows for prolonged runs.
	var resetWorker = function() {
		// Remove the ground as we reset it.
		scene.remove(ground);

		scene.replaceWorker();
	};

	// Remove an object and all associated THREE.JS objects
	// during a resetWorker situation.
	var disposeObject = function(obj) {
	    if (obj instanceof THREE.Mesh) {
	        if (obj.material.map instanceof THREE.Texture) {
	            obj.material.map.dispose();
	        }
	        obj.material.dispose();
	        if (!obj.isConnector) {
	            obj.geometry.dispose();
	        }
	    } else if (obj instanceof THREE.AxisHelper) {
	        obj.material.dispose();
	        obj.geometry.dispose();
	    }
	    if (obj.children) {
	        for (var i = 0; i < obj.children.length; i++) {
	            disposeObject(obj.children[i]);
	        }
	    }
	};

	// Remove an object from the simulation.
	var removeObject = function(obj) {
		scene.remove(obj);
        obj.removeAllEvents && obj.removeAllEvents();
        disposeObject(obj);
	}

	// Only clear objects with associated physics when resetting the
	// worker.
	var clearObjects = function() {
		for (var i = 0; i < scene.children.length; ++i) {
			var o = scene.children[i];
			if (!(o instanceof THREE.Mesh) &&
				!(o instanceof THREE.PerspectiveCamera) &&
				!(o instanceof THREE.OrthographicCamera) &&
				!(o instanceof THREE.DirectionalLight) &&
				!(o instanceof THREE.Object3D) &&
				!(o instanceof THREE.GridHelper)) {
		        removeObject(o);
		    }
		}
	};

	// Reset the state of the simulation.
	var resetBodies = function() {

		// // Reset the position of the breadcrumb trail.
		// for ( var i = 0; i < breadcrumb_balls.length; ++i ) {
		// 	breadcrumb_balls[i].position.set( 0,0,0 );
		// }

		// Remove the robot.
		Robot.removeRobot();

		// Update the floor circle to the best individual.
		floor_mesh.scale.x = 1/scale_factor;
		floor_mesh.scale.y = 1/scale_factor;
		scale_factor = EvoInterface.GA.requestBestFitness();
		floor_mesh.scale.x = scale_factor;
		floor_mesh.scale.y = scale_factor;

		if (reset_counter == 1000) {
			clearObjects();
			resetWorker();
			reset_counter = 0;
			initScene(true);
		} else {
			initScene(false);
		}
		reset_counter += 1;
	};

	var render = function() {
		// console.log(renderer.domElement);
		window.requestAnimationFrame( render );
		renderer.render( scene, camera );
	};
}

var Simulator = Simulator || new simulator();<|endoftext|>


<commit_before>require('@google-cloud/debug-agent').start({ allowExpressions: true });

var functions = require('firebase-functions');
const admin = require('firebase-admin');
const q = require('q');
admin.initializeApp(functions.config().firebase);

exports.obtainIdentityVerification = functions.https.onRequest((req, res) => {
    console.log("Got: ", req.method);
    if (req.method !== 'POST') {
        res.status(404).send('Method not supported');
        return;
    }
    console.log(req.body);
    const email = req.body.email;
    verifyIdentity(email).then(({isVerified, message}) => {
        let answer = {
            access: isVerified,
            message: message || ''
        };
        answer = JSON.stringify(answer);
        console.log("Sent: ", answer);
        res.status(200).send(answer);
    })
    .catch((error) => {
        console.log("Failed to verify user: ", error);
        res.status(200).send({
            access: false,
            message: "internal error"
        });
    });
});

exports.obtainAdminPermission = functions.https.onRequest((req, res) => {
    console.log("Got: ", req.method);
    if (req.method !== 'POST') {
        res.status(404).send('Method not supported');
        return;
    }
    console.log(req.body);
    const email = req.body.email;
    const computerUID = req.body.computerUID;
    obtainPermission(email, computerUID).then(({isPermitted, message}) => {
        let answer = {
            access: isPermitted,
            message: message || ''
        };
        answer = JSON.stringify(answer);
        console.log("Sent: ", answer);
        res.status(200).send(answer);
    }).catch((error) => {
        console.log("Failed to verify user: ", error);
        res.status(200).send({
            access: false,
            message: "internal error"
        });
    });
});

exports.connectivityCheck = functions.https.onRequest((req, res) => {
    console.log("Got: ", req.method);
    res.status(200).send("OK");
});

function obtainPermission(email, computerUID) {
    let def = q.defer();

    getUIDByEmail(email).then((userUID) => {
        return getTokenByUID(userUID);
    }).then(({token, userUID}) => {
        return sendNotification(token, userUID, computerUID);
    }).then((userUID) => {
        def.resolve({isPermitted: true});
    }).catch((error) => {
        console.log("Error in getting permission: ", error);
        def.reject();
    });

    return def.promise;
}

function verifyIdentity(email) {
    let def = q.defer();
    getUIDByEmail(email).then((userUID) => {
        return getTokenByUID(userUID);
    }).then(({token, userUID}) => {
        return sendIdentityVerificationRequest(token, userUID);
    }).then((userUID) => {
        return obtainIdentityVerification(userUID);
    }).then(({identityVerification, message}) =>{
        def.resolve({isVerified: identityVerification, message: message});
    }).catch((error) => {
        console.log("Error in verification: ", error);
        def.reject();
    });

    return def.promise;
}

function getUIDByEmail(email) {
    console.log("Getting UID of ", email);
    let def = q.defer();
    admin.auth().getUserByEmail(email)
        .then(userRecored => {
            console.log("Got UID: ", userRecored.uid);
            def.resolve(userRecored.uid);
        }).catch(error => {
            console.log("Error getting UID: ", error);
            def.reject();
        });
    return def.promise;
}

function getTokenByUID(userUID) {
    console.log("Getting token of ", userUID);
    let def = q.defer();
    if (userUID === undefined) {
        def.reject();
        return def.promise;
    }
    admin.database().ref('Users').child(userUID).child('deviceToken')
        .on('value', snapshot => {
            console.log("Got token: ", snapshot.val());
            def.resolve({token: snapshot.val(), userUID: userUID});
        });
    return def.promise;
}

function sendNotification(token, userUID, computerUID) {
    console.log("Sending notification to: ", token);
    let def = q.defer();

    createPermissionRequestPayload(userUID, computerUID).then(payload => {
        console.log("Sending: ", payload);
        admin.messaging().sendToDevice(token, payload)
            .then(function (response) {
                // See the MessagingDevicesResponse reference documentation for the contents of response.
                console.log("Successfully sent message:", response);
                def.resolve(userUID);
            })
            .catch(function (error) {
                console.log("Error sending message:", error);
                def.reject();
            });
    });

    return def.promise;
}

function createVerificationPayload(userUID) {
    let def = q.defer();
    admin.auth().getUser(userUID).then(user => {
        console.log("User: ", user.toJSON());
        let payload =
            {
                data: {
                    priority: 'high',
                    userEmail: user.email,
                    userName: user.displayName,
                    userPhotoUrl: user.photoURL
                }
            };
        def.resolve(payload);
    });
    return def.promise;
}

function sendIdentityVerificationRequest(token, userUID){
    console.log("Sending verification request to: ", token);
    let def = q.defer();
    createVerificationPayload(userUID).then(payload => {
        console.log("Sending: ", payload);
        admin.messaging().sendToDevice(token, payload)
            .then(function (response) {
                console.log("Successfully sent message:", response);
                def.resolve(userUID);
            })
            .catch(function (error) {
                console.log("Error sending message:", error);
                def.reject();
            });
    });
    return def.promise;
}

/**
 * Listens for change in the database (IdentityVerifications/{userUID}).
 * If there is no change in 'timeout' milliseconds,
 * listening stops and identityVerification = false, message = 'timeout reached'
 * @param {string} userUID
 * @return {JSON} {boolean} identityVerification, {string} massage
**/
function obtainIdentityVerification(userUID){
    let def = q.defer();
    console.log(`Waiting for verification from ${userUID}`);
    let timeout = 1000 * 120;
    let verificationRef = admin.database().ref("IdentityVerifications");

    console.log(`Started watchdog for ${timeout} milliseconds, on ${verificationRef}`);
    let timeoutGuard;
    timeoutGuard = setTimeout(() => {
        console.log("Reached timeout");
        verificationRef.off(); //Remove listener
        def.resolve({identityVerification: false, message: 'Reached timeout'});
    }, timeout);

    verificationRef.on('child_added', snapshot => {
        let identityFlag = snapshot.val();
        console.log(`Found value change: ${snapshot.key}:${identityFlag}`);
        if (snapshot.key !== userUID){
            console.log(`Got irrelevant trigger`);
            return;
        }
        if(identityFlag){
            def.resolve({identityVerification: true});
        }else{
            def.resolve({identityVerification: false, message: 'Rejected by user'});
        }
        console.log(`Finished handling database change, promise state is ${def.promise.inspect().state}`);
        verificationRef.child(userUID).remove(); //Handle promise
        clearTimeout(timeoutGuard);
    });
    return def.promise;
}

function createPermissionRequestPayload(userUID, computerUID) {
    console.log("Creating payload about user: ", userUID);
    let def = q.defer();
    admin.auth().getUser(userUID).then(user => {
        console.log("User: ", user.toJSON());
        console.log(user.displayName, user.email, user.photoURL);
        let payload =
            {
                data: {
                    priority: 'high',
                    userEmail: user.email,
                    userName: user.displayName,
                    userPhotoUrl: user.photoURL,
                    computer: computerUID,
                }
            };
        console.log("Created payload: ", payload);
        def.resolve(payload);
    }).catch(error => {
        console.log("Failed to create payload: ", error);
        def.reject();
    });
    return def.promise;
}

// function createNotification(title, body, priority = "high") {
//     return {
//         notification: {
//             priority: "high",
//             title: title,
//             body: body
//         }
//     };
// }<commit_msg>Made some clean up. On result true there will be no message.<commit_after>require('@google-cloud/debug-agent').start({ allowExpressions: true });

var functions = require('firebase-functions');
const admin = require('firebase-admin');
const q = require('q');
admin.initializeApp(functions.config().firebase);
//TODO handle notification screen after time out
exports.obtainIdentityVerification = functions.https.onRequest((req, res) => {
    console.log("Got: ", req.method);
    if (req.method !== 'POST') {
        res.status(404).send('Method not supported');
        return;
    }
    console.log(req.body);
    const email = req.body.email;
    verifyIdentity(email).then(({isVerified, message}) => {
        let answer = {
            access: isVerified,
            message: message
        };
        answer = JSON.stringify(answer);
        console.log("Sent: ", answer);
        res.status(200).send(answer);
    })
    .catch(error => {
        console.log("Failed to verify user: ", error);
        res.status(200).send({
            access: false,
            message: "internal error"
        });
    });
});

exports.obtainAdminPermission = functions.https.onRequest((req, res) => {
    console.log("Got: ", req.method);
    if (req.method !== 'POST') {
        res.status(404).send('Method not supported');
        return;
    }
    console.log(req.body);
    const email = req.body.email;
    const computerUID = req.body.computerUID;
    obtainPermission(email, computerUID).then(({isPermitted, message}) => {
        let answer = {
            access: isPermitted,
            message: message || ''
        };
        answer = JSON.stringify(answer);
        console.log("Sent: ", answer);
        res.status(200).send(answer);
    }).catch((error) => {
        console.log("Failed to verify user: ", error);
        res.status(200).send({
            access: false,
            message: "internal error"
        });
    });
});

exports.connectivityCheck = functions.https.onRequest((req, res) => {
    console.log("Got: ", req.method);
    res.status(200).send("OK");
});

function obtainPermission(email, computerUID) {
    let def = q.defer();

    getUIDByEmail(email).then(userUID => {
        return getTokenByUID(userUID);
    }).then(({token, userUID}) => {
        return sendNotification(token, userUID, computerUID);
    }).then((userUID) => {
        def.resolve({isPermitted: true});
    }).catch((error) => {
        console.log("Error in getting permission: ", error);
        def.reject();
    });

    return def.promise;
}

function verifyIdentity(email) {
    let def = q.defer();
    getUIDByEmail(email).then(userUID => {
        return getTokenByUID(userUID);
    }).then(({token, userUID}) => {
        return sendIdentityVerificationRequest(token, userUID);
    }).then(userUID => {
        return obtainIdentityVerification(userUID);
    }).then(({identityVerification, message}) =>{
        def.resolve({isVerified: identityVerification, message: message});
    }).catch(error => {
        console.log("Error in verification: ", error);
        def.reject();
    });

    return def.promise;
}

function getUIDByEmail(email) {
    console.log("Getting UID of ", email);
    let def = q.defer();
    admin.auth().getUserByEmail(email)
        .then(userRecored => {
            console.log("Got UID: ", userRecored.uid);
            def.resolve(userRecored.uid);
        }).catch(error => {
            console.log("Error getting UID: ", error);
            def.reject();
        });
    return def.promise;
}

function getTokenByUID(userUID) {
    console.log("Getting token of ", userUID);
    let def = q.defer();
    if (userUID === undefined) {
        def.reject();
        return def.promise;
    }
    admin.database().ref('Users').child(userUID).child('deviceToken')
        .on('value', snapshot => {
            console.log("Got token: ", snapshot.val());
            def.resolve({token: snapshot.val(), userUID: userUID});
        });
    return def.promise;
}

function sendNotification(token, userUID, computerUID) {
    console.log("Sending notification to: ", token);
    let def = q.defer();

    createPermissionRequestPayload(userUID, computerUID).then(payload => {
        console.log("Sending: ", payload);
        admin.messaging().sendToDevice(token, payload)
            .then(response => {
                // See the MessagingDevicesResponse reference documentation for the contents of response.
                console.log("Successfully sent message:", response);
                def.resolve(userUID);
            })
            .catch(error => {
                console.log("Error sending message:", error);
                def.reject();
            });
    });

    return def.promise;
}

function createVerificationPayload(userUID) {
    let def = q.defer();
    admin.auth().getUser(userUID).then(user => {
        console.log("User: ", user.toJSON());
        let payload =
            {
                data: {
                    priority: 'high',
                    userEmail: user.email,
                    userName: user.displayName,
                    userPhotoUrl: user.photoURL
                }
            };
        def.resolve(payload);
    });
    return def.promise;
}

function sendIdentityVerificationRequest(token, userUID){
    console.log("Sending verification request to: ", token);
    let def = q.defer();
    createVerificationPayload(userUID).then(payload => {
        console.log("Sending: ", payload);
        admin.messaging().sendToDevice(token, payload)
            .then(response => {
                console.log("Successfully sent message:", response);
                def.resolve(userUID);
            })
            .catch(error => {
                console.log("Error sending message:", error);
                def.reject();
            });
    });
    return def.promise;
}

/**
 * Listens for change in the database (IdentityVerifications/{userUID}).
 * If there is no change in 2 minutes,
 * listening stops and returned {identityVerification: false, message: 'timeout reached'}
 * @param {string} userUID
 * @return {JSON} {boolean} identityVerification, {string} massage
**/
function obtainIdentityVerification(userUID){
    let def = q.defer();
    console.log(`Waiting for verification from ${userUID}`);
    let timeout = 1000 * 120;
    let verificationRef = admin.database().ref("IdentityVerifications");

    console.log(`Started watchdog on ${verificationRef}, for ${timeout} milliseconds`);
    let timeoutGuard;
    timeoutGuard = setTimeout(() => {
        console.log("Reached timeout");
        verificationRef.off(); //Remove listener
        def.resolve({identityVerification: false, message: 'Reached timeout'});
    }, timeout);

    verificationRef.on('child_added', snapshot => {
        let identityFlag = snapshot.val();
        console.log(`Found value change: ${snapshot.key}:${identityFlag}`);
        if (snapshot.key !== userUID){
            console.log(`Got irrelevant trigger`);
            return;
        }
        clearTimeout(timeoutGuard);
        if(identityFlag){
            def.resolve({identityVerification: true});
        }else{
            def.resolve({identityVerification: false, message: 'Rejected by user'});
        }
        console.log(`Finished handling database change, promise state is ${def.promise.inspect().state}`);
        verificationRef.child(userUID).remove().then(() => {
            console.log('Verification cleared successfully');
        });
    });
    return def.promise;
}

function createPermissionRequestPayload(userUID, computerUID) {
    console.log("Creating payload about user: ", userUID);
    let def = q.defer();
    admin.auth().getUser(userUID).then(user => {
        console.log("User: ", user.toJSON());
        console.log(user.displayName, user.email, user.photoURL);
        let payload =
            {
                data: {
                    priority: 'high',
                    userEmail: user.email,
                    userName: user.displayName,
                    userPhotoUrl: user.photoURL,
                    computer: computerUID,
                }
            };
        console.log("Created payload: ", payload);
        def.resolve(payload);
    }).catch(error => {
        console.log("Failed to create payload: ", error);
        def.reject();
    });
    return def.promise;
}

// function createNotification(title, body, priority = "high") {
//     return {
//         notification: {
//             priority: "high",
//             title: title,
//             body: body
//         }
//     };
// }<|endoftext|>


<commit_before>var fs = require('fs')
var http = require('http')
var toxy = require('..')

var fixtures = __dirname + '/../test/fixtures'

var opts = {
  ssl: {
    key: fs.readFileSync(fixtures + '/key.pem', 'utf8'),
    cert: fs.readFileSync(fixtures + '/cert.pem', 'utf8')
  }
}

var proxy = toxy(opts)

proxy
  .forward('http://localhost:3001')
  .poison(toxy.poisons.latency(1000))
  .poison(toxy.poisons.slowRead(512))
  .all('/*')

proxy.listen(3443)
console.log('HTTPS server listening on port:', 3443)
<commit_msg>fix(example): https<commit_after>var fs = require('fs')
var http = require('http')
var toxy = require('..')

var fixtures = __dirname + '/../test/fixtures'

var opts = {
  ssl: {
    key: fs.readFileSync(fixtures + '/key.pem', 'utf8'),
    cert: fs.readFileSync(fixtures + '/cert.pem', 'utf8')
  }
}

var proxy = toxy(opts)

proxy
  .forward('http://httpbin.org')
  .poison(toxy.poisons.latency(1000))
  .poison(toxy.poisons.slowRead(512))
  .all('/*')

proxy.listen(3443)
console.log('HTTPS server listening on port:', 3443)
<|endoftext|>


<commit_before>// This is the devtools script, which is called when the user opens the
// Chrome devtool on a page. We check to see if we global hook has detected
// Vue presence on the page. If yes, create the Vue panel; otherwise poll
// for 10 seconds.

let panelLoaded = false
let panelShown = false
let pendingAction
let created = false
let checkCount = 0

chrome.devtools.network.onNavigated.addListener(createPanelIfHasVue)
const checkVueInterval = setInterval(createPanelIfHasVue, 1000)
createPanelIfHasVue()

function createPanelIfHasVue () {
  if (created || checkCount++ > 10) {
    clearInterval(checkVueInterval)
    return
  }
  panelLoaded = false
  panelShown = false
  chrome.devtools.inspectedWindow.eval(
    '!!(window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue || window.__VUE_DEVTOOLS_GLOBAL_HOOK__.apps.length)',
    function (hasVue) {
      if (!hasVue || created) {
        return
      }
      clearInterval(checkVueInterval)
      created = true
      chrome.devtools.panels.create(
        'Vue', 'icons/128.png', 'devtools.html',
        panel => {
          // panel loaded
          panel.onShown.addListener(onPanelShown)
          panel.onHidden.addListener(onPanelHidden)
        }
      )
    }
  )
}

// Runtime messages

chrome.runtime.onMessage.addListener(request => {
  if (request === 'vue-panel-load') {
    onPanelLoad()
  } else if (request.vueToast) {
    toast(request.vueToast.message, request.vueToast.type)
  } else if (request.vueContextMenu) {
    onContextMenu(request.vueContextMenu)
  }
})

// Page context menu entry

function onContextMenu ({ id }) {
  if (id === 'vue-inspect-instance') {
    const src = 'window.__VUE_DEVTOOLS_CONTEXT_MENU_HAS_TARGET__'

    chrome.devtools.inspectedWindow.eval(src, function (res, err) {
      if (err) {
        console.log(err)
      }
      if (typeof res !== 'undefined' && res) {
        panelAction(() => {
          chrome.runtime.sendMessage('vue-get-context-menu-target')
        }, 'open-devtools')
      } else {
        pendingAction = null
        toast('component-not-found')
      }
    })
  }
}

// Action that may execute immediatly
// or later when the Vue panel is ready

function panelAction (cb, message = null) {
  if (created && panelLoaded && panelShown) {
    cb()
  } else {
    pendingAction = cb
    message && toast(message)
  }
}

function executePendingAction () {
  pendingAction && pendingAction()
  pendingAction = null
}

// Execute pending action when Vue panel is ready

function onPanelLoad () {
  executePendingAction()
  panelLoaded = true
}

// Manage panel visibility

function onPanelShown () {
  chrome.runtime.sendMessage('vue-panel-shown')
  panelShown = true
  panelLoaded && executePendingAction()
}

function onPanelHidden () {
  chrome.runtime.sendMessage('vue-panel-hidden')
  panelShown = false
}

// Toasts

const toastMessages = {
  'open-devtools': { message: 'Open Vue devtools to see component details', type: 'normal' },
  'component-not-found': { message: 'No Vue component was found', type: 'warn' }
}

function toast (id) {
  if (!Object.keys().includes(id)) return

  const { message, type } = toastMessages[id]

  const src = `(function() {
    __VUE_DEVTOOLS_TOAST__(\`${message}\`, '${type}');
  })()`

  chrome.devtools.inspectedWindow.eval(src, function (res, err) {
    if (err) {
      console.log(err)
    }
  })
}
<commit_msg>fix(toast): missing variable in keys()<commit_after>// This is the devtools script, which is called when the user opens the
// Chrome devtool on a page. We check to see if we global hook has detected
// Vue presence on the page. If yes, create the Vue panel; otherwise poll
// for 10 seconds.

let panelLoaded = false
let panelShown = false
let pendingAction
let created = false
let checkCount = 0

chrome.devtools.network.onNavigated.addListener(createPanelIfHasVue)
const checkVueInterval = setInterval(createPanelIfHasVue, 1000)
createPanelIfHasVue()

function createPanelIfHasVue () {
  if (created || checkCount++ > 10) {
    clearInterval(checkVueInterval)
    return
  }
  panelLoaded = false
  panelShown = false
  chrome.devtools.inspectedWindow.eval(
    '!!(window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue || window.__VUE_DEVTOOLS_GLOBAL_HOOK__.apps.length)',
    function (hasVue) {
      if (!hasVue || created) {
        return
      }
      clearInterval(checkVueInterval)
      created = true
      chrome.devtools.panels.create(
        'Vue', 'icons/128.png', 'devtools.html',
        panel => {
          // panel loaded
          panel.onShown.addListener(onPanelShown)
          panel.onHidden.addListener(onPanelHidden)
        }
      )
    }
  )
}

// Runtime messages

chrome.runtime.onMessage.addListener(request => {
  if (request === 'vue-panel-load') {
    onPanelLoad()
  } else if (request.vueToast) {
    toast(request.vueToast.message, request.vueToast.type)
  } else if (request.vueContextMenu) {
    onContextMenu(request.vueContextMenu)
  }
})

// Page context menu entry

function onContextMenu ({ id }) {
  if (id === 'vue-inspect-instance') {
    const src = 'window.__VUE_DEVTOOLS_CONTEXT_MENU_HAS_TARGET__'

    chrome.devtools.inspectedWindow.eval(src, function (res, err) {
      if (err) {
        console.log(err)
      }
      if (typeof res !== 'undefined' && res) {
        panelAction(() => {
          chrome.runtime.sendMessage('vue-get-context-menu-target')
        }, 'open-devtools')
      } else {
        pendingAction = null
        toast('component-not-found')
      }
    })
  }
}

// Action that may execute immediatly
// or later when the Vue panel is ready

function panelAction (cb, message = null) {
  if (created && panelLoaded && panelShown) {
    cb()
  } else {
    pendingAction = cb
    message && toast(message)
  }
}

function executePendingAction () {
  pendingAction && pendingAction()
  pendingAction = null
}

// Execute pending action when Vue panel is ready

function onPanelLoad () {
  executePendingAction()
  panelLoaded = true
}

// Manage panel visibility

function onPanelShown () {
  chrome.runtime.sendMessage('vue-panel-shown')
  panelShown = true
  panelLoaded && executePendingAction()
}

function onPanelHidden () {
  chrome.runtime.sendMessage('vue-panel-hidden')
  panelShown = false
}

// Toasts

const toastMessages = {
  'open-devtools': { message: 'Open Vue devtools to see component details', type: 'normal' },
  'component-not-found': { message: 'No Vue component was found', type: 'warn' }
}

function toast (id) {
  if (!Object.keys(toastMessages).includes(id)) return

  const { message, type } = toastMessages[id]

  const src = `(function() {
    __VUE_DEVTOOLS_TOAST__(\`${message}\`, '${type}');
  })()`

  chrome.devtools.inspectedWindow.eval(src, function (res, err) {
    if (err) {
      console.log(err)
    }
  })
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name Monster Minigame Auto-script
// @namespace https://github.com/wchill/steamSummerMinigame
// @description A script that runs the Steam Monster Minigame for you. Modified from mouseas's original version to include autoclick.
// @version 1.02
// @match http://steamcommunity.com/minigame/towerattack*
// @updateURL https://raw.githubusercontent.com/wchill/steamSummerMinigame/master/autoPlay.js
// @downloadURL https://raw.githubusercontent.com/wchill/steamSummerMinigame/master/autoPlay.js
// ==/UserScript==

// IMPORTANT: Update the @version property above to a higher number such as 1.1 and 1.2 when you update the script! Otherwise, Tamper / Greasemonkey users will not update automatically.

var clickRate = 20; // change to number of desired clicks per second

var isAlreadyRunning = false;

var disableParticleEffects = true; // Set to false to keep particle effects

// disable particle effects - this drastically reduces the game's memory leak
if (window.g_Minigame !== undefined && disableParticleEffects) {
	window.g_Minigame.CurrentScene().DoClickEffect = function() {};
	window.g_Minigame.CurrentScene().SpawnEmitter = function() {};
}

if (thingTimer !== undefined) {
	window.clearTimeout(thingTimer);
}

function doTheThing() {
	if (isAlreadyRunning || g_Minigame === undefined || !g_Minigame.CurrentScene().m_bRunning || !g_Minigame.CurrentScene().m_rgPlayerTechTree) {
		return;
	}
	isAlreadyRunning = true;

	goToLaneWithBestTarget();

	useGoodLuckCharmIfRelevant();
	useMedicsIfRelevant();

	// TODO use abilities if available and a suitable target exists
	// - Tactical Nuke on a Spawner if below 50% and above 25% of its health
	// - Cluster Bomb and Napalm if the current lane has a spawner and 2+ creeps
	// - Metal Detector if a boss, miniboss, or spawner death is imminent (predicted in > 2 and < 7 seconds)
	// - Morale Booster if available and lane has > 2 live enemies
	// - Decrease Cooldowns if another player used a long-cooldown ability < 10 seconds ago (any ability but Medics or a consumable)

	// TODO purchase abilities and upgrades intelligently

	attemptRespawn();

	isAlreadyRunning = false;
}

function goToLaneWithBestTarget() {
	// We can overlook spawners if all spawners are 40% hp or higher and a creep is under 10% hp
	var spawnerOKThreshold = 0.4;
	var creepSnagThreshold = 0.1;

	var targetFound = false;
	var lowHP = 0;
	var lowLane = 0;
	var lowTarget = 0;
	var lowPercentageHP = 0;
	var preferredLane = -1;

	var ENEMY_TYPE = {
		"SPAWNER":0,
		"CREEP":1,
		"BOSS":2,
		"MINIBOSS":3,
		"TREASURE":4
	}

	// determine which lane and enemy is the optimal target
	var enemyTypePriority = [
		ENEMY_TYPE.TREASURE,
		ENEMY_TYPE.BOSS,
		ENEMY_TYPE.MINIBOSS,
		ENEMY_TYPE.SPAWNER,
		ENEMY_TYPE.CREEP
		];

	var skippingSpawner = false;
	var skippedSpawnerLane = 0;
	var skippedSpawnerTarget = 0;

	for (var k = 0; !targetFound && k < enemyTypePriority.length; k++) {
		var enemies = [];

		// gather all the enemies of the specified type.
		for (var i = 0; i < 3; i++) {
			for (var j = 0; j < 4; j++) {
				var enemy = g_Minigame.CurrentScene().GetEnemy(i, j);
				if (enemy && enemy.m_data.type == enemyTypePriority[k]) {
					enemies[enemies.length] = enemy;
				}
			}
		}

		//Prefer lane with raining gold, unless current enemy target is a treasure or boss.
		if(lowTarget != ENEMY_TYPE.TREASURE || lowTarget != ENEMY_TYPE.BOSS ){
			for(i = 0; i < g_Minigame.CurrentScene().m_rgGameData.lanes.length; i++){
				// ignore if lane is empty
				if(g_Minigame.CurrentScene().m_rgGameData.lanes[i].dps == 0)
					continue;
				for(j = 0; j < g_Minigame.CurrentScene().m_rgGameData.lanes[i].active_player_abilities.length; j++){
					if(g_Minigame.CurrentScene().m_rgGameData.lanes[i].active_player_abilities[j].ability == 17){
						preferredLane = i;
						console.log('switching to lane with raining gold');
					}
				}
			}
		}

		// target the enemy of the specified type with the lowest hp
		for (var i = 0; i < enemies.length; i++) {
			if (enemies[i] && !enemies[i].m_bIsDestroyed) {
				// Only select enemy and lane if the preferedLane matches the potential enemy lane
				if((lowHP < 1 || enemies[i].m_flDisplayedHP < lowHP) && ((preferredLane != -1 && preferredLane == enemies[i].m_nLane) || preferredLane == -1)) {
					targetFound = true;
					lowHP = enemies[i].m_flDisplayedHP;
					lowLane = enemies[i].m_nLane;
					lowTarget = enemies[i].m_nID;
				}
				var percentageHP = enemies[i].m_flDisplayedHP / enemies[i].m_data.max_hp;
				if(lowPercentageHP == 0 || percentageHP < lowPercentageHP) {
					lowPercentageHP = percentageHP;
				}
			}
		}

		// If we just finished looking at spawners,
		// AND none of them were below our threshold,
		// remember them and look for low creeps (so don't quit now)
		// Don't skip spawner if lane has raining gold
		if ((enemyTypePriority[k] == ENEMY_TYPE.SPAWNER && lowPercentageHP > spawnerOKThreshold) && preferredLane == -1) {
			skippedSpawnerLane = lowLane;
			skippedSpawnerTarget = lowTarget;
			skippingSpawner = true;
			targetFound = false;
		}

		// If we skipped a spawner and just finished looking at creeps,
		// AND the lowest was above our snag threshold,
		// just go back to the spawner!
		if (skippingSpawner && enemyTypePriority[k] == ENEMY_TYPE.CREEP && lowPercentageHP > creepSnagThreshold ) {
			lowLane = skippedSpawnerLane;
			lowTarget = skippedSpawnerTarget;
		}
	}

	// go to the chosen lane
	if (targetFound) {
		if (g_Minigame.CurrentScene().m_nExpectedLane != lowLane) {
			//console.log('switching langes');
			g_Minigame.CurrentScene().TryChangeLane(lowLane);
		}

		// target the chosen enemy
		if (g_Minigame.CurrentScene().m_nTarget != lowTarget) {
			//console.log('switching targets');
			g_Minigame.CurrentScene().TryChangeTarget(lowTarget);
		}
	}
}

function useMedicsIfRelevant() {
	var myMaxHealth = g_Minigame.CurrentScene().m_rgPlayerTechTree.max_hp;

	// check if health is below 50%
	var hpPercent = g_Minigame.CurrentScene().m_rgPlayerData.hp / myMaxHealth;
	if (hpPercent > 0.5 || g_Minigame.CurrentScene().m_rgPlayerData.hp < 1) {
		return; // no need to heal - HP is above 50% or already dead
	}

	// check if Medics is purchased and cooled down
	if (hasPurchasedAbility(7)) {

		if (isAbilityCoolingDown(7)) {
			return;
		}

		// Medics is purchased, cooled down, and needed. Trigger it.
		console.log('Medics is purchased, cooled down, and needed. Trigger it.');
		triggerAbility(7);
	}
}

// Use Good Luck Charm if doable
function useGoodLuckCharmIfRelevant() {
	// check if Good Luck Charms is purchased and cooled down
	if (hasPurchasedAbility(6)) {
		if (isAbilityCoolingDown(6)) {
			return;
		}

		// Good Luck Charms is purchased, cooled down, and needed. Trigger it.
		console.log('Good Luck Charms is purchased, cooled down, and needed. Trigger it.');
		triggerAbility(6);
	}
}

//If player is dead, call respawn method
function attemptRespawn() {
	if ((g_Minigame.CurrentScene().m_bIsDead) &&
			((g_Minigame.CurrentScene().m_rgPlayerData.time_died * 1000) + 5000) < (new Date().getTime())) {
		RespawnPlayer();
	}
}

function isAbilityCoolingDown(abilityId) {
	return g_Minigame.CurrentScene().GetCooldownForAbility(abilityId) > 0;
}

function hasPurchasedAbility(abilityId) {
	// each bit in unlocked_abilities_bitfield corresponds to an ability.
	// the above condition checks if the ability's bit is set or cleared. I.e. it checks if
	// the player has purchased the specified ability.
	return (1 << abilityId) & g_Minigame.CurrentScene().m_rgPlayerTechTree.unlocked_abilities_bitfield;
}

function triggerAbility(abilityId) {
	var elem = document.getElementById('ability_' + abilityId);
	if (elem && elem.childElements() && elem.childElements().length >= 1) {
		g_Minigame.CurrentScene().TryAbility(document.getElementById('ability_' + abilityId).childElements()[0]);
	}
}

var thingTimer = window.setInterval(doTheThing, 1000);
function clickTheThing() {
    g_Minigame.m_CurrentScene.DoClick(
        {
            data: {
                getLocalPosition: function() {
                    var enemy = g_Minigame.m_CurrentScene.GetEnemy(
                                      g_Minigame.m_CurrentScene.m_rgPlayerData.current_lane,
                                      g_Minigame.m_CurrentScene.m_rgPlayerData.target),
                        laneOffset = enemy.m_nLane * 440;

                    return {
                        x: enemy.m_Sprite.position.x - laneOffset,
                        y: enemy.m_Sprite.position.y - 52
                    }
                }
            }
        }
    );
}

var clickTimer = window.setInterval(clickTheThing, 1000/clickRate);
<commit_msg>Use moral booster<commit_after>// ==UserScript==
// @name Monster Minigame Auto-script
// @namespace https://github.com/wchill/steamSummerMinigame
// @description A script that runs the Steam Monster Minigame for you. Modified from mouseas's original version to include autoclick.
// @version 1.02
// @match http://steamcommunity.com/minigame/towerattack*
// @updateURL https://raw.githubusercontent.com/wchill/steamSummerMinigame/master/autoPlay.js
// @downloadURL https://raw.githubusercontent.com/wchill/steamSummerMinigame/master/autoPlay.js
// ==/UserScript==

// IMPORTANT: Update the @version property above to a higher number such as 1.1 and 1.2 when you update the script! Otherwise, Tamper / Greasemonkey users will not update automatically.

var clickRate = 20; // change to number of desired clicks per second

var isAlreadyRunning = false;

var disableParticleEffects = true; // Set to false to keep particle effects

// disable particle effects - this drastically reduces the game's memory leak
if (window.g_Minigame !== undefined && disableParticleEffects) {
	window.g_Minigame.CurrentScene().DoClickEffect = function() {};
	window.g_Minigame.CurrentScene().SpawnEmitter = function() {};
}

if (thingTimer !== undefined) {
	window.clearTimeout(thingTimer);
}

function doTheThing() {
	if (isAlreadyRunning || g_Minigame === undefined || !g_Minigame.CurrentScene().m_bRunning || !g_Minigame.CurrentScene().m_rgPlayerTechTree) {
		return;
	}
	isAlreadyRunning = true;

	goToLaneWithBestTarget();

	useGoodLuckCharmIfRelevant();
	useMedicsIfRelevant();
	useMoralBoosterIfRelevant()

	// TODO use abilities if available and a suitable target exists
	// - Tactical Nuke on a Spawner if below 50% and above 25% of its health
	// - Cluster Bomb and Napalm if the current lane has a spawner and 2+ creeps
	// - Metal Detector if a boss, miniboss, or spawner death is imminent (predicted in > 2 and < 7 seconds)
	// - Morale Booster if available and lane has > 2 live enemies
	// - Decrease Cooldowns if another player used a long-cooldown ability < 10 seconds ago (any ability but Medics or a consumable)

	// TODO purchase abilities and upgrades intelligently

	attemptRespawn();

	isAlreadyRunning = false;
}

function goToLaneWithBestTarget() {
	// We can overlook spawners if all spawners are 40% hp or higher and a creep is under 10% hp
	var spawnerOKThreshold = 0.4;
	var creepSnagThreshold = 0.1;

	var targetFound = false;
	var lowHP = 0;
	var lowLane = 0;
	var lowTarget = 0;
	var lowPercentageHP = 0;
	var preferredLane = -1;

	var ENEMY_TYPE = {
		"SPAWNER":0,
		"CREEP":1,
		"BOSS":2,
		"MINIBOSS":3,
		"TREASURE":4
	}

	// determine which lane and enemy is the optimal target
	var enemyTypePriority = [
		ENEMY_TYPE.TREASURE,
		ENEMY_TYPE.BOSS,
		ENEMY_TYPE.MINIBOSS,
		ENEMY_TYPE.SPAWNER,
		ENEMY_TYPE.CREEP
		];

	var skippingSpawner = false;
	var skippedSpawnerLane = 0;
	var skippedSpawnerTarget = 0;

	for (var k = 0; !targetFound && k < enemyTypePriority.length; k++) {
		var enemies = [];

		// gather all the enemies of the specified type.
		for (var i = 0; i < 3; i++) {
			for (var j = 0; j < 4; j++) {
				var enemy = g_Minigame.CurrentScene().GetEnemy(i, j);
				if (enemy && enemy.m_data.type == enemyTypePriority[k]) {
					enemies[enemies.length] = enemy;
				}
			}
		}

		//Prefer lane with raining gold, unless current enemy target is a treasure or boss.
		if(lowTarget != ENEMY_TYPE.TREASURE || lowTarget != ENEMY_TYPE.BOSS ){
			for(i = 0; i < g_Minigame.CurrentScene().m_rgGameData.lanes.length; i++){
				// ignore if lane is empty
				if(g_Minigame.CurrentScene().m_rgGameData.lanes[i].dps == 0)
					continue;
				for(j = 0; j < g_Minigame.CurrentScene().m_rgGameData.lanes[i].active_player_abilities.length; j++){
					if(g_Minigame.CurrentScene().m_rgGameData.lanes[i].active_player_abilities[j].ability == 17){
						preferredLane = i;
						console.log('switching to lane with raining gold');
					}
				}
			}
		}

		// target the enemy of the specified type with the lowest hp
		for (var i = 0; i < enemies.length; i++) {
			if (enemies[i] && !enemies[i].m_bIsDestroyed) {
				// Only select enemy and lane if the preferedLane matches the potential enemy lane
				if((lowHP < 1 || enemies[i].m_flDisplayedHP < lowHP) && ((preferredLane != -1 && preferredLane == enemies[i].m_nLane) || preferredLane == -1)) {
					targetFound = true;
					lowHP = enemies[i].m_flDisplayedHP;
					lowLane = enemies[i].m_nLane;
					lowTarget = enemies[i].m_nID;
				}
				var percentageHP = enemies[i].m_flDisplayedHP / enemies[i].m_data.max_hp;
				if(lowPercentageHP == 0 || percentageHP < lowPercentageHP) {
					lowPercentageHP = percentageHP;
				}
			}
		}

		// If we just finished looking at spawners,
		// AND none of them were below our threshold,
		// remember them and look for low creeps (so don't quit now)
		// Don't skip spawner if lane has raining gold
		if ((enemyTypePriority[k] == ENEMY_TYPE.SPAWNER && lowPercentageHP > spawnerOKThreshold) && preferredLane == -1) {
			skippedSpawnerLane = lowLane;
			skippedSpawnerTarget = lowTarget;
			skippingSpawner = true;
			targetFound = false;
		}

		// If we skipped a spawner and just finished looking at creeps,
		// AND the lowest was above our snag threshold,
		// just go back to the spawner!
		if (skippingSpawner && enemyTypePriority[k] == ENEMY_TYPE.CREEP && lowPercentageHP > creepSnagThreshold ) {
			lowLane = skippedSpawnerLane;
			lowTarget = skippedSpawnerTarget;
		}
	}

	// go to the chosen lane
	if (targetFound) {
		if (g_Minigame.CurrentScene().m_nExpectedLane != lowLane) {
			//console.log('switching langes');
			g_Minigame.CurrentScene().TryChangeLane(lowLane);
		}

		// target the chosen enemy
		if (g_Minigame.CurrentScene().m_nTarget != lowTarget) {
			//console.log('switching targets');
			g_Minigame.CurrentScene().TryChangeTarget(lowTarget);
		}
	}
}

function useMedicsIfRelevant() {
	var myMaxHealth = g_Minigame.CurrentScene().m_rgPlayerTechTree.max_hp;

	// check if health is below 50%
	var hpPercent = g_Minigame.CurrentScene().m_rgPlayerData.hp / myMaxHealth;
	if (hpPercent > 0.5 || g_Minigame.CurrentScene().m_rgPlayerData.hp < 1) {
		return; // no need to heal - HP is above 50% or already dead
	}

	// check if Medics is purchased and cooled down
	if (hasPurchasedAbility(7)) {

		if (isAbilityCoolingDown(7)) {
			return;
		}

		// Medics is purchased, cooled down, and needed. Trigger it.
		console.log('Medics is purchased, cooled down, and needed. Trigger it.');
		triggerAbility(7);
	}
}

// Use Good Luck Charm if doable
function useGoodLuckCharmIfRelevant() {
	// check if Good Luck Charms is purchased and cooled down
	if (hasPurchasedAbility(6)) {
		if (isAbilityCoolingDown(6)) {
			return;
		}

		// Good Luck Charms is purchased, cooled down, and needed. Trigger it.
		console.log('Good Luck Charms is purchased, cooled down, and needed. Trigger it.');
		triggerAbility(6);
	}
}

// Use Moral Booster if doable
function useMoralBoosterIfRelevant() {
	// check if Good Luck Charms is purchased and cooled down
	if (hasPurchasedAbility(12)) {
		if (isAbilityCoolingDown(12)) {
			return;
		}
		var numberOfWorthwhileEnimies = 0;
		for(i = 0; i < g_Minigame.CurrentScene().m_rgGameData.lanes[g_Minigame.CurrentScene().m_nExpectedLane].enemies.length; i++){
			//Worthwhile enemy is when an enamy has a current hp value of at least 1,000,000
			if(g_Minigame.CurrentScene().m_rgGameData.lanes[g_Minigame.CurrentScene().m_nExpectedLane].enemies[i].hp > 1000000)
				numberOfWorthwhileEnimies++;
		}
		if(numberOfWortwhileEnimies == 2){
			// Moral Booster is purchased, cooled down, and needed. Trigger it.
			console.log('Moral Booster is purchased, cooled down, and needed. Trigger it.');
			triggerAbility(12);
		}
	}
}

//If player is dead, call respawn method
function attemptRespawn() {
	if ((g_Minigame.CurrentScene().m_bIsDead) &&
			((g_Minigame.CurrentScene().m_rgPlayerData.time_died * 1000) + 5000) < (new Date().getTime())) {
		RespawnPlayer();
	}
}

function isAbilityCoolingDown(abilityId) {
	return g_Minigame.CurrentScene().GetCooldownForAbility(abilityId) > 0;
}

function hasPurchasedAbility(abilityId) {
	// each bit in unlocked_abilities_bitfield corresponds to an ability.
	// the above condition checks if the ability's bit is set or cleared. I.e. it checks if
	// the player has purchased the specified ability.
	return (1 << abilityId) & g_Minigame.CurrentScene().m_rgPlayerTechTree.unlocked_abilities_bitfield;
}

function triggerAbility(abilityId) {
	var elem = document.getElementById('ability_' + abilityId);
	if (elem && elem.childElements() && elem.childElements().length >= 1) {
		g_Minigame.CurrentScene().TryAbility(document.getElementById('ability_' + abilityId).childElements()[0]);
	}
}

var thingTimer = window.setInterval(doTheThing, 1000);
function clickTheThing() {
    g_Minigame.m_CurrentScene.DoClick(
        {
            data: {
                getLocalPosition: function() {
                    var enemy = g_Minigame.m_CurrentScene.GetEnemy(
                                      g_Minigame.m_CurrentScene.m_rgPlayerData.current_lane,
                                      g_Minigame.m_CurrentScene.m_rgPlayerData.target),
                        laneOffset = enemy.m_nLane * 440;

                    return {
                        x: enemy.m_Sprite.position.x - laneOffset,
                        y: enemy.m_Sprite.position.y - 52
                    }
                }
            }
        }
    );
}

var clickTimer = window.setInterval(clickTheThing, 1000/clickRate);
<|endoftext|>


<commit_before>(function (angular) {
    'use strict';
    var SignalRService = function (jQuery) {
        this.jQuery = jQuery;
    };

    SignalRService.prototype.getHub = function (hubName) {
        return this.jQuery.connection[hubName];
    };

    var SignalRProvider = function () {
        this._url = '/signalr';
        this._proxies = {};
    };

    SignalRProvider.prototype.url = function (value) {
        if (angular.isUndefined(value)) {
            return this._url;
        }
        this._url = value;
        return this;
    };

    SignalRProvider.prototype.proxies = function (value) {
        if (angular.isUndefined(value)) {
            return this._proxies;
        }
        this._proxies = value;
        return this;
    };

    SignalRProvider.prototype.$get = function ($rootScope, $window) {
        var jQuery = $window.jQuery;
        var self = this;
        angular.forEach(jQuery.connection.hub.proxies, function (proxy, proxyName) {
            if (!self._proxies.hasOwnProperty(proxyName)) {
                return;
            }
            angular.forEach(self._proxies[proxyName], function (methodName) {
                proxy.client[methodName] = function () {
                    var args = [];
                    angular.forEach(arguments, function (argument) {
                        args.push(argument);
                    });
                    $rootScope.$broadcast('eehSignalR:' + methodName, args);
                    $rootScope.$apply();
                };
            });
        });
        jQuery.connection.hub.url = this.url();
        jQuery.connection.hub.start();
        return new SignalRService(jQuery);
    };

    angular.module('eehSignalR', []).provider('eehSignalR', SignalRProvider);
}(angular));
<commit_msg>Make API for adding proxy methods to broadcast more explicit<commit_after>(function (angular) {
    'use strict';
    var SignalRService = function (jQuery) {
        this.jQuery = jQuery;
    };

    SignalRService.prototype.getHub = function (hubName) {
        return this.jQuery.connection[hubName];
    };

    var SignalRProvider = function () {
        this._url = '/signalr';
        this._proxies = {};
    };

    SignalRProvider.prototype.url = function (value) {
        if (angular.isUndefined(value)) {
            return this._url;
        }
        this._url = value;
        return this;
    };

    SignalRProvider.prototype.proxy = function (name, methods) {
        if (angular.isUndefined(methods)) {
            return this._proxies[name];
        }
        this._proxies[name] = methods;
        return this;
    };

    SignalRProvider.prototype.$get = function ($rootScope, $window) {
        var jQuery = $window.jQuery;
        var self = this;
        angular.forEach(jQuery.connection.hub.proxies, function (proxy, proxyName) {
            if (!self._proxies.hasOwnProperty(proxyName)) {
                return;
            }
            angular.forEach(self._proxies[proxyName], function (methodName) {
                proxy.client[methodName] = function () {
                    var args = [];
                    angular.forEach(arguments, function (argument) {
                        args.push(argument);
                    });
                    $rootScope.$broadcast('eehSignalR:' + methodName, args);
                    $rootScope.$apply();
                };
            });
        });
        jQuery.connection.hub.url = this.url();
        jQuery.connection.hub.start();
        return new SignalRService(jQuery);
    };

    angular.module('eehSignalR', []).provider('eehSignalR', SignalRProvider);
}(angular));
<|endoftext|>


<commit_before>var countlyConfig = {
    mongodb: {
        host: process.env.MONGO_PORT_27017_TCP_ADDR,
        db: "countly",
        port: process.env.MONGO_PORT_27017_TCP_PORT
    },
    /*  or for a replica set
    mongodb: {
        replSetServers : [
            '192.168.3.1:27017/?auto_reconnect=true',
            '192.168.3.2:27017/?auto_reconnect=true'
        ],
        db: "countly",
    },
    */
    /*  or define as a url
    mongodb: "localhost:27017/countly?auto_reconnect=true",
    */
    web: {
        port: 6001,
        use_intercom: true
    }
};

module.exports = countlyConfig;
<commit_msg>changes<commit_after>var countlyConfig = {
    mongodb: {
        host: process.env.MONGO_PORT_27017_TCP_ADDR,
        db: "countly",
        port: process.env.MONGO_PORT_27017_TCP_PORT
    },
    /*  or for a replica set
    mongodb: {
        replSetServers : [
            '192.168.3.1:27017/?auto_reconnect=true',
            '192.168.3.2:27017/?auto_reconnect=true'
        ],
        db: "countly",
    },
    */
    /*  or define as a url
    mongodb: "localhost:27017/countly?auto_reconnect=true",
    */
    web: {
        host: "localhost",
        port: 6001,
        use_intercom: true
    },
    path: "",
    cdn: ""
};

module.exports = countlyConfig;
<|endoftext|>


<commit_before>/*
 * RTLText
 * Copyright 2012 Twitter and other contributors
 * Released under the MIT license
 *
 * What it does:
 *
 * This module will set the direction of a textarea to RTL when a threshold
 * of RTL characters has been reached (rtlThreshold). It also applies Twitter-
 * specific RTL rules regarding the placement of @ signs, # tags, and URLs.
 *
 * How to use:
 *
 * Bind keyup and keydown to RTLText.onTextChange. If you have initial text,
 * call RTLText.setText(textarea, initial_string) to set markers on that
 * initial text.
 */
var RTLText = function () {
  'use strict';

  var that = {};
  var rtlThreshold = 0.3;

  /*
   * Right-to-left Unicode blocks for modern scripts are:
   *
   * Consecutive range of the main letters:
   * U+0590  to U+05FF  - Hebrew
   * U+0600  to U+06FF  - Arabic
   * U+0700  to U+074F  - Syriac
   * U+0750  to U+077F  - Arabic Supplement
   * U+0780  to U+07BF  - Thaana
   * U+07C0  to U+07FF  - N'Ko
   * U+0800  to U+083F  - Samaritan
   *
   * Arabic Extended:
   * U+08A0  to U+08FF  - Arabic Extended-A
   *
   * Consecutive presentation forms:
   * U+FB1D  to U+FB4F  - Hebrew presentation forms
   * U+FB50  to U+FDFF  - Arabic presentation forms A
   *
   * More Arabic presentation forms:
   * U+FE70  to U+FEFF  - Arabic presentation forms B
   */
  var rtlChar = /[\u0590-\u083F]|[\u08A0-\u08FF]|[\uFB1D-\uFDFF]|[\uFE70-\uFEFF]/mg;
  var dirMark = /\u200e|\u200f/mg;
  var ltrMark = "\u200e";
  var rtlMark = "\u200f";
  var keyConstants = {
    BACKSPACE: 8,
    DELETE: 46
  };
  var twLength = 0;
  var DEFAULT_TCO_LENGTH = 22;
  var tcoLength = null;
  var isRTL = false;
  var originalText = "";
  var originalDir = "";
  // Can't use trim cause of IE. Regex from here: http://stackoverflow.com/questions/2308134/trim-in-javascript-not-working-in-ie
  var trimRegex = /^\s+|\s+$/g;

  var setManually = false;
  var heldKeyCodes =  { '91': false,
                        '16': false,
                        '88': false,
                        '17': false };
  var useCtrlKey = navigator.userAgent.indexOf('Mac') === -1;

  /* Private methods */

  // Caret manipulation
  function elementHasFocus (el) {
    // Try/catch to fix a bug in IE that will cause 'unspecified error' if another frame has focus
    try {
      return document.activeElement === el;
    }
    catch (err) {
      return false;
    }
  }

  function getCaretPosition (el) {
    if (!elementHasFocus(el)) { return 0; }

    var range;
    if (typeof el.selectionStart === "number") {
      return el.selectionStart;
    }
    else if (document.selection) {
      el.focus();
      range = document.selection.createRange();
      range.moveStart('character', -el.value.length);
      var length = range.text.length;
      return length;
    }
  }

  function setCaretPosition (el, position) {
    if (!elementHasFocus(el)) { return; }

    if (typeof el.selectionStart === "number") {
      el.selectionStart = position;
      el.selectionEnd = position;
    }
    else if (document.selection) {
      var range = el.createTextRange();
      range.collapse(true);
      range.moveEnd('character', position);
      range.moveStart('character', position);
      range.select();
    }
  }

  // End of caret methods

  function replaceIndices (oldText, extractFn, replaceCb) {
    var lastIndex = 0;
    var newText = '';
    var extractedItems = extractFn(oldText);

    for (var i = 0; i < extractedItems.length; i++) {
      var item = extractedItems[i];
      var type = '';

      if (item.screenName) {
        type = 'screenName';
      }
      if (item.hashtag) {
        type = 'hashtag';
      }
      if (item.url) {
        type = 'url';
      }
      if (item.cashtag) {
        type = 'cashtag';
      }

      var respObj = {
        entityText: oldText.slice(item.indices[0], item.indices[1]),
        entityType: type
      };

      newText += oldText.slice(lastIndex, item.indices[0]) + replaceCb(respObj);
      lastIndex = item.indices[1];
    }
    return newText + oldText.slice(lastIndex, oldText.length);
  }

  // Handle all LTR/RTL markers for tweet features
  function setMarkers (plainText) {
    var matchedRtlChars = plainText.match(rtlChar);
    var text = plainText;
    if (matchedRtlChars || originalDir === "rtl") {
      text = replaceIndices(text, twttr.txt.extractEntitiesWithIndices, function (itemObj) {
        if (itemObj.entityType === "screenName") {
          return ltrMark + itemObj.entityText + rtlMark;
        }
        else if (itemObj.entityType === "hashtag") {
          return (itemObj.entityText.charAt(1).match(rtlChar)) ? itemObj.entityText : ltrMark + itemObj.entityText;
        }
        else if (itemObj.entityType === "url") {
          return itemObj.entityText + ltrMark;
        }
        else if (itemObj.entityType === "cashtag") {
          return ltrMark + itemObj.entityText;
        }
      });
    }
    return text;
  }

  // If a user deletes a hidden marker char, it will just get rewritten during
  // notifyTextUpdated. Special case this by continuing to delete in the same
  // direction until a normal char is consumed.
  function erasePastMarkers (e) {
    var offset;
    var textarea = (e.target) ? e.target : e.srcElement;
    var key = (e.which) ? e.which : e.keyCode;
    if (key === keyConstants.BACKSPACE) { // backspace
      offset = -1;
    } else if (key === keyConstants.DELETE) { // delete forward
      offset = 0;
    } else {
      return;
    }

    var pos = getCaretPosition(textarea);
    var text = textarea.value;
    var numErased = 0;
    var charToDelete;
    do {
      charToDelete = text.charAt(pos + offset) || '';
      // Delete characters until a non-marker is removed.
      if (charToDelete) {
        pos += offset;
        numErased++;
        text = text.slice(0, pos) + text.slice(pos + 1, text.length);
      }
    } while (charToDelete.match(dirMark));

    if (numErased > 1) {
      textarea.value = text;
      // If more than 1 needed to be removed, update the text
      // and caret manually and stop the event.
      setCaretPosition(textarea, pos);
      e.preventDefault ? e.preventDefault() : e.returnValue = false;
    }
  }

  function removeMarkers (text) {
    return text ? text.replace(dirMark, '') : undefined;
  }

  function shouldBeRTL (plainText) {
    var matchedRtlChars = plainText.match(rtlChar);
    // Remove original placeholder text from this
    plainText = plainText.replace(originalText, "");
    var urlMentionsLength = 0;
    var trimmedText = plainText.replace(trimRegex, '');
    var defaultDir = originalDir;

    if (!trimmedText || !trimmedText.replace(/#/g, '')) {
      return defaultDir === 'rtl' ? true : false; // No text, use default.
    }

    if (!matchedRtlChars) {
      return false; // No RTL chars, use LTR
    }

    if (plainText) {
      var mentions = twttr.txt.extractMentionsWithIndices(plainText);
      var mentionsLength = mentions.length;
      var i;

      for (i = 0; i < mentionsLength; i++) {
        urlMentionsLength += mentions[i].screenName.length + 1;
      }

      var urls = twttr.txt.extractUrlsWithIndices(plainText);
      var urlsLength = urls.length;

      for (i = 0; i < urlsLength; i++) {
        urlMentionsLength += urls[i].url.length + 2;
      }

    }
    var length = trimmedText.length - urlMentionsLength;
    return length > 0 && matchedRtlChars.length / length > rtlThreshold;
  }

  function detectManualDirection (e) {
    var textarea = e.target || e.srcElement;
    if (e.type === "keydown" && (e.keyCode === 91 || e.keyCode === 16 || e.keyCode === 88 || e.keyCode === 17)) {
      heldKeyCodes[String(e.keyCode)] = true;
    }
    else if (e.type === "keyup" && (e.keyCode === 91 || e.keyCode === 16 || e.keyCode === 88 || e.keyCode === 17)) {
      heldKeyCodes[String(e.keyCode)] = false;
    }

    if (((!useCtrlKey && heldKeyCodes['91']) || (useCtrlKey && heldKeyCodes['17'])) && heldKeyCodes['16'] && heldKeyCodes['88']) {
      setManually = true;

      if (textarea.dir === 'rtl') {
        setTextDirection('ltr', textarea);
      }
      else {
        setTextDirection('rtl', textarea);
      }
      heldKeyCodes =  { '91': false,
                        '16': false,
                        '88': false,
                        '17': false };
    }
  }

  function setTextDirection (dir, textarea) {
    textarea.setAttribute('dir', dir);
    textarea.style.direction = dir;
    textarea.style.textAlign = (dir === 'rtl' ? 'right' : 'left');
  }

  /* Public methods */

  // Bind this to *both* keydown & keyup
  that.onTextChange = function (e) {
    var event = e || window.event;

    detectManualDirection(e);

    // Handle backspace through control characters:
    if (event.type === "keydown") {
      erasePastMarkers(event);
    }

    that.setText(event.target || event.srcElement);
  };

  // Optionally takes a second param, with original text, to exclude from RTL/LTR calculation
  that.setText = function (textarea) {
    // Original directionality could be in a few places. Check them all.
    if (!originalDir) {
      if (textarea.style.direction) {
        originalDir = textarea.style.direction;
      }
      else if (textarea.dir) {
        originalDir = textarea.dir;
      }
      else if (document.body.style.direction) {
        originalDir = document.body.style.direction;
      }
      else {
        originalDir = document.body.dir;
      }
    }

    if (arguments.length === 2) {
      originalDir = textarea.ownerDocument.documentElement.className;
      originalText = arguments[1];
    }

    var text = textarea.value;
    if (!text) {
      return;
    }
    var plainText = removeMarkers(text);
    isRTL = shouldBeRTL(plainText);
    var newText = setMarkers(plainText);
    var newTextDir = (isRTL ? 'rtl' : 'ltr');

    if (newText !== text) {
      // Fix for Chrome for Android
      textarea.value = "";
      textarea.focus();
      textarea.value = newText;
      // Assume any recent change in text length due to markers affects the
      // current cursor position. If more accuracy is needed, the position
      // could be translated during replace operations inside setMarkers.
      setCaretPosition(textarea, getCaretPosition(textarea) + newText.length - plainText.length);
    }
    if (!setManually) {
      setTextDirection(newTextDir, textarea);
    }
  };

  // Use this to get the length of a tweet with unicode control characters removed
  that.textLength = function (text) {
    var tweet = removeMarkers(text);
    var urls = twttr.txt.extractUrls(tweet);
    var length = tweet.length - urls.join('').length;
    var urlsLength = urls.length;
    var tcoLength = that.getTcoLength();
    for (var i = 0; i < urlsLength; i++) {
      length += tcoLength;
      if (/^https:/.test(urls[i])) {
        length += 1;
      }
    }

    return twLength = length;
  };

  // Do this before text is submitted
  that.cleanText = function (text) {
    return removeMarkers(text);
  };

  // If markers need to be added to a string without affecting the text box, use this
  that.addRTLMarkers = function (s) {
    return setMarkers(s);
  };

  // For determining if text should be RTL (returns boolean)
  that.shouldBeRTL = function (s) {
    return shouldBeRTL(s);
  };

  that.getTcoLength = function () {
    return tcoLength || DEFAULT_TCO_LENGTH;
  };
  that.setTcoLength = function (length) {
    if (length > 0) {
      tcoLength = parseInt(length, 10);
    } else {
      tcoLength = null;
    }
  };

  return that;

}();

if (typeof module !== 'undefined' && module.exports) {
  module.exports = RTLText;
}

<commit_msg>Return an empty string instead of undefined.<commit_after>/*
 * RTLText
 * Copyright 2012 Twitter and other contributors
 * Released under the MIT license
 *
 * What it does:
 *
 * This module will set the direction of a textarea to RTL when a threshold
 * of RTL characters has been reached (rtlThreshold). It also applies Twitter-
 * specific RTL rules regarding the placement of @ signs, # tags, and URLs.
 *
 * How to use:
 *
 * Bind keyup and keydown to RTLText.onTextChange. If you have initial text,
 * call RTLText.setText(textarea, initial_string) to set markers on that
 * initial text.
 */
var RTLText = function () {
  'use strict';

  var that = {};
  var rtlThreshold = 0.3;

  /*
   * Right-to-left Unicode blocks for modern scripts are:
   *
   * Consecutive range of the main letters:
   * U+0590  to U+05FF  - Hebrew
   * U+0600  to U+06FF  - Arabic
   * U+0700  to U+074F  - Syriac
   * U+0750  to U+077F  - Arabic Supplement
   * U+0780  to U+07BF  - Thaana
   * U+07C0  to U+07FF  - N'Ko
   * U+0800  to U+083F  - Samaritan
   *
   * Arabic Extended:
   * U+08A0  to U+08FF  - Arabic Extended-A
   *
   * Consecutive presentation forms:
   * U+FB1D  to U+FB4F  - Hebrew presentation forms
   * U+FB50  to U+FDFF  - Arabic presentation forms A
   *
   * More Arabic presentation forms:
   * U+FE70  to U+FEFF  - Arabic presentation forms B
   */
  var rtlChar = /[\u0590-\u083F]|[\u08A0-\u08FF]|[\uFB1D-\uFDFF]|[\uFE70-\uFEFF]/mg;
  var dirMark = /\u200e|\u200f/mg;
  var ltrMark = "\u200e";
  var rtlMark = "\u200f";
  var keyConstants = {
    BACKSPACE: 8,
    DELETE: 46
  };
  var twLength = 0;
  var DEFAULT_TCO_LENGTH = 22;
  var tcoLength = null;
  var isRTL = false;
  var originalText = "";
  var originalDir = "";
  // Can't use trim cause of IE. Regex from here: http://stackoverflow.com/questions/2308134/trim-in-javascript-not-working-in-ie
  var trimRegex = /^\s+|\s+$/g;

  var setManually = false;
  var heldKeyCodes =  { '91': false,
                        '16': false,
                        '88': false,
                        '17': false };
  var useCtrlKey = navigator.userAgent.indexOf('Mac') === -1;

  /* Private methods */

  // Caret manipulation
  function elementHasFocus (el) {
    // Try/catch to fix a bug in IE that will cause 'unspecified error' if another frame has focus
    try {
      return document.activeElement === el;
    }
    catch (err) {
      return false;
    }
  }

  function getCaretPosition (el) {
    if (!elementHasFocus(el)) { return 0; }

    var range;
    if (typeof el.selectionStart === "number") {
      return el.selectionStart;
    }
    else if (document.selection) {
      el.focus();
      range = document.selection.createRange();
      range.moveStart('character', -el.value.length);
      var length = range.text.length;
      return length;
    }
  }

  function setCaretPosition (el, position) {
    if (!elementHasFocus(el)) { return; }

    if (typeof el.selectionStart === "number") {
      el.selectionStart = position;
      el.selectionEnd = position;
    }
    else if (document.selection) {
      var range = el.createTextRange();
      range.collapse(true);
      range.moveEnd('character', position);
      range.moveStart('character', position);
      range.select();
    }
  }

  // End of caret methods

  function replaceIndices (oldText, extractFn, replaceCb) {
    var lastIndex = 0;
    var newText = '';
    var extractedItems = extractFn(oldText);

    for (var i = 0; i < extractedItems.length; i++) {
      var item = extractedItems[i];
      var type = '';

      if (item.screenName) {
        type = 'screenName';
      }
      if (item.hashtag) {
        type = 'hashtag';
      }
      if (item.url) {
        type = 'url';
      }
      if (item.cashtag) {
        type = 'cashtag';
      }

      var respObj = {
        entityText: oldText.slice(item.indices[0], item.indices[1]),
        entityType: type
      };

      newText += oldText.slice(lastIndex, item.indices[0]) + replaceCb(respObj);
      lastIndex = item.indices[1];
    }
    return newText + oldText.slice(lastIndex, oldText.length);
  }

  // Handle all LTR/RTL markers for tweet features
  function setMarkers (plainText) {
    var matchedRtlChars = plainText.match(rtlChar);
    var text = plainText;
    if (matchedRtlChars || originalDir === "rtl") {
      text = replaceIndices(text, twttr.txt.extractEntitiesWithIndices, function (itemObj) {
        if (itemObj.entityType === "screenName") {
          return ltrMark + itemObj.entityText + rtlMark;
        }
        else if (itemObj.entityType === "hashtag") {
          return (itemObj.entityText.charAt(1).match(rtlChar)) ? itemObj.entityText : ltrMark + itemObj.entityText;
        }
        else if (itemObj.entityType === "url") {
          return itemObj.entityText + ltrMark;
        }
        else if (itemObj.entityType === "cashtag") {
          return ltrMark + itemObj.entityText;
        }
      });
    }
    return text;
  }

  // If a user deletes a hidden marker char, it will just get rewritten during
  // notifyTextUpdated. Special case this by continuing to delete in the same
  // direction until a normal char is consumed.
  function erasePastMarkers (e) {
    var offset;
    var textarea = (e.target) ? e.target : e.srcElement;
    var key = (e.which) ? e.which : e.keyCode;
    if (key === keyConstants.BACKSPACE) { // backspace
      offset = -1;
    } else if (key === keyConstants.DELETE) { // delete forward
      offset = 0;
    } else {
      return;
    }

    var pos = getCaretPosition(textarea);
    var text = textarea.value;
    var numErased = 0;
    var charToDelete;
    do {
      charToDelete = text.charAt(pos + offset) || '';
      // Delete characters until a non-marker is removed.
      if (charToDelete) {
        pos += offset;
        numErased++;
        text = text.slice(0, pos) + text.slice(pos + 1, text.length);
      }
    } while (charToDelete.match(dirMark));

    if (numErased > 1) {
      textarea.value = text;
      // If more than 1 needed to be removed, update the text
      // and caret manually and stop the event.
      setCaretPosition(textarea, pos);
      e.preventDefault ? e.preventDefault() : e.returnValue = false;
    }
  }

  function removeMarkers (text) {
    return text ? text.replace(dirMark, '') : '';
  }

  function shouldBeRTL (plainText) {
    var matchedRtlChars = plainText.match(rtlChar);
    // Remove original placeholder text from this
    plainText = plainText.replace(originalText, "");
    var urlMentionsLength = 0;
    var trimmedText = plainText.replace(trimRegex, '');
    var defaultDir = originalDir;

    if (!trimmedText || !trimmedText.replace(/#/g, '')) {
      return defaultDir === 'rtl' ? true : false; // No text, use default.
    }

    if (!matchedRtlChars) {
      return false; // No RTL chars, use LTR
    }

    if (plainText) {
      var mentions = twttr.txt.extractMentionsWithIndices(plainText);
      var mentionsLength = mentions.length;
      var i;

      for (i = 0; i < mentionsLength; i++) {
        urlMentionsLength += mentions[i].screenName.length + 1;
      }

      var urls = twttr.txt.extractUrlsWithIndices(plainText);
      var urlsLength = urls.length;

      for (i = 0; i < urlsLength; i++) {
        urlMentionsLength += urls[i].url.length + 2;
      }

    }
    var length = trimmedText.length - urlMentionsLength;
    return length > 0 && matchedRtlChars.length / length > rtlThreshold;
  }

  function detectManualDirection (e) {
    var textarea = e.target || e.srcElement;
    if (e.type === "keydown" && (e.keyCode === 91 || e.keyCode === 16 || e.keyCode === 88 || e.keyCode === 17)) {
      heldKeyCodes[String(e.keyCode)] = true;
    }
    else if (e.type === "keyup" && (e.keyCode === 91 || e.keyCode === 16 || e.keyCode === 88 || e.keyCode === 17)) {
      heldKeyCodes[String(e.keyCode)] = false;
    }

    if (((!useCtrlKey && heldKeyCodes['91']) || (useCtrlKey && heldKeyCodes['17'])) && heldKeyCodes['16'] && heldKeyCodes['88']) {
      setManually = true;

      if (textarea.dir === 'rtl') {
        setTextDirection('ltr', textarea);
      }
      else {
        setTextDirection('rtl', textarea);
      }
      heldKeyCodes =  { '91': false,
                        '16': false,
                        '88': false,
                        '17': false };
    }
  }

  function setTextDirection (dir, textarea) {
    textarea.setAttribute('dir', dir);
    textarea.style.direction = dir;
    textarea.style.textAlign = (dir === 'rtl' ? 'right' : 'left');
  }

  /* Public methods */

  // Bind this to *both* keydown & keyup
  that.onTextChange = function (e) {
    var event = e || window.event;

    detectManualDirection(e);

    // Handle backspace through control characters:
    if (event.type === "keydown") {
      erasePastMarkers(event);
    }

    that.setText(event.target || event.srcElement);
  };

  // Optionally takes a second param, with original text, to exclude from RTL/LTR calculation
  that.setText = function (textarea) {
    // Original directionality could be in a few places. Check them all.
    if (!originalDir) {
      if (textarea.style.direction) {
        originalDir = textarea.style.direction;
      }
      else if (textarea.dir) {
        originalDir = textarea.dir;
      }
      else if (document.body.style.direction) {
        originalDir = document.body.style.direction;
      }
      else {
        originalDir = document.body.dir;
      }
    }

    if (arguments.length === 2) {
      originalDir = textarea.ownerDocument.documentElement.className;
      originalText = arguments[1];
    }

    var text = textarea.value;
    if (!text) {
      return;
    }
    var plainText = removeMarkers(text);
    isRTL = shouldBeRTL(plainText);
    var newText = setMarkers(plainText);
    var newTextDir = (isRTL ? 'rtl' : 'ltr');

    if (newText !== text) {
      // Fix for Chrome for Android
      textarea.value = "";
      textarea.focus();
      textarea.value = newText;
      // Assume any recent change in text length due to markers affects the
      // current cursor position. If more accuracy is needed, the position
      // could be translated during replace operations inside setMarkers.
      setCaretPosition(textarea, getCaretPosition(textarea) + newText.length - plainText.length);
    }
    if (!setManually) {
      setTextDirection(newTextDir, textarea);
    }
  };

  // Use this to get the length of a tweet with unicode control characters removed
  that.textLength = function (text) {
    var tweet = removeMarkers(text);
    var urls = twttr.txt.extractUrls(tweet);
    var length = tweet.length - urls.join('').length;
    var urlsLength = urls.length;
    var tcoLength = that.getTcoLength();
    for (var i = 0; i < urlsLength; i++) {
      length += tcoLength;
      if (/^https:/.test(urls[i])) {
        length += 1;
      }
    }

    return twLength = length;
  };

  // Do this before text is submitted
  that.cleanText = function (text) {
    return removeMarkers(text);
  };

  // If markers need to be added to a string without affecting the text box, use this
  that.addRTLMarkers = function (s) {
    return setMarkers(s);
  };

  // For determining if text should be RTL (returns boolean)
  that.shouldBeRTL = function (s) {
    return shouldBeRTL(s);
  };

  that.getTcoLength = function () {
    return tcoLength || DEFAULT_TCO_LENGTH;
  };
  that.setTcoLength = function (length) {
    if (length > 0) {
      tcoLength = parseInt(length, 10);
    } else {
      tcoLength = null;
    }
  };

  return that;

}();

if (typeof module !== 'undefined' && module.exports) {
  module.exports = RTLText;
}

<|endoftext|>