koishi-plugin-tmp-bot 1.7.1 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -97,7 +97,7 @@ module.exports = async (ctx, cfg, session, tmpId) => {
97
97
  return '渲染异常,请重试'
98
98
  } finally {
99
99
  if (page) {
100
- page.close()
100
+ await page.close()
101
101
  }
102
102
  }
103
103
 
@@ -0,0 +1,16 @@
1
+ const tmpTrafficMap = require("./tmpTrafficMap");
2
+ const tmpTrafficText = require("./tmpTrafficText");
3
+
4
+ /**
5
+ * 查询路况
6
+ */
7
+ module.exports = async (ctx, cfg, serverName) => {
8
+ switch (cfg.tmpTrafficType) {
9
+ case 1:
10
+ return await tmpTrafficText(ctx, cfg, serverName)
11
+ case 2:
12
+ return await tmpTrafficMap(ctx, cfg, serverName)
13
+ default:
14
+ return '指令配置错误'
15
+ }
16
+ }
@@ -0,0 +1,116 @@
1
+ const truckyAppApi = require('../../api/truckyAppApi')
2
+ const truckersMpMapApi = require('../../api/truckersMpMapApi')
3
+ const baiduTranslate = require('../../util/baiduTranslate')
4
+ const {resolve} = require("path");
5
+ const common = require("../../util/common");
6
+ const {segment} = require("koishi");
7
+
8
+ /**
9
+ * 服务器别名
10
+ */
11
+ const serverAlias = {
12
+ 's1': {
13
+ name: 'sim1',
14
+ mapType: 'ets',
15
+ serverId: 2,
16
+ bounds: [[-94189, 93775], [79264, -78999]]
17
+ },
18
+ 's2': {
19
+ name: 'sim2',
20
+ mapType: 'ets',
21
+ serverId: 41,
22
+ bounds: [[-94189, 93775], [79264, -78999]]
23
+ },
24
+ 'p': {
25
+ name: 'eupromods1',
26
+ mapType: 'promods',
27
+ serverId: 50,
28
+ bounds: [[-96355, 16381], [205581, -70750]]
29
+ },
30
+ 'a': {
31
+ name: 'arc1',
32
+ mapType: 'ets',
33
+ serverId: 7,
34
+ bounds: [[-94189, 93775], [79264, -78999]]
35
+ }
36
+ }
37
+
38
+ /**
39
+ * 路况程度转中文
40
+ */
41
+ const severityToZh = {
42
+ 'Fluid': '🟢畅通',
43
+ 'Moderate': '🟠正常',
44
+ 'Congested': '🔴缓慢',
45
+ 'Heavy': '🟣拥堵'
46
+ }
47
+
48
+ /**
49
+ * 位置类型转中文
50
+ */
51
+ const typeToZh = {
52
+ 'City': '城市',
53
+ 'Road': '公路',
54
+ 'Intersection': '十字路口'
55
+ }
56
+
57
+ /**
58
+ * 查询路况
59
+ */
60
+ module.exports = async (ctx, cfg, serverName) => {
61
+ if (!ctx.puppeteer) {
62
+ return '未启用 puppeteer 服务'
63
+ }
64
+
65
+ // 根据别名获取服务器信息
66
+ let serverInfo = serverAlias[serverName]
67
+ if (!serverInfo) {
68
+ return '请输入正确的服务器名称 (s1, s2, p, a)'
69
+ }
70
+
71
+ // 查询路况信息
72
+ let trafficData = await truckyAppApi.trafficTop(ctx.http, serverInfo.name)
73
+ if (trafficData.error) {
74
+ return '查询路况信息失败'
75
+ }
76
+
77
+ // 查询地图玩家数据
78
+ let mapData = await truckersMpMapApi.area(ctx.http, serverInfo.serverId, serverInfo.bounds[0][0], serverInfo.bounds[0][1], serverInfo.bounds[1][0], serverInfo.bounds[1][1])
79
+
80
+ // 构建路况数据
81
+ let data = {
82
+ mapType: serverInfo.mapType,
83
+ trafficList: [],
84
+ playerCoordinateList: mapData.error && mapData.data ? [] : mapData.data.map(item => [item.X, item.Y])
85
+ }
86
+ for (const traffic of trafficData.data) {
87
+ data.trafficList.push({
88
+ country: await baiduTranslate(ctx, cfg, traffic.country),
89
+ province: await baiduTranslate(ctx, cfg, traffic.name.substring(0, traffic.name.lastIndexOf('(') - 1)),
90
+ playerCount: traffic.players,
91
+ severity: severityToZh[traffic.newSeverity] || traffic.color
92
+ })
93
+ }
94
+
95
+ let page
96
+ try {
97
+ page = await ctx.puppeteer.page()
98
+ await page.setViewport({ width: 1000, height: 1000 })
99
+ await page.goto(`file:///${resolve(__dirname, '../../resource/traffic.html')}`)
100
+ await page.evaluate(`setData(${JSON.stringify(data)})`)
101
+ await common.sleep(100)
102
+ await page.waitForNetworkIdle()
103
+ const element = await page.$("#container");
104
+ return (
105
+ segment.image(await element.screenshot({
106
+ encoding: "binary"
107
+ }), "image/jpg")
108
+ )
109
+ } catch {
110
+ return '渲染异常,请重试'
111
+ } finally {
112
+ if (page) {
113
+ await page.close()
114
+ }
115
+ }
116
+ }
@@ -1,5 +1,5 @@
1
- const truckyAppApi = require('../api/truckyAppApi')
2
- const baiduTranslate = require('../util/baiduTranslate')
1
+ const truckyAppApi = require('../../api/truckyAppApi')
2
+ const baiduTranslate = require('../../util/baiduTranslate')
3
3
 
4
4
  /**
5
5
  * 服务器别名
package/lib/index.js CHANGED
@@ -6,7 +6,7 @@ const model = require('./database/model');
6
6
  const tmpQuery = require('./command/tmpQuery');
7
7
  const tmpServer = require('./command/tmpServer');
8
8
  const tmpBind = require('./command/tmpBind');
9
- const tmpTraffic = require('./command/tmpTraffic');
9
+ const tmpTraffic = require('./command/tmpTraffic/tmpTraffic');
10
10
  const tmpPosition = require('./command/tmpPosition');
11
11
  const likeMe = require('./command/likeMe');
12
12
  exports.name = 'tmp-bot';
@@ -14,12 +14,20 @@ exports.inject = {
14
14
  required: ['database'],
15
15
  optional: ['puppeteer']
16
16
  };
17
- exports.Config = koishi_1.Schema.object({
18
- baiduTranslateEnable: koishi_1.Schema.boolean().default(false).description('启用百度翻译'),
19
- baiduTranslateAppId: koishi_1.Schema.string().description('百度翻译APP ID'),
20
- baiduTranslateKey: koishi_1.Schema.string().description('百度翻译秘钥'),
21
- baiduTranslateCacheEnable: koishi_1.Schema.boolean().default(false).description('启用百度翻译缓存')
22
- });
17
+ exports.Config = koishi_1.Schema.intersect([
18
+ koishi_1.Schema.object({
19
+ baiduTranslateEnable: koishi_1.Schema.boolean().default(false).description('启用百度翻译'),
20
+ baiduTranslateAppId: koishi_1.Schema.string().description('百度翻译APP ID'),
21
+ baiduTranslateKey: koishi_1.Schema.string().description('百度翻译秘钥'),
22
+ baiduTranslateCacheEnable: koishi_1.Schema.boolean().default(false).description('启用百度翻译缓存')
23
+ }).description('基本配置'),
24
+ koishi_1.Schema.object({
25
+ tmpTrafficType: koishi_1.Schema.union([
26
+ koishi_1.Schema.const(1).description('文字'),
27
+ koishi_1.Schema.const(2).description('热力图')
28
+ ]).default(1).description('路况信息展示方式'),
29
+ }).description('指令配置'),
30
+ ]);
23
31
  function apply(ctx, cfg) {
24
32
  // 初始化数据表
25
33
  model(ctx);
@@ -0,0 +1,9 @@
1
+ /*
2
+ * heatmap.js v2.0.2 | JavaScript Heatmap Library
3
+ *
4
+ * Copyright 2008-2016 Patrick Wied <heatmapjs@patrick-wied.at> - All rights reserved.
5
+ * Dual licensed under MIT and Beerware license
6
+ *
7
+ * :: 2016-02-04 21:25
8
+ */
9
+ (function (a, b, c) { if (typeof module !== "undefined" && module.exports) { module.exports = c() } else if (typeof define === "function" && define.amd) { define(c) } else { b[a] = c() } })("h337", this, function () { var a = { defaultRadius: 40, defaultRenderer: "canvas2d", defaultGradient: { .25: "rgb(0,0,255)", .55: "rgb(0,255,0)", .85: "yellow", 1: "rgb(255,0,0)" }, defaultMaxOpacity: 1, defaultMinOpacity: 0, defaultBlur: .85, defaultXField: "x", defaultYField: "y", defaultValueField: "value", plugins: {} }; var b = function h() { var b = function d(a) { this._coordinator = {}; this._data = []; this._radi = []; this._min = 0; this._max = 1; this._xField = a["xField"] || a.defaultXField; this._yField = a["yField"] || a.defaultYField; this._valueField = a["valueField"] || a.defaultValueField; if (a["radius"]) { this._cfgRadius = a["radius"] } }; var c = a.defaultRadius; b.prototype = { _organiseData: function (a, b) { var d = a[this._xField]; var e = a[this._yField]; var f = this._radi; var g = this._data; var h = this._max; var i = this._min; var j = a[this._valueField] || 1; var k = a.radius || this._cfgRadius || c; if (!g[d]) { g[d] = []; f[d] = [] } if (!g[d][e]) { g[d][e] = j; f[d][e] = k } else { g[d][e] += j } if (g[d][e] > h) { if (!b) { this._max = g[d][e] } else { this.setDataMax(g[d][e]) } return false } else { return { x: d, y: e, value: j, radius: k, min: i, max: h } } }, _unOrganizeData: function () { var a = []; var b = this._data; var c = this._radi; for (var d in b) { for (var e in b[d]) { a.push({ x: d, y: e, radius: c[d][e], value: b[d][e] }) } } return { min: this._min, max: this._max, data: a } }, _onExtremaChange: function () { this._coordinator.emit("extremachange", { min: this._min, max: this._max }) }, addData: function () { if (arguments[0].length > 0) { var a = arguments[0]; var b = a.length; while (b--) { this.addData.call(this, a[b]) } } else { var c = this._organiseData(arguments[0], true); if (c) { this._coordinator.emit("renderpartial", { min: this._min, max: this._max, data: [c] }) } } return this }, setData: function (a) { var b = a.data; var c = b.length; this._data = []; this._radi = []; for (var d = 0; d < c; d++) { this._organiseData(b[d], false) } this._max = a.max; this._min = a.min || 0; this._onExtremaChange(); this._coordinator.emit("renderall", this._getInternalData()); return this }, removeData: function () { }, setDataMax: function (a) { this._max = a; this._onExtremaChange(); this._coordinator.emit("renderall", this._getInternalData()); return this }, setDataMin: function (a) { this._min = a; this._onExtremaChange(); this._coordinator.emit("renderall", this._getInternalData()); return this }, setCoordinator: function (a) { this._coordinator = a }, _getInternalData: function () { return { max: this._max, min: this._min, data: this._data, radi: this._radi } }, getData: function () { return this._unOrganizeData() } }; return b }(); var c = function i() { var a = function (a) { var b = a.gradient || a.defaultGradient; var c = document.createElement("canvas"); var d = c.getContext("2d"); c.width = 256; c.height = 1; var e = d.createLinearGradient(0, 0, 256, 1); for (var f in b) { e.addColorStop(f, b[f]) } d.fillStyle = e; d.fillRect(0, 0, 256, 1); return d.getImageData(0, 0, 256, 1).data }; var b = function (a, b) { var c = document.createElement("canvas"); var d = c.getContext("2d"); var e = a; var f = a; c.width = c.height = a * 2; if (b == 1) { d.beginPath(); d.arc(e, f, a, 0, 2 * Math.PI, false); d.fillStyle = "rgba(0,0,0,1)"; d.fill() } else { var g = d.createRadialGradient(e, f, a * b, e, f, a); g.addColorStop(0, "rgba(0,0,0,1)"); g.addColorStop(1, "rgba(0,0,0,0)"); d.fillStyle = g; d.fillRect(0, 0, 2 * a, 2 * a) } return c }; var c = function (a) { var b = []; var c = a.min; var d = a.max; var e = a.radi; var a = a.data; var f = Object.keys(a); var g = f.length; while (g--) { var h = f[g]; var i = Object.keys(a[h]); var j = i.length; while (j--) { var k = i[j]; var l = a[h][k]; var m = e[h][k]; b.push({ x: h, y: k, value: l, radius: m }) } } return { min: c, max: d, data: b } }; function d(b) { var c = b.container; var d = this.shadowCanvas = document.createElement("canvas"); var e = this.canvas = b.canvas || document.createElement("canvas"); var f = this._renderBoundaries = [1e4, 1e4, 0, 0]; var g = getComputedStyle(b.container) || {}; e.className = "heatmap-canvas"; this._width = e.width = d.width = b.width || +g.width.replace(/px/, ""); this._height = e.height = d.height = b.height || +g.height.replace(/px/, ""); this.shadowCtx = d.getContext("2d"); this.ctx = e.getContext("2d"); e.style.cssText = d.style.cssText = "position:absolute;left:0;top:0;"; c.style.position = "relative"; c.appendChild(e); this._palette = a(b); this._templates = {}; this._setStyles(b) } d.prototype = { renderPartial: function (a) { if (a.data.length > 0) { this._drawAlpha(a); this._colorize() } }, renderAll: function (a) { this._clear(); if (a.data.length > 0) { this._drawAlpha(c(a)); this._colorize() } }, _updateGradient: function (b) { this._palette = a(b) }, updateConfig: function (a) { if (a["gradient"]) { this._updateGradient(a) } this._setStyles(a) }, setDimensions: function (a, b) { this._width = a; this._height = b; this.canvas.width = this.shadowCanvas.width = a; this.canvas.height = this.shadowCanvas.height = b }, _clear: function () { this.shadowCtx.clearRect(0, 0, this._width, this._height); this.ctx.clearRect(0, 0, this._width, this._height) }, _setStyles: function (a) { this._blur = a.blur == 0 ? 0 : a.blur || a.defaultBlur; if (a.backgroundColor) { this.canvas.style.backgroundColor = a.backgroundColor } this._width = this.canvas.width = this.shadowCanvas.width = a.width || this._width; this._height = this.canvas.height = this.shadowCanvas.height = a.height || this._height; this._opacity = (a.opacity || 0) * 255; this._maxOpacity = (a.maxOpacity || a.defaultMaxOpacity) * 255; this._minOpacity = (a.minOpacity || a.defaultMinOpacity) * 255; this._useGradientOpacity = !!a.useGradientOpacity }, _drawAlpha: function (a) { var c = this._min = a.min; var d = this._max = a.max; var a = a.data || []; var e = a.length; var f = 1 - this._blur; while (e--) { var g = a[e]; var h = g.x; var i = g.y; var j = g.radius; var k = Math.min(g.value, d); var l = h - j; var m = i - j; var n = this.shadowCtx; var o; if (!this._templates[j]) { this._templates[j] = o = b(j, f) } else { o = this._templates[j] } var p = (k - c) / (d - c); n.globalAlpha = p < .01 ? .01 : p; n.drawImage(o, l, m); if (l < this._renderBoundaries[0]) { this._renderBoundaries[0] = l } if (m < this._renderBoundaries[1]) { this._renderBoundaries[1] = m } if (l + 2 * j > this._renderBoundaries[2]) { this._renderBoundaries[2] = l + 2 * j } if (m + 2 * j > this._renderBoundaries[3]) { this._renderBoundaries[3] = m + 2 * j } } }, _colorize: function () { var a = this._renderBoundaries[0]; var b = this._renderBoundaries[1]; var c = this._renderBoundaries[2] - a; var d = this._renderBoundaries[3] - b; var e = this._width; var f = this._height; var g = this._opacity; var h = this._maxOpacity; var i = this._minOpacity; var j = this._useGradientOpacity; if (a < 0) { a = 0 } if (b < 0) { b = 0 } if (a + c > e) { c = e - a } if (b + d > f) { d = f - b } var k = this.shadowCtx.getImageData(a, b, c, d); var l = k.data; var m = l.length; var n = this._palette; for (var o = 3; o < m; o += 4) { var p = l[o]; var q = p * 4; if (!q) { continue } var r; if (g > 0) { r = g } else { if (p < h) { if (p < i) { r = i } else { r = p } } else { r = h } } l[o - 3] = n[q]; l[o - 2] = n[q + 1]; l[o - 1] = n[q + 2]; l[o] = j ? n[q + 3] : r } k.data = l; this.ctx.putImageData(k, a, b); this._renderBoundaries = [1e3, 1e3, 0, 0] }, getValueAt: function (a) { var b; var c = this.shadowCtx; var d = c.getImageData(a.x, a.y, 1, 1); var e = d.data[3]; var f = this._max; var g = this._min; b = Math.abs(f - g) * (e / 255) >> 0; return b }, getDataURL: function () { return this.canvas.toDataURL() } }; return d }(); var d = function j() { var b = false; if (a["defaultRenderer"] === "canvas2d") { b = c } return b }(); var e = { merge: function () { var a = {}; var b = arguments.length; for (var c = 0; c < b; c++) { var d = arguments[c]; for (var e in d) { a[e] = d[e] } } return a } }; var f = function k() { var c = function h() { function a() { this.cStore = {} } a.prototype = { on: function (a, b, c) { var d = this.cStore; if (!d[a]) { d[a] = [] } d[a].push(function (a) { return b.call(c, a) }) }, emit: function (a, b) { var c = this.cStore; if (c[a]) { var d = c[a].length; for (var e = 0; e < d; e++) { var f = c[a][e]; f(b) } } } }; return a }(); var f = function (a) { var b = a._renderer; var c = a._coordinator; var d = a._store; c.on("renderpartial", b.renderPartial, b); c.on("renderall", b.renderAll, b); c.on("extremachange", function (b) { a._config.onExtremaChange && a._config.onExtremaChange({ min: b.min, max: b.max, gradient: a._config["gradient"] || a._config["defaultGradient"] }) }); d.setCoordinator(c) }; function g() { var g = this._config = e.merge(a, arguments[0] || {}); this._coordinator = new c; if (g["plugin"]) { var h = g["plugin"]; if (!a.plugins[h]) { throw new Error("Plugin '" + h + "' not found. Maybe it was not registered.") } else { var i = a.plugins[h]; this._renderer = new i.renderer(g); this._store = new i.store(g) } } else { this._renderer = new d(g); this._store = new b(g) } f(this) } g.prototype = { addData: function () { this._store.addData.apply(this._store, arguments); return this }, removeData: function () { this._store.removeData && this._store.removeData.apply(this._store, arguments); return this }, setData: function () { this._store.setData.apply(this._store, arguments); return this }, setDataMax: function () { this._store.setDataMax.apply(this._store, arguments); return this }, setDataMin: function () { this._store.setDataMin.apply(this._store, arguments); return this }, configure: function (a) { this._config = e.merge(this._config, a); this._renderer.updateConfig(this._config); this._coordinator.emit("renderall", this._store._getInternalData()); return this }, repaint: function () { this._coordinator.emit("renderall", this._store._getInternalData()); return this }, getData: function () { return this._store.getData() }, getDataURL: function () { return this._renderer.getDataURL() }, getValueAt: function (a) { if (this._store.getValueAt) { return this._store.getValueAt(a) } else if (this._renderer.getValueAt) { return this._renderer.getValueAt(a) } else { return null } } }; return g }(); var g = { create: function (a) { return new f(a) }, register: function (b, c) { a.plugins[b] = c } }; return g });
@@ -0,0 +1,246 @@
1
+ /*
2
+ * Leaflet Heatmap Overlay
3
+ *
4
+ * Copyright (c) 2008-2016, Patrick Wied (https://www.patrick-wied.at)
5
+ * Dual-licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
6
+ * and the Beerware (http://en.wikipedia.org/wiki/Beerware) license.
7
+ */
8
+ ; (function (name, context, factory) {
9
+ // Supports UMD. AMD, CommonJS/Node.js and browser context
10
+ if (typeof module !== "undefined" && module.exports) {
11
+ module.exports = factory(
12
+ require('heatmap.js'),
13
+ require('leaflet')
14
+ );
15
+ } else if (typeof define === "function" && define.amd) {
16
+ define(['heatmap.js', 'leaflet'], factory);
17
+ } else {
18
+ // browser globals
19
+ if (typeof window.h337 === 'undefined') {
20
+ throw new Error('heatmap.js must be loaded before the leaflet heatmap plugin');
21
+ }
22
+ if (typeof window.L === 'undefined') {
23
+ throw new Error('Leaflet must be loaded before the leaflet heatmap plugin');
24
+ }
25
+ context[name] = factory(window.h337, window.L);
26
+ }
27
+
28
+ })("HeatmapOverlay", this, function (h337, L) {
29
+ 'use strict';
30
+
31
+ // Leaflet < 0.8 compatibility
32
+ if (typeof L.Layer === 'undefined') {
33
+ L.Layer = L.Class;
34
+ }
35
+
36
+ var HeatmapOverlay = L.Layer.extend({
37
+
38
+ initialize: function (config) {
39
+ this.cfg = config;
40
+ this._el = L.DomUtil.create('div', 'leaflet-zoom-hide');
41
+ this._data = [];
42
+ this._max = 1;
43
+ this._min = 0;
44
+ this.cfg.container = this._el;
45
+ },
46
+
47
+ onAdd: function (map) {
48
+ var size = map.getSize();
49
+
50
+ this._map = map;
51
+
52
+ this._width = size.x;
53
+ this._height = size.y;
54
+
55
+ this._el.style.width = size.x + 'px';
56
+ this._el.style.height = size.y + 'px';
57
+ this._el.style.position = 'absolute';
58
+
59
+ this._origin = this._map.layerPointToLatLng(new L.Point(0, 0));
60
+
61
+ map.getPanes().overlayPane.appendChild(this._el);
62
+
63
+ if (!this._heatmap) {
64
+ this._heatmap = h337.create(this.cfg);
65
+ }
66
+
67
+ // this resets the origin and redraws whenever
68
+ // the zoom changed or the map has been moved
69
+ map.on('moveend', this._reset, this);
70
+ this._draw();
71
+ },
72
+
73
+ addTo: function (map) {
74
+ map.addLayer(this);
75
+ return this;
76
+ },
77
+
78
+ onRemove: function (map) {
79
+ // remove layer's DOM elements and listeners
80
+ map.getPanes().overlayPane.removeChild(this._el);
81
+
82
+ map.off('moveend', this._reset, this);
83
+ },
84
+ _draw: function () {
85
+ if (!this._map) { return; }
86
+
87
+ var mapPane = this._map.getPanes().mapPane;
88
+ var point = mapPane._leaflet_pos;
89
+
90
+ // reposition the layer
91
+ this._el.style[HeatmapOverlay.CSS_TRANSFORM] = 'translate(' +
92
+ -Math.round(point.x) + 'px,' +
93
+ -Math.round(point.y) + 'px)';
94
+
95
+ this._update();
96
+ },
97
+ _update: function () {
98
+ var bounds, zoom, scale;
99
+ var generatedData = { max: this._max, min: this._min, data: [] };
100
+
101
+ bounds = this._map.getBounds();
102
+ zoom = this._map.getZoom();
103
+ scale = Math.pow(2, zoom);
104
+
105
+ if (this._data.length == 0) {
106
+ if (this._heatmap) {
107
+ this._heatmap.setData(generatedData);
108
+ }
109
+ return;
110
+ }
111
+
112
+
113
+ var latLngPoints = [];
114
+ var radiusMultiplier = this.cfg.scaleRadius ? scale : 1;
115
+ var localMax = 0;
116
+ var localMin = 0;
117
+ var valueField = this.cfg.valueField;
118
+ var len = this._data.length;
119
+
120
+ while (len--) {
121
+ var entry = this._data[len];
122
+ var value = entry[valueField];
123
+ var latlng = entry.latlng;
124
+
125
+
126
+ // we don't wanna render points that are not even on the map ;-)
127
+ if (!bounds.contains(latlng)) {
128
+ continue;
129
+ }
130
+ // local max is the maximum within current bounds
131
+ localMax = Math.max(value, localMax);
132
+ localMin = Math.min(value, localMin);
133
+
134
+ var point = this._map.latLngToContainerPoint(latlng);
135
+ var latlngPoint = { x: Math.round(point.x), y: Math.round(point.y) };
136
+ latlngPoint[valueField] = value;
137
+
138
+ var radius;
139
+
140
+ if (entry.radius) {
141
+ radius = entry.radius * radiusMultiplier;
142
+ } else {
143
+ radius = (this.cfg.radius || 2) * radiusMultiplier;
144
+ }
145
+ latlngPoint.radius = radius;
146
+ latLngPoints.push(latlngPoint);
147
+ }
148
+ if (this.cfg.useLocalExtrema) {
149
+ generatedData.max = localMax;
150
+ generatedData.min = localMin;
151
+ }
152
+
153
+ generatedData.data = latLngPoints;
154
+
155
+ this._heatmap.setData(generatedData);
156
+ },
157
+ setData: function (data) {
158
+ this._max = data.max || this._max;
159
+ this._min = data.min || this._min;
160
+ var latField = this.cfg.latField || 'lat';
161
+ var lngField = this.cfg.lngField || 'lng';
162
+ var valueField = this.cfg.valueField || 'value';
163
+
164
+ // transform data to latlngs
165
+ var data = data.data;
166
+ var len = data.length;
167
+ var d = [];
168
+
169
+ while (len--) {
170
+ var entry = data[len];
171
+ var latlng = new L.LatLng(entry[latField], entry[lngField]);
172
+ var dataObj = { latlng: latlng };
173
+ dataObj[valueField] = entry[valueField];
174
+ if (entry.radius) {
175
+ dataObj.radius = entry.radius;
176
+ }
177
+ d.push(dataObj);
178
+ }
179
+ this._data = d;
180
+
181
+ this._draw();
182
+ },
183
+ // experimential... not ready.
184
+ addData: function (pointOrArray) {
185
+ if (pointOrArray.length > 0) {
186
+ var len = pointOrArray.length;
187
+ while (len--) {
188
+ this.addData(pointOrArray[len]);
189
+ }
190
+ } else {
191
+ var latField = this.cfg.latField || 'lat';
192
+ var lngField = this.cfg.lngField || 'lng';
193
+ var valueField = this.cfg.valueField || 'value';
194
+ var entry = pointOrArray;
195
+ var latlng = new L.LatLng(entry[latField], entry[lngField]);
196
+ var dataObj = { latlng: latlng };
197
+
198
+ dataObj[valueField] = entry[valueField];
199
+ this._max = Math.max(this._max, dataObj[valueField]);
200
+ this._min = Math.min(this._min, dataObj[valueField]);
201
+
202
+ if (entry.radius) {
203
+ dataObj.radius = entry.radius;
204
+ }
205
+ this._data.push(dataObj);
206
+ this._draw();
207
+ }
208
+ },
209
+ _reset: function () {
210
+ this._origin = this._map.layerPointToLatLng(new L.Point(0, 0));
211
+
212
+ var size = this._map.getSize();
213
+ if (this._width !== size.x || this._height !== size.y) {
214
+ this._width = size.x;
215
+ this._height = size.y;
216
+
217
+ this._el.style.width = this._width + 'px';
218
+ this._el.style.height = this._height + 'px';
219
+
220
+ this._heatmap._renderer.setDimensions(this._width, this._height);
221
+ }
222
+ this._draw();
223
+ }
224
+ });
225
+
226
+ HeatmapOverlay.CSS_TRANSFORM = (function () {
227
+ var div = document.createElement('div');
228
+ var props = [
229
+ 'transform',
230
+ 'WebkitTransform',
231
+ 'MozTransform',
232
+ 'OTransform',
233
+ 'msTransform'
234
+ ];
235
+
236
+ for (var i = 0; i < props.length; i++) {
237
+ var prop = props[i];
238
+ if (div.style[prop] !== undefined) {
239
+ return prop;
240
+ }
241
+ }
242
+ return props[0];
243
+ })();
244
+
245
+ return HeatmapOverlay;
246
+ });
@@ -0,0 +1,197 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title></title>
6
+ <link href="./package/leaflet/leaflet.min.css" rel="stylesheet">
7
+ <script src="./package/leaflet/leaflet.min.js"></script>
8
+ <script src="./package/leaflet/heatmap.min.js"></script>
9
+ <script src="./package/leaflet/leaflet-heatmap.js"></script>
10
+ <style>
11
+ body, html {
12
+ margin: 0;
13
+ padding: 0;
14
+ }
15
+ * {
16
+ font-family: "微软雅黑", serif;
17
+ }
18
+ #container {
19
+ width: 1000px;
20
+ position: relative;
21
+ }
22
+ .map {
23
+ width: 100%;
24
+ height: 900px;
25
+ background-color: #4b4b4b;
26
+ }
27
+ .traffic-box {
28
+ //position: absolute;
29
+ //bottom: 0;
30
+ //left: 0;
31
+ //z-index: 9999999;
32
+ width: 100%;
33
+ backdrop-filter: blur(3px);
34
+ background-color: #4b4b4b;
35
+ padding: 12px 16px;
36
+ box-sizing: border-box;
37
+ overflow-y: hidden;
38
+ }
39
+ .traffic-item {
40
+ color: #ffffff;
41
+ width: 33.3333%;
42
+ float: left;
43
+ margin-top: 8px;
44
+ font-size: 14px;
45
+ border-right: 1px solid rgba(255, 255, 255, 0.3);
46
+ box-sizing: border-box;
47
+ padding: 0 10px;
48
+ }
49
+ .traffic-item:nth-child(-n+3) {
50
+ margin-top: 0;
51
+ }
52
+ .traffic-item:last-child, .traffic-item:nth-child(3n) {
53
+ border-right: 0;
54
+ }
55
+ .traffic-item .region-info {
56
+ display: inline-block;
57
+ width: 64%;
58
+ }
59
+ .traffic-item .player-count {
60
+ display: inline-block;
61
+ width: 16%;
62
+ text-align: center;
63
+ }
64
+ .traffic-item .traffic-status {
65
+ display: inline-block;
66
+ width: 20%;
67
+ text-align: right;
68
+ }
69
+ </style>
70
+ </head>
71
+ <body>
72
+ <div id="container">
73
+ <div id="map" class="map"></div>
74
+ <div class="traffic-box"></div>
75
+ </div>
76
+ <script>
77
+ let mapConfig = {
78
+ ets: {
79
+ tileUrl: 'https://ets-map.oss-cn-beijing.aliyuncs.com/ets2/05102019/{z}/{x}/{y}.png',
80
+ multipliers: {
81
+ x: 71292,
82
+ y: 60412
83
+ },
84
+ breakpoints: {
85
+ uk: {
86
+ x: -31056.8,
87
+ y: -5832.867
88
+ }
89
+ },
90
+ bounds: {
91
+ y: 131072,
92
+ x: 131072
93
+ },
94
+ maxZoom: 8,
95
+ minZoom: 2,
96
+ // 游戏地转地图坐标
97
+ calculateMapCoordinate (x, y) {
98
+ return [
99
+ x / 1.325928 + mapConfig.ets.multipliers.x,
100
+ y / 1.325928 + mapConfig.ets.multipliers.y
101
+ ];
102
+ }
103
+ },
104
+ promods: {
105
+ tileUrl: 'https://tiles.truckyapp.com/promods/05102019/{z}/{x}/{y}.png',
106
+ multipliers: {
107
+ x: 41828,
108
+ y: 77369
109
+ },
110
+ breakpoints: {
111
+ uk: {
112
+ x: -31056.8,
113
+ y: -5832.867
114
+ }
115
+ },
116
+ bounds: {
117
+ y: 131072,
118
+ x: 131072
119
+ },
120
+ maxZoom: 8,
121
+ minZoom: 2,
122
+ // 游戏地转地图坐标
123
+ calculateMapCoordinate (x, y) {
124
+ return [
125
+ x / 2.303589 + mapConfig.promods.multipliers.x,
126
+ y / 2.303589 + mapConfig.promods.multipliers.y
127
+ ]
128
+ }
129
+ }
130
+ }
131
+
132
+ // 定义地图
133
+ let map = L.map('map', {
134
+ attributionControl: false,
135
+ crs: L.CRS.Simple,
136
+ zoomControl: false
137
+ });
138
+
139
+ function setData(data) {
140
+ // 边界
141
+ let bounds = L.latLngBounds(
142
+ map.unproject([0, mapConfig[data.mapType].bounds.y], mapConfig[data.mapType].maxZoom),
143
+ map.unproject([mapConfig[data.mapType].bounds.x, 0], mapConfig[data.mapType].maxZoom)
144
+ );
145
+
146
+ // 瓦片地图
147
+ L.tileLayer(mapConfig[data.mapType].tileUrl, {
148
+ minZoom: 1,
149
+ maxZoom: 8,
150
+ tileSize: 512,
151
+ bounds: bounds,
152
+ reuseTiles: true
153
+ }).addTo(map);
154
+ map.setMaxBounds(
155
+ new L.LatLngBounds(
156
+ map.unproject([0, mapConfig[data.mapType].bounds.y], mapConfig[data.mapType].maxZoom),
157
+ map.unproject([mapConfig[data.mapType].bounds.x, 0], mapConfig[data.mapType].maxZoom)
158
+ )
159
+ );
160
+
161
+ // 展示地图全貌
162
+ map.fitBounds(bounds)
163
+
164
+ // 热力图
165
+ let heatmapLayer = new HeatmapOverlay({
166
+ radius: 3,
167
+ maxOpacity: 0.8,
168
+ scaleRadius: true,
169
+ useLocalExtrema: true,
170
+ latField: "lat",
171
+ lngField: "lng",
172
+ valueField: "count"
173
+ });
174
+ map.addLayer(heatmapLayer);
175
+ let heatmapData = []
176
+ for (const arrayElement of data.playerCoordinateList) {
177
+ let unprojected = map.unproject(mapConfig[data.mapType].calculateMapCoordinate(arrayElement[0], arrayElement[1]), 8);
178
+ heatmapData.push({ lat: unprojected.lat, lng: unprojected.lng, count: 1 });
179
+ }
180
+ heatmapLayer.setData({
181
+ min: 1,
182
+ max: 5000,
183
+ data: heatmapData
184
+ })
185
+
186
+ // 展示热门地区路况状态
187
+ for (const traffic of data.trafficList) {
188
+ document.getElementsByClassName('traffic-box')[0].insertAdjacentHTML('beforeend', `
189
+ <div class="traffic-item">
190
+ <span class="region-info"><strong>${traffic.country}</strong> ${traffic.province}</span><span class="player-count">${traffic.playerCount}人</span><span class="traffic-status">${traffic.severity}</span>
191
+ </div>
192
+ `);
193
+ }
194
+ }
195
+ </script>
196
+ </body>
197
+ </html>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-tmp-bot",
3
3
  "description": "欧洲卡车模拟2 TMP查询机器人",
4
- "version": "1.7.1",
4
+ "version": "1.8.0",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "homepage": "https://www.npmjs.com/package/koishi-plugin-tmp-bot",