<commit_before>import express from 'express';
import passport from 'passport';
import flash from 'connect-flash';
import User from '../models/user';

const router = express.Router();

// ======================
// AUTH ROUTES
// ======================

// Sign up logic
router.post('/register', (req, res) => {
  User.register(req.body.username, req.body.password, (err, newUser) => {

    if (err) {
      req.flash('error', `${err.message}`);
      return res.status(500).json({
        message: err.message
      });
    }
    newUser.isAdmin = false;
    newUser.email = req.body.email;
    newUser.fullName = req.body.fullName;
    newUser.save();

    passport.authenticate('local')(req, res, () => {
      req.flash('success', 'Welcome to PostIt');
      res.status(200).json({
        message: `Welcome to PostIt + ${req.session.passport.user}`,
        user: req.session.passport.user
      });
    });
  });
});

// Login logic

router.post('/login', (req, res, next) => {
  passport.authenticate('local', (error, user, info) => {
    if (error) {
      return next(error);
    }

    if (!user) {
      return res.status(401).json({
        error: info
      });
    }

    req.login(user, (err) => {
      if (err) {
        return res.status(500).json({
          message: 'Cannot log in user'
        });
      }
      res.status(200).json({
        message: `Welcome back ${req.session.passport.user}`,
        user: req.session.passport.user
      });
    });
  })(req, res, next);
});

// Add logout route
router.get('/logout', (req, res) => {
  req.logout();
  req.flash('error', 'Loged out successful!');
  res.status(200).json({
    message: 'Logged out successfully'
  });
});

export default router;
<commit_msg>feature| modifying routes to allow for changes in models and changing path to models<commit_after>import express from 'express';
import passport from 'passport';
import flash from 'connect-flash';
import models from '../models/index';

const router = express.Router();

// ======================
// AUTH ROUTES
// ======================

// Sign up logic
router.post('/register', (req, res) => {
  models.User.register(req.body.username, req.body.password, (err, newUser) => {
    if (err) {
      req.flash('error', `${err.message}`);
      return res.status(500).json({
        message: err.message
      });
    }
    newUser.email = req.body.email;
    newUser.fullname = req.body.fullname;
    newUser.save();

    passport.authenticate('local')(req, res, () => {
      req.flash('success', 'Welcome to PostIt');
      res.status(200).json({
        message: `Welcome to PostIt + ${req.session.passport.user}`,
        user: req.session.passport.user
      });
    });
  });
});

// Login logic

router.post('/login', (req, res, next) => {
  passport.authenticate('local', (error, user, info) => {
    if (error) {
      return next(error);
    }

    if (!user) {
      return res.status(401).json({
        error: info
      });
    }

    req.login(user, (err) => {
      if (err) {
        return res.status(500).json({
          message: 'Cannot log in user'
        });
      }
      res.status(200).json({
        message: `Welcome back ${req.session.passport.user}`,
        user: req.session.passport.user
      });
    });
  })(req, res, next);
});

// Add logout route
router.get('/logout', (req, res) => {
  req.logout();
  req.flash('error', 'Loged out successful!');
  res.status(200).json({
    message: 'Logged out successfully'
  });
});

export default router;
<|endoftext|>


<commit_before>/*jslint node: true, unparam: true, nomen: true, vars: true*/
'use strict';

var router = require('express').Router();
var async = require('async');

router.get('/', function (req, res) {
    if (req.query.from || req.query.count) {
        async.series([
            function(callback){
                req.db.articles
                    .count({}, function (err, count){
                        if(err) next(err);
                        callback(null, count);
                    })
            },
            function(callback){
                req.db.articles
                    .find()
                    .skip(req.query.from || 0)
                    .limit(req.query.count)
                    .exec(function (err, results) {
                        callback(null, results);
                    });
            }], function (err, results){
                res.json({totalCount: results[0], data: results[1]});
            });
    } else {
        req.db.articles.find(function (err, results) {
            res.json(results);
        });
    }
});

router.get('/:id', function (req, res) {
    req.db.articles.findOne({
        title: req.params.id
    }, function (err, results) {
        res.json(results);
    });
});

module.exports = router;
<commit_msg>refactoring in blog.js<commit_after>/*jslint node: true, unparam: true, nomen: true, vars: true*/
'use strict';

var router = require('express').Router();
var async = require('async');

router.get('/', function (req, res) {
    if (req.query.from || req.query.count) {
        async.series({
            count: function(callback){
                req.db.articles
                    .count({}, function (err, count){
                        if(err) next(err);
                        callback(null, count);
                    })
            },
            data: function(callback){
                req.db.articles
                    .find()
                    .skip(req.query.from || 0)
                    .limit(req.query.count)
                    .exec(function (err, results) {
                        callback(null, results);
                    });
            }}, function (err, results){
                res.json({totalCount: results.count, data: results.data});
            });
    } else {
        req.db.articles.find(function (err, results) {
            res.json(results);
        });
    }
});

router.get('/:id', function (req, res) {
    req.db.articles.findOne({
        title: req.params.id
    }, function (err, results) {
        res.json(results);
    });
});

module.exports = router;
<|endoftext|>


<commit_before>var Q     = require('q'),
    File = require('../models/file');

exports.upload = function(req, res) {
    // var eventTitle = req.body.title,
    //     eventLocation = req.body.location,
    //     eventDescription = req.body.description,
    //     eventStart = req.body.start,
    //     eventEnd = req.body.end,
    //     eventCategory = req.body.category,
    //     eventCreator = req.body.creator,
    //     eventSchoolId = req.body.schoolId,
    //     file = new File({
    //         title: eventTitle,
    //         location: eventLocation,
    //         description: eventDescription,
    //         start: eventStart,
    //         end: eventEnd,
    //         category: eventCategory,
    //         creator: eventCreator,
    //         created: new Date(),
    //         schoolId: eventSchoolId
    //     });

    console.log(req.files);

    // var saveFile = function(file) {
    //     var deferred = Q.defer();

    //     file.save(function (err, savedFile) {
    //         if (err) {
    //             deferred.reject(err.message);
    //         }
    //         else {
    //             deferred.resolve(savedEvent);
    //         }
    //     });

    //     return deferred.promise;
    // }

    // saveFile(event).then(function(data) {
    //     res.json(data);
    // }, function(){
    //     res.send(500, 'failed to upload new file');
    // });
};

exports.get = function(req, res) {
	var fileId = req.params.fileId;

    var findFile = function(reqFileId) {
        var deferred = Q.defer();

        File.find({ _id: reqFileId }, function (err, event) {
            if (err) {
                deferred.reject(err.message);
            }
            else {
                deferred.resolve(event);
            }
        });

        return deferred.promise;
    }

    findFile(fileId).then(function(data) {
        res.json(data);
    }, function() {
        res.send(500, 'failed to retrieve file by ID');
    });
};<commit_msg>added response to file upload<commit_after>var Q     = require('q'),
    File = require('../models/file');

exports.upload = function(req, res) {
    // var eventTitle = req.body.title,
    //     eventLocation = req.body.location,
    //     eventDescription = req.body.description,
    //     eventStart = req.body.start,
    //     eventEnd = req.body.end,
    //     eventCategory = req.body.category,
    //     eventCreator = req.body.creator,
    //     eventSchoolId = req.body.schoolId,
    //     file = new File({
    //         title: eventTitle,
    //         location: eventLocation,
    //         description: eventDescription,
    //         start: eventStart,
    //         end: eventEnd,
    //         category: eventCategory,
    //         creator: eventCreator,
    //         created: new Date(),
    //         schoolId: eventSchoolId
    //     });

    console.log(req.files);
    res.send("OK");

    // var saveFile = function(file) {
    //     var deferred = Q.defer();

    //     file.save(function (err, savedFile) {
    //         if (err) {
    //             deferred.reject(err.message);
    //         }
    //         else {
    //             deferred.resolve(savedEvent);
    //         }
    //     });

    //     return deferred.promise;
    // }

    // saveFile(event).then(function(data) {
    //     res.json(data);
    // }, function(){
    //     res.send(500, 'failed to upload new file');
    // });
};

exports.get = function(req, res) {
	var fileId = req.params.fileId;

    var findFile = function(reqFileId) {
        var deferred = Q.defer();

        File.find({ _id: reqFileId }, function (err, event) {
            if (err) {
                deferred.reject(err.message);
            }
            else {
                deferred.resolve(event);
            }
        });

        return deferred.promise;
    }

    findFile(fileId).then(function(data) {
        res.json(data);
    }, function() {
        res.send(500, 'failed to retrieve file by ID');
    });
};<|endoftext|>


<commit_before>// soundcloud api
var SC_ID = 'ba47209edc0a4c129a460a936fb4e9f2';
// var TRACK_URL = 'https://soundcloud.com/longarms/starpower';
var TRACK_URL = 'https://soundcloud.com/nicolas-jaar/flashy-flashy';

SC.initialize({
  client_id: SC_ID
});

window.onload = init;

function init() {
  var root = new THREERoot({
    fov: 120,
    alpha: false
  });
  root.renderer.setClearColor(0x000000);//0x0e0609
  root.camera.position.set(0, 560, 0);

  var bloomPass = new THREE.BloomPass(4.0, 25, 4, 512);
  var copyPass = new THREE.ShaderPass(THREE.CopyShader);

  root.initPostProcessing([
    bloomPass,
    copyPass
  ]);

  // root.controls.autoRotate = true;
  var lightColor = new THREE.Color();

  lightColor.setHSL(0.00, 1.0, 0.5);
  var centerLight = new THREE.PointLight(lightColor, 0, 600, 2);//0xECD078
  root.add(centerLight);

  lightColor.setHSL(0.33, 0.25, 0.5);
  var topLight = new THREE.DirectionalLight(lightColor, 0.5); // 0xD95B43
  topLight.position.set(0, 1, 0);
  root.add(topLight);

  lightColor.setHSL(0.66, 0.25, 0.5);
  var bottomLight = new THREE.DirectionalLight(lightColor, 0.5); //0xC02942
  bottomLight.position.set(0, -1, 0);
  root.add(bottomLight);

  // generate spline
  var pointCount = 32;
  var points = [];
  var radius = 300;
  var x, y, z, pivotDistance;

  for (var i = 0; i < pointCount; i++) {
    var angle = Math.PI * 2 * i / pointCount;
    var r = radius * THREE.Math.randFloat(0.5, 1.0);

    x = Math.cos(angle) * r;
    y = 0;// THREE.Math.randFloat(-64, 64);// * (i % 2 ? 1 : -1)
    z = Math.sin(angle) * r;

    pivotDistance = 1;

    var v = new THREE.Vector4(x, y, z, pivotDistance);
    v._y = THREE.Math.randFloatSpread(256);

    points.push(v);
  }

  var animation = new Animation(points);
  var tween = animation.animate(24.0, {ease: Power0.easeInOut, repeat:-1});

  root.add(animation);

  // audio

  var audioInput = document.getElementById('audioInput');
  audioInput.value = TRACK_URL;
  audioInput.addEventListener('input', function() {
    audioInput.value && (audioInput.value.indexOf('http') == 0) && getTrack(audioInput.value);
  });

  var audioElement = document.getElementById('player');
  audioElement.crossOrigin = 'Anonymous';
  audioElement.loop = true;

  var analyzer = new SpectrumAnalyzer(pointCount, 0.75);
  analyzer.setSource(audioElement);

  var scLink = document.getElementById('sc_link');
  var scImage = document.getElementById('sc_img');

  var scVisible = true;
  var sc = document.getElementById('soundcloud');

  window.addEventListener('keyup', function(e) {
    if (e.keyCode === 88) {
      sc.style.display = (scVisible = !scVisible) ? 'block' : 'none';
    }
  });

  function getTrack(url) {
    SC.get('/resolve', {url: url}).then(function(data) {
      console.log('success?', data);

      if (typeof data.errors === 'undefined') {
        if (data.streamable) {
          audioElement.src = data.stream_url + '?client_id=' + SC_ID;
          scLink.href = data.permalink_url;
          scImage.src = data.artwork_url;
        }
        else {
          alert('This SoundCloud URL is not allowed to be streamed.');
        }
      }
      else {
        alert('SoundCloud error :(');
      }
    });
  }
  getTrack(TRACK_URL);

  // VISUALISER UPDATE LOOP

  root.addUpdateCallback(function() {
    analyzer.updateSample();

    var spline = animation.material.uniforms['uPath'].value;
    var data = analyzer.frequencyByteData;

    var avg = analyzer.getAverageFloat();
    var avgLL = analyzer.getAverageFloat(0, 8);
    var avgML = analyzer.getAverageFloat(8, 16);
    var avgMH = analyzer.getAverageFloat(16, 24);
    var avgHH = analyzer.getAverageFloat(24, 32);

    console.log(avgLL, avgML, avgMH, avgHH);

    animation.material.uniforms.roughness.value =     mapEase(Power2.easeInOut, avgLL, 0.0, 1.0, 0/5, 1.0);
    animation.material.uniforms.metalness.value =     mapEase(Power2.easeInOut, avgML, 0.0, 1.0, 0.0, 0.5);
    animation.material.uniforms.uGlobalPivot.value =  mapEase(Power4.easeOut, avgHH, 0.0, 1.0, 2.0, 0.125);

    centerLight.intensity = mapEase(Power2.easeIn, avg, 0.0, 1.0, 0.5, 1.0);
    topLight.intensity = mapEase(Power2.easeIn, avg, 0.0, 1.0, 0.0, 4.0);
    bottomLight.intensity = mapEase(Power2.easeIn, avg, 0.0, 1.0, 0.0, 4.0);

    tween.timeScale(avg);

    var maxY = mapEase(Power2.easeOut, avgLL, 0.0, 1.0, 0, 100);
    var maxW = mapEase(Power4.easeIn, avgHH, 0.0, 1.0, 100, 600);

    for (var i = 0; i < spline.length; i++) {
      var p = spline[i];

      p.y = p._y + data[i] / 255 * maxY * (i % 2 ? 1 : -1);
      p.w = data[i] / 255 * maxW + 20;
    }

    animation.rotation.x += 0.01 * avgLL;
    animation.rotation.y += 0.01 * avgML;
    animation.rotation.z += 0.01 * avgMH;

    centerLight.color.offsetHSL(0.001, 0, 0);
    topLight.color.offsetHSL(0.001, 0, 0);
    bottomLight.color.offsetHSL(0.001, 0, 0);
  });
}

////////////////////
// CLASSES
////////////////////

function Animation(path) {
  var prefabGeometry = new THREE.PlaneGeometry(2, 1.0, 1, 8);
  var prefabCount = 20000;
  var geometry = new THREE.BAS.PrefabBufferGeometry(prefabGeometry, prefabCount);

  // ANIMATION

  var totalDuration = this.totalDuration = 1.0;

  var aDelayDuration = geometry.createAttribute('aDelayDuration', 2);
  var offset = 0;

  for (var i = 0; i < prefabCount; i++) {
    var pDelay = mapEase(Circ.easeOut, i, 0, prefabCount, 0, totalDuration);

    for (var j = 0; j < geometry.prefabVertexCount; j++) {
      var vDelay = j * 0.00025 * THREE.Math.randFloat(0.75, 1.25);

      aDelayDuration.array[offset++] =  (pDelay + vDelay);
      aDelayDuration.array[offset++] =  totalDuration;
    }
  }

  // PIVOT

  geometry.createAttribute('aPivotRotation', 2, function(data) {
    data[0] = Math.random();// * 0.5 + 0.5;
    data[1] = Math.PI * 2 * THREE.Math.randInt(16, 32);
  });

  // COLOR

  var color = new THREE.Color();

  geometry.createAttribute('color', 3, function(data, i, count) {
    var l = Math.random();
    color.setRGB(l, l, l);
    color.toArray(data);
  });

  // STANDARD PROPS

  geometry.createAttribute('aRM', 2, function(data, i, count) {
    data[0] = Math.random(); // roughness
    data[1] = Math.random(); // metalness
  });

  var material = new THREE.BAS.StandardAnimationMaterial({
    shading: THREE.FlatShading,
    vertexColors: THREE.VertexColors,
    side: THREE.DoubleSide,
    //transparent: true,
    defines: {
      PATH_LENGTH: path.length,
      PATH_MAX: (path.length).toFixed(1)
    },
    uniforms: {
      uTime: {value: 0},
      uPath: {value: path},
      uSmoothness: {value: new THREE.Vector2().setScalar(1.5)},
      uGlobalPivot: {value: 0},
    },
    uniformValues: {
      emissive: new THREE.Color(0x000000),//0x542437,0x0e0609
      roughness: 0,
      metalness: 0
    },
    vertexFunctions: [
      THREE.BAS.ShaderChunk['catmull_rom_spline'],
      THREE.BAS.ShaderChunk['quaternion_rotation']
    ],
    vertexParameters: [
      'uniform float uTime;',
      'uniform vec4 uPath[PATH_LENGTH];',
      'uniform vec2 uSmoothness;',
      'uniform float uGlobalPivot;',

      'attribute vec2 aDelayDuration;',
      'attribute vec2 aPivotRotation;',
      'attribute vec2 aRM;'
    ],
    varyingParameters: [
      'varying vec2 vRM;'
    ],
    vertexInit: [
      'float tProgress = mod((uTime + aDelayDuration.x), aDelayDuration.y) / aDelayDuration.y;',

      'vRM = aRM;'
    ],
    vertexPosition: [
      'float pathProgress = tProgress * PATH_MAX;',
      'float pathProgressFract = fract(pathProgress);',

      'ivec4 indices = getCatmullRomSplineIndicesClosed(PATH_MAX, pathProgress);',
      'vec4 p0 = uPath[indices[0]];',
      'vec4 p1 = uPath[indices[1]];',
      'vec4 p2 = uPath[indices[2]];',
      'vec4 p3 = uPath[indices[3]];',

      'vec3 tDelta = catmullRomSpline(p0.xyz, p1.xyz, p2.xyz, p3.xyz, pathProgressFract, uSmoothness);',
      'vec4 tQuat = quatFromAxisAngle(normalize(tDelta), aPivotRotation.y * tProgress);',

      'transformed += catmullRomSpline(p0.w, p1.w, p2.w, p3.w, pathProgressFract) * aPivotRotation.x * uGlobalPivot;',
      'transformed = rotateVector(tQuat, transformed);',
      'transformed += tDelta;'
    ],
    fragmentRoughness: [
      'roughnessFactor = roughness * vRM.x;'
    ],
    fragmentMetalness: [
      'metalnessFactor = metalness * vRM.y;'
    ]
  });

  THREE.Mesh.call(this, geometry, material);

  this.frustumCulled = false;
}
Animation.prototype = Object.create(THREE.Mesh.prototype);
Animation.prototype.constructor = Animation;
Object.defineProperty(Animation.prototype, 'time', {
  get: function () {
    return this.material.uniforms['uTime'].value;
  },
  set: function (v) {
    this.material.uniforms['uTime'].value = v;
  }
});
Animation.prototype.animate = function (duration, options) {
  options = options || {};
  options.time = this.totalDuration;

  return TweenMax.fromTo(this, duration, {time: 0.0}, options);
};

function SpectrumAnalyzer(binCount, smoothingTimeConstant) {
  var Context = window["AudioContext"] || window["webkitAudioContext"];

  this.context = new Context();
  this.analyzerNode = this.context.createAnalyser();

  this.setBinCount(binCount);
  this.setSmoothingTimeConstant(smoothingTimeConstant);
}

SpectrumAnalyzer.prototype = {
  setSource: function (source) {
    this.source = this.context.createMediaElementSource(source);
    this.source.connect(this.analyzerNode);
    this.analyzerNode.connect(this.context.destination);
  },

  setBinCount: function (binCount) {
    this.binCount = binCount;
    this.analyzerNode.fftSize = binCount * 2;

    this.frequencyByteData = new Uint8Array(binCount); 	// frequency
    this.timeByteData = new Uint8Array(binCount);		// waveform
  },
  setSmoothingTimeConstant: function (smoothingTimeConstant) {
    this.analyzerNode.smoothingTimeConstant = smoothingTimeConstant;
  },
  // not save if out of bounds
  getAverage: function (start, end) {
    var total = 0;

    start = start || 0;
    end = end || this.binCount;

    for (var i = start; i < end; i++) {
      total += this.frequencyByteData[i];
    }

    return total / (end - start);
  },
  getAverageFloat:function(start, end) {
    return this.getAverage(start, end) / 255;
  },

  updateSample: function () {
    this.analyzerNode.getByteFrequencyData(this.frequencyByteData);
    this.analyzerNode.getByteTimeDomainData(this.timeByteData);
  }
};

// utils
function ease(e, t, b, c, d) {
  return b + e.getRatio(t / d) * c;
}

function mapEase(e, v, x1, y1, x2, y2) {
  var t = v;
  var b = x2;
  var c = y2 - x2;
  var d = y1 - x1;

  return ease(e, t, b, c, d);
}
<commit_msg>tweaks<commit_after>// soundcloud api
var SC_ID = 'ba47209edc0a4c129a460a936fb4e9f2';
var TRACK_URL = 'https://soundcloud.com/longarms/starpower';
//var TRACK_URL = 'https://soundcloud.com/nicolas-jaar/flashy-flashy';

SC.initialize({
  client_id: SC_ID
});

window.onload = init;

function init() {
  var root = new THREERoot({
    fov: 120,
    alpha: false
  });
  root.renderer.setClearColor(0x000000);//0x0e0609
  root.camera.position.set(0, 560, 0);

  var bloomPass = new THREE.BloomPass(4.0, 25, 4, 512);
  var copyPass = new THREE.ShaderPass(THREE.CopyShader);

  root.initPostProcessing([
    bloomPass,
    copyPass
  ]);

  // root.controls.autoRotate = true;
  var lightColor = new THREE.Color();

  lightColor.setHSL(0.00, 1.0, 0.5);
  var centerLight = new THREE.PointLight(lightColor, 0, 600, 2);//0xECD078
  root.add(centerLight);

  lightColor.setHSL(0.33, 0.25, 0.5);
  var topLight = new THREE.DirectionalLight(lightColor, 0.5); // 0xD95B43
  topLight.position.set(0, 1, 0);
  root.add(topLight);

  lightColor.setHSL(0.66, 0.25, 0.5);
  var bottomLight = new THREE.DirectionalLight(lightColor, 0.5); //0xC02942
  bottomLight.position.set(0, -1, 0);
  root.add(bottomLight);

  // generate spline
  var pointCount = 32;
  var points = [];
  var radius = 300;
  var x, y, z, pivotDistance;

  for (var i = 0; i < pointCount; i++) {
    var angle = Math.PI * 2 * i / pointCount;
    var r = radius * THREE.Math.randFloat(0.5, 1.0);

    x = Math.cos(angle) * r;
    y = 0;// THREE.Math.randFloat(-64, 64);// * (i % 2 ? 1 : -1)
    z = Math.sin(angle) * r;

    pivotDistance = 1;

    var v = new THREE.Vector4(x, y, z, pivotDistance);
    v._y = THREE.Math.randFloatSpread(256);

    points.push(v);
  }

  var animation = new Animation(points);
  var tween = animation.animate(24.0, {ease: Power0.easeInOut, repeat:-1});

  root.add(animation);

  // audio

  var audioInput = document.getElementById('audioInput');
  audioInput.value = TRACK_URL;
  audioInput.addEventListener('input', function() {
    audioInput.value && (audioInput.value.indexOf('http') == 0) && getTrack(audioInput.value);
  });

  var audioElement = document.getElementById('player');
  audioElement.crossOrigin = 'Anonymous';
  audioElement.loop = true;

  var analyzer = new SpectrumAnalyzer(pointCount, 0.75);
  analyzer.setSource(audioElement);

  var scLink = document.getElementById('sc_link');
  var scImage = document.getElementById('sc_img');

  var scVisible = true;
  var sc = document.getElementById('soundcloud');

  window.addEventListener('keyup', function(e) {
    if (e.keyCode === 88) {
      sc.style.display = (scVisible = !scVisible) ? 'block' : 'none';
    }
  });

  function getTrack(url) {
    SC.get('/resolve', {url: url}).then(function(data) {
      console.log('success?', data);

      if (typeof data.errors === 'undefined') {
        if (data.streamable) {
          audioElement.src = data.stream_url + '?client_id=' + SC_ID;
          scLink.href = data.permalink_url;
          scImage.src = data.artwork_url;
        }
        else {
          alert('This SoundCloud URL is not allowed to be streamed.');
        }
      }
      else {
        alert('SoundCloud error :(');
      }
    });
  }
  getTrack(TRACK_URL);

  // VISUALISER UPDATE LOOP

  root.addUpdateCallback(function() {
    analyzer.updateSample();

    var spline = animation.material.uniforms['uPath'].value;
    var data = analyzer.frequencyByteData;

    var avg = analyzer.getAverageFloat();
    var avgLL = analyzer.getAverageFloat(0, 8);
    var avgML = analyzer.getAverageFloat(8, 16);
    var avgMH = analyzer.getAverageFloat(16, 24);
    var avgHH = analyzer.getAverageFloat(24, 32);

    animation.material.uniforms.roughness.value =     mapEase(Power2.easeInOut, avgLL, 0.0, 1.0, 0/5, 1.0);
    animation.material.uniforms.metalness.value =     mapEase(Power2.easeInOut, avgML, 0.0, 1.0, 0.0, 0.5);
    animation.material.uniforms.uGlobalPivot.value =  mapEase(Power4.easeOut, avgHH, 0.0, 1.0, 2.0, 0.125);

    centerLight.intensity = mapEase(Power2.easeIn, avg, 0.0, 1.0, 0.5, 1.0);
    topLight.intensity = mapEase(Power2.easeIn, avg, 0.0, 1.0, 0.0, 4.0);
    bottomLight.intensity = mapEase(Power2.easeIn, avg, 0.0, 1.0, 0.0, 4.0);

    tween.timeScale(avg);

    var maxY = mapEase(Power2.easeOut, avgLL, 0.0, 1.0, 0, 100);
    var maxW = mapEase(Power4.easeIn, avgHH, 0.0, 1.0, 100, 600);

    for (var i = 0; i < spline.length; i++) {
      var p = spline[i];

      p.y = p._y + data[i] / 255 * maxY * (i % 2 ? 1 : -1);
      p.w = data[i] / 255 * maxW + 20;
    }

    animation.rotation.x += 0.01 * avgLL;
    animation.rotation.y += 0.01 * avgML;
    animation.rotation.z += 0.01 * avgMH;

    centerLight.color.offsetHSL(0.001, 0, 0);
    topLight.color.offsetHSL(0.001, 0, 0);
    bottomLight.color.offsetHSL(0.001, 0, 0);
  });
}

////////////////////
// CLASSES
////////////////////

function Animation(path) {
  var prefabGeometry = new THREE.PlaneGeometry(4, 1.0, 1, 8);
  var prefabCount = 10000;
  var geometry = new THREE.BAS.PrefabBufferGeometry(prefabGeometry, prefabCount);

  // ANIMATION

  var totalDuration = this.totalDuration = 1.0;

  var aDelayDuration = geometry.createAttribute('aDelayDuration', 2);
  var offset = 0;

  for (var i = 0; i < prefabCount; i++) {
    var pDelay = mapEase(Circ.easeOut, i, 0, prefabCount, 0, totalDuration);

    for (var j = 0; j < geometry.prefabVertexCount; j++) {
      var vDelay = j * 0.00025 * THREE.Math.randFloat(0.75, 1.25);

      aDelayDuration.array[offset++] =  (pDelay + vDelay);
      aDelayDuration.array[offset++] =  totalDuration;
    }
  }

  // PIVOT

  geometry.createAttribute('aPivotRotation', 2, function(data) {
    data[0] = Math.random();// * 0.5 + 0.5;
    data[1] = Math.PI * 2 * THREE.Math.randInt(16, 32);
  });

  // COLOR

  var color = new THREE.Color();

  geometry.createAttribute('color', 3, function(data, i, count) {
    var l = Math.random();
    color.setRGB(l, l, l);
    color.toArray(data);
  });

  // STANDARD PROPS

  geometry.createAttribute('aRM', 2, function(data, i, count) {
    data[0] = Math.random(); // roughness
    data[1] = Math.random(); // metalness
  });

  var material = new THREE.BAS.StandardAnimationMaterial({
    shading: THREE.FlatShading,
    vertexColors: THREE.VertexColors,
    side: THREE.DoubleSide,
    //transparent: true,
    defines: {
      PATH_LENGTH: path.length,
      PATH_MAX: (path.length).toFixed(1)
    },
    uniforms: {
      uTime: {value: 0},
      uPath: {value: path},
      uSmoothness: {value: new THREE.Vector2().setScalar(1.5)},
      uGlobalPivot: {value: 0},
    },
    uniformValues: {
      emissive: new THREE.Color(0x000000),//0x542437,0x0e0609
      roughness: 0,
      metalness: 0
    },
    vertexFunctions: [
      THREE.BAS.ShaderChunk['catmull_rom_spline'],
      THREE.BAS.ShaderChunk['quaternion_rotation']
    ],
    vertexParameters: [
      'uniform float uTime;',
      'uniform vec4 uPath[PATH_LENGTH];',
      'uniform vec2 uSmoothness;',
      'uniform float uGlobalPivot;',

      'attribute vec2 aDelayDuration;',
      'attribute vec2 aPivotRotation;',
      'attribute vec2 aRM;'
    ],
    varyingParameters: [
      'varying vec2 vRM;'
    ],
    vertexInit: [
      'float tProgress = mod((uTime + aDelayDuration.x), aDelayDuration.y) / aDelayDuration.y;',

      'vRM = aRM;'
    ],
    vertexPosition: [
      'float pathProgress = tProgress * PATH_MAX;',
      'float pathProgressFract = fract(pathProgress);',

      'ivec4 indices = getCatmullRomSplineIndicesClosed(PATH_MAX, pathProgress);',
      'vec4 p0 = uPath[indices[0]];',
      'vec4 p1 = uPath[indices[1]];',
      'vec4 p2 = uPath[indices[2]];',
      'vec4 p3 = uPath[indices[3]];',

      'vec3 tDelta = catmullRomSpline(p0.xyz, p1.xyz, p2.xyz, p3.xyz, pathProgressFract, uSmoothness);',
      'vec4 tQuat = quatFromAxisAngle(normalize(tDelta), aPivotRotation.y * tProgress);',

      'transformed += catmullRomSpline(p0.w, p1.w, p2.w, p3.w, pathProgressFract) * aPivotRotation.x * uGlobalPivot;',
      'transformed = rotateVector(tQuat, transformed);',
      'transformed += tDelta;'
    ],
    fragmentRoughness: [
      'roughnessFactor = roughness * vRM.x;'
    ],
    fragmentMetalness: [
      'metalnessFactor = metalness * vRM.y;'
    ]
  });

  THREE.Mesh.call(this, geometry, material);

  this.frustumCulled = false;
}
Animation.prototype = Object.create(THREE.Mesh.prototype);
Animation.prototype.constructor = Animation;
Object.defineProperty(Animation.prototype, 'time', {
  get: function () {
    return this.material.uniforms['uTime'].value;
  },
  set: function (v) {
    this.material.uniforms['uTime'].value = v;
  }
});
Animation.prototype.animate = function (duration, options) {
  options = options || {};
  options.time = this.totalDuration;

  return TweenMax.fromTo(this, duration, {time: 0.0}, options);
};

function SpectrumAnalyzer(binCount, smoothingTimeConstant) {
  var Context = window["AudioContext"] || window["webkitAudioContext"];

  this.context = new Context();
  this.analyzerNode = this.context.createAnalyser();

  this.setBinCount(binCount);
  this.setSmoothingTimeConstant(smoothingTimeConstant);
}

SpectrumAnalyzer.prototype = {
  setSource: function (source) {
    this.source = this.context.createMediaElementSource(source);
    this.source.connect(this.analyzerNode);
    this.analyzerNode.connect(this.context.destination);
  },

  setBinCount: function (binCount) {
    this.binCount = binCount;
    this.analyzerNode.fftSize = binCount * 2;

    this.frequencyByteData = new Uint8Array(binCount); 	// frequency
    this.timeByteData = new Uint8Array(binCount);		// waveform
  },
  setSmoothingTimeConstant: function (smoothingTimeConstant) {
    this.analyzerNode.smoothingTimeConstant = smoothingTimeConstant;
  },
  // not save if out of bounds
  getAverage: function (start, end) {
    var total = 0;

    start = start || 0;
    end = end || this.binCount;

    for (var i = start; i < end; i++) {
      total += this.frequencyByteData[i];
    }

    return total / (end - start);
  },
  getAverageFloat:function(start, end) {
    return this.getAverage(start, end) / 255;
  },

  updateSample: function () {
    this.analyzerNode.getByteFrequencyData(this.frequencyByteData);
    this.analyzerNode.getByteTimeDomainData(this.timeByteData);
  }
};

// utils
function ease(e, t, b, c, d) {
  return b + e.getRatio(t / d) * c;
}

function mapEase(e, v, x1, y1, x2, y2) {
  var t = v;
  var b = x2;
  var c = y2 - x2;
  var d = y1 - x1;

  return ease(e, t, b, c, d);
}
<|endoftext|>


<commit_before>var fs = require('fs');
var dialog = require('dialog');
var dispatcher = require('./dispatcher.js');
var jekyllController = require('./jekyll-controller.js');

var sitesList = [
  {
    id: 2,
    name: "Dummy site",
    filePath: "/Users/lalabadie/git/l-a.github.io",
    configFile: "_config.yml",
    serverActive: false,
    serverRequested: false,
    server: null
  }
];

this.siteById = function(id) {
  for (i=0; i<sitesList.length; i++) {
    if (sitesList[i].id === id) {
      return sitesList[i];
    }
  }
}

this.setSiteProperty = function(id, property, value) {
  var site = this.siteById(id);
  site[property] = value;
}

this.sendSitesList = function(requester) {
  requester.send('updateSitesList', sitesList);
};

this.addSite = function(requester, filePaths) {
  // TODO support multiple directories opening at once
  // (or split into handling the general OS "open" command and only manage the dialog here)

  var filePaths = (typeof filePaths === "string" ? [filePaths] : filePaths) || dialog.showOpenDialog({ properties: [ 'openDirectory' ]});
  console.log(filePaths);

  if ( filePaths != undefined ) {
    for (i = 0; i < filePaths.length; i++) {
      var filePath = filePaths[i];
      var automaticName = filePath.slice(filePath.lastIndexOf("/") + 1);
      var id = new Date().valueOf(); // I am an expert at unique IDs

      sitesList.push({
        id: id,
        name: automaticName,
        filePath: filePath,
        serverActive: false,
        serverRequested: false,
        server: null
      });
    }

    this.sendSitesList(requester);
  }
}

this.createSite = function(requester) {
  var folderPath = dialog.showSaveDialog({ properties: [ 'openDirectory' ]}).replace(/["']/g, "");

  fs.mkdir(folderPath);
  jekyllController.createNewSite(requester, folderPath);
}
<commit_msg>Handle canceled site creation<commit_after>var fs = require('fs');
var dialog = require('dialog');
var dispatcher = require('./dispatcher.js');
var jekyllController = require('./jekyll-controller.js');

var sitesList = [
  {
    id: 2,
    name: "Dummy site",
    filePath: "/Users/lalabadie/git/l-a.github.io",
    configFile: "_config.yml",
    serverActive: false,
    serverRequested: false,
    server: null
  }
];

this.siteById = function(id) {
  for (i=0; i<sitesList.length; i++) {
    if (sitesList[i].id === id) {
      return sitesList[i];
    }
  }
}

this.setSiteProperty = function(id, property, value) {
  var site = this.siteById(id);
  site[property] = value;
}

this.sendSitesList = function(requester) {
  requester.send('updateSitesList', sitesList);
};

this.addSite = function(requester, filePaths) {
  // TODO support multiple directories opening at once
  // (or split into handling the general OS "open" command and only manage the dialog here)

  var filePaths = (typeof filePaths === "string" ? [filePaths] : filePaths) || dialog.showOpenDialog({ properties: [ 'openDirectory' ]});

  if ( filePaths != undefined ) {
    for (i = 0; i < filePaths.length; i++) {
      var filePath = filePaths[i];
      var automaticName = filePath.slice(filePath.lastIndexOf("/") + 1);
      var id = new Date().valueOf(); // I am an expert at unique IDs

      sitesList.push({
        id: id,
        name: automaticName,
        filePath: filePath,
        serverActive: false,
        serverRequested: false,
        server: null
      });
    }

    this.sendSitesList(requester);
  }
}

this.createSite = function(requester) {
  var folderPath = dialog.showSaveDialog({ properties: [ 'openDirectory' ]});
  if ( folderPath != undefined ) {
    folderPath = folderPath.replace(/["']/g, "");
    fs.mkdir(folderPath);
    jekyllController.createNewSite(requester, folderPath);
  };
}
<|endoftext|>


<commit_before>var path = require('path');
var expect = require('chai').expect;
var request = require('supertest');
var Sequelize = require('sequelize');
var User = require('../db/dbconfig').User;
var Topic = require('../db/dbconfig').Topic;
var Plurb = require('../db/dbconfig').Plurb;
var userController = require('../controllers/userController');
var topicController = require('../controllers/topicController');
var plurbController = require('../controllers/plurbController');
var server = require(path.join(__dirname, '..', './server.js')).app;
var app = require('../server').app;

describe('server', function () {
  'use strict';

  it('exists', function () {
    expect(server).to.be.a('function');
  });

  it('Port should be 3000 if server is running on local host', function () {
    var port;
    if (!process.env.port) {
      port = 3000;
      expect(port).to.equal(3000);
    }
  });
});

describe('Invalid Routes', function () {
  // test that proper error code is recieved for invalid url
  it('Should return error', function (done) {
    request(app)
    .get('/abc')
    .expect(404)
    .end(done);
  });
});

/* User Tests */
//User Controllers
describe('User Controllers', function () {
  describe('getAllUsers()', function () {
    it('should be a function', function () {
      expect(userController.getAllUsers).to.exist;
      expect(userController.getAllUsers).to.be.a('function');
    });
  });
  describe('getUser()', function () {
    it('should be a function', function () {
      expect(userController.getUser).to.exist;
      expect(userController.getUser).to.be.a('function');
    });
  });
  describe('findOrCreateUser()', function () {
    it('should be a function', function () {
      expect(userController.findOrCreateUser).to.exist;
      expect(userController.findOrCreateUser).to.be.a('function');
    });
  });
  describe('addFriend()', function () {
    it('should be a function', function () {
      expect(userController.addFriend).to.exist;
      expect(userController.addFriend).to.be.a('function');
    });
  });
  describe('getFriends()', function () {
    it('should be a function', function () {
      expect(userController.getFriends).to.exist;
      expect(userController.getFriends).to.be.a('function');
    });
  });
  describe('removeFriend()', function () {
    it('should be a function', function () {
      expect(userController.removeFriend).to.exist;
      expect(userController.removeFriend).to.be.a('function');
    });
  });
});

//User Routes
describe('API routes GET users is functioning', function () {
  var newUser = {
    googid: '111222333444',
    firstName: 'John',
    lastName: 'Doe',
    email: 'john@gmail.com',
  };

  beforeEach(function (done) {
    User.sync()
    .then(function () {
      done();
    });
  });

  beforeEach(function (done) {
    User.findOrCreate({where: newUser})
    .then(function () {
      done();
    });
  });

  it('responds with a 200 (OK)', function (done) {
    request(app)
      .get('api/users')
      .expect(200);
      done();
  });
});

// describe('It should GET all users', function (){
//     var idCount;
//     var newUser = {
//     firstName: 'Jane',
//     lastName: 'Doe',
//     email: 'jane@gmail.com',
//   };

  //get last id count
  // before(function (done) {
  //   request(app)
  //   .get('/api/user')
  //   .end(function (res){
  //     idCount = res.body;
  //     done();
  //   });
  // });
  //   console.log("idCount: ", idCount);
  //create new user
  //get last id count
  //compare it
    //should be total+1
// });

describe('API route POST users', function () {
  var newUser = {
    googid: '556677889900',
    firstName: 'Post',
    lastName: 'Tester',
    email: 'pt@gmail.com',
  };

  beforeEach(function (done) {
    User.sync()
    .then(function () {
      done();
    });
  });

  beforeEach(function (done) {
    User.findOrCreate({where: newUser})
    .then(function () {
      done();
    });
  });

  it('responds with a 200 (OK)', function (done) {
    request(app)
      .post('api/user')
      .expect(201);
      done();
  });
});

/* Topic Tests */
//Topic Controllers
describe('Topic Controllers', function () {
  describe('getAllTopics()', function () {
    it('should be a function', function () {
      expect(topicController.getAllTopics).to.exist;
      expect(topicController.getAllTopics).to.be.a('function');
    });
  });
  describe('createTopic', function () {
    it('should be a function', function () {
      expect(topicController.createTopic).to.exist;
      expect(topicController.createTopic).to.be.a('function');
    });
  });
  describe('getTopicByName()', function () {
    it('should be a function', function () {
      expect(topicController.getTopicByName).to.exist;
      expect(topicController.getTopicByName).to.be.a('function');
    });
  });
  describe('deleteTopic', function () {
    it('should be a function', function () {
      expect(topicController.deleteTopic).to.exist;
      expect(topicController.deleteTopic).to.be.a('function');
    });
  });
});

describe('API routes GET topics', function () {

  var newTopic = {
    name: 'Animal Rights'
  };

  beforeEach(function (done) {
    Topic.sync()
    .then(function () {
      done();
    });
  });

  beforeEach(function (done) {
    Topic.create(newTopic)
    .then(function () {
      done();
    });
  });

  it('responds with a 200 (OK)', function (done) {
    request(app)
      .get('api/topic')
      .expect(200);
      done();
  });
});

/* Plurb Tests */
//Plurb Controllers
describe('Plurb Controllers', function () {
  describe('getAllPlurbs()', function () {
    it('should be a function', function () {
      expect(plurbController.getAllPlurbs).to.exist;
      expect(plurbController.getAllPlurbs).to.be.a('function');
    });
  });
  describe('createPlurb', function () {
    it('should be a function', function () {
      expect(plurbController.createPlurb).to.exist;
      expect(plurbController.createPlurb).to.be.a('function');
    });
  });
  describe('getPlurb()', function () {
    it('should be a function', function () {
      expect(userController.createUser).to.exist;
      expect(userController.createUser).to.be.a('function');
    });
  });
  describe('deletePlurb()', function () {
    it('should be a function', function () {
      expect(userController.createUser).to.exist;
      expect(userController.createUser).to.be.a('function');
    });
  });
});

describe('API routes GET plurbs', function () {

  var newPlurb = {
    text: 'I am a test Plurb. We will change the world!',
    location: 'New York'
  };

  beforeEach(function (done) {
    Plurb.sync()
    .then(function () {
      done();
    });
  });

  beforeEach(function (done) {
    Plurb.create(newPlurb)
    .then(function () {
      done();
    });
  });

  it('responds with a 200 (OK)', function (done) {
    request(app)
      .get('api/plurb')
      .expect(200);
      done();
  });
});
<commit_msg>(test) Fix topi routes<commit_after>var path = require('path');
var expect = require('chai').expect;
var request = require('supertest');
var Sequelize = require('sequelize');
var User = require('../db/dbconfig').User;
var Topic = require('../db/dbconfig').Topic;
var Plurb = require('../db/dbconfig').Plurb;
var userController = require('../controllers/userController');
var topicController = require('../controllers/topicController');
var plurbController = require('../controllers/plurbController');
var server = require(path.join(__dirname, '..', './server.js')).app;
var app = require('../server').app;

describe('server', function () {
  'use strict';

  it('exists', function () {
    expect(server).to.be.a('function');
  });

  it('Port should be 3000 if server is running on local host', function () {
    var port;
    if (!process.env.port) {
      port = 3000;
      expect(port).to.equal(3000);
    }
  });
});

describe('Invalid Routes', function () {
  // test that proper error code is recieved for invalid url
  it('Should return error', function (done) {
    request(app)
    .get('/abc')
    .expect(404)
    .end(done);
  });
});

/* User Tests */
//User Controllers
describe('User Controllers', function () {
  describe('getAllUsers()', function () {
    it('should be a function', function () {
      expect(userController.getAllUsers).to.exist;
      expect(userController.getAllUsers).to.be.a('function');
    });
  });
  describe('getUser()', function () {
    it('should be a function', function () {
      expect(userController.getUser).to.exist;
      expect(userController.getUser).to.be.a('function');
    });
  });
  describe('findOrCreateUser()', function () {
    it('should be a function', function () {
      expect(userController.findOrCreateUser).to.exist;
      expect(userController.findOrCreateUser).to.be.a('function');
    });
  });
  describe('addFriend()', function () {
    it('should be a function', function () {
      expect(userController.addFriend).to.exist;
      expect(userController.addFriend).to.be.a('function');
    });
  });
  describe('getFriends()', function () {
    it('should be a function', function () {
      expect(userController.getFriends).to.exist;
      expect(userController.getFriends).to.be.a('function');
    });
  });
  describe('removeFriend()', function () {
    it('should be a function', function () {
      expect(userController.removeFriend).to.exist;
      expect(userController.removeFriend).to.be.a('function');
    });
  });
});

//User Routes
describe('API routes GET users is functioning', function () {
  var newUser = {
    googid: '111222333444',
    firstName: 'John',
    lastName: 'Doe',
    email: 'john@gmail.com',
  };

  beforeEach(function (done) {
    User.sync()
    .then(function () {
      done();
    });
  });

  beforeEach(function (done) {
    User.findOrCreate({where: newUser})
    .then(function () {
      done();
    });
  });

  it('responds with a 200 (OK)', function (done) {
    request(app)
      .get('api/users')
      .expect(200);
      done();
  });
});

// describe('It should GET all users', function (){
//     var idCount;
//     var newUser = {
//     firstName: 'Jane',
//     lastName: 'Doe',
//     email: 'jane@gmail.com',
//   };

  //get last id count
  // before(function (done) {
  //   request(app)
  //   .get('/api/user')
  //   .end(function (res){
  //     idCount = res.body;
  //     done();
  //   });
  // });
  //   console.log("idCount: ", idCount);
  //create new user
  //get last id count
  //compare it
    //should be total+1
// });

describe('API route POST users', function () {
  var newUser = {
    googid: '556677889900',
    firstName: 'Post',
    lastName: 'Tester',
    email: 'pt@gmail.com',
  };

  beforeEach(function (done) {
    User.sync()
    .then(function () {
      done();
    });
  });

  beforeEach(function (done) {
    User.findOrCreate({where: newUser})
    .then(function () {
      done();
    });
  });

  it('responds with a 200 (OK)', function (done) {
    request(app)
      .post('api/user')
      .expect(201);
      done();
  });
});

/* Topic Tests */
//Topic Controllers
describe('Topic Controllers', function () {
  describe('getAllTopics()', function () {
    it('should be a function', function () {
      expect(topicController.getAllTopics).to.exist;
      expect(topicController.getAllTopics).to.be.a('function');
    });
  });
  describe('findOrCreateTopic', function () {
    it('should be a function', function () {
      expect(topicController.findOrCreateTopic).to.exist;
      expect(topicController.findOrCreateTopic).to.be.a('function');
    });
  });
  describe('getTopicByName()', function () {
    it('should be a function', function () {
      expect(topicController.getTopicByName).to.exist;
      expect(topicController.getTopicByName).to.be.a('function');
    });
  });
  describe('deleteTopic', function () {
    it('should be a function', function () {
      expect(topicController.deleteTopic).to.exist;
      expect(topicController.deleteTopic).to.be.a('function');
    });
  });
});

describe('API routes GET topics', function () {

  var newTopic = {
    name: 'Animal Rights'
  };

  beforeEach(function (done) {
    Topic.sync()
    .then(function () {
      done();
    });
  });

  beforeEach(function (done) {
    Topic.create(newTopic)
    .then(function () {
      done();
    });
  });

  it('responds with a 200 (OK)', function (done) {
    request(app)
      .get('api/topic')
      .expect(200);
      done();
  });
});

/* Plurb Tests */
//Plurb Controllers
describe('Plurb Controllers', function () {
  describe('getAllPlurbs()', function () {
    it('should be a function', function () {
      expect(plurbController.getAllPlurbs).to.exist;
      expect(plurbController.getAllPlurbs).to.be.a('function');
    });
  });
  describe('createPlurb', function () {
    it('should be a function', function () {
      expect(plurbController.createPlurb).to.exist;
      expect(plurbController.createPlurb).to.be.a('function');
    });
  });
  describe('getPlurb()', function () {
    it('should be a function', function () {
      expect(userController.createUser).to.exist;
      expect(userController.createUser).to.be.a('function');
    });
  });
  describe('deletePlurb()', function () {
    it('should be a function', function () {
      expect(userController.createUser).to.exist;
      expect(userController.createUser).to.be.a('function');
    });
  });
});

describe('API routes GET plurbs', function () {

  var newPlurb = {
    text: 'I am a test Plurb. We will change the world!',
    location: 'New York'
  };

  beforeEach(function (done) {
    Plurb.sync()
    .then(function () {
      done();
    });
  });

  beforeEach(function (done) {
    Plurb.create(newPlurb)
    .then(function () {
      done();
    });
  });

  it('responds with a 200 (OK)', function (done) {
    request(app)
      .get('api/plurb')
      .expect(200);
      done();
  });
});
<|endoftext|>


<commit_before>const neo4j = require('neo4j-driver').v1;

const driver = neo4j.driver(
  process.env.NEO4J_URL,
  neo4j.auth.basic(process.env.NEO4J_USER, process.env.NEO4J_PASSWORD)
);

let findUser = user => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run('MATCH (u:USER {email: $email}) RETURN u', { email: user.email })
      .then(result => {
        session.close();
        if (result.records.length > 0) {
          resolve({ user: result.records[0] });
        }
        resolve({ user: null });
      })
      .catch(err => {
        reject(err);
      });
  });
};

let createUser = user => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run('CREATE (user:USER {id: $userid, name: $name, email: $email}) RETURN user', {
        userid: user.id.toString(),
        name: user.name,
        email: user.email
      })
      .then(result => {
        session.close();
        resolve(result);
      })
      .catch(err => reject(err));
  });
};

let createArticle = article => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'CREATE (a:ARTICLE {id: $id, title: $title, url: $url, keywords: $keywords}) \
        MERGE (author:AUTHOR {name: $author}) \
        MERGE (a)-[r:AUTHORED_BY]->(author) \
        MERGE (provider:PROVIDER {name: $provider}) \
        MERGE (a)-[ap:PUBLISHED_BY]->(provider) \
        ON CREATE SET ap.published_on=$pubDate \
        RETURN a',
        {
          id: article._id.toString(),
          title: article.title,
          provider: article.provider,
          author: article.author,
          pubDate: article.pubDate.toString(),
          url: article.url,
          keywords: article.keywords.toString()
        }
      )
      .then(result => {
        session.close();
        resolve({ msg: result.records[0] });
      })
      .catch(err => reject(err));
  });
};

let articleCategoryRelationship = article => {
  const session = driver.session();
  session
    .run('MATCH (a:ARTICLE {id: $id}), (c:CATEGORY {id: $subCatId}) CREATE (a)-[r:HAS_CATEGORY]->(c) RETURN a', {
      id: article._id.toString(),
      subCatId: article.subcategory._id.toString()
    })
    .then(result => {
      session.close();
      console.log('Article node and Relationship created.');
      console.log(result.records[0]);
    })
    .catch(err => console.log(err));
};

let createCategory = category => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run('CREATE (c:CATEGORY {name: $name, id: $id}) RETURN c', {
        name: category.name,
        id: category._id.toString()
      })
      .then(result => {
        session.close();
        resolve({ msg: result.records });
      })
      .catch(err => reject(err));
  });
};

let createParentChildRelationship = item => {
  console.log(item);
  const session = driver.session();
  return new Promise((resolve, reject) => {
    if (item.parent) {
      session
        .run(
          'MATCH (a:CATEGORY {id: $parentId}), (b:CATEGORY {id: $childId}) \
          CREATE (b)-[:HAS_PARENT]->(a)',
          {
            parentId: item.parent._id.toString(),
            childId: item._id.toString()
          }
        )
        .then(result => {
          session.close();
          resolve({ msg: result.records });
        })
        .catch(err => reject(err));
    }
  });
};

let userAction = (user, action, item) => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    if (action === 'like') {
      session
        .run('MATCH (u:USER {email: $useremail}), (a:ARTICLE {id: $id}) CREATE (u)-[r:LIKES]->(a) RETURN r', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
    } else if (action === 'dislike') {
      session
        .run('MATCH (u:USER {email: $useremail}), (a:ARTICLE {id: $id}) CREATE (u)-[r:DISLIKES]->(a) RETURN r', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
    } else if (action === 'save') {
      session
        .run('MATCH (u:USER {email: $useremail}), (a:ARTICLE {id: $id}) CREATE (u)-[r:LATER]->(a) RETURN r', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
    }
  });
};

let userInterestIn = (userId, interestId) => {
  const session = driver.session();
  session
    .run('MATCH (u:USER {id: $userId}), (c:CATEGORY {id: $categoryId}) CREATE (u)-[r:INTERESTED_IN]->(c) RETURN r', {
      userId: userId.toString(),
      categoryId: interestId.toString()
    })
    .then(result => {
      session.close();
      console.log(result);
    })
    .catch(err => console.log(err));
};

let userRecommendation = interests => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'MATCH (a:ARTICLE)-[:HAS_CATEGORY]-(c:CATEGORY) WHERE c.id in $InterestList WITH a \
        MATCH (a)-[pub:PUBLISHED_BY]-(p:PROVIDER) \
        MATCH (a)-[:AUTHORED_BY]-(au:AUTHOR) \
        RETURN DISTINCT a.id AS id, a.title AS title, a.url AS url, a.keywords AS keywords, p.name AS provider,au.name AS author, pub.pubDate AS pubDate ORDER BY pub.pubDate DESC LIMIT 100',
        {
          InterestList: interests
        }
      )
      .then(result => {
        session.close();
        resolve(result);
      })
      .catch(err => reject(err));
  });
};

let userSavedList = user => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'MATCH (a:ARTICLE)<-[:LATER]-(user:USER) WHERE user.email = $UserEmail \
        RETURN a.id AS id, a.title AS title, a.url AS url',
        {
          UserEmail: user.email
        }
      )
      .then(result => {
        session.close();
        resolve(result);
      })
      .catch(err => reject(err));
  });
};

module.exports = {
  findUser,
  createUser,
  createParentChildRelationship,
  createCategory,
  createArticle,
  articleCategoryRelationship,
  userAction,
  userInterestIn,
  userRecommendation,
  userSavedList
};
<commit_msg>implemented queries to undo user action if required<commit_after>const neo4j = require('neo4j-driver').v1;

const driver = neo4j.driver(
  process.env.NEO4J_URL,
  neo4j.auth.basic(process.env.NEO4J_USER, process.env.NEO4J_PASSWORD)
);

let findUser = user => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run('MATCH (u:USER {email: $email}) RETURN u', { email: user.email })
      .then(result => {
        session.close();
        if (result.records.length > 0) {
          resolve({ user: result.records[0] });
        }
        resolve({ user: null });
      })
      .catch(err => {
        reject(err);
      });
  });
};

let createUser = user => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run('CREATE (user:USER {id: $userid, name: $name, email: $email}) RETURN user', {
        userid: user.id.toString(),
        name: user.name,
        email: user.email
      })
      .then(result => {
        session.close();
        resolve(result);
      })
      .catch(err => reject(err));
  });
};

let createArticle = article => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'CREATE (a:ARTICLE {id: $id, title: $title, url: $url, keywords: $keywords}) \
        MERGE (author:AUTHOR {name: $author}) \
        MERGE (a)-[r:AUTHORED_BY]->(author) \
        MERGE (provider:PROVIDER {name: $provider}) \
        MERGE (a)-[ap:PUBLISHED_BY]->(provider) \
        ON CREATE SET ap.published_on=$pubDate \
        RETURN a',
        {
          id: article._id.toString(),
          title: article.title,
          provider: article.provider,
          author: article.author,
          pubDate: article.pubDate.toString(),
          url: article.url,
          keywords: article.keywords.toString()
        }
      )
      .then(result => {
        session.close();
        resolve({ msg: result.records[0] });
      })
      .catch(err => reject(err));
  });
};

let articleCategoryRelationship = article => {
  const session = driver.session();
  session
    .run('MATCH (a:ARTICLE {id: $id}), (c:CATEGORY {id: $subCatId}) CREATE (a)-[r:HAS_CATEGORY]->(c) RETURN a', {
      id: article._id.toString(),
      subCatId: article.subcategory._id.toString()
    })
    .then(result => {
      session.close();
      console.log('Article node and Relationship created.');
      console.log(result.records[0]);
    })
    .catch(err => console.log(err));
};

let createCategory = category => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run('CREATE (c:CATEGORY {name: $name, id: $id}) RETURN c', {
        name: category.name,
        id: category._id.toString()
      })
      .then(result => {
        session.close();
        resolve({ msg: result.records });
      })
      .catch(err => reject(err));
  });
};

let createParentChildRelationship = item => {
  console.log(item);
  const session = driver.session();
  return new Promise((resolve, reject) => {
    if (item.parent) {
      session
        .run(
          'MATCH (a:CATEGORY {id: $parentId}), (b:CATEGORY {id: $childId}) \
          CREATE (b)-[:HAS_PARENT]->(a)',
          {
            parentId: item.parent._id.toString(),
            childId: item._id.toString()
          }
        )
        .then(result => {
          session.close();
          resolve({ msg: result.records });
        })
        .catch(err => reject(err));
    }
  });
};

let userAction = (user, action, item) => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    switch (action) {
    case 'like':
      session
        .run('MATCH (u:USER {email: $useremail}), (a:ARTICLE {id: $id}) CREATE (u)-[r:LIKES]->(a) RETURN r', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'unlike':
      session
        .run('MATCH (u:USER {email: $useremail})-[r:LIKES]-(a:ARTICLE {id: $id}) DELETE r RETURN a', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'dislike':
      session
        .run('MATCH (u:USER {email: $useremail}), (a:ARTICLE {id: $id}) CREATE (u)-[r:DISLIKES]->(a) RETURN r', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'undislike':
      session
        .run('MATCH (u:USER {email: $useremail})-[r:DISLIKES]-(a:ARTICLE {id: $id}) DELETE r RETURN a', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'save':
      session
        .run('MATCH (u:USER {email: $useremail}), (a:ARTICLE {id: $id}) CREATE (u)-[r:LATER]->(a) RETURN r', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    case 'unsave':
      session
        .run('MATCH (u:USER {email: $useremail})-[r:LATER]-(a:ARTICLE {id: $id}) DELETE r RETURN a', {
          useremail: user.email,
          id: item._id.toString()
        })
        .then(result => {
          session.close();
          resolve({ msg: result });
        })
        .catch(err => reject(err));
      break;
    default:
      break;
    }
  });
};

let userInterestIn = (userId, interestId) => {
  const session = driver.session();
  session
    .run('MATCH (u:USER {id: $userId}), (c:CATEGORY {id: $categoryId}) CREATE (u)-[r:INTERESTED_IN]->(c) RETURN r', {
      userId: userId.toString(),
      categoryId: interestId.toString()
    })
    .then(result => {
      session.close();
      console.log(result);
    })
    .catch(err => console.log(err));
};

let userRecommendation = interests => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'MATCH (a:ARTICLE)-[:HAS_CATEGORY]-(c:CATEGORY) WHERE c.id in $InterestList WITH a \
        MATCH (a)-[pub:PUBLISHED_BY]-(p:PROVIDER) \
        MATCH (a)-[:AUTHORED_BY]-(au:AUTHOR) \
        RETURN DISTINCT a.id AS id, a.title AS title, a.url AS url, a.keywords AS keywords, p.name AS provider,au.name AS author, pub.pubDate AS pubDate ORDER BY pub.pubDate DESC LIMIT 100',
        {
          InterestList: interests
        }
      )
      .then(result => {
        session.close();
        resolve(result);
      })
      .catch(err => reject(err));
  });
};

let userSavedList = user => {
  const session = driver.session();
  return new Promise((resolve, reject) => {
    session
      .run(
        'MATCH (a:ARTICLE)<-[:LATER]-(user:USER) WHERE user.email = $UserEmail \
        RETURN a.id AS id, a.title AS title, a.url AS url',
        {
          UserEmail: user.email
        }
      )
      .then(result => {
        session.close();
        resolve(result);
      })
      .catch(err => reject(err));
  });
};

module.exports = {
  findUser,
  createUser,
  createParentChildRelationship,
  createCategory,
  createArticle,
  articleCategoryRelationship,
  userAction,
  userInterestIn,
  userRecommendation,
  userSavedList
};
<|endoftext|>


<commit_before>var models = require('../../../models'),
    async = require('async'),
    notifications = require('../../../api/notifications');

module.exports = function (req, res) {

    /*
     * 1. get action
     * 1.1 get user grade
     * 2. get "going_users" of action
     *
     * final - is curr user going
     * */
    var user = req.session.user;

    models.Action.findById(req.params[0])
        .select({
            _id: 1,
            creator_id: 1,
            category: 1,
            title: 1,
            text_field: 1,
            text_field_preview: 1,
            image_field: 1,
            image_field_preview: 1,
            tags: 1,
            location: 1,
            execution_date: 1,
            required_participants: 1,
            num_of_going: 1,
            cycle_id: 1,
            action_resources: 1,
            grade: 1,
            evaluate_counter: 1,
            is_approved: 1,
            admin_text: 1,
            system_message: 1,
            what_users_bring: 1,
            going_users: 1,
            cycle_id: 1,
            social_popup_title: 1,
            social_popup_text: 1
        })
        .populate('action_resources.resource')
        .populate('category', { _id: 1, name: 1 })
        .populate('cycle_id.cycle', { _id: 1, title: 1 })
        .populate('what_users_bring.user_id', {_id: 1, first_name: 1, last_name: 1, avatar: 1, facebook_id: 1})

        .exec(function (err, action) {
            if (err) {
                console.log('actions/main.js: Error finding action by id. ', arguments);
                return res.render('500.ejs', {error:err});
            }

            if (!action || !action.cycle_id) {
                console.log('actions/main.js: Action not found. ', arguments);
                return res.render('404.ejs', {error:err});
            }

            async.parallel({
                grade: function(cbk) {
                    //if pending find grade
                    if (user && !action.is_approved) {
                        models.GradeAction.findOne({ user_id:user._id, action_id: req.params[0] }, function (err, grade) {
                            if (!grade) {
                                cbk(err, null);
                            } else {
                                cbk(err, {
                                    grade_id: grade._id,
                                    value: grade.evaluation_grade
                                });
                            }
                        });
                    } else {
                        cbk(err, null);
                    }
                },

                user: function (cbk) {
                    _.each(action.what_users_bring, function(obj){obj.user_id.avatar = obj.user_id.avatar_url()})
                    if (req.session.user)
                        models.User.findById(req.session.user._id, cbk);
                    else {
                        cbk(null, null);
                    }
                }
            }, function (err, args) {
                if (err) {
                    return res.render('500.ejs', {error:err});
                }

                var proxyJson = args.user ? JSON.stringify(args.user.proxy) : null;
                var going_users = action.going_users;
                var cycle = action.cycle_id[0];

                action.num_of_going = going_users.length;
                action.grade_obj = args.grade;
                action.from_date = action.execution_date.date;
                // action.to_date = action.from_date.addHours(action.execution_date.duration);
                action.to_date = new Date(action.execution_date.date.getTime() + action.execution_date.duration);
                var is_going = false;

                // is user going to action?
                if(user){
                    var user_id = user._id;
                    is_going = going_users.some(function(going_user){ return going_user.user_id + "" == user_id + ""})
                }
                action.is_going = is_going;
                action.cycle_id = cycle;
                var ejsFileName = action.is_approved ? 'action_approved.ejs' : 'action_append.ejs';
                var type = action.is_approved ? 'approved_action' : 'pending_action';
                console.log(action.text_field_preview);
                res.render(ejsFileName,{
                    action: action,
                    tab: 'actions',
                    type: type,
                    proxy: proxyJson,
                    social_popup_title: action.social_popup_title,
                    social_popup_text: action.social_popup_text,
                    meta: {
                        type:'action',
                        id: action.id,
                        image: ((action.image_field_preview && action.image_field_preview.url) ||
                            (action.image_field && action.image_field.url)),
                        title: action && action.title,
                        description: action.text_field_preview || action.text_field,
                        link: action && ('/action/' + action.id)
                    }
                });
            });
        });
};
<commit_msg>facebook app, join to action #2<commit_after>var models = require('../../../models'),
    async = require('async'),
    notifications = require('../../../api/notifications');

module.exports = function (req, res) {

    /*
     * 1. get action
     * 1.1 get user grade
     * 2. get "going_users" of action
     *
     * final - is curr user going
     * */
    var user = req.session.user;

    models.Action.findById(req.params[0])
        .select({
            _id: 1,
            creator_id: 1,
            category: 1,
            title: 1,
            text_field: 1,
            text_field_preview: 1,
            image_field: 1,
            image_field_preview: 1,
            tags: 1,
            location: 1,
            execution_date: 1,
            required_participants: 1,
            num_of_going: 1,
            cycle_id: 1,
            action_resources: 1,
            grade: 1,
            evaluate_counter: 1,
            is_approved: 1,
            admin_text: 1,
            system_message: 1,
            what_users_bring: 1,
            going_users: 1,
            cycle_id: 1,
            social_popup_title: 1,
            social_popup_text: 1
        })
        .populate('action_resources.resource')
        .populate('category', { _id: 1, name: 1 })
        .populate('cycle_id.cycle', { _id: 1, title: 1 })
        .populate('what_users_bring.user_id', {_id: 1, first_name: 1, last_name: 1, avatar: 1, facebook_id: 1})

        .exec(function (err, action) {
            if (err) {
                console.log('actions/main.js: Error finding action by id. ', arguments);
                return res.render('500.ejs', {error:err});
            }

            if (!action || !action.cycle_id) {
                console.log('actions/main.js: Action not found. ', arguments);
                return res.render('404.ejs', {error:err});
            }

            async.parallel({
                grade: function(cbk) {
                    //if pending find grade
                    if (user && !action.is_approved) {
                        models.GradeAction.findOne({ user_id:user._id, action_id: req.params[0] }, function (err, grade) {
                            if (!grade) {
                                cbk(err, null);
                            } else {
                                cbk(err, {
                                    grade_id: grade._id,
                                    value: grade.evaluation_grade
                                });
                            }
                        });
                    } else {
                        cbk(err, null);
                    }
                },

                user: function (cbk) {
                    _.each(action.what_users_bring, function(obj){obj.user_id.avatar = obj.user_id.avatar_url()})
                    if (req.session.user)
                        models.User.findById(req.session.user._id, cbk);
                    else {
                        cbk(null, null);
                    }
                }
            }, function (err, args) {
                if (err) {
                    return res.render('500.ejs', {error:err});
                }

                var proxyJson = args.user ? JSON.stringify(args.user.proxy) : null;
                var going_users = action.going_users;
                var cycle = action.cycle_id[0];

                action.num_of_going = going_users.length;
                action.grade_obj = args.grade;
                action.from_date = action.execution_date.date;
                // action.to_date = action.from_date.addHours(action.execution_date.duration);
                action.to_date = new Date(action.execution_date.date.getTime() + action.execution_date.duration);
                var is_going = false;

                // is user going to action?
                if(user){
                    var user_id = user._id;
                    is_going = going_users.some(function(going_user){ return going_user.user_id + "" == user_id + ""})
                }
                action.is_going = is_going;
                action.cycle_id = cycle;
                var ejsFileName = action.is_approved ? 'action_approved.ejs' : 'action_append.ejs';
                var type = action.is_approved ? 'approved_action' : 'pending_action';
                console.log(action.text_field_preview);
                res.render(ejsFileName,{
                    action: action,
                    tab: 'actions',
                    type: type,
                    proxy: proxyJson,
                    social_popup_title: action.social_popup_title,
                    social_popup_text: action.social_popup_text,
                    meta: {
                        type:'go',
                        id: action.id,
                        image: ((action.image_field_preview && action.image_field_preview.url) ||
                            (action.image_field && action.image_field.url)),
                        title: action && action.title,
                        description: action.text_field_preview || action.text_field,
                        link: action && ('/action/' + action.id)
                    }
                });
            });
        });
};
<|endoftext|>


<commit_before>/**
 * @classdesc
 * Represents a GeometryCollection.
 * @class
 * @category geometry
 * @extends maptalks.Geometry
 * @param {maptalks.Geometry[]} geometries - GeometryCollection's geometries
 */
Z.GeometryCollection = Z.Geometry.extend(/** @lends maptalks.GeometryCollection.prototype */{
    type:Z.Geometry['TYPE_GEOMETRYCOLLECTION'],

    exceptionDefs:{
        'en-US':{
            'INVALID_GEOMETRY':'invalid geometry for collection.'
        },
        'zh-CN':{
            'INVALID_GEOMETRY':'无效的Geometry被加入到collection中.'
        }
    },

    initialize:function (geometries, opts) {
        this._initOptions(opts);
        this.setGeometries(geometries);
    },

    /**
     * Set new geometries to the geometry collection
     * @param {maptalks.Geometry[]} geometries
     * @return {maptalks.GeometryCollection} this
     */
    setGeometries:function (_geometries) {
        var geometries = this._checkGeometries(_geometries);
        //Set the collection as child geometries' parent.
        if (Z.Util.isArray(geometries)) {
            for (var i = geometries.length - 1; i >= 0; i--) {
                geometries[i]._initOptions(this.config());
                geometries[i]._setParent(this);
                geometries[i].setEventParent(this);
                geometries[i].setSymbol(this.getSymbol());
            }
        }
        this._geometries = geometries;
        if (this.getLayer()) {
            this._bindGeometriesToLayer();
            this._onShapeChanged();
        }
        return this;
    },

    /**
     * Get geometries of the geometry collection
     * @return {maptalks.Geometry[]}
     */
    getGeometries:function () {
        if (!this._geometries) {
            return [];
        }
        return this._geometries;
    },

    /**
     * Travels among the geometries the collection has.
     * @param  {Function} fn - a callback function
     * @param  {*} context   - callback's context
     * @return {maptalks.GeometryCollection} this
     */
    forEach: function (fn, context) {
        if (!context) {
            context = this;
        }
        var geometries = this.getGeometries();
        for (var i = 0, len = geometries.length; i < len; i++) {
            if (!geometries[i]) {
                continue;
            }
            fn.call(context, geometries[i], i);
        }
        return this;
    },

    select: function (condition) {
        var evaFn = new Function('geometry', 'with (geometry) { return ' + condition + '; }');
        var selected = [];
        this.forEach(function (geometry) {
            var json = {
                'type' : geometry.getType(),
                'properties' : geometry._exportProperties()
            };
            if (evaFn(json) === true) {
                selected.push(geometry);
            }
        });
        return selected.length > 0 ? new Z.GeometryCollection(selected) : null;
    },

    /**
     * Translate or move the geometry collection by the given offset.
     * @param  {maptalks.Coordinate} offset - translate offset
     * @return {maptalks.GeometryCollection} this
     */
    translate:function (offset) {
        if (!offset) {
            return this;
        }
        if (this.isEmpty()) {
            return this;
        }
        this.forEach(function (geometry) {
            if (geometry && geometry.translate) {
                geometry.translate(offset);
            }
        });
        return this;
    },

    /**
     * Whether the geometry collection is empty
     * @return {Boolean}
     */
    isEmpty:function () {
        return !Z.Util.isArrayHasData(this.getGeometries());
    },

    /**
     * remove itself from the layer if any.
     * @returns {maptalks.Geometry} this
     * @fires maptalks.Geometry#removestart
     * @fires maptalks.Geometry#remove
     */
    remove:function () {
        this.forEach(function (geometry) {
            geometry._rootRemove();
        });
        this._rootRemoveAndFireEvent();
        return this;
    },

    /**
     * Show the geometry collection.
     * @return {maptalks.GeometryCollection} this
     * @fires maptalks.Geometry#show
     */
    show:function () {
        this.options['visible'] = true;
        this.forEach(function (geometry) {
            geometry.show();
        });
        return this;
    },

    /**
     * Hide the geometry collection.
     * @return {maptalks.GeometryCollection} this
     * @fires maptalks.Geometry#hide
     */
    hide:function () {
        this.options['visible'] = false;
        this.forEach(function (geometry) {
            geometry.hide();
        });
        return this;
    },

    setSymbol:function (symbol) {
        if (!symbol) {
            this._symbol = null;
        } else {
            var camelSymbol = this._prepareSymbol(symbol);
            this._symbol = camelSymbol;
        }
        this.forEach(function (geometry) {
            geometry.setSymbol(symbol);
        });
        this._onSymbolChanged();
        return this;
    },

    onConfig:function (config) {
        this.forEach(function (geometry) {
            geometry.config(config);
        });
    },

    /**
     * bind this geometry collection to a layer
     * @param  {maptalks.Layer} layer
     * @private
     */
    _bindLayer:function (layer) {
        this._commonBindLayer(layer);
        this._bindGeometriesToLayer();
    },

    _bindGeometriesToLayer:function () {
        var layer = this.getLayer();
        this.forEach(function (geometry) {
            geometry._bindLayer(layer);
        });
    },

    /**
     * Check whether the type of geometries is valid
     * @param  {maptalks.Geometry[]} geometries - geometries to check
     * @private
     */
    _checkGeometries:function (geometries) {
        if (geometries && !Z.Util.isArray(geometries)) {
            if (geometries instanceof Z.Geometry) {
                return [geometries];
            } else {
                throw new Error(this.exceptions['INVALID_GEOMETRY']);
            }
        } else if (Z.Util.isArray(geometries)) {
            for (var i = 0, len = geometries.length; i < len; i++) {
                if (!(geometries[i] instanceof Z.Geometry)) {
                    throw new Error(this.exceptions['INVALID_GEOMETRY']);
                }
            }
            return geometries;
        }
        return null;
    },

    _updateCache:function () {
        delete this._extent;
        if (this.isEmpty()) {
            return;
        }
        this.forEach(function (geometry) {
            if (geometry && geometry._updateCache) {
                geometry._updateCache();
            }
        });
    },

    _removePainter:function () {
        if (this._painter) {
            this._painter.remove();
        }
        delete this._painter;
        this.forEach(function (geometry) {
            geometry._removePainter();
        });
    },

    _computeCenter:function (projection) {
        if (!projection || this.isEmpty()) {
            return null;
        }
        var sumX = 0, sumY = 0, counter = 0;
        var geometries = this.getGeometries();
        for (var i = 0, len = geometries.length; i < len; i++) {
            if (!geometries[i]) {
                continue;
            }
            var center = geometries[i]._computeCenter(projection);
            if (center) {
                sumX += center.x;
                sumY += center.y;
                counter++;
            }
        }
        if (counter === 0) {
            return null;
        }
        return new Z.Coordinate(sumX / counter, sumY / counter);
    },

    _containsPoint: function (point, t) {
        if (this.isEmpty()) {
            return false;
        }
        var i, len;
        var geometries = this.getGeometries();
        for (i = 0, len = geometries.length; i < len; i++) {
            if (geometries[i]._containsPoint(point, t)) {
                return true;
            }
        }

        return false;
    },

    _computeExtent:function (projection) {
        if (this.isEmpty()) {
            return null;
        }
        var geometries = this.getGeometries();
        var result = null;
        for (var i = 0, len = geometries.length; i < len; i++) {
            if (!geometries[i]) {
                continue;
            }
            var geoExtent = geometries[i]._computeExtent(projection);
            if (geoExtent) {
                result = geoExtent.combine(result);
            }
        }
        return result;
    },

    _computeGeodesicLength:function (projection) {
        if (!projection || this.isEmpty()) {
            return 0;
        }
        var geometries = this.getGeometries();
        var result = 0;
        for (var i = 0, len = geometries.length; i < len; i++) {
            if (!geometries[i]) {
                continue;
            }
            result += geometries[i]._computeGeodesicLength(projection);
        }
        return result;
    },

    _computeGeodesicArea:function (projection) {
        if (!projection || this.isEmpty()) {
            return 0;
        }
        var geometries = this.getGeometries();
        var result = 0;
        for (var i = 0, len = geometries.length; i < len; i++) {
            if (!geometries[i]) {
                continue;
            }
            result += geometries[i]._computeGeodesicArea(projection);
        }
        return result;
    },

    _exportGeoJSONGeometry:function () {
        var geoJSON = [];
        if (!this.isEmpty()) {
            var geometries = this.getGeometries();
            for (var i = 0, len = geometries.length; i < len; i++) {
                if (!geometries[i]) {
                    continue;
                }
                geoJSON.push(geometries[i]._exportGeoJSONGeometry());
            }
        }
        return {
            'type':         'GeometryCollection',
            'geometries':   geoJSON
        };
    },

    _clearProjection:function () {
        if (this.isEmpty()) {
            return;
        }
        var geometries = this.getGeometries();
        for (var i = 0, len = geometries.length; i < len; i++) {
            if (!geometries[i]) {
                continue;
            }
            geometries[i]._clearProjection();
        }

    },

    /**
     * Get connect points if being connected by [ConnectorLine]{@link maptalks.ConnectorLine}
     * @private
     * @return {maptalks.Coordinate[]}
     */
    _getConnectPoints: function () {
        var extent = this.getExtent();
        var anchors = [
            new Z.Coordinate(extent.xmin, extent.ymax),
            new Z.Coordinate(extent.xmax, extent.ymin),
            new Z.Coordinate(extent.xmin, extent.ymin),
            new Z.Coordinate(extent.xmax, extent.ymax)
        ];
        return anchors;
    },

//----------覆盖Geometry中的编辑相关方法-----------------

    startEdit:function (opts) {
        if (this.isEmpty()) {
            return this;
        }
        if (!opts) {
            opts = {};
        }
        if (opts['symbol']) {
            this._originalSymbol = this.getSymbol();
            this.setSymbol(opts['symbol']);
        }
        var geometries = this.getGeometries();
        for (var i = 0, len = geometries.length; i < len; i++) {
            geometries[i].startEdit(opts);
        }
        this._editing = true;
        this.hide();
        var me = this;
        setTimeout(function () {
            me.fire('editstart');
        }, 1);
        return this;
    },

    endEdit:function () {
        if (this.isEmpty()) {
            return this;
        }
        var geometries = this.getGeometries();
        for (var i = 0, len = geometries.length; i < len; i++) {
            geometries[i].endEdit();
        }
        if (this._originalSymbol) {
            this.setSymbol(this._originalSymbol);
            delete this._originalSymbol;
        }
        this._editing = false;
        this.show();
        this.fire('editend');
        return this;
    },

    isEditing:function () {
        if (!this._editing) {
            return false;
        }
        return true;
    }
});
<commit_msg>disable draggable of GeometryCollection before editing it.<commit_after>/**
 * @classdesc
 * Represents a GeometryCollection.
 * @class
 * @category geometry
 * @extends maptalks.Geometry
 * @param {maptalks.Geometry[]} geometries - GeometryCollection's geometries
 */
Z.GeometryCollection = Z.Geometry.extend(/** @lends maptalks.GeometryCollection.prototype */{
    type:Z.Geometry['TYPE_GEOMETRYCOLLECTION'],

    exceptionDefs:{
        'en-US':{
            'INVALID_GEOMETRY':'invalid geometry for collection.'
        },
        'zh-CN':{
            'INVALID_GEOMETRY':'无效的Geometry被加入到collection中.'
        }
    },

    initialize:function (geometries, opts) {
        this._initOptions(opts);
        this.setGeometries(geometries);
    },

    /**
     * Set new geometries to the geometry collection
     * @param {maptalks.Geometry[]} geometries
     * @return {maptalks.GeometryCollection} this
     */
    setGeometries:function (_geometries) {
        var geometries = this._checkGeometries(_geometries);
        //Set the collection as child geometries' parent.
        if (Z.Util.isArray(geometries)) {
            for (var i = geometries.length - 1; i >= 0; i--) {
                geometries[i]._initOptions(this.config());
                geometries[i]._setParent(this);
                geometries[i].setEventParent(this);
                geometries[i].setSymbol(this.getSymbol());
            }
        }
        this._geometries = geometries;
        if (this.getLayer()) {
            this._bindGeometriesToLayer();
            this._onShapeChanged();
        }
        return this;
    },

    /**
     * Get geometries of the geometry collection
     * @return {maptalks.Geometry[]}
     */
    getGeometries:function () {
        if (!this._geometries) {
            return [];
        }
        return this._geometries;
    },

    /**
     * Travels among the geometries the collection has.
     * @param  {Function} fn - a callback function
     * @param  {*} context   - callback's context
     * @return {maptalks.GeometryCollection} this
     */
    forEach: function (fn, context) {
        if (!context) {
            context = this;
        }
        var geometries = this.getGeometries();
        for (var i = 0, len = geometries.length; i < len; i++) {
            if (!geometries[i]) {
                continue;
            }
            fn.call(context, geometries[i], i);
        }
        return this;
    },

    select: function (condition) {
        var evaFn = new Function('geometry', 'with (geometry) { return ' + condition + '; }');
        var selected = [];
        this.forEach(function (geometry) {
            var json = {
                'type' : geometry.getType(),
                'properties' : geometry._exportProperties()
            };
            if (evaFn(json) === true) {
                selected.push(geometry);
            }
        });
        return selected.length > 0 ? new Z.GeometryCollection(selected) : null;
    },

    /**
     * Translate or move the geometry collection by the given offset.
     * @param  {maptalks.Coordinate} offset - translate offset
     * @return {maptalks.GeometryCollection} this
     */
    translate:function (offset) {
        if (!offset) {
            return this;
        }
        if (this.isEmpty()) {
            return this;
        }
        this.forEach(function (geometry) {
            if (geometry && geometry.translate) {
                geometry.translate(offset);
            }
        });
        return this;
    },

    /**
     * Whether the geometry collection is empty
     * @return {Boolean}
     */
    isEmpty:function () {
        return !Z.Util.isArrayHasData(this.getGeometries());
    },

    /**
     * remove itself from the layer if any.
     * @returns {maptalks.Geometry} this
     * @fires maptalks.Geometry#removestart
     * @fires maptalks.Geometry#remove
     */
    remove:function () {
        this.forEach(function (geometry) {
            geometry._rootRemove();
        });
        this._rootRemoveAndFireEvent();
        return this;
    },

    /**
     * Show the geometry collection.
     * @return {maptalks.GeometryCollection} this
     * @fires maptalks.Geometry#show
     */
    show:function () {
        this.options['visible'] = true;
        this.forEach(function (geometry) {
            geometry.show();
        });
        return this;
    },

    /**
     * Hide the geometry collection.
     * @return {maptalks.GeometryCollection} this
     * @fires maptalks.Geometry#hide
     */
    hide:function () {
        this.options['visible'] = false;
        this.forEach(function (geometry) {
            geometry.hide();
        });
        return this;
    },

    setSymbol:function (symbol) {
        if (!symbol) {
            this._symbol = null;
        } else {
            var camelSymbol = this._prepareSymbol(symbol);
            this._symbol = camelSymbol;
        }
        this.forEach(function (geometry) {
            geometry.setSymbol(symbol);
        });
        this._onSymbolChanged();
        return this;
    },

    onConfig:function (config) {
        this.forEach(function (geometry) {
            geometry.config(config);
        });
    },

    /**
     * bind this geometry collection to a layer
     * @param  {maptalks.Layer} layer
     * @private
     */
    _bindLayer:function (layer) {
        this._commonBindLayer(layer);
        this._bindGeometriesToLayer();
    },

    _bindGeometriesToLayer:function () {
        var layer = this.getLayer();
        this.forEach(function (geometry) {
            geometry._bindLayer(layer);
        });
    },

    /**
     * Check whether the type of geometries is valid
     * @param  {maptalks.Geometry[]} geometries - geometries to check
     * @private
     */
    _checkGeometries:function (geometries) {
        if (geometries && !Z.Util.isArray(geometries)) {
            if (geometries instanceof Z.Geometry) {
                return [geometries];
            } else {
                throw new Error(this.exceptions['INVALID_GEOMETRY']);
            }
        } else if (Z.Util.isArray(geometries)) {
            for (var i = 0, len = geometries.length; i < len; i++) {
                if (!(geometries[i] instanceof Z.Geometry)) {
                    throw new Error(this.exceptions['INVALID_GEOMETRY']);
                }
            }
            return geometries;
        }
        return null;
    },

    _updateCache:function () {
        delete this._extent;
        if (this.isEmpty()) {
            return;
        }
        this.forEach(function (geometry) {
            if (geometry && geometry._updateCache) {
                geometry._updateCache();
            }
        });
    },

    _removePainter:function () {
        if (this._painter) {
            this._painter.remove();
        }
        delete this._painter;
        this.forEach(function (geometry) {
            geometry._removePainter();
        });
    },

    _computeCenter:function (projection) {
        if (!projection || this.isEmpty()) {
            return null;
        }
        var sumX = 0, sumY = 0, counter = 0;
        var geometries = this.getGeometries();
        for (var i = 0, len = geometries.length; i < len; i++) {
            if (!geometries[i]) {
                continue;
            }
            var center = geometries[i]._computeCenter(projection);
            if (center) {
                sumX += center.x;
                sumY += center.y;
                counter++;
            }
        }
        if (counter === 0) {
            return null;
        }
        return new Z.Coordinate(sumX / counter, sumY / counter);
    },

    _containsPoint: function (point, t) {
        if (this.isEmpty()) {
            return false;
        }
        var i, len;
        var geometries = this.getGeometries();
        for (i = 0, len = geometries.length; i < len; i++) {
            if (geometries[i]._containsPoint(point, t)) {
                return true;
            }
        }

        return false;
    },

    _computeExtent:function (projection) {
        if (this.isEmpty()) {
            return null;
        }
        var geometries = this.getGeometries();
        var result = null;
        for (var i = 0, len = geometries.length; i < len; i++) {
            if (!geometries[i]) {
                continue;
            }
            var geoExtent = geometries[i]._computeExtent(projection);
            if (geoExtent) {
                result = geoExtent.combine(result);
            }
        }
        return result;
    },

    _computeGeodesicLength:function (projection) {
        if (!projection || this.isEmpty()) {
            return 0;
        }
        var geometries = this.getGeometries();
        var result = 0;
        for (var i = 0, len = geometries.length; i < len; i++) {
            if (!geometries[i]) {
                continue;
            }
            result += geometries[i]._computeGeodesicLength(projection);
        }
        return result;
    },

    _computeGeodesicArea:function (projection) {
        if (!projection || this.isEmpty()) {
            return 0;
        }
        var geometries = this.getGeometries();
        var result = 0;
        for (var i = 0, len = geometries.length; i < len; i++) {
            if (!geometries[i]) {
                continue;
            }
            result += geometries[i]._computeGeodesicArea(projection);
        }
        return result;
    },

    _exportGeoJSONGeometry:function () {
        var geoJSON = [];
        if (!this.isEmpty()) {
            var geometries = this.getGeometries();
            for (var i = 0, len = geometries.length; i < len; i++) {
                if (!geometries[i]) {
                    continue;
                }
                geoJSON.push(geometries[i]._exportGeoJSONGeometry());
            }
        }
        return {
            'type':         'GeometryCollection',
            'geometries':   geoJSON
        };
    },

    _clearProjection:function () {
        if (this.isEmpty()) {
            return;
        }
        var geometries = this.getGeometries();
        for (var i = 0, len = geometries.length; i < len; i++) {
            if (!geometries[i]) {
                continue;
            }
            geometries[i]._clearProjection();
        }

    },

    /**
     * Get connect points if being connected by [ConnectorLine]{@link maptalks.ConnectorLine}
     * @private
     * @return {maptalks.Coordinate[]}
     */
    _getConnectPoints: function () {
        var extent = this.getExtent();
        var anchors = [
            new Z.Coordinate(extent.xmin, extent.ymax),
            new Z.Coordinate(extent.xmax, extent.ymin),
            new Z.Coordinate(extent.xmin, extent.ymin),
            new Z.Coordinate(extent.xmax, extent.ymax)
        ];
        return anchors;
    },

//----------覆盖Geometry中的编辑相关方法-----------------

    startEdit:function (opts) {
        if (this.isEmpty()) {
            return this;
        }
        if (!opts) {
            opts = {};
        }
        if (opts['symbol']) {
            this._originalSymbol = this.getSymbol();
            this.setSymbol(opts['symbol']);
        }
        this._draggbleBeforeEdit = this.options['draggable'];
        this.config('draggable', false);
        var geometries = this.getGeometries();
        for (var i = 0, len = geometries.length; i < len; i++) {
            geometries[i].startEdit(opts);
        }
        this._editing = true;
        this.hide();
        var me = this;
        setTimeout(function () {
            me.fire('editstart');
        }, 1);
        return this;
    },

    endEdit:function () {
        if (this.isEmpty()) {
            return this;
        }
        var geometries = this.getGeometries();
        for (var i = 0, len = geometries.length; i < len; i++) {
            geometries[i].endEdit();
        }
        if (this._originalSymbol) {
            this.setSymbol(this._originalSymbol);
            delete this._originalSymbol;
        }
        this._editing = false;
        this.show();
        this.config('draggable', this._draggbleBeforeEdit);
        this.fire('editend');
        return this;
    },

    isEditing:function () {
        if (!this._editing) {
            return false;
        }
        return true;
    }
});
<|endoftext|>