<commit_before>'use strict';

const _ = require('lodash');
const utm = require('utm');

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    add(p) {
        return new Point(this.x + p.x, this.y + p.y);
    }

    subtract(p) {
        return new Point(this.x - p.x, this.y - p.y);
    }

    scale(d) {
        return new Point(this.x * d, this.y * d);
    }

    rotate(alpha) {
        return new Point(this.x * Math.cos(alpha) - this.y * Math.sin(alpha), this.x * Math.sin(alpha) + this.y * Math.cos(alpha));
    }

    rotate(alpha, center) {
        return this.subtract(center).rotate(alpha).add(center);
    }

    distance(p) {
        const dx = this.x - p.x;
        const dy = this.y - p.y;
        return Math.sqrt(dx * dx + dy * dy);
    }

    cross(p) {
        return this.x * p.y - this.y * p.x;
    }
}

class Segment {
    constructor(p1, p2) {
        this.p1 = p1;
        this.p2 = p2;
    }

    /**
     * Find a point Q that divides the segment into ratio a/b
     */
    divider(a, b) {
        return this.p1.scale(b).add(this.p2.scale(a)).scale(1 / (a + b));
    }

    midpoint() {
        return this.divider(1, 1);
    }
}

class Line {
    constructor(p1, p2) {
        this.p1 = p1;
        this.p2 = p2;
    }

    intersection(s2) {
        const x1 = this.p1.x - this.p2.x;
        const x2 = s2.p1.x - s2.p2.x;
        const y1 = this.p1.y - this.p2.y;
        const y2 = s2.p1.y - s2.p2.y;
        const cross1 = this.p1.cross(this.p2);
        const cross2 = s2.p1.cross(s2.p2);
        const det = x1 * y2 - x2 * y1;
        return new Point(
            (cross1 * x2 - cross2 * x1) / det,
            (cross1 * y2 - cross2 * y1) / det
        );
    }
}

class Circle {
    constructor(center, r) {
        this.center = center;
        this.r = r;
    }
}

const midpointOfIntersection = (c1, c2) => {
    const segment = new Segment(c1.center, c2.center);
    return segment.divider(c1.r, c2.r);
};

const circumcenter = (p, q, r) => {
    console.log(`P: ${JSON.stringify(p)}`);
    console.log(`Q: ${JSON.stringify(p)}`);
    console.log(`R: ${JSON.stringify(p)}`);
    const pq = (new Segment(p, q)).midpoint();
    const qr = (new Segment(q, r)).midpoint();
    console.log(`PQ: ${JSON.stringify(pq)}`);
    console.log(`QR: ${JSON.stringify(qr)}`);
    const lineBisectorPQ = new Line(p.rotate(Math.PI / 2, pq), q.rotate(Math.PI / 2, pq));
    const lineBisectorQR = new Line(q.rotate(Math.PI / 2, qr), r.rotate(Math.PI / 2, qr));
    return lineBisectorPQ.intersection(lineBisectorQR);
};

const triangleArea = (p, q, r) => {
    return 0.5 * Math.abs(p.x * q.y + q.x * r.y + r.x * p.y - p.y * q.x - q.y * r.x - r.y * p.x);
};

const circumradius = (p, q, r) => {
    return p.distance(q) * q.distance(r) * r.distance(p) / (4 * triangleArea(p, q, r));
};

const circumcircle = (p, q, r) => {
    return new Circle(circumcenter(p, q, r), circumradius(p, q, r));
};

const dilaterationCartesian = (c1, c2) => {
    const p = midpointOfIntersection(c1, c2);
    const d = Math.abs(c1.r + c2.r - c1.center.distance(c2.center)) / 2;
    console.log(`r1 = ${c1.r}, r2 = ${c2.r} => d = ${d}`);
    return new Circle(p, d);
};

const multilaterationCartesian = (circles) => {
    const n = circles.length;
    let c = circles[0], i;
    for (i = 1; i < n; ++i) {
        c = dilaterationCartesian(c, circles[i]);
    }
    console.log(`multilaterate: ${JSON.stringify(c)}`);
    return c;
};

const trilaterationCartesian = (c1, c2, c3) => {
    console.log(`C1: ${JSON.stringify(c1)}`);
    console.log(`C2: ${JSON.stringify(c2)}`);
    console.log(`C3: ${JSON.stringify(c3)}`);
    // find midpoint of intersections of each pair of circles
    const p = midpointOfIntersection(c1, c2);
    const q = midpointOfIntersection(c2, c3);
    const r = midpointOfIntersection(c3, c1);
    const g = p.add(q).add(r).scale(1/3);

    return circumcircle(p, q, r);
};

const utmToPoint = (utm) => {
    return new Point(utm.easting, utm.northing);
};

const multilateration = (coords) => {
    const utms = _.map(coords, (coord) => utm.fromLatLon(coord.latitude, coord.longitude));
    const cs = _.map(utms, (utm, i) => new Circle(utmToPoint(utm), coords[i].accuracy));
    const c = multilaterationCartesian(cs);
    console.log(`utms: ${JSON.stringify(utms)}`);
    const latlon = utm.toLatLon(c.center.x, c.center.y, utms[0].zoneNum, utms[0].zoneLetter);
    return {
        latitude: latlon.latitude,
        longitude: latlon.longitude,
        accuracy: c.r
    };
};

const trilateration = (coord1, coord2, coord3) => {
    console.log(`COORD1: ${JSON.stringify(coord1)}`);
    console.log(`COORD2: ${JSON.stringify(coord2)}`);
    console.log(`COORD3: ${JSON.stringify(coord3)}`);
    const utm1 = utm.fromLatLon(coord1.latitude, coord1.longitude);
    const utm2 = utm.fromLatLon(coord2.latitude, coord2.longitude);
    const utm3 = utm.fromLatLon(coord3.latitude, coord3.longitude);

    console.log(`UTM1: ${JSON.stringify(utm1)}`);
    console.log(`UTM2: ${JSON.stringify(utm2)}`);
    console.log(`UTM3: ${JSON.stringify(utm3)}`);

    const c1 = new Circle(utmToPoint(utm1), coord1.accuracy);
    const c2 = new Circle(utmToPoint(utm2), coord2.accuracy);
    const c3 = new Circle(utmToPoint(utm3), coord3.accuracy);

    const c = trilaterationCartesian(c1, c2, c3);

    const latlon = utm.toLatLon(c.center.x / 1000, c.center.y / 1000, utm1.zoneNum, utm1.zoneLetter);
    return {
        latitude: latlon.latitude,
        longitude: latlon.longitude,
        accuracy: c.r
    };
};

module.exports = {
    Point,
    Segment,
    Line,
    Circle,
    trilaterationCartesian,
    trilateration,
    multilaterationCartesian,
    multilateration
};
<commit_msg>[API] fix multiliteration bug<commit_after>'use strict';

const _ = require('lodash');
const utm = require('utm');

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    add(p) {
        return new Point(this.x + p.x, this.y + p.y);
    }

    subtract(p) {
        return new Point(this.x - p.x, this.y - p.y);
    }

    scale(d) {
        return new Point(this.x * d, this.y * d);
    }

    rotate(alpha) {
        return new Point(this.x * Math.cos(alpha) - this.y * Math.sin(alpha), this.x * Math.sin(alpha) + this.y * Math.cos(alpha));
    }

    rotate(alpha, center) {
        return this.subtract(center).rotate(alpha).add(center);
    }

    distance(p) {
        const dx = this.x - p.x;
        const dy = this.y - p.y;
        return Math.sqrt(dx * dx + dy * dy);
    }

    cross(p) {
        return this.x * p.y - this.y * p.x;
    }
}

class Segment {
    constructor(p1, p2) {
        this.p1 = p1;
        this.p2 = p2;
    }

    /**
     * Find a point Q that divides the segment into ratio a/b
     */
    divider(a, b) {
        return this.p1.scale(b).add(this.p2.scale(a)).scale(1 / (a + b));
    }

    midpoint() {
        return this.divider(1, 1);
    }
}

class Line {
    constructor(p1, p2) {
        this.p1 = p1;
        this.p2 = p2;
    }

    intersection(s2) {
        const x1 = this.p1.x - this.p2.x;
        const x2 = s2.p1.x - s2.p2.x;
        const y1 = this.p1.y - this.p2.y;
        const y2 = s2.p1.y - s2.p2.y;
        const cross1 = this.p1.cross(this.p2);
        const cross2 = s2.p1.cross(s2.p2);
        const det = x1 * y2 - x2 * y1;
        return new Point(
            (cross1 * x2 - cross2 * x1) / det,
            (cross1 * y2 - cross2 * y1) / det
        );
    }
}

class Circle {
    constructor(center, r) {
        this.center = center;
        this.r = r;
    }
}

const midpointOfIntersection = (c1, c2) => {
    const segment = new Segment(c1.center, c2.center);
    return segment.divider(c1.r, c2.r);
};

const circumcenter = (p, q, r) => {
    console.log(`P: ${JSON.stringify(p)}`);
    console.log(`Q: ${JSON.stringify(p)}`);
    console.log(`R: ${JSON.stringify(p)}`);
    const pq = (new Segment(p, q)).midpoint();
    const qr = (new Segment(q, r)).midpoint();
    console.log(`PQ: ${JSON.stringify(pq)}`);
    console.log(`QR: ${JSON.stringify(qr)}`);
    const lineBisectorPQ = new Line(p.rotate(Math.PI / 2, pq), q.rotate(Math.PI / 2, pq));
    const lineBisectorQR = new Line(q.rotate(Math.PI / 2, qr), r.rotate(Math.PI / 2, qr));
    return lineBisectorPQ.intersection(lineBisectorQR);
};

const triangleArea = (p, q, r) => {
    return 0.5 * Math.abs(p.x * q.y + q.x * r.y + r.x * p.y - p.y * q.x - q.y * r.x - r.y * p.x);
};

const circumradius = (p, q, r) => {
    return p.distance(q) * q.distance(r) * r.distance(p) / (4 * triangleArea(p, q, r));
};

const circumcircle = (p, q, r) => {
    return new Circle(circumcenter(p, q, r), circumradius(p, q, r));
};

const dilaterationCartesian = (c1, c2) => {
    const p = midpointOfIntersection(c1, c2);
    const d = c1.center.distance(c2.center);
    let r = Math.abs(c1.r + c2.r - d) / 2;
    if (c1.r + d < c2.r) {
        r = c1.r;
    }
    if (c2.r + d < c1.r) {
        r = c2.r;
    }
    console.log(`r1 = ${c1.r}, r2 = ${c2.r}, d = ${d} => r = ${r}`);
    return new Circle(p, r);
};

const multilaterationCartesian = (circles) => {
    const n = circles.length;
    let c = circles[0], i;
    for (i = 1; i < n; ++i) {
        c = dilaterationCartesian(c, circles[i]);
    }
    console.log(`multilaterate: ${JSON.stringify(c)}`);
    return c;
};

const trilaterationCartesian = (c1, c2, c3) => {
    console.log(`C1: ${JSON.stringify(c1)}`);
    console.log(`C2: ${JSON.stringify(c2)}`);
    console.log(`C3: ${JSON.stringify(c3)}`);
    // find midpoint of intersections of each pair of circles
    const p = midpointOfIntersection(c1, c2);
    const q = midpointOfIntersection(c2, c3);
    const r = midpointOfIntersection(c3, c1);
    const g = p.add(q).add(r).scale(1/3);

    return circumcircle(p, q, r);
};

const utmToPoint = (utm) => {
    return new Point(utm.easting, utm.northing);
};

const multilateration = (coords) => {
    const utms = _.map(coords, (coord) => utm.fromLatLon(coord.latitude, coord.longitude));
    const cs = _.map(utms, (utm, i) => new Circle(utmToPoint(utm), coords[i].accuracy));
    const c = multilaterationCartesian(cs);
    console.log(`utms: ${JSON.stringify(utms)}`);
    const latlon = utm.toLatLon(c.center.x, c.center.y, utms[0].zoneNum, utms[0].zoneLetter);
    return {
        latitude: latlon.latitude,
        longitude: latlon.longitude,
        accuracy: c.r
    };
};

const trilateration = (coord1, coord2, coord3) => {
    console.log(`COORD1: ${JSON.stringify(coord1)}`);
    console.log(`COORD2: ${JSON.stringify(coord2)}`);
    console.log(`COORD3: ${JSON.stringify(coord3)}`);
    const utm1 = utm.fromLatLon(coord1.latitude, coord1.longitude);
    const utm2 = utm.fromLatLon(coord2.latitude, coord2.longitude);
    const utm3 = utm.fromLatLon(coord3.latitude, coord3.longitude);

    console.log(`UTM1: ${JSON.stringify(utm1)}`);
    console.log(`UTM2: ${JSON.stringify(utm2)}`);
    console.log(`UTM3: ${JSON.stringify(utm3)}`);

    const c1 = new Circle(utmToPoint(utm1), coord1.accuracy);
    const c2 = new Circle(utmToPoint(utm2), coord2.accuracy);
    const c3 = new Circle(utmToPoint(utm3), coord3.accuracy);

    const c = trilaterationCartesian(c1, c2, c3);

    const latlon = utm.toLatLon(c.center.x / 1000, c.center.y / 1000, utm1.zoneNum, utm1.zoneLetter);
    return {
        latitude: latlon.latitude,
        longitude: latlon.longitude,
        accuracy: c.r
    };
};

module.exports = {
    Point,
    Segment,
    Line,
    Circle,
    trilaterationCartesian,
    trilateration,
    multilaterationCartesian,
    multilateration
};
<|endoftext|>


<commit_before>// retrieve a JSON from a url
//***************************************
function grabJSON (url) {
  return $.ajax({
    url: url,
  })
}
//***************************************

//build bootstrap-select dropdown using json
//***************************************
function dropdownFromJSON (div_id, ajax_response) {
  $.each(ajax_response, function(name, file) {
       $(div_id).append($('<option/>').attr("value", file).text(name));
    });
  $('.selectpicker').selectpicker('refresh');
}
//***************************************

//build svg scales based on slider pick
//***************************************
function svgScales (div_id, bins, scale) {
  var sq = 25 // length of rect square sides
  var svg_container = $(div_id)
  svg_container.html("")
  var svg = document.createElementNS("http://www.w3.org/2000/svg", 'svg');
  svg.setAttribute('width', String(sq*bins))
  svg.setAttribute('height', String(sq))
  for (i=0; i<bins; i++){
    var x=(i*sq)
    var rect = document.createElementNS("http://www.w3.org/2000/svg", 'rect');
    rect.setAttribute('fill', colorbrewer[scale][bins][i])
    rect.setAttribute('width', String(sq))
    rect.setAttribute('height', String(sq))
    rect.setAttribute('x', String(i*sq))
    svg.appendChild(rect)
  }
  svg_container.append(svg)
}
//***************************************

// get preset_pos for McCormick model
//***************************************
// function to set preset_pos for McCormick model
//***************************************
function setPresetPos () {
  grabJSON("static/models/" + prebuilt_model + "/preset_pos.json").then(function (ajax_response) {
    preset_pos = ajax_response;
    preset_pos_static = preset_pos
  })
}
//***************************************

//download a model
//***************************************
function download(filename, text) {
    var element = document.createElement('a');
    element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
    element.setAttribute('download', filename);

    element.style.display = 'none';
    document.body.appendChild(element);

    element.click();

    document.body.removeChild(element);
}
//***************************************

//send text to REACH, get back stmts
//***************************************
function txtReach(txt) {
  var input_txt = {'text':txt}
  console.log(input_txt)
  console.log("converting text to statements via REACH");
  return $.ajax({
                url: indra_server_addr + "/reach/process_text",
                type: "POST",
                dataType: "json",
                data: JSON.stringify(input_txt),
                });
}

// send stmts to grounding mapper, get grounded stmts
//***************************************
function groundingMapper(res) {
  var stmts = res
  return $.ajax({
                url: indra_server_addr + "/preassembly/map_grounding",
                type: "POST",
                dataType: "json",
                data: JSON.stringify(stmts),
                });
}
//***************************************

function assembleCyJS(res) {
  var res_json = res
  res_json['line'] = $('#cellSelectDynamic').val().slice(6,-5)
  console.log(res_json)
  console.log("converting statements to cyjs");
  return $.ajax({
      url: indra_server_addr + "/assemblers/cyjs",
      type: "POST",
      dataType: "json",
      data: JSON.stringify(res_json),
  });
}

function assemblePySB(res) {
  var res_json = res
  res_json['line'] = $('#cellSelectDynamic').val().slice(6,-5)
  console.log(res_json)
  console.log("converting statements to cyjs");
  return $.ajax({
      url: indra_server_addr + "/assemblers/pysb",
      type: "POST",
      dataType: "json",
      data: JSON.stringify(res_json),
  });
}

function assembleLoopy(res) {
  var res_json = res
  res_json['line'] = $('#cellSelectDynamic').val().slice(6,-5)
  console.log(res_json)
  console.log("converting statements to cyjs");
  return $.ajax({
      url: indra_server_addr + "/assemblers/sif/loopy",
      type: "POST",
      dataType: "json",
      data: JSON.stringify(res_json),
  });
}

var mrna;
function get_ccle_mrna_amounts(gene_list, cell_line) {
  var input_txt = {'gene_list': gene_list,
                   'cell_lines': [cell_line]}
  console.log(input_txt)
  console.log("asking for mrna");
  return $.ajax({
            url: indra_server_addr + "/databases/cbio/ccle_mrna_amounts",
            type: "POST",
            dataType: "json",
            data: JSON.stringify(input_txt),
           }).then(function(res){
                      res = res["mrna_amounts"]
                      res = res.replace(/NaN/g, "null")
                      res = JSON.parse(res)
                      res = res[cell_line]
                      mrna = res;
                  })
}

var cna;
function get_ccle_cna(gene_list, cell_line) {
  var input_txt = {'gene_list': gene_list,
                   'cell_lines': [cell_line]}
  console.log(input_txt)
  console.log("asking for cna");
  return $.ajax({
            url: indra_server_addr + "/databases/cbio/ccle_cna",
            type: "POST",
            dataType: "json",
            data: JSON.stringify(input_txt),
           }).then(function(res){
                      res = res["cna"]
                      res = res.replace(/NaN/g, "null")
                      res = JSON.parse(res)
                      res = res[cell_line]
                      cna = res;
                  })
}
<commit_msg>Change API functions to reflect name changes in INDRA API function names<commit_after>// retrieve a JSON from a url
//***************************************
function grabJSON (url) {
  return $.ajax({
    url: url,
  })
}
//***************************************

//build bootstrap-select dropdown using json
//***************************************
function dropdownFromJSON (div_id, ajax_response) {
  $.each(ajax_response, function(name, file) {
       $(div_id).append($('<option/>').attr("value", file).text(name));
    });
  $('.selectpicker').selectpicker('refresh');
}
//***************************************

//build svg scales based on slider pick
//***************************************
function svgScales (div_id, bins, scale) {
  var sq = 25 // length of rect square sides
  var svg_container = $(div_id)
  svg_container.html("")
  var svg = document.createElementNS("http://www.w3.org/2000/svg", 'svg');
  svg.setAttribute('width', String(sq*bins))
  svg.setAttribute('height', String(sq))
  for (i=0; i<bins; i++){
    var x=(i*sq)
    var rect = document.createElementNS("http://www.w3.org/2000/svg", 'rect');
    rect.setAttribute('fill', colorbrewer[scale][bins][i])
    rect.setAttribute('width', String(sq))
    rect.setAttribute('height', String(sq))
    rect.setAttribute('x', String(i*sq))
    svg.appendChild(rect)
  }
  svg_container.append(svg)
}
//***************************************

// get preset_pos for McCormick model
//***************************************
// function to set preset_pos for McCormick model
//***************************************
function setPresetPos () {
  grabJSON("static/models/" + prebuilt_model + "/preset_pos.json").then(function (ajax_response) {
    preset_pos = ajax_response;
    preset_pos_static = preset_pos
  })
}
//***************************************

//download a model
//***************************************
function download(filename, text) {
    var element = document.createElement('a');
    element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
    element.setAttribute('download', filename);

    element.style.display = 'none';
    document.body.appendChild(element);

    element.click();

    document.body.removeChild(element);
}
//***************************************

//send text to REACH, get back stmts
//***************************************
function txtReach(txt) {
  var input_txt = {'text':txt}
  console.log(input_txt)
  console.log("converting text to statements via REACH");
  return $.ajax({
                url: indra_server_addr + "/reach/process_text",
                type: "POST",
                dataType: "json",
                data: JSON.stringify(input_txt),
                });
}

// send stmts to grounding mapper, get grounded stmts
//***************************************
function groundingMapper(res) {
  var stmts = res
  return $.ajax({
                url: indra_server_addr + "/preassembly/map_grounding",
                type: "POST",
                dataType: "json",
                data: JSON.stringify(stmts),
                });
}
//***************************************

function assembleCyJS(res) {
  var res_json = res
  res_json['line'] = $('#cellSelectDynamic').val().slice(6,-5)
  console.log(res_json)
  console.log("converting statements to cyjs");
  return $.ajax({
      url: indra_server_addr + "/assemblers/cyjs",
      type: "POST",
      dataType: "json",
      data: JSON.stringify(res_json),
  });
}

function assemblePySB(res) {
  var res_json = res
  res_json['line'] = $('#cellSelectDynamic').val().slice(6,-5)
  console.log(res_json)
  console.log("converting statements to cyjs");
  return $.ajax({
      url: indra_server_addr + "/assemblers/pysb",
      type: "POST",
      dataType: "json",
      data: JSON.stringify(res_json),
  });
}

function assembleLoopy(res) {
  var res_json = res
  res_json['line'] = $('#cellSelectDynamic').val().slice(6,-5)
  console.log(res_json)
  console.log("converting statements to cyjs");
  return $.ajax({
      url: indra_server_addr + "/assemblers/sif/loopy",
      type: "POST",
      dataType: "json",
      data: JSON.stringify(res_json),
  });
}

var mrna;
function get_ccle_mrna_amounts(gene_list, cell_line) {
  var input_txt = {'gene_list': gene_list,
                   'cell_lines': [cell_line]}
  console.log(input_txt)
  console.log("asking for mrna");
  return $.ajax({
            url: indra_server_addr + "/databases/cbio/get_ccle_mrna_amounts",
            type: "POST",
            dataType: "json",
            data: JSON.stringify(input_txt),
           }).then(function(res){
                      res = res["mrna_amounts"]
                      res = res.replace(/NaN/g, "null")
                      res = JSON.parse(res)
                      res = res[cell_line]
                      mrna = res;
                  })
}

var cna;
function get_ccle_cna(gene_list, cell_line) {
  var input_txt = {'gene_list': gene_list,
                   'cell_lines': [cell_line]}
  console.log(input_txt)
  console.log("asking for cna");
  return $.ajax({
            url: indra_server_addr + "/databases/cbio/get_ccle_cna",
            type: "POST",
            dataType: "json",
            data: JSON.stringify(input_txt),
           }).then(function(res){
                      res = res["cna"]
                      res = res.replace(/NaN/g, "null")
                      res = JSON.parse(res)
                      res = res[cell_line]
                      cna = res;
                  })
}
<|endoftext|>


<commit_before>var Interpreter = function(context) {
  this.context = context;
  this.define = [];
  this.rules = {};
  this.computed = [];
  this.maxdepth = 100;
  this.depth = 0;
  this.maxobjects = 1000;
  this.objectnum = 0;
  this.minsize = .2;
  this.maxsize = 1.0;
  this.seed = 'initial'; // integer or 'initial'
  this.stack = [];
  this.currMatrix = new THREE.Matrix4();
  this.currHex = Color('#ff0000');
  this.currHsv = exports._.extend(Color({hue: 0, saturation: 1, value: 1}), { computed: false });
  this.currBlend = { color: null, strength: 0, computed: false };
  this.currAlpha = 1;
  this.mt = new MersenneTwister();
}

Interpreter.prototype.terminated = function() {
  if (this.objectnum > this.maxobjects) return true;
  if (this.depth >= this.maxdepth) return true;
  return false;
}

Interpreter.prototype.pushState = function() {
  this.stack.push({
    matrix: this.currMatrix.clone(),
    hex: this.currHex.clone(),
    hsv: this.currHsv.clone(),
    blend: exports._.extend({}, this.currBlend),
    alpha: this.currAlpha
  });
}

Interpreter.prototype.popState = function() {
  if (this.stack.length > 0) {
    var state = this.stack.pop();
    this.currMatrix = state.matrix
    this.currHex = state.hex;
    this.currHsv = state.hsv;
    this.currBlend = state.blend;
    this.currAlpha = state.alpha;
  }
}

// execute eisenscript
Interpreter.prototype.generate = function() {
  var that = this;

  // extends for stacking intermediate product
  this.context = exports._.extend(this.context, {
    objects: []
  });

  // rewriting
  this.context.ast.forEach(function(statement) {
    switch (statement.type) {
      case Symbol.Define: that.define.push(statement); break;
      case Symbol.Set: that.define.push(statement); break;
      case Symbol.Statement: if (statement.computed) that.computed.push(statement); break;
      case Symbol.Rule:
        var rule = that.rewrite(statement);
        if (!that.rules[rule.id]) that.rules[rule.id] = [];
        that.rules[rule.id].push(rule);
        break;
    }
  });

  // creating intermediate code...
  // promise
  this.define.forEach(function(statement) {
    switch (statement.type) {
      case Symbol.Set:
        switch (statement.key) {
          case Condition.Maxdepth: that.maxdepth = statement.value; break;
          case Condition.Maxobjects: that.maxobjects = statement.value; break;
          case Condition.Minsize: that.minsize = statement.value; break;
          case Condition.Maxsize: that.maxsize = statement.value; break;
          case Condition.Seed: that.seed = statement.value; break;
          case Condition.Background: that.generateBackground(statement); break;
        }
        break;
      case Symbol.Define:
        // not implemented
        break;
    }
  });

  // initialize parameter
  this.currMatrix.identity();
  this.mt.setSeed(this.seed === 'initial' ? randInt(0, 65535) : this.seed);

  // execute main
  this.parseStatements(this.computed);

  // return the context that has objects property as code
  return this.context;
}

// rewrite subtree of rules
Interpreter.prototype.rewrite = function(rule) {
  rule.params.forEach(function(param) {
    if (param.type === Symbol.Modifier) {
      switch (param.key) {
        case Condition.Weight: rule.weight = param.value; break;
        case Condition.Maxdepth: rule.maxdepth = param.value; rule.alternate = param.alternate; break;
      }
    }
  });
  return rule;
}

// execute statements
Interpreter.prototype.parseStatements = function(statements) {
  var i = 0, len = statements.length;
  while (i < len) {
    if (this.terminated()) break;
    this.parseStatement(statements[i], 0);
    i++;
  }
}

// execute a statement
Interpreter.prototype.parseStatement = function(statement, index) {
  // parse transformation expression
  var expr = statement.exprs[index];
  if (expr) {
    this.depth++;
    this.pushState();
    for (var i = 0; i < expr.left; i++) {
      if (this.terminated()) break;
      this.parseTransformStatement(expr.right);
      // if statement.exprs[index + 1] is undefined, it would break the transformation loops.
      this.parseStatement(statement, index + 1);
    }
    this.popState();
    this.depth--;
    return;
  }
  // if not primitive, call rule and parse next transformation loops
  if (Primitive.indexOf(statement.id) === -1) {
    var rule = this.sampling(statement.id);
    if (rule) this.parseStatements(rule.body);
    return;
  }
  // achieve the end of nested transformation loops
  this.generatePrimitive(statement);
}

Interpreter.prototype.parseTransformStatement = function(transform) {
  var i = 0, len = transform.properties.length;
  while (i < len) {
    this.parseTransform(transform.properties[i]);
    i++;
  }
}

Interpreter.prototype.parseTransform = function(property) {
  var k = property.key, v = property.value;
  switch (k) {
    case Property.XShift:
      this.currMatrix.translate({ x:v, y:0, z:0 });
      break;
    case Property.YShift:
      this.currMatrix.translate({ x:0, y:v, z:0 });
      break;
    case Property.ZShift:
      this.currMatrix.translate({ x:0, y:0, z:v });
      break;
    case Property.RotateX:
      this.currMatrix.rotateX(degToRad(v));
      break;
    case Property.RotateY:
      this.currMatrix.rotateY(degToRad(v));
      break;
    case Property.RotateZ:
      this.currMatrix.rotateZ(degToRad(v));
      break;
    case Property.Size:
      this.currMatrix.scale({ x:v[0], y:v[1], z:v[2] });
      break;
    case Property.Matrix:
      this.currMatrix.set(v[0], v[1], v[2], 0, v[3], v[4], v[5], 0, v[6], v[7], v[8], 0);
      break;
    case Property.Color:
      this.currHex = Color(v);
      break;
    case Property.Hue:
      this.currHsv.computed = true;
      this.currHsv.hue += v % 360;
      break;
    case Property.Saturation:
      this.currHsv.computed = true;
      this.currHsv.saturation = clamp(this.currHsv.saturation * v, 0, 1);
      break;
    case Property.Brightness:
      this.currHsv.computed = true;
      this.currHsv.value = clamp(this.currHsv.value * v, 0, 1);;
      break;
    case Property.Blend:
      this.currBlend.computed = true;
      this.currBlend.color = property.color;
      this.currBlend.strength = this.currBlend.strength + clamp(property.strength, 0, 1);
      break;
    case Property.Alpha:
      this.currAlpha *= v;
      break;
  }
}

Interpreter.prototype.generatePrimitive = function(statement) {
  // if achieved maxobjects
  this.objectnum++;
  if (this.terminated()) return;

  // blend the current color with the specified color
  if (this.currBlend.computed) {
    this.currHex = this.currHex.toHSV();
    var blend = Color(this.currBlend.color).toHSV();
    this.currHex.hue += (blend.hue - this.currHex.hue) * this.currBlend.strength / 6;
    this.currHex.hue %= 360;
  }

  this.context.objects.push({
    type: Type.Primitive,
    name: statement.id,
    matrix: this.currMatrix.clone(),
    color: this.currHsv.computed ? this.currHex.blend(this.currHsv, 1).toCSS() : this.currHex.toCSS(),
    opacity: this.currAlpha
  });
}

Interpreter.prototype.generateBackground = function(statement) {
  this.context.objects.push({
    type: Type.Background,
    color: statement.value
  });
}

// randomly choose one of rules according to their weights
Interpreter.prototype.sampling = function(name, retry) {
  if (!this.rules[name]) {
    console.warn('eisenscript: undefined rule');
    return;
  }

  var sum = 0;
  this.rules[name].forEach(function(rule) {
    rule.weight = rule.weight || 1;
    sum += rule.weight;
  });

  var rand = this.mt.next() * sum;
  var expected;
  for (var i = 0; i < this.rules[name].length; i++) {
    var rule = this.rules[name][i];
    if (rule.weight - rand < 0) {
      rand -= rule.weight
      continue;
    }
    expected = rule;
    break;
  }

  // if achieve max retry count
  if (!expected) {
    retry = retry || 0;
    if (retry < 3) return this.sampling(name, ++retry);
    return;
  }

  // if achieved maxdepth
  expected.depth = (expected.depth || 0) + 1;
  if (expected.maxdepth && expected.maxdepth < expected.depth) {
    if (expected.alternate) return this.sampling(expected.alternate);
    return;
  }

  // the rule randomly chosen
  return expected;
}<commit_msg>add comment and tiny cleanup<commit_after>var Interpreter = function(context) {
  this.context = context;
  this.define = [];
  this.rules = {};
  this.computed = [];
  this.maxdepth = 100;
  this.depth = 0;
  this.maxobjects = 1000;
  this.objectnum = 0;
  this.minsize = .2;
  this.maxsize = 1.0;
  this.seed = 'initial'; // integer or 'initial'
  this.stack = [];
  this.currMatrix = new THREE.Matrix4();
  this.currHex = Color('#ff0000');
  this.currHsv = exports._.extend(Color({hue: 0, saturation: 1, value: 1}), { computed: false });
  this.currBlend = { color: null, strength: 0, computed: false };
  this.currAlpha = 1;
  this.mt = new MersenneTwister();
}

Interpreter.prototype.terminated = function() {
  if (this.objectnum > this.maxobjects) return true;
  if (this.depth >= this.maxdepth) return true;
  return false;
}

Interpreter.prototype.pushState = function() {
  this.stack.push({
    matrix: this.currMatrix.clone(),
    hex: this.currHex.clone(),
    hsv: this.currHsv.clone(),
    blend: exports._.extend({}, this.currBlend),
    alpha: this.currAlpha
  });
}

Interpreter.prototype.popState = function() {
  if (this.stack.length === 0) return;
  var state = this.stack.pop();
  this.currMatrix = state.matrix
  this.currHex = state.hex;
  this.currHsv = state.hsv;
  this.currBlend = state.blend;
  this.currAlpha = state.alpha;
}

// execute eisenscript
Interpreter.prototype.generate = function() {
  var that = this;

  // extends for stacking intermediate product
  this.context = exports._.extend(this.context, {
    objects: []
  });

  // rewriting
  this.context.ast.forEach(function(statement) {
    switch (statement.type) {
      case Symbol.Define: that.define.push(statement); break;
      case Symbol.Set: that.define.push(statement); break;
      case Symbol.Statement: if (statement.computed) that.computed.push(statement); break;
      case Symbol.Rule:
        var rule = that.rewrite(statement);
        if (!that.rules[rule.id]) that.rules[rule.id] = [];
        that.rules[rule.id].push(rule);
        break;
    }
  });

  // creating intermediate code...
  // promise
  this.define.forEach(function(statement) {
    switch (statement.type) {
      case Symbol.Set:
        switch (statement.key) {
          case Condition.Maxdepth: that.maxdepth = statement.value; break;
          case Condition.Maxobjects: that.maxobjects = statement.value; break;
          case Condition.Minsize: that.minsize = statement.value; break;
          case Condition.Maxsize: that.maxsize = statement.value; break;
          case Condition.Seed: that.seed = statement.value; break;
          case Condition.Background: that.generateBackground(statement); break;
        }
        break;
      case Symbol.Define:
        // not implemented
        break;
    }
  });

  // initialize parameter
  this.currMatrix.identity();
  this.mt.setSeed(this.seed === 'initial' ? randInt(0, 65535) : this.seed);

  // execute main
  this.parseStatements(this.computed);

  // return the context that has objects property as code
  return this.context;
}

// rewrite subtree of rules
Interpreter.prototype.rewrite = function(rule) {
  rule.params.forEach(function(param) {
    if (param.type === Symbol.Modifier) {
      switch (param.key) {
        case Condition.Weight: rule.weight = param.value; break;
        case Condition.Maxdepth: rule.maxdepth = param.value; rule.alternate = param.alternate; break;
      }
    }
  });
  return rule;
}

// execute statements
Interpreter.prototype.parseStatements = function(statements) {
  var i = 0, len = statements.length;
  while (i < len) {
    if (this.terminated()) break;
    this.parseStatement(statements[i], 0);
    i++;
  }
}

// execute a statement
Interpreter.prototype.parseStatement = function(statement, index) {
  // parse transformation expression
  var expr = statement.exprs[index];
  if (expr) {
    this.depth++;
    this.pushState();
    for (var i = 0; i < expr.left; i++) {
      if (this.terminated()) break;
      this.parseTransformStatement(expr.right);
      // if statement.exprs[index + 1] is undefined, it would break the transformation loops.
      this.parseStatement(statement, index + 1);
    }
    this.popState();
    this.depth--;
    return;
  }
  // if not primitive, call rule and parse next transformation loops
  if (Primitive.indexOf(statement.id) === -1) {
    var rule = this.sampling(statement.id);
    if (rule) this.parseStatements(rule.body);
    return;
  }
  // achieve the end of nested transformation loops
  this.generatePrimitive(statement);
}

Interpreter.prototype.parseTransformStatement = function(transform) {
  var i = 0, len = transform.properties.length;
  while (i < len) {
    this.parseTransform(transform.properties[i]);
    i++;
  }
}

Interpreter.prototype.parseTransform = function(property) {
  var k = property.key, v = property.value;
  switch (k) {
    case Property.XShift:
      this.currMatrix.translate({ x:v, y:0, z:0 });
      break;
    case Property.YShift:
      this.currMatrix.translate({ x:0, y:v, z:0 });
      break;
    case Property.ZShift:
      this.currMatrix.translate({ x:0, y:0, z:v });
      break;
    case Property.RotateX:
      this.currMatrix.rotateX(degToRad(v));
      break;
    case Property.RotateY:
      this.currMatrix.rotateY(degToRad(v));
      break;
    case Property.RotateZ:
      this.currMatrix.rotateZ(degToRad(v));
      break;
    case Property.Size:
      this.currMatrix.scale({ x:v[0], y:v[1], z:v[2] });
      break;
    case Property.Matrix:
      this.currMatrix.set(v[0], v[1], v[2], 0, v[3], v[4], v[5], 0, v[6], v[7], v[8], 0);
      break;
    case Property.Color:
      this.currHex = Color(v);
      break;
    case Property.Hue:
      this.currHsv.computed = true;
      this.currHsv.hue += v % 360;
      break;
    case Property.Saturation:
      this.currHsv.computed = true;
      this.currHsv.saturation = clamp(this.currHsv.saturation * v, 0, 1);
      break;
    case Property.Brightness:
      this.currHsv.computed = true;
      this.currHsv.value = clamp(this.currHsv.value * v, 0, 1);;
      break;
    case Property.Blend:
      this.currBlend.computed = true;
      this.currBlend.color = property.color;
      this.currBlend.strength = this.currBlend.strength + clamp(property.strength, 0, 1);
      break;
    case Property.Alpha:
      this.currAlpha *= v;
      break;
  }
}

Interpreter.prototype.generatePrimitive = function(statement) {
  // if achieved maxobjects
  this.objectnum++;
  if (this.terminated()) return;

  // blend the current color with the specified color
  if (this.currBlend.computed) {
    this.currHex = this.currHex.toHSV();
    var blend = Color(this.currBlend.color).toHSV();
    this.currHex.hue += (blend.hue - this.currHex.hue) * this.currBlend.strength / 6;
    this.currHex.hue %= 360;
  }

  // create primitive object
  this.context.objects.push({
    type: Type.Primitive,
    name: statement.id,
    matrix: this.currMatrix.clone(),
    color: this.currHsv.computed ? this.currHex.blend(this.currHsv, 1).toCSS() : this.currHex.toCSS(),
    opacity: this.currAlpha
  });
}

Interpreter.prototype.generateBackground = function(statement) {
  // create background object
  this.context.objects.push({
    type: Type.Background,
    color: statement.value
  });
}

// randomly choose one of rules according to their weights
Interpreter.prototype.sampling = function(name, retry) {
  if (!this.rules[name]) {
    console.warn('eisenscript: undefined rule');
    return;
  }

  var sum = 0;
  this.rules[name].forEach(function(rule) {
    rule.weight = rule.weight || 1;
    sum += rule.weight;
  });

  var rand = this.mt.next() * sum;
  var expected;
  for (var i = 0; i < this.rules[name].length; i++) {
    var rule = this.rules[name][i];
    if (rule.weight - rand < 0) {
      rand -= rule.weight
      continue;
    }
    expected = rule;
    break;
  }

  // if achieve max retry count
  if (!expected) {
    retry = retry || 0;
    if (retry < 3) return this.sampling(name, ++retry);
    return;
  }

  // if achieved maxdepth
  expected.depth = (expected.depth || 0) + 1;
  if (expected.maxdepth && expected.maxdepth < expected.depth) {
    if (expected.alternate) return this.sampling(expected.alternate);
    return;
  }

  // the rule randomly chosen
  return expected;
}<|endoftext|>


<commit_before>$(init);

var INVALIDATE_TIMEOUT_SEC = 50;
var REQUEST_INTERVAL = 2000;

var REMINDER_DELETE_CLIPBOARD = 10000;
var REMINDER_TITLE = "Don't forget!";
var REMINDER_BODY = "Remember to clear your clipboard, your password is still there!";

var DEFAULT_KEY_SIZE = 1024; //TODO test 2048 and persist on browser cache

var _sid;
var _crypt;
var invalidateSid = false;
var requestFinished = true;
var pollingInterval;
var _query_string = parseWindowURL();

function init() {

	if(_query_string && (_query_string.onlyinfo === true || _query_string.onlyinfo === 'true')) {
		$("#qrplaceholder").hide();
	} else {
		detectHttpProtocol();
	}

	//Enable scrolling effect on anchor clicking
	var _root = $('html, body');
	$('a.navbar-link').click(function(event){
		event.preventDefault();
		_root.animate({
			scrollTop: $( $(this).attr('href') ).offset().top
		}, 500);
		return false;
	});

	if(_query_string && _query_string.show) {
		$('a.navbar-link[href$="' + _query_string.show + '"').trigger('click');
		//window.location.hash = "#" + _query_string.show;
	}

}

function requestInit() {
	$("#sidLabel").text("Receiving...");
	$.post("init.php",{PUBLIC_KEY : _crypt.getPublicKey()},"json").done(
		function(data) {
			if(data.status === true) {
				_sid = data['message'];

				if(!checkBrowserSupport()) {
					alertError("Your browser is up to date, please use newer browser");
				} else {
					$("#sidLabel").text(_sid);
					initQrCode();
					initAsyncAjaxRequest();
				}
			} else {
				alertError("Cannot initialize KeeLink",data.message);
			}
		}
	).fail(
		function() {
			alertError("Error","Cannot initilize this service");
		}
	);
}

function generateKeyPair() {
	$("#sidLabel").text("Generating key pair...");
	_crypt = new JSEncrypt({default_key_size: DEFAULT_KEY_SIZE});
	_crypt.getKey();
	console.log(_crypt.getPublicKey());
}

function detectHttpProtocol() {
	//TODO No warn, redirect!
	if (window.location.protocol != "https:") {
		swal({
			title: "Are you sure?",
			text: "This connection is using HTTP protocol so is not secure, would you like to use HTTPS secure protocol?",
			icon: "warning",
			closeOnClickOutside:false,
			closeOnEsc: false,
			dangerMode: true,
			buttons: true
			}).then((value) => {
				if(value) {
					window.location.href = "https:" + window.location.href.substring(window.location.protocol.length);
				} else {
					generateKeyPair();
					requestInit();
				}
		});
	}
}

function parseWindowURL() {
	var query_string = {};
	var query = window.location.href.split("?")[1];
	if(query) {
		var vars = query.split("&");
		for (var i=0;i<vars.length;i++) {
			var pair = vars[i].split("=");
				// If first entry with this name
			if (typeof query_string[pair[0]] === "undefined") {
			query_string[pair[0]] = decodeURIComponent(pair[1]);
				// If second entry with this name
			} else if (typeof query_string[pair[0]] === "string") {
			var arr = [ query_string[pair[0]],decodeURIComponent(pair[1]) ];
			query_string[pair[0]] = arr;
				// If third or later entry with this name
			} else {
			query_string[pair[0]].push(decodeURIComponent(pair[1]));
			}
		}
		return query_string;
	}

}

function initAsyncAjaxRequest() {
	pollingInterval = setInterval(passwordLooker, REQUEST_INTERVAL);
	setTimeout(function () {
		invalidateSid = true;
	},1000 * INVALIDATE_TIMEOUT_SEC);
}

function passwordLooker() {
	if(!invalidateSid) {
		if(requestFinished) {
			requestFinished = false;
			$.post("getpassforsid.php",{'sid':_sid},onSuccess,"json").always(function() {requestFinished = true;});
		}
	} else {
		invalidateSession();
		alertWarn("No password received...","No password was received in the last minute, reload page to start a new session");
	}
}

function initClipboardButton(password) {
	$("#copyBtn").show();
	$("#moreBtn").show().click(
		function(){
			if($("#clearBtn").is(":hidden"))
				$("#clearBtn").slideDown();
			else
				$("#clearBtn").slideUp();
		}
	);

	$("#copyBtn").attr("data-clipboard-text",password);

	//Copy paassowrd to clipboard button
	var clipCopy = new Clipboard('#copyBtn');
	clipCopy.on('success', function() {
		remindDelete();
	});

	//Clear clipboard button
	new Clipboard('#clearBtn');

	$("#clearBtn").click(function() {
		alertSuccess("Ok","Clipboard cleared!");
		$("#moreBtn").click();
	});
}

function initQrCode() {
	var qrcode = new QRCode(document.getElementById("qrcode"), {
		text: "ksid://" + _sid,
		width: 200,
		height: 200,
		colorDark : "#000000",
		colorLight : "#ffffff",
		correctLevel : QRCode.CorrectLevel.H
	});

	setTimeout(function(){ $("#qrcode").css("opacity",1); }, 500);
}

function alertSuccess(title,msg) {
	swal({
	title: title,
	text: msg,
	icon: "success"
	},function() {
		$("#copyBtn").click();
	});
}

function alertInfo(title,msg) {
	swal({
	title: title,
	text: msg,
	icon: "info"
	});
}

function alertWarn(title,msg) {
	swal({
	title: title,
	text: msg,
	icon: "warning"
	});
}

function alertError(title,msg) {
	swal({
	title: title,
	text: msg,
	icon: "error"
	});
}

function checkBrowserSupport() {
	return "XMLHttpRequest" in window;
}

function checkNotificationSupport() {
	return "Notification" in window;
}

function remindDelete() {
	setTimeout(function() {
		if (Notification.permission === "granted") {
			var notification = new Notification(REMINDER_TITLE,{"body":REMINDER_BODY});
		}
		else if (Notification.permission !== 'denied') {
			Notification.requestPermission(function (permission) {
			if (permission === "granted") {
				var notification = new Notification(REMINDER_TITLE,{"body":REMINDER_BODY});
			}
			});
		}
	},REMINDER_DELETE_CLIPBOARD);
}

function onSuccess(data,textStatus,jqXhr) {
	if(data != undefined && data.status === true) {
		initClipboardButton(_crypt.decrypt(data.message));
		alertSuccess("Password received!","Would you copy password on clipboard? (Also remember to clear your clipboard after usage!)");
		$.post("removeentry.php",{'sid':_sid},function(){},"json");
		invalidateSession();
	}
}

function onFail(data,textStatus,jqXhr) {
	alertError("Comunication Failure","Are you connected to Internet?")
}

function invalidateSession() {
	invalidateSid = true;
	clearInterval(pollingInterval);
	_sid = null;
	$("#sidLabel").css("text-decoration", "line-through");
	$("#qrcode").css("filter", "blur(2px)");
	$("#qrcode").css("-webkit-filter", "blur(2px)");
}
<commit_msg>main.js label update<commit_after>$(init);

var INVALIDATE_TIMEOUT_SEC = 50;
var REQUEST_INTERVAL = 2000;

var REMINDER_DELETE_CLIPBOARD = 10000;
var REMINDER_TITLE = "Don't forget!";
var REMINDER_BODY = "Remember to clear your clipboard, your password is still there!";

var DEFAULT_KEY_SIZE = 1024; //TODO test 2048 and persist on browser cache

var _sid;
var _crypt;
var invalidateSid = false;
var requestFinished = true;
var pollingInterval;
var _query_string = parseWindowURL();

function init() {

	if(_query_string && (_query_string.onlyinfo === true || _query_string.onlyinfo === 'true')) {
		$("#qrplaceholder").hide();
	} else {
		detectHttpProtocol();
	}

	//Enable scrolling effect on anchor clicking
	var _root = $('html, body');
	$('a.navbar-link').click(function(event){
		event.preventDefault();
		_root.animate({
			scrollTop: $( $(this).attr('href') ).offset().top
		}, 500);
		return false;
	});

	if(_query_string && _query_string.show) {
		$('a.navbar-link[href$="' + _query_string.show + '"').trigger('click');
		//window.location.hash = "#" + _query_string.show;
	}

}

function requestInit() {
	$("#sidLabel").text("Receiving...");
	$.post("init.php",{PUBLIC_KEY : _crypt.getPublicKey()},"json").done(
		function(data) {
			if(data.status === true) {
				_sid = data['message'];

				if(!checkBrowserSupport()) {
					alertError("Your browser is up to date, please use newer browser");
				} else {
					$("#sidLabel").text(_sid);
					initQrCode();
					initAsyncAjaxRequest();
				}
			} else {
				alertError("Cannot initialize KeeLink",data.message);
			}
		}
	).fail(
		function() {
			alertError("Error","Cannot initilize this service");
		}
	);
}

function generateKeyPair() {
	$("#sidLabel").text("Generating key pair...");
	_crypt = new JSEncrypt({default_key_size: DEFAULT_KEY_SIZE});
	_crypt.getKey();
	console.log(_crypt.getPublicKey());
}

function detectHttpProtocol() {
	//TODO No warn, redirect!
	$("#sidLabel").text("HTTPS protocol check...");
	if (window.location.protocol != "https:") {
		swal({
			title: "Are you sure?",
			text: "This connection is using HTTP protocol so is not secure, would you like to use HTTPS secure protocol?",
			icon: "warning",
			closeOnClickOutside:false,
			closeOnEsc: false,
			dangerMode: true,
			buttons: true
			}).then((value) => {
				if(value) {
					window.location.href = "https:" + window.location.href.substring(window.location.protocol.length);
				} else {
					generateKeyPair();
					requestInit();
				}
		});
	}
}

function parseWindowURL() {
	var query_string = {};
	var query = window.location.href.split("?")[1];
	if(query) {
		var vars = query.split("&");
		for (var i=0;i<vars.length;i++) {
			var pair = vars[i].split("=");
				// If first entry with this name
			if (typeof query_string[pair[0]] === "undefined") {
			query_string[pair[0]] = decodeURIComponent(pair[1]);
				// If second entry with this name
			} else if (typeof query_string[pair[0]] === "string") {
			var arr = [ query_string[pair[0]],decodeURIComponent(pair[1]) ];
			query_string[pair[0]] = arr;
				// If third or later entry with this name
			} else {
			query_string[pair[0]].push(decodeURIComponent(pair[1]));
			}
		}
		return query_string;
	}

}

function initAsyncAjaxRequest() {
	pollingInterval = setInterval(passwordLooker, REQUEST_INTERVAL);
	setTimeout(function () {
		invalidateSid = true;
	},1000 * INVALIDATE_TIMEOUT_SEC);
}

function passwordLooker() {
	if(!invalidateSid) {
		if(requestFinished) {
			requestFinished = false;
			$.post("getpassforsid.php",{'sid':_sid},onSuccess,"json").always(function() {requestFinished = true;});
		}
	} else {
		invalidateSession();
		alertWarn("No password received...","No password was received in the last minute, reload page to start a new session");
	}
}

function initClipboardButton(password) {
	$("#copyBtn").show();
	$("#moreBtn").show().click(
		function(){
			if($("#clearBtn").is(":hidden"))
				$("#clearBtn").slideDown();
			else
				$("#clearBtn").slideUp();
		}
	);

	$("#copyBtn").attr("data-clipboard-text",password);

	//Copy paassowrd to clipboard button
	var clipCopy = new Clipboard('#copyBtn');
	clipCopy.on('success', function() {
		remindDelete();
	});

	//Clear clipboard button
	new Clipboard('#clearBtn');

	$("#clearBtn").click(function() {
		alertSuccess("Ok","Clipboard cleared!");
		$("#moreBtn").click();
	});
}

function initQrCode() {
	var qrcode = new QRCode(document.getElementById("qrcode"), {
		text: "ksid://" + _sid,
		width: 200,
		height: 200,
		colorDark : "#000000",
		colorLight : "#ffffff",
		correctLevel : QRCode.CorrectLevel.H
	});

	setTimeout(function(){ $("#qrcode").css("opacity",1); }, 500);
}

function alertSuccess(title,msg) {
	swal({
	title: title,
	text: msg,
	icon: "success"
	},function() {
		$("#copyBtn").click();
	});
}

function alertInfo(title,msg) {
	swal({
	title: title,
	text: msg,
	icon: "info"
	});
}

function alertWarn(title,msg) {
	swal({
	title: title,
	text: msg,
	icon: "warning"
	});
}

function alertError(title,msg) {
	swal({
	title: title,
	text: msg,
	icon: "error"
	});
}

function checkBrowserSupport() {
	return "XMLHttpRequest" in window;
}

function checkNotificationSupport() {
	return "Notification" in window;
}

function remindDelete() {
	setTimeout(function() {
		if (Notification.permission === "granted") {
			var notification = new Notification(REMINDER_TITLE,{"body":REMINDER_BODY});
		}
		else if (Notification.permission !== 'denied') {
			Notification.requestPermission(function (permission) {
			if (permission === "granted") {
				var notification = new Notification(REMINDER_TITLE,{"body":REMINDER_BODY});
			}
			});
		}
	},REMINDER_DELETE_CLIPBOARD);
}

function onSuccess(data,textStatus,jqXhr) {
	if(data != undefined && data.status === true) {
		initClipboardButton(_crypt.decrypt(data.message));
		alertSuccess("Password received!","Would you copy password on clipboard? (Also remember to clear your clipboard after usage!)");
		$.post("removeentry.php",{'sid':_sid},function(){},"json");
		invalidateSession();
	}
}

function onFail(data,textStatus,jqXhr) {
	alertError("Comunication Failure","Are you connected to Internet?")
}

function invalidateSession() {
	invalidateSid = true;
	clearInterval(pollingInterval);
	_sid = null;
	$("#sidLabel").css("text-decoration", "line-through");
	$("#qrcode").css("filter", "blur(2px)");
	$("#qrcode").css("-webkit-filter", "blur(2px)");
}
<|endoftext|>


<commit_before>// vim:ts=2:sw=2:expandtab:autoindent:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ash Berlin, Ruediger Sonderfeld

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

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

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

(function() {
  // Load binary module
  $importer.load('curl', true);

  try {
    // If we have HTTP.Headers, define a default header callback that
    // creates
    $importer.load('http.headers');
    cURL.prototype.headerReceived = function headerReceived(hdr) {
      if (hdr.match(/^\r\n/)) {
        // Empty line signals end of headers
        try {
          // Pull out HTTP status line.
          var match = /^(HTTP\/1.[10])\s+(\d+)\s+(.*?)\r\n/.exec(this.header_buffer);
          if (match) {
            this.header_buffer = this.header_buffer.substr(match[0].length);
            [undefined, this.protocol, this.status, this.statusMessage] = match;
          }

          this.headers = HTTP.Headers.parse(this.header_buffer);
          delete this.header_buffer;
        }
        catch (e)
        {
        } // Do nothing on error
      }
      else
        this.header_buffer += hdr;
    },

    cURL.prototype.dataReceived = function (blob) {
      this.responseBlob.append(blob);
    }

    if (cURL.prototype.perform.old === undefined) {
      var old_perform = cURL.prototype.perform;
      cURL.prototype.perform = function perform() {
        this.header_buffer = "";
        delete this.headers;
        this.responseBlob = new Blob(0);
        return perform.old.apply(this, arguments);
      }
      cURL.prototype.perform.old = old_perform;
    }
  }
  catch (e if /Unable to find library/.exec(e))
  { // Stomp on the module not found message
  }

  return cURL;
})()
<commit_msg>Docs: make a start on adding curl docs<commit_after>// vim:ts=2:sw=2:expandtab:autoindent:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ash Berlin, Ruediger Sonderfeld

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

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

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

(function() {
  // Load binary module
  $importer.load('curl', true);

  try {
    // If we have HTTP.Headers, define a default header callback that
    // creates
    $importer.load('http.headers');
    cURL.prototype.headerReceived = function headerReceived(hdr) {
      if (hdr.match(/^\r\n/)) {
        // Empty line signals end of headers
        try {
          // Pull out HTTP status line.
          var match = /^(HTTP\/1.[10])\s+(\d+)\s+(.*?)\r\n/.exec(this.header_buffer);
          if (match) {
            this.header_buffer = this.header_buffer.substr(match[0].length);
            [undefined, this.protocol, this.status, this.statusMessage] = match;
          }

          this.headers = HTTP.Headers.parse(this.header_buffer);
          delete this.header_buffer;
        }
        catch (e)
        {
        } // Do nothing on error
      }
      else
        this.header_buffer += hdr;
    },

    cURL.prototype.dataReceived = function (blob) {
      this.responseBlob.append(blob);
    }

    if (cURL.prototype.perform.old === undefined) {
      var old_perform = cURL.prototype.perform;
      cURL.prototype.perform = function perform() {
        this.header_buffer = "";
        delete this.headers;
        this.responseBlob = new Blob(0);
        return perform.old.apply(this, arguments);
      }
      cURL.prototype.perform.old = old_perform;
    }
  }
  catch (e if /Unable to find library/.exec(e))
  { // Stomp on the module not found message
  }

  return cURL;
})()

/**
 * Class: cURL
 *
 * Network access via libcurl.
 *
 * Group: Constructor Properties
 *
 * Property: supportedProtocols
 *
 * Array of protocols by this module.
 *
 * Property: versionHex
 *
 * libcurl version number in hex. For example 7.18.2 is 0x071202
 *
 * Property: versionStr
 *
 * libcurl version number in dotted-decimal string form.
 *
 * Group: Constructor
 *
 * Constructor: cURL
 *
 * Construct a cURL object. Takes no parameters
 *
 * Group: Methods
 *
 * Method: perform
 *
 * Method: setMethod
 *
 * Group: Properties
 *
 * Property: url
 *
 * Property: protocol
 *
 * Property: status
 *
 * Property: statusMessage
 *
 * Group: Callback Methods
 *
 * Optional methods that get called when headers or data are received. If the
 * <http.headers> module can be loaded, then <headerReceived> will have a default implementation that will parse the headers into an <HTTP.Headers> object
 *
 * Method: dataReceived
 *
 * Method: headerReceived
 */
<|endoftext|>


<commit_before>// ==========================================================================
// Project:   MySystem.EditableLabelView
// Copyright: ©2011 Concord Consortium
// Author:    Noah Paessel <knowuh@gmail.com>
// ==========================================================================
/*globals MySystem RaphaelViews */

/** @class

  RaphaelView for an editable label.

  @extends SC.View
  @extends RaphaelViews.RenderSupport
  @extends SC.Editable
*/
MySystem.EditableLabelView = RaphaelViews.RaphaelView.extend(SC.Editable, {
/** @scope MySystem.EditableLabelView.prototype */

  childViews: ['editBoxView'],
  displayProperties: 'displayText textColor centerX centerY fontSize'.w(),

  // PROPERTIES

  isEditing:     NO,
  isAllSelected: NO,
  fontSize:      12,
  text:          '',
  textColor:     '#000',
  centerX:       0,
  centerY:       0,

  displayText: function () {
    var txt = this.get('text');
    if (this.get('isEditing')) { txt = txt + "_"; }
    return txt;
  }.property('text', 'isEditing').cacheable(),

  textBBox: function () {
    var raphaelText = this.get('raphaelObject');
    return raphaelText ? raphaelText.getBBox() : null;
  }.property('displayText', 'centerX', 'centerY', 'fontSize', 'raphaelObject'),  // don't make this .cacheable(), it doesn't work right

  acceptsFirstResponder: function () {
    return this.get('isEnabled');
  }.property('isEnabled').cacheable(),

  willLoseFirstResponder: function () {
    console.log("loosing first responder");
    this.set('isEditing', NO);
    this.set('isAllSelected', NO);
  },

  renderCallback: function (raphaelCanvas, attrs) {
    return raphaelCanvas.text().attr(attrs);
  },

  render: function (context, firstTime) {
    var attrs = {
          x:             this.get('centerX'),
          y:             this.get('centerY'),
          fill:          this.get('textColor'),
          text:          this.get('displayText'),
          'font-size':   this.get('fontSize'),
          'text-anchor': 'middle'
        },

        raphaelText;

    if (firstTime) {
      context.callback(this, this.renderCallback, attrs);
      this.renderChildViews(context,firstTime);
    }
    else {
      raphaelText = this.get('raphaelObject');
      raphaelText.attr(attrs);
    }
  },

  toggle: function (paramName) {
    this.set(paramName, (! this.get(paramName)));
  },

  editFirstTime: function () {
    var item = this.get('item');

    if (this.get('isEditFirstTimePending')) {
      this.beginEditing();
      this.beginEditing(); // call twice to force selectAll
      // this.set('hasEditedFirstTime', YES);
    }
  }.observes('isEditFirstTimePending'),

  beginEditing: function () {
    if (!this.get('isEditable')) { return NO ; }
    this.becomeFirstResponder();
    if (this.get('isEditing')) {
      this.toggle('isAllSelected');
    }
    else {
      this.set('isEditing', YES);
    }
    return YES ;
  },

  discardEditing: function () {
    return this.commitEditing();
  },

  commitEditing: function () {
    this.resignFirstResponder();
    this.set('isEditing', NO) ;
    return YES ;
  },

  updateText: function (newtext) {
    this.beginPropertyChanges();
    this.set('isAllSelected', NO);
    this.set('text',newtext);
    this.endPropertyChanges();
  },

  keyDown: function (evt) {
    var chr = null;
    if (this.interpretKeyEvents(evt)) {
      return YES;
    }
    if (evt.type === 'keypress') {
      chr = evt.getCharString();
      if (chr) {
        this.appendText(chr);
        return YES;
      }
    }
    return NO;
  },

  appendText: function (chr) {
    if (this.get('isAllSelected')) {
      this.updateText(chr);
    }
    else {
      this.updateText(this.get('text') + chr);
    }
    return YES;
  },

  // @see frameworks/sproutcore/frameworks/desktop/system/key_bindings.js
  insertNewline: function () {
    this.commitEditing();
  },

  // @see frameworks/sproutcore/frameworks/desktop/system/key_bindings.js
  insertTab: function () {
    this.commitEditing();
  },

  // @see frameworks/sproutcore/frameworks/desktop/system/key_bindings.js
  cancel: function () {
    this.discardEditing();
  },

  // @see frameworks/sproutcore/frameworks/desktop/system/key_bindings.js
  selectAll: function() {
    this.set('isAllSelected', YES);
  },

  // @see frameworks/sproutcore/frameworks/desktop/system/key_bindings.js
  deleteBackward: function () {
    var t       = this.get('text'),
        newText = t.substr(0,t.length-1);

    if (this.get('isAllSelected')) {
      newText = "";
    }
    this.updateText(newText);
    return YES;
  },

    recentUp: function(up_now) {
      var now      = new Date().getTime(),// ms
          interval = 202,                 // ms
          maxTime  = 200;                 // ms

      if (typeof this.lastUp !== 'undefined' && this.lastUp) {
        interval  = now - this.lastUp;
        if (interval < maxTime) {
          return YES;
        }
      }
      if (up_now) {
        this.lastUp = now;
      }
      return NO;
    },

    mouseDown: function (evt) {
      // this.startDrag(evt);
      if (this.recentUp(NO)) {
        return YES;
      }
      return YES;
    },

    mouseUp: function(evt) {
      if (this.recentUp(YES)) {
        return this.doubleClick(evt);
      }
      return NO;
    },

    doubleClick: function(evt) {
      this.beginEditing();
      return YES;
    },

  // @see frameworks/sproutcore/frameworks/desktop/system/key_bindings.js
  // only problem is that deleteForward seems bound to "."
  // deleteForward: function () {
  //   return this.deleteBackward();
  // },

  editBoxView: RaphaelViews.RaphaelView.design({
    displayProperties:    'textBBox isAllSelected'.w(),

    textLabelView:        SC.outlet('parentView'),
    isVisibleBinding:     '.textLabelView.isEditing',
    isAllSelectedBinding: '.textLabelView.isAllSelected',
    textBBoxBinding:      '.textLabelView.textBBox',
    textBBoxBindingDefault: SC.Binding.oneWay(),

    minHeight:            18,
    minWidth:             20,
    margin:               2,

    fill:                 '#FF5',
    strokeWidth:          1,
    stroke:               '#CCC',
    editingOpacity:       0.3,
    normalOpacity:        0.05,

    x: function () {
      var textBBox = this.get('textBBox');
      return textBBox ? textBBox.x - this.get('margin') : 0;
    }.property('textBBox').cacheable(),

    y: function () {
      var textBBox = this.get('textBBox');
      return textBBox ? textBBox.y - this.get('margin') : 0;
    }.property('textBBox').cacheable(),

    width: function () {
      var textBBox  = this.get('textBBox'),
          minWidth = this.get('minWidth'),
          width    = textBBox ? textBBox.width + 2 * this.get('margin') : 0;

      return (width >= minWidth) ? width : minWidth;
    }.property('textBBox').cacheable(),

    height: function () {
      var textBBox  = this.get('textBBox'),
          minHeight = this.get('minHeight'),
          height    = textBBox ? textBBox.height + 2 * this.get('margin') : 0;

      return (height >= minHeight) ? height : minHeight;
    }.property('textBBox').cacheable(),

    renderCallback: function (raphaelCanvas, attrs) {
      return raphaelCanvas.rect().attr(attrs);
    },

    render: function (context, firstTime) {
      var raphaelRect,
          opacity = this.get('isAllSelected') ? this.get('editingOpacity') : this.get('normalOpacity'),
          attrs = {
             'fill':         this.get('fill'),
             'fill-opacity': opacity,
             'stroke-width': this.get('strokeWidth'),
             'stroke':       this.get('stroke'),
             'x':            this.get('x'),
             'y':            this.get('y'),
             'width':        this.get('width'),
             'height':       this.get('height')
          };

      if (firstTime) {
        context.callback(this, this.renderCallback, attrs);
      }
      else {
        raphaelRect = this.get('raphaelObject');
        raphaelRect.attr(attrs);
      }
    } // render

  })
});
<commit_msg>[#17128035] can't click to add text to empty label<commit_after>// ==========================================================================
// Project:   MySystem.EditableLabelView
// Copyright: ©2011 Concord Consortium
// Author:    Noah Paessel <knowuh@gmail.com>
// ==========================================================================
/*globals MySystem RaphaelViews */

/** @class

  RaphaelView for an editable label.

  @extends SC.View
  @extends RaphaelViews.RenderSupport
  @extends SC.Editable
*/
MySystem.EditableLabelView = RaphaelViews.RaphaelView.extend(SC.Editable, {
/** @scope MySystem.EditableLabelView.prototype */

  childViews: ['editBoxView'],
  displayProperties: 'displayText textColor centerX centerY fontSize'.w(),

  // PROPERTIES

  isEditing:     NO,
  isAllSelected: NO,
  fontSize:      12,
  text:          '',
  textColor:     '#000',
  centerX:       0,
  centerY:       0,

  displayText: function () {
    var txt = this.get('text');
    if (this.get('isEditing')) {
      txt = txt + "_";
    }
    else {
      txt = (txt.replace(/\s+/g,"") === "") ? "«click to edit»" : txt;
    }
    return txt;
  }.property('text', 'isEditing').cacheable(),

  textBBox: function () {
    var raphaelText = this.get('raphaelObject');
    return raphaelText ? raphaelText.getBBox() : null;
  }.property('displayText', 'centerX', 'centerY', 'fontSize', 'raphaelObject'),  // don't make this .cacheable(), it doesn't work right

  acceptsFirstResponder: function () {
    return this.get('isEnabled');
  }.property('isEnabled').cacheable(),

  willLoseFirstResponder: function () {
    console.log("loosing first responder");
    this.set('isEditing', NO);
    this.set('isAllSelected', NO);
  },

  renderCallback: function (raphaelCanvas, attrs) {
    return raphaelCanvas.text().attr(attrs);
  },

  render: function (context, firstTime) {
    var attrs = {
          x:             this.get('centerX'),
          y:             this.get('centerY'),
          fill:          this.get('textColor'),
          text:          this.get('displayText'),
          'font-size':   this.get('fontSize'),
          'text-anchor': 'middle'
        },

        raphaelText;

    if (firstTime) {
      context.callback(this, this.renderCallback, attrs);
      this.renderChildViews(context,firstTime);
    }
    else {
      raphaelText = this.get('raphaelObject');
      raphaelText.attr(attrs);
    }
  },

  toggle: function (paramName) {
    this.set(paramName, (! this.get(paramName)));
  },

  editFirstTime: function () {
    var item = this.get('item');

    if (this.get('isEditFirstTimePending')) {
      this.beginEditing();
      this.beginEditing(); // call twice to force selectAll
      // this.set('hasEditedFirstTime', YES);
    }
  }.observes('isEditFirstTimePending'),

  beginEditing: function () {
    if (!this.get('isEditable')) { return NO ; }
    this.becomeFirstResponder();
    if (this.get('isEditing')) {
      this.toggle('isAllSelected');
    }
    else {
      this.set('isEditing', YES);
    }
    return YES ;
  },

  discardEditing: function () {
    return this.commitEditing();
  },

  commitEditing: function () {
    this.resignFirstResponder();
    this.set('isEditing', NO) ;
    return YES ;
  },

  updateText: function (newtext) {
    this.beginPropertyChanges();
    this.set('isAllSelected', NO);
    this.set('text',newtext);
    this.endPropertyChanges();
  },

  keyDown: function (evt) {
    var chr = null;
    if (this.interpretKeyEvents(evt)) {
      return YES;
    }
    if (evt.type === 'keypress') {
      chr = evt.getCharString();
      if (chr) {
        this.appendText(chr);
        return YES;
      }
    }
    return NO;
  },

  appendText: function (chr) {
    if (this.get('isAllSelected')) {
      this.updateText(chr);
    }
    else {
      this.updateText(this.get('text') + chr);
    }
    return YES;
  },

  // @see frameworks/sproutcore/frameworks/desktop/system/key_bindings.js
  insertNewline: function () {
    this.commitEditing();
  },

  // @see frameworks/sproutcore/frameworks/desktop/system/key_bindings.js
  insertTab: function () {
    this.commitEditing();
  },

  // @see frameworks/sproutcore/frameworks/desktop/system/key_bindings.js
  cancel: function () {
    this.discardEditing();
  },

  // @see frameworks/sproutcore/frameworks/desktop/system/key_bindings.js
  selectAll: function() {
    this.set('isAllSelected', YES);
  },

  // @see frameworks/sproutcore/frameworks/desktop/system/key_bindings.js
  deleteBackward: function () {
    var t       = this.get('text'),
        newText = t.substr(0,t.length-1);

    if (this.get('isAllSelected')) {
      newText = "";
    }
    this.updateText(newText);
    return YES;
  },

    recentUp: function(up_now) {
      var now      = new Date().getTime(),// ms
          interval = 202,                 // ms
          maxTime  = 200;                 // ms

      if (typeof this.lastUp !== 'undefined' && this.lastUp) {
        interval  = now - this.lastUp;
        if (interval < maxTime) {
          return YES;
        }
      }
      if (up_now) {
        this.lastUp = now;
      }
      return NO;
    },

    mouseDown: function (evt) {
      // this.startDrag(evt);
      if (this.recentUp(NO)) {
        return YES;
      }
      return YES;
    },

    mouseUp: function(evt) {
      if (this.recentUp(YES)) {
        return this.doubleClick(evt);
      }
      return NO;
    },

    doubleClick: function(evt) {
      this.beginEditing();
      return YES;
    },

  // @see frameworks/sproutcore/frameworks/desktop/system/key_bindings.js
  // only problem is that deleteForward seems bound to "."
  // deleteForward: function () {
  //   return this.deleteBackward();
  // },

  editBoxView: RaphaelViews.RaphaelView.design({
    displayProperties:    'textBBox isAllSelected'.w(),

    textLabelView:        SC.outlet('parentView'),
    isVisibleBinding:     '.textLabelView.isEditing',
    isAllSelectedBinding: '.textLabelView.isAllSelected',
    textBBoxBinding:      '.textLabelView.textBBox',
    textBBoxBindingDefault: SC.Binding.oneWay(),

    minHeight:            18,
    minWidth:             20,
    margin:               2,

    fill:                 '#FF5',
    strokeWidth:          1,
    stroke:               '#CCC',
    editingOpacity:       0.3,
    normalOpacity:        0.05,

    x: function () {
      var textBBox = this.get('textBBox');
      return textBBox ? textBBox.x - this.get('margin') : 0;
    }.property('textBBox').cacheable(),

    y: function () {
      var textBBox = this.get('textBBox');
      return textBBox ? textBBox.y - this.get('margin') : 0;
    }.property('textBBox').cacheable(),

    width: function () {
      var textBBox  = this.get('textBBox'),
          minWidth = this.get('minWidth'),
          width    = textBBox ? textBBox.width + 2 * this.get('margin') : 0;

      return (width >= minWidth) ? width : minWidth;
    }.property('textBBox').cacheable(),

    height: function () {
      var textBBox  = this.get('textBBox'),
          minHeight = this.get('minHeight'),
          height    = textBBox ? textBBox.height + 2 * this.get('margin') : 0;

      return (height >= minHeight) ? height : minHeight;
    }.property('textBBox').cacheable(),

    renderCallback: function (raphaelCanvas, attrs) {
      return raphaelCanvas.rect().attr(attrs);
    },

    render: function (context, firstTime) {
      var raphaelRect,
          opacity = this.get('isAllSelected') ? this.get('editingOpacity') : this.get('normalOpacity'),
          attrs = {
             'fill':         this.get('fill'),
             'fill-opacity': opacity,
             'stroke-width': this.get('strokeWidth'),
             'stroke':       this.get('stroke'),
             'x':            this.get('x'),
             'y':            this.get('y'),
             'width':        this.get('width'),
             'height':       this.get('height')
          };

      if (firstTime) {
        context.callback(this, this.renderCallback, attrs);
      }
      else {
        raphaelRect = this.get('raphaelObject');
        raphaelRect.attr(attrs);
      }
    } // render

  })
});
<|endoftext|>


<commit_before>import fetch from 'node-fetch';
import meetupRandomizer from 'meetup-randomizer';
import {
  getParamsFromRequest,
  getEventFromResponseData,
  getIdFromEvent,
} from './helpers';

export async function handler(request /* , context */) {
  const headers =
    import.meta.env.MODE === 'development'
      ? /* c8 ignore next */ { 'Access-Control-Allow-Origin': '*' }
      : {};

  let meetup;
  let count;

  try {
    ({ meetup, count } = getParamsFromRequest(request));
  } catch (err) {
    return {
      headers,
      statusCode: 400,
      body: JSON.stringify({ error: { message: err.message } }),
    };
  }

  try {
    const eventUrl = `https://api.meetup.com/${encodeURIComponent(
      meetup,
    )}/events?status=upcoming&only=id,visibility`;

    const res = await fetch(eventUrl);

    // This case covers invalid Meetup group names as well as invalid event IDs.
    if (res.status === 404) {
      throw new Error("Sorry, I couldn't find any information on that.");
    }

    const data = await res.json();
    const eventId = getIdFromEvent(getEventFromResponseData(data));
    const winners = await meetupRandomizer.run(meetup, eventId, count);

    if (Array.isArray(winners) && winners.length) {
      return {
        headers,
        statusCode: 200,
        body: JSON.stringify({ winners }),
      };
    }

    throw new Error('Sorry, we received unexpected data for that request.');
  } catch (err) {
    return {
      headers,
      statusCode: 404,
      body: JSON.stringify({ error: { message: err.message } }),
    };
  }
}
<commit_msg>refactor: fix conditional CORS header logic for real<commit_after>import fetch from 'node-fetch';
import meetupRandomizer from 'meetup-randomizer';
import {
  getParamsFromRequest,
  getEventFromResponseData,
  getIdFromEvent,
} from './helpers';

export async function handler(request /* , context */) {
  const headers =
    process.env.NODE_ENV === 'development'
      ? /* c8 ignore next */ { 'Access-Control-Allow-Origin': '*' }
      : {};

  let meetup;
  let count;

  try {
    ({ meetup, count } = getParamsFromRequest(request));
  } catch (err) {
    return {
      headers,
      statusCode: 400,
      body: JSON.stringify({ error: { message: err.message } }),
    };
  }

  try {
    const eventUrl = `https://api.meetup.com/${encodeURIComponent(
      meetup,
    )}/events?status=upcoming&only=id,visibility`;

    const res = await fetch(eventUrl);

    // This case covers invalid Meetup group names as well as invalid event IDs.
    if (res.status === 404) {
      throw new Error("Sorry, I couldn't find any information on that.");
    }

    const data = await res.json();
    const eventId = getIdFromEvent(getEventFromResponseData(data));
    const winners = await meetupRandomizer.run(meetup, eventId, count);

    if (Array.isArray(winners) && winners.length) {
      return {
        headers,
        statusCode: 200,
        body: JSON.stringify({ winners }),
      };
    }

    throw new Error('Sorry, we received unexpected data for that request.');
  } catch (err) {
    return {
      headers,
      statusCode: 404,
      body: JSON.stringify({ error: { message: err.message } }),
    };
  }
}
<|endoftext|>


<commit_before>var http = require('http');
var internalIp = require('internal-ip');
var router = require('router');
var path = require('path');
var serveMp4 = require('../utils/serve-mp4');
var debug = require('debug')('castnow:localfile');
var fs = require('fs');
var port = 4100;

var isFile = function(item) {
  return fs.existsSync(item.path) && fs.statSync(item.path).isFile();
};

var contains = function(arr, cb) {
  for (var i=0, len=arr.length; i<len; i++) {
    if (cb(arr[i], i)) return true;
  }
  return false;
};

var localfile = function(ctx, next) {
  if (ctx.mode !== 'launch') return next();
  if (!contains(ctx.options.playlist, isFile)) return next();

  var route = router();
  var list = ctx.options.playlist.slice(0);
  var ip = (ctx.options.myip || internalIp());

  ctx.options.playlist = list.map(function(item, idx) {
    if (!isFile(item)) return item;
    return {
      path: 'http://' + ip + ':' + port + '/' + idx,
      type: 'video/mp4',
      media: {
        metadata: {
          title: path.basename(item.path)
        }
      }
    };
  });

  route.all('/{idx}', function(req, res) {
    debug('incoming request serving %s', list[req.params.idx].path);
    serveMp4(req, res, list[req.params.idx].path);
  });

  http.createServer(route).listen(port);
  debug('started webserver on address %s using port %s', ip, port);
  next();

};

module.exports = localfile;
<commit_msg>avoid crash when opening http://127.0.0.1:4100 in the browser ( closes #73 )<commit_after>var http = require('http');
var internalIp = require('internal-ip');
var router = require('router');
var path = require('path');
var serveMp4 = require('../utils/serve-mp4');
var debug = require('debug')('castnow:localfile');
var fs = require('fs');
var port = 4100;

var isFile = function(item) {
  return fs.existsSync(item.path) && fs.statSync(item.path).isFile();
};

var contains = function(arr, cb) {
  for (var i=0, len=arr.length; i<len; i++) {
    if (cb(arr[i], i)) return true;
  }
  return false;
};

var localfile = function(ctx, next) {
  if (ctx.mode !== 'launch') return next();
  if (!contains(ctx.options.playlist, isFile)) return next();

  var route = router();
  var list = ctx.options.playlist.slice(0);
  var ip = (ctx.options.myip || internalIp());

  ctx.options.playlist = list.map(function(item, idx) {
    if (!isFile(item)) return item;
    return {
      path: 'http://' + ip + ':' + port + '/' + idx,
      type: 'video/mp4',
      media: {
        metadata: {
          title: path.basename(item.path)
        }
      }
    };
  });

  route.all('/{idx}', function(req, res) {
    if (!list[req.params.idx]) {
      res.statusCode = '404';
      return res.end('page not found');
    }
    debug('incoming request serving %s', list[req.params.idx].path);
    serveMp4(req, res, list[req.params.idx].path);
  });

  http.createServer(route).listen(port);
  debug('started webserver on address %s using port %s', ip, port);
  next();

};

module.exports = localfile;
<|endoftext|>


<commit_before>import React from 'react'
import Modal from '../../modal'
import Loading from '../../loading'
import ImageIcon from '../../imageicon'
import IconIcon from '../../iconicon'
import {goto} from 'app/utils/store'
import store from 'app/utils/store'
const icon = require("../../../../imgs/services.svg")
import {match_traits, get_service_data} from '../utils'
import PluginScreen from 'app/components/plugin/screen'

import Empty from 'app/components/empty'
import Settings from 'app/containers/service/settings'
import Logs from 'app/containers/service/logs'
import DetailsTab from './detailstab'
import Rules from './rules'
import ExternalUrl from './externalurl'
import {i18n} from 'app/utils/i18n'
import TabBar from 'app/components/tabbar'

const tab_options={
  details: DetailsTab,
  settings: Settings,
  rules: Rules,
  logs: Logs
}

function get_plugin_component({tab, type}, props){
  if (type!="screen")
    return null
  let sp=tab.split('/')
  return (props) => (
    <PluginScreen data={{service: props.service, project: props.project}} plugin={sp[0]} component={sp[1]}/>
  )
}
function get_external_url_component({tab, type}, props){
  if (type!="external url")
    return null
  const url = get_external_url(tab, props)
  return (props) => (
    <ExternalUrl url={url}/>
  )
}

function get_external_url_template(id, props){
  for(let eu of (props.external_urls || [])){
    if (eu.id==id){
      return eu
    }
  }
  return null
}
function get_external_url(id, props){
  const eu=get_external_url_template(id, props)
  if (!eu)
    return null

  let url = eu.extra.url
  const config = props.service.config
  Object.keys(config).map((k) => {
    url = url.replace(`{config.${k}}`, config[k])
  })
  return url
}

const Details = React.createClass({
  propTypes:{
    screens: React.PropTypes.arrayOf(React.PropTypes.object),
    service: React.PropTypes.shape({
      uuid: React.PropTypes.string.isRequired,
      name: React.PropTypes.string.isRequired,
      description: React.PropTypes.string,
      config: React.PropTypes.object.isRequired,
    }).isRequired,
    service_template: React.PropTypes.shape({
      name: React.PropTypes.string.isRequired,
      description: React.PropTypes.string,
      params: React.PropTypes.string,
    }).isRequired
  },
  getInitialState(){
    return {tab: "details", type: "internal"}
  },
  setTab({tab, type}){
    this.setState({tab, type})
  },
  handleTabChange(id, type){
    if (type=="screen"){
      this.setTab({tab: id, type: "screen"})
    }
    else if (type=="external url"){
      const euc = get_external_url_template(id, this.props)
      if (!euc.extra.iframe){
        const url = get_external_url(id, this.props)
        if (!url)
          console.warn("Invalid URL from %o", id)
        else
          window.open(url)
      }
      else{
        this.setTab({tab: id, type: "external url"})
      }
    }
    else{
      this.setTab({tab: id})
    }
  },
  componentDidMount(){
    this.setTab({tab: "details"})
  },
  render(){
    const props = this.props
    const state = this.state
    if (props.loading){
      return (
        <Loading>{i18n("Service details")}</Loading>
      )
    }
    let current_tab = state.tab

    let sections=[
      { name: i18n("Details"), id: "details" },
      { name: i18n("Settings"), id: "settings" },
      { name: i18n("Rules"), id: "rules" },
      { name: i18n("Logs"), id: "logs" },
    ];

    props.screens.map( (s) => {
      if (match_traits(s.traits, props.service.traits)){
        sections.push({
          name: s.name,
          id: s.id,
          description: s.description,
          type: "screen"
        })
      }
    });

    (props.external_urls || []).map( (u) => {
      sections.push({
        name: u.name,
        id: u.id,
        description: u.description,
        type: "external url",
        icon: !u.extra.iframe ? "external" : null
      })
    })
    let CurrentTab = (
      tab_options[current_tab] ||
      get_plugin_component(state, props) ||
      get_external_url_component(state, props) ||
      Empty
    )

    let handleClose = undefined
    if (props.project)
      handleClose = () => goto(`/project/${props.project.shortname}/services`)

    return (

          {props.service.icon ? (
            <IconIcon src={icon} icon={props.service.icon} plugin={props.service.type.split('/',1)[0]}/>
          ) : (
            <ImageIcon src={icon} name={props.service.name}/>
          )}

{i18n(props.service.name)}

            {i18n(props.service_template.name)}

          <TabBar tabs={sections.map( s => ({
            key: s.id,
            label: s.name,
            icon: s.icon,
            onClick: () => this.handleTabChange(s.id, s.type),
            active: (s.id == current_tab),
            description: s.title
          }) ) } />

          <CurrentTab {...props} service={props.service} onClose={handleClose} />

    )
  }
})

export default Details
<commit_msg>Fix use proper match_traits for service screens<commit_after>import React from 'react'
import Modal from '../../modal'
import Loading from '../../loading'
import ImageIcon from '../../imageicon'
import IconIcon from '../../iconicon'
import {goto} from 'app/utils/store'
import store from 'app/utils/store'
const icon = require("../../../../imgs/services.svg")
import {get_service_data} from '../utils'
import PluginScreen from 'app/components/plugin/screen'

import Empty from 'app/components/empty'
import Settings from 'app/containers/service/settings'
import Logs from 'app/containers/service/logs'
import DetailsTab from './detailstab'
import Rules from './rules'
import ExternalUrl from './externalurl'
import {i18n} from 'app/utils/i18n'
import TabBar from 'app/components/tabbar'
import {match_traits} from 'app/utils'

const tab_options={
  details: DetailsTab,
  settings: Settings,
  rules: Rules,
  logs: Logs
}

function get_plugin_component({tab, type}, props){
  if (type!="screen")
    return null
  let sp=tab.split('/')
  return (props) => (
    <PluginScreen data={{service: props.service, project: props.project}} plugin={sp[0]} component={sp[1]}/>
  )
}
function get_external_url_component({tab, type}, props){
  if (type!="external url")
    return null
  const url = get_external_url(tab, props)
  return (props) => (
    <ExternalUrl url={url}/>
  )
}

function get_external_url_template(id, props){
  for(let eu of (props.external_urls || [])){
    if (eu.id==id){
      return eu
    }
  }
  return null
}
function get_external_url(id, props){
  const eu=get_external_url_template(id, props)
  if (!eu)
    return null

  let url = eu.extra.url
  const config = props.service.config
  Object.keys(config).map((k) => {
    url = url.replace(`{config.${k}}`, config[k])
  })
  return url
}

const Details = React.createClass({
  propTypes:{
    screens: React.PropTypes.arrayOf(React.PropTypes.object),
    service: React.PropTypes.shape({
      uuid: React.PropTypes.string.isRequired,
      name: React.PropTypes.string.isRequired,
      description: React.PropTypes.string,
      config: React.PropTypes.object.isRequired,
    }).isRequired,
    service_template: React.PropTypes.shape({
      name: React.PropTypes.string.isRequired,
      description: React.PropTypes.string,
      params: React.PropTypes.string,
    }).isRequired
  },
  getInitialState(){
    return {tab: "details", type: "internal"}
  },
  setTab({tab, type}){
    this.setState({tab, type})
  },
  handleTabChange(id, type){
    if (type=="screen"){
      this.setTab({tab: id, type: "screen"})
    }
    else if (type=="external url"){
      const euc = get_external_url_template(id, this.props)
      if (!euc.extra.iframe){
        const url = get_external_url(id, this.props)
        if (!url)
          console.warn("Invalid URL from %o", id)
        else
          window.open(url)
      }
      else{
        this.setTab({tab: id, type: "external url"})
      }
    }
    else{
      this.setTab({tab: id})
    }
  },
  componentDidMount(){
    this.setTab({tab: "details"})
  },
  render(){
    const props = this.props
    const state = this.state
    if (props.loading){
      return (
        <Loading>{i18n("Service details")}</Loading>
      )
    }
    let current_tab = state.tab

    let sections=[
      { name: i18n("Details"), id: "details" },
      { name: i18n("Settings"), id: "settings" },
      { name: i18n("Rules"), id: "rules" },
      { name: i18n("Logs"), id: "logs" },
    ];

    props.screens.map( (s) => {
      if (match_traits({has: s.traits, any: props.service.traits})){
        sections.push({
          name: s.name,
          id: s.id,
          description: s.description,
          type: "screen"
        })
      }
    });

    (props.external_urls || []).map( (u) => {
      sections.push({
        name: u.name,
        id: u.id,
        description: u.description,
        type: "external url",
        icon: !u.extra.iframe ? "external" : null
      })
    })
    let CurrentTab = (
      tab_options[current_tab] ||
      get_plugin_component(state, props) ||
      get_external_url_component(state, props) ||
      Empty
    )

    let handleClose = undefined
    if (props.project)
      handleClose = () => goto(`/project/${props.project.shortname}/services`)

    return (

          {props.service.icon ? (
            <IconIcon src={icon} icon={props.service.icon} plugin={props.service.type.split('/',1)[0]}/>
          ) : (
            <ImageIcon src={icon} name={props.service.name}/>
          )}

{i18n(props.service.name)}

            {i18n(props.service_template.name)}

          <TabBar tabs={sections.map( s => ({
            key: s.id,
            label: s.name,
            icon: s.icon,
            onClick: () => this.handleTabChange(s.id, s.type),
            active: (s.id == current_tab),
            description: s.title
          }) ) } />

          <CurrentTab {...props} service={props.service} onClose={handleClose} />

    )
  }
})

export default Details
<|endoftext|>


<commit_before>import Mousetrap from 'mousetrap'
require('imports-loader?Mousetrap=>require("mousetrap")!mousetrap/plugins/pause/mousetrap-pause') // eslint-disable-line

// if (process.browser) {

//   module.exports = {
//     pause() {
//       Mousetrap.pause() // eslint-disable-line
//     },
//     unpause() {
//       Mousetrap.unpause() // eslint-disable-line
//     },
//     bind(...args) {
//       Mousetrap.bind(...args) // eslint-disable-line
//     },
//     unbind(...args) {
//       Mousetrap.unbind(...args) // eslint-disable-line
//     }
//   }
// }

export default (app, inject) => {
  inject('mousetrap', Mousetrap)
}
<commit_msg>Remove comment<commit_after>import Mousetrap from 'mousetrap'
require('imports-loader?Mousetrap=>require("mousetrap")!mousetrap/plugins/pause/mousetrap-pause') // eslint-disable-line

export default (app, inject) => {
  inject('mousetrap', Mousetrap)
}
<|endoftext|>