PluginProbe
WebTotem Security / 2.4.31
WebTotem Security v2.4.31
3.0.2 3.0.1 3.0.0 trunk 1.0 1.1 1.2 1.3 1.3.1 1.3.2 1.3.3 2.0 2.1 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.1 2.2.2 2.2.3 All 110 releases
wt-security / includes / js / chart.js

chart.js in WebTotem Security 2.4.31, at includes/js/chart.js

857 lines 26.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 const isDarkThemeSet = ()=> {
2 return !!document.querySelector(".wtotem_theme—dark")}
3 ;
4
5 async function drawLineChart(dataset) {
6 var diagram = document.getElementById('wtotem_chart_diagram');
7 var days = diagram.dataset.days;
8
9 const attacksAccessor = (d) => d.attacks;
10 const blockedAccessor = (d) => d.blocked;
11 const biggerAccessor = (d) =>
12 d.attacks > d.blocked ? d.attacks : d.blocked;
13 const dateParser = (days <= 1) ? d3.timeParse("%Y-%m-%d %H:%m:%M"): d3.timeParse("%Y-%m-%d");
14 const xAccessor = (d) => dateParser(d.date);
15
16
17 const chartWrapper = document.getElementById('line-chart')
18 let dimensions = {
19 width: chartWrapper.offsetWidth,
20 height: 251,
21 margin: {
22 top: 15,
23 right: 15,
24 bottom: 40,
25 left: 60,
26 },
27 };
28 dimensions.boundedWidth =
29 dimensions.width - dimensions.margin.left - dimensions.margin.right;
30 dimensions.boundedHeight =
31 dimensions.height - dimensions.margin.top - dimensions.margin.bottom;
32
33 const wrapper = d3
34 .select("#line-chart")
35 .append("svg")
36 .attr("width", dimensions.width)
37 .attr("height", dimensions.height);
38
39 const bounds = wrapper
40 .append("g")
41 .style(
42 "transform",
43 `translate(${dimensions.margin.left - 10}px, ${
44 dimensions.margin.top
45 }px)`
46 );
47
48
49 const yValues = dataset.reduce(
50 (acc, curr) => [...acc, curr.attacks, curr.blocked],
51 [0, 100]
52 );
53
54 const yScale = d3
55 .scaleLinear()
56 .domain(d3.extent(yValues))
57 .range([dimensions.boundedHeight, 0]);
58 const xScale = d3
59 .scaleTime()
60 .domain(d3.extent(dataset, xAccessor))
61 .range([0, dimensions.boundedWidth]);
62
63 function make_y_gridlines() {
64 return d3.axisLeft(yScale).ticks(5);
65 }
66
67 bounds
68 .append("g")
69 .attr("class", "grid")
70 .call(
71 make_y_gridlines().tickSize(-dimensions.boundedWidth).tickFormat("")
72 );
73
74 const area1 = d3
75 .area()
76 .x((d) => xScale(xAccessor(d)))
77 .y0(yScale(0))
78 .y1((d) => yScale(attacksAccessor(d)));
79
80 const area2 = d3
81 .area()
82 .x((d) => xScale(xAccessor(d)))
83 .y0(yScale(0))
84 .y1((d) => yScale(blockedAccessor(d)));
85
86 const isDarkTheme = isDarkThemeSet();
87 const minOpacity = isDarkTheme ? 0.2 : 0.1;
88 const maxOpacity = isDarkTheme ? 0.8 : 0.6;
89
90 bounds
91 .append("linearGradient")
92 .attr("id", "area-gradient1")
93 .attr("gradientUnits", "userSpaceOnUse")
94 .attr("x1", 0)
95 .attr("y1", yScale(0))
96 .attr("x2", 0)
97 .attr("y2", yScale(100))
98 .selectAll("stop")
99 .data([
100 { offset: "0%", color: "#d46c6a", opacity: minOpacity},
101 { offset: "100%", color: "#d46c6a", opacity: maxOpacity},
102 ])
103 .enter()
104 .append("stop")
105 .attr("offset", function (d) {
106 return d.offset;
107 })
108 .attr("stop-color", function (d) {
109 return d.color;
110 })
111 .attr("stop-opacity", function (d) {
112 return d.opacity;
113 });
114
115 bounds
116 .append("linearGradient")
117 .attr("id", "area-gradient2")
118 .attr("gradientUnits", "userSpaceOnUse")
119 .attr("x1", 0)
120 .attr("y1", yScale(0))
121 .attr("x2", 0)
122 .attr("y2", yScale(100))
123 .selectAll("stop")
124 .data([
125 { offset: "0%", color: "#bace3d", opacity: minOpacity },
126 { offset: "100%", color: "#bace3d", opacity: maxOpacity},
127 ])
128 .enter()
129 .append("stop")
130 .attr("offset", function (d) {
131 return d.offset;
132 })
133 .attr("stop-color", function (d) {
134 return d.color;
135 })
136 .attr("stop-opacity", function (d) {
137 return d.opacity;
138 });
139
140 const lineGenerator1 = d3
141 .line()
142 .x((d) => xScale(xAccessor(d)))
143 .y((d) => yScale(attacksAccessor(d)));
144 const lineGenerator2 = d3
145 .line()
146 .x((d) => xScale(xAccessor(d)))
147 .y((d) => yScale(attacksAccessor(d)));
148
149 const line1 = bounds
150 .append("path")
151 .datum(dataset)
152 .attr("d", lineGenerator1(dataset))
153 .attr("class", "area")
154 .attr("d", area1)
155 .style("fill", "url(#area-gradient1)");
156
157 const line2 = bounds
158 .append("path")
159 .datum(dataset)
160 .attr("d", lineGenerator2(dataset))
161 .attr("class", "area")
162 .attr("d", area2)
163 .style("fill", "url(#area-gradient2)");
164
165 const yAxisGenerator = d3.axisLeft().scale(yScale);
166 // const xAxisGenerator = d3.axisBottom().scale(xScale);
167
168 let dateFormat = (days <= 1) ? d3.timeFormat("%H:%M") : (days > 31) ? d3.timeFormat("%b %Y") : d3.timeFormat("%b %d");
169 const xAxisGenerator = (days <= 1) ? d3.axisBottom().scale(xScale).ticks(d3.timeHour.every(2)).tickFormat(dateFormat) :
170 (days > 31) ? d3.axisBottom().scale(xScale).ticks(d3.timeMonth.every(1)).tickFormat(dateFormat) :
171 (days <= 7) ? d3.axisBottom().scale(xScale).ticks(d3.timeDay.every(1)).tickFormat(dateFormat) :
172 d3.axisBottom().scale(xScale).ticks(9).tickFormat(dateFormat);
173 //const xAxisGenerator = d3.axisBottom().scale(xScale).ticks(ticks).tickFormat(dateFormat);
174
175 const yAxis = bounds.append("g").attr("class", "axis").call(yAxisGenerator);
176 const xAxis = bounds
177 .append("g")
178 .call(xAxisGenerator)
179 .attr("class", "axis chart-date")
180 .style("transform", `translateY(${dimensions.boundedHeight}px)`);
181
182 const listeningRect = bounds
183 .append("rect")
184 .attr("class", "listening-rect")
185 .attr("width", dimensions.boundedWidth)
186 .attr("height", dimensions.boundedHeight)
187 .on("mousemove", onMouseMove)
188 .on("mouseleave", onMouseLeave);
189
190 const tooltipAttacks = d3.select("#tooltipAttacks");
191 const tooltipBlocked = d3.select("#tooltipBlocked");
192 const tooltipCircle1 = bounds
193 .append("circle")
194 .attr("class", "tooltip-circle")
195 .attr("r", 4)
196 .attr("stroke", "#F3F5F6")
197 .attr("fill", "#1D293F")
198 .attr("stroke-width", 2)
199 .style("opacity", 0);
200 const tooltipCircle2 = bounds
201 .append("circle")
202 .attr("class", "tooltip-circle")
203 .attr("r", 4)
204 .attr("stroke", "#F3F5F6")
205 .attr("fill", "#1D293F")
206 .attr("stroke-width", 2)
207 .style("opacity", 0);
208 function onMouseMove() {
209 const mousePosition = d3.mouse(this);
210 const hoveredDate = xScale.invert(mousePosition[0]);
211
212 const getDistanceFromHoveredDate = (d) =>
213 Math.abs(xAccessor(d) - hoveredDate);
214 const closestIndex = d3.scan(
215 dataset,
216 (a, b) =>
217 getDistanceFromHoveredDate(a) - getDistanceFromHoveredDate(b)
218 );
219 const closestDataPoint = dataset[closestIndex];
220
221 const closestXValue = xAccessor(closestDataPoint);
222 const closestAttacksValue = attacksAccessor(closestDataPoint);
223 const closestBlockedValue = blockedAccessor(closestDataPoint);
224
225 if(closestAttacksValue || closestBlockedValue){
226 AmplitudeAnalytics.worldMap(closestAttacksValue, closestBlockedValue);
227 }
228
229 const x = xScale(closestXValue) + dimensions.margin.left + 8;
230 const yAttacks =
231 yScale(closestAttacksValue) + dimensions.margin.top + 10;
232 const yBlocked =
233 yScale(closestBlockedValue) + dimensions.margin.top + 10;
234
235 tooltipAttacks.style(
236 "transform",
237 `translate(` +
238 `calc( -50% + ${x}px),` +
239 `calc(-100% + ${yAttacks}px)` +
240 `)`
241 );
242 tooltipBlocked.style(
243 "transform",
244 `translate(` +
245 `calc( -50% + ${x}px),` +
246 `calc(-100% + ${yBlocked}px)` +
247 `)`
248 );
249
250 tooltipAttacks.style("opacity", 1);
251 tooltipBlocked.style("opacity", 1);
252
253 tooltipAttacks.select("#countAttacks").html(closestAttacksValue);
254 tooltipBlocked.select("#countBlocked").html(closestBlockedValue);
255 tooltipCircle1
256 .attr("cx", xScale(closestXValue))
257 .attr("cy", yScale(closestAttacksValue))
258 .style("opacity", 1);
259 tooltipCircle2
260 .attr("cx", xScale(closestXValue))
261 .attr("cy", yScale(closestBlockedValue))
262 .style("opacity", 1);
263 }
264
265 function onMouseLeave() {
266 tooltipAttacks.style("opacity", 0);
267 tooltipBlocked.style("opacity", 0);
268
269 tooltipCircle1.style("opacity", 0);
270 tooltipCircle2.style("opacity", 0);
271 }
272 }
273
274 const drawWafChart = (data) => {
275 var firewallChart = d3.select("#line-chart").selectAll("svg")
276 firewallChart = firewallChart.remove();
277 drawLineChart(data);
278 };
279
280 if(typeof waf_chart == "object"){
281 drawWafChart(waf_chart);
282 }
283
284 var resizeTimerFirewallChart;
285 window.onresize = function (event) {
286 clearTimeout(resizeTimerFirewallChart);
287 resizeTimerFirewallChart = setTimeout(function () {
288 drawLineChart(waf_chart);
289 }, 10);
290 };
291
292 // server-status
293 async function drawServerStatusChart(id, elementSelector, tooltipSelector, tooltipValueSelector, color, dataset) {
294 const dataAccessor = (d) => d.value;
295
296 let diagram = document.querySelector(elementSelector);
297 let days = diagram.dataset.days;
298
299 const dateParser = (days <= 1) ? d3.timeParse("%Y-%m-%d %H:%m:%M"): d3.timeParse("%Y-%m-%d");
300
301 const xAccessor = (d) => dateParser(d.date);
302
303 const chartWrapper = document.querySelector(elementSelector);
304 let dimensions = {
305 width: chartWrapper.offsetWidth,
306 height: 251,
307 margin: {
308 top: 15,
309 right: 15,
310 bottom: 40,
311 left: 60,
312 },
313 };
314 dimensions.boundedWidth =
315 dimensions.width - dimensions.margin.left - dimensions.margin.right;
316 dimensions.boundedHeight =
317 dimensions.height - dimensions.margin.top - dimensions.margin.bottom;
318
319 const wrapper = d3
320 .select(elementSelector)
321 .append("svg")
322 .attr("width", dimensions.width)
323 .attr("height", dimensions.height);
324
325 const bounds = wrapper
326 .append("g")
327 .style(
328 "transform",
329 `translate(${dimensions.margin.left - 10}px, ${
330 dimensions.margin.top
331 }px)`
332 );
333
334 const yValues = dataset.reduce(
335 (acc, curr) => [...acc, curr.value],
336 [0, 100]
337 );
338
339 const yScale = d3
340 .scaleLinear()
341 .domain(d3.extent(yValues))
342 .range([dimensions.boundedHeight, 0]);
343 const xScale = d3
344 .scaleTime()
345 .domain(d3.extent(dataset, xAccessor))
346 .range([0, dimensions.boundedWidth]);
347
348 function make_y_gridlines() {
349 return d3.axisLeft(yScale).ticks(5);
350 }
351
352 bounds
353 .append("g")
354 .attr("class", "grid")
355 .call(
356 make_y_gridlines().tickSize(-dimensions.boundedWidth).tickFormat("")
357 );
358
359 const area1 = d3
360 .area()
361 .x((d) => xScale(xAccessor(d)))
362 .y0(yScale(0))
363 .y1((d) => yScale(dataAccessor(d)));
364
365 const gradientAreaId = "area-gradient-" + id;
366
367 const isDarkTheme = isDarkThemeSet();
368 const minOpacity = isDarkTheme ? 0.2 : 0.1;
369 const maxOpacity = isDarkTheme ? 0.8 : 0.6;
370
371 bounds
372 .append("linearGradient")
373 .attr("id", gradientAreaId)
374 .attr("gradientUnits", "userSpaceOnUse")
375 .attr("x1", 0)
376 .attr("y1", yScale(0))
377 .attr("x2", 0)
378 .attr("y2", yScale(100))
379 .selectAll("stop")
380 .data([
381 { offset: "0%", color: color, opacity: minOpacity },
382 { offset: "100%", color: color, opacity: maxOpacity },
383 ])
384 .enter()
385 .append("stop")
386 .attr("offset", function (d) {
387 return d.offset;
388 })
389 .attr("stop-color", function (d) {
390 return d.color;
391 })
392 .attr("stop-opacity", function (d) {
393 return d.opacity;
394 });
395
396 const lineGenerator1 = d3
397 .line()
398 .x((d) => xScale(xAccessor(d)))
399 .y((d) => yScale(dataAccessor(d)));
400
401 const line1 = bounds
402 .append("path")
403 .datum(dataset)
404 .attr("d", lineGenerator1(dataset))
405 .attr("class", "area")
406 .attr("d", area1)
407 .style("fill", "url(#"+gradientAreaId+")");
408
409 const yAxisGenerator = d3.axisLeft().scale(yScale);
410 // const xAxisGenerator = d3.axisBottom().scale(xScale);
411 let dateFormat = (days <= 1) ? d3.timeFormat("%H:%M") : (days > 31) ? d3.timeFormat("%b %Y") : d3.timeFormat("%b %d");
412 const xAxisGenerator = (days <= 1) ? d3.axisBottom().scale(xScale).ticks(d3.timeHour.every(2)).tickFormat(dateFormat) :
413 (days > 31) ? d3.axisBottom().scale(xScale).ticks(d3.timeMonth.every(1)).tickFormat(dateFormat) :
414 (days <= 7) ? d3.axisBottom().scale(xScale).ticks(d3.timeDay.every(1)).tickFormat(dateFormat) :
415 d3.axisBottom().scale(xScale).ticks(9).tickFormat(dateFormat);
416
417 const yAxis = bounds.append("g").attr("class", "axis").call(yAxisGenerator);
418 const xAxis = bounds
419 .append("g")
420 .call(xAxisGenerator)
421 .attr("class", "axis")
422 .style("transform", `translateY(${dimensions.boundedHeight}px)`);
423
424 const listeningRect = bounds
425 .append("rect")
426 .attr("class", "listening-rect")
427 .attr("width", dimensions.boundedWidth)
428 .attr("height", dimensions.boundedHeight)
429 .on("mousemove", onMouseMove)
430 .on("mouseleave", onMouseLeave);
431
432 const tooltipData = d3.select(tooltipSelector);
433 const tooltipCircle1 = bounds
434 .append("circle")
435 .attr("class", "tooltip-circle")
436 .attr("r", 4)
437 .attr("stroke", "#F3F5F6")
438 .attr("fill", "#1D293F")
439 .attr("stroke-width", 2)
440 .style("opacity", 0);
441
442 function onMouseMove() {
443 const mousePosition = d3.mouse(this);
444 const hoveredDate = xScale.invert(mousePosition[0]);
445
446 const getDistanceFromHoveredDate = (d) =>
447 Math.abs(xAccessor(d) - hoveredDate);
448 const closestIndex = d3.scan(
449 dataset,
450 (a, b) =>
451 getDistanceFromHoveredDate(a) - getDistanceFromHoveredDate(b)
452 );
453 const closestDataPoint = dataset[closestIndex];
454
455 const closestXValue = xAccessor(closestDataPoint);
456 const closestValue = dataAccessor(closestDataPoint);
457
458 const x = xScale(closestXValue) + dimensions.margin.left + 8;
459 const yAttacks =
460 yScale(closestValue) + dimensions.margin.top + 10;
461
462 tooltipData.style(
463 "transform",
464 `translate(` +
465 `calc( -50% + ${x}px),` +
466 `calc(-100% + ${yAttacks}px)` +
467 `)`
468 );
469
470 tooltipData.style("opacity", 1);
471
472 tooltipData.select(tooltipValueSelector).html(closestValue);
473 tooltipCircle1
474 .attr("cx", xScale(closestXValue))
475 .attr("cy", yScale(closestValue))
476 .style("opacity", 1);
477 }
478
479 function onMouseLeave() {
480 tooltipData.style("opacity", 0);
481 tooltipCircle1.style("opacity", 0);
482 }
483 }
484
485 const drawRamChart = (data) => {
486 const ramChartSelector = "#ram-chart";
487 const ramTooltipSelector = "#tooltipRam";
488 const ramTooltipValueSelector = "#countRam";
489 const ramChartColor = "#3d50df";
490
491
492 let chartRam = d3.select(ramChartSelector).selectAll("svg")
493 chartRam = chartRam.remove();
494
495 drawServerStatusChart("ram", ramChartSelector, ramTooltipSelector, ramTooltipValueSelector, ramChartColor, data);
496 }
497
498
499 if(typeof ram_chart == "object"){
500 drawRamChart(ram_chart);
501 }
502
503
504 const drawCpuChart = (data) => {
505 const cpuChartSelector = "#cpu-chart";
506 const cpuTooltipSelector = "#tooltipCpu";
507 const cpuTooltipValueSelector = "#countCpu";
508 const cpuChartColor = "#6d3594";
509
510 let chartCpu = d3.select(cpuChartSelector).selectAll("svg");
511 chartCpu = chartCpu.remove();
512
513 drawServerStatusChart("cpu", cpuChartSelector, cpuTooltipSelector, cpuTooltipValueSelector, cpuChartColor, data);
514 }
515
516 if(typeof cpu_chart == "object") {
517 drawCpuChart(cpu_chart);
518 }
519
520
521 var resizeTimerRamChart;
522 var resizeTimerCpuChart;
523
524 window.onresize = function (event) {
525
526 if (document.querySelector("#ram-chart") !== null) {
527 clearTimeout(resizeTimerRamChart);
528 resizeTimerRamChart = setTimeout(function () {
529 if(typeof ram_chart == "object") {
530 drawRamChart(ram_chart);
531 }
532 }, 10);
533 }
534
535 if (document.querySelector("#cpu-chart") !== null) {
536 clearTimeout(resizeTimerCpuChart);
537 resizeTimerCpuChart = setTimeout(function () {
538 if(typeof cpu_chart == "object") {
539 drawCpuChart(cpu_chart);
540 }
541 }, 10);
542 }
543 };
544
545
546 const colorModeToggle = document.querySelector("#color_scheme_toggle");
547 if(colorModeToggle){
548 const addThemeChangeEventListener = (callback)=>{
549 colorModeToggle.addEventListener("change", callback)
550 }
551
552 addThemeChangeEventListener(()=>{
553 if(typeof cpu_chart == "object") {
554 drawCpuChart(cpu_chart);
555 }
556 if(typeof ram_chart == "object") {
557 drawRamChart(ram_chart);
558 }
559 if(typeof attacks_map == "object"){
560 attacksMap();
561 }
562 });
563 }
564
565 // disk-chart
566
567 async function drawDiskChart_(elementSelector, data) {
568 // set the dimensions and margins of the graph
569 var width = 150
570 height = 150
571 margin = 1
572
573 // The radius of the pieplot is half the width or half the height (smallest one). I subtract a bit of margin.
574 var radius = Math.min(width, height) / 2 - margin
575
576 // append the svg object to the div called 'my_dataviz'
577 var svg = d3.select(elementSelector)
578 .append("svg")
579 .attr("width", width)
580 .attr("height", height)
581 .append("g")
582 .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
583
584 // Create dummy data
585 // var data = {a: 9, b: 20, c:30, d:8, e:12}
586
587 // set the color scale
588 var color = d3.scaleOrdinal()
589 .domain(data)
590 .range(["#5E6977", "#3D50DF"])
591
592 // Compute the position of each group on the pie:
593 var pie = d3.pie()
594 .value(function(d) {return d.value; })
595 var data_ready = pie(d3.entries(data))
596
597 // Build the pie chart: Basically, each part of the pie is a path that we build using the arc function.
598 svg
599 .selectAll('whatever')
600 .data(data_ready)
601 .enter()
602 .append('path')
603 .attr('d', d3.arc()
604 .innerRadius(30) // This is the size of the donut hole
605 .outerRadius(radius)
606 )
607 .attr('fill', function(d){ return(color(d.data.key)) })
608 .attr("stroke", "white")
609 .style("stroke-width", "15px")
610 .style("opacity", 1)
611
612 }
613
614
615 const drawDiskChart = (data) => {
616 const diskData = {use: data.used, free: data.free};
617 const discChartSelector = "#disk-chart";
618 drawDiskChart_(discChartSelector, diskData);
619 };
620
621 if(typeof disc_chart == "object") {
622 drawDiskChart(disc_chart);
623 }
624
625 /**
626 * Create chart "Attacks on world map"
627 * @returns {Promise<void>}
628 */
629 async function attacksMap() {
630
631 var countries = attacks_map['countries'];
632 var labels = attacks_map['labels'];
633 new Chart(document.getElementById("firewall"), {
634 type: "horizontalBar",
635
636 data: {
637 labels: labels,
638 datasets: [
639 {
640 backgroundColor: "#3D50DF",
641 data: attacks_map['attacks'],
642 },
643 ],
644 },
645 options: {
646 cornerRadius: 3,
647 maintainAspectRatio: false,
648 scales: {
649 yAxes: [
650 {
651 barPercentage: 0.6,
652 stacked: true,
653 gridLines: {
654 display: true,
655 },
656 },
657 ],
658 xAxes: [
659 {
660 gridLines: {
661 display: false,
662 },
663 },
664 ],
665 },
666 legend: {
667 display: false,
668 },
669 },
670 });
671
672 const fill = (country) => {
673 svg._groups[0][0].childNodes[0].childNodes.forEach((e) => {
674 if (e.__data__.properties.name === country) {
675 d3.select(e).style("fill", "#3D50DF");
676 }
677 });
678 };
679 // The svg
680 var svg = d3.select("#firewallMap"),
681 width = +svg.attr("width"),
682 height = +svg.attr("height");
683
684 // Map and projection
685 var path = d3.geoPath();
686 var projection = d3
687 .geoMercator()
688 .scale(60)
689 .center([0, 0])
690 .translate([210, 220]);
691
692 // Load external data and boot
693 d3.queue().defer(d3.json, world_map_json).await(ready);
694
695 function ready(error, topo) {
696
697 // Draw the map
698 svg.append("g")
699 .selectAll("path")
700 .data(topo.features)
701 .enter()
702 .append("path")
703 // draw each country
704 .attr("d", d3.geoPath().projection(projection))
705 // set the color of each country
706 .attr("fill", function () {
707 return "#5E6977";
708 })
709 .style("stroke", "transparent")
710 .attr("class", function () {
711 return "Country";
712 });
713 countries.map((e) => {
714 fill(e);
715 });
716 }
717
718
719 Chart.elements.Rectangle.prototype.draw = function () {
720 function t(t) {
721 return s[(f + t) % 4];
722 }
723 var r,
724 e,
725 i,
726 o,
727 _,
728 h,
729 l,
730 a,
731 b = this._chart.ctx,
732 d = this._view,
733 n = d.borderWidth,
734 u = this._chart.config.options.cornerRadius;
735 if (
736 (u < 0 && (u = 0),
737 void 0 === u && (u = 0),
738 d.horizontal
739 ? ((r = d.base),
740 (e = d.x),
741 (i = d.y - d.height / 2),
742 (o = d.y + d.height / 2),
743 (_ = e > r ? 1 : -1),
744 (h = 1),
745 (l = d.borderSkipped || "left"))
746 : ((r = d.x - d.width / 2),
747 (e = d.x + d.width / 2),
748 (i = d.y),
749 (_ = 1),
750 (h = (o = d.base) > i ? 1 : -1),
751 (l = d.borderSkipped || "bottom")),
752 n)
753 ) {
754 var T = Math.min(Math.abs(r - e), Math.abs(i - o)),
755 v = (n = n > T ? T : n) / 2,
756 g = r + ("left" !== l ? v * _ : 0),
757 c = e + ("right" !== l ? -v * _ : 0),
758 C = i + ("top" !== l ? v * h : 0),
759 w = o + ("bottom" !== l ? -v * h : 0);
760 g !== c && ((i = C), (o = w)),
761 C !== w && ((r = g), (e = c));
762 }
763 b.beginPath(),
764 (b.fillStyle = d.backgroundColor),
765 (b.strokeStyle = d.borderColor),
766 (b.lineWidth = n);
767 var s = [
768 [r, o],
769 [r, i],
770 [e, i],
771 [e, o],
772 ],
773 f = ["bottom", "left", "top", "right"].indexOf(l, 0);
774 -1 === f && (f = 0);
775 var q = t(0);
776 b.moveTo(q[0], q[1]);
777 for (var m = 1; m < 4; m++)
778 (q = t(m)),
779 (nextCornerId = m + 1),
780 4 == nextCornerId && (nextCornerId = 0),
781 (nextCorner = t(nextCornerId)),
782 (width = s[2][0] - s[1][0]),
783 (height = s[0][1] - s[1][1]),
784 (x = s[1][0]),
785 (y = s[1][1]),
786 (a = u) > Math.abs(height) / 2 &&
787 (a = Math.floor(Math.abs(height) / 2)),
788 a > Math.abs(width) / 2 &&
789 (a = Math.floor(Math.abs(width) / 2)),
790 height < 0
791 ? ((x_tl = x),
792 (x_tr = x + width),
793 (y_tl = y + height),
794 (y_tr = y + height),
795 (x_bl = x),
796 (x_br = x + width),
797 (y_bl = y),
798 (y_br = y),
799 b.moveTo(x_bl + a, y_bl),
800 b.lineTo(x_br - a, y_br),
801 b.quadraticCurveTo(x_br, y_br, x_br, y_br - a),
802 b.lineTo(x_tr, y_tr + a),
803 b.quadraticCurveTo(x_tr, y_tr, x_tr - a, y_tr),
804 b.lineTo(x_tl + a, y_tl),
805 b.quadraticCurveTo(x_tl, y_tl, x_tl, y_tl + a),
806 b.lineTo(x_bl, y_bl - a),
807 b.quadraticCurveTo(x_bl, y_bl, x_bl + a, y_bl))
808 : width < 0
809 ? ((x_tl = x + width),
810 (x_tr = x),
811 (y_tl = y),
812 (y_tr = y),
813 (x_bl = x + width),
814 (x_br = x),
815 (y_bl = y + height),
816 (y_br = y + height),
817 b.moveTo(x_bl + a, y_bl),
818 b.lineTo(x_br - a, y_br),
819 b.quadraticCurveTo(x_br, y_br, x_br, y_br - a),
820 b.lineTo(x_tr, y_tr + a),
821 b.quadraticCurveTo(x_tr, y_tr, x_tr - a, y_tr),
822 b.lineTo(x_tl + a, y_tl),
823 b.quadraticCurveTo(x_tl, y_tl, x_tl, y_tl + a),
824 b.lineTo(x_bl, y_bl - a),
825 b.quadraticCurveTo(x_bl, y_bl, x_bl + a, y_bl))
826 : (b.moveTo(x + a, y),
827 b.lineTo(x + width - a, y),
828 b.quadraticCurveTo(
829 x + width,
830 y,
831 x + width,
832 y + a
833 ),
834 b.lineTo(x + width, y + height - a),
835 b.quadraticCurveTo(
836 x + width,
837 y + height,
838 x + width - a,
839 y + height
840 ),
841 b.lineTo(x + a, y + height),
842 b.quadraticCurveTo(
843 x,
844 y + height,
845 x,
846 y + height - a
847 ),
848 b.lineTo(x, y + a),
849 b.quadraticCurveTo(x, y, x + a, y));
850 b.fill(), n && b.stroke();
851 };
852 }
853
854 if(typeof attacks_map == "object"){
855 attacksMap();
856 }
857