From 37ee801f2bff21323ccacc68c53eaaa6e5b2e97e Mon Sep 17 00:00:00 2001 From: Thomas Rudin Date: Sun, 29 Dec 2019 16:12:30 +0100 Subject: [PATCH] working stats-only page fixes #76 --- doc/pics/stats_webfragment.png | Bin 0 -> 2465 bytes doc/stats_webfragment.md | 11 +++ readme.md | 1 + static/js/bundle-stats.js | 104 +++++++++++++++++++++++++++++ static/js/bundle-stats.js.map | 1 + static/js/components/WorldStats.js | 2 +- static/js/rollup.config.js | 12 +++- static/js/stats.js | 9 +++ static/stats.html | 4 +- 9 files changed, 139 insertions(+), 5 deletions(-) create mode 100644 doc/pics/stats_webfragment.png create mode 100644 doc/stats_webfragment.md create mode 100644 static/js/bundle-stats.js create mode 100644 static/js/bundle-stats.js.map diff --git a/doc/pics/stats_webfragment.png b/doc/pics/stats_webfragment.png new file mode 100644 index 0000000000000000000000000000000000000000..5a9eba6a0ee96f7c4b3a70e673fa1e1088570090 GIT binary patch literal 2465 zcmV;S310SzP)F0kdctsi@O zdwvZ1P|&ifO7-6R>itxy4=AOOBgdDG-+k^03#Gr~X4B5E7riJj6;ZeSz?4u-*KUggR_ZLM7dSeH0IR*F zdIv2IAx>L(EYFl!U{h!L5#Y6jwS~{fRuG1PC9nS~w7q4Qwy?%gz_gdTu(pYxrMiUC zG7TCIT0F~Z(K7H%iG5rLokmkfWg|tgszXClj4yju?ZsPCN@-w83~()XDTO67K=eWE zEus6Pgje{d4SLCL_r2%*tV_?Bh^(yWtOmp|g{CWWSj+-RW*9vt0DSx2!SqxXkYs%# zhq_6}NS(BIug`n>Qc9_BQU=ytsh;tIE#fbK-i4-H4C=Nxv~FJC>80jq55bNlRH0lc z#eOVT%889<{p;>qwpOn!d)FIP`0vg2aI@vOJM6v!fUmG5I+JGiqFOH(l7{?!x%Q{? zo4<|+l1#n=fH(br-;B4+xpF!jo>uPf3#C#K?xxe};*ZphP^ukYk7h85ZmUOEqvc4m(RH&?tyC)2YPDKBY+m*!u`#FJ%bT}b1X$qh z&1H8A05=z~(W6?+=(a`t55X3L4lgf%Dm9L(D?LiJdZqZ`FG@!me|=jMScI0LJUutv zY)M_60PriZiqf9KCah#iY1nJMP};ATD=%GUhYWz3Kc(NF}r$@qsG6Oo6k-k7P?zUFiFf&a(~bw|M}; z=$V?ta~vUrmv!rrv-}UO^f7|~u|&+O^m{4`Aa+)rzN6vw2%CW5wIMxAt)kXa(%95? zps8o@XfyZpOod|*!(tX8R%rFo<5bWQ0T|g1mxBQ?a+D$XZ61(l28)&``kPWpJ`3i<;^yzqhSDquxJbdN@?g> z3SLjCe>;+c{-oQimkRSpS12D{j{yJ*m7~l4csirA$*6nYD9@XYE*tkP>&J-NO-T!y0A@Vs6< z88vRk)5&-;9bS|!59`f-R!pqatBa(dR4O5;)S}yBsf6yP(-{Cju~x6Z_s6wH^Rhdf z%%FVOJgmfqN=Pmi`A6;I*470!-aOvr_6D*xS62`he+!D`63diIrNk6$1G5>xUHRmq zSuFxUp?r98F3x^9JMZuKu3eDC-Ib~cuwr?Gxf?|c5oJ}=HB}Zc1Bk)AZ1jB3QtsD3 zt2$APSap4=L4S#Nw)zag6D&DB@BR9t_rCL^Or8K3vYG7fws=#|lnGI+^{t(bu+b$j z#q>dfj=1VjLQ_H@+>2;QXeBBJgN`O~ECK+8g~WZXflgwkKv;@)O2ajuO7uZu&<8|~ zn4{iJ{3Uh?MA-%%=mY@CtF@=A696vCf*t{hG_{ry32TmLO0i^V6cb3Orx?jmSpXp($b{s~OXC!ZFE` zJ8CSpFRALgYkO6AuFB2bD4+loaWo@UNf&>KU1*wZ(7+VYCQV!1<(n*;zWV#=Rq5nt?i`p}y#j^$QG&(K-P6;XDF8sR(m1)gIpbhF9L0ij?X<}!Z0+B@dil+t|M17Z{ID$Q5#Kzm0RS8| zfr+>O2^v+n=qJx5UHl#7n2e(YDBGaL`cVzt4Odh-8{Lk9tySZjLl4F_9$RweISBv& zlC8~NuE8^`wAc-HGPn1W;AlovJhc+aC_M*RZ=c_1gl&>(S1HZ%QoUlS8v>BoTE(w`+Y99qRmIIjU&XFsQCmC)_T6w(8bP zD7wXf9N(6cHFg0pttC(dF0Ag68^+HGI@ZuJ$_S&s%2BBxQ6oDfg#}R@F zFSqQ}h#T~DKJFp!=gR9F5j}QT8o#hIKjPmieunBO_1Xfb12gqrfV-JwiG{+twr)iEoKu*&fdw`s#IracKO>^u4a+>DY f1LQQ#u?P4+-M!VvmG6C~00000NkvXXu0mjf^yIr3 literal 0 HcmV?d00001 diff --git a/doc/stats_webfragment.md b/doc/stats_webfragment.md new file mode 100644 index 0000000..d6f015e --- /dev/null +++ b/doc/stats_webfragment.md @@ -0,0 +1,11 @@ + +# Stats webfragment + + + +The "world stats" info from the bottom right corner of the mapserver +can be embedded as an iframe into any existing web-page: + +```html + +``` diff --git a/readme.md b/readme.md index 35c0625..b841f9c 100644 --- a/readme.md +++ b/readme.md @@ -23,6 +23,7 @@ Demo: [Pandorabox Server map](https://pandorabox.io/map/#-1782.25/493.5/10) * [Search](doc/search.md) * [Configuration](doc/config.md) * [Recommended specs](doc/recommended_specs.md) +* [Stats webfragment](doc/stats_webfragment.md) * [Contribution](doc/contrib.md) * [Development](doc/dev.md) * [License](doc/license.md) diff --git a/static/js/bundle-stats.js b/static/js/bundle-stats.js new file mode 100644 index 0000000..dbc7ce2 --- /dev/null +++ b/static/js/bundle-stats.js @@ -0,0 +1,104 @@ +(function(f){typeof define==='function'&&define.amd?define(f):f();}((function(){'use strict';function WorldStats(info){ + + var timeIcon = m("span", { class: "fa fa-sun", style: "color: orange;" }); + + if (info.time < 5500 || info.time > 19000) //0 - 24'000 + timeIcon = m("span", { class: "fa fa-moon", style: "color: blue;" }); + + function getHour(){ + return Math.floor(info.time/1000); + } + + function getMinute(){ + var min = Math.floor((info.time % 1000) / 1000 * 60); + return min > 10 ? min : "0" + min; + } + + function getLag(){ + var color = "green"; + if (info.max_lag > 0.8) + color = "orange"; + else if (info.max_lag > 1.2) + color = "red"; + + return [ + m("span", { class: "fa fa-wifi", style: "color: " + color }), + parseInt(info.max_lag*1000), + " ms" + ]; + } + + function getPlayers(){ + return [ + m("span", { class: "fa fa-users" }), + info.players ? info.players.length : "0" + ]; + } + + return m("div", [ + getPlayers(), + " ", + getLag(), + " ", + m("span", { class: "fa fa-clock" }), + timeIcon, + getHour(), ":", getMinute() + ]); + +}class WebSocketChannel { + constructor(){ + this.wsUrl = window.location.protocol.replace("http", "ws") + + "//" + window.location.host + + window.location.pathname.substring(0, window.location.pathname.lastIndexOf("/")) + + "/api/ws"; + + this.listenerMap = {/* type -> [listeners] */}; + } + + addListener(type, listener){ + var list = this.listenerMap[type]; + if (!list){ + list = []; + this.listenerMap[type] = list; + } + + list.push(listener); + } + + removeListener(type, listener){ + var list = this.listenerMap[type]; + if (!list){ + return; + } + + this.listenerMap[type] = list.filter(l => l != listener); + } + + connect(){ + var ws = new WebSocket(this.wsUrl); + var self = this; + + ws.onmessage = function(e){ + var event = JSON.parse(e.data); + //rendered-tile, mapobject-created, mapobjects-cleared + + var listeners = self.listenerMap[event.type]; + if (listeners){ + listeners.forEach(function(listener){ + listener(event.data); + }); + } + }; + + ws.onerror = function(){ + //reconnect after some time + setTimeout(self.connect.bind(self), 1000); + }; + } +} + +var wsChannel = new WebSocketChannel();wsChannel.connect(); + +wsChannel.addListener("minetest-info", function(info){ + m.render(document.getElementById("app"), WorldStats(info)); +});})));//# sourceMappingURL=bundle-stats.js.map diff --git a/static/js/bundle-stats.js.map b/static/js/bundle-stats.js.map new file mode 100644 index 0000000..d98b2d8 --- /dev/null +++ b/static/js/bundle-stats.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bundle-stats.js","sources":["components/WorldStats.js","WebSocketChannel.js","stats.js"],"sourcesContent":["\nexport default function(info){\n\n var timeIcon = m(\"span\", { class: \"fa fa-sun\", style: \"color: orange;\" });\n\n if (info.time < 5500 || info.time > 19000) //0 - 24'000\n timeIcon = m(\"span\", { class: \"fa fa-moon\", style: \"color: blue;\" });\n\n function getHour(){\n return Math.floor(info.time/1000);\n }\n\n function getMinute(){\n var min = Math.floor((info.time % 1000) / 1000 * 60);\n return min > 10 ? min : \"0\" + min;\n }\n\n function getLag(){\n var color = \"green\";\n if (info.max_lag > 0.8)\n color = \"orange\";\n else if (info.max_lag > 1.2)\n color = \"red\";\n\n return [\n m(\"span\", { class: \"fa fa-wifi\", style: \"color: \" + color }),\n parseInt(info.max_lag*1000),\n \" ms\"\n ];\n }\n\n function getPlayers(){\n return [\n m(\"span\", { class: \"fa fa-users\" }),\n info.players ? info.players.length : \"0\"\n ];\n }\n\n return m(\"div\", [\n getPlayers(),\n \" \",\n getLag(),\n \" \",\n m(\"span\", { class: \"fa fa-clock\" }),\n timeIcon,\n getHour(), \":\", getMinute()\n ]);\n\n};\n","\nclass WebSocketChannel {\n constructor(){\n this.wsUrl = window.location.protocol.replace(\"http\", \"ws\") +\n \"//\" + window.location.host +\n window.location.pathname.substring(0, window.location.pathname.lastIndexOf(\"/\")) +\n \"/api/ws\";\n\n this.listenerMap = {/* type -> [listeners] */};\n }\n\n addListener(type, listener){\n var list = this.listenerMap[type];\n if (!list){\n list = [];\n this.listenerMap[type] = list;\n }\n\n list.push(listener);\n }\n\n removeListener(type, listener){\n var list = this.listenerMap[type];\n if (!list){\n return;\n }\n\n this.listenerMap[type] = list.filter(l => l != listener);\n }\n\n connect(){\n var ws = new WebSocket(this.wsUrl);\n var self = this;\n\n ws.onmessage = function(e){\n var event = JSON.parse(e.data);\n //rendered-tile, mapobject-created, mapobjects-cleared\n\n var listeners = self.listenerMap[event.type];\n if (listeners){\n listeners.forEach(function(listener){\n listener(event.data);\n });\n }\n };\n\n ws.onerror = function(){\n //reconnect after some time\n setTimeout(self.connect.bind(self), 1000);\n };\n }\n}\n\nexport default new WebSocketChannel();\n","\nimport WorldStats from './components/WorldStats.js';\nimport wsChannel from './WebSocketChannel.js';\n\nwsChannel.connect();\n\nwsChannel.addListener(\"minetest-info\", function(info){\n\tm.render(document.getElementById(\"app\"), WorldStats(info));\n});\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/static/js/components/WorldStats.js b/static/js/components/WorldStats.js index 303ea79..cb139f9 100644 --- a/static/js/components/WorldStats.js +++ b/static/js/components/WorldStats.js @@ -12,7 +12,7 @@ export default function(info){ function getMinute(){ var min = Math.floor((info.time % 1000) / 1000 * 60); - return min > 10 ? min : "0" + min; + return min >= 10 ? min : "0" + min; } function getLag(){ diff --git a/static/js/rollup.config.js b/static/js/rollup.config.js index bc5416a..47ad1ea 100644 --- a/static/js/rollup.config.js +++ b/static/js/rollup.config.js @@ -1,5 +1,5 @@ -export default { +export default [{ input: 'main.js', output: { file :'bundle.js', @@ -7,4 +7,12 @@ export default { sourcemap: true, compact: true } -}; +},{ + input: 'stats.js', + output: { + file :'bundle-stats.js', + format: 'umd', + sourcemap: true, + compact: true + } +}]; diff --git a/static/js/stats.js b/static/js/stats.js index e69de29..c9643d5 100644 --- a/static/js/stats.js +++ b/static/js/stats.js @@ -0,0 +1,9 @@ + +import WorldStats from './components/WorldStats.js'; +import wsChannel from './WebSocketChannel.js'; + +wsChannel.connect(); + +wsChannel.addListener("minetest-info", function(info){ + m.render(document.getElementById("app"), WorldStats(info)); +}); diff --git a/static/stats.html b/static/stats.html index a761b20..3842994 100644 --- a/static/stats.html +++ b/static/stats.html @@ -14,9 +14,9 @@ - + - +