<commit_before>width = 740;
height = 200;
margin = 10;
labels = 40;

lookback = 60*60*24*31;

function add_fields(fields) {
    return (d) => {
        var sum = 0;
        for (var i = 0; i < fields.length; i++) {
            sum += (d[fields[i]] || 0);
        }
        return sum;
    }
}

function render_key(key, value) {
    switch (key) {
        case ":time": return (new Date(value * 1000)).toString();
        case ":runtime":
        if (value < 2 * 60 * 1000) {
            return Math.floor(value / 1000) + "s";
        } else {
            var h = Math.floor(value / 1000 / 60 / 60);
            var m = Math.floor(value / 1000 / 60);
            return h + ":" + (m - 60 * h);
        }
        default: return value;
    }
}

function html_path(json_path) {
    return json_path.replace("/json/", "/").replace(".json", ".html");
}

MONTHS = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" ");

function pretty_date(date) {
    return date.getDate() + " " + MONTHS[date.getMonth()] + " " + date.getFullYear();
}

function pretty_time(date) {
    var minutes = date.getMinutes();
    return date.getHours() + ":" + (minutes < 10 ? "0" : "") + date.getMinutes();
}

function draw_class(node, name, data) {
    var header = node.append("header");

    var g = node.append("svg")
        .attr("width", width + 2 * margin + labels)
        .attr("height", height + 2 * margin + labels)
        .append("g").attr("transform", "translate(" + (margin + labels) + "," + margin + ")");

    var table = node.append("table");

    var total = d3.max(data, add_fields(["success", "expected", "fail", "error", "timeout", "unsupported"]))

    var x = d3.scaleTime().range([0, width]);
    var y = d3.scaleLinear().range([height, 0]);
    x.domain(d3.extent(data, x => new Date(x[":time"] * 1000)));
    y.domain([0, total]);
    g.append("g").call(d3.axisLeft().scale(y))
    g.append("g").call(d3.axisBottom().scale(x))
        .attr("transform", "translate(0," + height + ")")

    branches = {}
    for (var i = 0; i < data.length; i++) {
        var array = (branches[data[i][":branch"]] || []);
        array.push(data[i]);
        branches[data[i][":branch"]] = array;
    }
    var key = d3.scaleOrdinal(d3.schemeCategory10).domain(Object.keys(branches));

    header.append("ul").selectAll("li")
        .data(Object.keys(branches)).enter().append("li")
        .style("border-left-width", "1em")
        .style("border-left-color", key)
        .text((x) => x);
    header.append("h1").text(name);

    for (var branch in branches) {
        console.log(name, branch, key(branch))
        if (!branches.hasOwnProperty(branch)) continue;
        g.append("g").selectAll("circle")
            .data(branches[branch]).enter().append("circle")
            .attr("cx", (d) => x(new Date(d[":time"] * 1000)))
            .attr("cy", (d) => y(add_fields(["success", "expected"])(d)))
            .attr("r", 5)
            .attr("fill", key(branch))
            .append("title")
            .text((d) => {
                var s = "";
                var keys = Object.keys(d);
                keys.sort();
                for (var i = 0; i < keys.length; i++) {
                    s += keys[i] + ": " + render_key(keys[i], d[keys[i]]) + "\n";
                }
                return s;
            });
    }

    table.append("thead").selectAll("th")
        .data(["Date", "Time", "Branch", "Passing", "Timeouts", "Link"]).enter().append("th")
        .text((d) => d);

    table.append("tbody").selectAll("tr")
        .data(data).enter().append("tr")
        .on("click", function() { this.children[this.children.length - 1].children[0].click() })
        .selectAll("td").data(d => [
            pretty_date(new Date(d[":time"] * 1000)),
            pretty_time(new Date(d[":time"] * 1000)),
            "" + d[":branch"] + "",
            add_fields(["success", "expected"])(d) + "/" +
                add_fields(["success", "expected", "timeout", "fail", "unsupported"])(d),
            d["timeout"] || 0,
            "»",
        ]).enter().append("td")
        .html(d => d);
}

function relevant_data(data) {
    return data[":time"] > new Date() / 1000 - lookback;
}

function draw(node, data) {
    for (var i in data) {
        if (!data.hasOwnProperty(i)) continue;
        var class_data = data[i].filter(relevant_data);
        if (class_data.length > 1) {
            draw_class(node.append("section").attr("data-suite", i), i, class_data);
        }
    }
}
<commit_msg>Scale charts<commit_after>width = 740;
height = 200;
margin = 10;
labels = 40;

lookback = 60*60*24*31;

function add_fields(fields) {
    return (d) => {
        var sum = 0;
        for (var i = 0; i < fields.length; i++) {
            sum += (d[fields[i]] || 0);
        }
        return sum;
    }
}

function render_key(key, value) {
    switch (key) {
        case ":time": return (new Date(value * 1000)).toString();
        case ":runtime":
        if (value < 2 * 60 * 1000) {
            return Math.floor(value / 1000) + "s";
        } else {
            var h = Math.floor(value / 1000 / 60 / 60);
            var m = Math.floor(value / 1000 / 60);
            return h + ":" + (m - 60 * h);
        }
        default: return value;
    }
}

function html_path(json_path) {
    return json_path.replace("/json/", "/").replace(".json", ".html");
}

MONTHS = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" ");

function pretty_date(date) {
    return date.getDate() + " " + MONTHS[date.getMonth()] + " " + date.getFullYear();
}

function pretty_time(date) {
    var minutes = date.getMinutes();
    return date.getHours() + ":" + (minutes < 10 ? "0" : "") + date.getMinutes();
}

function draw_class(node, name, data) {
    var header = node.append("header");

    var g = node.append("svg")
        .attr("width", width + 2 * margin + labels)
        .attr("height", height + 2 * margin + labels)
        .append("g").attr("transform", "translate(" + (margin + labels) + "," + margin + ")");

    var table = node.append("table");

    var x = d3.scaleTime().range([0, width]);
    var y = d3.scaleLinear().range([height, 0]);
    x.domain(d3.extent(data, x => new Date(x[":time"] * 1000)));
    y.domain(d3.extent(data, x => add_fields(["success", "expected"])(x)));
    g.append("g").call(d3.axisLeft().scale(y))
    g.append("g").call(d3.axisBottom().scale(x))
        .attr("transform", "translate(0," + height + ")")

    branches = {}
    for (var i = 0; i < data.length; i++) {
        var array = (branches[data[i][":branch"]] || []);
        array.push(data[i]);
        branches[data[i][":branch"]] = array;
    }
    var key = d3.scaleOrdinal(d3.schemeCategory10).domain(Object.keys(branches));

    header.append("ul").selectAll("li")
        .data(Object.keys(branches)).enter().append("li")
        .style("border-left-width", "1em")
        .style("border-left-color", key)
        .text((x) => x);
    header.append("h1").text(name);

    for (var branch in branches) {
        console.log(name, branch, key(branch))
        if (!branches.hasOwnProperty(branch)) continue;
        g.append("g").selectAll("circle")
            .data(branches[branch]).enter().append("circle")
            .attr("cx", (d) => x(new Date(d[":time"] * 1000)))
            .attr("cy", (d) => y(add_fields(["success", "expected"])(d)))
            .attr("r", 5)
            .attr("fill", key(branch))
            .append("title")
            .text((d) => {
                var s = "";
                var keys = Object.keys(d);
                keys.sort();
                for (var i = 0; i < keys.length; i++) {
                    s += keys[i] + ": " + render_key(keys[i], d[keys[i]]) + "\n";
                }
                return s;
            });
    }

    table.append("thead").selectAll("th")
        .data(["Date", "Time", "Branch", "Passing", "Timeouts", "Link"]).enter().append("th")
        .text((d) => d);

    table.append("tbody").selectAll("tr")
        .data(data).enter().append("tr")
        .on("click", function() { this.children[this.children.length - 1].children[0].click() })
        .selectAll("td").data(d => [
            pretty_date(new Date(d[":time"] * 1000)),
            pretty_time(new Date(d[":time"] * 1000)),
            "" + d[":branch"] + "",
            add_fields(["success", "expected"])(d) + "/" +
                add_fields(["success", "expected", "timeout", "fail", "unsupported"])(d),
            d["timeout"] || 0,
            "»",
        ]).enter().append("td")
        .html(d => d);
}

function relevant_data(data) {
    return data[":time"] > new Date() / 1000 - lookback;
}

function draw(node, data) {
    for (var i in data) {
        if (!data.hasOwnProperty(i)) continue;
        var class_data = data[i].filter(relevant_data);
        if (class_data.length > 1) {
            draw_class(node.append("section").attr("data-suite", i), i, class_data);
        }
    }
}
<|endoftext|>


<commit_before>/* require("DataStream.js"); */
/* require("jszip.js"); */

nz = {};

format_DataStream_types = {
  "s": "readCString",
  "c": "readUInt8Array",
  "b": "readInt8Array",
  "B": "readUInt8Array",
  "h": "readInt16Array",
  "H": "readUInt16Array",
  "i": "readInt32Array",
  "I": "readUInt32Array",
  "l": "readInt32Array",
  "L": "readUInt32Array",
  "f": "readFloat32Array",
  "d": "readFloat64Array"
}

format_types = {
  "s": "String",
  "c": "Int",
  "b": "Int",
  "h": "Int",
  "i": "Int",
  "l": "Int",
  "f": "Float",
  "d": "Float"
}

function fmt_to_DS(format_string) {
  // match format string to required DataStream reader
  //var endianness = endianness_lookup[format_string[0]];
  var ft = format_string[1];
  if (ft.toLowerCase() == "s") {
    return "readCString"
  } else {
    var bytes = parseInt(format_string[2]);
    var type = format_types[ft.toLowerCase()];
    var unsigned = (ft == ft.toUpperCase());
    return "read" + ((unsigned)? "U" : "") + type + (bytes*8).toFixed() + "Array";
  }
}

function fmt_endianness(format_string) {
  if (format_string[0] == "<") {
    return DataStream.LITTLE_ENDIAN;
  }
  else if (format_string[0] == ">") {
    return DataStream.BIG_ENDIAN;
  }
  else {
    throw "invalid format string: must start with < or >"
  }
}

function dirname(path) {
  var path = rstrip(path, "\/");
  var pathlist = path.split("/")
  return pathlist.slice(0, pathlist.length-1).join("/")
}

function rstrip(str, tostrip) {
  var tostrip = (tostrip == null) ? "\\s" : tostrip;
  var endregex = new RegExp(tostrip + tostrip + '*$')
  return str.replace(endregex, '');
}

function lstrip(str, tostrip) {
  var tostrip = (tostrip == null) ? '\\s' : tostrip;
  var startregex = new RegExp('^' + tostrip + tostrip + '*');
  return str.replace(startregex, '');
}

function strip (str, tostrip) {
  return rstrip(lstrip(str, tostrip), tostrip);
}

nz.Node = function() {}; // base class
nz.Node.prototype = {
  _attrs_filename: ".attrs",
  _link_filename: ".link",
  _type: "Node",

  init: function(parent, path, nxclass) {
    // handling of the arguments:
    // if _cache is not null, populate the cache for this node
    this.root = (parent == null) ? this : parent.root;
    this.readonly = this.root.readonly;
    if (path[0] == "/") {
      this.path = path;
    } else {
      this.path = rstrip(parent.path, "/") + "/" + path;
      // add paths to cache... useful later.
      this.root._cache[this.path] = null;
    }
    this.nxclass = nxclass;
  },

  getAttrs: function() {
    // use cached value if not null:
    var attrs_path = lstrip(this.path + "/" + this._attrs_filename, "/");
    if (this.root._cache[attrs_path] == null) {
      var attrs = JSON.parse(this.file_readText(attrs_path));
      this.root._cache[attrs_path] = attrs;
    };
    return this.root._cache[attrs_path];
  },

  getLink: function(path) {
    var link_path = lstrip(path + this._link_filename, "/");
    if (this.root._cache[link_path] == null) {
      var link = JSON.parse(this.file_readText(link_path));
      this.root._cache[link_path] = link;
    };
    return this.root._cache[link_path];
  },

  parent: function() {
    return this.root.get(dirname(this.path));
  },

  groupnames: function() {
    var that = this;
    return this.keys().filter(function(fn) {return that.file_isdir(fn)});
  },

  fieldnames: function() {
    var that = this;
    return this.keys().filter(function(fn) {return !(that.file_isdir(fn))});
  },

  keys: function() {
    //var nonkey_regex = /^[^\.]*$/;
    return this.file_listdir().filter(function(fn) {return fn.indexOf(".") < 0});// nonkey_regex.test(fn)});
  },

  items: function() {
    var that = this;
    return this.keys().map(function(fn) {
      return [fn, that.get(fn)]
    });
  },

  contains: function(key) {
    return this.file_exists(this.path + "/" + key);
  },

  get: function(path) {
    // convert to full path:
    var that = this;
    var path = (path[0] == "/") ? path : rstrip(this.path, "/") + "/" + path;
    if (!(this.file_exists(path))) {
      //throw "key error";
      return null;
    }
    else if (this.file_isdir(path)) {
      var g = new nz.Group();
      g.init(this, path);
      return g;
    }
    else if (this.file_exists(path + this._attrs_filename)) {
      var f = new nz.Field();
      f.init(this, path);
      return f;
    }
    else if (this.file_exists(path + this._link_filename)) {
      return makeSoftLink(this, path, this.getLink(path).target);
    }
    else {
      throw "unknown element type"
    }
  },

  file_isdir: function(path) {
    var path = strip(path, "/") + "/";
    // root path is "/"
    return (path == "/" || path in this.root.filenames)
  },

  file_listdir: function(path) {
    // abstraction for looking up paths
    // should work for unpacked directories and packed zip archives
    var path = (path == null) ? this.path : path;
    path = lstrip(rstrip(path, "/") + "/", "/"); // never one on the left, always one on the right;
    var path_regex = new RegExp('^' + path + "([^/]+)/?$"); // some non-pathsep characters followed by optional single pathsep;
    var filenames = Object.keys(this.root.filenames);
    var direntries = filenames.filter(function(s) {return path_regex.test(s)}).map(function(fn) {return fn.match(path_regex)[1]});
    return direntries;
  },

  file_exists: function(path) {
    var path = strip(path, "/");
    return (path in this.root.filenames || (path + "/") in this.root.filenames)
  },

  file_readText: function(path) {
    // returns a Promise, to be resolved with the data.
    var entry =  this.root.filenames[path];
    return entry.asText();
  },

  file_readArrayBuffer: function(path) {
    var entry = this.root.filenames[path];
    return entry.asArrayBuffer();
  },

  file_getsize: function(path) {
    var path = strip(path, "/");
    var entry = this.root.filenames[path];
    return (entry == null) ? null : entry.uncompressedSize;
  }

}

nz.File = function() { nz.Node.call(this); }
nz.File.prototype = new nz.Node();
nz.File.prototype.constructor = nz.File;
nz.File.prototype._type = "File"
nz.File.prototype.init = function(zipfilename, filenames) {
  nz.Node.prototype.init.call(this, null, "/", "NXroot", {});
  this.zipfilename = zipfilename;
  this.mode = "r";
  this.filenames = filenames;
  this._cache = {};
  return this;
}

nz.Group = function() { nz.Node.call(this); }
nz.Group.prototype = new nz.Node();
nz.Group.prototype.constructor = nz.Group;
nz.Group.prototype._type = "Group"
nz.Group.prototype.init = function(node, path) {
  nz.Node.prototype.init.call(this, node, path, "NXCollection");
  // precache the attrs?
  this.getAttrs();
}

nz.Field = function() {};
nz.Field.prototype = {
  _attrs_suffix: ".attrs",
  _type: "Field",

  init: function(parent, path) {
    this._attrs = null;

    this.root = parent.root;
    if (path[0] == "/") {
      this.path = path;
    } else {
      this.path = rstrip(parent.path, "/") + "/" + path;
    }
  },

  getAttrs: function() {
    // use cached value if not null:
    var attrs_path = lstrip(this.path + this._attrs_suffix, "/");
    if (this.root._cache[attrs_path] == null) {
      var attrs = JSON.parse(this.root.file_readText(attrs_path));
      this.root._cache[attrs_path] = attrs;
    };
    return this.root._cache[attrs_path];
  },

  getValue: function() {
    var value_path = lstrip(this.path, "/");
    if (this.root._cache[value_path] == null) {
      var root = this.root,
          path = lstrip(this.path, "/"),
          attrs,
          format_string;

      var attrs = this.getAttrs();
      format_string = attrs.format;
      if (attrs.binary) {
        // returns deferred
        var buf = root.file_readArrayBuffer(path);
        var ds = new DataStream(buf);
        ds.endianness = fmt_endianness(format_string);
        var reader = fmt_to_DS(format_string);
        var bytes_each = parseInt(format_string[2]);
        this.root._cache[value_path] = ds[reader](ds.byteLength / bytes_each);
      }
      else {
        var valstr = root.file_readText(path);
        var accessor;
        if (/[fd]/.test(attrs.format[1].toLowerCase())) {
          accessor = function(d) {return d.map(parseFloat)};
        }
        else if (/[cbhil]/.test(attrs.format[1].toLowerCase())) {
          accessor = function(d) {return d.map(parseInt)};
        }
        else {
          accessor = function(d) {return d};
        }
        this.root._cache[value_path] = d3.tsv.parseRows(valstr, accessor);
      }
    }
    return this.root._cache[value_path];
  }

}

function makeSoftLink(parent, path) {
  var linkinfo = parent.root.getLink(path);
  var target = linkinfo.target;
  var target_obj = parent.root.get(target);
  target_obj.orig_path = path;
  return target_obj;
}

function getValue(field) {
  if (field == null) { return null }
  else return field.getValue();
}
nz.getValue = getValue

function getAttrs(field) {
  return field.getAttrs();
}
nz.getAttrs = getAttrs;

function logj(value) {
  console.log(JSON.stringify(value));
  return value;
}

nz.cacheAll = function(node) {
  node.getAttrs();
  var itemname, itemobj, items = node.items();
  items.forEach(function(item,i) {
    itemname = item[0];
    itemobj = item[1];
    itemobj.getAttrs();
    if (itemobj.items) { nz.cacheAll(itemobj) }
    else if (itemobj.getValue) { itemobj.getValue(); }
  });
}

/*
'A': {en:m._EnArray, de:m._DeArray},
's': {en:m._EnString, de:m._DeString},
'c': {en:m._EnChar, de:m._DeChar},
'b': {en:m._EnInt, de:m._DeInt, len:1, bSigned:true, min:-Math.pow(2, 7), max:Math.pow(2, 7)-1},
'B': {en:m._EnInt, de:m._DeInt, len:1, bSigned:false, min:0, max:Math.pow(2, 8)-1},
'h': {en:m._EnInt, de:m._DeInt, len:2, bSigned:true, min:-Math.pow(2, 15), max:Math.pow(2, 15)-1},
'H': {en:m._EnInt, de:m._DeInt, len:2, bSigned:false, min:0, max:Math.pow(2, 16)-1},
'i': {en:m._EnInt, de:m._DeInt, len:4, bSigned:true, min:-Math.pow(2, 31), max:Math.pow(2, 31)-1},
'I': {en:m._EnInt, de:m._DeInt, len:4, bSigned:false, min:0, max:Math.pow(2, 32)-1},
'l': {en:m._EnInt, de:m._DeInt, len:4, bSigned:true, min:-Math.pow(2, 31), max:Math.pow(2, 31)-1},
'L': {en:m._EnInt, de:m._DeInt, len:4, bSigned:false, min:0, max:Math.pow(2, 32)-1},
'f': {en:m._En754, de:m._De754, len:4, mLen:23, rt:Math.pow(2, -24)-Math.pow(2, -77)},
'd': {en:m._En754, de:m._De754, len:8, mLen:52, rt:0}};
*/

<commit_msg>cache even directories, though they contain no information<commit_after>/* require("DataStream.js"); */
/* require("jszip.js"); */

nz = {};

format_DataStream_types = {
  "s": "readCString",
  "c": "readUInt8Array",
  "b": "readInt8Array",
  "B": "readUInt8Array",
  "h": "readInt16Array",
  "H": "readUInt16Array",
  "i": "readInt32Array",
  "I": "readUInt32Array",
  "l": "readInt32Array",
  "L": "readUInt32Array",
  "f": "readFloat32Array",
  "d": "readFloat64Array"
}

format_types = {
  "s": "String",
  "c": "Int",
  "b": "Int",
  "h": "Int",
  "i": "Int",
  "l": "Int",
  "f": "Float",
  "d": "Float"
}

function fmt_to_DS(format_string) {
  // match format string to required DataStream reader
  //var endianness = endianness_lookup[format_string[0]];
  var ft = format_string[1];
  if (ft.toLowerCase() == "s") {
    return "readCString"
  } else {
    var bytes = parseInt(format_string[2]);
    var type = format_types[ft.toLowerCase()];
    var unsigned = (ft == ft.toUpperCase());
    return "read" + ((unsigned)? "U" : "") + type + (bytes*8).toFixed() + "Array";
  }
}

function fmt_endianness(format_string) {
  if (format_string[0] == "<") {
    return DataStream.LITTLE_ENDIAN;
  }
  else if (format_string[0] == ">") {
    return DataStream.BIG_ENDIAN;
  }
  else {
    throw "invalid format string: must start with < or >"
  }
}

function dirname(path) {
  var path = rstrip(path, "\/");
  var pathlist = path.split("/")
  return pathlist.slice(0, pathlist.length-1).join("/")
}

function rstrip(str, tostrip) {
  var tostrip = (tostrip == null) ? "\\s" : tostrip;
  var endregex = new RegExp(tostrip + tostrip + '*$')
  return str.replace(endregex, '');
}

function lstrip(str, tostrip) {
  var tostrip = (tostrip == null) ? '\\s' : tostrip;
  var startregex = new RegExp('^' + tostrip + tostrip + '*');
  return str.replace(startregex, '');
}

function strip (str, tostrip) {
  return rstrip(lstrip(str, tostrip), tostrip);
}

nz.Node = function() {}; // base class
nz.Node.prototype = {
  _attrs_filename: ".attrs",
  _link_filename: ".link",
  _type: "Node",

  init: function(parent, path, nxclass) {
    // handling of the arguments:
    // if _cache is not null, populate the cache for this node
    this.root = (parent == null) ? this : parent.root;
    this.readonly = this.root.readonly;
    if (path[0] == "/") {
      this.path = path;
    } else {
      this.path = rstrip(parent.path, "/") + "/" + path;
    }
    this.nxclass = nxclass;
    // add paths to cache... useful later.
    this.root._cache[this.path] = null;
  },

  getAttrs: function() {
    // use cached value if not null:
    var attrs_path = lstrip(this.path + "/" + this._attrs_filename, "/");
    if (this.root._cache[attrs_path] == null) {
      var attrs = JSON.parse(this.file_readText(attrs_path));
      this.root._cache[attrs_path] = attrs;
    };
    return this.root._cache[attrs_path];
  },

  getLink: function(path) {
    var link_path = lstrip(path + this._link_filename, "/");
    if (this.root._cache[link_path] == null) {
      var link = JSON.parse(this.file_readText(link_path));
      this.root._cache[link_path] = link;
    };
    return this.root._cache[link_path];
  },

  parent: function() {
    return this.root.get(dirname(this.path));
  },

  groupnames: function() {
    var that = this;
    return this.keys().filter(function(fn) {return that.file_isdir(fn)});
  },

  fieldnames: function() {
    var that = this;
    return this.keys().filter(function(fn) {return !(that.file_isdir(fn))});
  },

  keys: function() {
    //var nonkey_regex = /^[^\.]*$/;
    return this.file_listdir().filter(function(fn) {return fn.indexOf(".") < 0});// nonkey_regex.test(fn)});
  },

  items: function() {
    var that = this;
    return this.keys().map(function(fn) {
      return [fn, that.get(fn)]
    });
  },

  contains: function(key) {
    return this.file_exists(this.path + "/" + key);
  },

  get: function(path) {
    // convert to full path:
    var that = this;
    var path = (path[0] == "/") ? path : rstrip(this.path, "/") + "/" + path;
    if (!(this.file_exists(path))) {
      //throw "key error";
      return null;
    }
    else if (this.file_isdir(path)) {
      var g = new nz.Group();
      g.init(this, path);
      return g;
    }
    else if (this.file_exists(path + this._attrs_filename)) {
      var f = new nz.Field();
      f.init(this, path);
      return f;
    }
    else if (this.file_exists(path + this._link_filename)) {
      return makeSoftLink(this, path, this.getLink(path).target);
    }
    else {
      throw "unknown element type"
    }
  },

  file_isdir: function(path) {
    var path = strip(path, "/") + "/";
    // root path is "/"
    return (path == "/" || path in this.root.filenames)
  },

  file_listdir: function(path) {
    // abstraction for looking up paths
    // should work for unpacked directories and packed zip archives
    var path = (path == null) ? this.path : path;
    path = lstrip(rstrip(path, "/") + "/", "/"); // never one on the left, always one on the right;
    var path_regex = new RegExp('^' + path + "([^/]+)/?$"); // some non-pathsep characters followed by optional single pathsep;
    var filenames = Object.keys(this.root.filenames);
    var direntries = filenames.filter(function(s) {return path_regex.test(s)}).map(function(fn) {return fn.match(path_regex)[1]});
    return direntries;
  },

  file_exists: function(path) {
    var path = strip(path, "/");
    return (path in this.root.filenames || (path + "/") in this.root.filenames)
  },

  file_readText: function(path) {
    // returns a Promise, to be resolved with the data.
    var entry =  this.root.filenames[path];
    return entry.asText();
  },

  file_readArrayBuffer: function(path) {
    var entry = this.root.filenames[path];
    return entry.asArrayBuffer();
  },

  file_getsize: function(path) {
    var path = strip(path, "/");
    var entry = this.root.filenames[path];
    return (entry == null) ? null : entry.uncompressedSize;
  }

}

nz.File = function() { nz.Node.call(this); }
nz.File.prototype = new nz.Node();
nz.File.prototype.constructor = nz.File;
nz.File.prototype._type = "File"
nz.File.prototype.init = function(zipfilename, filenames) {
  nz.Node.prototype.init.call(this, null, "/", "NXroot", {});
  this.zipfilename = zipfilename;
  this.mode = "r";
  this.filenames = filenames;
  this._cache = {};
  return this;
}

nz.Group = function() { nz.Node.call(this); }
nz.Group.prototype = new nz.Node();
nz.Group.prototype.constructor = nz.Group;
nz.Group.prototype._type = "Group"
nz.Group.prototype.init = function(node, path) {
  nz.Node.prototype.init.call(this, node, path, "NXCollection");
  // precache the attrs?
  this.getAttrs();
}

nz.Field = function() {};
nz.Field.prototype = {
  _attrs_suffix: ".attrs",
  _type: "Field",

  init: function(parent, path) {
    this._attrs = null;

    this.root = parent.root;
    if (path[0] == "/") {
      this.path = path;
    } else {
      this.path = rstrip(parent.path, "/") + "/" + path;
    }
  },

  getAttrs: function() {
    // use cached value if not null:
    var attrs_path = lstrip(this.path + this._attrs_suffix, "/");
    if (this.root._cache[attrs_path] == null) {
      var attrs = JSON.parse(this.root.file_readText(attrs_path));
      this.root._cache[attrs_path] = attrs;
    };
    return this.root._cache[attrs_path];
  },

  getValue: function() {
    var value_path = lstrip(this.path, "/");
    if (this.root._cache[value_path] == null) {
      var root = this.root,
          path = lstrip(this.path, "/"),
          attrs,
          format_string;

      var attrs = this.getAttrs();
      format_string = attrs.format;
      if (attrs.binary) {
        // returns deferred
        var buf = root.file_readArrayBuffer(path);
        var ds = new DataStream(buf);
        ds.endianness = fmt_endianness(format_string);
        var reader = fmt_to_DS(format_string);
        var bytes_each = parseInt(format_string[2]);
        this.root._cache[value_path] = ds[reader](ds.byteLength / bytes_each);
      }
      else {
        var valstr = root.file_readText(path);
        var accessor;
        if (/[fd]/.test(attrs.format[1].toLowerCase())) {
          accessor = function(d) {return d.map(parseFloat)};
        }
        else if (/[cbhil]/.test(attrs.format[1].toLowerCase())) {
          accessor = function(d) {return d.map(parseInt)};
        }
        else {
          accessor = function(d) {return d};
        }
        this.root._cache[value_path] = d3.tsv.parseRows(valstr, accessor);
      }
    }
    return this.root._cache[value_path];
  }

}

function makeSoftLink(parent, path) {
  var linkinfo = parent.root.getLink(path);
  var target = linkinfo.target;
  var target_obj = parent.root.get(target);
  target_obj.orig_path = path;
  return target_obj;
}

function getValue(field) {
  if (field == null) { return null }
  else return field.getValue();
}
nz.getValue = getValue

function getAttrs(field) {
  return field.getAttrs();
}
nz.getAttrs = getAttrs;

function logj(value) {
  console.log(JSON.stringify(value));
  return value;
}

nz.cacheAll = function(node) {
  node.getAttrs();
  var itemname, itemobj, items = node.items();
  items.forEach(function(item,i) {
    itemname = item[0];
    itemobj = item[1];
    itemobj.getAttrs();
    if (itemobj.items) { nz.cacheAll(itemobj) }
    else if (itemobj.getValue) { itemobj.getValue(); }
  });
}

/*
'A': {en:m._EnArray, de:m._DeArray},
's': {en:m._EnString, de:m._DeString},
'c': {en:m._EnChar, de:m._DeChar},
'b': {en:m._EnInt, de:m._DeInt, len:1, bSigned:true, min:-Math.pow(2, 7), max:Math.pow(2, 7)-1},
'B': {en:m._EnInt, de:m._DeInt, len:1, bSigned:false, min:0, max:Math.pow(2, 8)-1},
'h': {en:m._EnInt, de:m._DeInt, len:2, bSigned:true, min:-Math.pow(2, 15), max:Math.pow(2, 15)-1},
'H': {en:m._EnInt, de:m._DeInt, len:2, bSigned:false, min:0, max:Math.pow(2, 16)-1},
'i': {en:m._EnInt, de:m._DeInt, len:4, bSigned:true, min:-Math.pow(2, 31), max:Math.pow(2, 31)-1},
'I': {en:m._EnInt, de:m._DeInt, len:4, bSigned:false, min:0, max:Math.pow(2, 32)-1},
'l': {en:m._EnInt, de:m._DeInt, len:4, bSigned:true, min:-Math.pow(2, 31), max:Math.pow(2, 31)-1},
'L': {en:m._EnInt, de:m._DeInt, len:4, bSigned:false, min:0, max:Math.pow(2, 32)-1},
'f': {en:m._En754, de:m._De754, len:4, mLen:23, rt:Math.pow(2, -24)-Math.pow(2, -77)},
'd': {en:m._En754, de:m._De754, len:8, mLen:52, rt:0}};
*/

<|endoftext|>


<commit_before>define(["dojo/_base/declare", "dojo/has", "dojo/on", "../util/misc", "put-selector/put", "xstyle/css!../css/extensions/ColumnHider.css"],
function(declare, has, listen, miscUtil, put){
/*
 *	Column Hider plugin for dgrid
 *	Originally contributed by TRT 2011-09-28
 *
 *	A dGrid plugin that attaches a menu to a dgrid, along with a way of opening it,
 *	that will allow you to show and hide columns.  A few caveats:
 *
 *	1. Menu placement is entirely based on CSS definitions.
 *	2. If you want columns initially hidden, you must add "hidden: true" to your
 *		column definition.
 *	3. This implementation does NOT support ColumnSet, and has not been tested
 *		with multi-subrow records.
 *	4. Column show/hide is controlled via straight up HTML checkboxes.  If you
 *		are looking for something more fancy, you'll probably need to use this
 *		definition as a template to write your own plugin.
 *
 */

	var activeGrid, // references grid for which the menu is currently open
		bodyListener, // references pausable event handler for body mousedown
		// Need to handle old IE specially for checkbox listener and for attribute.
		hasIE = has("ie"),
		hasIEQuirks = hasIE && has("quirks"),
		forAttr = hasIE < 8 || hasIEQuirks ? "htmlFor" : "for";

	function getColumnIdFromCheckbox(cb, grid){
		// Given one of the checkboxes from the hider menu,
		// return the id of the corresponding column.
		// (e.g. gridIDhere-hider-menu-check-colIDhere -> colIDhere)
		return cb.id.substr(grid.id.length + 18);
	}

	return declare(null, {
		// hiderMenuNode: DOMNode
		//		The node for the menu to show/hide columns.
		hiderMenuNode: null,

		// hiderToggleNode: DOMNode
		//		The node for the toggler to open the menu.
		hiderToggleNode: null,

		// _hiderMenuOpened: Boolean
		//		Records the current open/closed state of the menu.
		_hiderMenuOpened: false,

		// _columnHiderRules: Object
		//		Hash containing handles returned from addCssRule.
		_columnHiderRules: null,

		// _columnHiderCheckboxes: Object
		//		Hash containing checkboxes generated for menu items.
		_columnHiderCheckboxes: null,

		_renderHiderMenuEntries: function(){
			// summary:
			//		Iterates over subRows for the sake of adding items to the
			//		column hider menu.

			var subRows = this.subRows,
				srLength, cLength, sr, c;

			for(sr = 0, srLength = subRows.length; sr < srLength; sr++){
				for(c = 0, cLength = subRows[sr].length; c < cLength; c++){
					this._renderHiderMenuEntry(subRows[sr][c]);
				}
			}
		},

		_renderHiderMenuEntry: function(col){
			var id = col.id,
				div, checkId, checkbox;

			if(col.hidden){
				// Hidden state is true; hide the column.
				this._hideColumn(id);
			}

			// Allow cols to opt out of the hider (e.g. for selector column).
			if(col.unhidable){ return; }

			// Create the checkbox and label for each column selector.
			div = put("div.dgrid-hider-menu-row");
			checkId = this.domNode.id + "-hider-menu-check-" + id;

			this._columnHiderCheckboxes[id] = checkbox = put(div, "input#" + checkId +
					".dgrid-hider-menu-check.hider-menu-check-" + id + "[type=checkbox]");
			put(div, "label.dgrid-hider-menu-label.hider-menu-label" + id +
				"[" + forAttr + "=" + checkId + "]", col.label || col.field || "");

			put(this.hiderMenuNode, div);

			if(!col.hidden){
				// Hidden state is false; checkbox should be initially checked.
				// (Need to do this after adding to DOM to avoid IE6 clobbering it.)
				checkbox.checked = true;
			}
		},

		renderHeader: function(){
			var grid = this,
				hiderMenuNode = this.hiderMenuNode,
				hiderToggleNode = this.hiderToggleNode,
				id;

			this.inherited(arguments);

			if(!hiderMenuNode){ // first run
				// Assume that if this plugin is used, then columns are hidable.
				// Create the toggle node.
				hiderToggleNode = this.hiderToggleNode =
					put(this.headerScrollNode, "div.ui-icon.dgrid-hider-toggle");

				this._listeners.push(listen(hiderToggleNode, "click", function(e){
					grid._toggleColumnHiderMenu(e);
				}));

				// Create the column list, with checkboxes.
				hiderMenuNode = this.hiderMenuNode =
					put("div#dgrid-hider-menu-" + this.id + ".dgrid-hider-menu");

				// Make sure our menu is initially hidden, then attach to the document.
				hiderMenuNode.style.display = "none";
				put(this.domNode, hiderMenuNode);

				// Hook up delegated listener for modifications to checkboxes.
				this._listeners.push(listen(hiderMenuNode,
						".dgrid-hider-menu-check:" + (hasIE < 9 || hasIEQuirks ? "click" : "change"),
					function(e){
						grid._updateColumnHiddenState(
							getColumnIdFromCheckbox(e.target, grid), !e.target.checked);
					}
				));
				this._listeners.push(listen(hiderMenuNode, "mousedown", function(e){
					// Stop click events from propagating here, so that we can simply
					// track body clicks for hide without having to drill-up to check.
					e.stopPropagation();
				}));

				// Hook up top-level mousedown listener if it hasn't been yet.
				if(!bodyListener){
					bodyListener = listen.pausable(document, "mousedown", function(e){
						// If an event reaches this listener, the menu is open,
						// but a click occurred outside, so close the dropdown.
						activeGrid && activeGrid._toggleColumnHiderMenu(e);
					});
					bodyListener.pause(); // pause initially; will resume when menu opens
				}
			}else{ // subsequent run
				// Remove active rules, and clear out the menu (to be repopulated).
				for(id in this._columnHiderRules){
					this._columnHiderRules[id].remove();
				}
				hiderMenuNode.innerHTML = "";
			}

			this._columnHiderCheckboxes = {};
			this._columnHiderRules = {};

			// Populate menu with checkboxes/labels based on current columns.
			this._renderHiderMenuEntries();
		},

		destroy: function(){
			this.inherited(arguments);
			// Remove any remaining rules applied to hidden columns.
			for(var id in this._columnHiderRules){
				this._columnHiderRules[id].remove();
			}
		},

		isColumnHidden: function(id){
			// summary:
			//		Convenience method to determine current hidden state of a column
			return !!this._columnHiderRules[id];
		},

		_toggleColumnHiderMenu: function(){
			var hidden = this._hiderMenuOpened, // reflects hidden state after toggle
				hiderMenuNode = this.hiderMenuNode,
				domNode = this.domNode;

			// Show or hide the hider menu
			hiderMenuNode.style.display = (hidden ? "none" : "");

			// Adjust height of menu
			if (hidden) {
				// Clear the set size
				hiderMenuNode.style.height = "";
			} else {
				// Adjust height of the menu if necessary
				// Why 12? Based on menu default paddings and border, we need
				// to adjust to be 12 pixels shorter. Given the infrequency of
				// this style changing, we're assuming it will remain this
				// static value of 12 for now, to avoid pulling in any sort of
				// computed styles.
				if (hiderMenuNode.offsetHeight > domNode.offsetHeight - 12) {
					hiderMenuNode.style.height = (domNode.offsetHeight - 12) + "px";
				}
			}

			// Pause or resume the listener for clicks outside the menu
			bodyListener[hidden ? "pause" : "resume"]();

			// Update activeGrid appropriately
			activeGrid = hidden ? null : this;

			// Toggle the instance property
			this._hiderMenuOpened = !hidden;
		},

		_hideColumn: function(id){
			// summary:
			//		Hides the column indicated by the given id.

			// Use miscUtil function directly, since we clean these up ourselves anyway
			var selectorPrefix = "#" + miscUtil.escapeCssIdentifier(this.domNode.id) + " .dgrid-column-",
				next, rules, i; // used in IE8 code path

			if (this._columnHiderRules[id]) {
				return;
			}

			if(has("ie") === 8 && !has("quirks")){
				// Avoid inconsistent behavior in IE8 when display: none is set on a cell
				next = this.column(id).headerNode.nextSibling;

				rules = [ miscUtil.addCssRule(selectorPrefix + id,
					"width: 0 !important; white-space: nowrap !important; padding: 0 !important; margin: 0 !important; border: none !important;")
				];

				if(next && (next = this.column(next)) && (next = next.id)){
					// Also remove left border on next sibling if one exists, to avoid
					// width issues due to borders not collapsing
					rules.push(miscUtil.addCssRule(selectorPrefix + next, "border-left: none !important;"));
				}

				this._columnHiderRules[id] = {
					remove: function(){
						for(i = rules.length; i--;){ rules[i].remove(); }
					}
				};
			}else{
				this._columnHiderRules[id] =
					miscUtil.addCssRule(selectorPrefix + id, "display: none;");
			}
		},

		_updateColumnHiddenState: function(id, hidden){
			// summary:
			//		Performs internal work for toggleColumnHiddenState; see the public
			//		method for more information.

			if(!hidden){
				this._columnHiderRules[id] && this._columnHiderRules[id].remove();
				delete this._columnHiderRules[id];
			}else{
				this._hideColumn(id);
			}

			// Update hidden state in actual column definition,
			// in case columns are re-rendered.
			this.columns[id].hidden = hidden;

			// Emit event to notify of column state change.
			listen.emit(this.domNode, "dgrid-columnstatechange", {
				grid: this,
				column: this.columns[id],
				hidden: hidden,
				bubbles: true
			});

			// Adjust the size of the header.
			this.resize();
		},

		toggleColumnHiddenState: function(id, hidden){
			// summary:
			//		Shows or hides the column with the given id.
			// id: String
			//		ID of column to show/hide.
			// hide: Boolean?
			//		If specified, explicitly sets the hidden state of the specified
			//		column.  If unspecified, toggles the column from the current state.

			if(typeof hidden === "undefined"){ hidden = !this._columnHiderRules[id]; }
			this._updateColumnHiddenState(id, hidden);

			// Since this can be called directly, re-sync the appropriate checkbox.
			this._columnHiderCheckboxes[id].checked = !hidden;
		}
	});
});
<commit_msg>Fix #524 Temporarily change CSS "display" property of tables to force them to re-render with correct column widths in IE8<commit_after>define(["dojo/_base/declare", "dojo/has", "dojo/on", "../util/misc", "put-selector/put", "xstyle/css!../css/extensions/ColumnHider.css"],
function(declare, has, listen, miscUtil, put){
/*
 *	Column Hider plugin for dgrid
 *	Originally contributed by TRT 2011-09-28
 *
 *	A dGrid plugin that attaches a menu to a dgrid, along with a way of opening it,
 *	that will allow you to show and hide columns.  A few caveats:
 *
 *	1. Menu placement is entirely based on CSS definitions.
 *	2. If you want columns initially hidden, you must add "hidden: true" to your
 *		column definition.
 *	3. This implementation does NOT support ColumnSet, and has not been tested
 *		with multi-subrow records.
 *	4. Column show/hide is controlled via straight up HTML checkboxes.  If you
 *		are looking for something more fancy, you'll probably need to use this
 *		definition as a template to write your own plugin.
 *
 */

	var activeGrid, // references grid for which the menu is currently open
		bodyListener, // references pausable event handler for body mousedown
		// Need to handle old IE specially for checkbox listener and for attribute.
		hasIE = has("ie"),
		hasIEQuirks = hasIE && has("quirks"),
		forAttr = hasIE < 8 || hasIEQuirks ? "htmlFor" : "for";

	function getColumnIdFromCheckbox(cb, grid){
		// Given one of the checkboxes from the hider menu,
		// return the id of the corresponding column.
		// (e.g. gridIDhere-hider-menu-check-colIDhere -> colIDhere)
		return cb.id.substr(grid.id.length + 18);
	}

	return declare(null, {
		// hiderMenuNode: DOMNode
		//		The node for the menu to show/hide columns.
		hiderMenuNode: null,

		// hiderToggleNode: DOMNode
		//		The node for the toggler to open the menu.
		hiderToggleNode: null,

		// _hiderMenuOpened: Boolean
		//		Records the current open/closed state of the menu.
		_hiderMenuOpened: false,

		// _columnHiderRules: Object
		//		Hash containing handles returned from addCssRule.
		_columnHiderRules: null,

		// _columnHiderCheckboxes: Object
		//		Hash containing checkboxes generated for menu items.
		_columnHiderCheckboxes: null,

		_renderHiderMenuEntries: function(){
			// summary:
			//		Iterates over subRows for the sake of adding items to the
			//		column hider menu.

			var subRows = this.subRows,
				srLength, cLength, sr, c;

			for(sr = 0, srLength = subRows.length; sr < srLength; sr++){
				for(c = 0, cLength = subRows[sr].length; c < cLength; c++){
					this._renderHiderMenuEntry(subRows[sr][c]);
				}
			}
		},

		_renderHiderMenuEntry: function(col){
			var id = col.id,
				div, checkId, checkbox;

			if(col.hidden){
				// Hidden state is true; hide the column.
				this._hideColumn(id);
			}

			// Allow cols to opt out of the hider (e.g. for selector column).
			if(col.unhidable){ return; }

			// Create the checkbox and label for each column selector.
			div = put("div.dgrid-hider-menu-row");
			checkId = this.domNode.id + "-hider-menu-check-" + id;

			this._columnHiderCheckboxes[id] = checkbox = put(div, "input#" + checkId +
					".dgrid-hider-menu-check.hider-menu-check-" + id + "[type=checkbox]");
			put(div, "label.dgrid-hider-menu-label.hider-menu-label" + id +
				"[" + forAttr + "=" + checkId + "]", col.label || col.field || "");

			put(this.hiderMenuNode, div);

			if(!col.hidden){
				// Hidden state is false; checkbox should be initially checked.
				// (Need to do this after adding to DOM to avoid IE6 clobbering it.)
				checkbox.checked = true;
			}
		},

		renderHeader: function(){
			var grid = this,
				hiderMenuNode = this.hiderMenuNode,
				hiderToggleNode = this.hiderToggleNode,
				id;

			this.inherited(arguments);

			if(!hiderMenuNode){ // first run
				// Assume that if this plugin is used, then columns are hidable.
				// Create the toggle node.
				hiderToggleNode = this.hiderToggleNode =
					put(this.headerScrollNode, "div.ui-icon.dgrid-hider-toggle");

				this._listeners.push(listen(hiderToggleNode, "click", function(e){
					grid._toggleColumnHiderMenu(e);
				}));

				// Create the column list, with checkboxes.
				hiderMenuNode = this.hiderMenuNode =
					put("div#dgrid-hider-menu-" + this.id + ".dgrid-hider-menu");

				// Make sure our menu is initially hidden, then attach to the document.
				hiderMenuNode.style.display = "none";
				put(this.domNode, hiderMenuNode);

				// Hook up delegated listener for modifications to checkboxes.
				this._listeners.push(listen(hiderMenuNode,
						".dgrid-hider-menu-check:" + (hasIE < 9 || hasIEQuirks ? "click" : "change"),
					function(e){
						grid._updateColumnHiddenState(
							getColumnIdFromCheckbox(e.target, grid), !e.target.checked);
					}
				));
				this._listeners.push(listen(hiderMenuNode, "mousedown", function(e){
					// Stop click events from propagating here, so that we can simply
					// track body clicks for hide without having to drill-up to check.
					e.stopPropagation();
				}));

				// Hook up top-level mousedown listener if it hasn't been yet.
				if(!bodyListener){
					bodyListener = listen.pausable(document, "mousedown", function(e){
						// If an event reaches this listener, the menu is open,
						// but a click occurred outside, so close the dropdown.
						activeGrid && activeGrid._toggleColumnHiderMenu(e);
					});
					bodyListener.pause(); // pause initially; will resume when menu opens
				}
			}else{ // subsequent run
				// Remove active rules, and clear out the menu (to be repopulated).
				for(id in this._columnHiderRules){
					this._columnHiderRules[id].remove();
				}
				hiderMenuNode.innerHTML = "";
			}

			this._columnHiderCheckboxes = {};
			this._columnHiderRules = {};

			// Populate menu with checkboxes/labels based on current columns.
			this._renderHiderMenuEntries();
		},

		destroy: function(){
			this.inherited(arguments);
			// Remove any remaining rules applied to hidden columns.
			for(var id in this._columnHiderRules){
				this._columnHiderRules[id].remove();
			}
		},

		isColumnHidden: function(id){
			// summary:
			//		Convenience method to determine current hidden state of a column
			return !!this._columnHiderRules[id];
		},

		_toggleColumnHiderMenu: function(){
			var hidden = this._hiderMenuOpened, // reflects hidden state after toggle
				hiderMenuNode = this.hiderMenuNode,
				domNode = this.domNode;

			// Show or hide the hider menu
			hiderMenuNode.style.display = (hidden ? "none" : "");

			// Adjust height of menu
			if (hidden) {
				// Clear the set size
				hiderMenuNode.style.height = "";
			} else {
				// Adjust height of the menu if necessary
				// Why 12? Based on menu default paddings and border, we need
				// to adjust to be 12 pixels shorter. Given the infrequency of
				// this style changing, we're assuming it will remain this
				// static value of 12 for now, to avoid pulling in any sort of
				// computed styles.
				if (hiderMenuNode.offsetHeight > domNode.offsetHeight - 12) {
					hiderMenuNode.style.height = (domNode.offsetHeight - 12) + "px";
				}
			}

			// Pause or resume the listener for clicks outside the menu
			bodyListener[hidden ? "pause" : "resume"]();

			// Update activeGrid appropriately
			activeGrid = hidden ? null : this;

			// Toggle the instance property
			this._hiderMenuOpened = !hidden;
		},

		_hideColumn: function(id){
			// summary:
			//		Hides the column indicated by the given id.

			// Use miscUtil function directly, since we clean these up ourselves anyway
			var selectorPrefix = "#" + miscUtil.escapeCssIdentifier(this.domNode.id) + " .dgrid-column-",
				tableRule; // used in IE8 code path

			if (this._columnHiderRules[id]) {
				return;
			}

			this._columnHiderRules[id] =
				miscUtil.addCssRule(selectorPrefix + id, "display: none;");

			if(has("ie") === 8 && !has("quirks")){
				tableRule = miscUtil.addCssRule(".dgrid-row-table", "display: inline-table;");

				window.setTimeout(function(){
					tableRule.remove();
				}, 0);
			}
		},

		_updateColumnHiddenState: function(id, hidden){
			// summary:
			//		Performs internal work for toggleColumnHiddenState; see the public
			//		method for more information.

			if(!hidden){
				this._columnHiderRules[id] && this._columnHiderRules[id].remove();
				delete this._columnHiderRules[id];
			}else{
				this._hideColumn(id);
			}

			// Update hidden state in actual column definition,
			// in case columns are re-rendered.
			this.columns[id].hidden = hidden;

			// Emit event to notify of column state change.
			listen.emit(this.domNode, "dgrid-columnstatechange", {
				grid: this,
				column: this.columns[id],
				hidden: hidden,
				bubbles: true
			});

			// Adjust the size of the header.
			this.resize();
		},

		toggleColumnHiddenState: function(id, hidden){
			// summary:
			//		Shows or hides the column with the given id.
			// id: String
			//		ID of column to show/hide.
			// hide: Boolean?
			//		If specified, explicitly sets the hidden state of the specified
			//		column.  If unspecified, toggles the column from the current state.

			if(typeof hidden === "undefined"){ hidden = !this._columnHiderRules[id]; }
			this._updateColumnHiddenState(id, hidden);

			// Since this can be called directly, re-sync the appropriate checkbox.
			this._columnHiderCheckboxes[id].checked = !hidden;
		}
	});
});
<|endoftext|>


<commit_before>'use strict';

var async  = require('async');
var exec   = require('child_process').exec;
var moment = require('moment');
var _      = require('underscore');

_.templateSettings = {
  interpolate : /\{\{(.+?)\}\}/g
};

/**
 * Deploy helper
 * @param {Object} options                    Options to set up deploy
 * @param {String} options.user               User deploy from
 * @param {String} options.domain             Remote server domain
 * @param {String} options.deployTo           Remote folder to deploy in
 *
 * @param {String} options.repository         Git repository of project
 * @param {String} [options.branch='master']  Git branch that will be used for deploy
 *
 * @param {String} [options.deployFrom]       Remote folder to deploy from
 * @param {String} [options.keepReleases=3]   Amount of releases to keep
 */
function Deploy(options) {

  options.branch = options.branch || 'master';
  options.keepReleases = options.keepReleases || 3;
  options.hooks = options.hooks || {};
  this.options = options;

  this._folders = {};
  this._folders.projectPath = options.deployTo;
  this._folders.logsPath = this._folders.projectPath + '/logs';
  this._folders.sharedPath = this._folders.projectPath + '/shared';
  this._folders.releasesPath = this._folders.projectPath + '/releases';

  // always symlinked
  this._folders.currentPath = this._folders.projectPath + '/current';

  // will be resolved on deploy start
  this._folders.releasePath = null;

  this._commands = [];
}

Deploy.prototype.setup = function (done) {
  console.log('Starting...');

  this.run('mkdir -p {{releasesPath}} {{logsPath}} {{sharedPath}}');

  this.exec(done);
};

Deploy.prototype.start = function (done) {
  var that = this;

  this._trigger('beforeDeploy', start);

  function start() {
    var timestamp = moment().format('YYYYMMDDHHmmss');

    that._folders.releasePath = that._folders.releasesPath + '/' + timestamp;

    that.run('mkdir -p {{releasePath}}');
    that.run('git clone -q -b {{branch}} {{repository}} {{releasePath}}');
    that.exec(npmInstall);
  }

  /**
   * Install dependencies
   */
  function npmInstall(err) {
    if (err) {
      throw err;
    }

    that._npmInstall(symlink);
  }

  /**
   * Update/create symlink of current release
   */
  function symlink(err) {
    if (err) {
      throw err;
    }

    that.run('rm -f {{currentPath}}');
    that.run('ln -s {{releasePath}} {{currentPath}}');
    that.exec(cleanup);
  }

  function cleanup(err) {
    if (err) {
      throw err;
    }

    that.cleanup(function (err) {
      if (err) {
        throw err;
      }

      that._trigger('afterDeploy', done);
    });
  }
};

/**
 * Install project dependencies
 *
 * @param  {Function} done Installing dependencies done hook
 */
Deploy.prototype._npmInstall = function (done) {
  var that = this;

  this._trigger('beforeNpm', function () {
    that.run('cd {{releasePath}} && test -f {{releasePath}}/package.json && npm install || true');
    that.exec(function (err) {
      if (err) {
        throw err;
      }

      that._trigger('afterNpm', done);
    });
  });
};

Deploy.prototype.rollback = function (done) {
  var that = this;

  this.run('ls -1 {{releasesPath}}', { quiet: true });
  this.exec(rollback);

  function rollback(err, results) {
    var ls = results[0].trim(),
        folders = ls.split('\n'),
        release,
        previousRelease;

    if (folders.length < 2) {
      throw 'Rolling back is impossible, there are less then 2 releases.';
    }

    release = that._folders.releasesPath + '/' + folders[folders.length - 1];
    previousRelease = that._folders.releasesPath + '/' + folders[folders.length - 2];

    that.run('rm -f {{currentPath}}');
    that.run('ln -s ' + previousRelease + ' {{currentPath}}');
    that.run('rm -Rf ' + release);
    that.exec(done);
  }
};

/**
 * Remove releases that are not needed
 *
 * @param  {Function} done Cleanup done callback
 */
Deploy.prototype.cleanup = function (done) {
  var that = this;

  this.run('ls -1 {{releasesPath}}', { quiet: true });
  this.exec(function (err, results) {
    var folders,
        foldersToRemove;

    if (err) {
      throw err;
    }

    // split `ls` command response, trim last \n
    folders = results[0].trim().split('\n');
    foldersToRemove = folders.slice(0, -that.options.keepReleases);

    foldersToRemove.forEach(function (folder) {
      that.run('rm -Rf {{releasesPath}}/' + folder);
    });

    that.exec(done);
  });
};

/**
 * Trigger hooks
 */
Deploy.prototype._trigger = function (name, done) {
  var that = this,
      hook = this.options.hooks[name],
      isHookAsync = false;

  if (typeof hook === 'undefined') {
    // hook is not defined
    done();
    return;
  } else if (typeof hook !== 'function') {
    console.log('Hook `%s` should be a function', name);
    done();
    return;
  }

  console.log(
    (moment().format('YYYY-MM-DD HH:mm:ss') + ' executing ' + '`' + name +'`').green
  );

  hook.call(
    {
      // async hooks execution
      async: function () {
        isHookAsync = true;
        return afterHook;
      }
    },

    this.run.bind(this),
    this.runLocally.bind(this)
  );

  if ( !isHookAsync ) {
    afterHook();
  }

  function afterHook() {
    that.exec(done);
  }
};

/**
 * Add commands for remote execution
 *
 * @param {String}  command                 Command to execute
 * @param {Object}  [options]               Command execution options
 * @param {Boolean} [options.local=false]   Run command locally
 * @param {Boolean} [options.quiet=false]   Do not show output on the screen
 */
Deploy.prototype.run = function (command, options) {
  options = _.extend({ quiet: false, local: false }, options || {});

  this._commands.push({
    command: this._expandCommand(command),
    local: options.local,
    quiet: options.quiet
  });
};

/**
 * Add commands for local execution
 *
 * @param {String}  command                 Command to execute
 * @param {Object}  [options]               Command execution options
 * @param {Boolean} [options.quiet=false]   Do not show output on the screen
 */
Deploy.prototype.runLocally = function (command, options) {
  options = _.extend({ quiet: false }, options || {});
  options.local = true;
  this.run(command, options);
};

/**
 * Expand command: augment with variables, e.g. folders, user, domain
 *
 * @param {String} command Command to expand
 * @return {String}        Expanded command
 */
Deploy.prototype._expandCommand = function (command) {
  var data = _.extend({}, this.options, this._folders);

  return _.template(command, data);
};

/**
 * Convert command to remote
 */
Deploy.prototype._remoteCommand = function (command) {
  command = command.replace(/\"/g, '\\\"');

  return _.template(
    'ssh -A {{host}} "{{command}}"',
    { host: this.options.user + '@' + this.options.domain, command: command }
  );
};

/**
 * Execute stored commands
 *
 * @param  {Function} done Callback that will be called when all commands executed
 */
Deploy.prototype.exec = function (done) {
  var that = this;

  async.mapSeries(this._commands, function (command, callback) {
    var _exec,
        cmd = command.command;

    that.log(command);

    _exec = exec(
      command.local ? cmd : that._remoteCommand(cmd),
      callback
    );

    if ( !command.quiet ) {
      _exec.stdout.pipe(process.stdout);
      _exec.stderr.pipe(process.stderr);
    }
  }, function () {
    that._commands = [];
    done.apply(null, arguments);
  });
};

Deploy.prototype.log = function (command) {
  var isLocal = command.local,
      cmd     = command.command,
      log     = '* ';

  log = '*' + (' executing ' + (isLocal ? 'locally: ' : '') + '"' + cmd + '"').yellow;

  console.log(log);
};

module.exports = {
  Deploy: Deploy
};
<commit_msg>Move helper method down.<commit_after>'use strict';

var async  = require('async');
var exec   = require('child_process').exec;
var moment = require('moment');
var _      = require('underscore');

_.templateSettings = {
  interpolate : /\{\{(.+?)\}\}/g
};

/**
 * Deploy helper
 * @param {Object} options                    Options to set up deploy
 * @param {String} options.user               User deploy from
 * @param {String} options.domain             Remote server domain
 * @param {String} options.deployTo           Remote folder to deploy in
 *
 * @param {String} options.repository         Git repository of project
 * @param {String} [options.branch='master']  Git branch that will be used for deploy
 *
 * @param {String} [options.deployFrom]       Remote folder to deploy from
 * @param {String} [options.keepReleases=3]   Amount of releases to keep
 */
function Deploy(options) {

  options.branch = options.branch || 'master';
  options.keepReleases = options.keepReleases || 3;
  options.hooks = options.hooks || {};
  this.options = options;

  this._folders = {};
  this._folders.projectPath = options.deployTo;
  this._folders.logsPath = this._folders.projectPath + '/logs';
  this._folders.sharedPath = this._folders.projectPath + '/shared';
  this._folders.releasesPath = this._folders.projectPath + '/releases';

  // always symlinked
  this._folders.currentPath = this._folders.projectPath + '/current';

  // will be resolved on deploy start
  this._folders.releasePath = null;

  this._commands = [];
}

Deploy.prototype.setup = function (done) {
  console.log('Starting...');

  this.run('mkdir -p {{releasesPath}} {{logsPath}} {{sharedPath}}');

  this.exec(done);
};

Deploy.prototype.start = function (done) {
  var that = this;

  this._trigger('beforeDeploy', start);

  function start() {
    var timestamp = moment().format('YYYYMMDDHHmmss');

    that._folders.releasePath = that._folders.releasesPath + '/' + timestamp;

    that.run('mkdir -p {{releasePath}}');
    that.run('git clone -q -b {{branch}} {{repository}} {{releasePath}}');
    that.exec(npmInstall);
  }

  /**
   * Install dependencies
   */
  function npmInstall(err) {
    if (err) {
      throw err;
    }

    that._npmInstall(symlink);
  }

  /**
   * Update/create symlink of current release
   */
  function symlink(err) {
    if (err) {
      throw err;
    }

    that.run('rm -f {{currentPath}}');
    that.run('ln -s {{releasePath}} {{currentPath}}');
    that.exec(cleanup);
  }

  function cleanup(err) {
    if (err) {
      throw err;
    }

    that.cleanup(function (err) {
      if (err) {
        throw err;
      }

      that._trigger('afterDeploy', done);
    });
  }
};

/**
 * Install project dependencies
 *
 * @param  {Function} done Installing dependencies done hook
 */
Deploy.prototype._npmInstall = function (done) {
  var that = this;

  this._trigger('beforeNpm', function () {
    that.run('cd {{releasePath}} && test -f {{releasePath}}/package.json && npm install || true');
    that.exec(function (err) {
      if (err) {
        throw err;
      }

      that._trigger('afterNpm', done);
    });
  });
};

Deploy.prototype.rollback = function (done) {
  var that = this;

  this.run('ls -1 {{releasesPath}}', { quiet: true });
  this.exec(rollback);

  function rollback(err, results) {
    var ls = results[0].trim(),
        folders = ls.split('\n'),
        release,
        previousRelease;

    if (folders.length < 2) {
      throw 'Rolling back is impossible, there are less then 2 releases.';
    }

    release = that._folders.releasesPath + '/' + folders[folders.length - 1];
    previousRelease = that._folders.releasesPath + '/' + folders[folders.length - 2];

    that.run('rm -f {{currentPath}}');
    that.run('ln -s ' + previousRelease + ' {{currentPath}}');
    that.run('rm -Rf ' + release);
    that.exec(done);
  }
};

/**
 * Remove releases that are not needed
 *
 * @param  {Function} done Cleanup done callback
 */
Deploy.prototype.cleanup = function (done) {
  var that = this;

  this.run('ls -1 {{releasesPath}}', { quiet: true });
  this.exec(function (err, results) {
    var folders,
        foldersToRemove;

    if (err) {
      throw err;
    }

    // split `ls` command response, trim last \n
    folders = results[0].trim().split('\n');
    foldersToRemove = folders.slice(0, -that.options.keepReleases);

    foldersToRemove.forEach(function (folder) {
      that.run('rm -Rf {{releasesPath}}/' + folder);
    });

    that.exec(done);
  });
};

/**
 * Trigger hooks
 */
Deploy.prototype._trigger = function (name, done) {
  var that = this,
      hook = this.options.hooks[name],
      isHookAsync = false;

  if (typeof hook === 'undefined') {
    // hook is not defined
    done();
    return;
  } else if (typeof hook !== 'function') {
    console.log('Hook `%s` should be a function', name);
    done();
    return;
  }

  console.log(
    (moment().format('YYYY-MM-DD HH:mm:ss') + ' executing ' + '`' + name +'`').green
  );

  hook.call(
    {
      // async hooks execution
      async: function () {
        isHookAsync = true;
        return afterHook;
      }
    },

    this.run.bind(this),
    this.runLocally.bind(this)
  );

  if ( !isHookAsync ) {
    afterHook();
  }

  function afterHook() {
    that.exec(done);
  }
};

/**
 * Add commands for remote execution
 *
 * @param {String}  command                 Command to execute
 * @param {Object}  [options]               Command execution options
 * @param {Boolean} [options.local=false]   Run command locally
 * @param {Boolean} [options.quiet=false]   Do not show output on the screen
 */
Deploy.prototype.run = function (command, options) {
  options = _.extend({ quiet: false, local: false }, options || {});

  this._commands.push({
    command: this._expandCommand(command),
    local: options.local,
    quiet: options.quiet
  });
};

/**
 * Add commands for local execution
 *
 * @param {String}  command                 Command to execute
 * @param {Object}  [options]               Command execution options
 * @param {Boolean} [options.quiet=false]   Do not show output on the screen
 */
Deploy.prototype.runLocally = function (command, options) {
  options = _.extend({ quiet: false }, options || {});
  options.local = true;
  this.run(command, options);
};

/**
 * Execute stored commands
 *
 * @param  {Function} done Callback that will be called when all commands executed
 */
Deploy.prototype.exec = function (done) {
  var that = this;

  async.mapSeries(this._commands, function (command, callback) {
    var _exec,
        cmd = command.command;

    that.log(command);

    _exec = exec(
      command.local ? cmd : that._remoteCommand(cmd),
      callback
    );

    if ( !command.quiet ) {
      _exec.stdout.pipe(process.stdout);
      _exec.stderr.pipe(process.stderr);
    }
  }, function () {
    that._commands = [];
    done.apply(null, arguments);
  });
};

/**
 * Expand command: augment with variables, e.g. folders, user, domain
 *
 * @param {String} command Command to expand
 * @return {String}        Expanded command
 */
Deploy.prototype._expandCommand = function (command) {
  var data = _.extend({}, this.options, this._folders);

  return _.template(command, data);
};

/**
 * Convert command to remote
 */
Deploy.prototype._remoteCommand = function (command) {
  command = command.replace(/\"/g, '\\\"');

  return _.template(
    'ssh -A {{host}} "{{command}}"',
    { host: this.options.user + '@' + this.options.domain, command: command }
  );
};

Deploy.prototype.log = function (command) {
  var isLocal = command.local,
      cmd     = command.command,
      log     = '* ';

  log = '*' + (' executing ' + (isLocal ? 'locally: ' : '') + '"' + cmd + '"').yellow;

  console.log(log);
};

module.exports = {
  Deploy: Deploy
};
<|endoftext|>


<commit_before>function getMapForCanvas(canvas)
{
    var map =
    [
        new Line(30, 0, 110, 130),
        new Line(110, 130, 220, 60),
        new Line(270, 0, 370, 130),
        new Line(370, 130, 460, 60),
        new Line(700, 200, 550, 230),
        new Line(520, 250, 450, 270),
        new Line(450, 270, 450, 400),
        new Line(540, 0, 540, 130),
        new Line(540, 130, 585, 130),
        new Line(610, 130, 700, 130),
        new Line(0, 340, 220, 270),
        new Line(220, 270, 220, 400),
        new Line(220, 270, 290, 270),
        new Line(370, 270, 450, 270)
    ];

	map.push(new Line(0, 0, canvas.width, 0));
	map.push(new Line(canvas.width, 0, canvas.width, canvas.height));
	map.push(new Line(canvas.width, canvas.height, 0, canvas.height));
	map.push(new Line(0, canvas.height, 0, 0));

    convertToWorld(map);
    return map;
}

function convertToWorld(map) {
    for (i = 0; i < map.length; i++) {
        map[i] = getWorldLine(map[i]);
    }
}<commit_msg>replaced map<commit_after>function getMapForCanvas(canvas)
{
  //   var map =
  //   [
  //       new Line(30, 0, 110, 130),
  //       new Line(110, 130, 220, 60),
  //       new Line(270, 0, 370, 130),
  //       new Line(370, 130, 460, 60),
  //       new Line(700, 200, 550, 230),
  //       new Line(520, 250, 450, 270),
  //       new Line(450, 270, 450, 400),
  //       new Line(540, 0, 540, 130),
  //       new Line(540, 130, 585, 130),
  //       new Line(610, 130, 700, 130),
  //       new Line(0, 340, 220, 270),
  //       new Line(220, 270, 220, 400),
  //       new Line(220, 270, 290, 270),
  //       new Line(370, 270, 450, 270)
  //   ];
  //
	// map.push(new Line(0, 0, canvas.width, 0));
	// map.push(new Line(canvas.width, 0, canvas.width, canvas.height));
	// map.push(new Line(canvas.width, canvas.height, 0, canvas.height));
	// map.push(new Line(0, canvas.height, 0, 0));

    var map = [
      new Line(60.8389,15.0809,60.8389,13.2666),
      new Line(0.9887,40.3049,64.8519,40.2121),
      new Line(7.1836,40.2121,7.2962,31.2908),
      new Line(21.6452,40.2248,21.6452,31.2226),
      new Line(21.6452,31.2226,21.7249,31.3540),
      new Line(30.1670,40.1591,30.2467,31.2882),
      new Line(64.8918,39.9619,64.8918,45.6788),
      new Line(64.8918,45.6788,73.7322,45.6129),
      new Line(73.8915,40.2248,108.0588,40.2248),
      new Line(108.0588,40.2248,108.1384,19.7232),
      new Line(108.1384,19.7232,112.0409,19.5918),
      new Line(112.0409,19.5918,111.9613,12.1666),
      new Line(111.9613,12.1666,105.1916,12.0352),
      new Line(105.1916,12.0352,105.1120,13.1523),
      new Line(105.1120,13.1523,104.9526,13.3493),
      new Line(104.9526,13.3493,52.5470,13.0866),
      new Line(7.3093,31.2882,9.3801,31.2882),
      new Line(12.4065,30.8940,12.4065,31.3540),
      new Line(12.4065,28.9227,12.4065,28.5941),
      new Line(25.3884,28.3970,25.3088,22.3517),
      new Line(32.7954,28.3312,32.7156,22.2861),
      new Line(26.6628,22.3517,39.2465,22.2861),
      new Line(42.6713,22.3517,54.1399,22.3517),
      new Line(5.6367,13.1523,5.6367,19.7889),
      new Line(10.8137,19.7889,14.6366,19.7232),
      new Line(18.9372,19.6576,22.2027,19.6576),
      new Line(9.3801,13.3493,9.4597,19.7232),
      new Line(13.9197,13.2179,14.0790,19.7232),
      new Line(17.5036,13.0866,17.4240,19.5918),
      new Line(22.2027,13.1523,22.1230,19.8547),
      new Line(25.5478,13.1523,25.6274,19.7232),
      new Line(23.3973,19.6576,28.4946,19.7232),
      new Line(30.0874,13.1523,30.0079,19.9204),
      new Line(30.0079,19.9204,30.0874,19.5918),
      new Line(29.5300,19.6576,30.5653,19.6576),
      new Line(33.8307,13.1523,33.7510,19.7889),
      new Line(30.0079,13.2179,30.0874,19.5918),
      new Line(41.1580,13.0866,41.0783,14.1379),
      new Line(41.0783,15.1236,41.1580,19.6576),
      new Line(44.6623,13.2837,44.7419,19.7889),
      new Line(21.8044,31.3540,25.1495,31.2882),
      new Line(64.3343,31.2882,73.8119,31.1569),
      new Line(65.0511,31.4196,64.9715,38.5821),
      new Line(81.7763,37.1364,81.7763,40.0934),
      new Line(84.0063,31.2882,89.6610,31.2882),
      new Line(89.6610,31.2882,89.6610,36.0194),
      new Line(89.6610,36.0194,86.5549,36.0194),
      new Line(86.5620,40.1887,86.5620,37.0989),
      new Line(89.8284,40.2121,89.8284,37.1918),
      new Line(99.8528,35.9837,100.9227,35.9837),
      new Line(100.9790,37.1918,101.6830,37.1686),
      new Line(102.7812,37.1918,108.1312,37.1918),
      new Line(100.8946,22.3465,108.1312,22.3698),
      new Line(81.7470,22.3930,80.1982,22.3930),
      new Line(83.2392,25.8546,83.3237,28.5032),
      new Line(83.2392,25.9243,83.2674,22.4162),
      new Line(84.4219,22.4394,84.4219,28.4101),
      new Line(81.0710,22.3001,81.0992,21.7658),
      new Line(81.0429,20.0465,81.0429,19.8143),
      new Line(104.8650,19.7446,105.4563,19.7213),
      new Line(106.7234,19.7213,108.1877,19.6982),
      new Line(105.1747,19.7446,105.1747,13.2165),
      new Line(103.7105,19.7213,100.9227,19.7213),
      new Line(99.7682,19.6982,95.4038,19.6982),
      new Line(94.1928,19.6749,92.8131,19.6982),
      new Line(91.6586,19.6749,88.7865,19.7213),
      new Line(87.6320,19.7679,78.4243,19.8143),
      new Line(76.9318,19.7446,76.2278,19.7446),
      new Line(75.1297,19.7446,72.4828,19.7213),
      new Line(101.1761,19.6517,101.1199,13.2396),
      new Line(97.4310,19.6517,97.4592,13.2165),
      new Line(93.0383,19.6749,93.0947,13.1235),
      new Line(89.0963,19.7213,89.0681,13.1003),
      new Line(81.1837,19.7911,81.1274,13.0072),
      new Line(76.5939,19.7446,76.5939,13.1932),
      new Line(72.9896,19.8143,72.9896,13.1467),
      new Line(68.3716,13.1467,68.3434,19.7446),
      new Line(60.4874,28.5496,74.0033,28.5032),
      new Line(73.9752,22.5557,73.9469,22.0446),
      new Line(73.9469,22.0446,65.5840,21.9051),
      new Line(65.5840,21.9051,65.5840,22.1839),
      new Line(65.5840,22.1839,65.6403,22.4394),
      new Line(65.6403,22.4394,65.6403,28.5032),
      new Line(63.8382,22.3930,65.5840,22.3930),
      new Line(62.5710,22.3930,55.5033,22.3465),
      new Line(59.8396,19.6982,61.9234,19.6749),
      new Line(63.0779,19.6749,71.3846,19.6749),
      new Line(60.8535,15.0053,60.8535,19.6517),
      new Line(57.2210,19.7213,57.2491,13.1235),
      new Line(82.9651,31.2948,76.6198,31.2948),
      new Line(73.7485,45.6551,73.7839,39.7179),
      new Line(73.9257,40.2443,73.7662,40.2296),
      new Line(64.8862,39.9810,73.7839,39.9518),
      new Line(81.7720,40.0552,81.7720,40.2414),
      new Line(86.5633,36.0108,86.5633,35.6964),
      new Line(89.6474,36.0254,98.6425,35.9743),
      new Line(25.3783,28.3261,25.3783,28.4870),
      new Line(17.7035,19.6837,15.9844,19.6837),
      new Line(17.4024,19.5082,17.4024,19.6690),
      new Line(9.7453,19.7422,7.1752,19.7422),
      new Line(6.0765,19.7860,5.4559,19.7714),
      new Line(61.1489,22.4287,61.1489,28.6133),
      new Line(61.1489,28.6133,61.1881,28.4839),
      new Line(39.2602,22.2847,42.6654,22.3510),
      new Line(26.1790,31.2478,33.5884,31.2765),
      new Line(37.3627,31.2881,33.5247,31.2486),
      new Line(55.4450,31.2881,39.1235,31.2881),
      new Line(37.7980,31.2684,37.2242,31.2684),
      new Line(63.1013,31.2683,56.3748,31.2683),
      new Line(74.1967,35.5492,74.1745,31.2155),
      new Line(74.0039,28.5005,74.4586,28.5005),
      new Line(74.4586,28.5005,74.4292,24.5254),
      new Line(73.8128,31.1559,74.1703,31.1541),
      new Line(74.1758,31.1862,74.2315,40.1964),
      new Line(73.9446,22.0513,73.9446,22.5688),
      new Line(23.7588,31.2971,23.7324,30.5562),
      new Line(23.6971,29.1890,23.7500,28.5892),
      new Line(14.3022,31.2570,14.1692,27.1546),
      new Line(14.1692,27.1546,16.2204,27.1356),
      new Line(16.2204,27.1356,16.2394,26.8697),
      new Line(22.5830,28.6550,19.7911,28.6550),
      new Line(23.7503,28.6408,31.1366,28.5032),
      new Line(19.8278,28.6132,19.8278,22.4875),
      new Line(19.8278,22.3832,25.2497,22.3572),
      new Line(16.2656,27.0323,16.1665,19.7728),
      new Line(5.4142,13.0427,52.4294,13.0427),
      new Line(16.2375,31.3264,21.6094,31.2910),
      new Line(14.9180,31.3381,14.9298,32.4219),
      new Line(16.2610,31.3264,16.2846,32.3277),
      new Line(79.4829,28.6052,79.5830,22.1993),
      new Line(74.4326,22.8286,74.4524,22.0373),
      new Line(74.4524,22.0373,73.9578,22.0373),
      new Line(73.9380,24.5696,74.4326,24.5696),
      new Line(74.4276,22.8272,73.0992,22.8070),
      new Line(74.4343,24.5481,70.9911,24.5338),
      new Line(28.5238,19.8081,61.7966,19.7674),
      new Line(60.4267,28.5820,48.2768,28.6090),
      new Line(46.5139,28.5621,31.2367,28.5306),
      new Line(81.8684,22.2753,86.9179,22.2346),
      new Line(86.9179,22.2346,86.9383,22.0513),
      new Line(86.9383,22.0513,87.7120,22.0513),
      new Line(87.7120,22.0513,87.7120,22.2346),
      new Line(87.7120,22.2346,93.5963,22.1735),
      new Line(93.5963,22.1735,93.6166,21.9699),
      new Line(93.6166,21.9699,94.4107,22.0106),
      new Line(94.4107,22.0106,94.4107,22.2549),
      new Line(94.4107,22.2549,95.6324,22.2549),
      new Line(98.0350,22.2957,100.2950,22.2549),
      new Line(100.2950,22.2549,100.3154,21.9495),
      new Line(100.3154,21.9495,101.3538,21.9292),
      new Line(101.3538,21.9292,101.3334,22.3771),
      new Line(101.3334,22.3771,102.8401,22.3567),
      new Line(102.8401,22.3567,102.8605,19.7709),
      new Line(98.0184,22.2461,98.1108,35.9509),
      new Line(95.6037,28.8723,95.5633,22.3149),
      new Line(95.6440,31.3137,95.6037,35.9544),
      new Line(95.6440,31.2935,89.6717,31.2935),
      new Line(95.5633,28.8925,79.4825,28.7916),
      new Line(76.0931,31.2569,76.0931,40.1992),
      new Line(82.9641,31.2953,76.0898,31.2870),
      new Line(67.4098,22.3231,71.4502,22.3416),
      new Line(71.4502,22.3416,71.4687,22.8028),
      new Line(67.4467,22.3231,67.4467,27.8211),
    ];

    convertToWorld(map);
    return map;
}

function convertToWorld(map) {
    for (i = 0; i < map.length; i++) {
      var sc = 6;
      map[i].s.x = map[i].s.x * sc;
      map[i].s.y = map[i].s.y * sc;
      map[i].t.x = map[i].t.x * sc;
      map[i].t.y = map[i].t.y * sc;
        map[i] = getWorldLine(map[i]);
    }
}
<|endoftext|>


<commit_before>/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

Engine.currentGame = {};

function Engine(resolution, title, canvasParent)
{
    Engine.currentGame[title] = { gameAssets: {},
                                  resolution: resolution,
                                  currentScene: null,
                                  loadingScene: null};

    var engine = {};
    engine.loading = true;
    engine.gameTitle = title;

    engine.canvas = document.createElement('canvas');
    engine.canvas.oncontextmenu = function() { return false; };

    var canvasLocation = canvasParent || 'body';
    var oldScene = null;
    var maxFrameTime = 100;

    var scriptsPreloading = 0;
    var scriptsLoaded = 0;

    var assetsPreloading = 0;
    var assetsLoaded = 0;

    engine.input = null;

    $.getScript("engine/Input.js", function()
    {
        engine.input = new Input(["Keyboard", "Mouse", "Controllers"], engine.canvas);
    });

    engine.Start = function(scene)
    {
        if(engine.loading)
        {
            console.log("please use the onloaded function to start up");
            return;
        }
        if(scene instanceof Scene)
        {
            Engine.currentGame[engine.gameTitle].currentScene = scene;
            gameLoop();
        }else
        {
            console.log("the scene has to be an instance of Scene");
            return false;
        }
    };

    engine.onLoaded = function(callback)
    {
        if(engine.input === null || scriptsLoaded < scriptsPreloading || assetsLoaded < assetsPreloading)
        {
            scheduleFrame(engine.onLoaded.bind(this, callback));
            return;
        }

        engine.loading = false;
        callback();
    };

    scheduleFrame = function(callback)
    {
        return window.requestAnimationFrame(callback);
    };

    cancelFrame = function(loop)
    {
        window.cancelAnimationFrame(loop);
    };

    gameLoop = function()
    {
        engine.canvas.id = engine.gameTitle;
        engine.canvas.width = Engine.currentGame[engine.gameTitle].resolution.x;
        engine.canvas.height = Engine.currentGame[engine.gameTitle].resolution.y;
        engine.canvas.style.border = "1px solid";
        if(canvasLocation !== 'body' && document.getElementById(canvasLocation))
        {
            document.getElementById(canvasLocation).appendChild(engine.canvas);
        }else
        {
            (document.getElementsByTagName('body')[0]).appendChild(engine.canvas);
        }

        engine.lastFrame = new Date().getTime();
        engine.loop = true;
        engine.currentFrame = 0;

        engine.gameLoopCallback = function()
        {
            var now = new Date().getTime();
            engine.currentFrame++;
            engine.loop = scheduleFrame(engine.gameLoopCallback);
            var dt = now - engine.lastFrame;
            if(dt > maxFrameTime) { dt = maxFrameTime; }

            Engine.currentGame[engine.gameTitle].currentScene.Update.apply(engine, [engine.input, dt/1000]);
            Draw(engine.canvas.getContext('2d'));
            if(engine.input !== null) engine.input.Update(dt/1000);
            engine.lastFrame = now;
        };
        scheduleFrame(engine.gameLoopCallback);
    };

    function Draw(context)
    {
        context.clearRect(0,0, Engine.currentGame[engine.gameTitle].resolution.x, Engine.currentGame[engine.gameTitle].resolution.y);
        context.fillStyle = "#000";
        context.save();
        context.scale(1,1);

        Engine.currentGame[engine.gameTitle].currentScene.Draw.apply(Engine, [engine.canvas.getContext('2d')]);

        context.restore();
    }

    engine.pauseGame = function()
    {
        if(engine.loop)
        {
            cancelFrame(engine.loop);
        }
        engine.loop = null;
    };

    engine.unpauseGame = function()
    {
        if(!engine.loop)
        {
            engine.lastFrame = new Date().getTime();
            engine.loop = scheduleFrame(engine.gameLoopCallback);
        }
    };

    engine.isString = function(obj)
    {
        return typeof obj === "string";
    };

    engine.isArray = function(obj)
    {
        return Object.prototype.toString.call(obj) === '[object Array]';
    };

    engine.isNumber = function(obj)
    {
        return Object.prototype.toString.call(obj) === '[object Number]';
    };

    engine.isFunction = function(obj)
    {
        return Object.prototype.toString.call(obj) === '[object Function]';
    };

    engine.isObject = function(obj)
    {
        return Object.prototype.toString.call(obj) === '[object Object]';
    };

    engine.isUndefined = function(obj)
    {
        return obj === void 0;
    };

    engine.normalizeArg = function(arg)
    {
        if(engine.isString(arg))
        {
            arg = arg.replace(/\s+/g, '').split(",");
        }
        if(!engine.isArray(arg))
        {
            arg = [arg];
        }
        return arg;
    };

    function normalizeAssets(arg)
    {
        var assetArray = {};
        arg = engine.normalizeArg(arg);

        for(var i = 0; i < arg.length; i++)
        {
            if(arg[i].indexOf(":") !== -1)
            {
                var subArray = arg[i].split(":");
                if(!engine.isUndefined(assetArray[subArray[0]]))
                {
                    console.log("Warning: asset with duplicate name," + subArray[0] + " " + subArray[1] + " asset not loaded");
                }else
                {
                    assetArray[subArray[0]] = subArray[1];
                }
            }else
            {
                console.log("Error: assets are invalid");
                return false;
            }
        }

        return assetArray;
    };

    engine.switchScene = function(scene, keepScene)
    {
        engine.pauseGame();
        oldScene = Engine.currentGame[engine.gameTitle].currentScene;
        Engine.currentGame[engine.gameTitle].currentScene = scene;
        if(!keepScene) delete oldScene;
        engine.unpauseGame();
    };

    engine.switchOldScene = function(keepScene)
    {
        if(oldScene !== null)
        {
            engine.switchScene(oldScene, keepScene);
        }
    };

    engine.PreloadScripts = function(scripts)
    {
        scripts  = engine.normalizeArg(scripts);

        if(scripts !== false)
        {
            for(var i = 0; i < scripts.length; i++)
            {
                scriptsPreloading++;
                $.getScript(scripts[i], function()
                {
                    scriptsLoaded++;
                });
            }
        }else
        {
            console.log("Error: loading scripts failed");
            return false;
        }
    };

    engine.PreloadAssets = function(assets)
    {
        assets = normalizeAssets(assets);

        if(assets !== false)
        {
            for(var key in assets)
            {
                Engine.currentGame[engine.gameTitle].gameAssets[key] = loadImage(assets[key], key);
            }
        }else
        {
            console.log("Error: loading assets failed");
            return false;
        }
    };

    function loadImage(imageUrl, key)
    {
        assetsPreloading++;
        var image = new Image();
        image.name = image.alt = key;
        image.onload = function()
        {
            assetsLoaded++;
        };
        image.src = imageUrl;

        return image;
    }
    engine.PreloadScripts(["engine/ExtendedMath.js", "engine/GameObject.js", "engine/Scene.js"]);

    return engine;
};<commit_msg>Fixed a bug: now calling the scenes update and draw correct.<commit_after>/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

Engine.currentGame = {};

function Engine(resolution, title, canvasParent)
{
    Engine.currentGame[title] = { gameAssets: {},
                                  resolution: resolution,
                                  currentScene: null,
                                  loadingScene: null};

    var engine = {};
    engine.loading = true;
    engine.gameTitle = title;

    engine.canvas = document.createElement('canvas');
    engine.canvas.oncontextmenu = function() { return false; };

    var canvasLocation = canvasParent || 'body';
    var oldScene = null;
    var maxFrameTime = 100;

    var scriptsPreloading = 0;
    var scriptsLoaded = 0;

    var assetsPreloading = 0;
    var assetsLoaded = 0;

    engine.input = null;

    $.getScript("engine/Input.js", function()
    {
        engine.input = new Input(["Keyboard", "Mouse", "Controllers"], engine.canvas);
    });

    engine.Start = function(scene)
    {
        if(engine.loading)
        {
            console.log("please use the onloaded function to start up");
            return;
        }
        if(scene instanceof Scene)
        {
            Engine.currentGame[engine.gameTitle].currentScene = scene;
            gameLoop();
        }else
        {
            console.log("the scene has to be an instance of Scene");
            return false;
        }
    };

    engine.onLoaded = function(callback)
    {
        if(engine.input === null || scriptsLoaded < scriptsPreloading || assetsLoaded < assetsPreloading)
        {
            scheduleFrame(engine.onLoaded.bind(this, callback));
            return;
        }

        engine.loading = false;
        callback();
    };

    scheduleFrame = function(callback)
    {
        return window.requestAnimationFrame(callback);
    };

    cancelFrame = function(loop)
    {
        window.cancelAnimationFrame(loop);
    };

    gameLoop = function()
    {
        engine.canvas.id = engine.gameTitle;
        engine.canvas.width = Engine.currentGame[engine.gameTitle].resolution.x;
        engine.canvas.height = Engine.currentGame[engine.gameTitle].resolution.y;
        engine.canvas.style.border = "1px solid";
        if(canvasLocation !== 'body' && document.getElementById(canvasLocation))
        {
            document.getElementById(canvasLocation).appendChild(engine.canvas);
        }else
        {
            (document.getElementsByTagName('body')[0]).appendChild(engine.canvas);
        }

        engine.lastFrame = new Date().getTime();
        engine.loop = true;
        engine.currentFrame = 0;

        engine.gameLoopCallback = function()
        {
            var now = new Date().getTime();
            engine.currentFrame++;
            engine.loop = scheduleFrame(engine.gameLoopCallback);
            var dt = now - engine.lastFrame;
            if(dt > maxFrameTime) { dt = maxFrameTime; }

            Engine.currentGame[engine.gameTitle].currentScene.Update(engine.input, dt/1000);
            Draw(engine.canvas.getContext('2d'));
            if(engine.input !== null) engine.input.Update(dt/1000);
            engine.lastFrame = now;
        };
        scheduleFrame(engine.gameLoopCallback);
    };

    function Draw(context)
    {
        context.clearRect(0,0, Engine.currentGame[engine.gameTitle].resolution.x, Engine.currentGame[engine.gameTitle].resolution.y);
        context.fillStyle = "#000";
        context.save();
        context.scale(1,1);

        Engine.currentGame[engine.gameTitle].currentScene.Draw(engine.canvas.getContext('2d'));

        context.restore();
    }

    engine.pauseGame = function()
    {
        if(engine.loop)
        {
            cancelFrame(engine.loop);
        }
        engine.loop = null;
    };

    engine.unpauseGame = function()
    {
        if(!engine.loop)
        {
            engine.lastFrame = new Date().getTime();
            engine.loop = scheduleFrame(engine.gameLoopCallback);
        }
    };

    engine.isString = function(obj)
    {
        return typeof obj === "string";
    };

    engine.isArray = function(obj)
    {
        return Object.prototype.toString.call(obj) === '[object Array]';
    };

    engine.isNumber = function(obj)
    {
        return Object.prototype.toString.call(obj) === '[object Number]';
    };

    engine.isFunction = function(obj)
    {
        return Object.prototype.toString.call(obj) === '[object Function]';
    };

    engine.isObject = function(obj)
    {
        return Object.prototype.toString.call(obj) === '[object Object]';
    };

    engine.isUndefined = function(obj)
    {
        return obj === void 0;
    };

    engine.normalizeArg = function(arg)
    {
        if(engine.isString(arg))
        {
            arg = arg.replace(/\s+/g, '').split(",");
        }
        if(!engine.isArray(arg))
        {
            arg = [arg];
        }
        return arg;
    };

    function normalizeAssets(arg)
    {
        var assetArray = {};
        arg = engine.normalizeArg(arg);

        for(var i = 0; i < arg.length; i++)
        {
            if(arg[i].indexOf(":") !== -1)
            {
                var subArray = arg[i].split(":");
                if(!engine.isUndefined(assetArray[subArray[0]]))
                {
                    console.log("Warning: asset with duplicate name," + subArray[0] + " " + subArray[1] + " asset not loaded");
                }else
                {
                    assetArray[subArray[0]] = subArray[1];
                }
            }else
            {
                console.log("Error: assets are invalid");
                return false;
            }
        }

        return assetArray;
    };

    engine.switchScene = function(scene, keepScene)
    {
        engine.pauseGame();
        oldScene = Engine.currentGame[engine.gameTitle].currentScene;
        Engine.currentGame[engine.gameTitle].currentScene = scene;
        if(!keepScene) delete oldScene;
        engine.unpauseGame();
    };

    engine.switchOldScene = function(keepScene)
    {
        if(oldScene !== null)
        {
            engine.switchScene(oldScene, keepScene);
        }
    };

    engine.PreloadScripts = function(scripts)
    {
        scripts  = engine.normalizeArg(scripts);

        if(scripts !== false)
        {
            for(var i = 0; i < scripts.length; i++)
            {
                scriptsPreloading++;
                $.getScript(scripts[i], function()
                {
                    scriptsLoaded++;
                });
            }
        }else
        {
            console.log("Error: loading scripts failed");
            return false;
        }
    };

    engine.PreloadAssets = function(assets)
    {
        assets = normalizeAssets(assets);

        if(assets !== false)
        {
            for(var key in assets)
            {
                Engine.currentGame[engine.gameTitle].gameAssets[key] = loadImage(assets[key], key);
            }
        }else
        {
            console.log("Error: loading assets failed");
            return false;
        }
    };

    function loadImage(imageUrl, key)
    {
        assetsPreloading++;
        var image = new Image();
        image.name = image.alt = key;
        image.onload = function()
        {
            assetsLoaded++;
        };
        image.src = imageUrl;

        return image;
    }
    engine.PreloadScripts(["engine/ExtendedMath.js", "engine/Sprite.js", "engine/Animation.js", "engine/GameObject.js", "engine/Scene.js", "engine/ReadTextFile.js"]);

    return engine;
};<|endoftext|>