<commit_before>/**
 * Copyright 2013,2015, 2016 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

module.exports = function (RED) {
  var cfenv = require('cfenv'),
    watson = require('watson-developer-cloud'),
    imageType = require('image-type'),
    url = require('url'),
    temp = require('temp'),
    fileType = require('file-type'),
    fs = require('fs'),
    async = require('async'),
    apikey = null, sAPIKey=null, service=null;

  // temp is being used for file streaming to allow the file to arrive so it can be processed.
  temp.track();

  service = cfenv.getAppEnv().getServiceCreds(/visual recognition/i);

  if (service) {
    sAPIKey = service.apikey;
  }

  RED.httpAdmin.get('/watson-visual-recognition/vcap', function (req, res) {
    res.json(service ? {bound_service: true} : null);
  });

  function imageCheck(data) {
    return data instanceof Buffer && imageType(data) !== null;
  }

  function urlCheck(str) {
    var parsed = url.parse(str);
    return (!!parsed.hostname && !!parsed.protocol && str.indexOf(' ') < 0);
  }

  function stream_buffer(file, contents, cb) {
    fs.writeFile(file, contents, function (err) {
      if (err) {
        throw err;
      }
      cb();
    });
  }

  function verifyPayload(node, msg) {
    if (!msg.payload) {
      this.status({fill:'red', shape:'ring', text:'missing payload'});
      node.error('Missing property: msg.payload', msg);
      return false;
    }
    return true;
  }

  function verifyInputs(feature, node, msg) {
    switch(feature) {
    case 'classifyImage':
    case 'detectFaces':
    case 'recognizeText':
      if (typeof msg.payload === 'boolean' || typeof msg.payload === 'number') {
        this.status({fill:'red', shape:'ring', text:'bad format payload'});
        node.error('Bad format : msg.payload must be a URL string or a Node.js Buffer', msg);
        return false;
      }
    }
    return true;
  }

  function verifyServiceCredentials(node, msg) {
    // If it is present the newly provided user entered key
    // takes precedence over the existing one.
    node.apikey = sAPIKey || node.credentials.apikey;
    if (!node.apikey) {
      node.status({fill:'red', shape:'ring', text:'missing credentials'});
      var message ='Missing Watson Visual Recognition API service credentials';
      node.error(message, msg);
      return false;
    }
    node.service = watson.visual_recognition({
      api_key: node.apikey,
      version: 'v3',
      version_date: '2016-05-19'
    });
    return true;
  }

  function processResponse(err, body, feature, node, msg) {
    if (err != null && body==null) {
      node.status({fill:'red', shape:'ring',
        text:'call to watson visual recognition v3 service failed'});
      msg.result = {};
      if (err.code==null) {
        msg.result['error']=err;
      } else {
        msg.result['error_code']= err.code;
        if (!err.error) {
          msg.result['error']= err.error;
        }
      }
      node.error(err);
      return;
    } else if (err == null && body != null && body.images != null &&
      body.images[0].error) {
      node.status({fill:'red', shape:'ring',
                   text:'call to watson visual recognition v3 service failed'});
      msg.result = {};
      msg.result['error_id']= body.images[0].error.error_id;
      msg.result['error']= body.images[0].error.description;
      msg.payload='see msg.result.error';
      node.send(msg);
    } else {
      if (feature === 'deleteClassifier') {
        msg.result = 'Successfully deleted classifier_id: '+ msg.params.classifier_id ;
      } else {
        msg.result = body;
      }
      msg.payload='see msg.result'; // to remove any Buffer that could remains
      node.send(msg);
      node.status({});
    }
  }

  function prepareParamsCommon(params, node, msg, cb) {
    if (imageCheck(msg.payload)) {
      temp.open({suffix: '.' + fileType(msg.payload).ext}, function (err, info) {
        if (err) {
          this.status({fill:'red', shape:'ring', text:'unable to open image stream'});
          node.error('Node has been unable to open the image stream', msg);
          return cb();
        }
        stream_buffer(info.path, msg.payload, function () {
          params['images_file'] = fs.createReadStream(info.path);
          if (msg.params != null && msg.params.classifier_ids != null) {
            params['classifier_ids']=msg.params['classifier_ids'];
          }
          if (msg.params != null && msg.params.owners != null) {
            params['owners']=msg.params['owners'];
          }
          if (msg.params != null && msg.params.threshold != null) {
            params['threshold']=msg.params['threshold'];
          }
          cb();
          });
        });
    } else if (urlCheck(msg.payload)) {
      params['url'] = msg.payload;
      if (msg.params != null && msg.params.classifier_ids != null) {
        params['classifier_ids']=msg.params['classifier_ids'];
      }
      if (msg.params != null && msg.params.owners != null) {
        params['owners']=msg.params['owners'];
      }
      if (msg.params != null && msg.params.threshold != null) {
        params['threshold']=msg.params['threshold'];
      }
      return cb();
    } else {
      node.status({fill:'red', shape:'ring', text:'payload is invalid'});
      node.error('Payload must be either an image buffer or a string representing a url', msg);
    }
  }

  function addTask (asyncTasks, msg, key, listParams, node) {
    asyncTasks.push(function (callback) {
      var buffer = msg.params[key];
      temp.open({suffix: '.' + fileType(buffer).ext}, function (err, info) {
        if (err) {
          node.status({fill:'red', shape:'ring',
                       text:'unable to open image stream'});
          node.error('Node has been unable to open the image stream', msg);
          return callback('open error on '+key);
        }
        stream_buffer(info.path, msg.params[key], function () {
          listParams[key]=fs.createReadStream(info.path);
          callback(null, key);
        });
      });
    });
  }

  function prepareParamsCreateClassifier (params, node, msg, cb) {
    var listParams = {}, asyncTasks = [] , key=null;
    for (var key in msg.params) {
      if (key.indexOf('_examples')>=0) {
        addTask(asyncTasks, msg, key, listParams, node);
      } else if (key==='name') {
        listParams[key]=msg.params[key];
      }
    } // for
    async.parallel(asyncTasks, function(error, results){
      if (error) {
        //console.log('createClassifier ended with error ' + error);
        throw error;
      }
      for (var p in listParams) {
        params[p]=listParams[p];
      }
      cb();
    });
  }

  function performDeleteAllClassifiers(params, node, msg) {
    node.service.listClassifiers(params, function(err, body) {
      node.status({});
      if (err) {
        node.status({fill:'red', shape:'ring',
          text:'Delete All : call to listClassifiers failed'});
        node.error(err, msg);
      } else {
        // Array to hold async tasks
        var asyncTasks=[], nbTodelete=0, nbdeleted=0;
        nbTodelete = body.classifiers.length;
        body.classifiers.forEach(function (aClassifier) {
          asyncTasks.push(function (cb) {
            var parms = {};
            parms.classifier_id=aClassifier.classifier_id;
            node.service.deleteClassifier(parms, function(err, body) {
              if (err) {
                node.error(err, msg);
                console.log('Error with the removal of classifier_id ' +
                  parms.classifier_id +' : ' + err);
                return cb('error');
              }
              console.log('Classifier ID '+ aClassifier.classifier_id +
                ' deleted successfully.');
              nbdeleted++;
              cb(null,parms.classifier_id);
            });
          });
        });
        async.parallel(asyncTasks, function(error, deletedList){
          if (deletedList.length===nbTodelete) {
            msg.payload='see msg.result.error';
            msg.result = 'All custom classifiers have been deleted.';
          } else {
            msg.payload='see msg.result.error';
            msg.result = 'Some Classifiers could have not been deleted;'+
            'See log for errors.';
          }
          node.send(msg);
          node.status({});
        });
      }
    });
  }  // delete all func

  function executeService(feature, params, node, msg) {
    node.status({fill:'blue', shape:'dot', text:'Calling '+ feature + ' ...'});
    switch(feature) {
    case 'classifyImage':
      prepareParamsCommon(params, node, msg, function () {
        node.service.classify(params, function(err, body, other) {
          processResponse(err,body,feature,node,msg);
        });
      });
      break;
    case 'detectFaces':
      prepareParamsCommon(params, node, msg, function () {
        node.service.detectFaces(params, function(err, body, other) {
          processResponse(err,body,feature,node,msg);
        });
      });
      break;
    case 'recognizeText':
      prepareParamsCommon(params, node, msg, function () {
        node.service.recognizeText(params, function(err, body, other) {
          processResponse(err,body,feature,node,msg);
        });
      });
      break;
    case 'createClassifier':
      prepareParamsCreateClassifier(params, node, msg, function () {
        node.service.createClassifier(params, function(err, body, other) {
          processResponse(err,body,feature,node,msg);
        });
      });
      break;
    case 'retrieveClassifiersList':
      node.service.listClassifiers(params, function(err, body, other) {
        processResponse(err,body,feature,node,msg);
      });
      break;
    case 'retrieveClassifierDetails':
      params['classifier_id']=msg.params['classifier_id'];
      node.service.getClassifier(params, function(err, body, other) {
          processResponse(err,body,feature,node,msg);
      });
      break;
    case 'deleteClassifier':
      params['classifier_id']=msg.params['classifier_id'];
      node.service.deleteClassifier(params, function(err, body, other) {
          processResponse(err,body,feature,node,msg);
      });
      break;
    case 'deleteAllClassifiers':
      performDeleteAllClassifiers(params,node, msg);
      break;
    }
  }

  // This is the Watson Visual Recognition V3 Node
  function WatsonVisualRecognitionV3Node (config) {
    var node = this, b=false, feature = config['image-feature'];
    RED.nodes.createNode(this, config);

    node.on('input', function (msg) {
      var params = {};
      node.status({});
      // so there is at most 1 temp file at a time (did not found a better solution...)
      temp.cleanup();

      b=verifyPayload(node, msg);
      if (!b) {
        return;
      }
      b=verifyInputs(node, msg);
      if (!b) {
        return;
      }
      b=verifyServiceCredentials(node, msg);
      if (!b) {
        return;
      }
      executeService(feature,params,node,msg);
    });
  }

  RED.nodes.registerType('visual-recognition-v3', WatsonVisualRecognitionV3Node, {
    credentials: {
      apikey: {type:'password'}
    }
  });

  RED.nodes.registerType('visual-recognition-util-v3', WatsonVisualRecognitionV3Node, {
    credentials: {
      apikey: {type:'password'}
    }
  });

};
<commit_msg>Codacy fix Complexity 9<commit_after>/**
 * Copyright 2013,2015, 2016 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

module.exports = function (RED) {
  var cfenv = require('cfenv'),
    watson = require('watson-developer-cloud'),
    imageType = require('image-type'),
    url = require('url'),
    temp = require('temp'),
    fileType = require('file-type'),
    fs = require('fs'),
    async = require('async'),
    apikey = null, sAPIKey=null, service=null;

  // temp is being used for file streaming to allow the file to arrive so it can be processed.
  temp.track();

  service = cfenv.getAppEnv().getServiceCreds(/visual recognition/i);

  if (service) {
    sAPIKey = service.apikey;
  }

  RED.httpAdmin.get('/watson-visual-recognition/vcap', function (req, res) {
    res.json(service ? {bound_service: true} : null);
  });

  function imageCheck(data) {
    return data instanceof Buffer && imageType(data) !== null;
  }

  function urlCheck(str) {
    var parsed = url.parse(str);
    return (!!parsed.hostname && !!parsed.protocol && str.indexOf(' ') < 0);
  }

  function stream_buffer(file, contents, cb) {
    fs.writeFile(file, contents, function (err) {
      if (err) {
        throw err;
      }
      cb();
    });
  }

  function verifyPayload(node, msg) {
    if (!msg.payload) {
      this.status({fill:'red', shape:'ring', text:'missing payload'});
      node.error('Missing property: msg.payload', msg);
      return false;
    }
    return true;
  }

  function verifyInputs(feature, node, msg) {
    switch(feature) {
    case 'classifyImage':
    case 'detectFaces':
    case 'recognizeText':
      if (typeof msg.payload === 'boolean' || typeof msg.payload === 'number') {
        this.status({fill:'red', shape:'ring', text:'bad format payload'});
        node.error('Bad format : msg.payload must be a URL string or a Node.js Buffer', msg);
        return false;
      }
    }
    return true;
  }

  function verifyServiceCredentials(node, msg) {
    // If it is present the newly provided user entered key
    // takes precedence over the existing one.
    node.apikey = sAPIKey || node.credentials.apikey;
    if (!node.apikey) {
      node.status({fill:'red', shape:'ring', text:'missing credentials'});
      var message ='Missing Watson Visual Recognition API service credentials';
      node.error(message, msg);
      return false;
    }
    node.service = watson.visual_recognition({
      api_key: node.apikey,
      version: 'v3',
      version_date: '2016-05-19'
    });
    return true;
  }

  function processResponse(err, body, feature, node, msg) {
    if (err != null && body==null) {
      node.status({fill:'red', shape:'ring',
        text:'call to watson visual recognition v3 service failed'});
      msg.result = {};
      if (err.code==null) {
        msg.result['error']=err;
      } else {
        msg.result['error_code']= err.code;
        if (!err.error) {
          msg.result['error']= err.error;
        }
      }
      node.error(err);
      return;
    } else if (err == null && body != null && body.images != null &&
      body.images[0].error) {
      node.status({fill:'red', shape:'ring',
                   text:'call to watson visual recognition v3 service failed'});
      msg.result = {};
      msg.result['error_id']= body.images[0].error.error_id;
      msg.result['error']= body.images[0].error.description;
      msg.payload='see msg.result.error';
      node.send(msg);
    } else {
      if (feature === 'deleteClassifier') {
        msg.result = 'Successfully deleted classifier_id: '+ msg.params.classifier_id ;
      } else {
        msg.result = body;
      }
      msg.payload='see msg.result'; // to remove any Buffer that could remains
      node.send(msg);
      node.status({});
    }
  }

  function prepareParamsCommon(params, node, msg, cb) {
    if (imageCheck(msg.payload)) {
      temp.open({suffix: '.' + fileType(msg.payload).ext}, function (err, info) {
        if (err) {
          this.status({fill:'red', shape:'ring', text:'unable to open image stream'});
          node.error('Node has been unable to open the image stream', msg);
          return cb();
        }
        stream_buffer(info.path, msg.payload, function () {
          params['images_file'] = fs.createReadStream(info.path);
          if (msg.params != null && msg.params.classifier_ids != null) {
            params['classifier_ids']=msg.params['classifier_ids'];
          }
          if (msg.params != null && msg.params.owners != null) {
            params['owners']=msg.params['owners'];
          }
          if (msg.params != null && msg.params.threshold != null) {
            params['threshold']=msg.params['threshold'];
          }
          cb();
          });
        });
    } else if (urlCheck(msg.payload)) {
      params['url'] = msg.payload;
      if (msg.params != null && msg.params.classifier_ids != null) {
        params['classifier_ids']=msg.params['classifier_ids'];
      }
      if (msg.params != null && msg.params.owners != null) {
        params['owners']=msg.params['owners'];
      }
      if (msg.params != null && msg.params.threshold != null) {
        params['threshold']=msg.params['threshold'];
      }
      return cb();
    } else {
      node.status({fill:'red', shape:'ring', text:'payload is invalid'});
      node.error('Payload must be either an image buffer or a string representing a url', msg);
    }
  }

  function addTask (asyncTasks, msg, key, listParams, node) {
    asyncTasks.push(function (callback) {
      var buffer = msg.params[key];
      temp.open({suffix: '.' + fileType(buffer).ext}, function (err, info) {
        if (err) {
          node.status({fill:'red', shape:'ring',
                       text:'unable to open image stream'});
          node.error('Node has been unable to open the image stream', msg);
          return callback('open error on '+key);
        }
        stream_buffer(info.path, msg.params[key], function () {
          listParams[key]=fs.createReadStream(info.path);
          callback(null, key);
        });
      });
    });
  }

  function prepareParamsCreateClassifier (params, node, msg, cb) {
    var listParams = {}, asyncTasks = [] , key=null;
    for (key in msg.params) {
      if (key.indexOf('_examples')>=0) {
        addTask(asyncTasks, msg, key, listParams, node);
      } else if (key==='name') {
        listParams[key]=msg.params[key];
      }
    } // for
    async.parallel(asyncTasks, function(error, results){
      if (error) {
        //console.log('createClassifier ended with error ' + error);
        throw error;
      }
      for (var p in listParams) {
        params[p]=listParams[p];
      }
      cb();
    });
  }

  function performDeleteAllClassifiers(params, node, msg) {
    node.service.listClassifiers(params, function(err, body) {
      node.status({});
      if (err) {
        node.status({fill:'red', shape:'ring',
          text:'Delete All : call to listClassifiers failed'});
        node.error(err, msg);
      } else {
        // Array to hold async tasks
        var asyncTasks=[], nbTodelete=0, nbdeleted=0;
        nbTodelete = body.classifiers.length;
        body.classifiers.forEach(function (aClassifier) {
          asyncTasks.push(function (cb) {
            var parms = {};
            parms.classifier_id=aClassifier.classifier_id;
            node.service.deleteClassifier(parms, function(err, body) {
              if (err) {
                node.error(err, msg);
                console.log('Error with the removal of classifier_id ' +
                  parms.classifier_id +' : ' + err);
                return cb('error');
              }
              console.log('Classifier ID '+ aClassifier.classifier_id +
                ' deleted successfully.');
              nbdeleted++;
              cb(null,parms.classifier_id);
            });
          });
        });
        async.parallel(asyncTasks, function(error, deletedList){
          if (deletedList.length===nbTodelete) {
            msg.payload='see msg.result.error';
            msg.result = 'All custom classifiers have been deleted.';
          } else {
            msg.payload='see msg.result.error';
            msg.result = 'Some Classifiers could have not been deleted;'+
            'See log for errors.';
          }
          node.send(msg);
          node.status({});
        });
      }
    });
  }  // delete all func

function executeService(feature, params, node, msg)
{
  switch(feature) {
  case 'classifyImage':
    prepareParamsCommon(params, node, msg, function () {
      node.service.classify(params, function(err, body, other) {
        processResponse(err,body,feature,node,msg);
      });
    });
    break;
  case 'detectFaces':
    prepareParamsCommon(params, node, msg, function () {
      node.service.detectFaces(params, function(err, body, other) {
        processResponse(err,body,feature,node,msg);
      });
    });
    break;
  case 'recognizeText':
    prepareParamsCommon(params, node, msg, function () {
      node.service.recognizeText(params, function(err, body, other) {
        processResponse(err,body,feature,node,msg);
      });
    });
    break;
  }
}

function executeUtilService(feature, params, node, msg) {
  switch(feature) {
    case 'createClassifier':
      prepareParamsCreateClassifier(params, node, msg, function () {
        node.service.createClassifier(params, function(err, body, other) {
          processResponse(err,body,feature,node,msg);
        });
      });
      break;
    case 'retrieveClassifiersList':
      node.service.listClassifiers(params, function(err, body, other) {
        processResponse(err,body,feature,node,msg);
      });
      break;
    case 'retrieveClassifierDetails':
      params['classifier_id']=msg.params['classifier_id'];
      node.service.getClassifier(params, function(err, body, other) {
          processResponse(err,body,feature,node,msg);
      });
      break;
    case 'deleteClassifier':
      params['classifier_id']=msg.params['classifier_id'];
      node.service.deleteClassifier(params, function(err, body, other) {
          processResponse(err,body,feature,node,msg);
      });
      break;
    case 'deleteAllClassifiers':
      performDeleteAllClassifiers(params,node, msg);
      break;
    }
}

  function execute(feature, params, node, msg) {
    node.status({fill:'blue', shape:'dot', text:'Calling '+ feature + ' ...'});
    if (feature==='classifyImage'||feature==='detectFaces'||feature==='recognizeText') {
      executeService(feature, params, node, msg);
    } else {
      executeUtilService(feature, params, node, msg);
    }
  }

  // This is the Watson Visual Recognition V3 Node
  function WatsonVisualRecognitionV3Node (config) {
    var node = this, b=false, feature = config['image-feature'];
    RED.nodes.createNode(this, config);

    node.on('input', function (msg) {
      var params = {};
      node.status({});
      // so there is at most 1 temp file at a time (did not found a better solution...)
      temp.cleanup();

      b=verifyPayload(node, msg);
      if (!b) {
        return;
      }
      b=verifyInputs(node, msg);
      if (!b) {
        return;
      }
      b=verifyServiceCredentials(node, msg);
      if (!b) {
        return;
      }
      execute(feature,params,node,msg);
    });
  }

  RED.nodes.registerType('visual-recognition-v3', WatsonVisualRecognitionV3Node, {
    credentials: {
      apikey: {type:'password'}
    }
  });

  RED.nodes.registerType('visual-recognition-util-v3', WatsonVisualRecognitionV3Node, {
    credentials: {
      apikey: {type:'password'}
    }
  });

};
<|endoftext|>


<commit_before>module.exports = {
  /* get the reminders due today with req.session.username and
  'new Date().toISOString().slice(0,10)' and return it in JSON.*/
  get: function(req, res) {
    res.type('text/json');
    db.collection("reminders").find({
      name: req.session.username/*,
      dueDate: {$gte: new Date(req.param('today'))},
      startReminding: {$lt: new Date(req.param('today'))}*/
    }).toArray(function(err, reminders) {
      if (!err) // gotta get the contents of the reminders, since they're not static.
        res.send(reminders);
      else
        res.send(500, err);
    });
  },
  /* add 1 or a batch or reminders in the valid JSON format to the db with req.session.username and req.body.reminders.
     if action=add, then add them. if action=remove, then remove them.*/
  post: function(req, res) {
    res.type('text/json');
    // remove existing reminders for this box so that there's no dublicates.
    db.collection("reminders").removeMany({
      $and: [{name: req.session.username}, {box: req.body.box}, {monday: req.body.monday}]
    }, function(err, result) {
      if (!err) {
        if (req.body.options) { // if there aren't options the client just wants to delete reminders
          var m = new Date(req.body.monday);

          var dueDate = new Date(m.getFullYear(),
            m.getMonth(),
            m.getDate() + parseInt(req.body.box.split('').reverse()[0]));

          dueDate.setHours(23, 59, 59, 999); // Until the end of the day

          var startReminders = new Date(dueDate.getFullYear(),
            dueDate.getMonth(),
            dueDate.getDate() - (parseInt(req.body.options.startReminding)+1));

          startReminders.setHours(0, 0, 0, 0); // At the beginning of the day
          var reminders = {
            startRemindingNum: req.body.options.startReminding,
            startReminding: startReminders,
            dueDate: dueDate,

            monday: req.body.monday,
            box: req.body.box,
            description: req.body.description,
            colorCode: req.body.colorCode,

            name: req.session.username
          };
          db.collection("reminders").insert(reminders, function(err, result) {
            if (!err)
              res.send(200);
            else
              res.send(500, err);
          });
        } else {
          res.send(200);
        }
      } else {
        res.end(500, err);
      }
    });
  }
};<commit_msg>duedeate bug<commit_after>module.exports = {
  /* get the reminders due today with req.session.username and
  'new Date().toISOString().slice(0,10)' and return it in JSON.*/
  get: function(req, res) {
    res.type('text/json');
    db.collection("reminders").find({
      name: req.session.username/*,
      dueDate: {$gte: new Date(req.param('today'))},
      startReminding: {$lt: new Date(req.param('today'))}*/
    }).toArray(function(err, reminders) {
      if (!err) // gotta get the contents of the reminders, since they're not static.
        res.send(reminders);
      else
        res.send(500, err);
    });
  },
  /* add 1 or a batch or reminders in the valid JSON format to the db with req.session.username and req.body.reminders.
     if action=add, then add them. if action=remove, then remove them.*/
  post: function(req, res) {
    res.type('text/json');
    // remove existing reminders for this box so that there's no dublicates.
    db.collection("reminders").removeMany({
      $and: [{name: req.session.username}, {box: req.body.box}, {monday: req.body.monday}]
    }, function(err, result) {
      if (!err) {
        if (req.body.options) { // if there aren't options the client just wants to delete reminders
          var m = new Date(req.body.monday);

          var dueDate = new Date(m.getFullYear(),
            m.getMonth(),
            m.getDate() + parseInt(req.body.box.split('').reverse()[0]));

          dueDate.setHours(23, 59, 59, 0); // Until the end of the day

          var startReminders = new Date(dueDate.getFullYear(),
            dueDate.getMonth(),
            dueDate.getDate() - (parseInt(req.body.options.startReminding)+1));

          startReminders.setHours(0, 0, 0, 0); // At the beginning of the day
          var reminders = {
            startRemindingNum: req.body.options.startReminding,
            startReminding: startReminders,
            dueDate: dueDate,

            monday: req.body.monday,
            box: req.body.box,
            description: req.body.description,
            colorCode: req.body.colorCode,

            name: req.session.username
          };
          db.collection("reminders").insert(reminders, function(err, result) {
            if (!err)
              res.send(200);
            else
              res.send(500, err);
          });
        } else {
          res.send(200);
        }
      } else {
        res.end(500, err);
      }
    });
  }
};<|endoftext|>


<commit_before>const config = require('./userconfig/config.json'); // Import configuration
const moment = require('moment'); // Part of log writing

module.exports = { // Export event functions
	"ready": function ready(selfbot) { // Once the selfbot is ready (fully booted) ...
		console.log(`[${moment().format('DD/MM/YYYY HH:mm:ss')}] Motiful ready!`); // ...console log a ready message.
	},
	"error": function error(selfbot) { // If a "serious connection error" occurs...
		console.log(`[${moment().format('DD/MM/YYYY HH:mm:ss')}] Motiful encountered a "serious connection error"!`); // ...console log a notifcation.
	}
};<commit_msg>Fix status when actual user is offline<commit_after>const config = require('./userconfig/config.json'); // Import configuration
const moment = require('moment'); // Part of log writing

module.exports = { // Export event functions
	"ready": function ready(selfbot) { // Once the selfbot is ready (fully booted) ...
		console.log(`[${moment().format('DD/MM/YYYY HH:mm:ss')}] Motiful ready!`); // ...console log a ready message.
		selfbot.user.setStatus('invisible');
		/*
		Set motiful's status to invisible, so you won't appear as online if you actually aren't but have motiful running.
		If you ARE online, the online/idle/dnd status of your discord client will overweigh motiful's invisible status, meaning
		that this won't make you permanently display as invisible.
		*/
	},
	"error": function error(selfbot) { // If a "serious connection error" occurs...
		console.log(`[${moment().format('DD/MM/YYYY HH:mm:ss')}] Motiful encountered a "serious connection error"!`); // ...console log a notifcation.
	}
};<|endoftext|>


<commit_before>const express = require('express');
const bcrypt = require('bcrypt');
const mongoose = require('mongoose');
const auth = require('../lib/auth.js');
const router = express.Router();

const User = mongoose.models.User;

module.exports = router;

router.get('/', function (req, res, next) {
    if (req.user) {
        console.log("User already logged in:" + req.user.username);
        res.redirect('/profile');
    } else
        res.render('signup');
});

router.post('/', async function (req, res, next) {
    //const uv = new mongoose.model('UserVerify');
    //const username = req.body.email;
    console.log(req);

    try {
        const s = await bcrypt.genSalt(1);
        const h = await bcrypt.hash(req.body.password, s);
        const user = await User.create(
            {
                username: req.body.email,
                passwordHash: h,
                salt: s,
                fullName: req.body.email,
                email: req.body.email
            });
        console.log("User created: " + user.username + "===" + user.id);
        res.redirect('/profile');
    } catch (err) {
        res.render('error', {message:"Nepodarilo sa vytvoriť účet", error:err});
    }
    /*
    u = await uv.addNew(dbConnection, username, req.user.username, req.user.password, function(err, user){
        if (err) {
            console.log("Error creating signup record for "+username);
            return;
        }
        console.log("Signup created for "+username);
    });
    */

});
<commit_msg>check user existence while signup<commit_after>const express = require('express');
const bcrypt = require('bcrypt');
const mongoose = require('mongoose');
const auth = require('../lib/auth.js');
const router = express.Router();

const User = mongoose.models.User;

module.exports = router;

router.get('/', function (req, res, next) {
    if (req.user) {
        console.log("User already logged in:" + req.user.username);
        res.redirect('/profile');
    } else
        res.render('signup');
});

router.post('/', async function (req, res, next) {
    //const uv = new mongoose.model('UserVerify');
    //const username = req.body.email;

    try {
        const s = await bcrypt.genSalt(1);
        const h = await bcrypt.hash(req.body.password, s);
        const u = await User.findOneActive({email:req.body.email});

        if (u) return res.render('error',{message:"Užívateľ už existuje", error:{}});

        const user = await User.create(
            {
                username: req.body.email,
                passwordHash: h,
                salt: s,
                fullName: req.body.email,
                email: req.body.email
            });
        console.log("User created: " + user.username + "===" + user.id);
        res.redirect('/profile');
    } catch (err) {
        res.render('error', {message:"Nepodarilo sa vytvoriť účet", error:err});
    }
    /*
    u = await uv.addNew(dbConnection, username, req.user.username, req.user.password, function(err, user){
        if (err) {
            console.log("Error creating signup record for "+username);
            return;
        }
        console.log("Signup created for "+username);
    });
    */

});
<|endoftext|>


<commit_before>const _ = require('lodash');
const moment = require('moment');
const Promise = require('bluebird');
const debug = require('debug')('routes:semantics');
const nconf = require('nconf');

const mongo = require('../lib/mongo');
const params = require('../lib/params');

const supported = [ "it", "pl", "en", "fr", "es", "pt", "ru", "he", "nl", "de", "et", "hr",
                    "ro", "uk", "fa", "fi", "hu", "no", "da", "ja", "lt", "id", "sv", "cs",
                    "lv", "ar", "af", "ko", "sk", "el", "th", "tr", "bn", "bg", "sl", "hi", "tl" ];

const LanguageError = {
    error: true,
    message: 'missing language',
    supported,
    reminder: 'the list of supported language comes from a mongodb.distinct call, should be updated'
};
function validLanguage(propl) {
    return (_.size(propl) == 2 && supported.indexOf(propl) !== -1);
}

function labels(req) {
    const { amount, skip } = params.optionParsing(req.params.paging, 100);
    debug("labels request (lang: %s), amount %d skip %d",
        req.params.lang, amount, skip);

    if(!validLanguage(req.params.lang))
        return { json: LanguageError };

    return mongo
        .readLimit(nconf.get('schema').labels, { lang: req.params.lang }, { when: -1 }, amount, skip)
        .then(function(data) {
            debug("retrived %d objects, with amount %d skip %d", _.size(data), amount, skip);
            return { json: data };
        })
        .catch(function(e) {
            debug("data (error): %s", e);
            return { 'text': `error: ${e}` };
        });
};

function semantics(req) {
    const { amount, skip } = params.optionParsing(req.params.paging, 100);
    debug("semantic request (lang: %s), amount %d skip %d",
        req.params.lang, amount, skip);

    if(!validLanguage(req.params.lang))
        return { json: LanguageError };

    return mongo
        .readLimit(nconf.get('schema').semantics, { lang: req.params.lang }, { when: -1 }, amount, skip)
        .then(function(data) {
            debug("retrived %d objects, with amount %d skip %d", _.size(data), amount, skip);
            return { json: data };
        })
        .catch(function(e) {
            debug("data (error): %s", e);
            return { 'text': `error: ${e}` };
        });
};

function redactEnriched(enrich) {
    _.unset(enrich, '_id');
    let s = _.first(enrich.summary);
    _.unset(s, '_id');
    _.unset(s, 'id');
    _.unset(s, 'user');
    _.unset(s, 'timeline');
    _.unset(s, 'impressionOrder');
    _.unset(s, 'impressionTime');
    enrich.summary = s;
    // XXX maybe can be redacted the condition of the ❌ below
    return enrich;
}

function enrich(req) {
    const DEFAULTAMOUNT = 13;
    const backintime = moment().subtract(2, 'd').toISOString();
    const { amount, skip } = params.optionParsing(req.params.paging, DEFAULTAMOUNT);
    debug("enrich request (lang: %s), amount %d skip %d",
        req.params.lang, amount, skip);

    if(!validLanguage(req.params.lang))
        return { json: LanguageError };

    return mongo
        .aggregate(nconf.get('schema').labels, [
            { $sort: { when: -1 }},
            { $match: { lang: req.params.lang, when: { "$lt": new Date(backintime) }} },
            { $skip: skip },
            { $limit: amount },
            { $lookup: { from: 'summary', localField: 'semanticId', foreignField: 'semanticId', as: 'summary' }}
        ])
        .map(redactEnriched)
        .then(function(enriched) {
            debug("return enrich, %d objects (%j)", _.size(enriched), _.map(enriched, function(e) {
                if(!e.summary || !e.summary.source || !e.summary.nature)
                    return "❌";
                return [ e.summary.source, e.summary.nature ];
            }));
            return { json: enriched };
        });
};

function noogle(req) {
    const DEFAULTAMOUNT = 13;
    const { amount, skip } = params.optionParsing(req.params.paging, DEFAULTAMOUNT);
    debug("noogle request (lang: %s, label: %s), amount %d skip %d",
        req.params.lang, req.params.label, amount, skip);

    if(!validLanguage(req.params.lang))
        return { json: LanguageError };

    return mongo
        .aggregate(nconf.get('schema').semantics, [
            { $sort: { when: -1 }},
            { $match: { lang: req.params.lang, label: req.params.label }},
            { $group: { _id: "$semanticId" }},
            { $skip: skip },
            { $limit: amount },
            { $lookup: { from: 'summary', localField: '_id', foreignField: 'semanticId', as: 'summary' }},
            { $lookup: { from: 'labels', localField: '_id', foreignField: 'semanticId', as: 'labels' }}
        ])
        .map(function(dirty) {
            let base = _.first(dirty.labels);
            base.summary = dirty.summary;
            base.when = moment(base.when);
            return base;
        })
        .map(redactEnriched)
        .then(function(results) {
            debug("return noogle, %d objects (%j)", _.size(results), _.map(results, function(e) {
                if(!e.summary || !e.summary.source || !e.summary.nature)
                    return "❌";
                return [ e.summary.source, e.summary.nature ];
            }));
            const ordered = _.orderBy(results, {when: -1 });
            return { json: results };
        });
};

function loud(req) {
    const MAXENTRIES = 2000;
    const DEFAULTAMOUNT = 13;
    const backintime = moment().subtract(2, 'd').toISOString();
    const { amount, skip } = params.optionParsing(req.params.paging, DEFAULTAMOUNT);
    debug("loud request (lang: %s), amount %d skip %d",
        req.params.lang, amount, skip);

    if(!validLanguage(req.params.lang))
        return { json: LanguageError };

    return loudKeywordsPipeline(MAXENTRIES, backintime, amount, skip, req.params.lang)
        .then(function(loudness) {
            debug("return loudness: %j", _.map(loudness, 'label'));
            return { json: loudness };
        });

};

function loudKeywordsPipeline(maxentries, backintime, amount, skip, lang) {
    return mongo
        .aggregate(nconf.get('schema').semantics, [
            { $match: { lang: lang, when: { "$gt": new Date(backintime) }} },
            { $limit: maxentries },
            { $group: { _id: '$title', wp: { $first: '$wp'}, count: { $sum: 1 }}},
            { $sort: { "count": -1 }},
            { $skip: skip },
            { $limit: amount },
            { $project: { "label": "$_id", _id: false, wp: true, count: true }}
        ]);
}

const cache = _.reduce(supported, function(memo, l) {
    _.set(memo, l, {
        content: null,
        computedAt: null,
        next: null,
    });
    return memo;
}, {} );

function formatReturn(lang, updated) {
    if(updated) {
        cache[lang].content = updated.content;
        cache[lang].computedAt = updated.computedAt;
        cache[lang].next = updated.next
    }
    return {
        json: {
            content: cache[lang].content,
            computedAt: cache[lang].computedAt.toISOString(),
            next: cache[lang].next.toISOString(),
        }
    };
};

function langinfo(req) {
    /* this API returns an complete information on a language population, with number of
     * active contributors in the last 48 hours and total keyword seen in the last 48 hours,
     * this API do not support paging and is meant to be cached */
    const MAXENTRIES = 60000;
    const DEFAULTAMOUNT = 10;
    const hoursNumber = 48;
    const backintime = moment().subtract(hoursNumber, 'h').toISOString();
    const amount = 13;
    const skip = 0;
    const lang = req.params.lang;
    const cacheMinutes = 60 * 12;

    if(!validLanguage(lang))
        return { json: LanguageError };

    if(cache[lang].next && moment().isBefore(cache[lang].next) && cache[lang].content) {
        debug("langInfo %s, using cached version", lang);
        return formatReturn(lang);
    }

    debug("langInfo %s, retrieving from DB", lang);
    return Promise.all([
        loudKeywordsPipeline(MAXENTRIES, backintime, amount, skip, lang),
        mongo.aggregate(nconf.get('schema').semantics, [
            { $sort: { when: -1 }},
            { $match: { lang: req.params.lang, when: { "$gt": new Date(backintime) } }},
            { $limit: MAXENTRIES },
            { $group: { _id: "$label" }},
            { $group: { _id: null, amount: { "$sum": 1 } }},
        ]).then(function(o) { return (o && o[0] && o[0].amount) ? o[0].amount : 0 }),
        mongo.aggregate(nconf.get('schema').labels, [
            { $sort: { when: -1 }},
            { $match: { lang: lang, when: { "$gt": new Date(backintime) } }},
            { $limit: MAXENTRIES },
            { $lookup: { from: 'summary', localField: 'semanticId', foreignField: 'semanticId', as: 'summary' }},
            { $group: { _id: "dummy", profiles: { $addToSet: "$summary.user"} }}
        ]).then(function(usermess) {
            // remind/TODO grouped by size and anonymized, this can be a nice stats
            // _.flatten(usermess[0].profiles)
            if(!(usermess && usermess[0] && usermess[0].profiles))
                return 0;
            return _.size(_.uniq(_.flatten(usermess[0].profiles)))
        })
    ])
    .then(function(results) {
        let retval = {
            consideredHoursWindow: hoursNumber,
            language: req.params.lang,
            most: _.map(results[0], 'label'),
            labelsCount: results[1],
            contributors: results[2],
        };
        return formatReturn(lang, {
            content: retval,
            computedAt: moment(),
            next: moment().add(cacheMinutes, 'minutes')
        });
    });
}

module.exports = {
    labels,
    semantics,
    enrich,
    loud,
    noogle,
    langinfo
};
<commit_msg>updated languages present<commit_after>const _ = require('lodash');
const moment = require('moment');
const Promise = require('bluebird');
const debug = require('debug')('routes:semantics');
const nconf = require('nconf');

const mongo = require('../lib/mongo');
const params = require('../lib/params');

const supported = [ "en", "de", "fr", "pl", "pt", "it", "fa", "sv", "es", "ja", "uk", "cs",
                    "sk", "bg", "nl", "ru", "ko", "hr", "el", "et", "ar", "no", "da", "he",
                    "id", "ro", "hu", "bn", "lt", "ta", "fi", "tl", "ur", "tr", "mk", "th",
                    "ml", "sl", "af", "lv", "vi", "hi" ];

const LanguageError = {
    error: true,
    message: 'missing language',
    supported,
    reminder: 'the list of supported language comes from a mongodb.distinct call, should be updated'
};
function validLanguage(propl) {
    return (_.size(propl) == 2 && supported.indexOf(propl) !== -1);
}

function labels(req) {
    const { amount, skip } = params.optionParsing(req.params.paging, 100);
    debug("labels request (lang: %s), amount %d skip %d",
        req.params.lang, amount, skip);

    if(!validLanguage(req.params.lang))
        return { json: LanguageError };

    return mongo
        .readLimit(nconf.get('schema').labels, { lang: req.params.lang }, { when: -1 }, amount, skip)
        .then(function(data) {
            debug("retrived %d objects, with amount %d skip %d", _.size(data), amount, skip);
            return { json: data };
        })
        .catch(function(e) {
            debug("data (error): %s", e);
            return { 'text': `error: ${e}` };
        });
};

function semantics(req) {
    const { amount, skip } = params.optionParsing(req.params.paging, 100);
    debug("semantic request (lang: %s), amount %d skip %d",
        req.params.lang, amount, skip);

    if(!validLanguage(req.params.lang))
        return { json: LanguageError };

    return mongo
        .readLimit(nconf.get('schema').semantics, { lang: req.params.lang }, { when: -1 }, amount, skip)
        .then(function(data) {
            debug("retrived %d objects, with amount %d skip %d", _.size(data), amount, skip);
            return { json: data };
        })
        .catch(function(e) {
            debug("data (error): %s", e);
            return { 'text': `error: ${e}` };
        });
};

function redactEnriched(enrich) {
    _.unset(enrich, '_id');
    let s = _.first(enrich.summary);
    _.unset(s, '_id');
    _.unset(s, 'id');
    _.unset(s, 'user');
    _.unset(s, 'timeline');
    _.unset(s, 'impressionOrder');
    _.unset(s, 'impressionTime');
    enrich.summary = s;
    // XXX maybe can be redacted the condition of the ❌ below
    return enrich;
}

function enrich(req) {
    const DEFAULTAMOUNT = 13;
    const backintime = moment().subtract(2, 'd').toISOString();
    const { amount, skip } = params.optionParsing(req.params.paging, DEFAULTAMOUNT);
    debug("enrich request (lang: %s), amount %d skip %d",
        req.params.lang, amount, skip);

    if(!validLanguage(req.params.lang))
        return { json: LanguageError };

    return mongo
        .aggregate(nconf.get('schema').labels, [
            { $sort: { when: -1 }},
            { $match: { lang: req.params.lang, when: { "$lt": new Date(backintime) }} },
            { $skip: skip },
            { $limit: amount },
            { $lookup: { from: 'summary', localField: 'semanticId', foreignField: 'semanticId', as: 'summary' }}
        ])
        .map(redactEnriched)
        .then(function(enriched) {
            debug("return enrich, %d objects (%j)", _.size(enriched), _.map(enriched, function(e) {
                if(!e.summary || !e.summary.source || !e.summary.nature)
                    return "❌";
                return [ e.summary.source, e.summary.nature ];
            }));
            return { json: enriched };
        });
};

function noogle(req) {
    const DEFAULTAMOUNT = 13;
    const { amount, skip } = params.optionParsing(req.params.paging, DEFAULTAMOUNT);
    debug("noogle request (lang: %s, label: %s), amount %d skip %d",
        req.params.lang, req.params.label, amount, skip);

    if(!validLanguage(req.params.lang))
        return { json: LanguageError };

    return mongo
        .aggregate(nconf.get('schema').semantics, [
            { $sort: { when: -1 }},
            { $match: { lang: req.params.lang, label: req.params.label }},
            { $group: { _id: "$semanticId" }},
            { $skip: skip },
            { $limit: amount },
            { $lookup: { from: 'summary', localField: '_id', foreignField: 'semanticId', as: 'summary' }},
            { $lookup: { from: 'labels', localField: '_id', foreignField: 'semanticId', as: 'labels' }}
        ])
        .map(function(dirty) {
            let base = _.first(dirty.labels);
            base.summary = dirty.summary;
            base.when = moment(base.when);
            return base;
        })
        .map(redactEnriched)
        .then(function(results) {
            debug("return noogle, %d objects (%j)", _.size(results), _.map(results, function(e) {
                if(!e.summary || !e.summary.source || !e.summary.nature)
                    return "❌";
                return [ e.summary.source, e.summary.nature ];
            }));
            const ordered = _.orderBy(results, {when: -1 });
            return { json: results };
        });
};

function loud(req) {
    const MAXENTRIES = 2000;
    const DEFAULTAMOUNT = 13;
    const backintime = moment().subtract(2, 'd').toISOString();
    const { amount, skip } = params.optionParsing(req.params.paging, DEFAULTAMOUNT);
    debug("loud request (lang: %s), amount %d skip %d",
        req.params.lang, amount, skip);

    if(!validLanguage(req.params.lang))
        return { json: LanguageError };

    return loudKeywordsPipeline(MAXENTRIES, backintime, amount, skip, req.params.lang)
        .then(function(loudness) {
            debug("return loudness: %j", _.map(loudness, 'label'));
            return { json: loudness };
        });

};

function loudKeywordsPipeline(maxentries, backintime, amount, skip, lang) {
    return mongo
        .aggregate(nconf.get('schema').semantics, [
            { $match: { lang: lang, when: { "$gt": new Date(backintime) }} },
            { $limit: maxentries },
            { $group: { _id: '$title', wp: { $first: '$wp'}, count: { $sum: 1 }}},
            { $sort: { "count": -1 }},
            { $skip: skip },
            { $limit: amount },
            { $project: { "label": "$_id", _id: false, wp: true, count: true }}
        ]);
}

const cache = _.reduce(supported, function(memo, l) {
    _.set(memo, l, {
        content: null,
        computedAt: null,
        next: null,
    });
    return memo;
}, {} );

function formatReturn(lang, updated) {
    if(updated) {
        cache[lang].content = updated.content;
        cache[lang].computedAt = updated.computedAt;
        cache[lang].next = updated.next
    }
    return {
        json: {
            content: cache[lang].content,
            computedAt: cache[lang].computedAt.toISOString(),
            next: cache[lang].next.toISOString(),
        }
    };
};

function langinfo(req) {
    /* this API returns an complete information on a language population, with number of
     * active contributors in the last 48 hours and total keyword seen in the last 48 hours,
     * this API do not support paging and is meant to be cached */
    const MAXENTRIES = 60000;
    const DEFAULTAMOUNT = 10;
    const hoursNumber = 48;
    const backintime = moment().subtract(hoursNumber, 'h').toISOString();
    const amount = 13;
    const skip = 0;
    const lang = req.params.lang;
    const cacheMinutes = 60 * 12;

    if(!validLanguage(lang))
        return { json: LanguageError };

    if(cache[lang].next && moment().isBefore(cache[lang].next) && cache[lang].content) {
        debug("langInfo %s, using cached version", lang);
        return formatReturn(lang);
    }

    debug("langInfo %s, retrieving from DB", lang);
    return Promise.all([
        loudKeywordsPipeline(MAXENTRIES, backintime, amount, skip, lang),
        mongo.aggregate(nconf.get('schema').semantics, [
            { $sort: { when: -1 }},
            { $match: { lang: req.params.lang, when: { "$gt": new Date(backintime) } }},
            { $limit: MAXENTRIES },
            { $group: { _id: "$label" }},
            { $group: { _id: null, amount: { "$sum": 1 } }},
        ]).then(function(o) { return (o && o[0] && o[0].amount) ? o[0].amount : 0 }),
        mongo.aggregate(nconf.get('schema').labels, [
            { $sort: { when: -1 }},
            { $match: { lang: lang, when: { "$gt": new Date(backintime) } }},
            { $limit: MAXENTRIES },
            { $lookup: { from: 'summary', localField: 'semanticId', foreignField: 'semanticId', as: 'summary' }},
            { $group: { _id: "dummy", profiles: { $addToSet: "$summary.user"} }}
        ]).then(function(usermess) {
            // remind/TODO grouped by size and anonymized, this can be a nice stats
            // _.flatten(usermess[0].profiles)
            if(!(usermess && usermess[0] && usermess[0].profiles))
                return 0;
            return _.size(_.uniq(_.flatten(usermess[0].profiles)))
        })
    ])
    .then(function(results) {
        let retval = {
            consideredHoursWindow: hoursNumber,
            language: req.params.lang,
            most: _.map(results[0], 'label'),
            labelsCount: results[1],
            contributors: results[2],
        };
        return formatReturn(lang, {
            content: retval,
            computedAt: moment(),
            next: moment().add(cacheMinutes, 'minutes')
        });
    });
}

module.exports = {
    labels,
    semantics,
    enrich,
    loud,
    noogle,
    langinfo
};
<|endoftext|>


<commit_before>/**
 * Set up database connection to use
 */
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var config = require('../config.js');

//Connect to the database
if(!config.noDB){
	mongoose.connect('mongodb://'+config.db_host+':'+config.db_port+'/'+config.db_collection);
	console.log('Connected to '+config.db_host+':'+config.db_port+'/'+config.db_collection);
};

/**
 * Define the models
 */
//For less typing

var ObjectId = Schema.ObjectId;

//Define basic first
this.userDataModel = {
		name	: {
				first	: String,
				last	:	String
				},
		email	: { type: String, lowercase:true, required: true, index: {unique: true, sparse: true}},
	};
var UserSchema = new Schema(this.userDataModel);

this.commentDataModel = {
		eventID		:	ObjectId,
		userID		: 	ObjectId,
		text		:	{type: String, required:true},
		timestmp	:	{type: Date, default: Date.now},
		latitude	:	{type: Number, select: false},
		longitude	: 	{type: Number, select: false}
	};
var CommentSchema = new Schema(this.commentDataModel);

this.locationDataModel = {
		name		:	{type: String, required:true},
		latitude	:	{type: Number, required:true},
		longitude	:	{type: Number, required: true},
		radius		:	{type: Number, required: true}
	};
//Need this to make API testing DBRefs easier
this.LocationDataModel = this.locationDataModel;
var LocationSchema = new Schema(this.locationDataModel);

this,contactDataModel = {
		name		:	{type: String, required:true},
		email		:	{type: String, required:true},
		phone		:	{type: String, required:true}
	};
// For testing API DBRefs
this.ContactsDataModel = this.contactDataModel;
var ContactSchema = new Schema(this.contactDataModel);

this.eventDataModel = {
		GID			:	{type: Number, min:0, required:true},
		timestmp	:	{type: Date, default: Date.now},
		title		:	{type: String, required:true},
		type		:	{type: String, enum: config.eventTypes, required:true},
		group		:	{type: Number, required:true},
		status		:	{type: String, enum: ['Ongoing', 'Closed'], required:true},
		userID		:	ObjectId,
		description	:	{type: String, required:true},
		radius		:	Number,
		comments	:	{type: [CommentSchema]},
		location	:	{type: ObjectId, ref: 'Location', required:true},
		contact		:	{type: ObjectId, ref: 'Contacts', required:true}
	};
var EventSchema = new Schema(this.eventDataModel);

//Virtual method to get the number of comments
EventSchema.virtual('numComments').get(function(){
	return this.comments.length;
});

this.reportDataModel = {
		description	:	String,
		type		:	{type: String, enum: ['Emergency', 'Warning', 'Weather', 'Traffic'] },
		location	:	ObjectId,
		submitter	:	ObjectId,
		timestmp	:	{type: Date, default: Date.now},
		reviewer	:	ObjectId,
		status		:	{type: String, enum: ['Valid', 'Invalid']},
		reviewComment	:	String,
		reviewTimestmp	:	Date,
		event		:	ObjectId
	};
var ReportSchema = new Schema(this.reportDataModel);

/**
 * Set the models up
 */
this.comment = mongoose.model('Comment', CommentSchema);
this.location = mongoose.model('Location', LocationSchema);
this.contact = mongoose.model('Contacts', ContactSchema);
this.event = mongoose.model('Event', EventSchema);

/**
 * At this point, creating new data should be as easy as:
 * var newEvent = new event();
 * newEvent.title = 'Test'
 * newEvent.save(function(err) {});
 *
 * Finding events is as easy as:
 * event.find({id:1}, function(err, docs){
 * 		//docs contains all Events with a matching id
 * });
 * More: http://mongoosejs.com/docs/finding-documents.html
 *
 */<commit_msg>Fix typo<commit_after>/**
 * Set up database connection to use
 */
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var config = require('../config.js');

//Connect to the database
if(!config.noDB){
	mongoose.connect('mongodb://'+config.db_host+':'+config.db_port+'/'+config.db_collection);
	console.log('Connected to '+config.db_host+':'+config.db_port+'/'+config.db_collection);
};

/**
 * Define the models
 */
//For less typing

var ObjectId = Schema.ObjectId;

//Define basic first
this.userDataModel = {
		name	: {
				first	: String,
				last	:	String
				},
		email	: { type: String, lowercase:true, required: true, index: {unique: true, sparse: true}},
	};
var UserSchema = new Schema(this.userDataModel);

this.commentDataModel = {
		eventID		:	ObjectId,
		userID		: 	ObjectId,
		text		:	{type: String, required:true},
		timestmp	:	{type: Date, default: Date.now},
		latitude	:	{type: Number, select: false},
		longitude	: 	{type: Number, select: false}
	};
var CommentSchema = new Schema(this.commentDataModel);

this.locationDataModel = {
		name		:	{type: String, required:true},
		latitude	:	{type: Number, required:true},
		longitude	:	{type: Number, required: true},
		radius		:	{type: Number, required: true}
	};
//Need this to make API testing DBRefs easier
this.LocationDataModel = this.locationDataModel;
var LocationSchema = new Schema(this.locationDataModel);

this.contactDataModel = {
		name		:	{type: String, required:true},
		email		:	{type: String, required:true},
		phone		:	{type: String, required:true}
	};
// For testing API DBRefs
this.ContactsDataModel = this.contactDataModel;
var ContactSchema = new Schema(this.contactDataModel);

this.eventDataModel = {
		GID			:	{type: Number, min:0, required:true},
		timestmp	:	{type: Date, default: Date.now},
		title		:	{type: String, required:true},
		type		:	{type: String, enum: config.eventTypes, required:true},
		group		:	{type: Number, required:true},
		status		:	{type: String, enum: ['Ongoing', 'Closed'], required:true},
		userID		:	ObjectId,
		description	:	{type: String, required:true},
		radius		:	Number,
		comments	:	{type: [CommentSchema]},
		location	:	{type: ObjectId, ref: 'Location', required:true},
		contact		:	{type: ObjectId, ref: 'Contacts', required:true}
	};
var EventSchema = new Schema(this.eventDataModel);

//Virtual method to get the number of comments
EventSchema.virtual('numComments').get(function(){
	return this.comments.length;
});

this.reportDataModel = {
		description	:	String,
		type		:	{type: String, enum: ['Emergency', 'Warning', 'Weather', 'Traffic'] },
		location	:	ObjectId,
		submitter	:	ObjectId,
		timestmp	:	{type: Date, default: Date.now},
		reviewer	:	ObjectId,
		status		:	{type: String, enum: ['Valid', 'Invalid']},
		reviewComment	:	String,
		reviewTimestmp	:	Date,
		event		:	ObjectId
	};
var ReportSchema = new Schema(this.reportDataModel);

/**
 * Set the models up
 */
this.comment = mongoose.model('Comment', CommentSchema);
this.location = mongoose.model('Location', LocationSchema);
this.contact = mongoose.model('Contacts', ContactSchema);
this.event = mongoose.model('Event', EventSchema);

/**
 * At this point, creating new data should be as easy as:
 * var newEvent = new event();
 * newEvent.title = 'Test'
 * newEvent.save(function(err) {});
 *
 * Finding events is as easy as:
 * event.find({id:1}, function(err, docs){
 * 		//docs contains all Events with a matching id
 * });
 * More: http://mongoosejs.com/docs/finding-documents.html
 *
 */<|endoftext|>


<commit_before>/**
 * Created by FREDERIC on 5/05/2017.
 */

$(document).ready(function() {

    $.getJSON("holdevents.json", function (data) {
        var keys = Object.keys(data);
        //keys.reverse();
        var a = 0;
        var current = 1;
        var l = keys.length;
        var rest = l%3;
        var full = (l - rest)/3;
        var xof = Math.ceil(full+rest);
        var progress = current + " of " + (xof) +".";
        $("#dynamicpos").empty().append("Page: " + progress);

		for (var n = (l-1); n > l-4; n--) {
			var eventitem = data[keys[n]];
			var title = eventitem[1];
			var date = eventitem[2];
			var location = eventitem[3];
			var thumbnail = eventitem[4];
			var description = eventitem[5];
			$(".eventslice").append("
 " +
				"" +
				"

"+title+"

 Date: " + date + "

 Location: " + location + "

" + description + "

");
			$("#newer").css("visibility","hidden");
		}

        $(".move").on("click", function(event) {
            var x = event.target.id;
            if (x === "older") {
                l = l - 3;
                current = current + 1;
                $(".lister").css("visibility", "hidden");
            }
            if (x ==="newer") {
                l  = l+3;
                current = current - 1;
            }
            var progress = current + " of " + (xof) + ".";
            $("#dynamicpos").empty().append("Page: " + progress);
            $(".eventslice").empty();
            for (var n = (l-1); n > l-4; n--) {
                var eventitem = data[keys[n]];
                var title = eventitem[1];
                var date = eventitem[2];
                var location = eventitem[3];
                var thumbnail = eventitem[4];
                var description = eventitem[5];
                $(".eventslice").append("
 " +
                    "" +
                    "

"+title+"

 Date: " + date + "

 Location: " + location + "

" + description + "

");
            if (current === xof) {$("#older").css("visibility","hidden");
            } else {$("#older").css("visibility","visible");}
            }
        if (current === 1) {$("#newer").css("visibility","hidden");
            $(".lister").css("visibility", "visible");
        } else {$("#newer").css("visibility","visible")}
        });
    });
});
<commit_msg>Delete reader.js<commit_after><|endoftext|>


<commit_before>export default /* glsl */ `
#ifdef USE_CLEAR_COAT
  uniform float uClearCoat;
  uniform float uClearCoatRoughness;

  #ifdef USE_CLEAR_COAT_MAP
    uniform sampler2D uClearCoatMap;
    uniform float uClearCoatMapScale;

    #ifdef USE_CLEAR_COAT_MAP_TEX_COORD_TRANSFORM
      uniform mat3 uClearCoatMapTexCoordTransform;
    #endif

    void getClearCoat(inout PBRData data) {
      #ifdef USE_CLEAR_COAT_MAP_TEX_COORD_TRANSFORM
        vec2 texCoord = getTextureCoordinates(data, CLEAR_COAT_MAP_TEX_COORD_INDEX, uClearCoatMapTexCoordTransform);
      #else
        vec2 texCoord = getTextureCoordinates(data, CLEAR_COAT_MAP_TEX_COORD_INDEX);
      #endif

      data.clearCoat = uClearCoat * texture2D(uClearCoatMap, texCoord).r;
    }
  #else
    void getClearCoat(inout PBRData data) {
      data.clearCoat = uClearCoat;
    }
  #endif

  #ifdef USE_CLEAR_COAT_ROUGHNESS_MAP
    uniform sampler2D uClearCoatRoughnessMap;
    uniform float uClearCoatRoughnessMapScale;

    #ifdef USE_CLEAR_COAT_ROUGHNESS_MAP_TEX_COORD_TRANSFORM
      uniform mat3 uClearCoatRoughnessMapTexCoordTransform;
    #endif

    void getClearCoatRoughness(inout PBRData data) {
      #ifdef USE_CLEAR_COAT_ROUGHNESS_MAP_TEX_COORD_TRANSFORM
        vec2 texCoord = getTextureCoordinates(data, CLEAR_COAT_ROUGHNESS_MAP_TEX_COORD_INDEX, uClearCoatRoughnessMapTexCoordTransform);
      #else
        vec2 texCoord = getTextureCoordinates(data, CLEAR_COAT_ROUGHNESS_MAP_TEX_COORD_INDEX);
      #endif

      data.clearCoatRoughness = uClearCoatRoughness * texture2D(uClearCoatRoughnessMap, texCoord).g;
    }
  #else
    void getClearCoatRoughness(inout PBRData data) {
      data.clearCoatRoughness = uClearCoatRoughness;
    }
  #endif

  #ifdef USE_CLEAR_COAT_NORMAL_MAP
    uniform sampler2D uClearCoatNormalMap;
    uniform float uClearCoatNormalMapScale;

    #ifdef USE_CLEAR_COAT_NORMAL_MAP_TEX_COORD_TRANSFORM
      uniform mat3 uClearCoatNormalMapTexCoordTransform;
    #endif

    void getClearCoatNormal(inout PBRData data) {
      #ifdef USE_CLEAR_COAT_NORMAL_MAP_TEX_COORD_TRANSFORM
        vec2 texCoord = getTextureCoordinates(data, CLEAR_COAT_NORMAL_MAP_TEX_COORD_INDEX, uClearCoatNormalMapTexCoordTransform);
      #else
        vec2 texCoord = getTextureCoordinates(data, CLEAR_COAT_NORMAL_MAP_TEX_COORD_INDEX);
      #endif

      vec3 normalMap = texture2D(uClearCoatNormalMap, texCoord).rgb * 2.0 - 1.0;
      normalMap.y *= uClearCoatNormalMapScale;
      normalMap = normalize(normalMap);

      vec3 N = normalize(data.normalView);
      vec3 V = normalize(data.eyeDirView);

      vec3 normalView;

      #ifdef USE_TANGENTS
        vec3 bitangent = cross(N, data.tangentView.xyz) * sign(data.tangentView.w);
        mat3 TBN = mat3(data.tangentView.xyz, bitangent, N);
        normalView = normalize(TBN * normalMap);
      #else
        normalMap.xy *= float(gl_FrontFacing) * 2.0 - 1.0;
        // make the output normalView match glTF expected right handed orientation
        normalMap.y *= -1.0;
        normalView = perturb(normalMap, N, V, texCoord);
      #endif

      data.clearCoatNormal = normalize(vec3(data.inverseViewMatrix * vec4(normalView, 0.0)));
    }
  #else
    void getClearCoatNormal(inout PBRData data) {
      // geometric normal without perturbation from normalMap
      // this normal is in world space
      data.clearCoatNormal = normalize(vec3(data.inverseViewMatrix * vec4(normalize(data.normalView), 0.0)));
    }
  #endif

  // IOR = 1.5, F0 = 0.04
  // as material is no longer in contact with air we calculate new IOR on the
  // clear coat and material interface
  vec3 f0ClearCoatToSurface(const vec3 f0) {
    return saturate(f0 * (f0 * (0.941892 - 0.263008 * f0) + 0.346479) - 0.0285998);
  }

  float clearCoatBRDF(const PBRData data, const vec3 h, float NoH, float LoH, out float Fcc) {
    #if defined(USE_NORMAL_MAP) || defined(USE_CLEAR_COAT_NORMAL_MAP)
      float clearCoatNoH = saturate(dot(data.clearCoatNormal, h));
    #else
      float clearCoatNoH = NoH;
    #endif
    float D = D_GGX(data.clearCoatLinearRoughness, clearCoatNoH, h, data.normalWorld);
    float V = V_Kelemen(LoH);
    // air-polyurethane interface has IOR = 1.5 -> F0 = 0.04
    float F = F_Schlick(0.04, 1.0, LoH) * data.clearCoat;

    Fcc = F;
    return D * V * F;
  }
#endif
`;
<commit_msg>fix: clearcoat normal undefined normalView<commit_after>export default /* glsl */ `
#ifdef USE_CLEAR_COAT
  uniform float uClearCoat;
  uniform float uClearCoatRoughness;

  #ifdef USE_CLEAR_COAT_MAP
    uniform sampler2D uClearCoatMap;
    uniform float uClearCoatMapScale;

    #ifdef USE_CLEAR_COAT_MAP_TEX_COORD_TRANSFORM
      uniform mat3 uClearCoatMapTexCoordTransform;
    #endif

    void getClearCoat(inout PBRData data) {
      #ifdef USE_CLEAR_COAT_MAP_TEX_COORD_TRANSFORM
        vec2 texCoord = getTextureCoordinates(data, CLEAR_COAT_MAP_TEX_COORD_INDEX, uClearCoatMapTexCoordTransform);
      #else
        vec2 texCoord = getTextureCoordinates(data, CLEAR_COAT_MAP_TEX_COORD_INDEX);
      #endif

      data.clearCoat = uClearCoat * texture2D(uClearCoatMap, texCoord).r;
    }
  #else
    void getClearCoat(inout PBRData data) {
      data.clearCoat = uClearCoat;
    }
  #endif

  #ifdef USE_CLEAR_COAT_ROUGHNESS_MAP
    uniform sampler2D uClearCoatRoughnessMap;
    uniform float uClearCoatRoughnessMapScale;

    #ifdef USE_CLEAR_COAT_ROUGHNESS_MAP_TEX_COORD_TRANSFORM
      uniform mat3 uClearCoatRoughnessMapTexCoordTransform;
    #endif

    void getClearCoatRoughness(inout PBRData data) {
      #ifdef USE_CLEAR_COAT_ROUGHNESS_MAP_TEX_COORD_TRANSFORM
        vec2 texCoord = getTextureCoordinates(data, CLEAR_COAT_ROUGHNESS_MAP_TEX_COORD_INDEX, uClearCoatRoughnessMapTexCoordTransform);
      #else
        vec2 texCoord = getTextureCoordinates(data, CLEAR_COAT_ROUGHNESS_MAP_TEX_COORD_INDEX);
      #endif

      data.clearCoatRoughness = uClearCoatRoughness * texture2D(uClearCoatRoughnessMap, texCoord).g;
    }
  #else
    void getClearCoatRoughness(inout PBRData data) {
      data.clearCoatRoughness = uClearCoatRoughness;
    }
  #endif

  #ifdef USE_CLEAR_COAT_NORMAL_MAP
    uniform sampler2D uClearCoatNormalMap;
    uniform float uClearCoatNormalMapScale;

    #ifdef USE_CLEAR_COAT_NORMAL_MAP_TEX_COORD_TRANSFORM
      uniform mat3 uClearCoatNormalMapTexCoordTransform;
    #endif

    void getClearCoatNormal(inout PBRData data) {
      #ifdef USE_CLEAR_COAT_NORMAL_MAP_TEX_COORD_TRANSFORM
        vec2 texCoord = getTextureCoordinates(data, CLEAR_COAT_NORMAL_MAP_TEX_COORD_INDEX, uClearCoatNormalMapTexCoordTransform);
      #else
        vec2 texCoord = getTextureCoordinates(data, CLEAR_COAT_NORMAL_MAP_TEX_COORD_INDEX);
      #endif

      vec3 normalMap = texture2D(uClearCoatNormalMap, texCoord).rgb * 2.0 - 1.0;
      normalMap.y *= uClearCoatNormalMapScale;
      normalMap = normalize(normalMap);

      vec3 N = normalize(data.normalView);
      vec3 V = normalize(data.eyeDirView);

      vec3 normalView;

      #ifdef USE_TANGENTS
        vec3 bitangent = cross(N, data.tangentView.xyz) * sign(data.tangentView.w);
        mat3 TBN = mat3(data.tangentView.xyz, bitangent, N);
        normalView = normalize(TBN * normalMap);
      #else
        normalMap.xy *= float(gl_FrontFacing) * 2.0 - 1.0;
        // make the output normalView match glTF expected right handed orientation
        normalMap.y *= -1.0;
        normalView = perturb(normalMap, N, V, texCoord);
      #endif

      data.clearCoatNormal = normalize(vec3(data.inverseViewMatrix * vec4(normalView, 0.0)));
    }
  #else
    void getClearCoatNormal(inout PBRData data) {
      // geometric normal without perturbation from normalMap
      // this normal is in world space
      data.clearCoatNormal = normalize(vec3(data.inverseViewMatrix * vec4(normalize(vNormalView), 0.0)));
    }
  #endif

  // IOR = 1.5, F0 = 0.04
  // as material is no longer in contact with air we calculate new IOR on the
  // clear coat and material interface
  vec3 f0ClearCoatToSurface(const vec3 f0) {
    return saturate(f0 * (f0 * (0.941892 - 0.263008 * f0) + 0.346479) - 0.0285998);
  }

  float clearCoatBRDF(const PBRData data, const vec3 h, float NoH, float LoH, out float Fcc) {
    #if defined(USE_NORMAL_MAP) || defined(USE_CLEAR_COAT_NORMAL_MAP)
      float clearCoatNoH = saturate(dot(data.clearCoatNormal, h));
    #else
      float clearCoatNoH = NoH;
    #endif
    float D = D_GGX(data.clearCoatLinearRoughness, clearCoatNoH, h, data.normalWorld);
    float V = V_Kelemen(LoH);
    // air-polyurethane interface has IOR = 1.5 -> F0 = 0.04
    float F = F_Schlick(0.04, 1.0, LoH) * data.clearCoat;

    Fcc = F;
    return D * V * F;
  }
#endif
`;
<|endoftext|>


<commit_before>
Ui.Image.extend('KJing.SquareImage', {
	squareSize: undefined,

	setSquareSize: function(size) {
		this.squareSize = size;
		this.invalidateMeasure();
	}
}, {
	measureCore: function(w, h) {
		if(this.getIsReady()) {
			var ratio = this.getNaturalWidth() / this.getNaturalHeight();
			if(ratio > 1)
				return { width: this.squareSize, height: this.squareSize/ratio };
			else
				return { width: this.squareSize*ratio, height: this.squareSize };
		}
		else
			return { width: this.squareSize, height: this.squareSize };
	}
});

Ui.LBox.extend('KJing.ItemViewIcon', {
	tagsBox: undefined,
	tags: undefined,
	isRound: false,
	iconName: undefined,
	iconSrc: undefined,
	imageSrc: undefined,
	squareSize: 48,
	icon: undefined,

	constructor: function() {
	},

	setSquareSize: function(squareSize) {
		this.squareSize = squareSize;
		if(this.tags !== undefined) {
			this.tagsBox.setWidth(this.squareSize);
			this.tagsBox.setHeight(this.squareSize);
		}
		if(this.icon !== undefined) {
			if(KJing.SquareImage.hasInstance(this.icon))
				this.icon.setSquareSize(this.squareSize);
			else {
				this.icon.setWidth(this.squareSize);
				this.icon.setHeight(this.squareSize);
			}
		}
	},

	setRoundMode: function(isRound) {
		this.isRound = isRound;
		if(this.imageSrc !== undefined)
			this.setImage(this.imageSrc);
	},

	setIcon: function(icon) {
		this.iconName = icon;
		this.icon = new Ui.Icon({
			icon: this.iconName,
			width: this.squareSize, height: this.squareSize
		});
		this.setContent(this.icon);
		if(this.tagsBox !== undefined)
			this.append(this.tagsBox);
	},

	setIconImage: function(icon) {
		this.iconSrc = icon;
		this.icon = new KJing.SquareImage({
			src: this.iconSrc,
			squareSize: this.squareSize
		});
		this.setContent(this.icon);
		if(this.tagsBox !== undefined)
			this.append(this.tagsBox);
	},

	setImage: function(image) {
		this.imageSrc = image;
		if(this.isRound) {
			this.icon = new KJing.RoundItemGraphic({
				imageSrc: this.imageSrc, width: this.squareSize, height: this.squareSize
			});
			this.setContent(this.icon);
		}
		else {
			this.icon = new KJing.SquareImage({ src: this.imageSrc, squareSize: this.squareSize });
			this.connect(this.icon, 'error', this.onImageError);
			this.setContent(this.icon);
		}
		if(this.tagsBox !== undefined)
			this.append(this.tagsBox);
	},

	setTags: function(tags) {
		this.tags = tags;
		if(this.tags !== undefined) {
			if(this.tagsBox === undefined) {
				this.tagsBox = new Ui.LBox({ width: this.squareSize, height: this.squareSize, verticalAlign: 'bottom', horizontalAlign: 'center' });
				this.append(this.tagsBox);
			}
			var flow = new Ui.Flow({ itemAlign: 'right', verticalAlign: 'bottom' });
			this.tagsBox.setContent(flow);
			for(var i = 0; i < tags.length; i++)
				flow.append(new Ui.Icon({ icon: tags[i], width: 24, height: 24, fill: '#00c3ff' }));
		}
		else {
			if(this.tagsBox !== undefined) {
				this.remove(this.tagsBox);
				this.tagsBox = undefined;
			}
		}
	},

	onImageError: function(image) {
		this.disconnect(image, 'error', this.onImageError);
		if(this.iconSrc !== undefined)
			this.setIconImage(this.iconSrc);
		else if(this.iconName !== undefined)
			this.setIcon(this.iconName);
	}
});

Ui.Button.extend('KJing.ItemView', {
	view: undefined,
	content: undefined,
	name: undefined,
	progressbar: undefined,
	iconSrc: undefined,
	iconName: undefined,
	imageSrc: undefined,
	share: false,
	tags: undefined,
	tagsBox: undefined,
	isRound: false,
	itemIcon: undefined,

	constructor: function(config) {
		this.view = config.view;
		delete(config.view);

		this.setDraggableData(this);
		this.itemIcon = new KJing.ItemViewIcon({ verticalAlign: 'bottom', horizontalAlign: 'center' });
		this.setIcon(this.itemIcon);

		this.connect(this, 'press', function() {
			if(this.getIsSelected())
				this.unselect();
			else
				this.select();
		});
	},

	getView: function() {
		return this.view;
	},

	addMimetype: function(mimetype) {
//		this.content.addMimetype(mimetype);
	},

	setItemTags: function(tags) {
		this.itemIcon.setTags(tags);

//		this.tags = tags;
/*		if(this.tags !== undefined) {
			if(this.tagsBox === undefined) {
				this.tagsBox = new Ui.LBox({ width: 64, height: 64, verticalAlign: 'bottom', horizontalAlign: 'center' });
				this.content.append(this.tagsBox);
			}
			var flow = new Ui.Flow({ itemAlign: 'right', verticalAlign: 'bottom' });
			this.tagsBox.setContent(flow);
			for(var i = 0; i < tags.length; i++)
				flow.append(new Ui.Icon({ icon: tags[i], width: 24, height: 24, fill: '#00c3ff' }));
		}
		else {
			if(this.tagsBox !== undefined) {
				this.content.remove(this.tagsBox);
				this.tagsBox = undefined;
			}
		}*/
	},

	setItemIcon: function(icon) {
		this.itemIcon.setIcon(icon);
//		this.setIcon(icon);
/*		this.iconName = icon;
		this.content.setContent(new Ui.Icon({ icon: this.iconName, verticalAlign: 'bottom', horizontalAlign: 'center', width: 64, height: 64 }));
		if(this.tagsBox !== undefined)
			this.append(this.tagsBox);*/
	},

	setItemIconSrc: function(icon) {
		this.itemIcon.setIconImage(icon);
//		this.iconSrc = icon;
//		this.setIcon(new Ui.Image({ src: this.iconSrc, verticalAlign: 'bottom', horizontalAlign: 'center' }));
//		if(this.tagsBox !== undefined)
//			this.content.append(this.tagsBox);
	},

	setItemImage: function(image) {
		this.itemIcon.setImage(image);
/*		this.imageSrc = image;
		if(this.isRound) {
			var graphic = new KJing.RoundItemGraphic({
				verticalAlign: 'bottom', horizontalAlign: 'center',
				imageSrc: this.imageSrc, width: 70, height: 70
			});
			this.setIcon(graphic);
		}
		else {
			var lbox = new Ui.LBox({ verticalAlign: 'bottom', horizontalAlign: 'center' });
			this.setIcon(lbox);
			lbox.append(new Ui.Rectangle({ fill: new Ui.Color({ r: 0.7, b: 0.7, g: 0.7 }) }));
			lbox.append(new Ui.Rectangle({ fill: 'white', margin: 1 }));
			var image = new Ui.Image({ src: this.imageSrc, margin: 3, width: 64 });
			lbox.append(image);
			this.connect(image, 'error', this.onImageError);
		}
//		if(this.tagsBox !== undefined)
//			this.content.append(this.tagsBox);*/
	},

	getItemName: function() {
		return this.name;
	},

	setItemName: function(name) {
		this.name = name;
		this.setText(name);
	},

	setItemLabel: function(label) {
		this.setText(label);
	},

	onImageError: function(image) {
		this.disconnect(image, 'error', this.onImageError);
		if(this.iconSrc !== undefined)
			this.setItemIconSrc(this.iconSrc);
		else if(this.iconName !== undefined)
			this.setItemIcon(this.iconName);
	}
}, {
	onStyleChange: function() {
		KJing.ItemView.base.onStyleChange.apply(this, arguments)
		this.itemIcon.setSquareSize(this.getStyleProperty('iconSize'));
		this.itemIcon.setRoundMode(this.getStyleProperty('roundMode'));
	}
}, {
	style: {
		roundMode: false
	}
});

/*Ui.Selectionable.extend('KJing.ItemView', {
	view: undefined,
	content: undefined,
	name: undefined,
	label: undefined,
	progressbar: undefined,
	iconSrc: undefined,
	iconName: undefined,
	imageSrc: undefined,
	share: false,
	tags: undefined,
	tagsBox: undefined,
	isRound: false,
	bg: undefined,

	constructor: function(config) {
		this.view = config.view;
		delete(config.view);

		this.setDraggableData(this);

		this.bg = new Ui.Rectangle({ fill: '#e0eff8' });
		this.bg.hide();
		this.append(this.bg);

		var vbox = new Ui.VBox({ margin: 5, spacing: 5 });
		this.append(vbox);

		this.content = new Ui.DropBox({ width: 70, height: 70 });
		this.connect(this.content, 'drop', this.onDrop);
		this.connect(this.content, 'dropfile', this.onDropFile);
		vbox.append(this.content);

		this.label = new Ui.CompactLabel({ width: 100, maxLine: 3, textAlign: 'center' });
		vbox.append(this.label);

		this.connect(this, 'press', function() {
			if(this.getIsSelected())
				this.unselect();
			else
				this.select();
		});
	},

	setRoundMode: function(isRound) {
		this.isRound = isRound;
		if(this.imageSrc !== undefined)
			this.setItemImage(this.imageSrc);
	},

	getView: function() {
		return this.view;
	},

	addMimetype: function(mimetype) {
		this.content.addMimetype(mimetype);
	},

	setItemTags: function(tags) {
		this.tags = tags;
		if(this.tags !== undefined) {
			if(this.tagsBox === undefined) {
				this.tagsBox = new Ui.LBox({ width: 64, height: 64, verticalAlign: 'bottom', horizontalAlign: 'center' });
				this.content.append(this.tagsBox);
			}
			var flow = new Ui.Flow({ itemAlign: 'right', verticalAlign: 'bottom' });
			this.tagsBox.setContent(flow);
			for(var i = 0; i < tags.length; i++)
				flow.append(new Ui.Icon({ icon: tags[i], width: 24, height: 24, fill: '#00c3ff' }));
		}
		else {
			if(this.tagsBox !== undefined) {
				this.content.remove(this.tagsBox);
				this.tagsBox = undefined;
			}
		}
	},

	setItemIcon: function(icon) {
		this.iconName = icon;
		this.content.setContent(new Ui.Icon({ icon: this.iconName, verticalAlign: 'bottom', horizontalAlign: 'center', width: 64, height: 64 }));
		if(this.tagsBox !== undefined)
			this.append(this.tagsBox);
	},

	setItemIconSrc: function(icon) {
		this.iconSrc = icon;
		this.content.setContent(new Ui.Image({ src: this.iconSrc, verticalAlign: 'bottom', horizontalAlign: 'center' }));
		if(this.tagsBox !== undefined)
			this.content.append(this.tagsBox);
	},

	setItemImage: function(image) {
		this.imageSrc = image;
		if(this.isRound) {
			var graphic = new KJing.RoundItemGraphic({
				verticalAlign: 'bottom', horizontalAlign: 'center',
				imageSrc: this.imageSrc, width: 70, height: 70
			});
			this.content.setContent(graphic);
		}
		else {
			var lbox = new Ui.LBox({ verticalAlign: 'bottom', horizontalAlign: 'center' });
			this.content.setContent(lbox);
			lbox.append(new Ui.Rectangle({ fill: new Ui.Color({ r: 0.7, b: 0.7, g: 0.7 }) }));
			lbox.append(new Ui.Rectangle({ fill: 'white', margin: 1 }));
			var image = new Ui.Image({ src: this.imageSrc, margin: 3, width: 64 });
			lbox.append(image);
			this.connect(image, 'error', this.onImageError);
		}
		if(this.tagsBox !== undefined)
			this.content.append(this.tagsBox);
	},

	getItemName: function() {
		return this.name;
	},

	setItemName: function(name) {
		this.name = name;
		if((this.label.getText() === undefined) || (this.label.getText() === ''))
			this.setItemLabel(name);
	},

	setItemLabel: function(label) {
		this.label.setText(label);
	},

	onImageError: function(image) {
		this.disconnect(image, 'error', this.onImageError);
		if(this.iconSrc !== undefined)
			this.setItemIconSrc(this.iconSrc);
		else if(this.iconName !== undefined)
			this.setItemIcon(this.iconName);
	},

	onDrop: function() {
	},

	onDropFile: function() {
	}
}, {
	onSelect: function() {
		this.bg.show();
	},

	onUnselect: function() {
		this.bg.hide();
	}
});
*/<commit_msg>improve KJing.ItemView look<commit_after>
Ui.Image.extend('KJing.SquareImage', {
	squareSize: undefined,

	setSquareSize: function(size) {
		this.squareSize = size;
		this.invalidateMeasure();
	}
}, {
	measureCore: function(w, h) {
		if(this.getIsReady()) {
			var ratio = this.getNaturalWidth() / this.getNaturalHeight();
			if(ratio > 1)
				return { width: this.squareSize, height: this.squareSize/ratio };
			else
				return { width: this.squareSize*ratio, height: this.squareSize };
		}
		else
			return { width: this.squareSize, height: this.squareSize };
	}
});

Ui.LBox.extend('KJing.ItemViewIcon', {
	tagsBox: undefined,
	tags: undefined,
	isRound: false,
	iconName: undefined,
	iconSrc: undefined,
	imageSrc: undefined,
	squareSize: 48,
	icon: undefined,

	constructor: function() {
	},

	setSquareSize: function(squareSize) {
		this.squareSize = squareSize;
		if(this.tags !== undefined) {
			this.tagsBox.setWidth(this.squareSize);
			this.tagsBox.setHeight(this.squareSize);
		}
		if(this.icon !== undefined) {
			if(KJing.SquareImage.hasInstance(this.icon))
				this.icon.setSquareSize(this.squareSize);
			else {
				this.icon.setWidth(this.squareSize);
				this.icon.setHeight(this.squareSize);
			}
		}
	},

	setRoundMode: function(isRound) {
		this.isRound = isRound;
		if(this.imageSrc !== undefined)
			this.setImage(this.imageSrc);
	},

	setIcon: function(icon) {
		this.iconName = icon;
		this.icon = new Ui.Icon({
			icon: this.iconName,
			width: this.squareSize, height: this.squareSize
		});
		this.setContent(this.icon);
		if(this.tagsBox !== undefined)
			this.append(this.tagsBox);
	},

	setIconImage: function(icon) {
		this.iconSrc = icon;
		this.icon = new KJing.SquareImage({
			src: this.iconSrc,
			squareSize: this.squareSize
		});
		this.setContent(this.icon);
		if(this.tagsBox !== undefined)
			this.append(this.tagsBox);
	},

	setImage: function(image) {
		this.imageSrc = image;
		if(this.isRound) {
			this.icon = new KJing.RoundItemGraphic({
				imageSrc: this.imageSrc, width: this.squareSize, height: this.squareSize
			});
			this.setContent(this.icon);
		}
		else {
			this.icon = new KJing.SquareImage({ src: this.imageSrc, squareSize: this.squareSize });
			this.connect(this.icon, 'error', this.onImageError);
			this.setContent(this.icon);
		}
		if(this.tagsBox !== undefined)
			this.append(this.tagsBox);
	},

	setTags: function(tags) {
		this.tags = tags;
		if(this.tags !== undefined) {
			if(this.tagsBox === undefined) {
				this.tagsBox = new Ui.LBox({ width: this.squareSize, height: this.squareSize, verticalAlign: 'bottom', horizontalAlign: 'center' });
				this.append(this.tagsBox);
			}
			var flow = new Ui.Flow({ itemAlign: 'right', verticalAlign: 'bottom' });
			this.tagsBox.setContent(flow);
			for(var i = 0; i < tags.length; i++)
				flow.append(new Ui.Icon({ icon: tags[i], width: 24, height: 24, fill: '#00c3ff' }));
		}
		else {
			if(this.tagsBox !== undefined) {
				this.remove(this.tagsBox);
				this.tagsBox = undefined;
			}
		}
	},

	onImageError: function(image) {
		this.disconnect(image, 'error', this.onImageError);
		if(this.iconSrc !== undefined)
			this.setIconImage(this.iconSrc);
		else if(this.iconName !== undefined)
			this.setIcon(this.iconName);
	}
});

Ui.Button.extend('KJing.ItemView', {
	view: undefined,
	content: undefined,
	name: undefined,
	progressbar: undefined,
	iconSrc: undefined,
	iconName: undefined,
	imageSrc: undefined,
	share: false,
	tags: undefined,
	tagsBox: undefined,
	isRound: false,
	itemIcon: undefined,
	selectedIcon: undefined,

	constructor: function(config) {
		this.view = config.view;
		delete(config.view);

		this.setDraggableData(this);
		this.itemIcon = new KJing.ItemViewIcon({ verticalAlign: 'bottom', horizontalAlign: 'center' });
		this.setIcon(this.itemIcon);

		this.connect(this, 'press', function() {
			if(this.getIsSelected())
				this.unselect();
			else
				this.select();
		});
	},

	getView: function() {
		return this.view;
	},

	addMimetype: function(mimetype) {
//		this.content.addMimetype(mimetype);
	},

	setItemTags: function(tags) {
		this.itemIcon.setTags(tags);
	},

	setItemIcon: function(icon) {
		this.itemIcon.setIcon(icon);
	},

	setItemIconSrc: function(icon) {
		this.itemIcon.setIconImage(icon);
	},

	setItemImage: function(image) {
		this.itemIcon.setImage(image);
	},

	getItemName: function() {
		return this.name;
	},

	setItemName: function(name) {
		this.name = name;
		this.setText(name);
	},

	setItemLabel: function(label) {
		this.setText(label);
	},

	onImageError: function(image) {
		this.disconnect(image, 'error', this.onImageError);
		if(this.iconSrc !== undefined)
			this.setItemIconSrc(this.iconSrc);
		else if(this.iconName !== undefined)
			this.setItemIcon(this.iconName);
	}
}, {
	onSelect: function() {
		this.selectedIcon = new Ui.Icon({
			icon: 'check', verticalAlign: 'top', horizontalAlign: 'right',
			marginTop: 5, marginRight: 5,
			width: 32, height: 32, fill: this.getStyleProperty('selectCheckColor')
		});
		this.getDropBox().append(this.selectedIcon);
	},

	onUnselect: function() {
		this.getDropBox().remove(this.selectedIcon);
		this.selectedIcon = undefined;
	},

	onStyleChange: function() {
		KJing.ItemView.base.onStyleChange.apply(this, arguments)
		this.itemIcon.setSquareSize(this.getStyleProperty('iconSize'));
		this.itemIcon.setRoundMode(this.getStyleProperty('roundMode'));
		if(this.selectedIcon !== undefined)
			this.selectedIcon.setFill(this.getStyleProperty('selectCheckColor'));
	}
}, {
	style: {
		selectCheckColor: 'red',
		roundMode: false
	}
});

/*Ui.Selectionable.extend('KJing.ItemView', {
	view: undefined,
	content: undefined,
	name: undefined,
	label: undefined,
	progressbar: undefined,
	iconSrc: undefined,
	iconName: undefined,
	imageSrc: undefined,
	share: false,
	tags: undefined,
	tagsBox: undefined,
	isRound: false,
	bg: undefined,

	constructor: function(config) {
		this.view = config.view;
		delete(config.view);

		this.setDraggableData(this);

		this.bg = new Ui.Rectangle({ fill: '#e0eff8' });
		this.bg.hide();
		this.append(this.bg);

		var vbox = new Ui.VBox({ margin: 5, spacing: 5 });
		this.append(vbox);

		this.content = new Ui.DropBox({ width: 70, height: 70 });
		this.connect(this.content, 'drop', this.onDrop);
		this.connect(this.content, 'dropfile', this.onDropFile);
		vbox.append(this.content);

		this.label = new Ui.CompactLabel({ width: 100, maxLine: 3, textAlign: 'center' });
		vbox.append(this.label);

		this.connect(this, 'press', function() {
			if(this.getIsSelected())
				this.unselect();
			else
				this.select();
		});
	},

	setRoundMode: function(isRound) {
		this.isRound = isRound;
		if(this.imageSrc !== undefined)
			this.setItemImage(this.imageSrc);
	},

	getView: function() {
		return this.view;
	},

	addMimetype: function(mimetype) {
		this.content.addMimetype(mimetype);
	},

	setItemTags: function(tags) {
		this.tags = tags;
		if(this.tags !== undefined) {
			if(this.tagsBox === undefined) {
				this.tagsBox = new Ui.LBox({ width: 64, height: 64, verticalAlign: 'bottom', horizontalAlign: 'center' });
				this.content.append(this.tagsBox);
			}
			var flow = new Ui.Flow({ itemAlign: 'right', verticalAlign: 'bottom' });
			this.tagsBox.setContent(flow);
			for(var i = 0; i < tags.length; i++)
				flow.append(new Ui.Icon({ icon: tags[i], width: 24, height: 24, fill: '#00c3ff' }));
		}
		else {
			if(this.tagsBox !== undefined) {
				this.content.remove(this.tagsBox);
				this.tagsBox = undefined;
			}
		}
	},

	setItemIcon: function(icon) {
		this.iconName = icon;
		this.content.setContent(new Ui.Icon({ icon: this.iconName, verticalAlign: 'bottom', horizontalAlign: 'center', width: 64, height: 64 }));
		if(this.tagsBox !== undefined)
			this.append(this.tagsBox);
	},

	setItemIconSrc: function(icon) {
		this.iconSrc = icon;
		this.content.setContent(new Ui.Image({ src: this.iconSrc, verticalAlign: 'bottom', horizontalAlign: 'center' }));
		if(this.tagsBox !== undefined)
			this.content.append(this.tagsBox);
	},

	setItemImage: function(image) {
		this.imageSrc = image;
		if(this.isRound) {
			var graphic = new KJing.RoundItemGraphic({
				verticalAlign: 'bottom', horizontalAlign: 'center',
				imageSrc: this.imageSrc, width: 70, height: 70
			});
			this.content.setContent(graphic);
		}
		else {
			var lbox = new Ui.LBox({ verticalAlign: 'bottom', horizontalAlign: 'center' });
			this.content.setContent(lbox);
			lbox.append(new Ui.Rectangle({ fill: new Ui.Color({ r: 0.7, b: 0.7, g: 0.7 }) }));
			lbox.append(new Ui.Rectangle({ fill: 'white', margin: 1 }));
			var image = new Ui.Image({ src: this.imageSrc, margin: 3, width: 64 });
			lbox.append(image);
			this.connect(image, 'error', this.onImageError);
		}
		if(this.tagsBox !== undefined)
			this.content.append(this.tagsBox);
	},

	getItemName: function() {
		return this.name;
	},

	setItemName: function(name) {
		this.name = name;
		if((this.label.getText() === undefined) || (this.label.getText() === ''))
			this.setItemLabel(name);
	},

	setItemLabel: function(label) {
		this.label.setText(label);
	},

	onImageError: function(image) {
		this.disconnect(image, 'error', this.onImageError);
		if(this.iconSrc !== undefined)
			this.setItemIconSrc(this.iconSrc);
		else if(this.iconName !== undefined)
			this.setItemIcon(this.iconName);
	},

	onDrop: function() {
	},

	onDropFile: function() {
	}
}, {
	onSelect: function() {
		this.bg.show();
	},

	onUnselect: function() {
		this.bg.hide();
	}
});
*/<|endoftext|>