<commit_before>function World(scene) {
    var self = this;

    var seed = Math.random() * 100;

    var material0 = new THREE.MeshBasicMaterial({
        color: 0x00ff00,
        wireframe: true
    });
    var material1 = new THREE.MeshBasicMaterial({
        color: 0xA52A2A
    });

    var chunks = {};

    function chunkAt(cx, cy, cz, display) {
        var chunk = chunks[cx + ',' + cy + ',' + cz];
        if (!chunk) {
            chunk = Chunk.generateChunk(cx, cy, cz, self);
            chunks[cx + "," + cy + "," + cz] = chunk;
        }
        if (display) {
            displayChunk(chunk);
        }
        return chunk;
    }

    function displayChunk(chunk) {
        if (chunk.isDisplayed()) return;
        var mesh = chunk.createMesh(new THREE.MeshFaceMaterial([material0, material1]));
        scene.add(mesh);
    }

    function mod(a, b) {
        return (((a % b) + b) % b) | 0;
    }

    self.getSeed = function () {
        return seed;
    }

    self.getChunks = function () {
        return chunks;
    }

    self.addItem = function (position) {
        var cube = new THREE.Mesh( new THREE.CubeGeometry(0.1, 0.1, 0.1), new THREE.MeshNormalMaterial() );
        cube.position = position;
        scene.add(cube);
        console.log("Done", position);
    }

    self.loadChunk = function (cx, cy, cz) {
        var chunk = chunkAt(cx, cy, cz, true);
    }

    self.unloadChunk = function (cx, cy, cz) {
        var chunk = chunkAt(cx, cy, cz, false);
        chunk.remove(scene);
    }

    self.blockAt = function (wx, wy, wz) {
        var cx = Math.floor(wx / CHUNK_WIDTH);
        var cy = Math.floor(wy / CHUNK_HEIGHT);
        var cz = Math.floor(wz / CHUNK_DEPTH);
        var ox = mod(wx, CHUNK_WIDTH);
        var oy = mod(wy, CHUNK_HEIGHT);
        var oz = mod(wz, CHUNK_DEPTH);

        return chunkAt(cx, cy, cz, false).blockAt(ox, oy, oz);
    }

    self.findClosestGround = function (wx, wy, wz) {
        var cx = Math.floor(wx / CHUNK_WIDTH);
        var cy = Math.floor(wy / CHUNK_HEIGHT);
        var cz = Math.floor(wz / CHUNK_DEPTH);
        var ox = mod(wx, CHUNK_WIDTH);
        var oy = mod(wy, CHUNK_HEIGHT);
        var oz = mod(wz, CHUNK_DEPTH);

        var chunk = chunkAt(cx, cy, cz, true);
        var block;
        if (chunk.blockAt(ox, oy, oz).isType(Block.AIR)) {
            // Try and find ground below
            while (true) {
                if (oy-- < 0) {
                    oy = CHUNK_HEIGHT;
                    cy--;
                    chunk = chunkAt(cx, cy, cz, true);
                }
                block = chunk.blockAt(ox, oy, oz);
                if (block && block.isType(Block.DIRT)) {
                    return oy + cy * CHUNK_HEIGHT;
                }
            }
        } else if (chunk.blockAt(ox, oy, oz).isType(Block.DIRT)) {
            // Try and find air above
            while (true) {
                if (oy++ >= CHUNK_HEIGHT) {
                    oy = 0;
                    cy++;
                    chunk = chunkAt(cx, cy, cz, true);
                }
                block = chunk.blockAt(ox, oy, oz);
                if (block && block.isType(Block.AIR)) {
                    return oy - 1 + cy * CHUNK_HEIGHT;
                }
            }
        } else {
            throw "findClosestGround only knows how to deal with ground and air blocks.";
        }
    }
}<commit_msg>Remove a log message.<commit_after>function World(scene) {
    var self = this;

    var seed = Math.random() * 100;

    var material0 = new THREE.MeshBasicMaterial({
        color: 0x00ff00,
        wireframe: true
    });
    var material1 = new THREE.MeshBasicMaterial({
        color: 0xA52A2A
    });

    var chunks = {};

    function chunkAt(cx, cy, cz, display) {
        var chunk = chunks[cx + ',' + cy + ',' + cz];
        if (!chunk) {
            chunk = Chunk.generateChunk(cx, cy, cz, self);
            chunks[cx + "," + cy + "," + cz] = chunk;
        }
        if (display) {
            displayChunk(chunk);
        }
        return chunk;
    }

    function displayChunk(chunk) {
        if (chunk.isDisplayed()) return;
        var mesh = chunk.createMesh(new THREE.MeshFaceMaterial([material0, material1]));
        scene.add(mesh);
    }

    function mod(a, b) {
        return (((a % b) + b) % b) | 0;
    }

    self.getSeed = function () {
        return seed;
    }

    self.getChunks = function () {
        return chunks;
    }

    self.addItem = function (position) {
        var cube = new THREE.Mesh( new THREE.CubeGeometry(0.1, 0.1, 0.1), new THREE.MeshNormalMaterial() );
        cube.position = position;
        scene.add(cube);
    }

    self.loadChunk = function (cx, cy, cz) {
        var chunk = chunkAt(cx, cy, cz, true);
    }

    self.unloadChunk = function (cx, cy, cz) {
        var chunk = chunkAt(cx, cy, cz, false);
        chunk.remove(scene);
    }

    self.blockAt = function (wx, wy, wz) {
        var cx = Math.floor(wx / CHUNK_WIDTH);
        var cy = Math.floor(wy / CHUNK_HEIGHT);
        var cz = Math.floor(wz / CHUNK_DEPTH);
        var ox = mod(wx, CHUNK_WIDTH);
        var oy = mod(wy, CHUNK_HEIGHT);
        var oz = mod(wz, CHUNK_DEPTH);

        return chunkAt(cx, cy, cz, false).blockAt(ox, oy, oz);
    }

    self.findClosestGround = function (wx, wy, wz) {
        var cx = Math.floor(wx / CHUNK_WIDTH);
        var cy = Math.floor(wy / CHUNK_HEIGHT);
        var cz = Math.floor(wz / CHUNK_DEPTH);
        var ox = mod(wx, CHUNK_WIDTH);
        var oy = mod(wy, CHUNK_HEIGHT);
        var oz = mod(wz, CHUNK_DEPTH);

        var chunk = chunkAt(cx, cy, cz, true);
        var block;
        if (chunk.blockAt(ox, oy, oz).isType(Block.AIR)) {
            // Try and find ground below
            while (true) {
                if (oy-- < 0) {
                    oy = CHUNK_HEIGHT;
                    cy--;
                    chunk = chunkAt(cx, cy, cz, true);
                }
                block = chunk.blockAt(ox, oy, oz);
                if (block && block.isType(Block.DIRT)) {
                    return oy + cy * CHUNK_HEIGHT;
                }
            }
        } else if (chunk.blockAt(ox, oy, oz).isType(Block.DIRT)) {
            // Try and find air above
            while (true) {
                if (oy++ >= CHUNK_HEIGHT) {
                    oy = 0;
                    cy++;
                    chunk = chunkAt(cx, cy, cz, true);
                }
                block = chunk.blockAt(ox, oy, oz);
                if (block && block.isType(Block.AIR)) {
                    return oy - 1 + cy * CHUNK_HEIGHT;
                }
            }
        } else {
            throw "findClosestGround only knows how to deal with ground and air blocks.";
        }
    }
}<|endoftext|>


<commit_before>import gulp from "gulp";
import start from "gulp-start-process";
import ps from "ps-node";
import config from "../config";

var dotnetProcess = null;
var starting = false;

function startDotnet(stream, cb) {
    if( starting ) return;

    starting = true;

    ps.lookup({}, (error, resultList) => {
        if (error) throw new Error(error);

        var processFound = null;

        resultList.forEach(process => {
            if (process.command.indexOf(config.paths.dotnetProcessString) > 0) {
                processFound = process;
                return;
            }
        });

        let dotnetStart = () => {
            dotnetProcess = start("dotnet run", { setsid: true }, cb);
            starting = false;
        };

        if (processFound != null) {
            ps.kill(processFound.pid, (error) => {

                if (error) throw new Error(error);

                dotnetStart();
            });
        } else {
            dotnetStart();
        }
    });
}

export function dotnetPipeline(stream, cb) {
    startDotnet(stream, cb);
}

gulp.task("dotnet", cb => {
    dotnetPipeline(null, cb);
});<commit_msg>Using arguments to identify process instead<commit_after>import gulp from "gulp";
import start from "gulp-start-process";
import ps from "ps-node";
import config from "../config";

var dotnetProcess = null;
var starting = false;

function startDotnet(stream, cb) {
    if( starting ) return;

    starting = true;

    ps.lookup({}, (error, resultList) => {
        if (error) throw new Error(error);

        var processFound = null;

        resultList.forEach(process => {
            for( var argumentIndex=0; argumentIndex<process.arguments.length; argumentIndex++ ) {
                var argument = process.arguments[argumentIndex];
                if (argument.indexOf(config.paths.dotnetProcessString) > 0) {
                    processFound = process;
                    return;
                }
            }
        });

        let dotnetStart = () => {
            dotnetProcess = start("dotnet run", { setsid: true }, cb);
            starting = false;
        };

        if (processFound != null) {
            try {
                ps.kill(processFound.pid, (error) => {
                    dotnetStart();
                });
            } catch( e ) {
                // Do nothing
            }
        } else {
            dotnetStart();
        }
    });
}

export function dotnetPipeline(stream, cb) {
    startDotnet(stream, cb);
}

gulp.task("dotnet", cb => {
    dotnetPipeline(null, cb);
});<|endoftext|>


<commit_before>import gulp from 'gulp';
import htmlmin from 'gulp-htmlmin';
import critical from 'critical';
import config from '../config/markup';

gulp.task('markup', callback => {
  critical.generate(config.critical).then(function (output) {
    gulp.src(config.src)
      .pipe(htmlmin(config.htmlmin))
      .pipe(gulp.dest(config.dest));
    return callback();
  });
});
<commit_msg>Add timeout<commit_after>import gulp from 'gulp';
import htmlmin from 'gulp-htmlmin';
import critical from 'critical';
import config from '../config/markup';

gulp.task('markup', callback => {
  critical.generate(config.critical).then(function (output) {
    gulp.src(config.src)
      .pipe(htmlmin(config.htmlmin))
      .pipe(gulp.dest(config.dest));

    return setTimeout(callback, 1000);
  });
});
<|endoftext|>


<commit_before>var bindFacebookEvents, initializeFacebookSDK, loadFacebookSDK, restoreFacebookRoot, saveFacebookRoot;

$(function () {
  loadFacebookSDK();
  if (!window.fbEventsBound) {
    return bindFacebookEvents();
  }
});

bindFacebookEvents = function () {
  $(document).on('page:fetch', saveFacebookRoot).on('page:change', restoreFacebookRoot).on('page:load', function () {
    return typeof FB !== "undefined" && FB !== null ? FB.XFBML.parse() : void 0;
  });
  return this.fbEventsBound = true;
};

saveFacebookRoot = function () {
  if ($('#fb-root').length) {
    return this.fbRoot = $('#fb-root').detach();
  }
};

restoreFacebookRoot = function () {
  if (this.fbRoot != null) {
    if ($('#fb-root').length) {
      return $('#fb-root').replaceWith(this.fbRoot);
    } else {
      return $('body').append(this.fbRoot);
    }
  }
};

loadFacebookSDK = function () {
  window.fbAsyncInit = initializeFacebookSDK;
  return $.getScript("//connect.facebook.net/" + window.mumukiLocale.facebook_code + "/sdk.js#xfbml=1&version=v2.5");
};

initializeFacebookSDK = function () {
  return FB.init({
    status: true,
    cookie: true,
    xfbml: true,
    version: 'v2.5'
  });
};
<commit_msg>fix facebook_code null<commit_after>var bindFacebookEvents, initializeFacebookSDK, loadFacebookSDK, restoreFacebookRoot, saveFacebookRoot;

$(function () {
  loadFacebookSDK();
  if (!window.fbEventsBound) {
    return bindFacebookEvents();
  }
});

bindFacebookEvents = function () {
  $(document).on('page:fetch', saveFacebookRoot).on('page:change', restoreFacebookRoot).on('page:load', function () {
    return typeof FB !== "undefined" && FB !== null ? FB.XFBML.parse() : void 0;
  });
  return this.fbEventsBound = true;
};

saveFacebookRoot = function () {
  if ($('#fb-root').length) {
    return this.fbRoot = $('#fb-root').detach();
  }
};

restoreFacebookRoot = function () {
  if (this.fbRoot != null) {
    if ($('#fb-root').length) {
      return $('#fb-root').replaceWith(this.fbRoot);
    } else {
      return $('body').append(this.fbRoot);
    }
  }
};

loadFacebookSDK = function () {
  window.fbAsyncInit = initializeFacebookSDK;
  return $.getScript("//connect.facebook.net/" + (window.mumukiLocale && window.mumukiLocale.facebook_code) + "/sdk.js#xfbml=1&version=v2.5");
};

initializeFacebookSDK = function () {
  return FB.init({
    status: true,
    cookie: true,
    xfbml: true,
    version: 'v2.5'
  });
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  Image,
  View,
  Navigator,
  TouchableHighlight
} from 'react-native';

import UserDogs from './UserDogs';
import TestPage from './TestPage';
import UserSignup from './UserSignup';
import Login from './Login';
import DogCreate from './DogCreate';
import WelcomePage from './WelcomePage';
import UserEdit from './UserEdit'
import MapScene from './MapScene'

const styles = require('./style.js')

class MainScene extends Component {
  onPressDogs() {
    console.log("onPressDogs");
    var property = "";

    this.props.navigator.push({
      title: 'Dogs',
      component: UserDogs,
      passProps: { user_id: 1 },
    });
  }

  onPressTestPage() {
    this.props.navigator.push({
      component: TestPage,
    });
  }

  onPressUserSignup() {
    this.props.navigator.push({
      component: UserSignup,
    });
  }

  onPressLogin() {
    this.props.navigator.push({
      component: Login,
    });
  }

  onPressDogCreate() {
    this.props.navigator.push({
      component: DogCreate,
    });
  }

  onPressWelcomePage() {
    this.props.navigator.push({
      component: WelcomePage,
    });
  }

  onPressMapScene() {
    this.props.navigator.push({
      component: MapScene,
    });
  }

  render(){
    return(
      <Image source={require('./Resources/0.jpg')} style={styles.bImage}>

          <View style={styles.topMargin}></View>
            <View style={styles.container}>
              <View style={styles.outterMargin}>
              </View>
                <View style={styles.content}>

                <Text>Hola a todos!</Text>
                <TouchableHighlight
                  style={styles.button}
                  onPress={this.onPressDogs.bind(this)}>

                  <Text style={styles.buttonText}>
                    Dogs
                  </Text>
                </TouchableHighlight>
                <TouchableHighlight
                  style={styles.button}
                  onPress={this.onPressTestPage.bind(this)}>
                  <Text style={styles.buttonText}>
                    Test Page
                  </Text>
                </TouchableHighlight>
                <TouchableHighlight
                  style={styles.button}
                  onPress={this.onPressUserSignup.bind(this)}>
                  <Text style={styles.buttonText}>
                    Sign Up
                  </Text>
                </TouchableHighlight>
                <TouchableHighlight
                  style={styles.button}
                  onPress={this.onPressLogin.bind(this)}>
                  <Text style={styles.buttonText}>
                    Login
                  </Text>
                </TouchableHighlight>
                <TouchableHighlight
                  style={styles.button}
                  onPress={this.onPressDogCreate.bind(this)}>
                  <Text style={styles.buttonText}>
                    Create a Dog
                  </Text>
                </TouchableHighlight>
                <TouchableHighlight
                  style={styles.button}
                  onPress={this.onPressWelcomePage.bind(this)}>
                  <Text style={styles.buttonText}>
                    Welcome Page
                  </Text>
                </TouchableHighlight>
                <TouchableHighlight
                  style={styles.button}
                  onPress={this.onPressMapScene.bind(this)}>
                  <Text style={styles.buttonText}>
                    Map
                  </Text>
                </TouchableHighlight>
                </View>
              <View style={styles.outterMargin}>
            </View>
          </View>
      </Image>

    );
  }
}

module.exports = MainScene;
<commit_msg>Add session logic and routing<commit_after>import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  Image,
  View,
  Navigator,
  TouchableHighlight,
  TabBarIOS,
  selectedTab,
} from 'react-native';

import UserDogs from './UserDogs';
import TestPage from './TestPage';
import UserSignup from './UserSignup';
import Login from './Login';
import DogCreate from './DogCreate';
import WelcomePage from './WelcomePage';
import UserEdit from './UserEdit'
import MapScene from './MapScene'
import PlayDates from './PlayDates'

var base64Icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAQAAACSR7JhAAADtUlEQVR4Ac3YA2Bj6QLH0XPT1Fzbtm29tW3btm3bfLZtv7e2ObZnms7d8Uw098tuetPzrxv8wiISrtVudrG2JXQZ4VOv+qUfmqCGGl1mqLhoA52oZlb0mrjsnhKpgeUNEs91Z0pd1kvihA3ULGVHiQO2narKSHKkEMulm9VgUyE60s1aWoMQUbpZOWE+kaqs4eLEjdIlZTcFZB0ndc1+lhB1lZrIuk5P2aib1NBpZaL+JaOGIt0ls47SKzLC7CqrlGF6RZ09HGoNy1lYl2aRSWL5GuzqWU1KafRdoRp0iOQEiDzgZPnG6DbldcomadViflnl/cL93tOoVbsOLVM2jylvdWjXolWX1hmfZbGR/wjypDjFLSZIRov09BgYmtUqPQPlQrPapecLgTIy0jMgPKtTeob2zWtrGH3xvjUkPCtNg/tm1rjwrMa+mdUkPd3hWbH0jArPGiU9ufCsNNWFZ40wpwn+62/66R2RUtoso1OB34tnLOcy7YB1fUdc9e0q3yru8PGM773vXsuZ5YIZX+5xmHwHGVvlrGPN6ZSiP1smOsMMde40wKv2VmwPPVXNut4sVpUreZiLBHi0qln/VQeI/LTMYXpsJtFiclUN+5HVZazim+Ky+7sAvxWnvjXrJFneVtLWLyPJu9K3cXLWeOlbMTlrIelbMDlrLenrjEQOtIF+fuI9xRp9ZBFp6+b6WT8RrxEpdK64BuvHgDk+vUy+b5hYk6zfyfs051gRoNO1usU12WWRWL73/MMEy9pMi9qIrR4ZpV16Rrvduxazmy1FSvuFXRkqTnE7m2kdb5U8xGjLw/spRr1uTov4uOgQE+0N/DvFrG/Jt7i/FzwxbA9kDanhf2w+t4V97G8lrT7wc08aA2QNUkuTfW/KimT01wdlfK4yEw030VfT0RtZbzjeMprNq8m8tnSTASrTLti64oBNdpmMQm0eEwvfPwRbUBywG5TzjPCsdwk3IeAXjQblLCoXnDVeoAz6SfJNk5TTzytCNZk/POtTSV40NwOFWzw86wNJRpubpXsn60NJFlHeqlYRbslqZm2jnEZ3qcSKgm0kTli3zZVS7y/iivZTweYXJ26Y+RTbV1zh3hYkgyFGSTKPfRVbRqWWVReaxYeSLarYv1Qqsmh1s95S7G+eEWK0f3jYKTbV6bOwepjfhtafsvUsqrQvrGC8YhmnO9cSCk3yuY984F1vesdHYhWJ5FvASlacshUsajFt2mUM9pqzvKGcyNJW0arTKN1GGGzQlH0tXwLDgQTurS8eIQAAAABJRU5ErkJggg==';

const styles = require('./style.js')

class MainScene extends Component {
  constructor(props){
    super(props);
    this.state = {
      selectedTab: "main",
    };
  }
  renderScene(route, navigator){
    console.log("renderScene was called: passProps: " + route.passProps);
    return(
      <route.component navigator={navigator} {...route.passProps}/>
    );
  }
  render(){
    return(
      <TabBarIOS
        barTintColor= "black"
        unselectedTintColor= "red"
        tintColor="white"
        selectedTab={this.state.selectedTab}
      >
         <TabBarIOS.Item
          icon = {{uri: base64Icon, scale: 3}}
          title = "Home"
          selected = {this.state.selectedTab === "main"}
          onPress = {() => {
            console.log("TabBarIOS was Pressed");
            console.log("navigator: " + this.props.navigator);
            this.setState({
              selectedTab: "main"
            });
          }}
         >

           <Navigator
             renderScene = {this.renderScene}
             initialRoute = {{
             title: 'PuppyPlayDate',
             component: MapScene,
           }}
           />
         </TabBarIOS.Item>

         <TabBarIOS.Item
          title = "Profile"
          selected = {this.state.selectedTab === "profile"}
          icon = {{uri: base64Icon, scale: 3}}
          onPress = {() => {
            this.setState({
              selectedTab: "profile"
            });
          }}
         >
         <Navigator
         renderScene = {this.renderScene}
         initialRoute = {{
           title: 'Profile',
           component: UserDogs,
           passProps: { user_id: 1 },
         }}
         />
        </TabBarIOS.Item>

        <TabBarIOS.Item
         title = "PlayDates"
         selected = {this.state.selectedTab === "playdates"}
         icon = {{uri: base64Icon, scale: 3}}
         onPress = {() => {
           this.setState({
             selectedTab: "playdates"
           });
         }}
        >
        <Navigator
        renderScene = {this.renderScene}
        initialRoute = {{
          title: 'PlayDates',
          component: PlayDates,
        }}
        />
       </TabBarIOS.Item>

       <TabBarIOS.Item
        title = "Test"
        selected = {this.state.selectedTab === "test"}
        icon = {{uri: base64Icon, scale: 3}}
        onPress = {() => {
          this.setState({
            selectedTab: "test"
          });
        }}
       >
       <Navigator
       renderScene = {this.renderScene}
       initialRoute = {{
         title: 'Test',
         component: TestPage,
       }}
       />
      </TabBarIOS.Item>

      </TabBarIOS>

    );
  }
}

module.exports = MainScene;
<|endoftext|>


<commit_before>/**
	The MIT License (MIT)

	Copyright (c) 2014 MyChannel-Apps.de

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.

	@author		Adrian Preuß <Bizarrus>, Christoph Kühl <djchrisnet>
	@docs		http://www.mychannel-apps.de/documentation/core/bot
*/

var Bot = (new function Bot() {
	var _user = KnuddelsServer.getDefaultBotUser();
	var textFilter = '';

	/*
		@docs	TODO
	*/
	this.setTextFilter = function setTextFilter(text) {
		var countBOLD = text.split("_").length-1;

		if(countBOLD % 2 !== 0){
			text = text.replace(/_/g, '');
		}

		var countKUGEL = text.split("°").length-1;

		if(countKUGEL % 2 !== 0){
			text = text.replace(/°/g, '');
		}
		textFilter = text;
		return text;
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getAge
	*/
	this.getAge = function getAge() {
		return _user.getAge();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getGender
	*/
	this.getGender = function getGender() {
		return _user.getGender();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getKnuddelAmount
	*/
	this.getKnuddelAmount = function getKnuddelAmount() {
		return _user.getKnuddelAmount();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getNick
	*/
	this.getNick = function getNick() {
		return _user.getNick();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getOnlineMinutes
	*/
	this.getOnlineMinutes = function getOnlineMinutes() {
		return _user.getOnlineMinutes();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getProfileLink
	*/
	this.getProfileLink	= function getProfileLink(displayText) {
		return _user.getProfileLink(displayText == undefined ? this.getNick() : displayText);
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getProfilePicture
	*/
	this.getProfilePicture	= function getProfilePicture() {
		return 'http://chat.knuddels.de/pics/fotos/knuddels.de?n=' + _user.getNick().urlencode();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getReadme
	*/
	this.getReadme = function getReadme() {
		return _user.getReadme();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getRegDate
	*/
	this.getRegDate = function getRegDate() {
		return _user.getRegDate();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getUserId
	*/
	this.getUserId = function getUserId() {
		return _user.getUserId();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getUserStatus
	*/
	this.getUserStatus = function getUserStatus() {
		return _user.getUserStatus();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getUserType
	*/
	this.getUserType = function getUserType() {
		return _user.getUserType();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isAppDeveloper
	*/
	this.isAppDeveloper = function isAppDeveloper() {
		return _user.isAppDeveloper();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isAppManager
	*/
	this.isAppManager = function isAppManager() {
		return _user.isAppManager();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isAway
	*/
	this.isAway = function isAway() {
		return _user.isAway();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isChannelModerator
	*/
	this.isChannelModerator = function isChannelModerator() {
		return _user.isChannelModerator();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isChannelOwner
	*/
	this.isChannelOwner = function isChannelOwner() {
		return _user.isChannelOwner();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isColorMuted
	*/
	this.isColorMuted = function isColorMuted() {
		return _user.isColorMuted();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isEventModerator
	*/
	this.isEventModerator = function isEventModerator() {
		return _user.isEventModerator();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isLocked
	*/
	this.isLocked = function isLocked() {
		return _user.isLocked();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isMuted
	*/
	this.isMuted = function isMuted() {
		return _user.isMuted();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isOnline
	*/
	this.isOnline = function isOnline() {
		return _user.isOnline();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isOnlineInChannel
	*/
	this.isOnlineInChannel = function isOnlineInChannel() {
		return _user.isOnlineInChannel();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_join
	*/
	this.join = function join() {
		_user.joinChannel();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_leave
	*/
	this.leave = function leave() {
		_user.leaveChannel();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_knuddel
		@TODO	UPDATE DOCS
	*/
	this.knuddel = function knuddel(user, amount, arg1, arg2) {
		if(!isTypeOf(amount, 'KnuddelAmount')) {
			amount = new KnuddelAmount(amount);
		}

		var params = {};

		if(arg1 !== undefined) {
			if(isTypeOf(arg1, 'string')) { params['displayReasonText'] = textFilter+arg1+'§'; }
			if(isTypeOf(arg1, 'boolean')) { params['hidePublicMessage'] = !(arg1); }
		}

		if(arg2 !== undefined) {
			if(isTypeOf(arg2, 'string')) { params['displayReasonText'] = textFilter+arg2+'§'; }
			if(isTypeOf(arg2, 'boolean')) { params['hidePublicMessage'] = !(arg2); }
		}

		if(params.size()) {
			_user.transferKnuddel(user, amount, params);
		} else {
			_user.transferKnuddel(user, amount);
		}
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getKnuddels
	*/
	this.getKnuddels = function getKnuddels() {
		return _user.getKnuddelAmount().asNumber();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_exception
	*/
	this.exception = function exception(exception) {
		_user.sendPublicMessage(textFilter+'°RR°_Exception:_°r°#' + (exception.message == undefined ? exception : exception.message));
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_publicMessage
	*/
	this.publicMessage = function publicMessage(message) {
		Logger.info('Bot.publicMessage(message) is DEPRECATED');

		this.public(message);
	}

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_postMessage
	*/
	this.postMessage = function postMessage(user, message, topic) {
		Logger.info('Bot.postMessage(user, message, topic) is DEPRECATED');

		this.post(user, message, topic);
	}

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_privateMessage
	*/
	this.privateMessage = function privateMessage(user, message) {
		Logger.info('Bot.privateMessage(user, message) is DEPRECATED');

		this.private(user, message);
	}

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_public
		@docs	TODO
	*/
	this.public = function public(message, delay) {
		if(message instanceof KCode) {
			message = message.toString();
		}

		if (delay) {
            return setTimeout(function publicDelay() {
                _user.sendPublicMessage(textFilter+message);
            }, delay);
        } else {
            _user.sendPublicMessage(textFilter+message);
        }
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_post
	*/
	this.post = function post(nick, message, topic) {
		if(message instanceof KCode) {
			message = message.toString();
		}

		if(topic == undefined) {
			topic = '';
		}

		// send to online users
		if(nick == undefined) {
			Channel.getUsers().each(function(user) {
				user.sendPostMessage(topic, textFilter+message);
			});
		} else {
			if(isTypeOf(nick, 'User')) {
				nick.sendPostMessage(topic, message);
			} else if(isTypeOf(nick, 'object') || isTypeOf(nick, 'array')) {
				nick.each(function(n) {
					Bot.post(n, textFilter+message, topic);
				});
			} else {
				Users.get(nick).sendPostMessage(topic, textFilter+message);
			}
		}
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_private
		@docs	TODO
	*/
	this.private = function private(nick, message, delay) {
		if(message instanceof KCode) {
			message = message.toString();
		}

		if (delay) {
            return setTimeout(function privateDelay() {
				// send to online users
				if(nick == undefined) {
					Channel.getUsers().each(function(user) {
						user.sendPrivateMessage(textFilter+message);
					});
				} else {
					if(isTypeOf(nick, 'User')) {
						nick.sendPrivateMessage(textFilter+message);
					} else if(isTypeOf(nick, 'object') || isTypeOf(nick, 'array')) {
						nick.each(function(n) {
							Bot.private(n, textFilter+message);
						});
					} else {
						var nick = Users.get(nick);
						if(nick != undefined) {
							nick.sendPrivateMessage(textFilter+message);
						}
					}
				}
            }, delay);
        } else {
			// send to online users
			if(nick == undefined) {
				Channel.getUsers().each(function(user) {
					user.sendPrivateMessage(textFilter+message);
				});
			} else {
				if(isTypeOf(nick, 'User')) {
					nick.sendPrivateMessage(textFilter+message);
				} else if(isTypeOf(nick, 'object') || isTypeOf(nick, 'array')) {
					nick.each(function(n) {
						Bot.private(n, textFilter+message);
					});
				} else {
					var nick = Users.get(nick);
					if(nick != undefined) {
						nick.sendPrivateMessage(textFilter+message);
					}
				}
			}
        }
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_exec
	*/
	this.exec = function exec(command) {
		_user.sendToChannel(command);
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_toString
	*/
	this.toString = function toString() {
		return '[KFramework Bot]';
	};
}());<commit_msg>Bot.clearTextFilter()<commit_after>/**
	The MIT License (MIT)

	Copyright (c) 2014 MyChannel-Apps.de

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.

	@author		Adrian Preuß <Bizarrus>, Christoph Kühl <djchrisnet>
	@docs		http://www.mychannel-apps.de/documentation/core/bot
*/

var Bot = (new function Bot() {
	var _user = KnuddelsServer.getDefaultBotUser();
	var textFilter = '';

	/*
		@docs	TODO
	*/
	this.setTextFilter = function setTextFilter(text) {
		var countBOLD = text.split("_").length-1;

		if(countBOLD % 2 !== 0){
			text = text.replace(/_/g, '');
		}

		var countKUGEL = text.split("°").length-1;

		if(countKUGEL % 2 !== 0){
			text = text.replace(/°/g, '');
		}
		textFilter = text;
		return text;
	};

	/*
		@docs	TODO
	*/
	this.clearTextFilter = function clearTextFilter() {
		textFilter = '';
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getAge
	*/
	this.getAge = function getAge() {
		return _user.getAge();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getGender
	*/
	this.getGender = function getGender() {
		return _user.getGender();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getKnuddelAmount
	*/
	this.getKnuddelAmount = function getKnuddelAmount() {
		return _user.getKnuddelAmount();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getNick
	*/
	this.getNick = function getNick() {
		return _user.getNick();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getOnlineMinutes
	*/
	this.getOnlineMinutes = function getOnlineMinutes() {
		return _user.getOnlineMinutes();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getProfileLink
	*/
	this.getProfileLink	= function getProfileLink(displayText) {
		return _user.getProfileLink(displayText == undefined ? this.getNick() : displayText);
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getProfilePicture
	*/
	this.getProfilePicture	= function getProfilePicture() {
		return 'http://chat.knuddels.de/pics/fotos/knuddels.de?n=' + _user.getNick().urlencode();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getReadme
	*/
	this.getReadme = function getReadme() {
		return _user.getReadme();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getRegDate
	*/
	this.getRegDate = function getRegDate() {
		return _user.getRegDate();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getUserId
	*/
	this.getUserId = function getUserId() {
		return _user.getUserId();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getUserStatus
	*/
	this.getUserStatus = function getUserStatus() {
		return _user.getUserStatus();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getUserType
	*/
	this.getUserType = function getUserType() {
		return _user.getUserType();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isAppDeveloper
	*/
	this.isAppDeveloper = function isAppDeveloper() {
		return _user.isAppDeveloper();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isAppManager
	*/
	this.isAppManager = function isAppManager() {
		return _user.isAppManager();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isAway
	*/
	this.isAway = function isAway() {
		return _user.isAway();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isChannelModerator
	*/
	this.isChannelModerator = function isChannelModerator() {
		return _user.isChannelModerator();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isChannelOwner
	*/
	this.isChannelOwner = function isChannelOwner() {
		return _user.isChannelOwner();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isColorMuted
	*/
	this.isColorMuted = function isColorMuted() {
		return _user.isColorMuted();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isEventModerator
	*/
	this.isEventModerator = function isEventModerator() {
		return _user.isEventModerator();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isLocked
	*/
	this.isLocked = function isLocked() {
		return _user.isLocked();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isMuted
	*/
	this.isMuted = function isMuted() {
		return _user.isMuted();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isOnline
	*/
	this.isOnline = function isOnline() {
		return _user.isOnline();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_isOnlineInChannel
	*/
	this.isOnlineInChannel = function isOnlineInChannel() {
		return _user.isOnlineInChannel();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_join
	*/
	this.join = function join() {
		_user.joinChannel();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_leave
	*/
	this.leave = function leave() {
		_user.leaveChannel();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_knuddel
		@TODO	UPDATE DOCS
	*/
	this.knuddel = function knuddel(user, amount, arg1, arg2) {
		if(!isTypeOf(amount, 'KnuddelAmount')) {
			amount = new KnuddelAmount(amount);
		}

		var params = {};

		if(arg1 !== undefined) {
			if(isTypeOf(arg1, 'string')) { params['displayReasonText'] = textFilter+arg1+'§'; }
			if(isTypeOf(arg1, 'boolean')) { params['hidePublicMessage'] = !(arg1); }
		}

		if(arg2 !== undefined) {
			if(isTypeOf(arg2, 'string')) { params['displayReasonText'] = textFilter+arg2+'§'; }
			if(isTypeOf(arg2, 'boolean')) { params['hidePublicMessage'] = !(arg2); }
		}

		if(params.size()) {
			_user.transferKnuddel(user, amount, params);
		} else {
			_user.transferKnuddel(user, amount);
		}
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_getKnuddels
	*/
	this.getKnuddels = function getKnuddels() {
		return _user.getKnuddelAmount().asNumber();
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_exception
	*/
	this.exception = function exception(exception) {
		_user.sendPublicMessage(textFilter+'°RR°_Exception:_°r°#' + (exception.message == undefined ? exception : exception.message));
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_publicMessage
	*/
	this.publicMessage = function publicMessage(message) {
		Logger.info('Bot.publicMessage(message) is DEPRECATED');

		this.public(message);
	}

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_postMessage
	*/
	this.postMessage = function postMessage(user, message, topic) {
		Logger.info('Bot.postMessage(user, message, topic) is DEPRECATED');

		this.post(user, message, topic);
	}

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_privateMessage
	*/
	this.privateMessage = function privateMessage(user, message) {
		Logger.info('Bot.privateMessage(user, message) is DEPRECATED');

		this.private(user, message);
	}

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_public
		@docs	TODO
	*/
	this.public = function public(message, delay) {
		if(message instanceof KCode) {
			message = message.toString();
		}

		if (delay) {
            return setTimeout(function publicDelay() {
                _user.sendPublicMessage(textFilter+message);
            }, delay);
        } else {
            _user.sendPublicMessage(textFilter+message);
        }
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_post
	*/
	this.post = function post(nick, message, topic) {
		if(message instanceof KCode) {
			message = message.toString();
		}

		if(topic == undefined) {
			topic = '';
		}

		// send to online users
		if(nick == undefined) {
			Channel.getUsers().each(function(user) {
				user.sendPostMessage(topic, textFilter+message);
			});
		} else {
			if(isTypeOf(nick, 'User')) {
				nick.sendPostMessage(topic, message);
			} else if(isTypeOf(nick, 'object') || isTypeOf(nick, 'array')) {
				nick.each(function(n) {
					Bot.post(n, textFilter+message, topic);
				});
			} else {
				Users.get(nick).sendPostMessage(topic, textFilter+message);
			}
		}
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_private
		@docs	TODO
	*/
	this.private = function private(nick, message, delay) {
		if(message instanceof KCode) {
			message = message.toString();
		}

		if (delay) {
            return setTimeout(function privateDelay() {
				// send to online users
				if(nick == undefined) {
					Channel.getUsers().each(function(user) {
						user.sendPrivateMessage(textFilter+message);
					});
				} else {
					if(isTypeOf(nick, 'User')) {
						nick.sendPrivateMessage(textFilter+message);
					} else if(isTypeOf(nick, 'object') || isTypeOf(nick, 'array')) {
						nick.each(function(n) {
							Bot.private(n, textFilter+message);
						});
					} else {
						var nick = Users.get(nick);
						if(nick != undefined) {
							nick.sendPrivateMessage(textFilter+message);
						}
					}
				}
            }, delay);
        } else {
			// send to online users
			if(nick == undefined) {
				Channel.getUsers().each(function(user) {
					user.sendPrivateMessage(textFilter+message);
				});
			} else {
				if(isTypeOf(nick, 'User')) {
					nick.sendPrivateMessage(textFilter+message);
				} else if(isTypeOf(nick, 'object') || isTypeOf(nick, 'array')) {
					nick.each(function(n) {
						Bot.private(n, textFilter+message);
					});
				} else {
					var nick = Users.get(nick);
					if(nick != undefined) {
						nick.sendPrivateMessage(textFilter+message);
					}
				}
			}
        }
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_exec
	*/
	this.exec = function exec(command) {
		_user.sendToChannel(command);
	};

	/*
		@docs	http://www.mychannel-apps.de/documentation/Bot_toString
	*/
	this.toString = function toString() {
		return '[KFramework Bot]';
	};
}());<|endoftext|>


<commit_before>'use strict'
const Trend = require('../models/trend')
const config = require('../../config')
const sentimentUtils = require('./sentiment-utils')

/**
 * Contains utility functions used to query and update the database.
 */
const dbUtils = {
  /**
   * Removes all trends from the database not located in the currTrends array.
   *
   * @param  {Array} currTrends Array of trend names (as strings) that are still trending, trends not in this array will be removed from the db
   */
  removeOldTrends: function (currTrends) {
    return new Promise((resolve, reject) => {
      Trend.remove({name: {$nin: currTrends}})
      .then(resolve)
      .catch(error => { reject(error) })
    })
  },

  /**
   * Given a specific trend, update its document in the database with the given
   * information, or create a new document for it if it does not already exist
   * in the database. Returns a promise that is resolved after the trend has
   * been saved.
   *
   * @param  {Object} trendData Data about the trend returned from the trends module
   * @param  {String} trendData.name Name of trend
   * @param  {String} trendData.rank Trend popularity rank
   * @param  {String} trendData.locations Array of country code locations in which the trend is trending
   *
   * @param  {Array} newsArticles Array of news articles for the trend returned from the news module
   *
   * @param  {Array} tweets Array of popular tweets for the trend returned from the tweet-search module
   *
   * @param  {Object} streamData Data returned from the tweetStream for this trend (can be undefined if the trend just started trending)
   * @param  {Number} streamData.sentiment Sentiment score collected for the trend by the tweetStream
   * @param  {String} streamData.sentiment_description Human readable description of the sentiment score
   * @param  {Number} streamData.tweets_analyzed Number of tweets analyzed to get the sentiment score
   * @param  {Array}  streamData.keywords Array of keywords collected from the tweetStream
   *
   * @return {Promise}
   */
  processTrend: function (trendData, newsArticles, tweets, streamData) {
    return new Promise((resolve, reject) => {
      const fullTrendData = {
        name: trendData.name,
        rank: trendData.rank,
        locations: trendData.locations,
        articles: newsArticles,
        tweets: tweets,
        sentiment_score: streamData ? streamData.sentiment : null,
        sentiment_description: streamData ? sentimentUtils.getSentimentDescription(streamData.sentiment) : null,
        tweets_analyzed: streamData ? streamData.tweets_analyzed : 0,
        keywords: streamData ? streamData.keywords : []
      }

      // Try to find the trend
      Trend.findOne({name: trendData.name})
      .then(doc => {
        // If trend exists
        if (doc) {
          dbUtils.updateExistingTrend(doc, fullTrendData).then(resolve)
        } else {
          dbUtils.createNewTrend(fullTrendData).then(resolve)
        }
      }).catch(reject)
    })
  },

  /**
   * Given the existing document for a trend in the db, and newly collected
   * data for a trend, update the trend's data in the db. Returns a promise
   *
   * @param  {Object} existingTrendData MongoDB document already existing in the database for the trend
   * @param  {Object} currentTrendData Object of the same form as existingTrendData, containing new information
   * @return {Promise} Promise resolved after trend document is updated
   */
  updateExistingTrend: function (existingTrendData, currentTrendData) {
    return new Promise((resolve, reject) => {
      const newTweetsAnalyzed = existingTrendData.tweets_analyzed + currentTrendData.tweets_analyzed

      // Calculate the new sentiment score (weighting for tweets_analyzed and avoiding dividing by zero)
      let newSentimentScore = newTweetsAnalyzed > 0
        ? (currentTrendData.sentiment_score * currentTrendData.tweets_analyzed +
        existingTrendData.sentiment_score * existingTrendData.tweets_analyzed) /
        newTweetsAnalyzed : null
      newSentimentScore = Math.round(newSentimentScore * 1000) / 1000 // Round to nearest thousandth

      // Create a new keyword array (removing duplicates)
      const keywordsExisting = {}
      let newKeywords = existingTrendData.keywords.concat(currentTrendData.keywords)
      .filter(keyword => {
        if (keywordsExisting[keyword.word]) {
          return false
        } else {
          keywordsExisting[keyword.word] = true
          return true
        }
      })
      newKeywords.sort((a, b) => {
        return b.occurences - a.occurences
      })
      newKeywords = newKeywords.slice(0, config.maxKeywordsPerTrend)

      Trend.findOneAndUpdate({name: existingTrendData.name},
        {
          $set: {
            sentiment_score: newSentimentScore,
            sentiment_description: newSentimentScore !== null ? sentimentUtils.getSentimentDescription(newSentimentScore) : null,
            tweets_analyzed: newTweetsAnalyzed,
            rank: currentTrendData.rank,
            keywords: newKeywords,
            tweets: currentTrendData.tweets,
            articles: currentTrendData.articles
          }
        })
      .then(resolve)
      .catch(reject)
    })
  },

  /**
   * Create a new trend in the database. Returns a promise
   *
   * @param  {Object} trendData Data for a trend as specified in the trend model
   * @return {Promise} Promise resolved arter trend is created
   */
  createNewTrend: function (trendData) {
    return new Promise((resolve, reject) => {
      new Trend(trendData).save()
      .then(resolve)
      .catch(reject)
    })
  }
}

module.exports = dbUtils
<commit_msg>Remove unnecessary arrow function<commit_after>'use strict'
const Trend = require('../models/trend')
const config = require('../../config')
const sentimentUtils = require('./sentiment-utils')

/**
 * Contains utility functions used to query and update the database.
 */
const dbUtils = {
  /**
   * Removes all trends from the database not located in the currTrends array.
   *
   * @param  {Array} currTrends Array of trend names (as strings) that are still trending, trends not in this array will be removed from the db
   */
  removeOldTrends: function (currTrends) {
    return new Promise((resolve, reject) => {
      Trend.remove({name: {$nin: currTrends}})
      .then(resolve)
      .catch(reject)
    })
  },

  /**
   * Given a specific trend, update its document in the database with the given
   * information, or create a new document for it if it does not already exist
   * in the database. Returns a promise that is resolved after the trend has
   * been saved.
   *
   * @param  {Object} trendData Data about the trend returned from the trends module
   * @param  {String} trendData.name Name of trend
   * @param  {String} trendData.rank Trend popularity rank
   * @param  {String} trendData.locations Array of country code locations in which the trend is trending
   *
   * @param  {Array} newsArticles Array of news articles for the trend returned from the news module
   *
   * @param  {Array} tweets Array of popular tweets for the trend returned from the tweet-search module
   *
   * @param  {Object} streamData Data returned from the tweetStream for this trend (can be undefined if the trend just started trending)
   * @param  {Number} streamData.sentiment Sentiment score collected for the trend by the tweetStream
   * @param  {String} streamData.sentiment_description Human readable description of the sentiment score
   * @param  {Number} streamData.tweets_analyzed Number of tweets analyzed to get the sentiment score
   * @param  {Array}  streamData.keywords Array of keywords collected from the tweetStream
   *
   * @return {Promise}
   */
  processTrend: function (trendData, newsArticles, tweets, streamData) {
    return new Promise((resolve, reject) => {
      const fullTrendData = {
        name: trendData.name,
        rank: trendData.rank,
        locations: trendData.locations,
        articles: newsArticles,
        tweets: tweets,
        sentiment_score: streamData ? streamData.sentiment : null,
        sentiment_description: streamData ? sentimentUtils.getSentimentDescription(streamData.sentiment) : null,
        tweets_analyzed: streamData ? streamData.tweets_analyzed : 0,
        keywords: streamData ? streamData.keywords : []
      }

      // Try to find the trend
      Trend.findOne({name: trendData.name})
      .then(doc => {
        // If trend exists
        if (doc) {
          dbUtils.updateExistingTrend(doc, fullTrendData).then(resolve)
        } else {
          dbUtils.createNewTrend(fullTrendData).then(resolve)
        }
      }).catch(reject)
    })
  },

  /**
   * Given the existing document for a trend in the db, and newly collected
   * data for a trend, update the trend's data in the db. Returns a promise
   *
   * @param  {Object} existingTrendData MongoDB document already existing in the database for the trend
   * @param  {Object} currentTrendData Object of the same form as existingTrendData, containing new information
   * @return {Promise} Promise resolved after trend document is updated
   */
  updateExistingTrend: function (existingTrendData, currentTrendData) {
    return new Promise((resolve, reject) => {
      const newTweetsAnalyzed = existingTrendData.tweets_analyzed + currentTrendData.tweets_analyzed

      // Calculate the new sentiment score (weighting for tweets_analyzed and avoiding dividing by zero)
      let newSentimentScore = newTweetsAnalyzed > 0
        ? (currentTrendData.sentiment_score * currentTrendData.tweets_analyzed +
        existingTrendData.sentiment_score * existingTrendData.tweets_analyzed) /
        newTweetsAnalyzed : null
      newSentimentScore = Math.round(newSentimentScore * 1000) / 1000 // Round to nearest thousandth

      // Create a new keyword array (removing duplicates)
      const keywordsExisting = {}
      let newKeywords = existingTrendData.keywords.concat(currentTrendData.keywords)
      .filter(keyword => {
        if (keywordsExisting[keyword.word]) {
          return false
        } else {
          keywordsExisting[keyword.word] = true
          return true
        }
      })
      newKeywords.sort((a, b) => {
        return b.occurences - a.occurences
      })
      newKeywords = newKeywords.slice(0, config.maxKeywordsPerTrend)

      Trend.findOneAndUpdate({name: existingTrendData.name},
        {
          $set: {
            sentiment_score: newSentimentScore,
            sentiment_description: newSentimentScore !== null ? sentimentUtils.getSentimentDescription(newSentimentScore) : null,
            tweets_analyzed: newTweetsAnalyzed,
            rank: currentTrendData.rank,
            keywords: newKeywords,
            tweets: currentTrendData.tweets,
            articles: currentTrendData.articles
          }
        })
      .then(resolve)
      .catch(reject)
    })
  },

  /**
   * Create a new trend in the database. Returns a promise
   *
   * @param  {Object} trendData Data for a trend as specified in the trend model
   * @return {Promise} Promise resolved arter trend is created
   */
  createNewTrend: function (trendData) {
    return new Promise((resolve, reject) => {
      new Trend(trendData).save()
      .then(resolve)
      .catch(reject)
    })
  }
}

module.exports = dbUtils
<|endoftext|>


<commit_before>const now = Date.now || function _now() {
  return new Date().getTime();
};

export default function debounce(fn, wait, immediate) {
  let timeout;
  let args;
  let context;
  let timestamp;
  let result;

  const later = () => {
    const last = now() - timestamp;

    if (last < wait && last >= 0) {
      timeout = setTimeout(later, wait - last);
    } else {
      timeout = null;
      if (!immediate) {
        result = fn.apply(context, args);
        if (!timeout) context = args = null;
      }
    }
  };

  return function debouncedFn(...debounceArgs) {
    context = this;
    args = debounceArgs;
    timestamp = now();
    const callNow = immediate && !timeout;

    if (!timeout) timeout = setTimeout(later, wait);
    if (callNow) {
      result = fn.apply(context, args);
      context = args = null;
    }

    return result;
  };
}
<commit_msg>add debounce explanation comment<commit_after>const now = Date.now || function _now() {
  return new Date().getTime();
};

/*
 * Adapted from underscore.js 1.8.3
 * "immediate" logic here is for covering edge cases
 */
export default function debounce(fn, wait, immediate) {
  let timeout;
  let args;
  let context;
  let timestamp;
  let result;

  const later = () => {
    const last = now() - timestamp;

    if (last < wait && last >= 0) {
      timeout = setTimeout(later, wait - last);
    } else {
      timeout = null;
      if (!immediate) {
        result = fn.apply(context, args);
        if (!timeout) context = args = null;
      }
    }
  };

  return function debouncedFn(...debounceArgs) {
    context = this;
    args = debounceArgs;
    timestamp = now();
    const callNow = immediate && !timeout;

    if (!timeout) timeout = setTimeout(later, wait);
    if (callNow) {
      result = fn.apply(context, args);
      context = args = null;
    }

    return result;
  };
}
<|endoftext|>


<commit_before>import MimeUtil from './mimeDetectorUtil';
import PlayerActions from './../components/Player/actions';
import LinkSupport from './../components/Player/utils/supportedLinks';
import metaParser from './../components/Player/utils/metaParser';
import ModalActions from './../components/Modal/actions';
import torrentActions from './../actions/torrentActions';
import Promise from 'bluebird';
import _ from 'lodash';
import ytdl from 'youtube-dl';
import ytdlSupported from './../components/Player/utils/ytdl-extractor';
import plugins from './plugins';
import ls from 'local-storage';

module.exports = (inputvalue, cb) => {
    return new Promise((resolve, reject) => {
        if (inputvalue.length > 0) {

            if (inputvalue.indexOf('://') == -1 && inputvalue.indexOf(':?') == -1 && inputvalue.indexOf('http') != 0) {
                inputvalue = 'http://' + inputvalue;
            }

            MimeUtil.parseURL(inputvalue)
                .then(parsed => {
                    switch (parsed.category) {
                        case 'torrent':
                            torrentActions.addTorrent(inputvalue);
                            break;
                        case 'direct':

                            if (parsed.type.parsed == 'html') {
                                // if it's html, we have 2 choices
                                // - try youtube-dl with it
                                // - add all the media on the page to a playlist
                                parsed.domain = parsed.url.match(/https?:\/\/[^\/]+\//g)[0];

                                function parseLinks(plugin) {
                                    // start scanning for media on the page
                                    var Linky = new LinkSupport;
                                    Linky.handleURL(parsed, plugin, resolvedLink => {
                                        var newFiles = resolvedLink[0];
                                        var queueParser = resolvedLink[1];
                                        if (newFiles.length) {
                                            ModalActions.close();
                                            PlayerActions.addPlaylist(newFiles);

                                            // start searching for thumbnails after 1 second
                                            _.delay(() => queueParser.forEach(el => {
                                                metaParser.push(el);
                                            }), 1000);
                                        } else {
                                            // try youtube-dl with it, use media scanner as a fallback
                                            var ytdlArgs = ['-g'];

                                            if (ls('ytdlQuality') < 4) {
                                                var qualities = [360, 480, 720, 1080];
                                                ytdlArgs.push('-f');
                                                ytdlArgs.push('[height <=? ' + qualities[ls('ytdlQuality')] + ']');
                                            }

                                            var video = ytdl(parsed.url, ytdlArgs);

                                            video.on('error', function(err) {
                                                ModalActions.close();
                                                console.log('ytdl ending error');
                                                reject(new Error('Error: Invalid URL'));
                                            });

                                            video.on('info', function(info) {
                                                if (info.url) {
                                                    ModalActions.close();
                                                    console.log(info);
                                                    PlayerActions.addPlaylist([{
                                                        originalURL: inputvalue,
                                                        uri: parsed.url,
                                                        youtubeDL: true,
                                                        image: info.thumbnail,
                                                        title: info.fulltitle
                                                    }]);
                                                } else parseLinks(plugin && plugin.checkFor ? plugin : null);
                                            });

                                        }
                                    }, reject);
                                }

                                // let's see if we have any plugin that can handle this link
                                var plugin = plugins.getExtractor(parsed.url);
                                var perfectMatch = false;
                                if (plugin && plugin.checkFor) {
                                    // we have a plugin for this link (matched by domain with regex)
                                    // a perfect match is when the plugin is also matched by media
                                    perfectMatch = plugins.perfectMatch(parsed.url, plugin);
//                                    if (perfectMatch) console.log('a perfect match');
                                }

                                if (perfectMatch || ytdlSupported(parsed.url)) {
                                    // a perfect match or a youtube-dl regex match should be
                                    // sent directly to youtube-dl for processing
                                    var video = ytdl(parsed.url, ['-g']);

                                    video.on('error', function(err) {
                                        parseLinks(plugin && plugin.checkFor ? plugin : null);
                                    });

                                    video.on('info', function(info) {
                                        if (info.url) {
                                            ModalActions.close();
                                            console.log(info);
                                            PlayerActions.addPlaylist([{
                                                originalURL: inputvalue,
                                                uri: parsed.url,
                                                youtubeDL: true,
                                                image: info.thumbnail,
                                                title: info.fulltitle
                                            }]);
                                        } else parseLinks(plugin && plugin.checkFor ? plugin : null);
                                    });

                                } else {
                                    parseLinks(plugin && plugin.checkFor ? plugin : null);
                                }

                            } else {
                                // it's not html, maybe it's some protocol vlc can handle
                                PlayerActions.addPlaylist([parsed.url]);
                                resolve(parsed.url);
                            }

                            break;
                        case 'error':
                            reject(new Error('Error: Invalid URL'));
                            break;
                    }
                })
        } else {
            reject(new Error('Error: No URL Given'));
        }
    });
}<commit_msg>Fixed Modal Showing When Playback Starts<commit_after>import MimeUtil from './mimeDetectorUtil';
import PlayerActions from './../components/Player/actions';
import LinkSupport from './../components/Player/utils/supportedLinks';
import metaParser from './../components/Player/utils/metaParser';
import ModalActions from './../components/Modal/actions';
import torrentActions from './../actions/torrentActions';
import Promise from 'bluebird';
import _ from 'lodash';
import ytdl from 'youtube-dl';
import ytdlSupported from './../components/Player/utils/ytdl-extractor';
import plugins from './plugins';
import ls from 'local-storage';

module.exports = (inputvalue, cb) => {
    return new Promise((resolve, reject) => {
        if (inputvalue.length > 0) {

            if (inputvalue.indexOf('://') == -1 && inputvalue.indexOf(':?') == -1 && inputvalue.indexOf('http') != 0) {
                inputvalue = 'http://' + inputvalue;
            }

            MimeUtil.parseURL(inputvalue)
                .then(parsed => {
                    switch (parsed.category) {
                        case 'torrent':
                            torrentActions.addTorrent(inputvalue);
                            break;
                        case 'direct':

                            if (parsed.type.parsed == 'html') {
                                // if it's html, we have 2 choices
                                // - try youtube-dl with it
                                // - add all the media on the page to a playlist
                                parsed.domain = parsed.url.match(/https?:\/\/[^\/]+\//g)[0];

                                function parseLinks(plugin) {
                                    // start scanning for media on the page
                                    var Linky = new LinkSupport;
                                    Linky.handleURL(parsed, plugin, resolvedLink => {
                                        var newFiles = resolvedLink[0];
                                        var queueParser = resolvedLink[1];
                                        if (newFiles.length) {
                                            ModalActions.close();
                                            PlayerActions.addPlaylist(newFiles);

                                            // start searching for thumbnails after 1 second
                                            _.delay(() => queueParser.forEach(el => {
                                                metaParser.push(el);
                                            }), 1000);
                                        } else {
                                            // try youtube-dl with it, use media scanner as a fallback
                                            var ytdlArgs = ['-g'];

                                            if (ls('ytdlQuality') < 4) {
                                                var qualities = [360, 480, 720, 1080];
                                                ytdlArgs.push('-f');
                                                ytdlArgs.push('[height <=? ' + qualities[ls('ytdlQuality')] + ']');
                                            }

                                            var video = ytdl(parsed.url, ytdlArgs);

                                            video.on('error', function(err) {
                                                ModalActions.close();
                                                console.log('ytdl ending error');
                                                reject(new Error('Error: Invalid URL'));
                                            });

                                            video.on('info', function(info) {
                                                if (info.url) {
                                                    ModalActions.close();
                                                    console.log(info);
                                                    PlayerActions.addPlaylist([{
                                                        originalURL: inputvalue,
                                                        uri: parsed.url,
                                                        youtubeDL: true,
                                                        image: info.thumbnail,
                                                        title: info.fulltitle
                                                    }]);
                                                } else parseLinks(plugin && plugin.checkFor ? plugin : null);
                                            });

                                        }
                                    }, reject);
                                }

                                // let's see if we have any plugin that can handle this link
                                var plugin = plugins.getExtractor(parsed.url);
                                var perfectMatch = false;
                                if (plugin && plugin.checkFor) {
                                    // we have a plugin for this link (matched by domain with regex)
                                    // a perfect match is when the plugin is also matched by media
                                    perfectMatch = plugins.perfectMatch(parsed.url, plugin);
//                                    if (perfectMatch) console.log('a perfect match');
                                }

                                if (perfectMatch || ytdlSupported(parsed.url)) {
                                    // a perfect match or a youtube-dl regex match should be
                                    // sent directly to youtube-dl for processing
                                    var video = ytdl(parsed.url, ['-g']);

                                    video.on('error', function(err) {
                                        parseLinks(plugin && plugin.checkFor ? plugin : null);
                                    });

                                    video.on('info', function(info) {
                                        if (info.url) {
                                            ModalActions.close();
                                            console.log(info);
                                            PlayerActions.addPlaylist([{
                                                originalURL: inputvalue,
                                                uri: parsed.url,
                                                youtubeDL: true,
                                                image: info.thumbnail,
                                                title: info.fulltitle
                                            }]);
                                        } else parseLinks(plugin && plugin.checkFor ? plugin : null);
                                    });

                                } else {
                                    parseLinks(plugin && plugin.checkFor ? plugin : null);
                                }

                            } else {
                                // it's not html, maybe it's some protocol vlc can handle
                                _.defer(() => {
                                    ModalActions.close();
                                });
                                PlayerActions.addPlaylist([parsed.url]);
                                resolve(parsed.url);
                            }

                            break;
                        case 'error':
                            reject(new Error('Error: Invalid URL'));
                            break;
                    }
                })
        } else {
            reject(new Error('Error: No URL Given'));
        }
    });
}<|endoftext|>


<commit_before>/**
 * Copyright (c) 2002-2017 "Neo Technology,","
 * Network Engine for Objects in Lund AB [http://neotechnology.com]
 *
 * This file is part of Neo4j.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Class for Node Type.
 */
class Node {
  /**
   * @constructor
   * @param {string} identity - Unique identity
   * @param {Array} labels - Array for all labels
   * @param {Object} properties - Map with node properties
   */
  constructor(identity, labels, properties) {
    this.identity = identity;
    this.labels = labels;
    this.properties = properties;
  }

  toString() {
    let s = "(" + this.identity;
    for (let i = 0; i < this.labels.length; i++) {
      s += ":" + this.labels[i];
    }
    let keys = Object.keys(this.properties);
    if (keys.length > 0) {
      s += " {";
      for(let i = 0; i < keys.length; i++) {
        if (i > 0) s += ",";
        s += keys[i] + ":" + JSON.stringify(this.properties[keys[i]]);
      }
      s += "}";
    }
    s += ")";
    return s;
  }
}

/**
 * Class for Relationship Type.
 */
class Relationship {
  /**
   * @constructor
   * @param {string} identity - Unique identity
   * @param {string} start - Identity of start Node
   * @param {string} end - Identity of end Node
   * @param {string} type - Relationship type
   * @param {Object} properties - Map with relationship properties
   */
  constructor(identity, start, end, type, properties) {
    this.identity = identity;
    this.start = start;
    this.end = end;
    this.type = type;
    this.properties = properties;
  }

  toString() {
    let s = "(" + this.start + ")-[:" + this.type;
    let keys = Object.keys(this.properties);
    if (keys.length > 0) {
      s += " {";
      for(let i = 0; i < keys.length; i++) {
        if (i > 0) s += ",";
        s += keys[i] + ":" + JSON.stringify(this.properties[keys[i]]);
      }
      s += "}";
    }
    s += "]->(" + this.end + ")";
    return s;
  }
}

/**
 * Class for UnboundRelationship Type.
 * @access private
 */
class UnboundRelationship {
  /**
   * @constructor
   * @param {string} identity - Unique identity
   * @param {string} type - Relationship type
   * @param {Object} properties - Map with relationship properties
   */
  constructor(identity, type, properties) {
    this.identity = identity;
    this.type = type;
    this.properties = properties;
  }

  /**
   * Bind relationship
   * @param {string} start - Indentity of start node
   * @param {string} end - Indentity of end node
   * @return {Relationship} - Created relationship
   */
  bind( start, end ) {
    return new Relationship(
      this.identity,
      start,
      end,
      this.type,
      this.properties);
  }

  toString() {
    let s = "-[:" + this.type;
    let keys = Object.keys(this.properties);
    if (keys.length > 0) {
      s += " {";
      for(let i = 0; i < keys.length; i++) {
        if (i > 0) s += ",";
        s += keys[i] + ":" + JSON.stringify(this.properties[keys[i]]);
      }
      s += "}";
    }
    s += "]->";
    return s;
  }
}

/**
 * Class for PathSegment Type.
 */
class PathSegment {
  /**
   * @constructor
   * @param {string} start - Identity of start Node
   * @param {Relationship} rel - Relationship segment
   * @param {string} end - Identity of end Node
   */
  constructor(start, rel, end) {
    this.start = start;
    this.relationship = rel;
    this.end = end;
  }
}

/**
 * Class for Path Type.
 */
class Path {
  /**
   * @constructor
   * @param {Node} start  - start node
   * @param {Node} end - end node
   * @param {Array} segments - Array of Segments
   */
  constructor(start, end, segments) {
    this.start = start;
    this.end = end;
    this.segments = segments;
    this.length = segments.length;
  }
}

export {
  Node,
  Relationship,
  UnboundRelationship,
  Path,
  PathSegment
}
<commit_msg>Fix JSDoc for Node, Relationship and PathSegment<commit_after>/**
 * Copyright (c) 2002-2017 "Neo Technology,","
 * Network Engine for Objects in Lund AB [http://neotechnology.com]
 *
 * This file is part of Neo4j.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Class for Node Type.
 */
class Node {
  /**
   * @constructor
   * @param {Integer} identity - Unique identity
   * @param {Array} labels - Array for all labels
   * @param {Object} properties - Map with node properties
   */
  constructor(identity, labels, properties) {
    this.identity = identity;
    this.labels = labels;
    this.properties = properties;
  }

  toString() {
    let s = "(" + this.identity;
    for (let i = 0; i < this.labels.length; i++) {
      s += ":" + this.labels[i];
    }
    let keys = Object.keys(this.properties);
    if (keys.length > 0) {
      s += " {";
      for(let i = 0; i < keys.length; i++) {
        if (i > 0) s += ",";
        s += keys[i] + ":" + JSON.stringify(this.properties[keys[i]]);
      }
      s += "}";
    }
    s += ")";
    return s;
  }
}

/**
 * Class for Relationship Type.
 */
class Relationship {
  /**
   * @constructor
   * @param {Integer} identity - Unique identity
   * @param {Integer} start - Identity of start Node
   * @param {Integer} end - Identity of end Node
   * @param {string} type - Relationship type
   * @param {Object} properties - Map with relationship properties
   */
  constructor(identity, start, end, type, properties) {
    this.identity = identity;
    this.start = start;
    this.end = end;
    this.type = type;
    this.properties = properties;
  }

  toString() {
    let s = "(" + this.start + ")-[:" + this.type;
    let keys = Object.keys(this.properties);
    if (keys.length > 0) {
      s += " {";
      for(let i = 0; i < keys.length; i++) {
        if (i > 0) s += ",";
        s += keys[i] + ":" + JSON.stringify(this.properties[keys[i]]);
      }
      s += "}";
    }
    s += "]->(" + this.end + ")";
    return s;
  }
}

/**
 * Class for UnboundRelationship Type.
 * @access private
 */
class UnboundRelationship {
  /**
   * @constructor
   * @param {Integer} identity - Unique identity
   * @param {string} type - Relationship type
   * @param {Object} properties - Map with relationship properties
   */
  constructor(identity, type, properties) {
    this.identity = identity;
    this.type = type;
    this.properties = properties;
  }

  /**
   * Bind relationship
   * @param {Integer} start - Identity of start node
   * @param {Integer} end - Identity of end node
   * @return {Relationship} - Created relationship
   */
  bind( start, end ) {
    return new Relationship(
      this.identity,
      start,
      end,
      this.type,
      this.properties);
  }

  toString() {
    let s = "-[:" + this.type;
    let keys = Object.keys(this.properties);
    if (keys.length > 0) {
      s += " {";
      for(let i = 0; i < keys.length; i++) {
        if (i > 0) s += ",";
        s += keys[i] + ":" + JSON.stringify(this.properties[keys[i]]);
      }
      s += "}";
    }
    s += "]->";
    return s;
  }
}

/**
 * Class for PathSegment Type.
 */
class PathSegment {
  /**
   * @constructor
   * @param {Node} start - start node
   * @param {Relationship} rel - relationship that connects start and end node
   * @param {Node} end - end node
   */
  constructor(start, rel, end) {
    this.start = start;
    this.relationship = rel;
    this.end = end;
  }
}

/**
 * Class for Path Type.
 */
class Path {
  /**
   * @constructor
   * @param {Node} start  - start node
   * @param {Node} end - end node
   * @param {Array} segments - Array of Segments
   */
  constructor(start, end, segments) {
    this.start = start;
    this.end = end;
    this.segments = segments;
    this.length = segments.length;
  }
}

export {
  Node,
  Relationship,
  UnboundRelationship,
  Path,
  PathSegment
}
<|endoftext|>


<commit_before>import { SYNC_RENDER, DOM_RENDER, NO_RENDER, EMPTY_BASE } from '../constants';
import options from '../options';
import { isFunction } from '../util';
import { hook, deepHook } from '../hooks';
import { enqueueRender } from '../render-queue';
import { getNodeProps } from '.';
import diff from './diff';
import { removeOrphanedChildren, recollectNodeTree } from './diff';
import { createComponent, collectComponent } from './component-recycler';
import { removeNode } from '../dom';

/** Mark component as dirty and queue up a render.
 *	@param {Component} component
 *	@private
 */
export function triggerComponentRender(component) {
	if (!component._dirty) {
		component._dirty = true;
		enqueueRender(component);
	}
}

/** Set a component's `props` (generally derived from JSX attributes).
 *	@param {Object} props
 *	@param {Object} [opts]
 *	@param {boolean} [opts.renderSync=false]	If `true` and {@link options.syncComponentUpdates} is `true`, triggers synchronous rendering.
 *	@param {boolean} [opts.render=true]			If `false`, no render will be triggered.
 */
export function setComponentProps(component, props, opts, context) {
	let d = component._disableRendering;

	component.__ref = props.ref;
	component.__key = props.key;
	delete props.ref;
	delete props.key;

	component._disableRendering = true;

	if (context) {
		if (!component.prevContext) component.prevContext = component.context;
		component.context = context;
	}

	if (component.base) {
		hook(component, 'componentWillReceiveProps', props, component.context);
	}

	if (!component.prevProps) component.prevProps = component.props;
	component.props = props;

	component._disableRendering = d;

	if (opts!==NO_RENDER) {
		if (opts===SYNC_RENDER || options.syncComponentUpdates!==false) {
			renderComponent(component);
		}
		else {
			triggerComponentRender(component);
		}
	}

	hook(component, '__ref', component);
}

/** Render a Component, triggering necessary lifecycle events and taking High-Order Components into account.
 *	@param {Component} component
 *	@param {Object} [opts]
 *	@param {boolean} [opts.build=false]		If `true`, component will build and store a DOM node if not already associated with one.
 *	@private
 */
export function renderComponent(component, opts) {
	if (component._disableRendering) return;

	let skip, rendered,
		props = component.props,
		state = component.state,
		context = component.context,
		previousProps = component.prevProps || props,
		previousState = component.prevState || state,
		previousContext = component.prevContext || context,
		isUpdate = component.base,
		initialBase = isUpdate || component.nextBase;

	// if updating
	if (isUpdate) {
		component.props = previousProps;
		component.state = previousState;
		component.context = previousContext;
		if (hook(component, 'shouldComponentUpdate', props, state, context)===false) {
			skip = true;
		}
		else {
			hook(component, 'componentWillUpdate', props, state, context);
		}
		component.props = props;
		component.state = state;
		component.context = context;
	}

	component.prevProps = component.prevState = component.prevContext = component.nextBase = null;
	component._dirty = false;

	if (!skip) {
		rendered = hook(component, 'render', props, state, context);

		let childComponent = rendered && rendered.nodeName,
			toUnmount, base;

		// context to pass to the child, can be updated via (grand-)parent component
		if (component.getChildContext) {
			context = extend(clone(context), component.getChildContext());
		}

		if (isFunction(childComponent) && childComponent.prototype.render) {
			// set up high order component link

			let inst = component._component;
			if (inst && inst.constructor!==childComponent) {
				toUnmount = inst;
				inst = null;
			}

			let childProps = getNodeProps(rendered);

			if (inst) {
				setComponentProps(inst, childProps, SYNC_RENDER, context);
			}
			else {
				inst = createComponent(childComponent, childProps, context);
				inst._parentComponent = component;
				component._component = inst;
				if (isUpdate) deepHook(inst, 'componentWillMount');
				setComponentProps(inst, childProps, NO_RENDER, context);
				renderComponent(inst, DOM_RENDER);
				if (isUpdate) deepHook(inst, 'componentDidMount');
			}

			base = inst.base;
		}
		else {
			let cbase = initialBase;

			// destroy high order component link
			toUnmount = component._component;
			if (toUnmount) {
				cbase = component._component = null;
			}

			if (initialBase || opts===DOM_RENDER) {
				if (cbase) cbase._component = null;
				base = diff(cbase, rendered || EMPTY_BASE, context);
			}
		}

		if (initialBase && base!==initialBase) {
			let p = initialBase.parentNode;
			if (p && base!==p) p.replaceChild(base, initialBase);
		}

		if (toUnmount) {
			unmountComponent(toUnmount, true);
		}

		component.base = base;
		if (base) {
			let componentRef = component,
				t = component;
			while ((t=t._parentComponent)) { componentRef = t; }
			base._component = componentRef;
			base._componentConstructor = componentRef.constructor;
		}

		if (isUpdate) {
			hook(component, 'componentDidUpdate', previousProps, previousState, previousContext);
		}
	}

	let cb = component._renderCallbacks, fn;
	if (cb) while ( (fn = cb.pop()) ) fn.call(component);

	return rendered;
}

/** Apply the Component referenced by a VNode to the DOM.
 *	@param {Element} dom	The DOM node to mutate
 *	@param {VNode} vnode	A Component-referencing VNode
 *	@returns {Element} dom	The created/mutated element
 *	@private
 */
export function buildComponentFromVNode(dom, vnode, context) {
	let c = dom && dom._component,
		oldDom = dom;

	let isOwner = c && dom._componentConstructor===vnode.nodeName;
	while (c && !isOwner && (c=c._parentComponent)) {
		isOwner = c.constructor===vnode.nodeName;
	}

	if (isOwner) {
		setComponentProps(c, getNodeProps(vnode), SYNC_RENDER, context);
		dom = c.base;
	}
	else {
		if (c) {
			unmountComponent(c, true);
			dom = oldDom = null;
		}
		dom = createComponentFromVNode(vnode, dom, context);
		if (oldDom && dom!==oldDom) {
			oldDom._component = null;
			recollectNodeTree(oldDom);
		}
	}

	return dom;
}

/** Instantiate and render a Component, given a VNode whose nodeName is a constructor.
 *	@param {VNode} vnode
 *	@private
 */
function createComponentFromVNode(vnode, dom, context) {
	let props = getNodeProps(vnode);
	let component = createComponent(vnode.nodeName, props, context);

	if (dom && !component.base) component.base = dom;

	setComponentProps(component, props, NO_RENDER, context);
	renderComponent(component, DOM_RENDER);

	// let node = component.base;
	//if (!node._component) {
	//	node._component = component;
	//	node._componentConstructor = vnode.nodeName;
	//}

	return component.base;
}

/** Remove a component from the DOM and recycle it.
 *	@param {Element} dom			A DOM node from which to unmount the given Component
 *	@param {Component} component	The Component instance to unmount
 *	@private
 */
export function unmountComponent(component, remove) {
	// console.log(`${remove?'Removing':'Unmounting'} component: ${component.constructor.name}`, component);

	hook(component, '__ref', null);
	hook(component, 'componentWillUnmount');

	// recursively tear down & recollect high-order component children:
	let inner = component._component;
	if (inner) {
		unmountComponent(inner, remove);
		remove = false;
	}

	let base = component.base;
	if (base) {
		if (remove!==false) removeNode(base);
		removeOrphanedChildren(base.childNodes, true);
	}

	if (remove) {
		component._parentComponent = null;
		collectComponent(component);
	}

	hook(component, 'componentDidUnmount');
}
<commit_msg>Optimize `setComponentProps()`<commit_after>import { SYNC_RENDER, DOM_RENDER, NO_RENDER, EMPTY_BASE } from '../constants';
import options from '../options';
import { isFunction, clone, extend } from '../util';
import { hook, deepHook } from '../hooks';
import { enqueueRender } from '../render-queue';
import { getNodeProps } from '.';
import diff from './diff';
import { removeOrphanedChildren, recollectNodeTree } from './diff';
import { createComponent, collectComponent } from './component-recycler';
import { removeNode } from '../dom';

/** Mark component as dirty and queue up a render.
 *	@param {Component} component
 *	@private
 */
export function triggerComponentRender(component) {
	if (!component._dirty) {
		component._dirty = true;
		enqueueRender(component);
	}
}

/** Set a component's `props` (generally derived from JSX attributes).
 *	@param {Object} props
 *	@param {Object} [opts]
 *	@param {boolean} [opts.renderSync=false]	If `true` and {@link options.syncComponentUpdates} is `true`, triggers synchronous rendering.
 *	@param {boolean} [opts.render=true]			If `false`, no render will be triggered.
 */
export function setComponentProps(component, props, opts, context) {
	let d = component._disableRendering===true;
	component._disableRendering = true;

	component.__ref = props.ref;
	component.__key = props.key;
	if (props.ref) delete props.ref;
	if (props.key) delete props.key;

	if (component.base!==undefined && component.base!==null) {
		hook(component, 'componentWillReceiveProps', props, context);
	}

	if (context && context!==component.context) {
		if (!component.prevContext) component.prevContext = component.context;
		component.context = context;
	}

	if (!component.prevProps) component.prevProps = component.props;
	component.props = props;

	component._disableRendering = d;

	if (opts!==NO_RENDER) {
		if (opts===SYNC_RENDER || options.syncComponentUpdates!==false) {
			renderComponent(component);
		}
		else {
			triggerComponentRender(component);
		}
	}

	hook(component, '__ref', component);
}

/** Render a Component, triggering necessary lifecycle events and taking High-Order Components into account.
 *	@param {Component} component
 *	@param {Object} [opts]
 *	@param {boolean} [opts.build=false]		If `true`, component will build and store a DOM node if not already associated with one.
 *	@private
 */
export function renderComponent(component, opts) {
	if (component._disableRendering) return;

	let skip, rendered,
		props = component.props,
		state = component.state,
		context = component.context,
		previousProps = component.prevProps || props,
		previousState = component.prevState || state,
		previousContext = component.prevContext || context,
		isUpdate = component.base,
		initialBase = isUpdate || component.nextBase;

	// if updating
	if (isUpdate) {
		component.props = previousProps;
		component.state = previousState;
		component.context = previousContext;
		if (hook(component, 'shouldComponentUpdate', props, state, context)===false) {
			skip = true;
		}
		else {
			hook(component, 'componentWillUpdate', props, state, context);
		}
		component.props = props;
		component.state = state;
		component.context = context;
	}

	component.prevProps = component.prevState = component.prevContext = component.nextBase = null;
	component._dirty = false;

	if (!skip) {
		rendered = hook(component, 'render', props, state, context);

		let childComponent = rendered && rendered.nodeName,
			toUnmount, base;

		// context to pass to the child, can be updated via (grand-)parent component
		if (component.getChildContext) {
			context = extend(clone(context), component.getChildContext());
		}

		if (isFunction(childComponent) && childComponent.prototype.render) {
			// set up high order component link

			let inst = component._component;
			if (inst && inst.constructor!==childComponent) {
				toUnmount = inst;
				inst = null;
			}

			let childProps = getNodeProps(rendered);

			if (inst) {
				setComponentProps(inst, childProps, SYNC_RENDER, context);
			}
			else {
				inst = createComponent(childComponent, childProps, context);
				inst._parentComponent = component;
				component._component = inst;
				if (isUpdate) deepHook(inst, 'componentWillMount');
				setComponentProps(inst, childProps, NO_RENDER, context);
				renderComponent(inst, DOM_RENDER);
				if (isUpdate) deepHook(inst, 'componentDidMount');
			}

			base = inst.base;
		}
		else {
			let cbase = initialBase;

			// destroy high order component link
			toUnmount = component._component;
			if (toUnmount) {
				cbase = component._component = null;
			}

			if (initialBase || opts===DOM_RENDER) {
				if (cbase) cbase._component = null;
				base = diff(cbase, rendered || EMPTY_BASE, context);
			}
		}

		if (initialBase && base!==initialBase) {
			let p = initialBase.parentNode;
			if (p && base!==p) p.replaceChild(base, initialBase);
		}

		if (toUnmount) {
			unmountComponent(toUnmount, true);
		}

		component.base = base;
		if (base) {
			let componentRef = component,
				t = component;
			while ((t=t._parentComponent)) { componentRef = t; }
			base._component = componentRef;
			base._componentConstructor = componentRef.constructor;
		}

		if (isUpdate) {
			hook(component, 'componentDidUpdate', previousProps, previousState, previousContext);
		}
	}

	let cb = component._renderCallbacks, fn;
	if (cb) while ( (fn = cb.pop()) ) fn.call(component);

	return rendered;
}

/** Apply the Component referenced by a VNode to the DOM.
 *	@param {Element} dom	The DOM node to mutate
 *	@param {VNode} vnode	A Component-referencing VNode
 *	@returns {Element} dom	The created/mutated element
 *	@private
 */
export function buildComponentFromVNode(dom, vnode, context) {
	let c = dom && dom._component,
		oldDom = dom;

	let isOwner = c && dom._componentConstructor===vnode.nodeName;
	while (c && !isOwner && (c=c._parentComponent)) {
		isOwner = c.constructor===vnode.nodeName;
	}

	if (isOwner) {
		setComponentProps(c, getNodeProps(vnode), SYNC_RENDER, context);
		dom = c.base;
	}
	else {
		if (c) {
			unmountComponent(c, true);
			dom = oldDom = null;
		}
		dom = createComponentFromVNode(vnode, dom, context);
		if (oldDom && dom!==oldDom) {
			oldDom._component = null;
			recollectNodeTree(oldDom);
		}
	}

	return dom;
}

/** Instantiate and render a Component, given a VNode whose nodeName is a constructor.
 *	@param {VNode} vnode
 *	@private
 */
function createComponentFromVNode(vnode, dom, context) {
	let props = getNodeProps(vnode);
	let component = createComponent(vnode.nodeName, props, context);

	if (dom && !component.base) component.base = dom;

	setComponentProps(component, props, NO_RENDER, context);
	renderComponent(component, DOM_RENDER);

	// let node = component.base;
	//if (!node._component) {
	//	node._component = component;
	//	node._componentConstructor = vnode.nodeName;
	//}

	return component.base;
}

/** Remove a component from the DOM and recycle it.
 *	@param {Element} dom			A DOM node from which to unmount the given Component
 *	@param {Component} component	The Component instance to unmount
 *	@private
 */
export function unmountComponent(component, remove) {
	// console.log(`${remove?'Removing':'Unmounting'} component: ${component.constructor.name}`, component);

	hook(component, '__ref', null);
	hook(component, 'componentWillUnmount');

	// recursively tear down & recollect high-order component children:
	let inner = component._component;
	if (inner) {
		unmountComponent(inner, remove);
		remove = false;
	}

	let base = component.base;
	if (base) {
		if (remove!==false) removeNode(base);
		removeOrphanedChildren(base.childNodes, true);
	}

	if (remove) {
		component._parentComponent = null;
		collectComponent(component);
	}

	hook(component, 'componentDidUnmount');
}
<|endoftext|>


<commit_before>var O = require('./output.js');

module.exports.output = O.makeOutput(
  'output-local-police', // name

  'monitors the changes in local police forces, new events annoucements, and new priorities.', // description

  ['local-police-uk'], // array containing the names of datasources used by output

  function check(datasourcesDict, callback) {
    // check that all the datasources that we need are here.
    for (var i = 0; i < this.sources.length; i++) {
      if (!(this.sources[i] in datasourcesDict)) {
        callback("Datasource '" + sources[i] + "' not found in " + datasourcesDict);
        return;
      }
    }

    var local_police_uk = datasourcesDict['local-police-uk'];

    // TODO get the lat lng parameters from the GUI
    var force = "metropolitan";
    var neighbourhood = "00ACGD";
    var lat = 51.529251355189885;
    var lng = -0.1490020751953125;

    local_police_uk.getData(force, neighbourhood, checkChange);

    function checkChange(dataFinal) {
      console.log(dataFinal);
    }

    /*function processStats(crimeStats) {
      // compute the total amount of crime for each crime
      var totCrimes = [];
      for (var i = 0; i < crimeStats.length; i++) {
        var totalCrime = 0;
        var types = Object.keys(crimeStats[i]);
        for (var t = 0; t < types.length; t++) {
          totalCrime += crimeStats[i][t];
        }
        totCrimes.push(totalCrime);
      }

      // compute the average of crimes per month
      var avg = 0;
      for (var m = 0; m < totCrimes.length; m++) {
        avg += totCrimes[m];
      }
      avg /= totCrimes.length;

      var dif = (totCrimes[totCrimes.length - 1] / avg * 100) - 100;

      // TODO that 10 percents also are here for the sake of the example and
      // should be parametrized somehow.
      if (Math.abs(dif) >= 10) {
        callback(undefined, dif);
      }
    }*/
  }
);

<commit_msg>refine output-local-police skeleton<commit_after>var O = require('./output.js');

module.exports.output = O.makeOutput(
  'output-local-police', // name

  'monitors the changes in local police forces, new events annoucements, and new priorities.', // description

  ['local-police-uk'], // array containing the names of datasources used by output

  function check(datasourcesDict, checkDoneCallback) {
    var outputName = this.name;

    // check that all the datasources that we need are here.
    for (var i = 0; i < this.sources.length; i++) {
      if (!(this.sources[i] in datasourcesDict)) {
        checkDoneCallback("Datasource '" + sources[i] + "' not found in " +
            datasourcesDict, outputName);
        return;
      }
    }

    var local_police_uk = datasourcesDict['local-police-uk'];

    // TODO get the lat lng parameters from the GUI
    var force = "metropolitan";
    var neighbourhood = "00ACGD";

    var pendingReq = 2;
    var localData;
    var remoteData;

    fs.readFile(path_to_JSON, 'utf8', function(err, data) {
      if (!err && data) {
        localData = JSON.parse(data);
      }
      pendingReq--;
      compareData();
    });

    local_police_uk.getData(force, neighbourhood, function(err, data) {
      if (!err) {
        remoteData = data;
      }
      pendingReq--;
      compareData();
    });

    function compareData() {
      // TODO deep equality test of remote data and local data
      // if (remote data != local data)
      //   store remote data as the next local data for reference
      //   fire the call back with a summary of the changes
    }
  }
);

<|endoftext|>