
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->
<!doctype html>
<html>
	<head>
		<meta charset='utf-8'>
		<title>Downsample Comparasions</title>
		<meta name='viewport' content='width=device-width, initial-scale=1'>
	</head>
	<body>
		<style>
			.chart {
				width: 800px;
				height: 400px;
			}
		</style>
		<h2 id='status'>Loading lib....</h2>
		<div id='container'></div>

        <script src='lib/simpleRequire.js'></script>
        <script src='lib/config.js'></script>
		<script>
            require([
                'echarts',
				'data/large-data.json'
            ], function (echarts, packedData) {
					function round2(val) {
						return Math.round(val * 100) / 100;
					}

					function round3(val) {
						return Math.round(val * 1000) / 1000;
					}

					function prepData(packed) {
						console.time('prep');

						// epoch,idl,recv,send,read,writ,used,free

						var numFields = packed[0];
						packed = packed.slice(numFields + 1);

						var repeatTimes = 5;

						var data = new Float64Array((packed.length / numFields) * 4 * repeatTimes);

						var off = 0;
						var date = packed[0];
						for (let repeat = 0; repeat < repeatTimes; repeat++) {
							for (let i = 0, j = 0; i < packed.length; i += numFields, j++) {
								date += 1;
								data[off++] = date * 60 * 1000;
								data[off++] = round3(100 - packed[i + 1]);
								data[off++] = round2(
									(100 * packed[i + 5]) / (packed[i + 5] + packed[i + 6])
								);
								data[off++] = packed[i + 3];
							}
						}
						console.timeEnd('prep');

						return data;
					}

					function makeChart(data, title, sampling) {
						var container = document.getElementById('container');
						var dom = document.createElement('div');
						var titleDom = document.createElement('h3');
						dom.classList.add('chart');
						if (title !== 'warmup') {
							container.appendChild(titleDom);
							container.appendChild(dom);
						}
						var myChart = echarts.init(dom, null, {
							width: 800,
							height: 400
						});

						titleDom.innerHTML = title;

						let opts = {
							animation: false,
							dataset: {
								source: data,
								dimensions: ['date', 'cpu', 'ram', 'tcpout']
							},
							tooltip: {
								trigger: 'axis'
							},
							legend: {},
							grid: {
								containLabel: true,
								left: 0,
								top: 50,
								right: 0,
								bottom: 30
							},
							xAxis: {
								type: 'time'
							},
							yAxis: [{
								type: 'value',
								max: 100,
								axisLabel: {
									formatter: '{value} %'
								}
							}, {
								type: 'value',
								max: 100,
								axisLabel: {
									formatter: '{value} MB'
								}
							}],
							series: [{
								name: 'CPU',
								type: 'line',
								showSymbol: false,
								sampling: sampling,
								lineStyle: { width: 1 },
								emphasis: { lineStyle: { width: 1 } },
								encode: {
									x: 'date',
									y: 'cpu'
								}
							}, {
								name: 'RAM',
								type: 'line',
								yAxisIndex: 1,
								showSymbol: false,
								sampling: sampling,
								lineStyle: { width: 1 },
								emphasis: { lineStyle: { width: 1 } },
								encode: {
									x: 'date',
									y: 'ram'
								}
							}, {
								name: 'TCP Out',
								type: 'line',
								yAxisIndex: 1,
								showSymbol: false,
								sampling: sampling,
								lineStyle: { width: 1 },
								emphasis: { lineStyle: { width: 1 } },
								encode: {
									x: 'date',
									y: 'tcpout'
								}
							}]
						};
						const startTime = Date.now();
						myChart.setOption(opts, {
							notMerge: true
						});
						const endTime = Date.now();
						titleDom.innerHTML = `${title}(${data.length / 4 * 3}) ${(endTime - startTime).toFixed(0)} ms`;
					}
					let status = document.getElementById('status');

					status.textContent = 'Warming up';
					let data = prepData(packedData);

					for (let i = 0; i < 5; i++) {
						makeChart(data, 'warmup');
						makeChart(data, 'warmup', 'lttb');
						makeChart(data, 'warmup', 'average');
						makeChart(data, 'warmup', 'max');
					}
					status.textContent = 'Running';
					makeChart(data, 'No Sampling', null);
					setTimeout(() => makeChart(data, 'LTTB Sampling', 'lttb'), 200);
					setTimeout(() => makeChart(data, 'Max Sampling', 'max'), 400);
					setTimeout(() => makeChart(data, 'Average Sampling', 'average'), 600);
      });
		</script>
	</body>
</html>