<commit_before>var _ = require('underscore'),
    express = require('express'),
    router = express.Router(),
    path = require('path'),
    fs = require('fs'),
    moment= require('moment'),
    mongoose = require('mongoose'),
    util = require('../lib/util'),
    config = require('../settings'),
    is_member = require('../lib/middleware').is_member,
    File = require('../models/files').File,
    Activity = require('../models').Activity;

router.get('/', function (req, res) {
    var query;
    if (req.user) {
        query = File.find().or([
            {creator: req.user._id},
            {'permissions.public': true},
            {'permissions.users': req.user._id},
            {'permissions.groups': { $in: req.user.groups }}
        ]);
    }
    else {
        query = File.find({'permissions.public': true});
    }
    query = query
        .sort('-created')
        .populate('creator', 'username name')
        .limit(20);
    if (req.query.page) {
        query = query.skip(20 * req.query.page);
    }
    query.exec(function (err, files) {
        if (err) {
            throw err;
        }
        res.format({
            html: function () {
                res.render('files/index', {files: files, meta: {title: 'Filer'}});
            },
            json: function () {
                res.json(files);
            }
        });
    });
});

router.get('/t/*', function (req, res) {
    var tagstring = req.params[0];
    var query;
    if (req.user) {
        query = File.find().or([
            {creator: req.user._id},
            {'permissions.public': true},
            {'permissions.users': req.user._id},
            {'permissions.groups': { $in: req.user.groups }}
        ]);
    }
    else {
        query = File.find({'permissions.public': true});
    }

    _.each(tagstring.split("/"), function (tag) {
        query.find({'tags': tag});
    });

    query = query
        .sort('-created')
        .populate('creator', 'username name')
        .limit(20);
    if (req.query.page) {
        query = query.skip(20 * req.query.page);
    }
    query.exec(function (err, files) {
        if (err) {
            throw err;
        }
        res.format({
            html: function () {
                res.render('files/index', {files: files, meta: {title: 'Filer'}});
            },
            json: function () {
                res.json(files);
            }
        });
    });
});

router.post('/upload', is_member, function (req, res) {
    var filename = req.files.file.originalname,
        tmp_path = req.files.file.path,
        user = req.user._id,
        tags = req.body.tags;

    if (_.isEmpty(tags)) {
        tags = [];
    }
    var options = {
            permissions: util.parse_web_permissions(req.body.permissions),
            tags: tags
        };

    util.upload_file(tmp_path, filename, user, options, function (err, file) {
        if (err) { throw err; }

        Activity.findOne({
            content_type: 'upload',
            'changes.user': file.creator,
            modified: {$gt: moment(file.created).subtract(10, 'minutes').toDate()},
            project: {$exists: false}
        }, function (err, activity) {

            if (!activity) {
                activity = new Activity();
                activity.content_type = 'upload';
            }

            activity.content_ids.push(file._id);
            activity.title = file.filename;
            activity.changes.push({user: req.user._id, changed: file.created});
            activity.permissions = file.permissions;
            activity.modified = file.created;

            if (file.tags) {
                _.each(file.tags, function (tag) {
                    activity.tags.addToSet(tag);
                });
            }

            if (!activity.content) {
                activity.content = {};
            }

            if (file.is_image) {
                if (!activity.content.images) {
                    activity.content.images = [];
                }
                var image_already_there = _.find(activity.content.images, function (image) {
                    return image.thumbnail_path === file.thumbnail_path;
                });
                if (!image_already_there) {
                    activity.content.images.push({thumbnail_path: file.thumbnail_path, _id: file._id});
                }
            }
            else {
                if (!activity.content.non_images) {
                    activity.content.non_images = [];
                }
                var already_there = _.find(activity.content.non_images, function (non_image) {
                    return non_image.filename === file.filename;
                });
                if (!already_there) {
                    activity.content.non_images.push({filename: file.filename, _id: file._id});
                }
            }
            activity.markModified('content');
            activity.save(function (err) {});
        });

        res.format({
            json: function () {
                file.populate('creator', 'username name', function (err, file) {
                    if (err) { throw err; }
                    res.json(file);
                });
            },
            html: function () {
                res.redirect("/files");
            }
        });
    });
});

router.put('/:id', function (req, res) {
    var id = req.params.id,
        tags = req.body.tags,
        users = [],
        groups = [],
        broadcast = false;

    _.each(req.body.permissions, function (permission) {
        console.log(permission);
    });
    File.findOneAndUpdate({_id: id}, {
        permissions: {
            users: users,
            groups: groups,
            broadcast: broadcast
        },
        tags: tags
    }, function(err, file) {
        if (err) { throw err; }
        console.log(file);
        res.json(file);
    });
});

router.delete('/:id', function (req, res, next) {
    var id = req.params.id;

    File.findByIdAndRemove(id, function (err, file) {
        if (err) { return next(err); }
        Activity.findOneAndRemove({content_type: 'upload', content_id: file._id}, function (err, activity) {});
        res.json(file);
    });
});

router.get('/:id', function (req, res) {
    var query = File.findById(req.params.id);
    if (req.user) {
        query = query.or([
            {creator: req.user._id},
            {'permissions.public': true},
            {'permissions.users': req.user._id},
            {'permissions.groups': { $in: req.user.groups }}
        ]);
    }
    else {
        query = query.where('permissions.public', true);
    }
    query.populate('creator', 'name username').exec(function (err, file) {
        if (!file) {
            res.send(404, 'Not found');
        }
        else {
            res.render('files/show_file', {file: file, meta: {title: file.filename}});
        }
    });
});

router.get('/th/:path/:filename', function (req, res) {
    var filepath = req.params.path,
        filename = req.params.filename,
        fullpath = path.join(config.files.thumbnail_prefix, filepath.substr(0,2), filepath.substr(2,2), filepath);

    fs.exists(fullpath, function (exists) {
        if (exists) {
            res.sendFile(fullpath);
        }
        else {
            res.sendStatus(404);
        }
    });
});

router.get('/n/:path/:filename', function (req, res) {
    var filepath = req.params.path,
        filename = req.params.filename,
        fullpath = path.join(config.files.normal_prefix, filepath.substr(0,2), filepath.substr(2,2), filepath);

    fs.exists(fullpath, function (exists) {
        if (exists) {
            res.sendFile(fullpath);
        }
        else {
            res.sendStatus(404);
        }
    });
});

router.get('/l/:path/:filename', function (req, res) {
    var filepath = req.params.path,
        filename = req.params.filename,
        fullpath = path.join(config.files.large_prefix, filepath.substr(0,2), filepath.substr(2,2), filepath);

    fs.exists(fullpath, function (exists) {
        if (exists) {
            res.sendFile(fullpath);
        }
        else {
            res.sendStatus(404);
        }
    });
});

router.get('/:path/:filename', function (req, res) {
    var filepath = req.params.path,
        filename = req.params.filename,
        fullpath = path.join(config.files.raw_prefix, filepath.substr(0,2), filepath.substr(2,2), filepath);

    fs.exists(fullpath, function (exists) {
        if (exists) {
            res.sendFile(fullpath);
        }
        else {
            res.sendStatus(404);
        }
    });
});

module.exports = router;
<commit_msg>Fix tags on normal file upload<commit_after>var _ = require('underscore'),
    express = require('express'),
    router = express.Router(),
    path = require('path'),
    fs = require('fs'),
    moment= require('moment'),
    mongoose = require('mongoose'),
    util = require('../lib/util'),
    config = require('../settings'),
    is_member = require('../lib/middleware').is_member,
    File = require('../models/files').File,
    Activity = require('../models').Activity;

router.get('/', function (req, res) {
    var query;
    if (req.user) {
        query = File.find().or([
            {creator: req.user._id},
            {'permissions.public': true},
            {'permissions.users': req.user._id},
            {'permissions.groups': { $in: req.user.groups }}
        ]);
    }
    else {
        query = File.find({'permissions.public': true});
    }
    query = query
        .sort('-created')
        .populate('creator', 'username name')
        .limit(20);
    if (req.query.page) {
        query = query.skip(20 * req.query.page);
    }
    query.exec(function (err, files) {
        if (err) {
            throw err;
        }
        res.format({
            html: function () {
                res.render('files/index', {files: files, meta: {title: 'Filer'}});
            },
            json: function () {
                res.json(files);
            }
        });
    });
});

router.get('/t/*', function (req, res) {
    var tagstring = req.params[0];
    var query;
    if (req.user) {
        query = File.find().or([
            {creator: req.user._id},
            {'permissions.public': true},
            {'permissions.users': req.user._id},
            {'permissions.groups': { $in: req.user.groups }}
        ]);
    }
    else {
        query = File.find({'permissions.public': true});
    }

    _.each(tagstring.split("/"), function (tag) {
        query.find({'tags': tag});
    });

    query = query
        .sort('-created')
        .populate('creator', 'username name')
        .limit(20);
    if (req.query.page) {
        query = query.skip(20 * req.query.page);
    }
    query.exec(function (err, files) {
        if (err) {
            throw err;
        }
        res.format({
            html: function () {
                res.render('files/index', {files: files, meta: {title: 'Filer'}});
            },
            json: function () {
                res.json(files);
            }
        });
    });
});

router.post('/upload', is_member, function (req, res) {
    var filename = req.files.file.originalname,
        tmp_path = req.files.file.path,
        user = req.user._id,
        tags = req.body.tags;

    if (_.isEmpty(tags)) {
        tags = [];
    }
    else {
        tags = tags.split(',');
    }

    var options = {
            permissions: util.parse_web_permissions(req.body.permissions),
            tags: tags
        };

    util.upload_file(tmp_path, filename, user, options, function (err, file) {
        if (err) { throw err; }

        Activity.findOne({
            content_type: 'upload',
            'changes.user': file.creator,
            modified: {$gt: moment(file.created).subtract(10, 'minutes').toDate()},
            project: {$exists: false}
        }, function (err, activity) {

            if (!activity) {
                activity = new Activity();
                activity.content_type = 'upload';
            }

            activity.content_ids.push(file._id);
            activity.title = file.filename;
            activity.changes.push({user: req.user._id, changed: file.created});
            activity.permissions = file.permissions;
            activity.modified = file.created;

            if (file.tags) {
                _.each(file.tags, function (tag) {
                    activity.tags.addToSet(tag);
                });
            }

            if (!activity.content) {
                activity.content = {};
            }

            if (file.is_image) {
                if (!activity.content.images) {
                    activity.content.images = [];
                }
                var image_already_there = _.find(activity.content.images, function (image) {
                    return image.thumbnail_path === file.thumbnail_path;
                });
                if (!image_already_there) {
                    activity.content.images.push({thumbnail_path: file.thumbnail_path, _id: file._id});
                }
            }
            else {
                if (!activity.content.non_images) {
                    activity.content.non_images = [];
                }
                var already_there = _.find(activity.content.non_images, function (non_image) {
                    return non_image.filename === file.filename;
                });
                if (!already_there) {
                    activity.content.non_images.push({filename: file.filename, _id: file._id});
                }
            }
            activity.markModified('content');
            activity.save(function (err) {});
        });

        res.format({
            json: function () {
                file.populate('creator', 'username name', function (err, file) {
                    if (err) { throw err; }
                    res.json(file);
                });
            },
            html: function () {
                res.redirect("/files");
            }
        });
    });
});

router.put('/:id', function (req, res) {
    var id = req.params.id,
        tags = req.body.tags,
        users = [],
        groups = [],
        broadcast = false;

    _.each(req.body.permissions, function (permission) {
        console.log(permission);
    });
    File.findOneAndUpdate({_id: id}, {
        permissions: {
            users: users,
            groups: groups,
            broadcast: broadcast
        },
        tags: tags
    }, function(err, file) {
        if (err) { throw err; }
        console.log(file);
        res.json(file);
    });
});

router.delete('/:id', function (req, res, next) {
    var id = req.params.id;

    File.findByIdAndRemove(id, function (err, file) {
        if (err) { return next(err); }
        Activity.findOneAndRemove({content_type: 'upload', content_id: file._id}, function (err, activity) {});
        res.json(file);
    });
});

router.get('/:id', function (req, res) {
    var query = File.findById(req.params.id);
    if (req.user) {
        query = query.or([
            {creator: req.user._id},
            {'permissions.public': true},
            {'permissions.users': req.user._id},
            {'permissions.groups': { $in: req.user.groups }}
        ]);
    }
    else {
        query = query.where('permissions.public', true);
    }
    query.populate('creator', 'name username').exec(function (err, file) {
        if (!file) {
            res.send(404, 'Not found');
        }
        else {
            res.render('files/show_file', {file: file, meta: {title: file.filename}});
        }
    });
});

router.get('/th/:path/:filename', function (req, res) {
    var filepath = req.params.path,
        filename = req.params.filename,
        fullpath = path.join(config.files.thumbnail_prefix, filepath.substr(0,2), filepath.substr(2,2), filepath);

    fs.exists(fullpath, function (exists) {
        if (exists) {
            res.sendFile(fullpath);
        }
        else {
            res.sendStatus(404);
        }
    });
});

router.get('/n/:path/:filename', function (req, res) {
    var filepath = req.params.path,
        filename = req.params.filename,
        fullpath = path.join(config.files.normal_prefix, filepath.substr(0,2), filepath.substr(2,2), filepath);

    fs.exists(fullpath, function (exists) {
        if (exists) {
            res.sendFile(fullpath);
        }
        else {
            res.sendStatus(404);
        }
    });
});

router.get('/l/:path/:filename', function (req, res) {
    var filepath = req.params.path,
        filename = req.params.filename,
        fullpath = path.join(config.files.large_prefix, filepath.substr(0,2), filepath.substr(2,2), filepath);

    fs.exists(fullpath, function (exists) {
        if (exists) {
            res.sendFile(fullpath);
        }
        else {
            res.sendStatus(404);
        }
    });
});

router.get('/:path/:filename', function (req, res) {
    var filepath = req.params.path,
        filename = req.params.filename,
        fullpath = path.join(config.files.raw_prefix, filepath.substr(0,2), filepath.substr(2,2), filepath);

    fs.exists(fullpath, function (exists) {
        if (exists) {
            res.sendFile(fullpath);
        }
        else {
            res.sendStatus(404);
        }
    });
});

module.exports = router;
<|endoftext|>


<commit_before>var express = require('express');
var router = express.Router();
var spark = require('spark');
var Color = require('color');
spark.login({ accessToken: process.env.PARTICLE_ACCESS });

var devicesPr = spark.listDevices();

var pumpkin;

devicesPr.then(
  function(devices){
    pumpkin = devices[4];
  },
  function(err) {
    console.log('List devices call failed: ', err);
  }
);

router.post('/addColor', function(req, res){
  var newColor;

  if(req.body.red){
    newColor = Color().rgb([parseInt(req.body.red, 10), parseInt(req.body.green, 10), parseInt(req.body.blue, 10)]);
  } else if (req.body.hex) {
    newColor = Color(req.body.hex);
  } else {
    newColor = Color(req.body.color);
  }

  var redString = newColor.red().toString(16);
  var greenString = newColor.green().toString(16);
  var blueString = newColor.blue().toString(16);

  if(redString.length === 1){
    redString = '0' + redString;
  }
  if(greenString.length === 1){
    greenString = '0' + greenString;
  }
  if(blueString.length === 1){
    blueString = '0' + blueString;
  }

  pumpkin.callFunction('pixels', 'all|' + redString + greenString + blueString, function(err, data) {
    if (err) {
      res.status(500).send(err);
    } else {
      res.status(200).send(data);
    }
  });
});

/* GET home page. */
router.get('/', function(req, res, next) {
  console.log(req.csurf, req.csrfToken());
  res.render('index', {
    title: 'Front Porch Pumpkin!',
    colors:{
      aliceblue: [240,248,255],
      antiquewhite: [250,235,215],
      aqua: [0,255,255],
      aquamarine: [127,255,212],
      azure:  [240,255,255],
      beccapurple: [102, 51, 153],
      beige:  [245,245,220],
      bisque: [255,228,196],
      black:  [0,0,0],
      blanchedalmond: [255,235,205],
      blue: [0,0,255],
      blueviolet: [138,43,226],
      brown:  [165,42,42],
      burlywood:  [222,184,135],
      cadetblue:  [95,158,160],
      chartreuse: [127,255,0],
      chocolate:  [210,105,30],
      coral:  [255,127,80],
      cornflowerblue: [100,149,237],
      cornsilk: [255,248,220],
      crimson:  [220,20,60],
      cyan: [0,255,255],
      darkblue: [0,0,139],
      darkcyan: [0,139,139],
      darkgoldenrod:  [184,134,11],
      darkgray: [169,169,169],
      darkgreen:  [0,100,0],
      darkgrey: [169,169,169],
      darkkhaki:  [189,183,107],
      darkmagenta:  [139,0,139],
      darkolivegreen: [85,107,47],
      darkorange: [255,140,0],
      darkorchid: [153,50,204],
      darkred:  [139,0,0],
      darksalmon: [233,150,122],
      darkseagreen: [143,188,143],
      darkslateblue:  [72,61,139],
      darkslategray:  [47,79,79],
      darkslategrey:  [47,79,79],
      darkturquoise:  [0,206,209],
      darkviolet: [148,0,211],
      deeppink: [255,20,147],
      deepskyblue:  [0,191,255],
      dimgray:  [105,105,105],
      dimgrey:  [105,105,105],
      dodgerblue: [30,144,255],
      firebrick:  [178,34,34],
      floralwhite:  [255,250,240],
      forestgreen:  [34,139,34],
      fuchsia:  [255,0,255],
      gainsboro:  [220,220,220],
      ghostwhite: [248,248,255],
      gold: [255,215,0],
      goldenrod:  [218,165,32],
      gray: [128,128,128],
      green:  [0,128,0],
      greenyellow:  [173,255,47],
      grey: [128,128,128],
      honeydew: [240,255,240],
      hotpink:  [255,105,180],
      indianred:  [205,92,92],
      indigo: [75,0,130],
      ivory:  [255,255,240],
      khaki:  [240,230,140],
      lavender: [230,230,250],
      lavenderblush:  [255,240,245],
      lawngreen:  [124,252,0],
      lemonchiffon: [255,250,205],
      lightblue:  [173,216,230],
      lightcoral: [240,128,128],
      lightcyan:  [224,255,255],
      lightgoldenrodyellow: [250,250,210],
      lightgray:  [211,211,211],
      lightgreen: [144,238,144],
      lightgrey:  [211,211,211],
      lightpink:  [255,182,193],
      lightsalmon:  [255,160,122],
      lightseagreen:  [32,178,170],
      lightskyblue: [135,206,250],
      lightslategray: [119,136,153],
      lightslategrey: [119,136,153],
      lightsteelblue: [176,196,222],
      lightyellow:  [255,255,224],
      lime: [0,255,0],
      limegreen:  [50,205,50],
      linen:  [250,240,230],
      magenta:  [255,0,255],
      maroon: [128,0,0],
      mediumaquamarine: [102,205,170],
      mediumblue: [0,0,205],
      mediumorchid: [186,85,211],
      mediumpurple: [147,112,219],
      mediumseagreen: [60,179,113],
      mediumslateblue:  [123,104,238],
      mediumspringgreen:  [0,250,154],
      mediumturquoise:  [72,209,204],
      mediumvioletred:  [199,21,133],
      midnightblue: [25,25,112],
      mintcream:  [245,255,250],
      mistyrose:  [255,228,225],
      moccasin: [255,228,181],
      navajowhite:  [255,222,173],
      navy: [0,0,128],
      oldlace:  [253,245,230],
      olive:  [128,128,0],
      olivedrab:  [107,142,35],
      orange: [255,165,0],
      orangered:  [255,69,0],
      orchid: [218,112,214],
      palegoldenrod:  [238,232,170],
      palegreen:  [152,251,152],
      paleturquoise:  [175,238,238],
      palevioletred:  [219,112,147],
      papayawhip: [255,239,213],
      peachpuff:  [255,218,185],
      peru: [205,133,63],
      pink: [255,192,203],
      plum: [221,160,221],
      powderblue: [176,224,230],
      purple: [128,0,128],
      rebeccapurple: [102, 51, 153],
      red:  [255,0,0],
      rosybrown:  [188,143,143],
      royalblue:  [65,105,225],
      saddlebrown:  [139,69,19],
      salmon: [250,128,114],
      sandybrown: [244,164,96],
      seagreen: [46,139,87],
      seashell: [255,245,238],
      sienna: [160,82,45],
      silver: [192,192,192],
      skyblue:  [135,206,235],
      slateblue:  [106,90,205],
      slategray:  [112,128,144],
      slategrey:  [112,128,144],
      snow: [255,250,250],
      springgreen:  [0,255,127],
      steelblue:  [70,130,180],
      tan:  [210,180,140],
      teal: [0,128,128],
      thistle:  [216,191,216],
      tomato: [255,99,71],
      turquoise:  [64,224,208],
      violet: [238,130,238],
      wheat:  [245,222,179],
      white:  [255,255,255],
      whitesmoke: [245,245,245],
      yellow: [255,255,0],
      yellowgreen:  [154,205,50]
    },
    csrfToken: req.csrfToken()
  });
});

module.exports = router;
<commit_msg>Added beccapurple<commit_after>var express = require('express');
var router = express.Router();
var spark = require('spark');
var Color = require('color');
spark.login({ accessToken: process.env.PARTICLE_ACCESS });

var devicesPr = spark.listDevices();

var pumpkin;

devicesPr.then(
  function(devices){
    pumpkin = devices[4];
  },
  function(err) {
    console.log('List devices call failed: ', err);
  }
);

router.post('/addColor', function(req, res){
  var newColor;

  if(req.body.red){
    newColor = Color().rgb([parseInt(req.body.red, 10), parseInt(req.body.green, 10), parseInt(req.body.blue, 10)]);
  } else if (req.body.hex) {
    newColor = Color(req.body.hex);
  } else {
    if(req.body.color == 'beccapurple'){
      newColor = Color().rgb([102, 51, 153]);
    } else {
      newColor = Color(req.body.color);
    }
  }

  var redString = newColor.red().toString(16);
  var greenString = newColor.green().toString(16);
  var blueString = newColor.blue().toString(16);

  if(redString.length === 1){
    redString = '0' + redString;
  }
  if(greenString.length === 1){
    greenString = '0' + greenString;
  }
  if(blueString.length === 1){
    blueString = '0' + blueString;
  }

  pumpkin.callFunction('pixels', 'all|' + redString + greenString + blueString, function(err, data) {
    if (err) {
      res.status(500).send(err);
    } else {
      res.status(200).send(data);
    }
  });
});

/* GET home page. */
router.get('/', function(req, res, next) {
  console.log(req.csurf, req.csrfToken());
  res.render('index', {
    title: 'Front Porch Pumpkin!',
    colors:{
      aliceblue: [240,248,255],
      antiquewhite: [250,235,215],
      aqua: [0,255,255],
      aquamarine: [127,255,212],
      azure:  [240,255,255],
      beccapurple: [102, 51, 153],
      beige:  [245,245,220],
      bisque: [255,228,196],
      black:  [0,0,0],
      blanchedalmond: [255,235,205],
      blue: [0,0,255],
      blueviolet: [138,43,226],
      brown:  [165,42,42],
      burlywood:  [222,184,135],
      cadetblue:  [95,158,160],
      chartreuse: [127,255,0],
      chocolate:  [210,105,30],
      coral:  [255,127,80],
      cornflowerblue: [100,149,237],
      cornsilk: [255,248,220],
      crimson:  [220,20,60],
      cyan: [0,255,255],
      darkblue: [0,0,139],
      darkcyan: [0,139,139],
      darkgoldenrod:  [184,134,11],
      darkgray: [169,169,169],
      darkgreen:  [0,100,0],
      darkgrey: [169,169,169],
      darkkhaki:  [189,183,107],
      darkmagenta:  [139,0,139],
      darkolivegreen: [85,107,47],
      darkorange: [255,140,0],
      darkorchid: [153,50,204],
      darkred:  [139,0,0],
      darksalmon: [233,150,122],
      darkseagreen: [143,188,143],
      darkslateblue:  [72,61,139],
      darkslategray:  [47,79,79],
      darkslategrey:  [47,79,79],
      darkturquoise:  [0,206,209],
      darkviolet: [148,0,211],
      deeppink: [255,20,147],
      deepskyblue:  [0,191,255],
      dimgray:  [105,105,105],
      dimgrey:  [105,105,105],
      dodgerblue: [30,144,255],
      firebrick:  [178,34,34],
      floralwhite:  [255,250,240],
      forestgreen:  [34,139,34],
      fuchsia:  [255,0,255],
      gainsboro:  [220,220,220],
      ghostwhite: [248,248,255],
      gold: [255,215,0],
      goldenrod:  [218,165,32],
      gray: [128,128,128],
      green:  [0,128,0],
      greenyellow:  [173,255,47],
      grey: [128,128,128],
      honeydew: [240,255,240],
      hotpink:  [255,105,180],
      indianred:  [205,92,92],
      indigo: [75,0,130],
      ivory:  [255,255,240],
      khaki:  [240,230,140],
      lavender: [230,230,250],
      lavenderblush:  [255,240,245],
      lawngreen:  [124,252,0],
      lemonchiffon: [255,250,205],
      lightblue:  [173,216,230],
      lightcoral: [240,128,128],
      lightcyan:  [224,255,255],
      lightgoldenrodyellow: [250,250,210],
      lightgray:  [211,211,211],
      lightgreen: [144,238,144],
      lightgrey:  [211,211,211],
      lightpink:  [255,182,193],
      lightsalmon:  [255,160,122],
      lightseagreen:  [32,178,170],
      lightskyblue: [135,206,250],
      lightslategray: [119,136,153],
      lightslategrey: [119,136,153],
      lightsteelblue: [176,196,222],
      lightyellow:  [255,255,224],
      lime: [0,255,0],
      limegreen:  [50,205,50],
      linen:  [250,240,230],
      magenta:  [255,0,255],
      maroon: [128,0,0],
      mediumaquamarine: [102,205,170],
      mediumblue: [0,0,205],
      mediumorchid: [186,85,211],
      mediumpurple: [147,112,219],
      mediumseagreen: [60,179,113],
      mediumslateblue:  [123,104,238],
      mediumspringgreen:  [0,250,154],
      mediumturquoise:  [72,209,204],
      mediumvioletred:  [199,21,133],
      midnightblue: [25,25,112],
      mintcream:  [245,255,250],
      mistyrose:  [255,228,225],
      moccasin: [255,228,181],
      navajowhite:  [255,222,173],
      navy: [0,0,128],
      oldlace:  [253,245,230],
      olive:  [128,128,0],
      olivedrab:  [107,142,35],
      orange: [255,165,0],
      orangered:  [255,69,0],
      orchid: [218,112,214],
      palegoldenrod:  [238,232,170],
      palegreen:  [152,251,152],
      paleturquoise:  [175,238,238],
      palevioletred:  [219,112,147],
      papayawhip: [255,239,213],
      peachpuff:  [255,218,185],
      peru: [205,133,63],
      pink: [255,192,203],
      plum: [221,160,221],
      powderblue: [176,224,230],
      purple: [128,0,128],
      rebeccapurple: [102, 51, 153],
      red:  [255,0,0],
      rosybrown:  [188,143,143],
      royalblue:  [65,105,225],
      saddlebrown:  [139,69,19],
      salmon: [250,128,114],
      sandybrown: [244,164,96],
      seagreen: [46,139,87],
      seashell: [255,245,238],
      sienna: [160,82,45],
      silver: [192,192,192],
      skyblue:  [135,206,235],
      slateblue:  [106,90,205],
      slategray:  [112,128,144],
      slategrey:  [112,128,144],
      snow: [255,250,250],
      springgreen:  [0,255,127],
      steelblue:  [70,130,180],
      tan:  [210,180,140],
      teal: [0,128,128],
      thistle:  [216,191,216],
      tomato: [255,99,71],
      turquoise:  [64,224,208],
      violet: [238,130,238],
      wheat:  [245,222,179],
      white:  [255,255,255],
      whitesmoke: [245,245,245],
      yellow: [255,255,0],
      yellowgreen:  [154,205,50]
    },
    csrfToken: req.csrfToken()
  });
});

module.exports = router;
<|endoftext|>


<commit_before>/*
 * ChanChan Orion REST API
 */

var utils = require('../utils');
var orion_url = "orion"; // To be changed to PEP for auth

// Return the list of available entities in Orion
exports.contexts = function(req, res) {
    // TODO: Check auth
    // Is it possible to get all contexts from the API?
    // Right now we get all contexts from a type
    contextType = "Room";

    return_get = function(res, buffer) {
        res.send(buffer);
    };

    var options = {
        host: orion_url,
        port: 10026,
        path: '/NGSI10/contextEntityTypes/'+contextType,
        method: 'GET',
        headers: {
            accept: 'application/json'
        }
    };

    utils.do_get(options, return_get, res);
};

//Create a new Context subscription in CKAN for an organization
exports.subscribe_context = function(req, res) {
  return_post = function(res, buffer, headers) {
      res.send(buffer);
  };

  var cygnus_ckan_url = "http://localhost";
  var org_id = req.params.org_id;
  var context_id = req.params.context_id;
  var org_port;

    if (org_id == "org_a" || org_id == "organization_a") {
      org_port = "5001";
  } else if (org_id == "org_b" || org_id == "organizatiob_b") {
      org_port = "5002";
  } else {
      res.status(404);
      res.send(err.message || "Org " + org_id + " not found.");
      return;
  }

  post_data = {
      "entities": [
           {
               "type": context_id,
               "isPattern": "false",
               "id": "FirstEntity"
           }
       ],
       "attributes": [
           "temperature"
       ],
       "reference": cygnus_ckan_url + ":" + org_port +"/notify",
       "duration": "P1M",
       "notifyConditions": [
           {
               "type": "ONCHANGE",
               "condValues": [
                   "pressure"
               ]
           }
       ],
       "throttling": "PT1S"
  };

  post_data = JSON.stringify(post_data);

  headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Content-Length': Buffer.byteLength(post_data)
  };

  var options = {
      host: orion_url,
      port: 10026,
      path: '/NGSI10/subscribeContext',
      method: 'POST',
      headers: headers
  };

  utils.do_post(options, post_data, return_post, res);
};

// Update entities data (temperature)
exports.update_context_temperature = function(req, res) {
  return_post = function(res, buffer, headers) {
      res.send(buffer);
  };

  var org_id = req.params.org_id;
  var context_id = req.params.context_id;
  var temperature_id = req.params.temperature_id;

    post_data = {
        "contextElements": [
                {
                    "type": org_id,
                    "isPattern": "false",
                    "id": context_id,
                    "attributes": [
                    {
                        "name": "temperature",
                        "type": "centigrade",
                        "value": temperature_id
                    },
                    {
                        "name": "pressure",
                        "type": "mmHg",
                        "value": "720"
                    }
                    ]
                }
            ],
            "updateAction": "APPEND"
    };

  post_data = JSON.stringify(post_data);

  headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Content-Length': Buffer.byteLength(post_data)
  };

  var options = {
      host: orion_url,
      port: 10026,
      path: '/NGSI10/updateContext',
      method: 'POST',
      headers: headers
  };

  utils.do_post(options, post_data, return_post, res);
};

function get_orion_items(type, restaurant_name_regexp, req, res) {
    return_post = function(res, buffer, headers) {
        res.send(unescape(buffer));
    };

    var name = restaurant_name_regexp;
    var orion_url = "orion";
    var orion_port = 10026;
    var orion_res_limit = 1000; // Max orion items to avoid pagination

    post_data = {
          "entities": [
           {
               "type": type,
               "isPattern": "true",
               "id": ".*"+name+".*"
           }]
    };

    // In geoqueries we get: lat=<lat>&long=<long>&radius=<radius>

    if (req.query.lat !== undefined && req.query.long !== undefined &&
        req.query.radius !== undefined) {

        console.log("GEO query")

        post_data ["restriction"] = {
            "scopes": [
               {
                 "type" : "FIWARE::Location",
                 "value" : {
                   "circle": {
                     "centerLatitude": req.query.lat,
                     "centerLongitude": req.query.long,
                     "radius": req.query.radius
                   }
                 }
               }
           ]
        }
    }

    if (name === undefined) {
        // Get all restaurants
        post_data.entities[0].id=".*";
    }

    post_data = JSON.stringify(post_data);

    headers = {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Content-Length': Buffer.byteLength(post_data)
    };

    var options = {
        host: orion_url,
        port: orion_port,
        path: '/NGSI10/queryContext?limit='+orion_res_limit,
        method: 'POST',
        headers: headers
    };

    utils.do_post(options, post_data, return_post, res);
}

// Find the restaurants given a name
exports.get_restaurants = function(req, res) {
    get_orion_items("restaurant", req.params.name, req, res);
};

// Find the reviews given a restaurant name regexp
exports.get_reviews = function(req, res) {
    get_orion_items("review", req.params.name, req, res);
};

// Find the reservations given a restaurant name regexp
exports.get_reservations = function(req, res) {
    get_orion_items("reservation", req.params.name, req, res);
};

// Update entities in orion
exports.update_entities = function(req, res) {
  return_post = function(res, buffer, headers) {
      res.send(buffer);
  };

  var org_id = req.params.org_id;
  var post_data = JSON.stringify(req.body);

  headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Content-Length': Buffer.byteLength(post_data)
  };

  var options = {
      host: orion_url,
      port: 10026,
      path: '/NGSI10/updateContext',
      method: 'POST',
      headers: headers
  };

  utils.do_post(options, post_data, return_post, res);
};
<commit_msg>Add 'Content-Type: application/json' header when returning JSON data from orion.<commit_after>/*
 * ChanChan Orion REST API
 */

var utils = require('../utils');
var orion_url = "orion"; // To be changed to PEP for auth

// Return the list of available entities in Orion
exports.contexts = function(req, res) {
    // TODO: Check auth
    // Is it possible to get all contexts from the API?
    // Right now we get all contexts from a type
    contextType = "Room";

    return_get = function(res, buffer) {
        res.send(buffer);
    };

    var options = {
        host: orion_url,
        port: 10026,
        path: '/NGSI10/contextEntityTypes/'+contextType,
        method: 'GET',
        headers: {
            accept: 'application/json'
        }
    };

    utils.do_get(options, return_get, res);
};

//Create a new Context subscription in CKAN for an organization
exports.subscribe_context = function(req, res) {
  return_post = function(res, buffer, headers) {
      res.send(buffer);
  };

  var cygnus_ckan_url = "http://localhost";
  var org_id = req.params.org_id;
  var context_id = req.params.context_id;
  var org_port;

    if (org_id == "org_a" || org_id == "organization_a") {
      org_port = "5001";
  } else if (org_id == "org_b" || org_id == "organizatiob_b") {
      org_port = "5002";
  } else {
      res.status(404);
      res.send(err.message || "Org " + org_id + " not found.");
      return;
  }

  post_data = {
      "entities": [
           {
               "type": context_id,
               "isPattern": "false",
               "id": "FirstEntity"
           }
       ],
       "attributes": [
           "temperature"
       ],
       "reference": cygnus_ckan_url + ":" + org_port +"/notify",
       "duration": "P1M",
       "notifyConditions": [
           {
               "type": "ONCHANGE",
               "condValues": [
                   "pressure"
               ]
           }
       ],
       "throttling": "PT1S"
  };

  post_data = JSON.stringify(post_data);

  headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Content-Length': Buffer.byteLength(post_data)
  };

  var options = {
      host: orion_url,
      port: 10026,
      path: '/NGSI10/subscribeContext',
      method: 'POST',
      headers: headers
  };

  utils.do_post(options, post_data, return_post, res);
};

// Update entities data (temperature)
exports.update_context_temperature = function(req, res) {
  return_post = function(res, buffer, headers) {
      res.send(buffer);
  };

  var org_id = req.params.org_id;
  var context_id = req.params.context_id;
  var temperature_id = req.params.temperature_id;

    post_data = {
        "contextElements": [
                {
                    "type": org_id,
                    "isPattern": "false",
                    "id": context_id,
                    "attributes": [
                    {
                        "name": "temperature",
                        "type": "centigrade",
                        "value": temperature_id
                    },
                    {
                        "name": "pressure",
                        "type": "mmHg",
                        "value": "720"
                    }
                    ]
                }
            ],
            "updateAction": "APPEND"
    };

  post_data = JSON.stringify(post_data);

  headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Content-Length': Buffer.byteLength(post_data)
  };

  var options = {
      host: orion_url,
      port: 10026,
      path: '/NGSI10/updateContext',
      method: 'POST',
      headers: headers
  };

  utils.do_post(options, post_data, return_post, res);
};

function get_orion_items(type, restaurant_name_regexp, req, res) {
    return_post = function(res, buffer, headers) {
        res.setHeader('Content-Type', 'application/json');
        res.send(unescape(buffer));
    };

    var name = restaurant_name_regexp;
    var orion_url = "orion";
    var orion_port = 10026;
    var orion_res_limit = 1000; // Max orion items to avoid pagination

    post_data = {
          "entities": [
           {
               "type": type,
               "isPattern": "true",
               "id": ".*"+name+".*"
           }]
    };

    // In geoqueries we get: lat=<lat>&long=<long>&radius=<radius>

    if (req.query.lat !== undefined && req.query.long !== undefined &&
        req.query.radius !== undefined) {

        console.log("GEO query")

        post_data ["restriction"] = {
            "scopes": [
               {
                 "type" : "FIWARE::Location",
                 "value" : {
                   "circle": {
                     "centerLatitude": req.query.lat,
                     "centerLongitude": req.query.long,
                     "radius": req.query.radius
                   }
                 }
               }
           ]
        }
    }

    if (name === undefined) {
        // Get all restaurants
        post_data.entities[0].id=".*";
    }

    post_data = JSON.stringify(post_data);

    headers = {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Content-Length': Buffer.byteLength(post_data)
    };

    var options = {
        host: orion_url,
        port: orion_port,
        path: '/NGSI10/queryContext?limit='+orion_res_limit,
        method: 'POST',
        headers: headers
    };

    utils.do_post(options, post_data, return_post, res);
}

// Find the restaurants given a name
exports.get_restaurants = function(req, res) {
    get_orion_items("restaurant", req.params.name, req, res);
};

// Find the reviews given a restaurant name regexp
exports.get_reviews = function(req, res) {
    get_orion_items("review", req.params.name, req, res);
};

// Find the reservations given a restaurant name regexp
exports.get_reservations = function(req, res) {
    get_orion_items("reservation", req.params.name, req, res);
};

// Update entities in orion
exports.update_entities = function(req, res) {
  return_post = function(res, buffer, headers) {
      res.send(buffer);
  };

  var org_id = req.params.org_id;
  var post_data = JSON.stringify(req.body);

  headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Content-Length': Buffer.byteLength(post_data)
  };

  var options = {
      host: orion_url,
      port: 10026,
      path: '/NGSI10/updateContext',
      method: 'POST',
      headers: headers
  };

  utils.do_post(options, post_data, return_post, res);
};
<|endoftext|>


<commit_before>(function(window) {
    'use strict';

    /**
     * Phune Gaming SDK providing all platform related functionality.
     *
     * @constructor
     */
    var PG = function() {

        var origin = (window.location.origin) ? window.location.origin : document.location.protocol + '//' + document.location.host,
            message, lastMessage = null,
            player, opponent;

        /**
         * Get the game results with the correct value based on the winnerPlayerId param.
         *
         * @private
         * @param {number} winnerPlayerId The id of the player that won the match.
         * @returns {string} A game result valid value.
         */
        var getGameResults = function(winnerPlayerId) {
            var gameResults;

            if (typeof winnerPlayerId !== 'undefined') {
                if (winnerPlayerId === 0) {
                    gameResults = 'draw';
                } else if (winnerPlayerId === player.id) {
                    gameResults = 'won';
                } else {
                    gameResults = 'lost';
                }
            }

            return gameResults;
        };

        /**
         * The game should build the user interface and get ready to start playing.
         *
         * @abstract
         * @param {Object} player Current player details.
         * @param {Object} opponent Opponent details.
         * @param {number} timeToPlay Time allowed for the player to make a move.
         */
        var onMatchPrepare = function(player, opponent, timeToPlay) {
            throw new Error('onMatchPrepare is not implemented.');
        };

        /**
         * The match start confirmation. Only now is the player allowed to play the game.
         *
         * @abstract
         * @param {boolean} playerIdToPlayNext The identifier of the player to whom the next move belongs.
         */
        var onMatchStart = function(playerIdToPlayNext) {
            throw new Error('onMatchStart is not implemented.');
        };

        /**
         * Acknowledgment to a valid move.
         *
         * @abstract
         * @param {boolean} playerIdWhoSentTheMove The identifier of the player that sent the move.
         * @param {boolean} playerToPlayNext The identifier of the player to whom the next move belongs.
         * @param {Object} moveDetails The move details.
         * @param {Object} moveResults The results of the move validation.
         * @param {string} [gameResults] If the move ended the game, this indicates its results. Possible values are 'won', 'lost', and 'draw'.
         */
        var onMoveValid = function(playerIdWhoSentTheMove, playerToPlayNext, moveDetails, moveResults, gameResults) {
            throw new Error('onMoveValid is not implemented.');
        };

        /**
         * Acknowledgment to an invalid move.
         *
         * @abstract
         * @param {boolean} playerIdWhoSentTheMove The identifier of the player that sent the move.
         * @param {boolean} playerToPlayNext The identifier of the player to whom the next move belongs.
         */
        var onMoveInvalid = function(playerIdWhoSentTheMove, playerToPlayNext) {
            throw new Error('onMoveInvalid is not implemented.');
        };

        /**
         * Called by the platform when a match end event is received.
         *
         * @abstract
         * @param {string} gameResults The game results. Possible values are 'won', 'lost', and 'draw'.
         */
        var onMatchEnd = function(gameResults) {
            throw new Error('onMatchEnd is not implemented.');
        };

        /**
         * A message from the server-side rules was received.
         *
         * @abstract
         * @param {boolean} playerWhoSentTheMessage The identifier of the player that sent the message.
         * @param {Object} messageDetails Message specific to a game and unknown to the platform. The developer is advised to have multiple message types with different bodies in order to achieve different goals.
         * @param {Object} messageResults The result returned by the server-side rules.
         */
        var onServerMessage = function(playerIdWhoSentTheMessage, messageDetails, messageResults) {
            throw new Error('onServerMessage is not implemented.');
        };

        /**
         * A message sent directly from another player was received.
         *
         * @abstract
         * @param {Object} messageDetails Message specific to a game and unknown to the platform. The developer is advised to have multiple message types with different bodies in order to achieve different goals.
         */
        var onPlayerMessage = function(messageDetails) {
            throw new Error('onPlayerMessage is not implemented.');
        };

        /**
         * A keyboard or TV remote control key was pressed.
         *
         * @abstract
         * @param {string} key The key that was pressed. Possible values are 'left', 'right', 'up', 'down', and 'enter'.
         */
        var onKeyPress = function(key) {
            throw new Error('onKeyPress is not implemented.');
        };

        return {
            /**
             * Initialize the Phune Gaming SDK.
             *
             * @param {Object} params Object containing all the options to configure the SDK. This includes the mandatory callback functions: onMatchPrepare, onMatchStart, onMoveValid, onMoveInvalid, onMatchEnd, and the optional callback functions: onServerMessage, onPlayerMessage, and onKeyPress.
             */
            init: function(params) {
                onMatchPrepare = params.onMatchPrepare || onMatchPrepare;
                onMatchStart = params.onMatchStart || onMatchStart;
                onMoveValid = params.onMoveValid || onMoveValid;
                onMoveInvalid = params.onMoveInvalid || onMoveInvalid;
                onMatchEnd = params.onMatchEnd || onMatchEnd;
                onServerMessage = params.onServerMessage || onServerMessage;
                onPlayerMessage = params.onPlayerMessage || onPlayerMessage;
                onKeyPress = params.onKeyPress || onKeyPress;

                window.addEventListener('message', function(msg) {
                    if (msg.origin !== origin) {
                        console.warn('Origin not recognized: ' + msg.origin);
                        return;
                    }
                    switch (msg.data.type) {
                    case 'matchPrepare':
                        player = msg.data.player;
                        opponent = msg.data.opponent;
                        onMatchPrepare(player, opponent, msg.data.moveTimeout);
                        break;
                    case 'matchStart':
                        onMatchStart(msg.data.nextPlayerId);
                        break;
                    case 'matchMoveValid':
                        onMoveValid(msg.data.playerId, msg.data.nextPlayerId, msg.data.content, msg.data.evaluationContent, getGameResults(msg.data.winnerPlayerId));
                        break;
                    case 'matchMoveInvalid':
                        onMoveInvalid(msg.data.playerId, msg.data.nextPlayerId);
                        break;
                    case 'matchEnd':
                        onMatchEnd(getGameResults(msg.data.winnerPlayerId));
                        break;
                    case 'serverMessage':
                        onServerMessage(msg.data.playerId, msg.data.content, msg.data.result);
                        break;
                    case 'playerMessage':
                        onPlayerMessage(msg.data.content);
                        break;
                    case 'keyPress':
                        onKeyPress(msg.data.value);
                        break;
                    }
                });

                // Inform the platform that the game loaded successfully.
                window.parent.postMessage({
                    type: 'loaded'
                }, origin);
            },

            /**
             * This function can be used optionally before calling PG.ready() which initiates the match.
             * It can be used to show the game screen to the user before the match starts. Allowing the player to configure the game on the server which will broadcast those configurations to the other players.
             */
            prepared: function() {
                window.parent.postMessage({
                    type: 'prepared'
                }, origin);
            },

            /**
             * Informs the server that the client is ready to start the match.
             */
            ready: function() {
                window.parent.postMessage({
                    type: 'ready'
                }, origin);
            },

            /**
             * Send a move to the platform server.
             *
             * @param {Object} moveDetails The move details.
             * @param {function(Object): boolean} [validate] Optional function to validate the move before sending it to server.
             * @returns {boolean} True when the move is valid or when no validation function was provided.
             */
            move: function(moveDetails, validate) {
                if (validate && !validate(moveDetails)) {
                    return false;
                }

                window.parent.postMessage({
                    type: 'move',
                    content: moveDetails
                }, origin);

                return true;
            },

            /**
             * Asks the platform to show the game menu.
             */
            showMenu: function() {
                window.parent.postMessage({
                    type: 'showMenu'
                }, origin);
            },

            /**
             * Send a message to the server-side rules. This message is specific to a game and will not be processed by the platform itself.
             * The response from the server could either be sent to you only or to all players.
             *
             * @param {Object} messageDetails The content of the message to be sent.
             * @param {boolean} isAnswerPublic Whether the reply from the server's rules should be sent to all players or not.
             * @param {boolean} [serializeRequest] Whether the messages should be processed in order of arrival or can be executed in parallel.
             */
            serverMessage: function(messageDetails, isAnswerPublic, serializeRequest) {
                window.parent.postMessage({
                    type: 'serverMessage',
                    publicAnswer: isAnswerPublic,
                    requiresConcurrencyControl: (serializeRequest) ? serializeRequest : true,
                    content: messageDetails
                }, origin);
            },

            /**
             * Peer-to-peer message sent directly to another player.
             *
             * @param {Object} messageDetails The content of the message to be sent.
             * @param {number} [sendTimeIntervalLimit] Do not allow sending more than one message within the specified time in milliseconds.
             *                 If this is called more than once during this interval only the last message will be sent.
             */
            playerMessage: function(messageDetails, sendTimeIntervalLimit) {
                if (!sendTimeIntervalLimit || lastMessage === null) {
                    message = {
                        type: 'playerMessage',
                        content: messageDetails
                    };
                    window.parent.postMessage(message, origin);

                    if (sendTimeIntervalLimit) {
                        setTimeout(function() {
                            if (lastMessage !== message) {
                                message = lastMessage;
                                lastMessage = null;
                                window.parent.postMessage(message, origin);
                            } else {
                                lastMessage = null;
                            }
                        }, sendTimeIntervalLimit);
                    }
                }
                if (sendTimeIntervalLimit) {
                    lastMessage = message;
                }
            }
        };
    };
    window.PG = new PG();

}(window));
<commit_msg>Add enum for game result values<commit_after>(function(window) {
    'use strict';

    /**
     * Phune Gaming SDK providing all platform related functionality.
     *
     * @constructor
     */
    var PG = function() {

        var origin = (window.location.origin) ? window.location.origin : document.location.protocol + '//' + document.location.host,
            result = {
                WON: 'won',
                LOST: 'lost',
                DRAW: 'draw'
            },
            message, lastMessage = null,
            player, opponent;

        /**
         * Get the game results with the correct value based on the winnerPlayerId param.
         *
         * @private
         * @param {number} winnerPlayerId The id of the player that won the match.
         * @returns {string} A game result valid value.
         */
        var getGameResult = function(winnerPlayerId) {
            if (typeof winnerPlayerId === 'undefined') {
                throw new Error('The "winnerPlayerId" parameter is missing or is empty');
            }

            if (winnerPlayerId === player.id) {
                return result.WON;
            } else if (winnerPlayerId === opponent.id) {
                return result.LOST;
            }

            return result.DRAW;
        };

        /**
         * The game should build the user interface and get ready to start playing.
         *
         * @abstract
         * @param {Object} player Current player details.
         * @param {Object} opponent Opponent details.
         * @param {number} timeToPlay Time allowed for the player to make a move.
         */
        var onMatchPrepare = function(player, opponent, timeToPlay) {
            throw new Error('onMatchPrepare is not implemented.');
        };

        /**
         * The match start confirmation. Only now is the player allowed to play the game.
         *
         * @abstract
         * @param {boolean} playerIdToPlayNext The identifier of the player to whom the next move belongs.
         */
        var onMatchStart = function(playerIdToPlayNext) {
            throw new Error('onMatchStart is not implemented.');
        };

        /**
         * Acknowledgment to a valid move.
         *
         * @abstract
         * @param {boolean} playerIdWhoSentTheMove The identifier of the player that sent the move.
         * @param {boolean} playerToPlayNext The identifier of the player to whom the next move belongs.
         * @param {Object} moveDetails The move details.
         * @param {Object} moveResults The results of the move validation.
         * @param {string} [gameResult] If the move ended the game, this indicates its results. Possible values are 'won', 'lost', and 'draw'.
         */
        var onMoveValid = function(playerIdWhoSentTheMove, playerToPlayNext, moveDetails, moveResults, gameResult) {
            throw new Error('onMoveValid is not implemented.');
        };

        /**
         * Acknowledgment to an invalid move.
         *
         * @abstract
         * @param {boolean} playerIdWhoSentTheMove The identifier of the player that sent the move.
         * @param {boolean} playerToPlayNext The identifier of the player to whom the next move belongs.
         */
        var onMoveInvalid = function(playerIdWhoSentTheMove, playerToPlayNext) {
            throw new Error('onMoveInvalid is not implemented.');
        };

        /**
         * Called by the platform when a match end event is received.
         *
         * @abstract
         * @param {string} gameResult The game results. Possible values are 'won', 'lost', and 'draw'.
         */
        var onMatchEnd = function(gameResult) {
            throw new Error('onMatchEnd is not implemented.');
        };

        /**
         * A message from the server-side rules was received.
         *
         * @abstract
         * @param {boolean} playerWhoSentTheMessage The identifier of the player that sent the message.
         * @param {Object} messageDetails Message specific to a game and unknown to the platform. The developer is advised to have multiple message types with different bodies in order to achieve different goals.
         * @param {Object} messageResults The result returned by the server-side rules.
         */
        var onServerMessage = function(playerIdWhoSentTheMessage, messageDetails, messageResults) {
            throw new Error('onServerMessage is not implemented.');
        };

        /**
         * A message sent directly from another player was received.
         *
         * @abstract
         * @param {Object} messageDetails Message specific to a game and unknown to the platform. The developer is advised to have multiple message types with different bodies in order to achieve different goals.
         */
        var onPlayerMessage = function(messageDetails) {
            throw new Error('onPlayerMessage is not implemented.');
        };

        /**
         * A keyboard or TV remote control key was pressed.
         *
         * @abstract
         * @param {string} key The key that was pressed. Possible values are 'left', 'right', 'up', 'down', and 'enter'.
         */
        var onKeyPress = function(key) {
            throw new Error('onKeyPress is not implemented.');
        };

        return {
            /**
             * Initialize the Phune Gaming SDK.
             *
             * @param {Object} params Object containing all the options to configure the SDK. This includes the mandatory callback functions: onMatchPrepare, onMatchStart, onMoveValid, onMoveInvalid, onMatchEnd, and the optional callback functions: onServerMessage, onPlayerMessage, and onKeyPress.
             */
            init: function(params) {
                onMatchPrepare = params.onMatchPrepare || onMatchPrepare;
                onMatchStart = params.onMatchStart || onMatchStart;
                onMoveValid = params.onMoveValid || onMoveValid;
                onMoveInvalid = params.onMoveInvalid || onMoveInvalid;
                onMatchEnd = params.onMatchEnd || onMatchEnd;
                onServerMessage = params.onServerMessage || onServerMessage;
                onPlayerMessage = params.onPlayerMessage || onPlayerMessage;
                onKeyPress = params.onKeyPress || onKeyPress;

                window.addEventListener('message', function(msg) {
                    if (msg.origin !== origin) {
                        console.warn('Origin not recognized: ' + msg.origin);
                        return;
                    }
                    switch (msg.data.type) {
                    case 'matchPrepare':
                        player = msg.data.player;
                        opponent = msg.data.opponent;
                        onMatchPrepare(player, opponent, msg.data.moveTimeout);
                        break;
                    case 'matchStart':
                        onMatchStart(msg.data.nextPlayerId);
                        break;
                    case 'matchMoveValid':
                        onMoveValid(msg.data.playerId, msg.data.nextPlayerId, msg.data.content, msg.data.evaluationContent, getGameResult(msg.data.winnerPlayerId));
                        break;
                    case 'matchMoveInvalid':
                        onMoveInvalid(msg.data.playerId, msg.data.nextPlayerId);
                        break;
                    case 'matchEnd':
                        onMatchEnd(getGameResult(msg.data.winnerPlayerId));
                        break;
                    case 'serverMessage':
                        onServerMessage(msg.data.playerId, msg.data.content, msg.data.result);
                        break;
                    case 'playerMessage':
                        onPlayerMessage(msg.data.content);
                        break;
                    case 'keyPress':
                        onKeyPress(msg.data.value);
                        break;
                    }
                });

                // Inform the platform that the game loaded successfully.
                window.parent.postMessage({
                    type: 'loaded'
                }, origin);
            },

            /**
             * This function can be used optionally before calling PG.ready() which initiates the match.
             * It can be used to show the game screen to the user before the match starts. Allowing the player to configure the game on the server which will broadcast those configurations to the other players.
             */
            prepared: function() {
                window.parent.postMessage({
                    type: 'prepared'
                }, origin);
            },

            /**
             * Informs the server that the client is ready to start the match.
             */
            ready: function() {
                window.parent.postMessage({
                    type: 'ready'
                }, origin);
            },

            /**
             * Send a move to the platform server.
             *
             * @param {Object} moveDetails The move details.
             * @param {function(Object): boolean} [validate] Optional function to validate the move before sending it to server.
             * @returns {boolean} True when the move is valid or when no validation function was provided.
             */
            move: function(moveDetails, validate) {
                if (validate && !validate(moveDetails)) {
                    return false;
                }

                window.parent.postMessage({
                    type: 'move',
                    content: moveDetails
                }, origin);

                return true;
            },

            /**
             * Asks the platform to show the game menu.
             */
            showMenu: function() {
                window.parent.postMessage({
                    type: 'showMenu'
                }, origin);
            },

            /**
             * Send a message to the server-side rules. This message is specific to a game and will not be processed by the platform itself.
             * The response from the server could either be sent to you only or to all players.
             *
             * @param {Object} messageDetails The content of the message to be sent.
             * @param {boolean} isAnswerPublic Whether the reply from the server's rules should be sent to all players or not.
             * @param {boolean} [serializeRequest] Whether the messages should be processed in order of arrival or can be executed in parallel.
             */
            serverMessage: function(messageDetails, isAnswerPublic, serializeRequest) {
                window.parent.postMessage({
                    type: 'serverMessage',
                    publicAnswer: isAnswerPublic,
                    requiresConcurrencyControl: (serializeRequest) ? serializeRequest : true,
                    content: messageDetails
                }, origin);
            },

            /**
             * Peer-to-peer message sent directly to another player.
             *
             * @param {Object} messageDetails The content of the message to be sent.
             * @param {number} [sendTimeIntervalLimit] Do not allow sending more than one message within the specified time in milliseconds.
             *                 If this is called more than once during this interval only the last message will be sent.
             */
            playerMessage: function(messageDetails, sendTimeIntervalLimit) {
                if (!sendTimeIntervalLimit || lastMessage === null) {
                    message = {
                        type: 'playerMessage',
                        content: messageDetails
                    };
                    window.parent.postMessage(message, origin);

                    if (sendTimeIntervalLimit) {
                        setTimeout(function() {
                            if (lastMessage !== message) {
                                message = lastMessage;
                                lastMessage = null;
                                window.parent.postMessage(message, origin);
                            } else {
                                lastMessage = null;
                            }
                        }, sendTimeIntervalLimit);
                    }
                }
                if (sendTimeIntervalLimit) {
                    lastMessage = message;
                }
            }
        };
    };
    window.PG = new PG();

}(window));
<|endoftext|>


<commit_before>const line = require('@line/bot-sdk');
const apiai = require("apiai");

class Maia extends line.Client {

    constructor(config) {
        super(config);
        this.handleEvent = this.handleEvent.bind(this);
    }

    middleware() {
        return (req, res, next) => {
            Promise
                .all(req.body.events.map(this.handleEvent))
                .then((result) => res.json(result));
        };
    }

    handleEvent(event) {
        var mention = /^@?maia /i;
        var message = event.message.text;

        if (event.type !== 'message' || event.message.type !== 'text' || !message.match(mention)) {
            // ignore non-text-message event
            return Promise.resolve(null);
        }

        var userId = event.source.userId;

        var agent = apiai(process.env.APIAI_KEY);
        var request = agent.textRequest(event.message.text, {
            sessionId: userId
        });

        request.on('response', (response) => {
            const echo = { type: 'text', text: response.result.fulfillment.speech };
            // use reply API
            return this.replyMessage(event.replyToken, echo);
        });

        request.on('error', (error) => {
            console.log(error);
        });

        request.end();
    }
}

module.exports = Maia;
<commit_msg>initial<commit_after>const line = require('@line/bot-sdk');
const apiai = require("apiai");

class Maia extends line.Client {

    constructor(config) {
        super(config);
        this.handleEvent = this.handleEvent.bind(this);
    }

    middleware() {
        return (req, res, next) => {
            Promise
                .all(req.body.events.map(this.handleEvent))
                .then((result) => res.json(result));
        };
    }

    handleEvent(event) {
        var mention = /^@?maia /i;

        if (event.type !== 'message' || event.message.type !== 'text' || (event.source.type === "group" && !event.message.text.match(mention))) {
            // ignore non-text-message event
            return Promise.resolve(null);
        }

        var message = event.message.text.replace(mention, "");
        var userId = event.source.userId;

        var agent = apiai(process.env.APIAI_KEY);
        var request = agent.textRequest(message, {
            sessionId: userId
        });

        request.on('response', (response) => {
            const echo = { type: 'text', text: response.result.fulfillment.speech };
            // use reply API
            return this.replyMessage(event.replyToken, echo);
        });

        request.on('error', (error) => {
            console.log(error);
        });

        request.end();
    }
}

module.exports = Maia;
<|endoftext|>


<commit_before>import App from "../app";
import {gql, withFilter} from "apollo-server-express";
import {pubsub} from "../helpers/subscriptionManager";
import Set from "../classes/set";
// We define a schema that encompasses all of the types
// necessary for the functionality in this file.
const schema = gql`
  type Set {
    id: ID
    name: String
    clients: [SetClient]
  }

  type SetClient {
    id: ID
    client: Client
    simulator: Simulator
    stationSet: StationSet
    station: String
    secondary: Boolean
    soundPlayer: Boolean
  }

  input SetClientInput {
    id: ID
    clientId: ID
    simulatorId: ID
    stationSet: ID
    station: ID
    secondary: Boolean
    soundPlayer: Boolean
  }
  extend type Query {
    sets: [Set]
  }
  extend type Mutation {
    createSet(name: String!): String
    removeSet(id: ID!): String
    addClientToSet(id: ID!, client: SetClientInput!): String
    removeClientFromSet(id: ID!, clientId: ID!): String
    updateSetClient(id: ID!, client: SetClientInput!): String
    renameSet(id: ID!, name: String!): String
  }
  extend type Subscription {
    setsUpdate: [Set]
  }
`;

const resolver = {
  SetClient: {
    client(rootValue) {
      return App.clients.find(c => c.id === rootValue.clientId);
    },
    simulator(rootValue) {
      return App.simulators.find(c => c.id === rootValue.simulatorId);
    },
    stationSet(rootValue) {
      return App.stationSets.find(c => c.id === rootValue.stationSet);
    },
  },
  Query: {
    sets() {
      return App.sets;
    },
  },
  Mutation: {
    // I'm not handling these as events
    // Seems a little overkill.
    createSet(rootValue, args, context) {
      console.log(context);
      App.sets.push(new Set(args));
      pubsub.publish("setsUpdate", App.sets);
    },
    removeSet(rootValue, {id}, context) {
      App.sets = App.sets.filter(s => s.id !== id);
      pubsub.publish("setsUpdate", App.sets);
    },
    addClientToSet(rootValue, {id, client}, context) {
      App.sets.find(s => s.id === id).addClient(client);
      pubsub.publish("setsUpdate", App.sets);
    },
    removeClientFromSet(rootValue, {id, clientId}, context) {
      App.sets.find(s => s.id === id).removeClient(clientId);
      pubsub.publish("setsUpdate", App.sets);
    },
    updateSetClient(rootValue, {id, client}, context) {
      App.sets.find(s => s.id === id).updateClient(client);
      pubsub.publish("setsUpdate", App.sets);
    },
    renameSet(root, {id, name}, context) {
      App.sets.find(s => s.id === id).rename(name);
      pubsub.publish("setsUpdate", App.sets);
    },
  },
  Subscription: {
    setsUpdate: {
      resolve(rootValue) {
        return rootValue;
      },
      subscribe: withFilter(
        () => pubsub.asyncIterator("setsUpdate"),
        rootValue => !!(rootValue && rootValue.length),
      ),
    },
  },
};

export default {schema, resolver};
<commit_msg>feat(Missions): Make all mission lists sortable. Also add category option to missions.<commit_after>import App from "../app";
import {gql, withFilter} from "apollo-server-express";
import {pubsub} from "../helpers/subscriptionManager";
import Set from "../classes/set";
// We define a schema that encompasses all of the types
// necessary for the functionality in this file.
const schema = gql`
  type Set {
    id: ID
    name: String
    clients: [SetClient]
  }

  type SetClient {
    id: ID
    client: Client
    simulator: Simulator
    stationSet: StationSet
    station: String
    secondary: Boolean
    soundPlayer: Boolean
  }

  input SetClientInput {
    id: ID
    clientId: ID
    simulatorId: ID
    stationSet: ID
    station: ID
    secondary: Boolean
    soundPlayer: Boolean
  }
  extend type Query {
    sets: [Set]
  }
  extend type Mutation {
    createSet(name: String!): String
    removeSet(id: ID!): String
    addClientToSet(id: ID!, client: SetClientInput!): String
    removeClientFromSet(id: ID!, clientId: ID!): String
    updateSetClient(id: ID!, client: SetClientInput!): String
    renameSet(id: ID!, name: String!): String
  }
  extend type Subscription {
    setsUpdate: [Set]
  }
`;

const resolver = {
  SetClient: {
    client(rootValue) {
      return App.clients.find(c => c.id === rootValue.clientId);
    },
    simulator(rootValue) {
      return App.simulators.find(c => c.id === rootValue.simulatorId);
    },
    stationSet(rootValue) {
      return App.stationSets.find(c => c.id === rootValue.stationSet);
    },
  },
  Query: {
    sets() {
      return App.sets;
    },
  },
  Mutation: {
    // I'm not handling these as events
    // Seems a little overkill.
    createSet(rootValue, args, context) {
      App.sets.push(new Set(args));
      pubsub.publish("setsUpdate", App.sets);
    },
    removeSet(rootValue, {id}, context) {
      App.sets = App.sets.filter(s => s.id !== id);
      pubsub.publish("setsUpdate", App.sets);
    },
    addClientToSet(rootValue, {id, client}, context) {
      App.sets.find(s => s.id === id).addClient(client);
      pubsub.publish("setsUpdate", App.sets);
    },
    removeClientFromSet(rootValue, {id, clientId}, context) {
      App.sets.find(s => s.id === id).removeClient(clientId);
      pubsub.publish("setsUpdate", App.sets);
    },
    updateSetClient(rootValue, {id, client}, context) {
      App.sets.find(s => s.id === id).updateClient(client);
      pubsub.publish("setsUpdate", App.sets);
    },
    renameSet(root, {id, name}, context) {
      App.sets.find(s => s.id === id).rename(name);
      pubsub.publish("setsUpdate", App.sets);
    },
  },
  Subscription: {
    setsUpdate: {
      resolve(rootValue) {
        return rootValue;
      },
      subscribe: withFilter(
        () => pubsub.asyncIterator("setsUpdate"),
        rootValue => !!(rootValue && rootValue.length),
      ),
    },
  },
};

export default {schema, resolver};
<|endoftext|>


<commit_before>var getReadableContent = require("../"),
	Parser = require("htmlparser2/lib/Parser.js"),
	Readability = require("../readabilitySAX.js"),
	request = require("request"),
	url = require("url"),
	ben = require("ben"),
	link;

var getSettings = function(link){
	return link ? {
		convertLinks: url.resolve.bind(null, link),
		link: link
	} : {};
};

var processContent = function(data){
	var settings = getSettings(link),
		readable = new Readability(settings),
		parser = new Parser(readable);

	console.log("parsing took (ms):", ben(1e3, function(){ parser.parseComplete(data); }));
	console.log("getArticle took (ms):", ben(1e3,function(){ readable.getArticle(); }));
	console.log("Whole parsing took (ms):", ben(500, function(){ getReadableContent.process(data, settings); }));
};

function debug(data){
	var readable = new Readability(getSettings(link)),
		parser = new Parser(readable);

	parser.parseComplete(data);

	var data = readable.getArticle("text");

	data.text = data.text.substr(0, 200).replace(/[\\\']/g, "");

	console.log(data);
	console.log("Found links:", Object.keys(readable._scannedLinks).length);
};

if(process.argv.length > 2){
	console.log("connecting to:", process.argv[2]);

	request(process.argv[2], function(err, resp, body){
		link = resp.request.uri;
		processContent(body);
	});
}
else
	require("fs").readFile(__dirname + "/testpage.html", function(a,b){processContent(b.toString("utf8"));});
<commit_msg>Removed unused code<commit_after>var getReadableContent = require("../"),
	Parser = require("htmlparser2/lib/Parser.js"),
	Readability = require("../readabilitySAX.js"),
	request = require("request"),
	url = require("url"),
	ben = require("ben");

var processContent = function(data, settings){
	var readable = new Readability(settings),
		parser = new Parser(readable);

	console.log("parsing took (ms):", ben(1e3, function(){ parser.parseComplete(data); }));
	console.log("getArticle took (ms):", ben(1e3,function(){ readable.getArticle(); }));
	console.log("Whole parsing took (ms):", ben(500, function(){ getReadableContent.process(data, settings); }));
};

if(process.argv.length > 2){
	console.log("connecting to:", process.argv[2]);

	request(process.argv[2], function(err, resp, body){
		processContent(body, {
			convertLinks: function(link){ url.resolve(resp.request.uri, link); },
			link: resp.request.uri
		});
	});
}
else
	require("fs").readFile(__dirname + "/testpage.html", function(a,b){processContent(b.toString("utf8"), {});});
<|endoftext|>


<commit_before>(function(exports){
  exports.replace_var = function(data, matches, query){
    return data.replace(/{\$[^}]*}/g, function(str){
        var id = str.substr(2, str.length - 3);
        if (id.match('^[0-9]*$')) {
          return matches[parseInt(id)];
        }
        var params = exports.parse_str(query);
        return params[id];
    });
  };

  exports.query = function(url, cb){
    this.getCSVMap(function(csvmap){
      var url_parts = exports.parse_url(url);
      var ret = {};
      ret.query_url = url;

      for (var i = 1; i < csvmap.length; i ++) {
        if (csvmap[i][0] != url_parts['hostname']) {
          continue;
        }
        var matches = csvmap[i][1].match(/'(.*)'([a-z]*)/);
        var pattern = new RegExp(matches[1].replace('/', '\\/'), matches[2]);
        matches = pattern.exec(url_parts['pathname']);
        if (null === matches) {
          continue;
        }

        ret.normalized_url = exports.replace_var(csvmap[i][2], matches, url_parts['query']);
        ret.normalized_id = exports.replace_var(csvmap[i][3], matches, url_parts['query']);
        cb(ret);
      }
    });
  };

  exports.parse_str = function(query_str){
    if ('undefined' === typeof(query_str)) {
      return {};
    }
    if (query_str == '') {
      return {};
    }
    var terms = query_str.split('&');
    var ret = {};
    for (var i = 0; i < terms.length; i ++) {
      var key_value = terms[i].split('=');
      if (key_value.length < 2) {
        continue;
      }
      var key = decodeURIComponent(key_value.shift());
      var value = decodeURIComponent(key_value.join('='));
      ret[key] = value;
    }
    return ret;
  }

  var csvmap = null;

  exports.getCSVMap = function(cb){
   if (null !== csvmap) {
     return cb(csvmap);
   }
   var fs = require('fs');
   fs.readFile('map.csv', 'ascii', function(err, data){
     csvmap = data.split("\n").map(function(line){ return line.split(','); });
     cb(csvmap);
   });
  },

  exports.parse_url = function(url){
    if ('undefined' !== typeof(document) && 'undefined' !== typeof(document.createElement)) {
      var a_dom = document.createElement('a');
      a_dom.href = url;
      return a_dom;
    } else {
      var u = require('url');
      return u.parse(url);
    }
  };
})(typeof exports === 'undefined'? this['URLNormalizer']={}: exports);
<commit_msg>處理 web 環境下不支援 require('fs'), 應該用 XMLHttpRequest 抓資料，並且 <a> 抓網址後面 ? 應該用 search 而不是 query<commit_after>(function(exports){
  exports.replace_var = function(data, matches, query){
    return data.replace(/{\$[^}]*}/g, function(str){
        var id = str.substr(2, str.length - 3);
        if (id.match('^[0-9]*$')) {
          return matches[parseInt(id)];
        }
        var params = exports.parse_str(query);
        return params[id];
    });
  };

  exports.query = function(url, cb){
    this.getCSVMap(function(csvmap){
      var url_parts = exports.parse_url(url);
      var ret = {};
      ret.query_url = url;

      for (var i = 1; i < csvmap.length; i ++) {
        if (csvmap[i][0] != url_parts['hostname']) {
          continue;
        }
        var matches = csvmap[i][1].match(/'(.*)'([a-z]*)/);
        var pattern = new RegExp(matches[1].replace('/', '\\/'), matches[2]);
        matches = pattern.exec(url_parts['pathname']);
        if (null === matches) {
          continue;
        }

        ret.normalized_url = exports.replace_var(csvmap[i][2], matches, url_parts['query']);
        ret.normalized_id = exports.replace_var(csvmap[i][3], matches, url_parts['query']);
        cb(ret);
      }
    });
  };

  exports.parse_str = function(query_str){
    if ('undefined' === typeof(query_str)) {
      return {};
    }
    if (query_str == '') {
      return {};
    }
    var terms = query_str.split('&');
    var ret = {};
    for (var i = 0; i < terms.length; i ++) {
      var key_value = terms[i].split('=');
      if (key_value.length < 2) {
        continue;
      }
      var key = decodeURIComponent(key_value.shift());
      var value = decodeURIComponent(key_value.join('='));
      ret[key] = value;
    }
    return ret;
  }

  var csvmap = null;

  exports.getCSVMap = function(cb){
    if (null !== csvmap) {
      return cb(csvmap);
    }
    if ('undefined' !== typeof(XMLHttpRequest)) {
      var csvFile = new XMLHttpRequest;
      csvFile.open("GET", "map.csv", true);
      csvFile.onreadystatechange = function(){
        if (csvFile.readyState == 4) {
          if (csvFile.status == 200) {
            cb(csvFile.responseText.split("\n").map(function(line){ return line.split(','); }));
          }
        }
      };
      csvFile.send('');
    } else {
      var fs = require('fs');
      fs.readFile('map.csv', 'ascii', function(err, data){
        csvmap = data.split("\n").map(function(line){ return line.split(','); });
        cb(csvmap);
      });
    }
  },

  exports.parse_url = function(url){
    if ('undefined' !== typeof(document) && 'undefined' !== typeof(document.createElement)) {
      var a_dom = document.createElement('a');
      a_dom.href = url;
      return {
        pathname: decodeURIComponent(a_dom.pathname),
        hostname: a_dom.hostname,
        query: a_dom.search.length ? a_dom.search.substr(1) : ''
      };
    } else {
      var u = require('url');
      var parts = u.parse(url);
      return {
        pathname: decodeURIComponent(parts.pathname),
        hostname: parts.hostname,
        query: parts.query
      };
    }
  };
})(typeof exports === 'undefined'? this['URLNormalizer']={}: exports);
<|endoftext|>


<commit_before>import _ from 'underscore';
import React from 'react';
import shell from 'shell';
import metrics from '../utils/MetricsUtil';
import ContainerUtil from '../utils/ContainerUtil';
import classNames from 'classnames';
import containerActions from '../actions/ContainerActions';
import dockerMachineUtil from '../utils/DockerMachineUtil';

var ContainerDetailsSubheader = React.createClass({
  contextTypes: {
    router: React.PropTypes.func
  },
  disableRun: function () {
    if (!this.props.container) {
      return false;
    }
    return (!this.props.container.State.Running || !this.props.defaultPort || this.props.container.State.Updating);
  },
  disableRestart: function () {
    if (!this.props.container) {
      return false;
    }
    return (this.props.container.State.Downloading || this.props.container.State.Restarting || this.props.container.State.Updating);
  },
  disableStop: function () {
    if (!this.props.container) {
      return false;
    }
    return (this.props.container.State.Downloading || this.props.container.State.ExitCode || !this.props.container.State.Running || this.props.container.State.Updating);
  },
  disableStart: function () {
    if (!this.props.container) {
      return false;
    }
    return (this.props.container.State.Downloading || this.props.container.State.Running || this.props.container.State.Updating);
  },
  disableTerminal: function () {
    if (!this.props.container) {
      return false;
    }
    return (!this.props.container.State.Running || this.props.container.State.Updating);
  },
  disableTab: function () {
    if (!this.props.container) {
      return false;
    }
    return (this.props.container.State.Downloading);
  },
  showHome: function () {
    if (!this.disableTab()) {
      metrics.track('Viewed Home', {
        from: 'header'
      });
      this.context.router.transitionTo('containerHome', {name: this.context.router.getCurrentParams().name});
    }
  },
  showSettings: function () {
    if (!this.disableTab()) {
      metrics.track('Viewed Settings');
      this.context.router.transitionTo('containerSettings', {name: this.context.router.getCurrentParams().name});
    }
  },
  handleRun: function () {
    if (this.props.defaultPort && !this.disableRun()) {
      metrics.track('Opened In Browser', {
        from: 'header'
      });
      shell.openExternal(this.props.ports[this.props.defaultPort].url);
    }
  },
  handleRestart: function () {
    if (!this.disableRestart()) {
      metrics.track('Restarted Container');
      containerActions.restart(this.props.container.Name);
    }
  },
  handleStop: function () {
    if (!this.disableStop()) {
      metrics.track('Stopped Container');
      containerActions.stop(this.props.container.Name);
    }
  },
  handleStart: function () {
    if (!this.disableStart()) {
      metrics.track('Started Container');
      containerActions.start(this.props.container.Name);
    }
  },
  handleTerminal: function () {
    if (!this.disableTerminal()) {
      metrics.track('Terminaled Into Container');
      var container = this.props.container;
      var shell = ContainerUtil.env(container).reduce((envs, env) => {
        envs[env[0]] = env[1];
        return envs;
      }, {}).SHELL;

      if(!shell) {
        shell = 'sh';
      }
      dockerMachineUtil.dockerTerminal(`docker exec -it ${this.props.container.Name} ${shell}`);
    }
  },
  render: function () {
    var restartActionClass = classNames({
      action: true,
      disabled: this.disableRestart()
    });
    var stopActionClass = classNames({
      action: true,
      disabled: this.disableStop()
    });
    var startActionClass = classNames({
      action: true,
      disabled: this.disableStart()
    });
    var terminalActionClass = classNames({
      action: true,
      disabled: this.disableTerminal()
    });

    var currentRoutes = _.map(this.context.router.getCurrentRoutes(), r => r.name);
    var currentRoute = _.last(currentRoutes);

    var tabHomeClasses = classNames({
      'details-tab': true,
      'active': currentRoute === 'containerHome',
      disabled: this.disableTab()
    });
    var tabSettingsClasses = classNames({
      'details-tab': true,
      'active': currentRoutes && (currentRoutes.indexOf('containerSettings') >= 0),
      disabled: this.disableTab()
    });
    var startStopToggle;
    if (this.disableStop()) {
      startStopToggle = (

START

      );
    } else {
      startStopToggle = (

STOP

      );
    }
    return (

          {startStopToggle}

RESTART

EXEC

          Home
          Settings

    );
  }
});

module.exports = ContainerDetailsSubheader;
<commit_msg>Added hub docs link within container<commit_after>import _ from 'underscore';
import React from 'react';
import shell from 'shell';
import metrics from '../utils/MetricsUtil';
import ContainerUtil from '../utils/ContainerUtil';
import classNames from 'classnames';
import containerActions from '../actions/ContainerActions';
import dockerMachineUtil from '../utils/DockerMachineUtil';

var ContainerDetailsSubheader = React.createClass({
  contextTypes: {
    router: React.PropTypes.func
  },
  disableRun: function () {
    if (!this.props.container) {
      return false;
    }
    return (!this.props.container.State.Running || !this.props.defaultPort || this.props.container.State.Updating);
  },
  disableRestart: function () {
    if (!this.props.container) {
      return false;
    }
    return (this.props.container.State.Downloading || this.props.container.State.Restarting || this.props.container.State.Updating);
  },
  disableStop: function () {
    if (!this.props.container) {
      return false;
    }
    return (this.props.container.State.Downloading || this.props.container.State.ExitCode || !this.props.container.State.Running || this.props.container.State.Updating);
  },
  disableStart: function () {
    if (!this.props.container) {
      return false;
    }
    return (this.props.container.State.Downloading || this.props.container.State.Running || this.props.container.State.Updating);
  },
  disableTerminal: function () {
    if (!this.props.container) {
      return false;
    }
    return (!this.props.container.State.Running || this.props.container.State.Updating);
  },
  disableTab: function () {
    if (!this.props.container) {
      return false;
    }
    return (this.props.container.State.Downloading);
  },
  showHome: function () {
    if (!this.disableTab()) {
      metrics.track('Viewed Home', {
        from: 'header'
      });
      this.context.router.transitionTo('containerHome', {name: this.context.router.getCurrentParams().name});
    }
  },
  showSettings: function () {
    if (!this.disableTab()) {
      metrics.track('Viewed Settings');
      this.context.router.transitionTo('containerSettings', {name: this.context.router.getCurrentParams().name});
    }
  },
  handleRun: function () {
    if (this.props.defaultPort && !this.disableRun()) {
      metrics.track('Opened In Browser', {
        from: 'header'
      });
      shell.openExternal(this.props.ports[this.props.defaultPort].url);
    }
  },
  handleRestart: function () {
    if (!this.disableRestart()) {
      metrics.track('Restarted Container');
      containerActions.restart(this.props.container.Name);
    }
  },
  handleStop: function () {
    if (!this.disableStop()) {
      metrics.track('Stopped Container');
      containerActions.stop(this.props.container.Name);
    }
  },
  handleStart: function () {
    if (!this.disableStart()) {
      metrics.track('Started Container');
      containerActions.start(this.props.container.Name);
    }
  },
  handleDocs: function () {
    let repoUri = 'https://hub.docker.com/r/';
    let imageName = this.props.container.Config.Image.split(':')[0];
    if (imageName.indexOf('/') === -1) {
      repoUri = repoUri + 'library/' + imageName;
    } else {
      repoUri = repoUri + imageName;
    }
    shell.openExternal(repoUri);
  },
  handleTerminal: function () {
    if (!this.disableTerminal()) {
      metrics.track('Terminaled Into Container');
      var container = this.props.container;
      var shell = ContainerUtil.env(container).reduce((envs, env) => {
        envs[env[0]] = env[1];
        return envs;
      }, {}).SHELL;

      if(!shell) {
        shell = 'sh';
      }
      dockerMachineUtil.dockerTerminal(`docker exec -it ${this.props.container.Name} ${shell}`);
    }
  },
  render: function () {
    var restartActionClass = classNames({
      action: true,
      disabled: this.disableRestart()
    });
    var stopActionClass = classNames({
      action: true,
      disabled: this.disableStop()
    });
    var startActionClass = classNames({
      action: true,
      disabled: this.disableStart()
    });
    var terminalActionClass = classNames({
      action: true,
      disabled: this.disableTerminal()
    });
    var docsActionClass = classNames({
      action: true,
      disabled: false
    })

    var currentRoutes = _.map(this.context.router.getCurrentRoutes(), r => r.name);
    var currentRoute = _.last(currentRoutes);

    var tabHomeClasses = classNames({
      'details-tab': true,
      'active': currentRoute === 'containerHome',
      disabled: this.disableTab()
    });
    var tabSettingsClasses = classNames({
      'details-tab': true,
      'active': currentRoutes && (currentRoutes.indexOf('containerSettings') >= 0),
      disabled: this.disableTab()
    });
    var startStopToggle;
    if (this.disableStop()) {
      startStopToggle = (

START

      );
    } else {
      startStopToggle = (

STOP

      );
    }

    return (

          {startStopToggle}

RESTART

EXEC

DOCS

          Home
          Settings

    );
  }
});

module.exports = ContainerDetailsSubheader;
<|endoftext|>