<|start_filename|>node_modules/homey-log/node_modules/raven/lib/middleware/connect.js<|end_filename|>
'use strict';

var raven = require('../client');
var parsers = require('../parsers');

// Legacy support
var connectMiddleware = function(client) {
  return connectMiddleware.errorHandler(client);
};

// Error handler. This should be the last item listed in middleware, but
// before any other error handlers.
connectMiddleware.errorHandler = function(client) {
  client = client instanceof raven.Client ? client : new raven.Client(client);
  return function(err, req, res, next) {
    var status = err.status || err.statusCode || err.status_code || 500;

    // skip anything not marked as an internal server error
    if (status < 500) return next(err);

    var kwargs = parsers.parseRequest(req);
    client.captureError(err, kwargs, function(result) {
      res.sentry = client.getIdent(result);
      next(err, req, res);
    });
  };
};

// Ensures asynchronous exceptions are routed to the errorHandler. This
// should be the **first** item listed in middleware.
connectMiddleware.requestHandler = function(client) {
  var domain = require('domain');
  return function(req, res, next) {
    var reqDomain = domain.create();
    reqDomain.on('error', next);
    return reqDomain.run(next);
  };
};

module.exports = connectMiddleware;

<|start_filename|>node_modules/color-space/munsell.js<|end_filename|>
/**
 * @module color-space/munsell
 */
'use strict'

var munsell = {
	name: 'munsell',
	alias: [],
	min: [],
	max: [],

	//hue, value, chroma
	channel: ['H', 'V', 'C']
}

/**
 * http://www.pp.bme.hu/ar/article/view/2395/1500
 */
munsell.coloroid = function (cv) {
	var c = arg[0], vm = arg[1];

	var a,t,v;

	//coloroid chroma / munsell chroma
	t = kav * Math.pow(c, 2/3);

	v = 10 * Math.sqrt(1.2219*vm - 0.23111*vm*vm + 0.23951*vm*vm*vm - 0.021009*vm*vm*vm*vm + 0.0008404*vm*vm*vm*vm*vm);
};


module.exports = munsell;


<|start_filename|>node_modules/color-space/index.js<|end_filename|>
/**
 * Color space data and conversions
 *
 * @module color-space
 *
 */
'use strict';


/** Exported spaces */
var spaces = {
	rgb: require('./rgb'),
	hsl: require('./hsl'),
	hsv: require('./hsv'),
	hsi: require('./hsi'),
	hwb: require('./hwb'),
	cmyk: require('./cmyk'),
	cmy: require('./cmy'),
	xyz: require('./xyz'),
	xyy: require('./xyy'),
	yiq: require('./yiq'),
	yuv: require('./yuv'),
	ydbdr: require('./ydbdr'),
	ycgco: require('./ycgco'),
	ypbpr: require('./ypbpr'),
	ycbcr: require('./ycbcr'),
	xvycc: require('./xvycc'),
	yccbccrc: require('./yccbccrc'),
	ucs: require('./ucs'),
	uvw: require('./uvw'),
	jpeg: require('./jpeg'),
	lab: require('./lab'),
	labh: require('./labh'),
	lms: require('./lms'),
	lchab: require('./lchab'),
	luv: require('./luv'),
	lchuv: require('./lchuv'),
	hsluv: require('./hsluv'),
	hpluv: require('./hpluv'),
	cubehelix: require('./cubehelix'),
	coloroid: require('./coloroid'),
	hcg: require('./hcg'),
	hcy: require('./hcy'),
	tsl: require('./tsl'),
	yes: require('./yes'),
	osaucs: require('./osaucs'),
	hsp: require('./hsp')
};



//build absent convertors from each to every space
var fromSpace;
for (var fromSpaceName in spaces) {
	fromSpace = spaces[fromSpaceName];
	for (var toSpaceName in spaces) {
		if (!fromSpace[toSpaceName]) fromSpace[toSpaceName] = getConvertor(fromSpaceName, toSpaceName);
	}
}


/** return converter through xyz/rgb space */
function getConvertor(fromSpaceName, toSpaceName){
	var fromSpace = spaces[fromSpaceName];

	//create straight converter
	if (fromSpaceName === toSpaceName) {
		return function (a) {
			return a;
		};
	}

	//create xyz converter, if available
	else if (fromSpace.xyz && spaces.xyz[toSpaceName]) {
		return function(arg){
			return spaces.xyz[toSpaceName](fromSpace.xyz(arg));
		};
	}
	//create rgb converter
	else if (fromSpace.rgb && spaces.rgb[toSpaceName]) {
		return function(arg){
			return spaces.rgb[toSpaceName](fromSpace.rgb(arg));
		};
	}
}


module.exports = spaces;


<|start_filename|>node_modules/homey-log/node_modules/raven/lib/transports.js<|end_filename|>
'use strict';

var events = require('events');
var util = require('util');

function Transport() {}
util.inherits(Transport, events.EventEmitter);

var http = require('http');

function HTTPTransport(options) {
  this.defaultPort = 80;
  this.transport = http;
  this.options = options || {};
}
util.inherits(HTTPTransport, Transport);
HTTPTransport.prototype.send = function(client, message, headers, ident) {
  var options = {
    hostname: client.dsn.host,
    path: client.dsn.path + 'api/' + client.dsn.project_id + '/store/',
    headers: headers,
    method: 'POST',
    port: client.dsn.port || this.defaultPort,
    ca: client.ca
  };
  for (var key in this.options) {
    if (this.options.hasOwnProperty(key)) {
      options[key] = this.options[key];
    }
  }
  var req = this.transport.request(options, function(res) {
    res.setEncoding('utf8');
    if (res.statusCode >= 200 && res.statusCode < 300) {
      client.emit('logged', ident);
    } else {
      var reason = res.headers['x-sentry-error'];
      var e = new Error('HTTP Error (' + res.statusCode + '): ' + reason);
      e.response = res;
      e.statusCode = res.statusCode;
      e.reason = reason;
      e.sendMessage = message;
      e.requestHeaders = headers;
      e.ident = ident;
      client.emit('error', e);
    }
    // force the socket to drain
    var noop = function() {};
    res.on('data', noop);
    res.on('end', noop);
  });
  req.on('error', function(e) {
    client.emit('error', e);
  });
  req.end(message);
};

var https = require('https');

function HTTPSTransport(options) {
  this.defaultPort = 443;
  this.transport = https;
  this.options = options || {};
}
util.inherits(HTTPSTransport, HTTPTransport);

var dgram = require('dgram');

function UDPTransport() {
  this.defaultPort = 12345;
}
util.inherits(UDPTransport, Transport);
UDPTransport.prototype.send = function(client, message, headers, ident) {
  message = new Buffer(headers['X-Sentry-Auth'] + '\n\n' + message);

  var udp = dgram.createSocket('udp4');
  udp.send(message, 0, message.length, client.dsn.port || this.defaultPort, client.dsn.host, function(e, bytes) {
    if (e) {
      return client.emit('error', e);
    }
    client.emit('logged', ident);
    udp.close();
  });
};

module.exports.http = new HTTPTransport();
module.exports.https = new HTTPSTransport();
module.exports.udp = new UDPTransport();
module.exports.Transport = Transport;
module.exports.HTTPTransport = HTTPTransport;
module.exports.HTTPSTransport = HTTPSTransport;

<|start_filename|>node_modules/homey-log/node_modules/raven/lib/client.js<|end_filename|>
'use strict';

var stringify = require('json-stringify-safe');
var parsers = require('./parsers');
var zlib = require('zlib');
var utils = require('./utils');
var uuid = require('uuid');
var transports = require('./transports');
var node_util = require('util'); // node_util to avoid confusion with "utils"
var events = require('events');

module.exports.version = require('../package.json').version;

var extend = Object.assign || function(target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = arguments[i];
    for (var key in source) {
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        target[key] = source[key];
      }
    }
  }
  return target;
};

var Client = function Client(dsn, options) {
  if (arguments.length === 0) {
    // no arguments, use default from environment
    dsn = process.env.SENTRY_DSN;
    options = {};
  }
  if (typeof dsn === 'object') {
    // They must only be passing through options
    options = dsn;
    dsn = process.env.SENTRY_DSN;
  }
  options = options || {};

  this.raw_dsn = dsn;
  this.dsn = utils.parseDSN(dsn);
  this.name = options.name || process.env.SENTRY_NAME || require('os').hostname();
  this.root = options.root || process.cwd();
  this.transport = options.transport || transports[this.dsn.protocol];
  this.release = options.release || process.env.SENTRY_RELEASE || '';
  this.environment = options.environment || process.env.SENTRY_ENVIRONMENT || '';

  this.loggerName = options.logger || '';
  this.dataCallback = options.dataCallback;

  if (this.dsn.protocol === 'https') {
    // In case we want to provide our own SSL certificates / keys
    this.ca = options.ca || null;
  }

  // enabled if a dsn is set
  this._enabled = !!this.dsn;

  var globalContext = this._globalContext = {};
  if (options.tags) {
    globalContext.tags = options.tags;
  }
  if (options.extra) {
    globalContext.extra = options.extra;
  }

  this.on('error', function(e) {}); // noop
};
node_util.inherits(Client, events.EventEmitter);
var proto = Client.prototype;

module.exports.Client = Client;

proto.getIdent =
  proto.get_ident = function getIdent(result) {
    return result.id;
  };

proto.process = function process(kwargs) {
  kwargs.modules = utils.getModules();
  kwargs.server_name = kwargs.server_name || this.name;

  if (typeof process.version !== 'undefined') {
    kwargs.extra.node = process.version;
  }

  kwargs.environment = kwargs.environment || this.environment;
  kwargs.extra = extend({}, this._globalContext.extra, kwargs.extra);
  kwargs.tags = extend({}, this._globalContext.tags, kwargs.tags);

  kwargs.logger = kwargs.logger || this.loggerName;
  kwargs.event_id = uuid().replace(/-/g, '');
  kwargs.timestamp = new Date().toISOString().split('.')[0];
  kwargs.project = this.dsn.project_id;
  kwargs.platform = 'node';

  if (this._globalContext.user) {
    kwargs.user = this._globalContext.user || kwargs.user;
  }

  // Only include release information if it is set
  if (this.release) {
    kwargs.release = this.release;
  }

  var ident = {
    id: kwargs.event_id
  };

  if (this.dataCallback) {
    kwargs = this.dataCallback(kwargs);
  }

  // this will happen asynchronously. We don't care about it's response.
  this._enabled && this.send(kwargs, ident);

  return ident;
};

proto.send = function send(kwargs, ident) {
  var self = this;
  
  var skwargs = stringify(kwargs);

  zlib.deflate(skwargs, function(err, buff) {
    var message = buff.toString('base64'),
      timestamp = new Date().getTime(),
      headers = {
        'X-Sentry-Auth': utils.getAuthHeader(timestamp, self.dsn.public_key, self.dsn.private_key),
        'Content-Type': 'application/octet-stream',
        'Content-Length': message.length
      };

    self.transport.send(self, message, headers, ident);
  });
};

proto.captureMessage = function captureMessage(message, kwargs, cb) {
  if (!cb && typeof kwargs === 'function') {
    cb = kwargs;
    kwargs = {};
  } else {
    kwargs = kwargs || {};
  }
  var result = this.process(parsers.parseText(message, kwargs));
  cb && cb(result);
  return result;
};

proto.captureException = function captureError(err, kwargs, cb) {
  if (!(err instanceof Error)) {
    // This handles when someone does:
    //   throw "something awesome";
    // We synthesize an Error here so we can extract a (rough) stack trace.
    err = new Error(err);
  }

  var self = this;
  if (!cb && typeof kwargs === 'function') {
    cb = kwargs;
    kwargs = {};
  } else {
    kwargs = kwargs || {};
  }
  parsers.parseError(err, kwargs, function(kw) {
    var result = self.process(kw);
    cb && cb(result);
  });
};
proto.captureError = proto.captureException; // legacy alias

proto.captureQuery = function captureQuery(query, engine, kwargs, cb) {
  if (!cb && typeof kwargs === 'function') {
    cb = kwargs;
    kwargs = {};
  } else {
    kwargs = kwargs || {};
  }
  var result = this.process(parsers.parseQuery(query, engine, kwargs));
  cb && cb(result);
  return result;
};

/*
 * Set/clear a user to be sent along with the payload.
 *
 * @param {object} user An object representing user data [optional]
 * @return {Raven}
 */
proto.setUserContext = function setUserContext(user) {
  this._globalContext.user = user;
};

/*
 * Merge extra attributes to be sent along with the payload.
 *
 * @param {object} extra An object representing extra data [optional]
 * @return {Raven}
 */
proto.setExtraContext = function setExtraContext(extra) {
  this._globalContext.extra = extend({}, this._globalContext.extra, extra);
  return this;
};

/*
 * Merge tags to be sent along with the payload.
 *
 * @param {object} tags An object representing tags [optional]
 * @return {Raven}
 */
proto.setTagsContext = function setTagsContext(tags) {
  this._globalContext.tags = extend({}, this._globalContext.tags, tags);
  return this;
};

proto.patchGlobal = function patchGlobal(cb) {
  module.exports.patchGlobal(this, cb);
  return this;
};

module.exports.patchGlobal = function patchGlobal(client, cb) {
  // handle when the first argument is the callback, with no client specified
  if (typeof client === 'function') {
    cb = client;
    client = new Client();
    // first argument is a string DSN
  } else if (typeof client === 'string') {
    client = new Client(client);
  }
  // at the end, if we still don't have a Client, let's make one!
  !(client instanceof Client) && (client = new Client());

  var called = false;
  process.on('uncaughtException', function(err) {
    if (cb) { // bind event listeners only if a callback was supplied
      var onLogged = function onLogged() {
        called = false;
        cb(true, err);
      };

      var onError = function onError() {
        called = false;
        cb(false, err);
      };

      if (called) {
        client.removeListener('logged', onLogged);
        client.removeListener('error', onError);
        return cb(false, err);
      }

      client.once('logged', onLogged);
      client.once('error', onError);
    }

    called = true;

    client.captureError(err, function(result) {
      node_util.log('uncaughtException: ' + client.getIdent(result));
    });
  });
};


<|start_filename|>node_modules/homey-log/node_modules/raven/lib/parsers.js<|end_filename|>
'use strict';

var cookie = require('cookie');
var urlParser = require('url');
var stringify = require('json-stringify-safe');

var utils = require('./utils');

module.exports.parseText = function parseText(message, kwargs) {
  kwargs = kwargs || {};
  kwargs.message = message;

  return kwargs;
};

module.exports.parseError = function parseError(err, kwargs, cb) {
  utils.parseStack(err, function(frames) {
    var name = err.name + '';
    if (typeof kwargs.message === 'undefined') {
      kwargs.message = name + ': ' + (err.message || '<no message>');
    }
    kwargs.exception = [{
      type: name,
      value: err.message,
      stacktrace: {
        frames: frames
      }
    }];

    // Save additional error properties to `extra` under the error type (e.g. `extra.AttributeError`)
    var extraErrorProps;
    for (var key in err) {
      if (err.hasOwnProperty(key)) {
        if (key !== 'name' && key !== 'message' && key !== 'stack') {
          extraErrorProps = extraErrorProps || {};
          extraErrorProps[key] = err[key];
        }
      }
    }
    if (extraErrorProps) {
      kwargs.extra = kwargs.extra || {};
      kwargs.extra[name] = extraErrorProps;
    }

    for (var n = frames.length - 1; n >= 0; n--) {
      if (frames[n].in_app) {
        kwargs.culprit = kwargs.culprit || utils.getCulprit(frames[n]);
        break;
      }
    }

    cb(kwargs);
  });
};

module.exports.parseQuery = function parseQuery(query, engine, kwargs) {
  kwargs = kwargs || {};
  kwargs.message = query;
  kwargs.query = {
    query: query,
    engine: engine
  };
  return kwargs;
};

module.exports.parseRequest = function parseRequest(req, kwargs) {
  kwargs = kwargs || {};

  // headers:
  //
  //   node: req.headers
  //   express: req.headers
  //   koa: req.header
  //
  var headers = req.headers || req.header || {};

  // method:
  //
  //   node: req.method
  //   express: req.method
  //   koa: req.method
  //
  var method = req.method;

  // host:
  //
  //   node: req.headers.host
  //   express: req.hostname in > 4 and req.host in < 4
  //   koa: req.host
  //
  var host = req.hostname || req.host || headers.host || '<no host>';

  // protocol:
  //
  //   node: <n/a>
  //   express: req.protocol
  //   koa: req.protocol
  //
  var protocol = 'https' === req.protocol || true === req.secure || true === (req.socket || {}).encrypted ? 'https' : 'http';

  // url (including path and query string):
  //
  //   node: req.originalUrl
  //   express: req.originalUrl
  //   koa: req.url
  //
  var originalUrl = req.originalUrl || req.url;

  // absolute url
  var url = protocol + '://' + host + originalUrl;

  // query string
  //
  //   node: req.url (raw)
  //   express: req.query
  //   koa: req.query
  //
  var query = req.query || urlParser.parse(originalUrl || '', true).query;

  // cookies:
  //
  //   node: req.headers.cookie
  //   express: req.headers.cookie
  //   koa: req.headers.cookie
  //
  var cookies = cookie.parse(headers.cookie || '');

  // body data:
  //
  //   node: req.body
  //   express: req.body
  //   koa: req.body
  //
  var data = req.body;
  if (['GET', 'HEAD'].indexOf(method) === -1) {
    if (typeof data === 'undefined') {
      data = '<unavailable>';
    }
  }

  if (data && {}.toString.call(data) !== '[object String]') {
    // Make sure the request body is a string
    data = stringify(data);
  }

  // client ip:
  //
  //   node: req.connection.remoteAddress
  //   express: req.ip
  //   koa: req.ip
  //
  var ip = req.ip || (req.connection || {}).remoteAddress;

  // http interface
  var http = {
    method: method,
    query_string: query,
    headers: headers,
    cookies: cookies,
    data: data,
    url: url
  };

  // expose http interface
  kwargs.request = http;

  // user
  //
  // typically found on req.user according to Express and Passport

  var user = {};
  if (!kwargs.user) {
    if (req.user) {
      // shallow copy is okay because we are only modifying top-level
      // object (req.user)
      for (var key in req.user) {
        if ({}.hasOwnProperty.call(req.user, key)) {
          user[key] = req.user[key];
        }
      }
    }

    if (ip) {
      user.ip_address = ip;
    }

    kwargs.user = user;
  }

  return kwargs;
};


<|start_filename|>node_modules/homey-log/index.js<|end_filename|>
'use strict';

module.exports.Log = require('./lib/Log.js');

<|start_filename|>node_modules/color-space/hsp.js<|end_filename|>
/**
 * @module color-space/hsp
 */
'use strict'

var rgb = require('./rgb'),
  Pr = 0.299,
  Pg = 0.587,
  Pb = 0.114;

module.exports = {
  name: 'hsp',
  min: [0, 0, 0],
  max: [360, 100, 255],
  channel: ['hue', 'saturation', 'perceived_brightness'],
  alias: ['HSP'],

  rgb: function (hsp) {
    var h = hsp[0]/360.0,
      s = hsp[1]/100.0,
      p = hsp[2],
      r, g, b, part,
      minOverMax = 1.0 - s;

    if (minOverMax > 0.0) {
      if (h < 1.0 / 6.0) { //  R>G>B
        h = 6.0 * (h - 0.0 / 6.0);
        part = 1.0 + h * (1.0 / minOverMax - 1.0);
        b = p / Math.sqrt(Pr / minOverMax / minOverMax + Pg * part * part + Pb);
        r = (b) / minOverMax;
        g = (b) + h * ((r) - (b));
      } else if (h < 2.0 / 6.0) { //  G>R>B
        h = 6.0 * (-h + 2.0 / 6.0);
        part = 1.0 + h * (1.0 / minOverMax - 1.0);
        b = p / Math.sqrt(Pg / minOverMax / minOverMax + Pr * part * part + Pb);
        g = (b) / minOverMax;
        r = (b) + h * ((g) - (b));
      } else if (h < 3.0 / 6.0) { //  G>B>R
        h = 6.0 * (h - 2.0 / 6.0);
        part = 1.0 + h * (1.0 / minOverMax - 1.0);
        r = p / Math.sqrt(Pg / minOverMax / minOverMax + Pb * part * part + Pr);
        g = (r) / minOverMax;
        b = (r) + h * ((g) - (r));
      } else if (h < 4.0 / 6.0) { //  B>G>R
        h = 6.0 * (-h + 4.0 / 6.0);
        part = 1.0 + h * (1.0 / minOverMax - 1.0);
        r = p / Math.sqrt(Pb / minOverMax / minOverMax + Pg * part * part + Pr);
        b = (r) / minOverMax;
        g = (r) + h * ((b) - (r));
      } else if (h < 5.0 / 6.0) { //  B>R>G
        h = 6.0 * (h - 4.0 / 6.0);
        part = 1.0 + h * (1.0 / minOverMax - 1.0);
        g = p / Math.sqrt(Pb / minOverMax / minOverMax + Pr * part * part + Pg);
        b = (g) / minOverMax;
        r = (g) + h * ((b) - (g));
      } else { //  R>B>G
        h = 6.0 * (-h + 6.0 / 6.0);
        part = 1.0 + h * (1.0 / minOverMax - 1.0);
        g = p / Math.sqrt(Pr / minOverMax / minOverMax + Pb * part * part + Pg);
        r = (g) / minOverMax;
        b = (g) + h * ((r) - (g));
      }
    } else {
      if (h < 1.0 / 6.0) { //  R>G>B
        h = 6.0 * (h - 0.0 / 6.0);
        r = Math.sqrt(p * p / (Pr + Pg * h * h));
        g = (r) * h;
        b = 0.0;
      } else if (h < 2.0 / 6.0) { //  G>R>B
        h = 6.0 * (-h + 2.0 / 6.0);
        g = Math.sqrt(p * p / (Pg + Pr * h * h));
        r = (g) * h;
        b = 0.0;
      } else if (h < 3.0 / 6.0) { //  G>B>R
        h = 6.0 * (h - 2.0 / 6.0);
        g = Math.sqrt(p * p / (Pg + Pb * h * h));
        b = (g) * h;
        r = 0.0;
      } else if (h < 4.0 / 6.0) { //  B>G>R
        h = 6.0 * (-h + 4.0 / 6.0);
        b = Math.sqrt(p * p / (Pb + Pg * h * h));
        g = (b) * h;
        r = 0.0;
      } else if (h < 5.0 / 6.0) { //  B>R>G
        h = 6.0 * (h - 4.0 / 6.0);
        b = Math.sqrt(p * p / (Pb + Pr * h * h));
        r = (b) * h;
        g = 0.0;
      } else { //  R>B>G
        h = 6.0 * (-h + 6.0 / 6.0);
        r = Math.sqrt(p * p / (Pr + Pb * h * h));
        b = (r) * h;
        g = 0.0;
      }
    }

	return [Math.round(r), Math.round(g), Math.round(b)];
  }

  
};


//append rgb
rgb.hsp = function (rgb) {
  var r = parseInt(rgb[0], 10),
    g = parseInt(rgb[1], 10),
    b = parseInt(rgb[2], 10),
    h, s, p;

  //  Calculate the Perceived brightness
  p = Math.sqrt(r * r * Pr + g * g * Pg + b * b * Pb);

  //  Calculate the Hue and Saturation
  if (r === g && r === b) {
    h = 0.0;
    s = 0.0;
  } else {    
    //  R is largest
    if (r >= g && r >= b) {
      if (b >= g) {
        h = 6.0 / 6.0 - 1.0 / 6.0 * (b - g) / (r - g);
        s = 1.0 - g / r;
      } else {
        h = 0.0 / 6.0 + 1.0 / 6.0 * (g - b) / (r - b);
        s = 1.0 - b / r;
      }
    }

    // G is largest
    if (g >= r && g >= b) {
      if (r >= b) {
        h = 2.0 / 6.0 - 1.0 / 6.0 * (r - b) / (g - b);
        s = 1 - b / g;
      } else {
        h = 2.0 / 6.0 + 1.0 / 6.0 * (b - r) / (g - r);
        s = 1.0 - r / g;
      }
    }

    // B is largest
    if (b >= r && b >= g) {
      if (g >= r) {
        h = 4.0 / 6.0 - 1.0 / 6.0 * (g - r) / (b - r);
        s = 1.0 - r / b;
      } else {
        h = 4.0 / 6.0 + 1.0 / 6.0 * (r - g) / (b - g);
        s = 1.0 - g / b;
      }
    }
  }
    
  return [Math.round(h*360.0), s*100.0, Math.round(p)];
};


<|start_filename|>node_modules/color-space/hcg.js<|end_filename|>
/**
 * @module color-space/hcg
 */
'use strict'

var rgb = require('./rgb');
var hsl = require('./hsl');
var hsv = require('./hsv');
var hwb = require('./hwb');
var mod = require('mumath/mod');


module.exports = {
	name: 'hcg',
	min: [0,0,0],
	max: [360,100,100],
	channel: ['hue', 'chroma', 'gray'],
	alias: ['HCG', 'HSG'],

	rgb: function(hcg) {
		var h = hcg[0] / 360;
		var c = hcg[1] / 100;
		var g = hcg[2] / 100;
		if (c === 0.0) {
			return [g * 255, g * 255, g * 255];
		}
		var hi = mod(h, 1) * 6;
		var v = mod(hi, 1);
		var pure = [0, 0, 0];
		var w = 1 - v;
		switch (Math.floor(hi)) {
			case 0:
				pure[0] = 1; pure[1] = v; pure[2] = 0; break;
			case 1:
				pure[0] = w; pure[1] = 1; pure[2] = 0; break;
			case 2:
				pure[0] = 0; pure[1] = 1; pure[2] = v; break;
			case 3:
				pure[0] = 0; pure[1] = w; pure[2] = 1; break;
			case 4:
				pure[0] = v; pure[1] = 0; pure[2] = 1; break;
			default:
				pure[0] = 1; pure[1] = 0; pure[2] = w;
		}
		var mg = (1.0 - c) * g;
		var rgb = [
			(c * pure[0] + mg) * 255,
			(c * pure[1] + mg) * 255,
			(c * pure[2] + mg) * 255
		];
		return rgb;
	},

	hsl: function(hcg) {
		var c = hcg[1] / 100;
		var g = hcg[2] / 100;
		var l = g * (1.0 - c) + 0.5 * c;
		var s = 0;
		if (l < 1.0 && l > 0.0) {
			if (l < 0.5) {
				s = c / (2 * l);
			} else {
				s = c / (2 * (1 - l));
			}
		}
		return [hcg[0], s * 100, l * 100];
	},

	hsv: function(hcg){
		var c = hcg[1] / 100;
		var g = hcg[2] / 100;
		var v = c + g * (1.0 - c);
		var res;
		if (v > 0.0) {
			var f = c / v;
			res = [hcg[0], f * 100, v * 100];
		} else {
			res = [hcg[0], 0, v * 100];
		}
		return res;
	},

	hwb: function(hcg){
		var c = hcg[1] / 100;
		var g = hcg[2] / 100;
		var v = c + g * (1.0 - c);
		return [hcg[0], (v - c) * 100, (1 - v) * 100];
	}
};


//append rgb
rgb.hcg = function(rgb) {
	var r = rgb[0] / 255;
	var g = rgb[1] / 255;
	var b = rgb[2] / 255;
	var max = Math.max(Math.max(r, g), b);
	var min = Math.min(Math.min(r, g), b);
	var chroma = (max - min);
	var grayscale;
	var hue;
	if (chroma < 1) {
		grayscale = min / (1 - chroma);
	} else {
		grayscale = 0;
	}
	if (chroma > 0) {
		if (max === r) {
			hue = mod((g - b) / chroma, 6);
		} else
		if (max === g) {
			hue = 2 + (b - r) / chroma;
		} else {
			hue = 4 + (r - g) / chroma;
		}
		hue /= 6;
		hue = mod(hue, 1);
	} else {
		hue = 0;
	}
	return [hue * 360, chroma * 100, grayscale * 100];
};

//extend hsl
hsl.hcg = function(hsl) {
	var s = hsl[1] / 100;
	var l = hsl[2] / 100;
	var c = 0;
	if (l < 0.5) {
		c = 2.0 * s * l;
	} else {
		c = 2.0 * s * (1.0 - l);
	}
	var res;
	if (c < 1.0) {
		var f = (l - 0.5 * c) / (1.0 - c);
		res = [hsl[0], c * 100, f * 100];
	} else {
		res = [hsl[0], c * 100, 0];
	}
	return res;
};

//extend hsv
hsv.hcg = function(hsv){
	var s = hsv[1] / 100;
	var v = hsv[2] / 100;
	var c = s * v;
	var res;
	if (c < 1.0) {
		var f = (v - c) / (1 - c);
		res = [hsv[0], c * 100, f * 100];
	} else {
		res = [hsv[0], c * 100, 0];
	}
	return res;
}


//extend hwb
hwb.hcg = function(hwb){
	var w = hwb[1] / 100;
	var b = hwb[2] / 100;
	var v = 1 - b;
	var c = v - w;
	var g = 0;
	if (c < 1) {
		g = (v - c) / (1 - c);
	}
	return [hwb[0], c * 100, g * 100];
}


<|start_filename|>node_modules/color-space/hsluv.js<|end_filename|>
/**
 * A uniform wrapper for hsluv.
 * // http://www.hsluv.org/
 *
 * @module color-space/hsluv
 */
'use strict'

var xyz = require('./xyz');
var lchuv = require('./lchuv');
var _hsluv = require('hsluv');


module.exports = {
	name: 'hsluv',
	min: [0,0,0],
	max: [360,100,100],
	channel: ['hue', 'saturation', 'lightness'],
	alias: ['HSLuv', 'HuSL'],

	lchuv: _hsluv.hsluvToLch,

	xyz: function(arg){
		return lchuv.xyz(_hsluv.hsluvToLch(arg));
	},

	//a shorter way to convert to hpluv
	hpluv: function(arg){
		return _hsluv.lchToHpluv( _hsluv.hsluvToLch(arg));
	}
};

//extend lchuv, xyz
lchuv.hsluv = _hsluv.lchToHsluv;
xyz.hsluv = function(arg){
	return _hsluv.lchToHsluv(xyz.lchuv(arg));
};
