1392 lines
43 KiB
JavaScript
1392 lines
43 KiB
JavaScript
/**
|
||
* @param {Object} data
|
||
* @param {Object} o
|
||
* @return {?}
|
||
*/
|
||
function Mover(data, o) {
|
||
if (this.created = data.created, this.x = data.x, this.y = data.y, this.offset = data.offset, this.destination = data.destination, this.layer = o.el, this.color = "hsl(" + data.port % 360 + ", 100%, 70%)", this.hit = data.onMoverHit, this.x === this.destination.x && this.y === this.destination.y) {
|
||
return void this.hit();
|
||
}
|
||
/** @type {string} */
|
||
var _tmp = "clippath-" + Math.random();
|
||
this.clipPath = o._defs.append("clipPath").attr("id", _tmp);
|
||
this.cliprect = this.clipPath.append("rect").attr({
|
||
x: -trail.radius,
|
||
y: -trail.radius,
|
||
width: trail.height,
|
||
height: trail.base
|
||
});
|
||
this.obj = this.layer.append("polygon").datum(this).classed("animating", true).attr("points", trail.points).attr("clip-path", "url(#" + _tmp + ")").attr("fill", this.color);
|
||
var vector = this.destination;
|
||
return this.dx = vector.lx - this.x, this.dy = vector.ly - this.y, this.distance = Math.sqrt(this.dx * this.dx + this.dy * this.dy), this.update(), data.zerg && this.distance > 3 * trail.height ? this.startCurve() : this.start(), this;
|
||
}
|
||
/**
|
||
* @param {?} dataAndEvents
|
||
* @param {?} position
|
||
* @return {undefined}
|
||
*/
|
||
function Floater(dataAndEvents, position) {
|
||
if (!num) {
|
||
/** @type {number} */
|
||
num = 1;
|
||
}
|
||
this.position = position;
|
||
this.addOne();
|
||
}
|
||
/**
|
||
* @return {undefined}
|
||
*/
|
||
function Anchor() {}
|
||
/**
|
||
* @param {Object} options
|
||
* @return {undefined}
|
||
*/
|
||
function Ping(options) {
|
||
this.position = options.position;
|
||
}
|
||
|
||
var ipv = {
|
||
version: "0"
|
||
};
|
||
/** @type {number} */
|
||
var ZERO = 1E-6;
|
||
/** @type {number} */
|
||
var TWO_PI = 2 * Math.PI;
|
||
var ipv_helpers = {
|
||
/**
|
||
* @param {Object} b
|
||
* @param {Object} a
|
||
* @return {?}
|
||
*/
|
||
sort_descCountAscCountry: function(b, a) {
|
||
return a.count > b.count ? 1 : a.count < b.count ? -1 : b.country < a.country ? 1 : a.country < b.country ? -1 : 0;
|
||
},
|
||
/**
|
||
* @param {Object} b
|
||
* @param {Object} a
|
||
* @return {?}
|
||
*/
|
||
sort_descCountAscService: function(b, a) {
|
||
return a.count > b.count ? 1 : a.count < b.count ? -1 : b.service < a.service ? 1 : a.service < b.service ? -1 : 0;
|
||
},
|
||
/**
|
||
* @param {Object} srv
|
||
* @return {?}
|
||
*/
|
||
return_cx: function(srv) {
|
||
return srv.cx;
|
||
},
|
||
/**
|
||
* @param {Object} o2
|
||
* @return {?}
|
||
*/
|
||
return_cy: function(o2) {
|
||
return o2.cy;
|
||
},
|
||
/**
|
||
* @param {MessageEvent} params
|
||
* @return {?}
|
||
*/
|
||
return_data: function(params) {
|
||
return params.data;
|
||
},
|
||
/**
|
||
* @param {?} dataAndEvents
|
||
* @return {?}
|
||
*/
|
||
d3_identity: function(dataAndEvents) {
|
||
return dataAndEvents;
|
||
}
|
||
};
|
||
ipv.hash = {
|
||
args: {},
|
||
/**
|
||
* @param {string} query
|
||
* @return {?}
|
||
*/
|
||
parse: function(query) {
|
||
query = (query || window.location.search).replace(/^\?/, "");
|
||
var args = {};
|
||
return query.split("&").forEach(function(pair) {
|
||
pair = pair.split("=");
|
||
args[pair[0]] = pair[1];
|
||
}), this.args = args, args;
|
||
},
|
||
/**
|
||
* @return {undefined}
|
||
*/
|
||
set: function() {}
|
||
},
|
||
ipv.stream = {
|
||
timestamp: d3.time.format("%Y-%m-%d %H:%M:%S.%L"),
|
||
active: null,
|
||
backlog: [],
|
||
timeout: 1e3
|
||
},
|
||
ipv.stream.socket = function(options, callback) {
|
||
/** @type {WebSocket} */
|
||
var self = new WebSocket(options.host);
|
||
return self.onopen = function() {
|
||
setInterval(function () {
|
||
self.send(options.psk);
|
||
}, 1000);
|
||
},
|
||
self.onmessage = callback,
|
||
self.onclose = function() {
|
||
var client = ipv.stream;
|
||
setTimeout(function() {
|
||
self = client.socket(options, callback);
|
||
}, client.timeout);
|
||
},
|
||
self.onerror = function() {
|
||
console.log("socket error");
|
||
},
|
||
ipv.stream.active = self,
|
||
self;
|
||
},
|
||
|
||
// Todo:?
|
||
ipv.stream.json = function(obj, files) {
|
||
/** @type {number} */
|
||
var frequency = 3000;
|
||
d3.json(obj, function(dataAndEvents, results) {
|
||
if (dataAndEvents) {
|
||
throw dataAndEvents;
|
||
}
|
||
results = results.map(function(data) {
|
||
return {
|
||
data: JSON.stringify(data),
|
||
timestamp: data.timestamp
|
||
};
|
||
});
|
||
var data = d3.nest().key(function(data) {
|
||
return "string" == typeof data.timestamp && (data.timestamp = +ipv.stream.timestamp(data.timestamp)), Math.round(data.timestamp / frequency) * frequency;
|
||
}).map(results);
|
||
var values = d3.keys(data).map(Number);
|
||
values.sort(d3.ascending);
|
||
var value = values[0];
|
||
/** @type {number} */
|
||
var id = setInterval(function() {
|
||
if (values.length) {
|
||
if (values[0] === value) {
|
||
data["" + values.shift()].forEach(files);
|
||
}
|
||
value += frequency;
|
||
} else {
|
||
clearInterval(id);
|
||
}
|
||
}, frequency);
|
||
});
|
||
},
|
||
|
||
// 暂停
|
||
ipv.stream.pause = function() {
|
||
if (ipv.stream.active) {
|
||
/** @type {boolean} */
|
||
ipv.stream.paused = true;
|
||
|
||
/** @type {number} */
|
||
ipv.stream.backlog.length = 0;
|
||
ipv.stream.msgHandler = ipv.stream.active.onmessage.bind({});
|
||
/**
|
||
* @param {?} m
|
||
* @return {undefined}
|
||
*/
|
||
ipv.stream.active.onmessage = function(m) {
|
||
if (ipv.stream.backlog.length >= 5E3) {
|
||
ipv.stream.backlog.shift();
|
||
}
|
||
ipv.stream.backlog.push(m);
|
||
};
|
||
}
|
||
},
|
||
|
||
// 播放
|
||
ipv.stream.play = function() {
|
||
if (ipv.stream.active) {
|
||
/** @type {boolean} */
|
||
ipv.stream.paused = false;
|
||
ipv.stream.active.onmessage = ipv.stream.msgHandler.bind(ipv.stream.active);
|
||
ipv.stream.backlog.forEach(function(msg) {
|
||
ipv.stream.active.onmessage(msg);
|
||
});
|
||
/** @type {number} */
|
||
ipv.stream.backlog.length = 0;
|
||
}
|
||
},
|
||
|
||
// 经纬度和坐标映射
|
||
ipv.map = function(obj) {
|
||
var map = L.map(obj.container, obj.options);
|
||
return map._proj = function(lng, lat) {
|
||
var offsetCoordinate = map.latLngToLayerPoint(new L.LatLng(lat, lng));
|
||
return [offsetCoordinate.x, offsetCoordinate.y];
|
||
}, map;
|
||
};
|
||
|
||
var trail = function() {
|
||
/** @type {number} */
|
||
var size = 2;
|
||
/** @type {number} */
|
||
var length = 2 * size;
|
||
/** @type {number} */
|
||
var x = 40 * length;
|
||
/** @type {number} */
|
||
var totalFiles = 6;
|
||
var logo_center = {
|
||
x: size,
|
||
y: size
|
||
};
|
||
/** @type {number} */
|
||
var b = Math.PI / 2;
|
||
/** @type {number} */
|
||
var a = 3 * Math.PI / 2;
|
||
/** @type {Array} */
|
||
var points = [];
|
||
/** @type {number} */
|
||
var filesSent = 0;
|
||
for (; totalFiles >= filesSent; ++filesSent) {
|
||
/** @type {number} */
|
||
var theta2 = b + (a - b) * (filesSent / totalFiles);
|
||
/** @type {number} */
|
||
var frame_temp = logo_center.x + size * Math.cos(theta2);
|
||
/** @type {number} */
|
||
var gutterTop = logo_center.y + size * Math.sin(theta2);
|
||
points.push([frame_temp - size, gutterTop - size]);
|
||
}
|
||
return points.push([x, length / 2], points[0]), {
|
||
points: points,
|
||
base: length,
|
||
height: size + x,
|
||
radius: size,
|
||
center: {
|
||
x: x / 2,
|
||
y: length / 2
|
||
}
|
||
};
|
||
}();
|
||
|
||
Mover.prototype.startCurve = function() {
|
||
/**
|
||
* @return {?}
|
||
*/
|
||
function _init() {
|
||
return function(weight) {
|
||
/** @type {number} */
|
||
var column = 1 - weight;
|
||
/** @type {number} */
|
||
var i = column * column;
|
||
/** @type {number} */
|
||
var r = 2 * column * weight;
|
||
/** @type {number} */
|
||
var g = weight * weight;
|
||
/** @type {number} */
|
||
var x = i * self.x + r * area.x + g * other.lx;
|
||
/** @type {number} */
|
||
var y = i * self.y + r * area.y + g * other.ly;
|
||
/** @type {number} */
|
||
var CIRCLE_AREA_TO_SCREEN_REL = Math.atan2(dest[1] - y, dest[0] - x);
|
||
return dest[0] = x, dest[1] = y, "translate(" + [x, y] + ") rotate(" + [180 * CIRCLE_AREA_TO_SCREEN_REL / Math.PI, 0, 0] + ")";
|
||
};
|
||
}
|
||
var other = this.destination;
|
||
this.dx;
|
||
dy = this.dy;
|
||
distance = this.distance;
|
||
/** @type {number} */
|
||
radius = distance / 2 * (Math.random() - 0.5);
|
||
height = trail.height;
|
||
/** @type {number} */
|
||
var y = height / distance;
|
||
var h = height;
|
||
/** @type {number} */
|
||
var duration = 750;
|
||
var self = this;
|
||
/** @type {number} */
|
||
var startAngle = Math.atan2(this.y - other.ly, this.x - other.lx);
|
||
/** @type {number} */
|
||
var angle = startAngle + Math.PI / 2;
|
||
var area = {
|
||
x: (this.x + other.lx) / 2 + radius * Math.cos(angle),
|
||
y: (this.y + other.ly) / 2 + radius * Math.sin(angle)
|
||
};
|
||
/** @type {Array} */
|
||
var dest = [this.x, this.y];
|
||
/** @type {number} */
|
||
var temp2 = duration * y;
|
||
this.cliprect.attr("width", 0).transition().duration(temp2).ease("linear").attr("width", h);
|
||
this.obj.transition().duration(temp2).ease("linear").attr("transform", _init()(y)).each("end", function() {
|
||
y = 1 === y ? 0 : y;
|
||
/** @type {number} */
|
||
_1mpos = 1 - y;
|
||
/**
|
||
* @param {number} x
|
||
* @return {?}
|
||
*/
|
||
var easing = function(x) {
|
||
return x >= 1 ? 1 : x * _1mpos + y;
|
||
};
|
||
self.obj.transition().duration(duration).ease(easing).attrTween("transform", _init).each("end", function() {
|
||
self.cliprect.transition().duration(temp2).ease("linear").attr("width", 0).each("end", function() {
|
||
/** @type {boolean} */
|
||
self.animating = false;
|
||
self.x = other.lx;
|
||
self.y = other.ly;
|
||
self.die();
|
||
});
|
||
});
|
||
});
|
||
},
|
||
|
||
Mover.prototype.start = function() {
|
||
var position = this.destination;
|
||
/** @type {number} */
|
||
var x = position.lx - this.x;
|
||
/** @type {number} */
|
||
var y = position.ly - this.y;
|
||
/** @type {number} */
|
||
var b = Math.sqrt(x * x + y * y);
|
||
var a = trail.height;
|
||
/** @type {string} */
|
||
var arc = "translate(" + [position.lx + this.offset.x, position.ly + this.offset.y] + ") rotate(" + this.svgRotation() + ")";
|
||
if (a > b) {
|
||
/** @type {number} */
|
||
var cos = 1;
|
||
/** @type {number} */
|
||
var key = b;
|
||
/** @type {number} */
|
||
var duration = 50;
|
||
} else {
|
||
/** @type {number} */
|
||
cos = a / b;
|
||
key = a;
|
||
/** @type {number} */
|
||
duration = 750;
|
||
}
|
||
/** @type {Array} */
|
||
var j = [x * cos + this.x, y * cos + this.y];
|
||
var self = this;
|
||
/** @type {number} */
|
||
var complicated = duration * cos;
|
||
this.cliprect.attr("width", 0).transition().duration(complicated).ease("linear").attr("width", key);
|
||
this.obj.transition().duration(complicated).ease("linear").attr("transform", "translate(" + j + ") rotate(" + this.svgRotation() + ")").each("end", function() {
|
||
self.obj.transition().duration(duration).ease("linear").attr("transform", arc).each("end", function() {
|
||
self.cliprect.transition().duration(complicated).ease("linear").attr("width", 0).each("end", function() {
|
||
/** @type {boolean} */
|
||
self.animating = false;
|
||
self.x = position.lx;
|
||
self.y = position.ly;
|
||
self.die();
|
||
});
|
||
});
|
||
});
|
||
},
|
||
Mover.prototype.theta = function(pointer) {
|
||
return 180 * Math.atan2(this.y - pointer.ly, this.x - pointer.lx) / Math.PI;
|
||
},
|
||
Mover.prototype.svgRotation = function() {
|
||
return [this.theta(this.destination), 0, 0];
|
||
},
|
||
Mover.prototype.update = function() {
|
||
this.obj.attr("transform", "translate(" + [this.x, this.y] + ") rotate(" + this.svgRotation() + ")");
|
||
},
|
||
Mover.prototype.setPosition = function(point, opt_arg2) {
|
||
/** @type {Object} */
|
||
this.destination = opt_arg2;
|
||
this.obj.attr("transform", "translate(" + [this.x = point.x, this.y = point.y] + ") rotate(" + this.svgRotation() + ")");
|
||
},
|
||
Mover.prototype.die = function() {
|
||
this.obj.remove();
|
||
this.clipPath.remove();
|
||
this.hit();
|
||
return this.layer.append("circle").classed("animating", true).attr({
|
||
cx: this.x + this.offset.x,
|
||
cy: this.y + this.offset.y,
|
||
fill: "none",
|
||
stroke: this.color,
|
||
"stroke-width": 5,
|
||
r: 1E-6
|
||
}).style({
|
||
opacity: 1
|
||
}).transition().duration(2600).ease("cubic-out").style("opacity", 1E-6).attr("r", 100).remove(), false;
|
||
},
|
||
|
||
Floater.prototype.addOne = function() {}, ipv.ui = function() {
|
||
/**
|
||
* @param {Function} body
|
||
* @return {undefined}
|
||
*/
|
||
function init(body) {
|
||
var path = body.selectAll(".module").data(d3.values(data), function(keyOrObj) {
|
||
return keyOrObj.key;
|
||
});
|
||
var scene = path.enter().append("div").classed("module", true).attr("id", function(keyOrObj) {
|
||
return "ui-datatable-" + keyOrObj.key;
|
||
}).style("width", function($slide) {
|
||
return $slide.width;
|
||
});
|
||
var table = (scene.append("div").classed("title", true).text(function(c) {
|
||
return c.name.toUpperCase();
|
||
}), scene.append("table").classed("table", true));
|
||
var cursor = path.select("table").datum(function(transition) {
|
||
return transition;
|
||
});
|
||
table.append("tr").classed("header", true).selectAll("td").data(function(row) {
|
||
return row.columns;
|
||
}).enter().append("td").attr("class", function(list) {
|
||
return "count" === list.attr || "timestamp" === list.attr ? "number" : "";
|
||
}).style("width", function($slide) {
|
||
return $slide.width;
|
||
}).text(function(result) {
|
||
return result.display;
|
||
});
|
||
cursor.each(function(index) {
|
||
self.datatables[index.key] = d3.select(this);
|
||
});
|
||
self.minibar = path.select(".title").append("div").classed("minibar", true);
|
||
self.minibar.each(function(v) {
|
||
if (!v.viz) {
|
||
this.parentNode.removeChild(this);
|
||
}
|
||
});
|
||
var update = ipv.ui.widgets.clock();
|
||
self.clock = {
|
||
update: update,
|
||
el: body.append("div").datum([]).attr({
|
||
id: "ui-clock",
|
||
"class": "module"
|
||
})
|
||
};
|
||
self.clock.el.call(update);
|
||
self.minimizebutton = body.call(ipv.ui.widgets.minimizebutton);
|
||
}
|
||
var data;
|
||
var self = {
|
||
datatables: {},
|
||
minibar: {}
|
||
};
|
||
var managedListeners = ipv.ui.cellfmt;
|
||
return init.layout = function(size) {
|
||
return arguments.length ? (data = {}, size.forEach(function(element) {
|
||
/** @type {Object} */
|
||
data[element.key] = element;
|
||
}), init) : data;
|
||
}, init.widgets = function(str) {
|
||
/**
|
||
* @param {Array} last
|
||
* @param {?} data
|
||
* @return {?}
|
||
*/
|
||
function process(last, data) {
|
||
if (data = data || self, !last.length) {
|
||
return data;
|
||
}
|
||
var tmp = data[last.shift()];
|
||
return tmp ? (data = tmp, process(last, data)) : data;
|
||
}
|
||
return str && "string" == typeof str ? process(str.split(".")) : self;
|
||
}, init.center = null, init.update = function(obj) {
|
||
var chart = self.minibar.data(obj.datatables, function(statement) {
|
||
return statement.type;
|
||
});
|
||
var node = chart.selectAll(".bar").data(function(messageEvent) {
|
||
return messageEvent.data;
|
||
});
|
||
node.enter().append("div").classed("bar", true).style("width", "3px");
|
||
/** @type {number} */
|
||
var height = 30;
|
||
node.style("height", function(v) {
|
||
return v.parent = this.parentNode.__data__, v.height = ~~(v.count / v.parent.data[0].count * (height - 5)) + 5, v.height + "px";
|
||
}).style("background-color", function(state) {
|
||
return "service" === state.parent.type ? state.color : "#ccc";
|
||
}).style("margin-top", function(line) {
|
||
return height - line.height + "px";
|
||
});
|
||
/** @type {number} */
|
||
var i = 0;
|
||
for (; i < obj.datatables.length; i++) {
|
||
var event = obj.datatables[i];
|
||
var div = self.datatables[event.type].selectAll(".row").data(event.data);
|
||
var args = (div.enter().append("tr").classed("row", true), div.selectAll("td").data(managedListeners[event.type]));
|
||
args.html(String);
|
||
args.enter().append("td").attr("class", function(dataAndEvents, b) {
|
||
return "cell " + this.parentNode.parentNode.firstChild.children[b].className;
|
||
});
|
||
}
|
||
self.clock.el.datum(obj.clock).call(self.clock.update);
|
||
if (!init.center) {
|
||
if (!("events" !== event.type)) {
|
||
if (!(10 !== event.data.length)) {
|
||
init.center = self.clock.update.center();
|
||
self.clock.el.select("#chevron").style("visibility", "visible").attr("transform", "translate(" + [init.center.x, init.center.y] + ")");
|
||
}
|
||
}
|
||
}
|
||
}, init;
|
||
},
|
||
|
||
ipv.ui.widgets = {
|
||
/**
|
||
* @return {?}
|
||
*/
|
||
minibar: function() {
|
||
/**
|
||
* @param {?} vals
|
||
* @return {undefined}
|
||
*/
|
||
function reduce(vals) {
|
||
vals.each(function() {});
|
||
}
|
||
return reduce;
|
||
},
|
||
/**
|
||
* @return {?}
|
||
*/
|
||
clock: function() {
|
||
/**
|
||
* @param {HTMLElement} element
|
||
* @return {?}
|
||
*/
|
||
function init(element) {
|
||
var width = element.clientWidth;
|
||
var olen = element.parentNode.clientHeight;
|
||
/** @type {number} */
|
||
var max = Math.min(width, olen);
|
||
return i !== max ? (i = max, j = i / 3, value = {
|
||
x: i / 2,
|
||
y: i / 1.5
|
||
}, x2 = j / 4, y = x2 / 2, d3.select(element).select("svg").attr("width", i + "px").attr("height", i + "px"), t = {
|
||
x1: 0,
|
||
y1: y,
|
||
x2: x2,
|
||
y2: y
|
||
}, true) : void 0;
|
||
}
|
||
/**
|
||
* @param {?} _
|
||
* @return {undefined}
|
||
*/
|
||
function chart(_) {
|
||
_.each(function(data) {
|
||
if (!p) {
|
||
init(this);
|
||
/** @type {boolean} */
|
||
p = true;
|
||
var groups = d3.select(this).selectAll("svg").data([data]);
|
||
var element = groups.enter().append("svg").append("g");
|
||
element.each(animate);
|
||
layer = groups.select("g");
|
||
}
|
||
if (data.length < 10) {
|
||
if (init(this)) {
|
||
/** @type {Array} */
|
||
data = [];
|
||
}
|
||
}
|
||
/** @type {number} */
|
||
var now = Date.now();
|
||
var div = layer.selectAll("line").data(data.filter(function(b) {
|
||
return now - b.meta.created < updateTimer;
|
||
}), function(dataAndEvents) {
|
||
return dataAndEvents.$loki;
|
||
});
|
||
div.style("opacity", function(b) {
|
||
return 1 - (now - b.meta.created) / millisecondsPerSecond;
|
||
});
|
||
div.enter().append("line").classed("ticker-line", true).attr(t).style("stroke", function(entry) {
|
||
return entry.service.color;
|
||
}).attr("transform", function() {
|
||
/** @type {number} */
|
||
var theta2 = -rot * Math.PI / 180;
|
||
var h = value.x + j * Math.cos(theta2);
|
||
var dy1 = value.y + j * Math.sin(theta2);
|
||
return "translate(" + [h - y, dy1 - y] + ") rotate(" + [-rot, y, y] + ")";
|
||
});
|
||
div.exit().remove();
|
||
});
|
||
}
|
||
/**
|
||
* @return {?}
|
||
*/
|
||
function start() {
|
||
return function(dataAndEvents) {
|
||
return rot = 360 * dataAndEvents, "rotate(" + [rot, value.x, value.y] + ")";
|
||
};
|
||
}
|
||
/**
|
||
* @return {undefined}
|
||
*/
|
||
function animate() {
|
||
d3.select(this).interrupt().transition();
|
||
d3.select(this).attr("transform", "rotate(0," + [value.x, value.y] + ")").transition().duration(duration).ease("linear").attrTween("transform", start).each("end", animate);
|
||
}
|
||
var rot;
|
||
var i;
|
||
var j;
|
||
var value;
|
||
var x2;
|
||
var y;
|
||
var layer;
|
||
var t;
|
||
/** @type {number} */
|
||
var duration = 3E4;
|
||
/** @type {number} */
|
||
var updateTimer = duration - 0.1 * duration;
|
||
/** @type {number} */
|
||
var millisecondsPerSecond = duration + 0.01 * duration;
|
||
/** @type {boolean} */
|
||
var p = false;
|
||
return chart.center = function(x) {
|
||
return arguments.length ? (value = x, chart) : value;
|
||
}, chart;
|
||
},
|
||
/**
|
||
* @return {?}
|
||
*/
|
||
minimizebutton: function() {
|
||
/** @type {boolean} */
|
||
var perm = false;
|
||
/** @type {Array} */
|
||
var items = ["+", "_"];
|
||
var c = this.append("div").classed("minimize-button minimize", true).text("_");
|
||
var event = c.style("height");
|
||
return c.on("mousedown", function() {
|
||
c.text(items[+perm]);
|
||
var type = perm ? "" : event;
|
||
d3.select(this.parentNode).transition().duration(1E3).style("height", type);
|
||
/** @type {boolean} */
|
||
perm = !perm;
|
||
}), c;
|
||
}
|
||
}, ipv.ui.cellfmt = {
|
||
/**
|
||
* @param {Object} response
|
||
* @return {?}
|
||
*/
|
||
source: function(response) {
|
||
return [response.count, response.display];
|
||
},
|
||
/**
|
||
* @param {Object} result
|
||
* @return {?}
|
||
*/
|
||
target: function(result) {
|
||
return [result.count, result.display];
|
||
},
|
||
/**
|
||
* @param {Object} defaults
|
||
* @return {?}
|
||
*/
|
||
service: function(defaults) {
|
||
return [defaults.count, defaults.port, defaults.display];
|
||
},
|
||
/**
|
||
* @param {Object} entry
|
||
* @return {?}
|
||
*/
|
||
events: function(entry) {
|
||
var value = entry.service;
|
||
return [entry.timestamp, entry.org, entry.ip, entry.source, entry.target, '<span style="color: ' + value.color + '">' + value.service + "</span>", value.port];
|
||
}
|
||
},
|
||
|
||
// 自运行
|
||
function() {
|
||
/**
|
||
* @param {Array} id
|
||
* @return {?}
|
||
*/
|
||
function load(id) {
|
||
/** @type {boolean} */
|
||
var b = false;
|
||
return id.forEach(function(jQuery) {
|
||
var count = jQuery.data[0].count;
|
||
if (count > event[jQuery.type].domain()[1]) {
|
||
event[jQuery.type].domain([1, count]);
|
||
/** @type {boolean} */
|
||
b = true;
|
||
}
|
||
}), b;
|
||
}
|
||
|
||
/**
|
||
* @param {?} query
|
||
* @return {?}
|
||
*/
|
||
function init(query) {
|
||
var rows = col.find(query);
|
||
var data = {
|
||
meta: {
|
||
totalLinks: rows.length,
|
||
maxFreq: 0
|
||
},
|
||
data: {}
|
||
};
|
||
return rows.forEach(function(inEvent) {
|
||
var d = inEvent.sourceObj;
|
||
var bounds = inEvent.targetObj;
|
||
var name = d.key + bounds.key;
|
||
var self = data.data[name] || (data.data[name] = {
|
||
count: 0,
|
||
max: {
|
||
port: "unknown",
|
||
count: 0
|
||
},
|
||
source: [d.lx, d.ly],
|
||
target: [bounds.lx, bounds.ly],
|
||
ports: {}
|
||
});
|
||
if (++self.count > data.meta.maxFreq) {
|
||
data.meta.maxFreq = self.count;
|
||
}
|
||
var options = inEvent.service;
|
||
port = options.port;
|
||
var count = self.ports[port] = (self.ports[port] || 0) + 1;
|
||
|
||
if (count > self.max.count) {
|
||
self.max.color = options.color;
|
||
self.max.port = port;
|
||
self.max.count = count;
|
||
}
|
||
}), data.data = d3.values(data.data), data;
|
||
}
|
||
/**
|
||
* @param {Object} msg
|
||
* @return {undefined}
|
||
*/
|
||
function enter(msg) {
|
||
var linkItems = chart.selectAll(".links").data(msg.data);
|
||
linkItems.enter().append("path").classed("links", true);
|
||
linkItems.attr("d", function(d) {
|
||
return "M" + [d.source] + "L" + [d.target];
|
||
}).style("stroke", function(element) {
|
||
return element.max.color;
|
||
}).style("stroke-width", function(collection) {
|
||
return Math.max(1, collection.count / msg.meta.maxFreq * 5);
|
||
}).style("opacity", function(collection) {
|
||
return collection.count / msg.meta.totalLinks + 0.5;
|
||
});
|
||
linkItems.exit().remove();
|
||
}
|
||
/**
|
||
* @return {undefined}
|
||
*/
|
||
function transition() {
|
||
var a = chart.selectAll(".links").remove();
|
||
/** @type {null} */
|
||
a = null;
|
||
}
|
||
/**
|
||
* @param {number} backoff
|
||
* @return {undefined}
|
||
*/
|
||
function ping(backoff) {
|
||
console.log("expire");
|
||
/** @type {number} */
|
||
var chipsFor = Date.now();
|
||
/** @type {number} */
|
||
var viewPortRight = chipsFor - backoff;
|
||
col.removeWhere(function(req) {
|
||
/** @type {boolean} */
|
||
var enoughRoomOnRight = req.meta.created <= viewPortRight;
|
||
if (enoughRoomOnRight) {
|
||
var node = req.sourceObj;
|
||
var p = req.targetObj;
|
||
node.count--;
|
||
p.count--;
|
||
node.countryObj.count--;
|
||
p.countryObj.count--;
|
||
req.serviceObj.count--;
|
||
}
|
||
return enoughRoomOnRight;
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 开始渲染页面
|
||
* @param {boolean} delegate 是否异常
|
||
* @param {Object} json_config json_config 配置项
|
||
* @param {Array} nmap_services 协议端口映射表
|
||
* @param {?} country_codes 国家(地区)简写与全称映射表
|
||
* @param {Object} layout 页面布局配置
|
||
* @param {?} dotCanvas particle-inverse.png图片对象
|
||
* @return {undefined}
|
||
*/
|
||
function show(delegate, json_config, nmap_services, country_codes, layout, dotCanvas) {
|
||
/**
|
||
* @param {Element} node
|
||
* @return {undefined}
|
||
*/
|
||
function init(node) {
|
||
/** @type {(Element|null)} */
|
||
var frag = document.querySelector("#ui-clock svg");
|
||
frag.appendChild(node);
|
||
var docFrag = d3.select("#chevron-container").append("svg").node();
|
||
d3.select("#svg-toggle-info").on("mousedown", function() {
|
||
d3.select("#infobox").transition().duration(1E3).style({
|
||
display: "block",
|
||
left: "0%"
|
||
});
|
||
});
|
||
d3.select("#infobox .close").on("mousedown", function() {
|
||
d3.select("#infobox").transition().duration(1E3).style({
|
||
left: "100%"
|
||
});
|
||
});
|
||
d3.select("#svg-zoom-in").on("mousedown", function() {
|
||
map.zoomIn();
|
||
});
|
||
d3.select("#svg-zoom-out").on("mousedown", function() {
|
||
map.zoomOut();
|
||
});
|
||
d3.select("#svg-toggle-play").on("mousedown", function() {
|
||
if (ipv.stream.paused) {
|
||
ipv.stream.play();
|
||
} else {
|
||
ipv.stream.pause();
|
||
}
|
||
var status = ipv.stream.paused;
|
||
d3.select(this.parentNode).select("text").style("font-size", status ? "12px" : "12px").html(status ? "▶" : "▐");
|
||
});
|
||
/** @type {boolean} */
|
||
var perm = false;
|
||
d3.select(".minimize-button").on("mousedown.toggle", function() {
|
||
if (perm) {
|
||
node.setAttribute("transform", "translate(" + [o.center.x, o.center.y] + ")");
|
||
frag.appendChild(node);
|
||
} else {
|
||
node.setAttribute("transform", "translate(40, 40)");
|
||
docFrag.appendChild(node);
|
||
}
|
||
/** @type {boolean} */
|
||
perm = !perm;
|
||
});
|
||
}
|
||
if (delegate) {
|
||
throw delegate;
|
||
}
|
||
|
||
if (_dotCanvas = dotCanvas, nmap_services.forEach(function(s) {
|
||
/** @type {number} */
|
||
s.count = 0;
|
||
/** @type {number} */
|
||
s.port = +s.port;
|
||
/** @type {string} */
|
||
s.type = "service";
|
||
/** @type {string} */
|
||
s.color = "hsl(" + +s.port % 360 + ", 100%, 70%)";
|
||
/** @type {string} */
|
||
console.log(s.port, s.service, s.color);
|
||
s.display = '<span style="color: ' + s.color + '">◯</span> ' + s.service;
|
||
self.insert(s);
|
||
}), result = country_codes, draw(json_config.map), !args.embed) {
|
||
if (o = ipv.ui().layout(layout), ifn = d3.select("body").append("div").attr("id", "ui").call(o), document.getElementById("ui").appendChild(document.getElementById("infobox")), isInline) {
|
||
var cb = d3.select(document.getElementById("chevronHiddenDiv")).select("g").node();
|
||
init(cb);
|
||
} else {
|
||
d3.select("#controls #logo").attr("src", json_config.ui.logo);
|
||
d3.xml("assets/chevron.svg", "image/svg+xml", function(data) {
|
||
var cb = d3.select(data.documentElement).select("g").node();
|
||
init(cb);
|
||
});
|
||
}
|
||
}
|
||
copied = ipv.stream.socket(json_config.stream, update);
|
||
}
|
||
/**
|
||
* @param {Element} params
|
||
* @return {undefined}
|
||
*/
|
||
function draw(params) {
|
||
/**
|
||
* @return {undefined}
|
||
*/
|
||
function drawLine() {
|
||
transition();
|
||
t = map.getZoom();
|
||
}
|
||
|
||
/**
|
||
* 更新页面内容
|
||
* @return {undefined}
|
||
*/
|
||
function update() {
|
||
var codeSegments = store.data;
|
||
/** @type {number} */
|
||
var i = 0;
|
||
for (; i < codeSegments.length; i++) {
|
||
var o = codeSegments[i];
|
||
var p = map.latLngToContainerPoint(o.latLng);
|
||
newLayerPos = map.latLngToLayerPoint(o.latLng);
|
||
o.cx = p.x;
|
||
o.cy = p.y;
|
||
o.lx = newLayerPos.x;
|
||
o.ly = newLayerPos.y;
|
||
}
|
||
/** @type {Array} */
|
||
var minPage = [2, map.getScaleZoom(map.getZoom()) * map.getZoom() + 2];
|
||
["source", "target", "service"].forEach(function(target) {
|
||
event[target].range(minPage);
|
||
});
|
||
that.redraw();
|
||
|
||
if (!y) {
|
||
chart.selectAll(".animating").style("visibility", "hidden").interrupt().transition().remove();
|
||
}
|
||
/** @type {boolean} */
|
||
y = false;
|
||
}
|
||
var vudata = {
|
||
tiles: {
|
||
toner: "http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png",
|
||
watercolor: "http://{s}.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg",
|
||
mars: "https://{s}.tiles.mapbox.com/v3/herwig.map-tly29w1z/{z}/{x}/{y}.png",
|
||
dm: "http://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png",
|
||
positron: "http://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png"
|
||
}
|
||
};
|
||
params.tileUrl = args.tiles ? vudata.tiles[args.tiles] : params.tileUrl ? params.tileUrl : null;
|
||
if (data) {
|
||
map = ipv.map(params);
|
||
L.geoJson(topojson.feature(data, data.objects.countries).features, {
|
||
style: {
|
||
fillColor: "#000",
|
||
weight: 1,
|
||
color: "#4bffff"
|
||
}
|
||
}).addTo(map);
|
||
} else {
|
||
map = ipv.map(params);
|
||
map.addLayer(params.tileUrl ? new L.TileLayer(params.tileUrl, {
|
||
noWrap: true
|
||
}) : new L.TileLayer("norse-basemap-v1_1/{z}/{x}/{y}.png", {
|
||
noWrap: true
|
||
}));
|
||
}
|
||
/**
|
||
* @param {?} rows
|
||
* @param {Object} context
|
||
* @return {undefined}
|
||
*/
|
||
render = function(rows, context) {
|
||
var ctx = context.context;
|
||
ctx.clearRect(0, 0, context.canvas.width, context.canvas.height);
|
||
/** @type {number} */
|
||
ctx.globalAlpha = 0.5;
|
||
/** @type {string} */
|
||
ctx.globalCompositeOperation = "lighter";
|
||
[me.data(), row.data()].forEach(function(ca, isToday) {
|
||
/** @type {string} */
|
||
ctx.fillStyle = isToday ? "white" : "hsl(0, 100%, 70%)";
|
||
ctx.beginPath();
|
||
/** @type {number} */
|
||
var i = 0;
|
||
var l = ca.length;
|
||
for (; l > i; i++) {
|
||
var c = ca[i];
|
||
if (context.bounds.contains(c.latLng)) {
|
||
/** @type {number} */
|
||
var x = 0 | c.cx;
|
||
/** @type {number} */
|
||
var y = 0 | c.cy;
|
||
ctx.moveTo(x, y);
|
||
ctx.arc(x, y, c.displayRadius = event[c.type](c.count) / 16, 0, TWO_PI);
|
||
}
|
||
}
|
||
ctx.fill();
|
||
ctx.closePath();
|
||
});
|
||
currentSet = d3.geom.quadtree().x(ipv_helpers.return_cx).y(ipv_helpers.return_cy)(store.data.slice());
|
||
};
|
||
that = L.canvasOverlay().drawing(render).addTo(map);
|
||
d3.select(that._canvas).classed("anchor-layer", true);
|
||
/** @type {Element} */
|
||
var canvas = document.createElement("canvas");
|
||
var _ctx = canvas.getContext("2d");
|
||
/** @type {number} */
|
||
canvas.width = canvas.height = 16;
|
||
/**
|
||
* @return {undefined}
|
||
*/
|
||
showbuffer.showbuffer = function() {
|
||
window.open(canvas.toDataURL("image/jpeg", 1));
|
||
};
|
||
state = L.canvasOverlay().drawing(function(dataAndEvents, jaws) {
|
||
jaws.context.clearRect(0, 0, jaws.canvas.width, jaws.canvas.height);
|
||
}).addTo(map);
|
||
var context = state._context;
|
||
/** @type {string} */
|
||
context.globalCompositeOperation = "lighter";
|
||
/** @type {number} */
|
||
var tileSize = 24;
|
||
/** @type {number} */
|
||
var container_border_width = tileSize / 2;
|
||
/** @type {null} */
|
||
var lastColor = null;
|
||
/**
|
||
* @return {undefined}
|
||
*/
|
||
clear = function() {
|
||
if (_dotCanvas) {
|
||
var color = this.color;
|
||
if (color !== lastColor) {
|
||
_ctx.clearRect(0, 0, tileSize, tileSize);
|
||
_ctx.save();
|
||
_ctx.drawImage(_dotCanvas, 0, 0, tileSize, tileSize);
|
||
_ctx.fillStyle = color;
|
||
/** @type {string} */
|
||
_ctx.globalCompositeOperation = "source-atop";
|
||
_ctx.fillRect(0, 0, tileSize, tileSize);
|
||
_ctx.restore();
|
||
lastColor = color;
|
||
}
|
||
var box = this.destination;
|
||
var height = box.displayRadius;
|
||
/** @type {number} */
|
||
var scrollTop = 2 * (Math.random() - 0.5) * height - container_border_width;
|
||
/** @type {number} */
|
||
var scrollLeft = 2 * (Math.random() - 0.5) * height - container_border_width;
|
||
context.drawImage(canvas, box.cx + scrollTop | 0, box.cy + scrollLeft | 0);
|
||
if (Math.random() > 0.7) {
|
||
/** @type {string} */
|
||
context.globalCompositeOperation = "destination-out";
|
||
/** @type {string} */
|
||
context.fillStyle = "rgba(255, 255, 255, 0.1)";
|
||
context.fillRect(0, 0, context.canvas.width, context.canvas.height);
|
||
/** @type {string} */
|
||
context.globalCompositeOperation = "lighter";
|
||
}
|
||
}
|
||
};
|
||
start(that._canvas);
|
||
svgLayer = new SVGOverlay(params.options);
|
||
map.addLayer(svgLayer);
|
||
chart = svgLayer.el;
|
||
/** @type {boolean} */
|
||
var y = true;
|
||
map.on("viewreset", update);
|
||
update();
|
||
map.on("zoomstart", drawLine);
|
||
map.on("moveend", update);
|
||
}
|
||
|
||
/**
|
||
* @return {undefined}
|
||
*/
|
||
function start() {
|
||
var row = {
|
||
key: false
|
||
};
|
||
document.getElementById("map").addEventListener("mousemove", function(touch) {
|
||
var self;
|
||
/** @type {number} */
|
||
var x = touch.pageX;
|
||
/** @type {number} */
|
||
var y = touch.pageY;
|
||
if (currentSet.visit(function(t, minlength, y3, maxX, maxY) {
|
||
if (self) {
|
||
return true;
|
||
}
|
||
if (x >= minlength && (maxX >= x && (y >= y3 && maxY >= y))) {
|
||
var p = t.point;
|
||
if (p) {
|
||
/** @type {number} */
|
||
var z0 = x - p.cx;
|
||
/** @type {number} */
|
||
var z1 = y - p.cy;
|
||
/** @type {number} */
|
||
var R = Math.sqrt(z0 * z0 + z1 * z1);
|
||
if (R <= p.r) {
|
||
return self = p, true;
|
||
}
|
||
}
|
||
}
|
||
}), self && self.key !== row.key) {
|
||
var params = {};
|
||
/** @type {string} */
|
||
var key = self.type + "Key";
|
||
params[key] = self.key;
|
||
enter(init(params));
|
||
} else {
|
||
transition();
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* 更新网页
|
||
* @param {Object} params
|
||
* @return {undefined}
|
||
*/
|
||
function update(params) {
|
||
if(!!ipv.stream.paused) return;
|
||
if (params = JSON.parse(params.data), "O1" !== params.source.country && "O1" !== params.destination.country2) {
|
||
console.log(params);
|
||
var data = {
|
||
source: {
|
||
key: (lat = params.source.latitude) + "_" + (lng = params.source.longitude),
|
||
latLng: [+lat, +lng],
|
||
country: params.cn,
|
||
// TODO: CITY
|
||
locString: (params.cn ? params.cn + ", " : "") + params.cn
|
||
},
|
||
target: {
|
||
key: (lat = params.destination.latitude) + "_" + (lng = params.destination.longitude),
|
||
latLng: [+lat, +lng],
|
||
country: params.destination.country,
|
||
locString: (params.destination.city ? params.destination.city + ", " : "") + params.destination.country
|
||
}
|
||
};
|
||
console.log(data)
|
||
/** @type {number} */
|
||
var _port = 21;
|
||
/** @type {string} */
|
||
var lc = "hsl(" + +_port % 360 + ", 100%, 70%)";
|
||
var values = self.findOne({
|
||
port: _port
|
||
}) || self.insert({
|
||
type: "service",
|
||
port: _port,
|
||
color: lc,
|
||
service: "unknown",
|
||
count: 0,
|
||
display: '<span style="color: ' + lc + '">◯</span> unknown'
|
||
});
|
||
++values.count;
|
||
self.update(values);
|
||
["target", "source"].forEach(function(i, dataAndEvents) {
|
||
var node;
|
||
var event = data[i];
|
||
if (!(node = store.findOne({
|
||
key: event.key,
|
||
type: i
|
||
}))) {
|
||
var pt = map.latLngToContainerPoint(event.latLng);
|
||
var coords = map.latLngToLayerPoint(event.latLng);
|
||
node = store.insert({
|
||
key: event.key,
|
||
cx: pt.x,
|
||
cy: pt.y,
|
||
lx: coords.x,
|
||
ly: coords.y,
|
||
latLng: event.latLng,
|
||
location: event.locString,
|
||
country: event.country,
|
||
type: i,
|
||
count: 0,
|
||
r: 20
|
||
});
|
||
/** @type {Array} */
|
||
v[params.key + params.type] = [];
|
||
}
|
||
data[i].document = node;
|
||
++node.count;
|
||
var results;
|
||
var country = event.country;
|
||
if (!(results = query.findOne({
|
||
$and: [{
|
||
type: i
|
||
}, {
|
||
country: country
|
||
}]
|
||
}))) {
|
||
/** @type {string} */
|
||
var type = "<";
|
||
type += 'img class="flag" src="img/flags/' + country + '.png"> ' + result[country];
|
||
if (isInline) {
|
||
type = result[country];
|
||
}
|
||
results = query.insert({
|
||
type: i,
|
||
country: country,
|
||
countryName: result[country],
|
||
display: type,
|
||
count: 0
|
||
});
|
||
}
|
||
++results.count;
|
||
node.countryObj = results;
|
||
query.update(results);
|
||
});
|
||
var bounds = data.source.document;
|
||
var i = data.target.document;
|
||
var created = moment().format("DD.MM.YYYY HH:mm:ss");
|
||
var event = {
|
||
timestamp: created,
|
||
org: params.org,
|
||
ip: params.md5,
|
||
source: data.source.locString,
|
||
target: data.target.locString,
|
||
sourceKey: data.source.key,
|
||
targetKey: data.target.key,
|
||
sourceCountry: params.country,
|
||
targetCountry: params.country2,
|
||
sourceObj: bounds,
|
||
targetObj: i,
|
||
serviceObj: values,
|
||
service: values,
|
||
type: "events"
|
||
};
|
||
col.insert(event);
|
||
/** @type {({x: number, y: number})} */
|
||
var pos = params.zerg ? {
|
||
x: 20 * (Math.random() - 0.5),
|
||
y: 20 * (Math.random() - 0.5)
|
||
} : {
|
||
x: 0,
|
||
y: 0
|
||
};
|
||
chart.append("circle").classed("animating", true).attr({
|
||
cx: bounds.lx + pos.x,
|
||
cy: bounds.ly + pos.y,
|
||
fill: "none",
|
||
stroke: values.color,
|
||
"stroke-width": 5,
|
||
r: 1E-6
|
||
}).style({
|
||
opacity: 1
|
||
}).transition().duration(4E3).ease("cubic-out").style("opacity", 1E-6).attr("r", 80).remove();
|
||
|
||
/** @type {Array} */
|
||
var net = (new Mover({
|
||
zerg: params.zerg,
|
||
created: created,
|
||
x: bounds.lx,
|
||
y: bounds.ly,
|
||
destination: i,
|
||
dk: i.key,
|
||
targetIdx: i.$loki,
|
||
latLng: bounds.latLng,
|
||
lastLatLng: bounds.latLng,
|
||
fixed: false,
|
||
port: _port,
|
||
offset: pos,
|
||
onMoverHit: clear
|
||
}, svgLayer), [{
|
||
type: "source",
|
||
data: service.data().slice(0, 10)
|
||
}, {
|
||
type: "service",
|
||
data: socket.data().slice(0, 10)
|
||
}, {
|
||
type: "target",
|
||
data: options.data().slice(0, 10)
|
||
}]);
|
||
if (!params.zerg) {
|
||
if (load(net)) {
|
||
that.redraw();
|
||
}
|
||
}
|
||
if (!args.embed) {
|
||
net.push({
|
||
type: "events",
|
||
data: col.data.slice(-10)
|
||
});
|
||
o.update({
|
||
datatables: net,
|
||
clock: col.data.slice()
|
||
});
|
||
}
|
||
}
|
||
}
|
||
var showbuffer = {};
|
||
var args = ipv.hash.parse();
|
||
if (args.pew) {
|
||
d3.select("body").append("audio").attr({
|
||
src: "assets/pew.mp3",
|
||
preload: "auto"
|
||
}).text("");
|
||
document.getElementsByTagName("audio")[0];
|
||
}
|
||
var copied;
|
||
var map;
|
||
var chart;
|
||
var data;
|
||
var that;
|
||
var render;
|
||
var state;
|
||
var clear;
|
||
var t;
|
||
var currentSet;
|
||
var v = {};
|
||
var event = {
|
||
counts: {
|
||
source: 0,
|
||
target: 0,
|
||
service: 0
|
||
},
|
||
source: d3.scale.sqrt().domain([0, 1]).range([2, 16]),
|
||
target: d3.scale.sqrt().domain([0, 1]).range([2, 16]),
|
||
service: d3.scale.sqrt().domain([0, 1]).range([2, 16])
|
||
};
|
||
var $ = new loki("attacks");
|
||
var col = $.addCollection("timeline", {
|
||
indices: ["source", "target", "service"]
|
||
});
|
||
var store = $.addCollection("anchors", {
|
||
indices: ["key", "country"]
|
||
});
|
||
var self = $.addCollection("services", {
|
||
indices: ["port"]
|
||
});
|
||
var query = $.addCollection("countries", {
|
||
indices: ["country", "type"]
|
||
});
|
||
var service = query.addDynamicView("source_countries");
|
||
service.applyFind({
|
||
type: "source"
|
||
});
|
||
service.applySort(ipv_helpers.sort_descCountAscCountry);
|
||
var options = query.addDynamicView("target_countries");
|
||
options.applyFind({
|
||
type: "target"
|
||
});
|
||
options.applySort(ipv_helpers.sort_descCountAscCountry);
|
||
var socket = self.addDynamicView("sorted_services");
|
||
socket.applyFind({
|
||
count: {
|
||
$gt: 0
|
||
}
|
||
});
|
||
socket.applySort(ipv_helpers.sort_descCountAscService);
|
||
var me = store.addDynamicView("anchor_sources");
|
||
me.applyFind({
|
||
type: "source"
|
||
});
|
||
me.applySimpleSort("count", true);
|
||
var row = store.addDynamicView("anchor_targets");
|
||
row.applyFind({
|
||
type: "target"
|
||
});
|
||
row.applySimpleSort("count", true);
|
||
/** @type {number} */
|
||
var backoff = 48E4;
|
||
setTimeout(function() {
|
||
setInterval(function() {
|
||
ping(backoff);
|
||
}, 6E4);
|
||
}, backoff);
|
||
var result;
|
||
var o;
|
||
var ifn;
|
||
var _dotCanvas;
|
||
d3.select("#preload");
|
||
|
||
// 判断是否页面内联设置
|
||
if (isInline) {
|
||
document.getElementById("particleHiddenDiv").innerHTML += '<img src="assets/particle-inverse.png" id="particleHidden" style="visibility:hidden">';
|
||
show(false, json_config, nmap_services_1500, country_codes, json_layout, document.getElementById("particleHidden"));
|
||
} else {
|
||
queue().defer(d3.json, "config.json").defer(d3.csv, "data/nmap-services-1500.csv").defer(d3.json, "data/country_codes.json").defer(d3.json, "layout.json").defer(function(path, pCallback) {
|
||
/** @type {Image} */
|
||
var image = new Image(0, 0);
|
||
image.onload = function() {
|
||
pCallback(null, this);
|
||
};
|
||
image.onerror = function() {
|
||
pCallback("error loading particle image");
|
||
};
|
||
image.src = path;
|
||
}, "assets/particle-inverse.png").await(show);
|
||
}
|
||
}();
|