WordPress Zero Spam - Version 5.2.12

Version Description

Download this release

Release Info

Developer bmarshall511
Plugin Icon 128x128 WordPress Zero Spam
Version 5.2.12
Comparing to
See all releases

Code changes from version 5.2.11 to 5.2.12

Files changed (41) hide show
  1. assets/js/Chart.bundle.min.js +11133 -9
  2. core/admin/class-admin.php +13 -13
  3. core/admin/class-dashboard.php +41 -51
  4. core/admin/class-settings.php +16 -16
  5. core/admin/tables/class-blockedlocations.php +28 -58
  6. core/admin/tables/class-blockedtable.php +17 -17
  7. core/admin/tables/class-logtable.php +21 -21
  8. core/class-access.php +2 -2
  9. core/class-settings.php +44 -44
  10. core/class-utilities.php +2 -2
  11. includes/class-cli.php +2 -2
  12. includes/class-plugin.php +4 -4
  13. includes/templates/admin-block-ip.php +17 -17
  14. includes/templates/admin-callout.php +12 -12
  15. includes/templates/admin-ips.php +5 -5
  16. includes/templates/admin-line-chart.php +2 -2
  17. includes/templates/admin-map.php +2 -2
  18. includes/templates/admin-modal-details.php +13 -13
  19. includes/templates/admin-pie.php +2 -2
  20. includes/templates/settings/errors.php +3 -3
  21. includes/templates/settings/export.php +9 -9
  22. modules/class-debug.php +6 -6
  23. modules/class-google.php +4 -4
  24. modules/class-ipinfomodule.php +8 -8
  25. modules/class-ipstack.php +12 -12
  26. modules/class-projecthoneypot.php +13 -13
  27. modules/class-stopforumspam.php +15 -15
  28. modules/class-zerospam.php +20 -20
  29. modules/comments/class-comments.php +10 -10
  30. modules/contactform7/class-contactform7.php +10 -10
  31. modules/davidwalsh/class-davidwalsh.php +7 -7
  32. modules/fluentforms/class-fluentforms.php +10 -10
  33. modules/formidable/class-formidable.php +10 -10
  34. modules/give/class-give.php +10 -10
  35. modules/login/class-login.php +10 -10
  36. modules/mailchimpforwp/class-mailchimpforwp.php +10 -10
  37. modules/memberpress/class-memberpress.php +20 -20
  38. modules/registration/class-registration.php +10 -10
  39. modules/wpforms/class-wpforms.php +10 -10
  40. readme.txt +25 -21
  41. wordpress-zero-spam.php +12 -12
assets/js/Chart.bundle.min.js CHANGED
@@ -1,13 +1,11137 @@
1
  /*!
2
- * Chart.js v3.5.0
3
  * https://www.chartjs.org
4
- * (c) 2021 Chart.js Contributors
5
  * Released under the MIT License
6
  */
7
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Chart=e()}(this,(function(){"use strict";const t="undefined"==typeof window?function(t){return t()}:window.requestAnimationFrame;function e(e,i,n){const o=n||(t=>Array.prototype.slice.call(t));let s=!1,a=[];return function(...n){a=o(n),s||(s=!0,t.call(window,(()=>{s=!1,e.apply(i,a)})))}}function i(t,e){let i;return function(){return e?(clearTimeout(i),i=setTimeout(t,e)):t(),e}}const n=t=>"start"===t?"left":"end"===t?"right":"center",o=(t,e,i)=>"start"===t?e:"end"===t?i:(e+i)/2,s=(t,e,i,n)=>t===(n?"left":"right")?i:"center"===t?(e+i)/2:e;var a=new class{constructor(){this._request=null,this._charts=new Map,this._running=!1,this._lastDate=void 0}_notify(t,e,i,n){const o=e.listeners[n],s=e.duration;o.forEach((n=>n({chart:t,initial:e.initial,numSteps:s,currentStep:Math.min(i-e.start,s)})))}_refresh(){const e=this;e._request||(e._running=!0,e._request=t.call(window,(()=>{e._update(),e._request=null,e._running&&e._refresh()})))}_update(t=Date.now()){const e=this;let i=0;e._charts.forEach(((n,o)=>{if(!n.running||!n.items.length)return;const s=n.items;let a,r=s.length-1,l=!1;for(;r>=0;--r)a=s[r],a._active?(a._total>n.duration&&(n.duration=a._total),a.tick(t),l=!0):(s[r]=s[s.length-1],s.pop());l&&(o.draw(),e._notify(o,n,t,"progress")),s.length||(n.running=!1,e._notify(o,n,t,"complete"),n.initial=!1),i+=s.length})),e._lastDate=t,0===i&&(e._running=!1)}_getAnims(t){const e=this._charts;let i=e.get(t);return i||(i={running:!1,initial:!0,items:[],listeners:{complete:[],progress:[]}},e.set(t,i)),i}listen(t,e,i){this._getAnims(t).listeners[e].push(i)}add(t,e){e&&e.length&&this._getAnims(t).items.push(...e)}has(t){return this._getAnims(t).items.length>0}start(t){const e=this._charts.get(t);e&&(e.running=!0,e.start=Date.now(),e.duration=e.items.reduce(((t,e)=>Math.max(t,e._duration)),0),this._refresh())}running(t){if(!this._running)return!1;const e=this._charts.get(t);return!!(e&&e.running&&e.items.length)}stop(t){const e=this._charts.get(t);if(!e||!e.items.length)return;const i=e.items;let n=i.length-1;for(;n>=0;--n)i[n].cancel();e.items=[],this._notify(t,e,Date.now(),"complete")}remove(t){return this._charts.delete(t)}};
8
- /*!
9
- * @kurkle/color v0.1.9
10
- * https://github.com/kurkle/color#readme
11
- * (c) 2020 Jukka Kurkela
12
- * Released under the MIT License
13
- */const r={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:10,B:11,C:12,D:13,E:14,F:15,a:10,b:11,c:12,d:13,e:14,f:15},l="0123456789ABCDEF",c=t=>l[15&t],h=t=>l[(240&t)>>4]+l[15&t],d=t=>(240&t)>>4==(15&t);function u(t){var e=function(t){return d(t.r)&&d(t.g)&&d(t.b)&&d(t.a)}(t)?c:h;return t?"#"+e(t.r)+e(t.g)+e(t.b)+(t.a<255?e(t.a):""):t}function f(t){return t+.5|0}const g=(t,e,i)=>Math.max(Math.min(t,i),e);function p(t){return g(f(2.55*t),0,255)}function m(t){return g(f(255*t),0,255)}function x(t){return g(f(t/2.55)/100,0,1)}function b(t){return g(f(100*t),0,100)}const _=/^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/;const y=/^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;function v(t,e,i){const n=e*Math.min(i,1-i),o=(e,o=(e+t/30)%12)=>i-n*Math.max(Math.min(o-3,9-o,1),-1);return[o(0),o(8),o(4)]}function w(t,e,i){const n=(n,o=(n+t/60)%6)=>i-i*e*Math.max(Math.min(o,4-o,1),0);return[n(5),n(3),n(1)]}function M(t,e,i){const n=v(t,1,.5);let o;for(e+i>1&&(o=1/(e+i),e*=o,i*=o),o=0;o<3;o++)n[o]*=1-e-i,n[o]+=e;return n}function k(t){const e=t.r/255,i=t.g/255,n=t.b/255,o=Math.max(e,i,n),s=Math.min(e,i,n),a=(o+s)/2;let r,l,c;return o!==s&&(c=o-s,l=a>.5?c/(2-o-s):c/(o+s),r=o===e?(i-n)/c+(i<n?6:0):o===i?(n-e)/c+2:(e-i)/c+4,r=60*r+.5),[0|r,l||0,a]}function S(t,e,i,n){return(Array.isArray(e)?t(e[0],e[1],e[2]):t(e,i,n)).map(m)}function P(t,e,i){return S(v,t,e,i)}function D(t){return(t%360+360)%360}function C(t){const e=y.exec(t);let i,n=255;if(!e)return;e[5]!==i&&(n=e[6]?p(+e[5]):m(+e[5]));const o=D(+e[2]),s=+e[3]/100,a=+e[4]/100;return i="hwb"===e[1]?function(t,e,i){return S(M,t,e,i)}(o,s,a):"hsv"===e[1]?function(t,e,i){return S(w,t,e,i)}(o,s,a):P(o,s,a),{r:i[0],g:i[1],b:i[2],a:n}}const O={x:"dark",Z:"light",Y:"re",X:"blu",W:"gr",V:"medium",U:"slate",A:"ee",T:"ol",S:"or",B:"ra",C:"lateg",D:"ights",R:"in",Q:"turquois",E:"hi",P:"ro",O:"al",N:"le",M:"de",L:"yello",F:"en",K:"ch",G:"arks",H:"ea",I:"ightg",J:"wh"},T={OiceXe:"f0f8ff",antiquewEte:"faebd7",aqua:"ffff",aquamarRe:"7fffd4",azuY:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"0",blanKedOmond:"ffebcd",Xe:"ff",XeviTet:"8a2be2",bPwn:"a52a2a",burlywood:"deb887",caMtXe:"5f9ea0",KartYuse:"7fff00",KocTate:"d2691e",cSO:"ff7f50",cSnflowerXe:"6495ed",cSnsilk:"fff8dc",crimson:"dc143c",cyan:"ffff",xXe:"8b",xcyan:"8b8b",xgTMnPd:"b8860b",xWay:"a9a9a9",xgYF:"6400",xgYy:"a9a9a9",xkhaki:"bdb76b",xmagFta:"8b008b",xTivegYF:"556b2f",xSange:"ff8c00",xScEd:"9932cc",xYd:"8b0000",xsOmon:"e9967a",xsHgYF:"8fbc8f",xUXe:"483d8b",xUWay:"2f4f4f",xUgYy:"2f4f4f",xQe:"ced1",xviTet:"9400d3",dAppRk:"ff1493",dApskyXe:"bfff",dimWay:"696969",dimgYy:"696969",dodgerXe:"1e90ff",fiYbrick:"b22222",flSOwEte:"fffaf0",foYstWAn:"228b22",fuKsia:"ff00ff",gaRsbSo:"dcdcdc",ghostwEte:"f8f8ff",gTd:"ffd700",gTMnPd:"daa520",Way:"808080",gYF:"8000",gYFLw:"adff2f",gYy:"808080",honeyMw:"f0fff0",hotpRk:"ff69b4",RdianYd:"cd5c5c",Rdigo:"4b0082",ivSy:"fffff0",khaki:"f0e68c",lavFMr:"e6e6fa",lavFMrXsh:"fff0f5",lawngYF:"7cfc00",NmoncEffon:"fffacd",ZXe:"add8e6",ZcSO:"f08080",Zcyan:"e0ffff",ZgTMnPdLw:"fafad2",ZWay:"d3d3d3",ZgYF:"90ee90",ZgYy:"d3d3d3",ZpRk:"ffb6c1",ZsOmon:"ffa07a",ZsHgYF:"20b2aa",ZskyXe:"87cefa",ZUWay:"778899",ZUgYy:"778899",ZstAlXe:"b0c4de",ZLw:"ffffe0",lime:"ff00",limegYF:"32cd32",lRF:"faf0e6",magFta:"ff00ff",maPon:"800000",VaquamarRe:"66cdaa",VXe:"cd",VScEd:"ba55d3",VpurpN:"9370db",VsHgYF:"3cb371",VUXe:"7b68ee",VsprRggYF:"fa9a",VQe:"48d1cc",VviTetYd:"c71585",midnightXe:"191970",mRtcYam:"f5fffa",mistyPse:"ffe4e1",moccasR:"ffe4b5",navajowEte:"ffdead",navy:"80",Tdlace:"fdf5e6",Tive:"808000",TivedBb:"6b8e23",Sange:"ffa500",SangeYd:"ff4500",ScEd:"da70d6",pOegTMnPd:"eee8aa",pOegYF:"98fb98",pOeQe:"afeeee",pOeviTetYd:"db7093",papayawEp:"ffefd5",pHKpuff:"ffdab9",peru:"cd853f",pRk:"ffc0cb",plum:"dda0dd",powMrXe:"b0e0e6",purpN:"800080",YbeccapurpN:"663399",Yd:"ff0000",Psybrown:"bc8f8f",PyOXe:"4169e1",saddNbPwn:"8b4513",sOmon:"fa8072",sandybPwn:"f4a460",sHgYF:"2e8b57",sHshell:"fff5ee",siFna:"a0522d",silver:"c0c0c0",skyXe:"87ceeb",UXe:"6a5acd",UWay:"708090",UgYy:"708090",snow:"fffafa",sprRggYF:"ff7f",stAlXe:"4682b4",tan:"d2b48c",teO:"8080",tEstN:"d8bfd8",tomato:"ff6347",Qe:"40e0d0",viTet:"ee82ee",JHt:"f5deb3",wEte:"ffffff",wEtesmoke:"f5f5f5",Lw:"ffff00",LwgYF:"9acd32"};let A;function L(t){A||(A=function(){const t={},e=Object.keys(T),i=Object.keys(O);let n,o,s,a,r;for(n=0;n<e.length;n++){for(a=r=e[n],o=0;o<i.length;o++)s=i[o],r=r.replace(s,O[s]);s=parseInt(T[a],16),t[r]=[s>>16&255,s>>8&255,255&s]}return t}(),A.transparent=[0,0,0,0]);const e=A[t.toLowerCase()];return e&&{r:e[0],g:e[1],b:e[2],a:4===e.length?e[3]:255}}function R(t,e,i){if(t){let n=k(t);n[e]=Math.max(0,Math.min(n[e]+n[e]*i,0===e?360:1)),n=P(n),t.r=n[0],t.g=n[1],t.b=n[2]}}function E(t,e){return t?Object.assign(e||{},t):t}function I(t){var e={r:0,g:0,b:0,a:255};return Array.isArray(t)?t.length>=3&&(e={r:t[0],g:t[1],b:t[2],a:255},t.length>3&&(e.a=m(t[3]))):(e=E(t,{r:0,g:0,b:0,a:1})).a=m(e.a),e}function z(t){return"r"===t.charAt(0)?function(t){const e=_.exec(t);let i,n,o,s=255;if(e){if(e[7]!==i){const t=+e[7];s=255&(e[8]?p(t):255*t)}return i=+e[1],n=+e[3],o=+e[5],i=255&(e[2]?p(i):i),n=255&(e[4]?p(n):n),o=255&(e[6]?p(o):o),{r:i,g:n,b:o,a:s}}}(t):C(t)}class F{constructor(t){if(t instanceof F)return t;const e=typeof t;let i;var n,o,s;"object"===e?i=I(t):"string"===e&&(s=(n=t).length,"#"===n[0]&&(4===s||5===s?o={r:255&17*r[n[1]],g:255&17*r[n[2]],b:255&17*r[n[3]],a:5===s?17*r[n[4]]:255}:7!==s&&9!==s||(o={r:r[n[1]]<<4|r[n[2]],g:r[n[3]]<<4|r[n[4]],b:r[n[5]]<<4|r[n[6]],a:9===s?r[n[7]]<<4|r[n[8]]:255})),i=o||L(t)||z(t)),this._rgb=i,this._valid=!!i}get valid(){return this._valid}get rgb(){var t=E(this._rgb);return t&&(t.a=x(t.a)),t}set rgb(t){this._rgb=I(t)}rgbString(){return this._valid?(t=this._rgb)&&(t.a<255?`rgba(${t.r}, ${t.g}, ${t.b}, ${x(t.a)})`:`rgb(${t.r}, ${t.g}, ${t.b})`):this._rgb;var t}hexString(){return this._valid?u(this._rgb):this._rgb}hslString(){return this._valid?function(t){if(!t)return;const e=k(t),i=e[0],n=b(e[1]),o=b(e[2]);return t.a<255?`hsla(${i}, ${n}%, ${o}%, ${x(t.a)})`:`hsl(${i}, ${n}%, ${o}%)`}(this._rgb):this._rgb}mix(t,e){const i=this;if(t){const n=i.rgb,o=t.rgb;let s;const a=e===s?.5:e,r=2*a-1,l=n.a-o.a,c=((r*l==-1?r:(r+l)/(1+r*l))+1)/2;s=1-c,n.r=255&c*n.r+s*o.r+.5,n.g=255&c*n.g+s*o.g+.5,n.b=255&c*n.b+s*o.b+.5,n.a=a*n.a+(1-a)*o.a,i.rgb=n}return i}clone(){return new F(this.rgb)}alpha(t){return this._rgb.a=m(t),this}clearer(t){return this._rgb.a*=1-t,this}greyscale(){const t=this._rgb,e=f(.3*t.r+.59*t.g+.11*t.b);return t.r=t.g=t.b=e,this}opaquer(t){return this._rgb.a*=1+t,this}negate(){const t=this._rgb;return t.r=255-t.r,t.g=255-t.g,t.b=255-t.b,this}lighten(t){return R(this._rgb,2,t),this}darken(t){return R(this._rgb,2,-t),this}saturate(t){return R(this._rgb,1,t),this}desaturate(t){return R(this._rgb,1,-t),this}rotate(t){return function(t,e){var i=k(t);i[0]=D(i[0]+e),i=P(i),t.r=i[0],t.g=i[1],t.b=i[2]}(this._rgb,t),this}}function B(t){return new F(t)}const V=t=>t instanceof CanvasGradient||t instanceof CanvasPattern;function W(t){return V(t)?t:B(t)}function N(t){return V(t)?t:B(t).saturate(.5).darken(.1).hexString()}function H(){}const j=function(){let t=0;return function(){return t++}}();function $(t){return null==t}function Y(t){if(Array.isArray&&Array.isArray(t))return!0;const e=Object.prototype.toString.call(t);return"[object"===e.substr(0,7)&&"Array]"===e.substr(-6)}function U(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)}const X=t=>("number"==typeof t||t instanceof Number)&&isFinite(+t);function q(t,e){return X(t)?t:e}function K(t,e){return void 0===t?e:t}const G=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100:t/e,Z=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100*e:+t;function Q(t,e,i){if(t&&"function"==typeof t.call)return t.apply(i,e)}function J(t,e,i,n){let o,s,a;if(Y(t))if(s=t.length,n)for(o=s-1;o>=0;o--)e.call(i,t[o],o);else for(o=0;o<s;o++)e.call(i,t[o],o);else if(U(t))for(a=Object.keys(t),s=a.length,o=0;o<s;o++)e.call(i,t[a[o]],a[o])}function tt(t,e){let i,n,o,s;if(!t||!e||t.length!==e.length)return!1;for(i=0,n=t.length;i<n;++i)if(o=t[i],s=e[i],o.datasetIndex!==s.datasetIndex||o.index!==s.index)return!1;return!0}function et(t){if(Y(t))return t.map(et);if(U(t)){const e=Object.create(null),i=Object.keys(t),n=i.length;let o=0;for(;o<n;++o)e[i[o]]=et(t[i[o]]);return e}return t}function it(t){return-1===["__proto__","prototype","constructor"].indexOf(t)}function nt(t,e,i,n){if(!it(t))return;const o=e[t],s=i[t];U(o)&&U(s)?ot(o,s,n):e[t]=et(s)}function ot(t,e,i){const n=Y(e)?e:[e],o=n.length;if(!U(t))return t;const s=(i=i||{}).merger||nt;for(let a=0;a<o;++a){if(!U(e=n[a]))continue;const o=Object.keys(e);for(let n=0,a=o.length;n<a;++n)s(o[n],t,e,i)}return t}function st(t,e){return ot(t,e,{merger:at})}function at(t,e,i){if(!it(t))return;const n=e[t],o=i[t];U(n)&&U(o)?st(n,o):Object.prototype.hasOwnProperty.call(e,t)||(e[t]=et(o))}function rt(t,e){const i=t.indexOf(".",e);return-1===i?t.length:i}function lt(t,e){if(""===e)return t;let i=0,n=rt(e,i);for(;t&&n>i;)t=t[e.substr(i,n-i)],i=n+1,n=rt(e,i);return t}function ct(t){return t.charAt(0).toUpperCase()+t.slice(1)}const ht=t=>void 0!==t,dt=t=>"function"==typeof t,ut=(t,e)=>{if(t.size!==e.size)return!1;for(const i of t)if(!e.has(i))return!1;return!0},ft=Object.create(null),gt=Object.create(null);function pt(t,e){if(!e)return t;const i=e.split(".");for(let e=0,n=i.length;e<n;++e){const n=i[e];t=t[n]||(t[n]=Object.create(null))}return t}function mt(t,e,i){return"string"==typeof e?ot(pt(t,e),i):ot(pt(t,""),e)}var xt=new class{constructor(t){this.animation=void 0,this.backgroundColor="rgba(0,0,0,0.1)",this.borderColor="rgba(0,0,0,0.1)",this.color="#666",this.datasets={},this.devicePixelRatio=t=>t.chart.platform.getDevicePixelRatio(),this.elements={},this.events=["mousemove","mouseout","click","touchstart","touchmove"],this.font={family:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",size:12,style:"normal",lineHeight:1.2,weight:null},this.hover={},this.hoverBackgroundColor=(t,e)=>N(e.backgroundColor),this.hoverBorderColor=(t,e)=>N(e.borderColor),this.hoverColor=(t,e)=>N(e.color),this.indexAxis="x",this.interaction={mode:"nearest",intersect:!0},this.maintainAspectRatio=!0,this.onHover=null,this.onClick=null,this.parsing=!0,this.plugins={},this.responsive=!0,this.scale=void 0,this.scales={},this.showLine=!0,this.describe(t)}set(t,e){return mt(this,t,e)}get(t){return pt(this,t)}describe(t,e){return mt(gt,t,e)}override(t,e){return mt(ft,t,e)}route(t,e,i,n){const o=pt(this,t),s=pt(this,i),a="_"+e;Object.defineProperties(o,{[a]:{value:o[e],writable:!0},[e]:{enumerable:!0,get(){const t=this[a],e=s[n];return U(t)?Object.assign({},e,t):K(t,e)},set(t){this[a]=t}}})}}({_scriptable:t=>!t.startsWith("on"),_indexable:t=>"events"!==t,hover:{_fallback:"interaction"},interaction:{_scriptable:!1,_indexable:!1}});const bt=Math.PI,_t=2*bt,yt=_t+bt,vt=Number.POSITIVE_INFINITY,wt=bt/180,Mt=bt/2,kt=bt/4,St=2*bt/3,Pt=Math.log10,Dt=Math.sign;function Ct(t){const e=Math.round(t);t=At(t,e,t/1e3)?e:t;const i=Math.pow(10,Math.floor(Pt(t))),n=t/i;return(n<=1?1:n<=2?2:n<=5?5:10)*i}function Ot(t){const e=[],i=Math.sqrt(t);let n;for(n=1;n<i;n++)t%n==0&&(e.push(n),e.push(t/n));return i===(0|i)&&e.push(i),e.sort(((t,e)=>t-e)).pop(),e}function Tt(t){return!isNaN(parseFloat(t))&&isFinite(t)}function At(t,e,i){return Math.abs(t-e)<i}function Lt(t,e){const i=Math.round(t);return i-e<=t&&i+e>=t}function Rt(t,e,i){let n,o,s;for(n=0,o=t.length;n<o;n++)s=t[n][i],isNaN(s)||(e.min=Math.min(e.min,s),e.max=Math.max(e.max,s))}function Et(t){return t*(bt/180)}function It(t){return t*(180/bt)}function zt(t){if(!X(t))return;let e=1,i=0;for(;Math.round(t*e)/e!==t;)e*=10,i++;return i}function Ft(t,e){const i=e.x-t.x,n=e.y-t.y,o=Math.sqrt(i*i+n*n);let s=Math.atan2(n,i);return s<-.5*bt&&(s+=_t),{angle:s,distance:o}}function Bt(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))}function Vt(t,e){return(t-e+yt)%_t-bt}function Wt(t){return(t%_t+_t)%_t}function Nt(t,e,i,n){const o=Wt(t),s=Wt(e),a=Wt(i),r=Wt(s-o),l=Wt(a-o),c=Wt(o-s),h=Wt(o-a);return o===s||o===a||n&&s===a||r>l&&c<h}function Ht(t,e,i){return Math.max(e,Math.min(i,t))}function jt(t){return Ht(t,-32768,32767)}function $t(t){return!t||$(t.size)||$(t.family)?null:(t.style?t.style+" ":"")+(t.weight?t.weight+" ":"")+t.size+"px "+t.family}function Yt(t,e,i,n,o){let s=e[o];return s||(s=e[o]=t.measureText(o).width,i.push(o)),s>n&&(n=s),n}function Ut(t,e,i,n){let o=(n=n||{}).data=n.data||{},s=n.garbageCollect=n.garbageCollect||[];n.font!==e&&(o=n.data={},s=n.garbageCollect=[],n.font=e),t.save(),t.font=e;let a=0;const r=i.length;let l,c,h,d,u;for(l=0;l<r;l++)if(d=i[l],null!=d&&!0!==Y(d))a=Yt(t,o,s,a,d);else if(Y(d))for(c=0,h=d.length;c<h;c++)u=d[c],null==u||Y(u)||(a=Yt(t,o,s,a,u));t.restore();const f=s.length/2;if(f>i.length){for(l=0;l<f;l++)delete o[s[l]];s.splice(0,f)}return a}function Xt(t,e,i){const n=t.currentDevicePixelRatio,o=0!==i?Math.max(i/2,.5):0;return Math.round((e-o)*n)/n+o}function qt(t,e){(e=e||t.getContext("2d")).save(),e.resetTransform(),e.clearRect(0,0,t.width,t.height),e.restore()}function Kt(t,e,i,n){let o,s,a,r,l;const c=e.pointStyle,h=e.rotation,d=e.radius;let u=(h||0)*wt;if(c&&"object"==typeof c&&(o=c.toString(),"[object HTMLImageElement]"===o||"[object HTMLCanvasElement]"===o))return t.save(),t.translate(i,n),t.rotate(u),t.drawImage(c,-c.width/2,-c.height/2,c.width,c.height),void t.restore();if(!(isNaN(d)||d<=0)){switch(t.beginPath(),c){default:t.arc(i,n,d,0,_t),t.closePath();break;case"triangle":t.moveTo(i+Math.sin(u)*d,n-Math.cos(u)*d),u+=St,t.lineTo(i+Math.sin(u)*d,n-Math.cos(u)*d),u+=St,t.lineTo(i+Math.sin(u)*d,n-Math.cos(u)*d),t.closePath();break;case"rectRounded":l=.516*d,r=d-l,s=Math.cos(u+kt)*r,a=Math.sin(u+kt)*r,t.arc(i-s,n-a,l,u-bt,u-Mt),t.arc(i+a,n-s,l,u-Mt,u),t.arc(i+s,n+a,l,u,u+Mt),t.arc(i-a,n+s,l,u+Mt,u+bt),t.closePath();break;case"rect":if(!h){r=Math.SQRT1_2*d,t.rect(i-r,n-r,2*r,2*r);break}u+=kt;case"rectRot":s=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-s,n-a),t.lineTo(i+a,n-s),t.lineTo(i+s,n+a),t.lineTo(i-a,n+s),t.closePath();break;case"crossRot":u+=kt;case"cross":s=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-s,n-a),t.lineTo(i+s,n+a),t.moveTo(i+a,n-s),t.lineTo(i-a,n+s);break;case"star":s=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-s,n-a),t.lineTo(i+s,n+a),t.moveTo(i+a,n-s),t.lineTo(i-a,n+s),u+=kt,s=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-s,n-a),t.lineTo(i+s,n+a),t.moveTo(i+a,n-s),t.lineTo(i-a,n+s);break;case"line":s=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-s,n-a),t.lineTo(i+s,n+a);break;case"dash":t.moveTo(i,n),t.lineTo(i+Math.cos(u)*d,n+Math.sin(u)*d)}t.fill(),e.borderWidth>0&&t.stroke()}}function Gt(t,e,i){return i=i||.5,t&&e&&t.x>e.left-i&&t.x<e.right+i&&t.y>e.top-i&&t.y<e.bottom+i}function Zt(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()}function Qt(t){t.restore()}function Jt(t,e,i,n,o){if(!e)return t.lineTo(i.x,i.y);if("middle"===o){const n=(e.x+i.x)/2;t.lineTo(n,e.y),t.lineTo(n,i.y)}else"after"===o!=!!n?t.lineTo(e.x,i.y):t.lineTo(i.x,e.y);t.lineTo(i.x,i.y)}function te(t,e,i,n){if(!e)return t.lineTo(i.x,i.y);t.bezierCurveTo(n?e.cp1x:e.cp2x,n?e.cp1y:e.cp2y,n?i.cp2x:i.cp1x,n?i.cp2y:i.cp1y,i.x,i.y)}function ee(t,e,i,n,o,s={}){const a=Y(e)?e:[e],r=s.strokeWidth>0&&""!==s.strokeColor;let l,c;for(t.save(),t.font=o.string,function(t,e){e.translation&&t.translate(e.translation[0],e.translation[1]);$(e.rotation)||t.rotate(e.rotation);e.color&&(t.fillStyle=e.color);e.textAlign&&(t.textAlign=e.textAlign);e.textBaseline&&(t.textBaseline=e.textBaseline)}(t,s),l=0;l<a.length;++l)c=a[l],r&&(s.strokeColor&&(t.strokeStyle=s.strokeColor),$(s.strokeWidth)||(t.lineWidth=s.strokeWidth),t.strokeText(c,i,n,s.maxWidth)),t.fillText(c,i,n,s.maxWidth),ie(t,i,n,c,s),n+=o.lineHeight;t.restore()}function ie(t,e,i,n,o){if(o.strikethrough||o.underline){const s=t.measureText(n),a=e-s.actualBoundingBoxLeft,r=e+s.actualBoundingBoxRight,l=i-s.actualBoundingBoxAscent,c=i+s.actualBoundingBoxDescent,h=o.strikethrough?(l+c)/2:c;t.strokeStyle=t.fillStyle,t.beginPath(),t.lineWidth=o.decorationWidth||2,t.moveTo(a,h),t.lineTo(r,h),t.stroke()}}function ne(t,e){const{x:i,y:n,w:o,h:s,radius:a}=e;t.arc(i+a.topLeft,n+a.topLeft,a.topLeft,-Mt,bt,!0),t.lineTo(i,n+s-a.bottomLeft),t.arc(i+a.bottomLeft,n+s-a.bottomLeft,a.bottomLeft,bt,Mt,!0),t.lineTo(i+o-a.bottomRight,n+s),t.arc(i+o-a.bottomRight,n+s-a.bottomRight,a.bottomRight,Mt,0,!0),t.lineTo(i+o,n+a.topRight),t.arc(i+o-a.topRight,n+a.topRight,a.topRight,0,-Mt,!0),t.lineTo(i+a.topLeft,n)}function oe(t,e,i){i=i||(i=>t[i]<e);let n,o=t.length-1,s=0;for(;o-s>1;)n=s+o>>1,i(n)?s=n:o=n;return{lo:s,hi:o}}const se=(t,e,i)=>oe(t,i,(n=>t[n][e]<i)),ae=(t,e,i)=>oe(t,i,(n=>t[n][e]>=i));function re(t,e,i){let n=0,o=t.length;for(;n<o&&t[n]<e;)n++;for(;o>n&&t[o-1]>i;)o--;return n>0||o<t.length?t.slice(n,o):t}const le=["push","pop","shift","splice","unshift"];function ce(t,e){t._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),le.forEach((e=>{const i="_onData"+ct(e),n=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value(...e){const o=n.apply(this,e);return t._chartjs.listeners.forEach((t=>{"function"==typeof t[i]&&t[i](...e)})),o}})})))}function he(t,e){const i=t._chartjs;if(!i)return;const n=i.listeners,o=n.indexOf(e);-1!==o&&n.splice(o,1),n.length>0||(le.forEach((e=>{delete t[e]})),delete t._chartjs)}function de(t){const e=new Set;let i,n;for(i=0,n=t.length;i<n;++i)e.add(t[i]);return e.size===n?t:Array.from(e)}function ue(){return"undefined"!=typeof window&&"undefined"!=typeof document}function fe(t){let e=t.parentNode;return e&&"[object ShadowRoot]"===e.toString()&&(e=e.host),e}function ge(t,e,i){let n;return"string"==typeof t?(n=parseInt(t,10),-1!==t.indexOf("%")&&(n=n/100*e.parentNode[i])):n=t,n}const pe=t=>window.getComputedStyle(t,null);function me(t,e){return pe(t).getPropertyValue(e)}const xe=["top","right","bottom","left"];function be(t,e,i){const n={};i=i?"-"+i:"";for(let o=0;o<4;o++){const s=xe[o];n[s]=parseFloat(t[e+"-"+s+i])||0}return n.width=n.left+n.right,n.height=n.top+n.bottom,n}function _e(t,e){const{canvas:i,currentDevicePixelRatio:n}=e,o=pe(i),s="border-box"===o.boxSizing,a=be(o,"padding"),r=be(o,"border","width"),{x:l,y:c,box:h}=function(t,e){const i=t.native||t,n=i.touches,o=n&&n.length?n[0]:i,{offsetX:s,offsetY:a}=o;let r,l,c=!1;if(((t,e,i)=>(t>0||e>0)&&(!i||!i.shadowRoot))(s,a,i.target))r=s,l=a;else{const t=e.getBoundingClientRect();r=o.clientX-t.left,l=o.clientY-t.top,c=!0}return{x:r,y:l,box:c}}(t,i),d=a.left+(h&&r.left),u=a.top+(h&&r.top);let{width:f,height:g}=e;return s&&(f-=a.width+r.width,g-=a.height+r.height),{x:Math.round((l-d)/f*i.width/n),y:Math.round((c-u)/g*i.height/n)}}const ye=t=>Math.round(10*t)/10;function ve(t,e,i,n){const o=pe(t),s=be(o,"margin"),a=ge(o.maxWidth,t,"clientWidth")||vt,r=ge(o.maxHeight,t,"clientHeight")||vt,l=function(t,e,i){let n,o;if(void 0===e||void 0===i){const s=fe(t);if(s){const t=s.getBoundingClientRect(),a=pe(s),r=be(a,"border","width"),l=be(a,"padding");e=t.width-l.width-r.width,i=t.height-l.height-r.height,n=ge(a.maxWidth,s,"clientWidth"),o=ge(a.maxHeight,s,"clientHeight")}else e=t.clientWidth,i=t.clientHeight}return{width:e,height:i,maxWidth:n||vt,maxHeight:o||vt}}(t,e,i);let{width:c,height:h}=l;if("content-box"===o.boxSizing){const t=be(o,"border","width"),e=be(o,"padding");c-=e.width+t.width,h-=e.height+t.height}return c=Math.max(0,c-s.width),h=Math.max(0,n?Math.floor(c/n):h-s.height),c=ye(Math.min(c,a,l.maxWidth)),h=ye(Math.min(h,r,l.maxHeight)),c&&!h&&(h=ye(c/2)),{width:c,height:h}}function we(t,e,i){const n=e||1,o=Math.floor(t.height*n),s=Math.floor(t.width*n);t.height=o/n,t.width=s/n;const a=t.canvas;return a.style&&(i||!a.style.height&&!a.style.width)&&(a.style.height=`${t.height}px`,a.style.width=`${t.width}px`),(t.currentDevicePixelRatio!==n||a.height!==o||a.width!==s)&&(t.currentDevicePixelRatio=n,a.height=o,a.width=s,t.ctx.setTransform(n,0,0,n,0,0),!0)}const Me=function(){let t=!1;try{const e={get passive(){return t=!0,!1}};window.addEventListener("test",null,e),window.removeEventListener("test",null,e)}catch(t){}return t}();function ke(t,e){const i=me(t,e),n=i&&i.match(/^(\d+)(\.\d+)?px$/);return n?+n[1]:void 0}function Se(t,e){return"native"in t?{x:t.x,y:t.y}:_e(t,e)}function Pe(t,e,i,n){const{controller:o,data:s,_sorted:a}=t,r=o._cachedMeta.iScale;if(r&&e===r.axis&&a&&s.length){const t=r._reversePixels?ae:se;if(!n)return t(s,e,i);if(o._sharedOptions){const n=s[0],o="function"==typeof n.getRange&&n.getRange(e);if(o){const n=t(s,e,i-o),a=t(s,e,i+o);return{lo:n.lo,hi:a.hi}}}}return{lo:0,hi:s.length-1}}function De(t,e,i,n,o){const s=t.getSortedVisibleDatasetMetas(),a=i[e];for(let t=0,i=s.length;t<i;++t){const{index:i,data:r}=s[t],{lo:l,hi:c}=Pe(s[t],e,a,o);for(let t=l;t<=c;++t){const e=r[t];e.skip||n(e,i,t)}}}function Ce(t,e,i,n){const o=[];if(!Gt(e,t.chartArea,t._minPadding))return o;return De(t,i,e,(function(t,i,s){t.inRange(e.x,e.y,n)&&o.push({element:t,datasetIndex:i,index:s})}),!0),o}function Oe(t,e,i,n,o){const s=function(t){const e=-1!==t.indexOf("x"),i=-1!==t.indexOf("y");return function(t,n){const o=e?Math.abs(t.x-n.x):0,s=i?Math.abs(t.y-n.y):0;return Math.sqrt(Math.pow(o,2)+Math.pow(s,2))}}(i);let a=Number.POSITIVE_INFINITY,r=[];if(!Gt(e,t.chartArea,t._minPadding))return r;return De(t,i,e,(function(i,l,c){if(n&&!i.inRange(e.x,e.y,o))return;const h=i.getCenterPoint(o);if(!Gt(h,t.chartArea,t._minPadding)&&!i.inRange(e.x,e.y,o))return;const d=s(e,h);d<a?(r=[{element:i,datasetIndex:l,index:c}],a=d):d===a&&r.push({element:i,datasetIndex:l,index:c})})),r}function Te(t,e,i,n){const o=Se(e,t),s=[],a=i.axis,r="x"===a?"inXRange":"inYRange";let l=!1;return function(t,e){const i=t.getSortedVisibleDatasetMetas();let n,o,s;for(let t=0,a=i.length;t<a;++t){({index:n,data:o}=i[t]);for(let t=0,i=o.length;t<i;++t)s=o[t],s.skip||e(s,n,t)}}(t,((t,e,i)=>{t[r](o[a],n)&&s.push({element:t,datasetIndex:e,index:i}),t.inRange(o.x,o.y,n)&&(l=!0)})),i.intersect&&!l?[]:s}var Ae={modes:{index(t,e,i,n){const o=Se(e,t),s=i.axis||"x",a=i.intersect?Ce(t,o,s,n):Oe(t,o,s,!1,n),r=[];return a.length?(t.getSortedVisibleDatasetMetas().forEach((t=>{const e=a[0].index,i=t.data[e];i&&!i.skip&&r.push({element:i,datasetIndex:t.index,index:e})})),r):[]},dataset(t,e,i,n){const o=Se(e,t),s=i.axis||"xy";let a=i.intersect?Ce(t,o,s,n):Oe(t,o,s,!1,n);if(a.length>0){const e=a[0].datasetIndex,i=t.getDatasetMeta(e).data;a=[];for(let t=0;t<i.length;++t)a.push({element:i[t],datasetIndex:e,index:t})}return a},point:(t,e,i,n)=>Ce(t,Se(e,t),i.axis||"xy",n),nearest:(t,e,i,n)=>Oe(t,Se(e,t),i.axis||"xy",i.intersect,n),x:(t,e,i,n)=>(i.axis="x",Te(t,e,i,n)),y:(t,e,i,n)=>(i.axis="y",Te(t,e,i,n))}};const Le=new RegExp(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/),Re=new RegExp(/^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/);function Ee(t,e){const i=(""+t).match(Le);if(!i||"normal"===i[1])return 1.2*e;switch(t=+i[2],i[3]){case"px":return t;case"%":t/=100}return e*t}function Ie(t,e){const i={},n=U(e),o=n?Object.keys(e):e,s=U(t)?n?i=>K(t[i],t[e[i]]):e=>t[e]:()=>t;for(const t of o)i[t]=+s(t)||0;return i}function ze(t){return Ie(t,{top:"y",right:"x",bottom:"y",left:"x"})}function Fe(t){return Ie(t,["topLeft","topRight","bottomLeft","bottomRight"])}function Be(t){const e=ze(t);return e.width=e.left+e.right,e.height=e.top+e.bottom,e}function Ve(t,e){t=t||{},e=e||xt.font;let i=K(t.size,e.size);"string"==typeof i&&(i=parseInt(i,10));let n=K(t.style,e.style);n&&!(""+n).match(Re)&&(console.warn('Invalid font style specified: "'+n+'"'),n="");const o={family:K(t.family,e.family),lineHeight:Ee(K(t.lineHeight,e.lineHeight),i),size:i,style:n,weight:K(t.weight,e.weight),string:""};return o.string=$t(o),o}function We(t,e,i,n){let o,s,a,r=!0;for(o=0,s=t.length;o<s;++o)if(a=t[o],void 0!==a&&(void 0!==e&&"function"==typeof a&&(a=a(e),r=!1),void 0!==i&&Y(a)&&(a=a[i%a.length],r=!1),void 0!==a))return n&&!r&&(n.cacheable=!1),a}function Ne(t,e){const{min:i,max:n}=t;return{min:i-Math.abs(Z(e,i)),max:n+Z(e,n)}}const He=["left","top","right","bottom"];function je(t,e){return t.filter((t=>t.pos===e))}function $e(t,e){return t.filter((t=>-1===He.indexOf(t.pos)&&t.box.axis===e))}function Ye(t,e){return t.sort(((t,i)=>{const n=e?i:t,o=e?t:i;return n.weight===o.weight?n.index-o.index:n.weight-o.weight}))}function Ue(t,e){const i=function(t){const e={};for(const i of t){const{stack:t,pos:n,stackWeight:o}=i;if(!t||!He.includes(n))continue;const s=e[t]||(e[t]={count:0,placed:0,weight:0,size:0});s.count++,s.weight+=o}return e}(t),{vBoxMaxWidth:n,hBoxMaxHeight:o}=e;let s,a,r;for(s=0,a=t.length;s<a;++s){r=t[s];const{fullSize:a}=r.box,l=i[r.stack],c=l&&r.stackWeight/l.weight;r.horizontal?(r.width=c?c*n:a&&e.availableWidth,r.height=o):(r.width=n,r.height=c?c*o:a&&e.availableHeight)}return i}function Xe(t,e,i,n){return Math.max(t[i],e[i])+Math.max(t[n],e[n])}function qe(t,e){t.top=Math.max(t.top,e.top),t.left=Math.max(t.left,e.left),t.bottom=Math.max(t.bottom,e.bottom),t.right=Math.max(t.right,e.right)}function Ke(t,e,i,n){const{pos:o,box:s}=i,a=t.maxPadding;if(!U(o)){i.size&&(t[o]-=i.size);const e=n[i.stack]||{size:0,count:1};e.size=Math.max(e.size,i.horizontal?s.height:s.width),i.size=e.size/e.count,t[o]+=i.size}s.getPadding&&qe(a,s.getPadding());const r=Math.max(0,e.outerWidth-Xe(a,t,"left","right")),l=Math.max(0,e.outerHeight-Xe(a,t,"top","bottom")),c=r!==t.w,h=l!==t.h;return t.w=r,t.h=l,i.horizontal?{same:c,other:h}:{same:h,other:c}}function Ge(t,e){const i=e.maxPadding;function n(t){const n={left:0,top:0,right:0,bottom:0};return t.forEach((t=>{n[t]=Math.max(e[t],i[t])})),n}return n(t?["left","right"]:["top","bottom"])}function Ze(t,e,i,n){const o=[];let s,a,r,l,c,h;for(s=0,a=t.length,c=0;s<a;++s){r=t[s],l=r.box,l.update(r.width||e.w,r.height||e.h,Ge(r.horizontal,e));const{same:a,other:d}=Ke(e,i,r,n);c|=a&&o.length,h=h||d,l.fullSize||o.push(r)}return c&&Ze(o,e,i,n)||h}function Qe(t,e,i,n,o){t.top=i,t.left=e,t.right=e+n,t.bottom=i+o,t.width=n,t.height=o}function Je(t,e,i,n){const o=i.padding;let{x:s,y:a}=e;for(const r of t){const t=r.box,l=n[r.stack]||{count:1,placed:0,weight:1},c=r.stackWeight/l.weight||1;if(r.horizontal){const n=e.w*c,s=l.size||t.height;ht(l.start)&&(a=l.start),t.fullSize?Qe(t,o.left,a,i.outerWidth-o.right-o.left,s):Qe(t,e.left+l.placed,a,n,s),l.start=a,l.placed+=n,a=t.bottom}else{const n=e.h*c,a=l.size||t.width;ht(l.start)&&(s=l.start),t.fullSize?Qe(t,s,o.top,a,i.outerHeight-o.bottom-o.top):Qe(t,s,e.top+l.placed,a,n),l.start=s,l.placed+=n,s=t.right}}e.x=s,e.y=a}xt.set("layout",{padding:{top:0,right:0,bottom:0,left:0}});var ti={addBox(t,e){t.boxes||(t.boxes=[]),e.fullSize=e.fullSize||!1,e.position=e.position||"top",e.weight=e.weight||0,e._layers=e._layers||function(){return[{z:0,draw(t){e.draw(t)}}]},t.boxes.push(e)},removeBox(t,e){const i=t.boxes?t.boxes.indexOf(e):-1;-1!==i&&t.boxes.splice(i,1)},configure(t,e,i){e.fullSize=i.fullSize,e.position=i.position,e.weight=i.weight},update(t,e,i,n){if(!t)return;const o=Be(t.options.layout.padding),s=Math.max(e-o.width,0),a=Math.max(i-o.height,0),r=function(t){const e=function(t){const e=[];let i,n,o,s,a,r;for(i=0,n=(t||[]).length;i<n;++i)o=t[i],({position:s,options:{stack:a,stackWeight:r=1}}=o),e.push({index:i,box:o,pos:s,horizontal:o.isHorizontal(),weight:o.weight,stack:a&&s+a,stackWeight:r});return e}(t),i=Ye(e.filter((t=>t.box.fullSize)),!0),n=Ye(je(e,"left"),!0),o=Ye(je(e,"right")),s=Ye(je(e,"top"),!0),a=Ye(je(e,"bottom")),r=$e(e,"x"),l=$e(e,"y");return{fullSize:i,leftAndTop:n.concat(s),rightAndBottom:o.concat(l).concat(a).concat(r),chartArea:je(e,"chartArea"),vertical:n.concat(o).concat(l),horizontal:s.concat(a).concat(r)}}(t.boxes),l=r.vertical,c=r.horizontal;J(t.boxes,(t=>{"function"==typeof t.beforeLayout&&t.beforeLayout()}));const h=l.reduce(((t,e)=>e.box.options&&!1===e.box.options.display?t:t+1),0)||1,d=Object.freeze({outerWidth:e,outerHeight:i,padding:o,availableWidth:s,availableHeight:a,vBoxMaxWidth:s/2/h,hBoxMaxHeight:a/2}),u=Object.assign({},o);qe(u,Be(n));const f=Object.assign({maxPadding:u,w:s,h:a,x:o.left,y:o.top},o),g=Ue(l.concat(c),d);Ze(r.fullSize,f,d,g),Ze(l,f,d,g),Ze(c,f,d,g)&&Ze(l,f,d,g),function(t){const e=t.maxPadding;function i(i){const n=Math.max(e[i]-t[i],0);return t[i]+=n,n}t.y+=i("top"),t.x+=i("left"),i("right"),i("bottom")}(f),Je(r.leftAndTop,f,d,g),f.x+=f.w,f.y+=f.h,Je(r.rightAndBottom,f,d,g),t.chartArea={left:f.left,top:f.top,right:f.left+f.w,bottom:f.top+f.h,height:f.h,width:f.w},J(r.chartArea,(e=>{const i=e.box;Object.assign(i,t.chartArea),i.update(f.w,f.h)}))}};function ei(t,e=[""],i=t,n,o=(()=>t[0])){ht(n)||(n=ui("_fallback",t));const s={[Symbol.toStringTag]:"Object",_cacheable:!0,_scopes:t,_rootScopes:i,_fallback:n,_getTarget:o,override:o=>ei([o,...t],e,i,n)};return new Proxy(s,{deleteProperty:(e,i)=>(delete e[i],delete e._keys,delete t[0][i],!0),get:(i,n)=>ai(i,n,(()=>function(t,e,i,n){let o;for(const s of e)if(o=ui(oi(s,t),i),ht(o))return si(t,o)?hi(i,n,t,o):o}(n,e,t,i))),getOwnPropertyDescriptor:(t,e)=>Reflect.getOwnPropertyDescriptor(t._scopes[0],e),getPrototypeOf:()=>Reflect.getPrototypeOf(t[0]),has:(t,e)=>fi(t).includes(e),ownKeys:t=>fi(t),set:(t,e,i)=>((t._storage||(t._storage=o()))[e]=i,delete t[e],delete t._keys,!0)})}function ii(t,e,i,n){const o={_cacheable:!1,_proxy:t,_context:e,_subProxy:i,_stack:new Set,_descriptors:ni(t,n),setContext:e=>ii(t,e,i,n),override:o=>ii(t.override(o),e,i,n)};return new Proxy(o,{deleteProperty:(e,i)=>(delete e[i],delete t[i],!0),get:(t,e,i)=>ai(t,e,(()=>function(t,e,i){const{_proxy:n,_context:o,_subProxy:s,_descriptors:a}=t;let r=n[e];dt(r)&&a.isScriptable(e)&&(r=function(t,e,i,n){const{_proxy:o,_context:s,_subProxy:a,_stack:r}=i;if(r.has(t))throw new Error("Recursion detected: "+Array.from(r).join("->")+"->"+t);r.add(t),e=e(s,a||n),r.delete(t),U(e)&&(e=hi(o._scopes,o,t,e));return e}(e,r,t,i));Y(r)&&r.length&&(r=function(t,e,i,n){const{_proxy:o,_context:s,_subProxy:a,_descriptors:r}=i;if(ht(s.index)&&n(t))e=e[s.index%e.length];else if(U(e[0])){const i=e,n=o._scopes.filter((t=>t!==i));e=[];for(const l of i){const i=hi(n,o,t,l);e.push(ii(i,s,a&&a[t],r))}}return e}(e,r,t,a.isIndexable));si(e,r)&&(r=ii(r,o,s&&s[e],a));return r}(t,e,i))),getOwnPropertyDescriptor:(e,i)=>e._descriptors.allKeys?Reflect.has(t,i)?{enumerable:!0,configurable:!0}:void 0:Reflect.getOwnPropertyDescriptor(t,i),getPrototypeOf:()=>Reflect.getPrototypeOf(t),has:(e,i)=>Reflect.has(t,i),ownKeys:()=>Reflect.ownKeys(t),set:(e,i,n)=>(t[i]=n,delete e[i],!0)})}function ni(t,e={scriptable:!0,indexable:!0}){const{_scriptable:i=e.scriptable,_indexable:n=e.indexable,_allKeys:o=e.allKeys}=t;return{allKeys:o,scriptable:i,indexable:n,isScriptable:dt(i)?i:()=>i,isIndexable:dt(n)?n:()=>n}}const oi=(t,e)=>t?t+ct(e):e,si=(t,e)=>U(e)&&"adapters"!==t;function ai(t,e,i){let n=t[e];return ht(n)||(n=i(),ht(n)&&(t[e]=n)),n}function ri(t,e,i){return dt(t)?t(e,i):t}const li=(t,e)=>!0===t?e:"string"==typeof t?lt(e,t):void 0;function ci(t,e,i,n){for(const o of e){const e=li(i,o);if(e){t.add(e);const o=ri(e._fallback,i,e);if(ht(o)&&o!==i&&o!==n)return o}else if(!1===e&&ht(n)&&i!==n)return null}return!1}function hi(t,e,i,n){const o=e._rootScopes,s=ri(e._fallback,i,n),a=[...t,...o],r=new Set;r.add(n);let l=di(r,a,i,s||i);return null!==l&&((!ht(s)||s===i||(l=di(r,a,s,l),null!==l))&&ei(Array.from(r),[""],o,s,(()=>function(t,e,i){const n=t._getTarget();e in n||(n[e]={});const o=n[e];if(Y(o)&&U(i))return i;return o}(e,i,n))))}function di(t,e,i,n){for(;i;)i=ci(t,e,i,n);return i}function ui(t,e){for(const i of e){if(!i)continue;const e=i[t];if(ht(e))return e}}function fi(t){let e=t._keys;return e||(e=t._keys=function(t){const e=new Set;for(const i of t)for(const t of Object.keys(i).filter((t=>!t.startsWith("_"))))e.add(t);return Array.from(e)}(t._scopes)),e}const gi=Number.EPSILON||1e-14,pi=(t,e)=>e<t.length&&!t[e].skip&&t[e],mi=t=>"x"===t?"y":"x";function xi(t,e,i,n){const o=t.skip?e:t,s=e,a=i.skip?e:i,r=Bt(s,o),l=Bt(a,s);let c=r/(r+l),h=l/(r+l);c=isNaN(c)?0:c,h=isNaN(h)?0:h;const d=n*c,u=n*h;return{previous:{x:s.x-d*(a.x-o.x),y:s.y-d*(a.y-o.y)},next:{x:s.x+u*(a.x-o.x),y:s.y+u*(a.y-o.y)}}}function bi(t,e="x"){const i=mi(e),n=t.length,o=Array(n).fill(0),s=Array(n);let a,r,l,c=pi(t,0);for(a=0;a<n;++a)if(r=l,l=c,c=pi(t,a+1),l){if(c){const t=c[e]-l[e];o[a]=0!==t?(c[i]-l[i])/t:0}s[a]=r?c?Dt(o[a-1])!==Dt(o[a])?0:(o[a-1]+o[a])/2:o[a-1]:o[a]}!function(t,e,i){const n=t.length;let o,s,a,r,l,c=pi(t,0);for(let h=0;h<n-1;++h)l=c,c=pi(t,h+1),l&&c&&(At(e[h],0,gi)?i[h]=i[h+1]=0:(o=i[h]/e[h],s=i[h+1]/e[h],r=Math.pow(o,2)+Math.pow(s,2),r<=9||(a=3/Math.sqrt(r),i[h]=o*a*e[h],i[h+1]=s*a*e[h])))}(t,o,s),function(t,e,i="x"){const n=mi(i),o=t.length;let s,a,r,l=pi(t,0);for(let c=0;c<o;++c){if(a=r,r=l,l=pi(t,c+1),!r)continue;const o=r[i],h=r[n];a&&(s=(o-a[i])/3,r[`cp1${i}`]=o-s,r[`cp1${n}`]=h-s*e[c]),l&&(s=(l[i]-o)/3,r[`cp2${i}`]=o+s,r[`cp2${n}`]=h+s*e[c])}}(t,s,e)}function _i(t,e,i){return Math.max(Math.min(t,i),e)}function yi(t,e,i,n,o){let s,a,r,l;if(e.spanGaps&&(t=t.filter((t=>!t.skip))),"monotone"===e.cubicInterpolationMode)bi(t,o);else{let i=n?t[t.length-1]:t[0];for(s=0,a=t.length;s<a;++s)r=t[s],l=xi(i,r,t[Math.min(s+1,a-(n?0:1))%a],e.tension),r.cp1x=l.previous.x,r.cp1y=l.previous.y,r.cp2x=l.next.x,r.cp2y=l.next.y,i=r}e.capBezierPoints&&function(t,e){let i,n,o,s,a,r=Gt(t[0],e);for(i=0,n=t.length;i<n;++i)a=s,s=r,r=i<n-1&&Gt(t[i+1],e),s&&(o=t[i],a&&(o.cp1x=_i(o.cp1x,e.left,e.right),o.cp1y=_i(o.cp1y,e.top,e.bottom)),r&&(o.cp2x=_i(o.cp2x,e.left,e.right),o.cp2y=_i(o.cp2y,e.top,e.bottom)))}(t,i)}const vi=t=>0===t||1===t,wi=(t,e,i)=>-Math.pow(2,10*(t-=1))*Math.sin((t-e)*_t/i),Mi=(t,e,i)=>Math.pow(2,-10*t)*Math.sin((t-e)*_t/i)+1,ki={linear:t=>t,easeInQuad:t=>t*t,easeOutQuad:t=>-t*(t-2),easeInOutQuad:t=>(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1),easeInCubic:t=>t*t*t,easeOutCubic:t=>(t-=1)*t*t+1,easeInOutCubic:t=>(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2),easeInQuart:t=>t*t*t*t,easeOutQuart:t=>-((t-=1)*t*t*t-1),easeInOutQuart:t=>(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2),easeInQuint:t=>t*t*t*t*t,easeOutQuint:t=>(t-=1)*t*t*t*t+1,easeInOutQuint:t=>(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2),easeInSine:t=>1-Math.cos(t*Mt),easeOutSine:t=>Math.sin(t*Mt),easeInOutSine:t=>-.5*(Math.cos(bt*t)-1),easeInExpo:t=>0===t?0:Math.pow(2,10*(t-1)),easeOutExpo:t=>1===t?1:1-Math.pow(2,-10*t),easeInOutExpo:t=>vi(t)?t:t<.5?.5*Math.pow(2,10*(2*t-1)):.5*(2-Math.pow(2,-10*(2*t-1))),easeInCirc:t=>t>=1?t:-(Math.sqrt(1-t*t)-1),easeOutCirc:t=>Math.sqrt(1-(t-=1)*t),easeInOutCirc:t=>(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1),easeInElastic:t=>vi(t)?t:wi(t,.075,.3),easeOutElastic:t=>vi(t)?t:Mi(t,.075,.3),easeInOutElastic(t){const e=.1125;return vi(t)?t:t<.5?.5*wi(2*t,e,.45):.5+.5*Mi(2*t-1,e,.45)},easeInBack(t){const e=1.70158;return t*t*((e+1)*t-e)},easeOutBack(t){const e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack(t){let e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:t=>1-ki.easeOutBounce(1-t),easeOutBounce(t){const e=7.5625,i=2.75;return t<1/i?e*t*t:t<2/i?e*(t-=1.5/i)*t+.75:t<2.5/i?e*(t-=2.25/i)*t+.9375:e*(t-=2.625/i)*t+.984375},easeInOutBounce:t=>t<.5?.5*ki.easeInBounce(2*t):.5*ki.easeOutBounce(2*t-1)+.5};function Si(t,e,i,n){return{x:t.x+i*(e.x-t.x),y:t.y+i*(e.y-t.y)}}function Pi(t,e,i,n){return{x:t.x+i*(e.x-t.x),y:"middle"===n?i<.5?t.y:e.y:"after"===n?i<1?t.y:e.y:i>0?e.y:t.y}}function Di(t,e,i,n){const o={x:t.cp2x,y:t.cp2y},s={x:e.cp1x,y:e.cp1y},a=Si(t,o,i),r=Si(o,s,i),l=Si(s,e,i),c=Si(a,r,i),h=Si(r,l,i);return Si(c,h,i)}const Ci=new Map;function Oi(t,e,i){return function(t,e){e=e||{};const i=t+JSON.stringify(e);let n=Ci.get(i);return n||(n=new Intl.NumberFormat(t,e),Ci.set(i,n)),n}(e,i).format(t)}function Ti(t,e,i){return t?function(t,e){return{x:i=>t+t+e-i,setWidth(t){e=t},textAlign:t=>"center"===t?t:"right"===t?"left":"right",xPlus:(t,e)=>t-e,leftForLtr:(t,e)=>t-e}}(e,i):{x:t=>t,setWidth(t){},textAlign:t=>t,xPlus:(t,e)=>t+e,leftForLtr:(t,e)=>t}}function Ai(t,e){let i,n;"ltr"!==e&&"rtl"!==e||(i=t.canvas.style,n=[i.getPropertyValue("direction"),i.getPropertyPriority("direction")],i.setProperty("direction",e,"important"),t.prevTextDirection=n)}function Li(t,e){void 0!==e&&(delete t.prevTextDirection,t.canvas.style.setProperty("direction",e[0],e[1]))}function Ri(t){return"angle"===t?{between:Nt,compare:Vt,normalize:Wt}:{between:(t,e,i)=>t>=Math.min(e,i)&&t<=Math.max(i,e),compare:(t,e)=>t-e,normalize:t=>t}}function Ei({start:t,end:e,count:i,loop:n,style:o}){return{start:t%i,end:e%i,loop:n&&(e-t+1)%i==0,style:o}}function Ii(t,e,i){if(!i)return[t];const{property:n,start:o,end:s}=i,a=e.length,{compare:r,between:l,normalize:c}=Ri(n),{start:h,end:d,loop:u,style:f}=function(t,e,i){const{property:n,start:o,end:s}=i,{between:a,normalize:r}=Ri(n),l=e.length;let c,h,{start:d,end:u,loop:f}=t;if(f){for(d+=l,u+=l,c=0,h=l;c<h&&a(r(e[d%l][n]),o,s);++c)d--,u--;d%=l,u%=l}return u<d&&(u+=l),{start:d,end:u,loop:f,style:t.style}}(t,e,i),g=[];let p,m,x,b=!1,_=null;const y=()=>b||l(o,x,p)&&0!==r(o,x),v=()=>!b||0===r(s,p)||l(s,x,p);for(let t=h,i=h;t<=d;++t)m=e[t%a],m.skip||(p=c(m[n]),p!==x&&(b=l(p,o,s),null===_&&y()&&(_=0===r(p,o)?t:i),null!==_&&v()&&(g.push(Ei({start:_,end:t,loop:u,count:a,style:f})),_=null),i=t,x=p));return null!==_&&g.push(Ei({start:_,end:d,loop:u,count:a,style:f})),g}function zi(t,e){const i=[],n=t.segments;for(let o=0;o<n.length;o++){const s=Ii(n[o],t.points,e);s.length&&i.push(...s)}return i}function Fi(t,e){const i=t.points,n=t.options.spanGaps,o=i.length;if(!o)return[];const s=!!t._loop,{start:a,end:r}=function(t,e,i,n){let o=0,s=e-1;if(i&&!n)for(;o<e&&!t[o].skip;)o++;for(;o<e&&t[o].skip;)o++;for(o%=e,i&&(s+=o);s>o&&t[s%e].skip;)s--;return s%=e,{start:o,end:s}}(i,o,s,n);if(!0===n)return Bi(t,[{start:a,end:r,loop:s}],i,e);return Bi(t,function(t,e,i,n){const o=t.length,s=[];let a,r=e,l=t[e];for(a=e+1;a<=i;++a){const i=t[a%o];i.skip||i.stop?l.skip||(n=!1,s.push({start:e%o,end:(a-1)%o,loop:n}),e=r=i.stop?a:null):(r=a,l.skip&&(e=a)),l=i}return null!==r&&s.push({start:e%o,end:r%o,loop:n}),s}(i,a,r<a?r+o:r,!!t._fullLoop&&0===a&&r===o-1),i,e)}function Bi(t,e,i,n){return n&&n.setContext&&i?function(t,e,i,n){const o=Vi(t.options),s=i.length,a=[];let r=e[0].start,l=r;for(const c of e){let e,h=o,d=i[r%s];for(l=r+1;l<=c.end;l++){const o=i[l%s];e=Vi(n.setContext({type:"segment",p0:d,p1:o,p0DataIndex:(l-1)%s,p1DataIndex:l%s,datasetIndex:t._datasetIndex})),Wi(e,h)&&(a.push({start:r,end:l-1,loop:c.loop,style:h}),h=e,r=l-1),d=o,h=e}r<l-1&&(a.push({start:r,end:l-1,loop:c.loop,style:e}),r=l-1)}return a}(t,e,i,n):e}function Vi(t){return{backgroundColor:t.backgroundColor,borderCapStyle:t.borderCapStyle,borderDash:t.borderDash,borderDashOffset:t.borderDashOffset,borderJoinStyle:t.borderJoinStyle,borderWidth:t.borderWidth,borderColor:t.borderColor}}function Wi(t,e){return e&&JSON.stringify(t)!==JSON.stringify(e)}var Ni=Object.freeze({__proto__:null,easingEffects:ki,color:W,getHoverColor:N,noop:H,uid:j,isNullOrUndef:$,isArray:Y,isObject:U,isFinite:X,finiteOrDefault:q,valueOrDefault:K,toPercentage:G,toDimension:Z,callback:Q,each:J,_elementsEqual:tt,clone:et,_merger:nt,merge:ot,mergeIf:st,_mergerIf:at,_deprecated:function(t,e,i,n){void 0!==e&&console.warn(t+': "'+i+'" is deprecated. Please use "'+n+'" instead')},resolveObjectKey:lt,_capitalize:ct,defined:ht,isFunction:dt,setsEqual:ut,toFontString:$t,_measureText:Yt,_longestText:Ut,_alignPixel:Xt,clearCanvas:qt,drawPoint:Kt,_isPointInArea:Gt,clipArea:Zt,unclipArea:Qt,_steppedLineTo:Jt,_bezierCurveTo:te,renderText:ee,addRoundedRectPath:ne,_lookup:oe,_lookupByKey:se,_rlookupByKey:ae,_filterBetween:re,listenArrayEvents:ce,unlistenArrayEvents:he,_arrayUnique:de,_createResolver:ei,_attachContext:ii,_descriptors:ni,splineCurve:xi,splineCurveMonotone:bi,_updateBezierControlPoints:yi,_isDomSupported:ue,_getParentNode:fe,getStyle:me,getRelativePosition:_e,getMaximumSize:ve,retinaScale:we,supportsEventListenerOptions:Me,readUsedSize:ke,fontString:function(t,e,i){return e+" "+t+"px "+i},requestAnimFrame:t,throttled:e,debounce:i,_toLeftRightCenter:n,_alignStartEnd:o,_textX:s,_pointInLine:Si,_steppedInterpolation:Pi,_bezierInterpolation:Di,formatNumber:Oi,toLineHeight:Ee,_readValueToProps:Ie,toTRBL:ze,toTRBLCorners:Fe,toPadding:Be,toFont:Ve,resolve:We,_addGrace:Ne,PI:bt,TAU:_t,PITAU:yt,INFINITY:vt,RAD_PER_DEG:wt,HALF_PI:Mt,QUARTER_PI:kt,TWO_THIRDS_PI:St,log10:Pt,sign:Dt,niceNum:Ct,_factorize:Ot,isNumber:Tt,almostEquals:At,almostWhole:Lt,_setMinAndMaxByKey:Rt,toRadians:Et,toDegrees:It,_decimalPlaces:zt,getAngleFromPoint:Ft,distanceBetweenPoints:Bt,_angleDiff:Vt,_normalizeAngle:Wt,_angleBetween:Nt,_limitValue:Ht,_int16Range:jt,getRtlAdapter:Ti,overrideTextDirection:Ai,restoreTextDirection:Li,_boundSegment:Ii,_boundSegments:zi,_computeSegments:Fi});class Hi{acquireContext(t,e){}releaseContext(t){return!1}addEventListener(t,e,i){}removeEventListener(t,e,i){}getDevicePixelRatio(){return 1}getMaximumSize(t,e,i,n){return e=Math.max(0,e||t.width),i=i||t.height,{width:e,height:Math.max(0,n?Math.floor(e/n):i)}}isAttached(t){return!0}}class ji extends Hi{acquireContext(t){return t&&t.getContext&&t.getContext("2d")||null}}const $i={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},Yi=t=>null===t||""===t;const Ui=!!Me&&{passive:!0};function Xi(t,e,i){t.canvas.removeEventListener(e,i,Ui)}function qi(t,e,i){const n=t.canvas,o=n&&fe(n)||n,s=new MutationObserver((t=>{const e=fe(o);t.forEach((t=>{for(let n=0;n<t.addedNodes.length;n++){const s=t.addedNodes[n];s!==o&&s!==e||i(t.target)}}))}));return s.observe(document,{childList:!0,subtree:!0}),s}function Ki(t,e,i){const n=t.canvas,o=n&&fe(n);if(!o)return;const s=new MutationObserver((t=>{t.forEach((t=>{for(let e=0;e<t.removedNodes.length;e++)if(t.removedNodes[e]===n){i();break}}))}));return s.observe(o,{childList:!0}),s}const Gi=new Map;let Zi=0;function Qi(){const t=window.devicePixelRatio;t!==Zi&&(Zi=t,Gi.forEach(((e,i)=>{i.currentDevicePixelRatio!==t&&e()})))}function Ji(t,i,n){const o=t.canvas,s=o&&fe(o);if(!s)return;const a=e(((t,e)=>{const i=s.clientWidth;n(t,e),i<s.clientWidth&&n()}),window),r=new ResizeObserver((t=>{const e=t[0],i=e.contentRect.width,n=e.contentRect.height;0===i&&0===n||a(i,n)}));return r.observe(s),function(t,e){Gi.size||window.addEventListener("resize",Qi),Gi.set(t,e)}(t,a),r}function tn(t,e,i){i&&i.disconnect(),"resize"===e&&function(t){Gi.delete(t),Gi.size||window.removeEventListener("resize",Qi)}(t)}function en(t,i,n){const o=t.canvas,s=e((e=>{null!==t.ctx&&n(function(t,e){const i=$i[t.type]||t.type,{x:n,y:o}=_e(t,e);return{type:i,chart:e,native:t,x:void 0!==n?n:null,y:void 0!==o?o:null}}(e,t))}),t,(t=>{const e=t[0];return[e,e.offsetX,e.offsetY]}));return function(t,e,i){t.addEventListener(e,i,Ui)}(o,i,s),s}class nn extends Hi{acquireContext(t,e){const i=t&&t.getContext&&t.getContext("2d");return i&&i.canvas===t?(function(t,e){const i=t.style,n=t.getAttribute("height"),o=t.getAttribute("width");if(t.$chartjs={initial:{height:n,width:o,style:{display:i.display,height:i.height,width:i.width}}},i.display=i.display||"block",i.boxSizing=i.boxSizing||"border-box",Yi(o)){const e=ke(t,"width");void 0!==e&&(t.width=e)}if(Yi(n))if(""===t.style.height)t.height=t.width/(e||2);else{const e=ke(t,"height");void 0!==e&&(t.height=e)}}(t,e),i):null}releaseContext(t){const e=t.canvas;if(!e.$chartjs)return!1;const i=e.$chartjs.initial;["height","width"].forEach((t=>{const n=i[t];$(n)?e.removeAttribute(t):e.setAttribute(t,n)}));const n=i.style||{};return Object.keys(n).forEach((t=>{e.style[t]=n[t]})),e.width=e.width,delete e.$chartjs,!0}addEventListener(t,e,i){this.removeEventListener(t,e);const n=t.$proxies||(t.$proxies={}),o={attach:qi,detach:Ki,resize:Ji}[e]||en;n[e]=o(t,e,i)}removeEventListener(t,e){const i=t.$proxies||(t.$proxies={}),n=i[e];if(!n)return;({attach:tn,detach:tn,resize:tn}[e]||Xi)(t,e,n),i[e]=void 0}getDevicePixelRatio(){return window.devicePixelRatio}getMaximumSize(t,e,i,n){return ve(t,e,i,n)}isAttached(t){const e=fe(t);return!(!e||!e.isConnected)}}function on(t){return!ue()||"undefined"!=typeof OffscreenCanvas&&t instanceof OffscreenCanvas?ji:nn}var sn=Object.freeze({__proto__:null,_detectPlatform:on,BasePlatform:Hi,BasicPlatform:ji,DomPlatform:nn});const an="transparent",rn={boolean:(t,e,i)=>i>.5?e:t,color(t,e,i){const n=W(t||an),o=n.valid&&W(e||an);return o&&o.valid?o.mix(n,i).hexString():e},number:(t,e,i)=>t+(e-t)*i};class ln{constructor(t,e,i,n){const o=e[i];n=We([t.to,n,o,t.from]);const s=We([t.from,o,n]);this._active=!0,this._fn=t.fn||rn[t.type||typeof s],this._easing=ki[t.easing]||ki.linear,this._start=Math.floor(Date.now()+(t.delay||0)),this._duration=this._total=Math.floor(t.duration),this._loop=!!t.loop,this._target=e,this._prop=i,this._from=s,this._to=n,this._promises=void 0}active(){return this._active}update(t,e,i){const n=this;if(n._active){n._notify(!1);const o=n._target[n._prop],s=i-n._start,a=n._duration-s;n._start=i,n._duration=Math.floor(Math.max(a,t.duration)),n._total+=s,n._loop=!!t.loop,n._to=We([t.to,e,o,t.from]),n._from=We([t.from,o,e])}}cancel(){const t=this;t._active&&(t.tick(Date.now()),t._active=!1,t._notify(!1))}tick(t){const e=this,i=t-e._start,n=e._duration,o=e._prop,s=e._from,a=e._loop,r=e._to;let l;if(e._active=s!==r&&(a||i<n),!e._active)return e._target[o]=r,void e._notify(!0);i<0?e._target[o]=s:(l=i/n%2,l=a&&l>1?2-l:l,l=e._easing(Math.min(1,Math.max(0,l))),e._target[o]=e._fn(s,r,l))}wait(){const t=this._promises||(this._promises=[]);return new Promise(((e,i)=>{t.push({res:e,rej:i})}))}_notify(t){const e=t?"res":"rej",i=this._promises||[];for(let t=0;t<i.length;t++)i[t][e]()}}xt.set("animation",{delay:void 0,duration:1e3,easing:"easeOutQuart",fn:void 0,from:void 0,loop:void 0,to:void 0,type:void 0});const cn=Object.keys(xt.animation);xt.describe("animation",{_fallback:!1,_indexable:!1,_scriptable:t=>"onProgress"!==t&&"onComplete"!==t&&"fn"!==t}),xt.set("animations",{colors:{type:"color",properties:["color","borderColor","backgroundColor"]},numbers:{type:"number",properties:["x","y","borderWidth","radius","tension"]}}),xt.describe("animations",{_fallback:"animation"}),xt.set("transitions",{active:{animation:{duration:400}},resize:{animation:{duration:0}},show:{animations:{colors:{from:"transparent"},visible:{type:"boolean",duration:0}}},hide:{animations:{colors:{to:"transparent"},visible:{type:"boolean",easing:"linear",fn:t=>0|t}}}});class hn{constructor(t,e){this._chart=t,this._properties=new Map,this.configure(e)}configure(t){if(!U(t))return;const e=this._properties;Object.getOwnPropertyNames(t).forEach((i=>{const n=t[i];if(!U(n))return;const o={};for(const t of cn)o[t]=n[t];(Y(n.properties)&&n.properties||[i]).forEach((t=>{t!==i&&e.has(t)||e.set(t,o)}))}))}_animateOptions(t,e){const i=e.options,n=function(t,e){if(!e)return;let i=t.options;if(!i)return void(t.options=e);i.$shared&&(t.options=i=Object.assign({},i,{$shared:!1,$animations:{}}));return i}(t,i);if(!n)return[];const o=this._createAnimations(n,i);return i.$shared&&function(t,e){const i=[],n=Object.keys(e);for(let e=0;e<n.length;e++){const o=t[n[e]];o&&o.active()&&i.push(o.wait())}return Promise.all(i)}(t.options.$animations,i).then((()=>{t.options=i}),(()=>{})),o}_createAnimations(t,e){const i=this._properties,n=[],o=t.$animations||(t.$animations={}),s=Object.keys(e),a=Date.now();let r;for(r=s.length-1;r>=0;--r){const l=s[r];if("$"===l.charAt(0))continue;if("options"===l){n.push(...this._animateOptions(t,e));continue}const c=e[l];let h=o[l];const d=i.get(l);if(h){if(d&&h.active()){h.update(d,c,a);continue}h.cancel()}d&&d.duration?(o[l]=h=new ln(d,t,l,c),n.push(h)):t[l]=c}return n}update(t,e){if(0===this._properties.size)return void Object.assign(t,e);const i=this._createAnimations(t,e);return i.length?(a.add(this._chart,i),!0):void 0}}function dn(t,e){const i=t&&t.options||{},n=i.reverse,o=void 0===i.min?e:0,s=void 0===i.max?e:0;return{start:n?s:o,end:n?o:s}}function un(t,e){const i=[],n=t._getSortedDatasetMetas(e);let o,s;for(o=0,s=n.length;o<s;++o)i.push(n[o].index);return i}function fn(t,e,i,n){const o=t.keys,s="single"===n.mode;let a,r,l,c;if(null!==e){for(a=0,r=o.length;a<r;++a){if(l=+o[a],l===i){if(n.all)continue;break}c=t.values[l],X(c)&&(s||0===e||Dt(e)===Dt(c))&&(e+=c)}return e}}function gn(t,e){const i=t&&t.options.stacked;return i||void 0===i&&void 0!==e.stack}function pn(t,e,i){const n=t[e]||(t[e]={});return n[i]||(n[i]={})}function mn(t,e,i){for(const n of e.getMatchingVisibleMetas("bar").reverse()){const e=t[n.index];if(i&&e>0||!i&&e<0)return n.index}return null}function xn(t,e){const{chart:i,_cachedMeta:n}=t,o=i._stacks||(i._stacks={}),{iScale:s,vScale:a,index:r}=n,l=s.axis,c=a.axis,h=function(t,e,i){return`${t.id}.${e.id}.${i.stack||i.type}`}(s,a,n),d=e.length;let u;for(let t=0;t<d;++t){const i=e[t],{[l]:n,[c]:s}=i;u=(i._stacks||(i._stacks={}))[c]=pn(o,h,n),u[r]=s,u._top=mn(u,a,!0),u._bottom=mn(u,a,!1)}}function bn(t,e){const i=t.scales;return Object.keys(i).filter((t=>i[t].axis===e)).shift()}function _n(t,e){const i=t.controller.index,n=t.vScale&&t.vScale.axis;if(n){e=e||t._parsed;for(const t of e){const e=t._stacks;if(!e||void 0===e[n]||void 0===e[n][i])return;delete e[n][i]}}}const yn=t=>"reset"===t||"none"===t,vn=(t,e)=>e?t:Object.assign({},t);class wn{constructor(t,e){this.chart=t,this._ctx=t.ctx,this.index=e,this._cachedDataOpts={},this._cachedMeta=this.getMeta(),this._type=this._cachedMeta.type,this.options=void 0,this._parsing=!1,this._data=void 0,this._objectData=void 0,this._sharedOptions=void 0,this._drawStart=void 0,this._drawCount=void 0,this.enableOptionSharing=!1,this.$context=void 0,this._syncList=[],this.initialize()}initialize(){const t=this,e=t._cachedMeta;t.configure(),t.linkScales(),e._stacked=gn(e.vScale,e),t.addElements()}updateIndex(t){this.index!==t&&_n(this._cachedMeta),this.index=t}linkScales(){const t=this,e=t.chart,i=t._cachedMeta,n=t.getDataset(),o=(t,e,i,n)=>"x"===t?e:"r"===t?n:i,s=i.xAxisID=K(n.xAxisID,bn(e,"x")),a=i.yAxisID=K(n.yAxisID,bn(e,"y")),r=i.rAxisID=K(n.rAxisID,bn(e,"r")),l=i.indexAxis,c=i.iAxisID=o(l,s,a,r),h=i.vAxisID=o(l,a,s,r);i.xScale=t.getScaleForId(s),i.yScale=t.getScaleForId(a),i.rScale=t.getScaleForId(r),i.iScale=t.getScaleForId(c),i.vScale=t.getScaleForId(h)}getDataset(){return this.chart.data.datasets[this.index]}getMeta(){return this.chart.getDatasetMeta(this.index)}getScaleForId(t){return this.chart.scales[t]}_getOtherScale(t){const e=this._cachedMeta;return t===e.iScale?e.vScale:e.iScale}reset(){this._update("reset")}_destroy(){const t=this._cachedMeta;this._data&&he(this._data,this),t._stacked&&_n(t)}_dataCheck(){const t=this,e=t.getDataset(),i=e.data||(e.data=[]),n=t._data;if(U(i))t._data=function(t){const e=Object.keys(t),i=new Array(e.length);let n,o,s;for(n=0,o=e.length;n<o;++n)s=e[n],i[n]={x:s,y:t[s]};return i}(i);else if(n!==i){if(n){he(n,t);const e=t._cachedMeta;_n(e),e._parsed=[]}i&&Object.isExtensible(i)&&ce(i,t),t._syncList=[],t._data=i}}addElements(){const t=this,e=t._cachedMeta;t._dataCheck(),t.datasetElementType&&(e.dataset=new t.datasetElementType)}buildOrUpdateElements(t){const e=this,i=e._cachedMeta,n=e.getDataset();let o=!1;e._dataCheck();const s=i._stacked;i._stacked=gn(i.vScale,i),i.stack!==n.stack&&(o=!0,_n(i),i.stack=n.stack),e._resyncElements(t),(o||s!==i._stacked)&&xn(e,i._parsed)}configure(){const t=this,e=t.chart.config,i=e.datasetScopeKeys(t._type),n=e.getOptionScopes(t.getDataset(),i,!0);t.options=e.createResolver(n,t.getContext()),t._parsing=t.options.parsing}parse(t,e){const i=this,{_cachedMeta:n,_data:o}=i,{iScale:s,_stacked:a}=n,r=s.axis;let l,c,h,d=0===t&&e===o.length||n._sorted,u=t>0&&n._parsed[t-1];if(!1===i._parsing)n._parsed=o,n._sorted=!0,h=o;else{h=Y(o[t])?i.parseArrayData(n,o,t,e):U(o[t])?i.parseObjectData(n,o,t,e):i.parsePrimitiveData(n,o,t,e);const s=()=>null===c[r]||u&&c[r]<u[r];for(l=0;l<e;++l)n._parsed[l+t]=c=h[l],d&&(s()&&(d=!1),u=c);n._sorted=d}a&&xn(i,h)}parsePrimitiveData(t,e,i,n){const{iScale:o,vScale:s}=t,a=o.axis,r=s.axis,l=o.getLabels(),c=o===s,h=new Array(n);let d,u,f;for(d=0,u=n;d<u;++d)f=d+i,h[d]={[a]:c||o.parse(l[f],f),[r]:s.parse(e[f],f)};return h}parseArrayData(t,e,i,n){const{xScale:o,yScale:s}=t,a=new Array(n);let r,l,c,h;for(r=0,l=n;r<l;++r)c=r+i,h=e[c],a[r]={x:o.parse(h[0],c),y:s.parse(h[1],c)};return a}parseObjectData(t,e,i,n){const{xScale:o,yScale:s}=t,{xAxisKey:a="x",yAxisKey:r="y"}=this._parsing,l=new Array(n);let c,h,d,u;for(c=0,h=n;c<h;++c)d=c+i,u=e[d],l[c]={x:o.parse(lt(u,a),d),y:s.parse(lt(u,r),d)};return l}getParsed(t){return this._cachedMeta._parsed[t]}getDataElement(t){return this._cachedMeta.data[t]}applyStack(t,e,i){const n=this.chart,o=this._cachedMeta,s=e[t.axis];return fn({keys:un(n,!0),values:e._stacks[t.axis]},s,o.index,{mode:i})}updateRangeFromParsed(t,e,i,n){const o=i[e.axis];let s=null===o?NaN:o;const a=n&&i._stacks[e.axis];n&&a&&(n.values=a,t.min=Math.min(t.min,s),t.max=Math.max(t.max,s),s=fn(n,o,this._cachedMeta.index,{all:!0})),t.min=Math.min(t.min,s),t.max=Math.max(t.max,s)}getMinMax(t,e){const i=this,n=i._cachedMeta,o=n._parsed,s=n._sorted&&t===n.iScale,a=o.length,r=i._getOtherScale(t),l=e&&n._stacked&&{keys:un(i.chart,!0),values:null},c={min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY},{min:h,max:d}=function(t){const{min:e,max:i,minDefined:n,maxDefined:o}=t.getUserBounds();return{min:n?e:Number.NEGATIVE_INFINITY,max:o?i:Number.POSITIVE_INFINITY}}(r);let u,f,g,p;function m(){return g=o[u],f=g[t.axis],p=g[r.axis],!X(f)||h>p||d<p}for(u=0;u<a&&(m()||(i.updateRangeFromParsed(c,t,g,l),!s));++u);if(s)for(u=a-1;u>=0;--u)if(!m()){i.updateRangeFromParsed(c,t,g,l);break}return c}getAllParsedValues(t){const e=this._cachedMeta._parsed,i=[];let n,o,s;for(n=0,o=e.length;n<o;++n)s=e[n][t.axis],X(s)&&i.push(s);return i}getMaxOverflow(){return!1}getLabelAndValue(t){const e=this._cachedMeta,i=e.iScale,n=e.vScale,o=this.getParsed(t);return{label:i?""+i.getLabelForValue(o[i.axis]):"",value:n?""+n.getLabelForValue(o[n.axis]):""}}_update(t){const e=this,i=e._cachedMeta;e.configure(),e._cachedDataOpts={},e.update(t||"default"),i._clip=function(t){let e,i,n,o;return U(t)?(e=t.top,i=t.right,n=t.bottom,o=t.left):e=i=n=o=t,{top:e,right:i,bottom:n,left:o,disabled:!1===t}}(K(e.options.clip,function(t,e,i){if(!1===i)return!1;const n=dn(t,i),o=dn(e,i);return{top:o.end,right:n.end,bottom:o.start,left:n.start}}(i.xScale,i.yScale,e.getMaxOverflow())))}update(t){}draw(){const t=this,e=t._ctx,i=t.chart,n=t._cachedMeta,o=n.data||[],s=i.chartArea,a=[],r=t._drawStart||0,l=t._drawCount||o.length-r;let c;for(n.dataset&&n.dataset.draw(e,s,r,l),c=r;c<r+l;++c){const t=o[c];t.hidden||(t.active?a.push(t):t.draw(e,s))}for(c=0;c<a.length;++c)a[c].draw(e,s)}getStyle(t,e){const i=e?"active":"default";return void 0===t&&this._cachedMeta.dataset?this.resolveDatasetElementOptions(i):this.resolveDataElementOptions(t||0,i)}getContext(t,e,i){const n=this,o=n.getDataset();let s;if(t>=0&&t<n._cachedMeta.data.length){const e=n._cachedMeta.data[t];s=e.$context||(e.$context=function(t,e,i){return Object.assign(Object.create(t),{active:!1,dataIndex:e,parsed:void 0,raw:void 0,element:i,index:e,mode:"default",type:"data"})}(n.getContext(),t,e)),s.parsed=n.getParsed(t),s.raw=o.data[t],s.index=s.dataIndex=t}else s=n.$context||(n.$context=function(t,e){return Object.assign(Object.create(t),{active:!1,dataset:void 0,datasetIndex:e,index:e,mode:"default",type:"dataset"})}(n.chart.getContext(),n.index)),s.dataset=o,s.index=s.datasetIndex=n.index;return s.active=!!e,s.mode=i,s}resolveDatasetElementOptions(t){return this._resolveElementOptions(this.datasetElementType.id,t)}resolveDataElementOptions(t,e){return this._resolveElementOptions(this.dataElementType.id,e,t)}_resolveElementOptions(t,e="default",i){const n=this,o="active"===e,s=n._cachedDataOpts,a=t+"-"+e,r=s[a],l=n.enableOptionSharing&&ht(i);if(r)return vn(r,l);const c=n.chart.config,h=c.datasetElementScopeKeys(n._type,t),d=o?[`${t}Hover`,"hover",t,""]:[t,""],u=c.getOptionScopes(n.getDataset(),h),f=Object.keys(xt.elements[t]),g=c.resolveNamedOptions(u,f,(()=>n.getContext(i,o)),d);return g.$shared&&(g.$shared=l,s[a]=Object.freeze(vn(g,l))),g}_resolveAnimations(t,e,i){const n=this,o=n.chart,s=n._cachedDataOpts,a=`animation-${e}`,r=s[a];if(r)return r;let l;if(!1!==o.options.animation){const o=n.chart.config,s=o.datasetAnimationScopeKeys(n._type,e),a=o.getOptionScopes(n.getDataset(),s);l=o.createResolver(a,n.getContext(t,i,e))}const c=new hn(o,l&&l.animations);return l&&l._cacheable&&(s[a]=Object.freeze(c)),c}getSharedOptions(t){if(t.$shared)return this._sharedOptions||(this._sharedOptions=Object.assign({},t))}includeOptions(t,e){return!e||yn(t)||this.chart._animationsDisabled}updateElement(t,e,i,n){yn(n)?Object.assign(t,i):this._resolveAnimations(e,n).update(t,i)}updateSharedOptions(t,e,i){t&&!yn(e)&&this._resolveAnimations(void 0,e).update(t,i)}_setStyle(t,e,i,n){t.active=n;const o=this.getStyle(e,n);this._resolveAnimations(e,i,n).update(t,{options:!n&&this.getSharedOptions(o)||o})}removeHoverStyle(t,e,i){this._setStyle(t,i,"active",!1)}setHoverStyle(t,e,i){this._setStyle(t,i,"active",!0)}_removeDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,"active",!1)}_setDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,"active",!0)}_resyncElements(t){const e=this,i=e._data,n=e._cachedMeta.data;for(const[t,i,n]of e._syncList)e[t](i,n);e._syncList=[];const o=n.length,s=i.length,a=Math.min(s,o);a&&e.parse(0,a),s>o?e._insertElements(o,s-o,t):s<o&&e._removeElements(s,o-s)}_insertElements(t,e,i=!0){const n=this,o=n._cachedMeta,s=o.data,a=t+e;let r;const l=t=>{for(t.length+=e,r=t.length-1;r>=a;r--)t[r]=t[r-e]};for(l(s),r=t;r<a;++r)s[r]=new n.dataElementType;n._parsing&&l(o._parsed),n.parse(t,e),i&&n.updateElements(s,t,e,"reset")}updateElements(t,e,i,n){}_removeElements(t,e){const i=this._cachedMeta;if(this._parsing){const n=i._parsed.splice(t,e);i._stacked&&_n(i,n)}i.data.splice(t,e)}_onDataPush(){const t=arguments.length;this._syncList.push(["_insertElements",this.getDataset().data.length-t,t])}_onDataPop(){this._syncList.push(["_removeElements",this._cachedMeta.data.length-1,1])}_onDataShift(){this._syncList.push(["_removeElements",0,1])}_onDataSplice(t,e){this._syncList.push(["_removeElements",t,e]),this._syncList.push(["_insertElements",t,arguments.length-2])}_onDataUnshift(){this._syncList.push(["_insertElements",0,arguments.length])}}wn.defaults={},wn.prototype.datasetElementType=null,wn.prototype.dataElementType=null;class Mn{constructor(){this.x=void 0,this.y=void 0,this.active=!1,this.options=void 0,this.$animations=void 0}tooltipPosition(t){const{x:e,y:i}=this.getProps(["x","y"],t);return{x:e,y:i}}hasValue(){return Tt(this.x)&&Tt(this.y)}getProps(t,e){const i=this,n=this.$animations;if(!e||!n)return i;const o={};return t.forEach((t=>{o[t]=n[t]&&n[t].active()?n[t]._to:i[t]})),o}}Mn.defaults={},Mn.defaultRoutes=void 0;const kn={values:t=>Y(t)?t:""+t,numeric(t,e,i){if(0===t)return"0";const n=this.chart.options.locale;let o,s=t;if(i.length>1){const e=Math.max(Math.abs(i[0].value),Math.abs(i[i.length-1].value));(e<1e-4||e>1e15)&&(o="scientific"),s=function(t,e){let i=e.length>3?e[2].value-e[1].value:e[1].value-e[0].value;Math.abs(i)>=1&&t!==Math.floor(t)&&(i=t-Math.floor(t));return i}(t,i)}const a=Pt(Math.abs(s)),r=Math.max(Math.min(-1*Math.floor(a),20),0),l={notation:o,minimumFractionDigits:r,maximumFractionDigits:r};return Object.assign(l,this.options.ticks.format),Oi(t,n,l)},logarithmic(t,e,i){if(0===t)return"0";const n=t/Math.pow(10,Math.floor(Pt(t)));return 1===n||2===n||5===n?kn.numeric.call(this,t,e,i):""}};var Sn={formatters:kn};function Pn(t,e){const i=t.options.ticks,n=i.maxTicksLimit||function(t){const e=t.options.offset,i=t._tickSize(),n=t._length/i+(e?0:1),o=t._maxLength/i;return Math.floor(Math.min(n,o))}(t),o=i.major.enabled?function(t){const e=[];let i,n;for(i=0,n=t.length;i<n;i++)t[i].major&&e.push(i);return e}(e):[],s=o.length,a=o[0],r=o[s-1],l=[];if(s>n)return function(t,e,i,n){let o,s=0,a=i[0];for(n=Math.ceil(n),o=0;o<t.length;o++)o===a&&(e.push(t[o]),s++,a=i[s*n])}(e,l,o,s/n),l;const c=function(t,e,i){const n=function(t){const e=t.length;let i,n;if(e<2)return!1;for(n=t[0],i=1;i<e;++i)if(t[i]-t[i-1]!==n)return!1;return n}(t),o=e.length/i;if(!n)return Math.max(o,1);const s=Ot(n);for(let t=0,e=s.length-1;t<e;t++){const e=s[t];if(e>o)return e}return Math.max(o,1)}(o,e,n);if(s>0){let t,i;const n=s>1?Math.round((r-a)/(s-1)):null;for(Dn(e,l,c,$(n)?0:a-n,a),t=0,i=s-1;t<i;t++)Dn(e,l,c,o[t],o[t+1]);return Dn(e,l,c,r,$(n)?e.length:r+n),l}return Dn(e,l,c),l}function Dn(t,e,i,n,o){const s=K(n,0),a=Math.min(K(o,t.length),t.length);let r,l,c,h=0;for(i=Math.ceil(i),o&&(r=o-n,i=r/Math.floor(r/i)),c=s;c<0;)h++,c=Math.round(s+h*i);for(l=Math.max(s,0);l<a;l++)l===c&&(e.push(t[l]),h++,c=Math.round(s+h*i))}xt.set("scale",{display:!0,offset:!1,reverse:!1,beginAtZero:!1,bounds:"ticks",grace:0,grid:{display:!0,lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickLength:8,tickWidth:(t,e)=>e.lineWidth,tickColor:(t,e)=>e.color,offset:!1,borderDash:[],borderDashOffset:0,borderWidth:1},title:{display:!1,text:"",padding:{top:4,bottom:4}},ticks:{minRotation:0,maxRotation:50,mirror:!1,textStrokeWidth:0,textStrokeColor:"",padding:3,display:!0,autoSkip:!0,autoSkipPadding:3,labelOffset:0,callback:Sn.formatters.values,minor:{},major:{},align:"center",crossAlign:"near",showLabelBackdrop:!1,backdropColor:"rgba(255, 255, 255, 0.75)",backdropPadding:2}}),xt.route("scale.ticks","color","","color"),xt.route("scale.grid","color","","borderColor"),xt.route("scale.grid","borderColor","","borderColor"),xt.route("scale.title","color","","color"),xt.describe("scale",{_fallback:!1,_scriptable:t=>!t.startsWith("before")&&!t.startsWith("after")&&"callback"!==t&&"parser"!==t,_indexable:t=>"borderDash"!==t&&"tickBorderDash"!==t}),xt.describe("scales",{_fallback:"scale"}),xt.describe("scale.ticks",{_scriptable:t=>"backdropPadding"!==t&&"callback"!==t,_indexable:t=>"backdropPadding"!==t});const Cn=(t,e,i)=>"top"===e||"left"===e?t[e]+i:t[e]-i;function On(t,e){const i=[],n=t.length/e,o=t.length;let s=0;for(;s<o;s+=n)i.push(t[Math.floor(s)]);return i}function Tn(t,e,i){const n=t.ticks.length,o=Math.min(e,n-1),s=t._startPixel,a=t._endPixel,r=1e-6;let l,c=t.getPixelForTick(o);if(!(i&&(l=1===n?Math.max(c-s,a-c):0===e?(t.getPixelForTick(1)-c)/2:(c-t.getPixelForTick(o-1))/2,c+=o<e?l:-l,c<s-r||c>a+r)))return c}function An(t){return t.drawTicks?t.tickLength:0}function Ln(t,e){if(!t.display)return 0;const i=Ve(t.font,e),n=Be(t.padding);return(Y(t.text)?t.text.length:1)*i.lineHeight+n.height}function Rn(t,e,i){let o=n(t);return(i&&"right"!==e||!i&&"right"===e)&&(o=(t=>"left"===t?"right":"right"===t?"left":t)(o)),o}class En extends Mn{constructor(t){super(),this.id=t.id,this.type=t.type,this.options=void 0,this.ctx=t.ctx,this.chart=t.chart,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this._margins={left:0,right:0,top:0,bottom:0},this.maxWidth=void 0,this.maxHeight=void 0,this.paddingTop=void 0,this.paddingBottom=void 0,this.paddingLeft=void 0,this.paddingRight=void 0,this.axis=void 0,this.labelRotation=void 0,this.min=void 0,this.max=void 0,this._range=void 0,this.ticks=[],this._gridLineItems=null,this._labelItems=null,this._labelSizes=null,this._length=0,this._maxLength=0,this._longestTextCache={},this._startPixel=void 0,this._endPixel=void 0,this._reversePixels=!1,this._userMax=void 0,this._userMin=void 0,this._suggestedMax=void 0,this._suggestedMin=void 0,this._ticksLength=0,this._borderValue=0,this._cache={},this._dataLimitsCached=!1,this.$context=void 0}init(t){const e=this;e.options=t.setContext(e.getContext()),e.axis=t.axis,e._userMin=e.parse(t.min),e._userMax=e.parse(t.max),e._suggestedMin=e.parse(t.suggestedMin),e._suggestedMax=e.parse(t.suggestedMax)}parse(t,e){return t}getUserBounds(){let{_userMin:t,_userMax:e,_suggestedMin:i,_suggestedMax:n}=this;return t=q(t,Number.POSITIVE_INFINITY),e=q(e,Number.NEGATIVE_INFINITY),i=q(i,Number.POSITIVE_INFINITY),n=q(n,Number.NEGATIVE_INFINITY),{min:q(t,i),max:q(e,n),minDefined:X(t),maxDefined:X(e)}}getMinMax(t){const e=this;let i,{min:n,max:o,minDefined:s,maxDefined:a}=e.getUserBounds();if(s&&a)return{min:n,max:o};const r=e.getMatchingVisibleMetas();for(let l=0,c=r.length;l<c;++l)i=r[l].controller.getMinMax(e,t),s||(n=Math.min(n,i.min)),a||(o=Math.max(o,i.max));return{min:q(n,q(o,n)),max:q(o,q(n,o))}}getPadding(){const t=this;return{left:t.paddingLeft||0,top:t.paddingTop||0,right:t.paddingRight||0,bottom:t.paddingBottom||0}}getTicks(){return this.ticks}getLabels(){const t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels||[]}beforeLayout(){this._cache={},this._dataLimitsCached=!1}beforeUpdate(){Q(this.options.beforeUpdate,[this])}update(t,e,i){const n=this,o=n.options.ticks,s=o.sampleSize;n.beforeUpdate(),n.maxWidth=t,n.maxHeight=e,n._margins=i=Object.assign({left:0,right:0,top:0,bottom:0},i),n.ticks=null,n._labelSizes=null,n._gridLineItems=null,n._labelItems=null,n.beforeSetDimensions(),n.setDimensions(),n.afterSetDimensions(),n._maxLength=n.isHorizontal()?n.width+i.left+i.right:n.height+i.top+i.bottom,n._dataLimitsCached||(n.beforeDataLimits(),n.determineDataLimits(),n.afterDataLimits(),n._range=Ne(n,n.options.grace),n._dataLimitsCached=!0),n.beforeBuildTicks(),n.ticks=n.buildTicks()||[],n.afterBuildTicks();const a=s<n.ticks.length;n._convertTicksToLabels(a?On(n.ticks,s):n.ticks),n.configure(),n.beforeCalculateLabelRotation(),n.calculateLabelRotation(),n.afterCalculateLabelRotation(),o.display&&(o.autoSkip||"auto"===o.source)&&(n.ticks=Pn(n,n.ticks),n._labelSizes=null),a&&n._convertTicksToLabels(n.ticks),n.beforeFit(),n.fit(),n.afterFit(),n.afterUpdate()}configure(){const t=this;let e,i,n=t.options.reverse;t.isHorizontal()?(e=t.left,i=t.right):(e=t.top,i=t.bottom,n=!n),t._startPixel=e,t._endPixel=i,t._reversePixels=n,t._length=i-e,t._alignToPixels=t.options.alignToPixels}afterUpdate(){Q(this.options.afterUpdate,[this])}beforeSetDimensions(){Q(this.options.beforeSetDimensions,[this])}setDimensions(){const t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0}afterSetDimensions(){Q(this.options.afterSetDimensions,[this])}_callHooks(t){const e=this;e.chart.notifyPlugins(t,e.getContext()),Q(e.options[t],[e])}beforeDataLimits(){this._callHooks("beforeDataLimits")}determineDataLimits(){}afterDataLimits(){this._callHooks("afterDataLimits")}beforeBuildTicks(){this._callHooks("beforeBuildTicks")}buildTicks(){return[]}afterBuildTicks(){this._callHooks("afterBuildTicks")}beforeTickToLabelConversion(){Q(this.options.beforeTickToLabelConversion,[this])}generateTickLabels(t){const e=this,i=e.options.ticks;let n,o,s;for(n=0,o=t.length;n<o;n++)s=t[n],s.label=Q(i.callback,[s.value,n,t],e)}afterTickToLabelConversion(){Q(this.options.afterTickToLabelConversion,[this])}beforeCalculateLabelRotation(){Q(this.options.beforeCalculateLabelRotation,[this])}calculateLabelRotation(){const t=this,e=t.options,i=e.ticks,n=t.ticks.length,o=i.minRotation||0,s=i.maxRotation;let a,r,l,c=o;if(!t._isVisible()||!i.display||o>=s||n<=1||!t.isHorizontal())return void(t.labelRotation=o);const h=t._getLabelSizes(),d=h.widest.width,u=h.highest.height,f=Ht(t.chart.width-d,0,t.maxWidth);a=e.offset?t.maxWidth/n:f/(n-1),d+6>a&&(a=f/(n-(e.offset?.5:1)),r=t.maxHeight-An(e.grid)-i.padding-Ln(e.title,t.chart.options.font),l=Math.sqrt(d*d+u*u),c=It(Math.min(Math.asin(Ht((h.highest.height+6)/a,-1,1)),Math.asin(Ht(r/l,-1,1))-Math.asin(Ht(u/l,-1,1)))),c=Math.max(o,Math.min(s,c))),t.labelRotation=c}afterCalculateLabelRotation(){Q(this.options.afterCalculateLabelRotation,[this])}beforeFit(){Q(this.options.beforeFit,[this])}fit(){const t=this,e={width:0,height:0},{chart:i,options:{ticks:n,title:o,grid:s}}=t,a=t._isVisible(),r=t.isHorizontal();if(a){const a=Ln(o,i.options.font);if(r?(e.width=t.maxWidth,e.height=An(s)+a):(e.height=t.maxHeight,e.width=An(s)+a),n.display&&t.ticks.length){const{first:i,last:o,widest:s,highest:a}=t._getLabelSizes(),l=2*n.padding,c=Et(t.labelRotation),h=Math.cos(c),d=Math.sin(c);if(r){const i=n.mirror?0:d*s.width+h*a.height;e.height=Math.min(t.maxHeight,e.height+i+l)}else{const i=n.mirror?0:h*s.width+d*a.height;e.width=Math.min(t.maxWidth,e.width+i+l)}t._calculatePadding(i,o,d,h)}}t._handleMargins(),r?(t.width=t._length=i.width-t._margins.left-t._margins.right,t.height=e.height):(t.width=e.width,t.height=t._length=i.height-t._margins.top-t._margins.bottom)}_calculatePadding(t,e,i,n){const o=this,{ticks:{align:s,padding:a},position:r}=o.options,l=0!==o.labelRotation,c="top"!==r&&"x"===o.axis;if(o.isHorizontal()){const r=o.getPixelForTick(0)-o.left,h=o.right-o.getPixelForTick(o.ticks.length-1);let d=0,u=0;l?c?(d=n*t.width,u=i*e.height):(d=i*t.height,u=n*e.width):"start"===s?u=e.width:"end"===s?d=t.width:(d=t.width/2,u=e.width/2),o.paddingLeft=Math.max((d-r+a)*o.width/(o.width-r),0),o.paddingRight=Math.max((u-h+a)*o.width/(o.width-h),0)}else{let i=e.height/2,n=t.height/2;"start"===s?(i=0,n=t.height):"end"===s&&(i=e.height,n=0),o.paddingTop=i+a,o.paddingBottom=n+a}}_handleMargins(){const t=this;t._margins&&(t._margins.left=Math.max(t.paddingLeft,t._margins.left),t._margins.top=Math.max(t.paddingTop,t._margins.top),t._margins.right=Math.max(t.paddingRight,t._margins.right),t._margins.bottom=Math.max(t.paddingBottom,t._margins.bottom))}afterFit(){Q(this.options.afterFit,[this])}isHorizontal(){const{axis:t,position:e}=this.options;return"top"===e||"bottom"===e||"x"===t}isFullSize(){return this.options.fullSize}_convertTicksToLabels(t){const e=this;let i,n;for(e.beforeTickToLabelConversion(),e.generateTickLabels(t),i=0,n=t.length;i<n;i++)$(t[i].label)&&(t.splice(i,1),n--,i--);e.afterTickToLabelConversion()}_getLabelSizes(){const t=this;let e=t._labelSizes;if(!e){const i=t.options.ticks.sampleSize;let n=t.ticks;i<n.length&&(n=On(n,i)),t._labelSizes=e=t._computeLabelSizes(n,n.length)}return e}_computeLabelSizes(t,e){const{ctx:i,_longestTextCache:n}=this,o=[],s=[];let a,r,l,c,h,d,u,f,g,p,m,x=0,b=0;for(a=0;a<e;++a){if(c=t[a].label,h=this._resolveTickFontOptions(a),i.font=d=h.string,u=n[d]=n[d]||{data:{},gc:[]},f=h.lineHeight,g=p=0,$(c)||Y(c)){if(Y(c))for(r=0,l=c.length;r<l;++r)m=c[r],$(m)||Y(m)||(g=Yt(i,u.data,u.gc,g,m),p+=f)}else g=Yt(i,u.data,u.gc,g,c),p=f;o.push(g),s.push(p),x=Math.max(g,x),b=Math.max(p,b)}!function(t,e){J(t,(t=>{const i=t.gc,n=i.length/2;let o;if(n>e){for(o=0;o<n;++o)delete t.data[i[o]];i.splice(0,n)}}))}(n,e);const _=o.indexOf(x),y=s.indexOf(b),v=t=>({width:o[t]||0,height:s[t]||0});return{first:v(0),last:v(e-1),widest:v(_),highest:v(y),widths:o,heights:s}}getLabelForValue(t){return t}getPixelForValue(t,e){return NaN}getValueForPixel(t){}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getPixelForDecimal(t){const e=this;e._reversePixels&&(t=1-t);const i=e._startPixel+t*e._length;return jt(e._alignToPixels?Xt(e.chart,i,0):i)}getDecimalForPixel(t){const e=(t-this._startPixel)/this._length;return this._reversePixels?1-e:e}getBasePixel(){return this.getPixelForValue(this.getBaseValue())}getBaseValue(){const{min:t,max:e}=this;return t<0&&e<0?e:t>0&&e>0?t:0}getContext(t){const e=this,i=e.ticks||[];if(t>=0&&t<i.length){const n=i[t];return n.$context||(n.$context=function(t,e,i){return Object.assign(Object.create(t),{tick:i,index:e,type:"tick"})}(e.getContext(),t,n))}return e.$context||(e.$context=(n=e.chart.getContext(),o=e,Object.assign(Object.create(n),{scale:o,type:"scale"})));var n,o}_tickSize(){const t=this,e=t.options.ticks,i=Et(t.labelRotation),n=Math.abs(Math.cos(i)),o=Math.abs(Math.sin(i)),s=t._getLabelSizes(),a=e.autoSkipPadding||0,r=s?s.widest.width+a:0,l=s?s.highest.height+a:0;return t.isHorizontal()?l*n>r*o?r/n:l/o:l*o<r*n?l/n:r/o}_isVisible(){const t=this.options.display;return"auto"!==t?!!t:this.getMatchingVisibleMetas().length>0}_computeGridLineItems(t){const e=this,i=e.axis,n=e.chart,o=e.options,{grid:s,position:a}=o,r=s.offset,l=e.isHorizontal(),c=e.ticks.length+(r?1:0),h=An(s),d=[],u=s.setContext(e.getContext()),f=u.drawBorder?u.borderWidth:0,g=f/2,p=function(t){return Xt(n,t,f)};let m,x,b,_,y,v,w,M,k,S,P,D;if("top"===a)m=p(e.bottom),v=e.bottom-h,M=m-g,S=p(t.top)+g,D=t.bottom;else if("bottom"===a)m=p(e.top),S=t.top,D=p(t.bottom)-g,v=m+g,M=e.top+h;else if("left"===a)m=p(e.right),y=e.right-h,w=m-g,k=p(t.left)+g,P=t.right;else if("right"===a)m=p(e.left),k=t.left,P=p(t.right)-g,y=m+g,w=e.left+h;else if("x"===i){if("center"===a)m=p((t.top+t.bottom)/2+.5);else if(U(a)){const t=Object.keys(a)[0],i=a[t];m=p(e.chart.scales[t].getPixelForValue(i))}S=t.top,D=t.bottom,v=m+g,M=v+h}else if("y"===i){if("center"===a)m=p((t.left+t.right)/2);else if(U(a)){const t=Object.keys(a)[0],i=a[t];m=p(e.chart.scales[t].getPixelForValue(i))}y=m-g,w=y-h,k=t.left,P=t.right}const C=K(o.ticks.maxTicksLimit,c),O=Math.max(1,Math.ceil(c/C));for(x=0;x<c;x+=O){const t=s.setContext(e.getContext(x)),i=t.lineWidth,o=t.color,a=s.borderDash||[],c=t.borderDashOffset,h=t.tickWidth,u=t.tickColor,f=t.tickBorderDash||[],g=t.tickBorderDashOffset;b=Tn(e,x,r),void 0!==b&&(_=Xt(n,b,i),l?y=w=k=P=_:v=M=S=D=_,d.push({tx1:y,ty1:v,tx2:w,ty2:M,x1:k,y1:S,x2:P,y2:D,width:i,color:o,borderDash:a,borderDashOffset:c,tickWidth:h,tickColor:u,tickBorderDash:f,tickBorderDashOffset:g}))}return e._ticksLength=c,e._borderValue=m,d}_computeLabelItems(t){const e=this,i=e.axis,n=e.options,{position:o,ticks:s}=n,a=e.isHorizontal(),r=e.ticks,{align:l,crossAlign:c,padding:h,mirror:d}=s,u=An(n.grid),f=u+h,g=d?-h:f,p=-Et(e.labelRotation),m=[];let x,b,_,y,v,w,M,k,S,P,D,C,O="middle";if("top"===o)w=e.bottom-g,M=e._getXAxisLabelAlignment();else if("bottom"===o)w=e.top+g,M=e._getXAxisLabelAlignment();else if("left"===o){const t=e._getYAxisLabelAlignment(u);M=t.textAlign,v=t.x}else if("right"===o){const t=e._getYAxisLabelAlignment(u);M=t.textAlign,v=t.x}else if("x"===i){if("center"===o)w=(t.top+t.bottom)/2+f;else if(U(o)){const t=Object.keys(o)[0],i=o[t];w=e.chart.scales[t].getPixelForValue(i)+f}M=e._getXAxisLabelAlignment()}else if("y"===i){if("center"===o)v=(t.left+t.right)/2-f;else if(U(o)){const t=Object.keys(o)[0],i=o[t];v=e.chart.scales[t].getPixelForValue(i)}M=e._getYAxisLabelAlignment(u).textAlign}"y"===i&&("start"===l?O="top":"end"===l&&(O="bottom"));const T=e._getLabelSizes();for(x=0,b=r.length;x<b;++x){_=r[x],y=_.label;const t=s.setContext(e.getContext(x));k=e.getPixelForTick(x)+s.labelOffset,S=e._resolveTickFontOptions(x),P=S.lineHeight,D=Y(y)?y.length:1;const i=D/2,n=t.color,l=t.textStrokeColor,h=t.textStrokeWidth;let u;if(a?(v=k,C="top"===o?"near"===c||0!==p?-D*P+P/2:"center"===c?-T.highest.height/2-i*P+P:-T.highest.height+P/2:"near"===c||0!==p?P/2:"center"===c?T.highest.height/2-i*P:T.highest.height-D*P,d&&(C*=-1)):(w=k,C=(1-D)*P/2),t.showLabelBackdrop){const e=Be(t.backdropPadding),i=T.heights[x],n=T.widths[x];let o=w+C-e.top,s=v-e.left;switch(O){case"middle":o-=i/2;break;case"bottom":o-=i}switch(M){case"center":s-=n/2;break;case"right":s-=n}u={left:s,top:o,width:n+e.width,height:i+e.height,color:t.backdropColor}}m.push({rotation:p,label:y,font:S,color:n,strokeColor:l,strokeWidth:h,textOffset:C,textAlign:M,textBaseline:O,translation:[v,w],backdrop:u})}return m}_getXAxisLabelAlignment(){const{position:t,ticks:e}=this.options;if(-Et(this.labelRotation))return"top"===t?"left":"right";let i="center";return"start"===e.align?i="left":"end"===e.align&&(i="right"),i}_getYAxisLabelAlignment(t){const e=this,{position:i,ticks:{crossAlign:n,mirror:o,padding:s}}=e.options,a=t+s,r=e._getLabelSizes().widest.width;let l,c;return"left"===i?o?(l="left",c=e.right+s):(c=e.right-a,"near"===n?l="right":"center"===n?(l="center",c-=r/2):(l="left",c=e.left)):"right"===i?o?(l="right",c=e.left+s):(c=e.left+a,"near"===n?l="left":"center"===n?(l="center",c+=r/2):(l="right",c=e.right)):l="right",{textAlign:l,x:c}}_computeLabelArea(){const t=this;if(t.options.ticks.mirror)return;const e=t.chart,i=t.options.position;return"left"===i||"right"===i?{top:0,left:t.left,bottom:e.height,right:t.right}:"top"===i||"bottom"===i?{top:t.top,left:0,bottom:t.bottom,right:e.width}:void 0}drawBackground(){const{ctx:t,options:{backgroundColor:e},left:i,top:n,width:o,height:s}=this;e&&(t.save(),t.fillStyle=e,t.fillRect(i,n,o,s),t.restore())}getLineWidthForValue(t){const e=this,i=e.options.grid;if(!e._isVisible()||!i.display)return 0;const n=e.ticks.findIndex((e=>e.value===t));if(n>=0){return i.setContext(e.getContext(n)).lineWidth}return 0}drawGrid(t){const e=this,i=e.options.grid,n=e.ctx,o=e._gridLineItems||(e._gridLineItems=e._computeGridLineItems(t));let s,a;const r=(t,e,i)=>{i.width&&i.color&&(n.save(),n.lineWidth=i.width,n.strokeStyle=i.color,n.setLineDash(i.borderDash||[]),n.lineDashOffset=i.borderDashOffset,n.beginPath(),n.moveTo(t.x,t.y),n.lineTo(e.x,e.y),n.stroke(),n.restore())};if(i.display)for(s=0,a=o.length;s<a;++s){const t=o[s];i.drawOnChartArea&&r({x:t.x1,y:t.y1},{x:t.x2,y:t.y2},t),i.drawTicks&&r({x:t.tx1,y:t.ty1},{x:t.tx2,y:t.ty2},{color:t.tickColor,width:t.tickWidth,borderDash:t.tickBorderDash,borderDashOffset:t.tickBorderDashOffset})}}drawBorder(){const t=this,{chart:e,ctx:i,options:{grid:n}}=t,o=n.setContext(t.getContext()),s=n.drawBorder?o.borderWidth:0;if(!s)return;const a=n.setContext(t.getContext(0)).lineWidth,r=t._borderValue;let l,c,h,d;t.isHorizontal()?(l=Xt(e,t.left,s)-s/2,c=Xt(e,t.right,a)+a/2,h=d=r):(h=Xt(e,t.top,s)-s/2,d=Xt(e,t.bottom,a)+a/2,l=c=r),i.save(),i.lineWidth=o.borderWidth,i.strokeStyle=o.borderColor,i.beginPath(),i.moveTo(l,h),i.lineTo(c,d),i.stroke(),i.restore()}drawLabels(t){const e=this;if(!e.options.ticks.display)return;const i=e.ctx,n=e._computeLabelArea();n&&Zt(i,n);const o=e._labelItems||(e._labelItems=e._computeLabelItems(t));let s,a;for(s=0,a=o.length;s<a;++s){const t=o[s],e=t.font,n=t.label;t.backdrop&&(i.fillStyle=t.backdrop.color,i.fillRect(t.backdrop.left,t.backdrop.top,t.backdrop.width,t.backdrop.height)),ee(i,n,0,t.textOffset,e,t)}n&&Qt(i)}drawTitle(){const{ctx:t,options:{position:e,title:i,reverse:n}}=this;if(!i.display)return;const s=Ve(i.font),a=Be(i.padding),r=i.align;let l=s.lineHeight/2;"bottom"===e||"center"===e||U(e)?(l+=a.bottom,Y(i.text)&&(l+=s.lineHeight*(i.text.length-1))):l+=a.top;const{titleX:c,titleY:h,maxWidth:d,rotation:u}=function(t,e,i,n){const{top:s,left:a,bottom:r,right:l,chart:c}=t,{chartArea:h,scales:d}=c;let u,f,g,p=0;const m=r-s,x=l-a;if(t.isHorizontal()){if(f=o(n,a,l),U(i)){const t=Object.keys(i)[0],n=i[t];g=d[t].getPixelForValue(n)+m-e}else g="center"===i?(h.bottom+h.top)/2+m-e:Cn(t,i,e);u=l-a}else{if(U(i)){const t=Object.keys(i)[0],n=i[t];f=d[t].getPixelForValue(n)-x+e}else f="center"===i?(h.left+h.right)/2-x+e:Cn(t,i,e);g=o(n,r,s),p="left"===i?-Mt:Mt}return{titleX:f,titleY:g,maxWidth:u,rotation:p}}(this,l,e,r);ee(t,i.text,0,0,s,{color:i.color,maxWidth:d,rotation:u,textAlign:Rn(r,e,n),textBaseline:"middle",translation:[c,h]})}draw(t){const e=this;e._isVisible()&&(e.drawBackground(),e.drawGrid(t),e.drawBorder(),e.drawTitle(),e.drawLabels(t))}_layers(){const t=this,e=t.options,i=e.ticks&&e.ticks.z||0,n=K(e.grid&&e.grid.z,-1);return t._isVisible()&&t.draw===En.prototype.draw?[{z:n,draw(e){t.drawBackground(),t.drawGrid(e),t.drawTitle()}},{z:n+1,draw(){t.drawBorder()}},{z:i,draw(e){t.drawLabels(e)}}]:[{z:i,draw(e){t.draw(e)}}]}getMatchingVisibleMetas(t){const e=this,i=e.chart.getSortedVisibleDatasetMetas(),n=e.axis+"AxisID",o=[];let s,a;for(s=0,a=i.length;s<a;++s){const a=i[s];a[n]!==e.id||t&&a.type!==t||o.push(a)}return o}_resolveTickFontOptions(t){return Ve(this.options.ticks.setContext(this.getContext(t)).font)}_maxDigits(){const t=this,e=t._resolveTickFontOptions(0).lineHeight;return(t.isHorizontal()?t.width:t.height)/e}}class In{constructor(t,e,i){this.type=t,this.scope=e,this.override=i,this.items=Object.create(null)}isForType(t){return Object.prototype.isPrototypeOf.call(this.type.prototype,t.prototype)}register(t){const e=this,i=Object.getPrototypeOf(t);let n;(function(t){return"id"in t&&"defaults"in t})(i)&&(n=e.register(i));const o=e.items,s=t.id,a=e.scope+"."+s;if(!s)throw new Error("class does not have id: "+t);return s in o||(o[s]=t,function(t,e,i){const n=ot(Object.create(null),[i?xt.get(i):{},xt.get(e),t.defaults]);xt.set(e,n),t.defaultRoutes&&function(t,e){Object.keys(e).forEach((i=>{const n=i.split("."),o=n.pop(),s=[t].concat(n).join("."),a=e[i].split("."),r=a.pop(),l=a.join(".");xt.route(s,o,l,r)}))}(e,t.defaultRoutes);t.descriptors&&xt.describe(e,t.descriptors)}(t,a,n),e.override&&xt.override(t.id,t.overrides)),a}get(t){return this.items[t]}unregister(t){const e=this.items,i=t.id,n=this.scope;i in e&&delete e[i],n&&i in xt[n]&&(delete xt[n][i],this.override&&delete ft[i])}}var zn=new class{constructor(){this.controllers=new In(wn,"datasets",!0),this.elements=new In(Mn,"elements"),this.plugins=new In(Object,"plugins"),this.scales=new In(En,"scales"),this._typedRegistries=[this.controllers,this.scales,this.elements]}add(...t){this._each("register",t)}remove(...t){this._each("unregister",t)}addControllers(...t){this._each("register",t,this.controllers)}addElements(...t){this._each("register",t,this.elements)}addPlugins(...t){this._each("register",t,this.plugins)}addScales(...t){this._each("register",t,this.scales)}getController(t){return this._get(t,this.controllers,"controller")}getElement(t){return this._get(t,this.elements,"element")}getPlugin(t){return this._get(t,this.plugins,"plugin")}getScale(t){return this._get(t,this.scales,"scale")}removeControllers(...t){this._each("unregister",t,this.controllers)}removeElements(...t){this._each("unregister",t,this.elements)}removePlugins(...t){this._each("unregister",t,this.plugins)}removeScales(...t){this._each("unregister",t,this.scales)}_each(t,e,i){const n=this;[...e].forEach((e=>{const o=i||n._getRegistryForType(e);i||o.isForType(e)||o===n.plugins&&e.id?n._exec(t,o,e):J(e,(e=>{const o=i||n._getRegistryForType(e);n._exec(t,o,e)}))}))}_exec(t,e,i){const n=ct(t);Q(i["before"+n],[],i),e[t](i),Q(i["after"+n],[],i)}_getRegistryForType(t){for(let e=0;e<this._typedRegistries.length;e++){const i=this._typedRegistries[e];if(i.isForType(t))return i}return this.plugins}_get(t,e,i){const n=e.get(t);if(void 0===n)throw new Error('"'+t+'" is not a registered '+i+".");return n}};class Fn{constructor(){this._init=[]}notify(t,e,i,n){const o=this;"beforeInit"===e&&(o._init=o._createDescriptors(t,!0),o._notify(o._init,t,"install"));const s=n?o._descriptors(t).filter(n):o._descriptors(t),a=o._notify(s,t,e,i);return"destroy"===e&&(o._notify(s,t,"stop"),o._notify(o._init,t,"uninstall")),a}_notify(t,e,i,n){n=n||{};for(const o of t){const t=o.plugin;if(!1===Q(t[i],[e,n,o.options],t)&&n.cancelable)return!1}return!0}invalidate(){$(this._cache)||(this._oldCache=this._cache,this._cache=void 0)}_descriptors(t){if(this._cache)return this._cache;const e=this._cache=this._createDescriptors(t);return this._notifyStateChanges(t),e}_createDescriptors(t,e){const i=t&&t.config,n=K(i.options&&i.options.plugins,{}),o=function(t){const e=[],i=Object.keys(zn.plugins.items);for(let t=0;t<i.length;t++)e.push(zn.getPlugin(i[t]));const n=t.plugins||[];for(let t=0;t<n.length;t++){const i=n[t];-1===e.indexOf(i)&&e.push(i)}return e}(i);return!1!==n||e?function(t,e,i,n){const o=[],s=t.getContext();for(let a=0;a<e.length;a++){const r=e[a],l=Bn(i[r.id],n);null!==l&&o.push({plugin:r,options:Vn(t.config,r,l,s)})}return o}(t,o,n,e):[]}_notifyStateChanges(t){const e=this._oldCache||[],i=this._cache,n=(t,e)=>t.filter((t=>!e.some((e=>t.plugin.id===e.plugin.id))));this._notify(n(e,i),t,"stop"),this._notify(n(i,e),t,"start")}}function Bn(t,e){return e||!1!==t?!0===t?{}:t:null}function Vn(t,e,i,n){const o=t.pluginScopeKeys(e),s=t.getOptionScopes(i,o);return t.createResolver(s,n,[""],{scriptable:!1,indexable:!1,allKeys:!0})}function Wn(t,e){const i=xt.datasets[t]||{};return((e.datasets||{})[t]||{}).indexAxis||e.indexAxis||i.indexAxis||"x"}function Nn(t,e){return"x"===t||"y"===t?t:e.axis||("top"===(i=e.position)||"bottom"===i?"x":"left"===i||"right"===i?"y":void 0)||t.charAt(0).toLowerCase();var i}function Hn(t){const e=t.options||(t.options={});e.plugins=K(e.plugins,{}),e.scales=function(t,e){const i=ft[t.type]||{scales:{}},n=e.scales||{},o=Wn(t.type,e),s=Object.create(null),a=Object.create(null);return Object.keys(n).forEach((t=>{const e=n[t],r=Nn(t,e),l=function(t,e){return t===e?"_index_":"_value_"}(r,o),c=i.scales||{};s[r]=s[r]||t,a[t]=st(Object.create(null),[{axis:r},e,c[r],c[l]])})),t.data.datasets.forEach((i=>{const o=i.type||t.type,r=i.indexAxis||Wn(o,e),l=(ft[o]||{}).scales||{};Object.keys(l).forEach((t=>{const e=function(t,e){let i=t;return"_index_"===t?i=e:"_value_"===t&&(i="x"===e?"y":"x"),i}(t,r),o=i[e+"AxisID"]||s[e]||e;a[o]=a[o]||Object.create(null),st(a[o],[{axis:e},n[o],l[t]])}))})),Object.keys(a).forEach((t=>{const e=a[t];st(e,[xt.scales[e.type],xt.scale])})),a}(t,e)}function jn(t){return(t=t||{}).datasets=t.datasets||[],t.labels=t.labels||[],t}const $n=new Map,Yn=new Set;function Un(t,e){let i=$n.get(t);return i||(i=e(),$n.set(t,i),Yn.add(i)),i}const Xn=(t,e,i)=>{const n=lt(e,i);void 0!==n&&t.add(n)};class qn{constructor(t){this._config=function(t){return(t=t||{}).data=jn(t.data),Hn(t),t}(t),this._scopeCache=new Map,this._resolverCache=new Map}get platform(){return this._config.platform}get type(){return this._config.type}set type(t){this._config.type=t}get data(){return this._config.data}set data(t){this._config.data=jn(t)}get options(){return this._config.options}set options(t){this._config.options=t}get plugins(){return this._config.plugins}update(){const t=this._config;this.clearCache(),Hn(t)}clearCache(){this._scopeCache.clear(),this._resolverCache.clear()}datasetScopeKeys(t){return Un(t,(()=>[[`datasets.${t}`,""]]))}datasetAnimationScopeKeys(t,e){return Un(`${t}.transition.${e}`,(()=>[[`datasets.${t}.transitions.${e}`,`transitions.${e}`],[`datasets.${t}`,""]]))}datasetElementScopeKeys(t,e){return Un(`${t}-${e}`,(()=>[[`datasets.${t}.elements.${e}`,`datasets.${t}`,`elements.${e}`,""]]))}pluginScopeKeys(t){const e=t.id;return Un(`${this.type}-plugin-${e}`,(()=>[[`plugins.${e}`,...t.additionalOptionScopes||[]]]))}_cachedScopes(t,e){const i=this._scopeCache;let n=i.get(t);return n&&!e||(n=new Map,i.set(t,n)),n}getOptionScopes(t,e,i){const{options:n,type:o}=this,s=this._cachedScopes(t,i),a=s.get(e);if(a)return a;const r=new Set;e.forEach((e=>{t&&(r.add(t),e.forEach((e=>Xn(r,t,e)))),e.forEach((t=>Xn(r,n,t))),e.forEach((t=>Xn(r,ft[o]||{},t))),e.forEach((t=>Xn(r,xt,t))),e.forEach((t=>Xn(r,gt,t)))}));const l=Array.from(r);return 0===l.length&&l.push(Object.create(null)),Yn.has(e)&&s.set(e,l),l}chartOptionScopes(){const{options:t,type:e}=this;return[t,ft[e]||{},xt.datasets[e]||{},{type:e},xt,gt]}resolveNamedOptions(t,e,i,n=[""]){const o={$shared:!0},{resolver:s,subPrefixes:a}=Kn(this._resolverCache,t,n);let r=s;if(function(t,e){const{isScriptable:i,isIndexable:n}=ni(t);for(const o of e)if(i(o)&&dt(t[o])||n(o)&&Y(t[o]))return!0;return!1}(s,e)){o.$shared=!1;r=ii(s,i=dt(i)?i():i,this.createResolver(t,i,a))}for(const t of e)o[t]=r[t];return o}createResolver(t,e,i=[""],n){const{resolver:o}=Kn(this._resolverCache,t,i);return U(e)?ii(o,e,void 0,n):o}}function Kn(t,e,i){let n=t.get(e);n||(n=new Map,t.set(e,n));const o=i.join();let s=n.get(o);if(!s){s={resolver:ei(e,i),subPrefixes:i.filter((t=>!t.toLowerCase().includes("hover")))},n.set(o,s)}return s}const Gn=["top","bottom","left","right","chartArea"];function Zn(t,e){return"top"===t||"bottom"===t||-1===Gn.indexOf(t)&&"x"===e}function Qn(t,e){return function(i,n){return i[t]===n[t]?i[e]-n[e]:i[t]-n[t]}}function Jn(t){const e=t.chart,i=e.options.animation;e.notifyPlugins("afterRender"),Q(i&&i.onComplete,[t],e)}function to(t){const e=t.chart,i=e.options.animation;Q(i&&i.onProgress,[t],e)}function eo(t){return ue()&&"string"==typeof t?t=document.getElementById(t):t&&t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas),t}const io={},no=t=>{const e=eo(t);return Object.values(io).filter((t=>t.canvas===e)).pop()};class oo{constructor(t,e){const n=this,o=this.config=new qn(e),s=eo(t),r=no(s);if(r)throw new Error("Canvas is already in use. Chart with ID '"+r.id+"' must be destroyed before the canvas can be reused.");const l=o.createResolver(o.chartOptionScopes(),n.getContext());this.platform=new(o.platform||on(s));const c=n.platform.acquireContext(s,l.aspectRatio),h=c&&c.canvas,d=h&&h.height,u=h&&h.width;this.id=j(),this.ctx=c,this.canvas=h,this.width=u,this.height=d,this._options=l,this._aspectRatio=this.aspectRatio,this._layers=[],this._metasets=[],this._stacks=void 0,this.boxes=[],this.currentDevicePixelRatio=void 0,this.chartArea=void 0,this._active=[],this._lastEvent=void 0,this._listeners={},this._responsiveListeners=void 0,this._sortedMetasets=[],this.scales={},this.scale=void 0,this._plugins=new Fn,this.$proxies={},this._hiddenIndices={},this.attached=!1,this._animationsDisabled=void 0,this.$context=void 0,this._doResize=i((()=>this.update("resize")),l.resizeDelay||0),io[n.id]=n,c&&h?(a.listen(n,"complete",Jn),a.listen(n,"progress",to),n._initialize(),n.attached&&n.update()):console.error("Failed to create chart: can't acquire context from the given item")}get aspectRatio(){const{options:{aspectRatio:t,maintainAspectRatio:e},width:i,height:n,_aspectRatio:o}=this;return $(t)?e&&o?o:n?i/n:null:t}get data(){return this.config.data}set data(t){this.config.data=t}get options(){return this._options}set options(t){this.config.options=t}_initialize(){const t=this;return t.notifyPlugins("beforeInit"),t.options.responsive?t.resize():we(t,t.options.devicePixelRatio),t.bindEvents(),t.notifyPlugins("afterInit"),t}clear(){return qt(this.canvas,this.ctx),this}stop(){return a.stop(this),this}resize(t,e){a.running(this)?this._resizeBeforeDraw={width:t,height:e}:this._resize(t,e)}_resize(t,e){const i=this,n=i.options,o=i.canvas,s=n.maintainAspectRatio&&i.aspectRatio,a=i.platform.getMaximumSize(o,t,e,s),r=n.devicePixelRatio||i.platform.getDevicePixelRatio();i.width=a.width,i.height=a.height,i._aspectRatio=i.aspectRatio,we(i,r,!0)&&(i.notifyPlugins("resize",{size:a}),Q(n.onResize,[i,a],i),i.attached&&i._doResize()&&i.render())}ensureScalesHaveIDs(){J(this.options.scales||{},((t,e)=>{t.id=e}))}buildOrUpdateScales(){const t=this,e=t.options,i=e.scales,n=t.scales,o=Object.keys(n).reduce(((t,e)=>(t[e]=!1,t)),{});let s=[];i&&(s=s.concat(Object.keys(i).map((t=>{const e=i[t],n=Nn(t,e),o="r"===n,s="x"===n;return{options:e,dposition:o?"chartArea":s?"bottom":"left",dtype:o?"radialLinear":s?"category":"linear"}})))),J(s,(i=>{const s=i.options,a=s.id,r=Nn(a,s),l=K(s.type,i.dtype);void 0!==s.position&&Zn(s.position,r)===Zn(i.dposition)||(s.position=i.dposition),o[a]=!0;let c=null;if(a in n&&n[a].type===l)c=n[a];else{c=new(zn.getScale(l))({id:a,type:l,ctx:t.ctx,chart:t}),n[c.id]=c}c.init(s,e)})),J(o,((t,e)=>{t||delete n[e]})),J(n,(e=>{ti.configure(t,e,e.options),ti.addBox(t,e)}))}_updateMetasets(){const t=this,e=t._metasets,i=t.data.datasets.length,n=e.length;if(e.sort(((t,e)=>t.index-e.index)),n>i){for(let e=i;e<n;++e)t._destroyDatasetMeta(e);e.splice(i,n-i)}t._sortedMetasets=e.slice(0).sort(Qn("order","index"))}_removeUnreferencedMetasets(){const t=this,{_metasets:e,data:{datasets:i}}=t;e.length>i.length&&delete t._stacks,e.forEach(((e,n)=>{0===i.filter((t=>t===e._dataset)).length&&t._destroyDatasetMeta(n)}))}buildOrUpdateControllers(){const t=this,e=[],i=t.data.datasets;let n,o;for(t._removeUnreferencedMetasets(),n=0,o=i.length;n<o;n++){const o=i[n];let s=t.getDatasetMeta(n);const a=o.type||t.config.type;if(s.type&&s.type!==a&&(t._destroyDatasetMeta(n),s=t.getDatasetMeta(n)),s.type=a,s.indexAxis=o.indexAxis||Wn(a,t.options),s.order=o.order||0,s.index=n,s.label=""+o.label,s.visible=t.isDatasetVisible(n),s.controller)s.controller.updateIndex(n),s.controller.linkScales();else{const i=zn.getController(a),{datasetElementType:o,dataElementType:r}=xt.datasets[a];Object.assign(i.prototype,{dataElementType:zn.getElement(r),datasetElementType:o&&zn.getElement(o)}),s.controller=new i(t,n),e.push(s.controller)}}return t._updateMetasets(),e}_resetElements(){const t=this;J(t.data.datasets,((e,i)=>{t.getDatasetMeta(i).controller.reset()}),t)}reset(){this._resetElements(),this.notifyPlugins("reset")}update(t){const e=this,i=e.config;i.update(),e._options=i.createResolver(i.chartOptionScopes(),e.getContext()),J(e.scales,(t=>{ti.removeBox(e,t)}));const n=e._animationsDisabled=!e.options.animation;e.ensureScalesHaveIDs(),e.buildOrUpdateScales();const o=new Set(Object.keys(e._listeners)),s=new Set(e.options.events);if(ut(o,s)&&!!this._responsiveListeners===e.options.responsive||(e.unbindEvents(),e.bindEvents()),e._plugins.invalidate(),!1===e.notifyPlugins("beforeUpdate",{mode:t,cancelable:!0}))return;const a=e.buildOrUpdateControllers();e.notifyPlugins("beforeElementsUpdate");let r=0;for(let t=0,i=e.data.datasets.length;t<i;t++){const{controller:i}=e.getDatasetMeta(t),o=!n&&-1===a.indexOf(i);i.buildOrUpdateElements(o),r=Math.max(+i.getMaxOverflow(),r)}e._minPadding=r,e._updateLayout(r),n||J(a,(t=>{t.reset()})),e._updateDatasets(t),e.notifyPlugins("afterUpdate",{mode:t}),e._layers.sort(Qn("z","_idx")),e._lastEvent&&e._eventHandler(e._lastEvent,!0),e.render()}_updateLayout(t){const e=this;if(!1===e.notifyPlugins("beforeLayout",{cancelable:!0}))return;ti.update(e,e.width,e.height,t);const i=e.chartArea,n=i.width<=0||i.height<=0;e._layers=[],J(e.boxes,(t=>{n&&"chartArea"===t.position||(t.configure&&t.configure(),e._layers.push(...t._layers()))}),e),e._layers.forEach(((t,e)=>{t._idx=e})),e.notifyPlugins("afterLayout")}_updateDatasets(t){const e=this,i="function"==typeof t;if(!1!==e.notifyPlugins("beforeDatasetsUpdate",{mode:t,cancelable:!0})){for(let n=0,o=e.data.datasets.length;n<o;++n)e._updateDataset(n,i?t({datasetIndex:n}):t);e.notifyPlugins("afterDatasetsUpdate",{mode:t})}}_updateDataset(t,e){const i=this,n=i.getDatasetMeta(t),o={meta:n,index:t,mode:e,cancelable:!0};!1!==i.notifyPlugins("beforeDatasetUpdate",o)&&(n.controller._update(e),o.cancelable=!1,i.notifyPlugins("afterDatasetUpdate",o))}render(){const t=this;!1!==t.notifyPlugins("beforeRender",{cancelable:!0})&&(a.has(t)?t.attached&&!a.running(t)&&a.start(t):(t.draw(),Jn({chart:t})))}draw(){const t=this;let e;if(t._resizeBeforeDraw){const{width:e,height:i}=t._resizeBeforeDraw;t._resize(e,i),t._resizeBeforeDraw=null}if(t.clear(),t.width<=0||t.height<=0)return;if(!1===t.notifyPlugins("beforeDraw",{cancelable:!0}))return;const i=t._layers;for(e=0;e<i.length&&i[e].z<=0;++e)i[e].draw(t.chartArea);for(t._drawDatasets();e<i.length;++e)i[e].draw(t.chartArea);t.notifyPlugins("afterDraw")}_getSortedDatasetMetas(t){const e=this._sortedMetasets,i=[];let n,o;for(n=0,o=e.length;n<o;++n){const o=e[n];t&&!o.visible||i.push(o)}return i}getSortedVisibleDatasetMetas(){return this._getSortedDatasetMetas(!0)}_drawDatasets(){const t=this;if(!1===t.notifyPlugins("beforeDatasetsDraw",{cancelable:!0}))return;const e=t.getSortedVisibleDatasetMetas();for(let i=e.length-1;i>=0;--i)t._drawDataset(e[i]);t.notifyPlugins("afterDatasetsDraw")}_drawDataset(t){const e=this,i=e.ctx,n=t._clip,o=!n.disabled,s=e.chartArea,a={meta:t,index:t.index,cancelable:!0};!1!==e.notifyPlugins("beforeDatasetDraw",a)&&(o&&Zt(i,{left:!1===n.left?0:s.left-n.left,right:!1===n.right?e.width:s.right+n.right,top:!1===n.top?0:s.top-n.top,bottom:!1===n.bottom?e.height:s.bottom+n.bottom}),t.controller.draw(),o&&Qt(i),a.cancelable=!1,e.notifyPlugins("afterDatasetDraw",a))}getElementsAtEventForMode(t,e,i,n){const o=Ae.modes[e];return"function"==typeof o?o(this,t,i,n):[]}getDatasetMeta(t){const e=this.data.datasets[t],i=this._metasets;let n=i.filter((t=>t&&t._dataset===e)).pop();return n||(n={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null,order:e&&e.order||0,index:t,_dataset:e,_parsed:[],_sorted:!1},i.push(n)),n}getContext(){return this.$context||(this.$context={chart:this,type:"chart"})}getVisibleDatasetCount(){return this.getSortedVisibleDatasetMetas().length}isDatasetVisible(t){const e=this.data.datasets[t];if(!e)return!1;const i=this.getDatasetMeta(t);return"boolean"==typeof i.hidden?!i.hidden:!e.hidden}setDatasetVisibility(t,e){this.getDatasetMeta(t).hidden=!e}toggleDataVisibility(t){this._hiddenIndices[t]=!this._hiddenIndices[t]}getDataVisibility(t){return!this._hiddenIndices[t]}_updateVisibility(t,e,i){const n=this,o=i?"show":"hide",s=n.getDatasetMeta(t),a=s.controller._resolveAnimations(void 0,o);ht(e)?(s.data[e].hidden=!i,n.update()):(n.setDatasetVisibility(t,i),a.update(s,{visible:i}),n.update((e=>e.datasetIndex===t?o:void 0)))}hide(t,e){this._updateVisibility(t,e,!1)}show(t,e){this._updateVisibility(t,e,!0)}_destroyDatasetMeta(t){const e=this,i=e._metasets&&e._metasets[t];i&&i.controller&&(i.controller._destroy(),delete e._metasets[t])}destroy(){const t=this,{canvas:e,ctx:i}=t;let n,o;for(t.stop(),a.remove(t),n=0,o=t.data.datasets.length;n<o;++n)t._destroyDatasetMeta(n);t.config.clearCache(),e&&(t.unbindEvents(),qt(e,i),t.platform.releaseContext(i),t.canvas=null,t.ctx=null),t.notifyPlugins("destroy"),delete io[t.id]}toBase64Image(...t){return this.canvas.toDataURL(...t)}bindEvents(){this.bindUserEvents(),this.options.responsive?this.bindResponsiveEvents():this.attached=!0}bindUserEvents(){const t=this,e=t._listeners,i=t.platform,n=function(e,i,n){e.offsetX=i,e.offsetY=n,t._eventHandler(e)};J(t.options.events,(o=>((n,o)=>{i.addEventListener(t,n,o),e[n]=o})(o,n)))}bindResponsiveEvents(){const t=this;t._responsiveListeners||(t._responsiveListeners={});const e=t._responsiveListeners,i=t.platform,n=(n,o)=>{i.addEventListener(t,n,o),e[n]=o},o=(n,o)=>{e[n]&&(i.removeEventListener(t,n,o),delete e[n])},s=(e,i)=>{t.canvas&&t.resize(e,i)};let a;const r=()=>{o("attach",r),t.attached=!0,t.resize(),n("resize",s),n("detach",a)};a=()=>{t.attached=!1,o("resize",s),n("attach",r)},i.isAttached(t.canvas)?r():a()}unbindEvents(){const t=this;J(t._listeners,((e,i)=>{t.platform.removeEventListener(t,i,e)})),t._listeners={},J(t._responsiveListeners,((e,i)=>{t.platform.removeEventListener(t,i,e)})),t._responsiveListeners=void 0}updateHoverStyle(t,e,i){const n=i?"set":"remove";let o,s,a,r;for("dataset"===e&&(o=this.getDatasetMeta(t[0].datasetIndex),o.controller["_"+n+"DatasetHoverStyle"]()),a=0,r=t.length;a<r;++a){s=t[a];const e=s&&this.getDatasetMeta(s.datasetIndex).controller;e&&e[n+"HoverStyle"](s.element,s.datasetIndex,s.index)}}getActiveElements(){return this._active||[]}setActiveElements(t){const e=this,i=e._active||[],n=t.map((({datasetIndex:t,index:i})=>{const n=e.getDatasetMeta(t);if(!n)throw new Error("No dataset found at index "+t);return{datasetIndex:t,element:n.data[i],index:i}}));!tt(n,i)&&(e._active=n,e._updateHoverStyles(n,i))}notifyPlugins(t,e,i){return this._plugins.notify(this,t,e,i)}_updateHoverStyles(t,e,i){const n=this,o=n.options.hover,s=(t,e)=>t.filter((t=>!e.some((e=>t.datasetIndex===e.datasetIndex&&t.index===e.index)))),a=s(e,t),r=i?t:s(t,e);a.length&&n.updateHoverStyle(a,o.mode,!1),r.length&&o.mode&&n.updateHoverStyle(r,o.mode,!0)}_eventHandler(t,e){const i=this,n={event:t,replay:e,cancelable:!0},o=e=>(e.options.events||this.options.events).includes(t.type);if(!1===i.notifyPlugins("beforeEvent",n,o))return;const s=i._handleEvent(t,e);return n.cancelable=!1,i.notifyPlugins("afterEvent",n,o),(s||n.changed)&&i.render(),i}_handleEvent(t,e){const i=this,{_active:n=[],options:o}=i,s=o.hover,a=e;let r=[],l=!1,c=null;return"mouseout"!==t.type&&(r=i.getElementsAtEventForMode(t,s.mode,s,a),c="click"===t.type?i._lastEvent:t),i._lastEvent=null,Gt(t,i.chartArea,i._minPadding)&&(Q(o.onHover,[t,r,i],i),"mouseup"!==t.type&&"click"!==t.type&&"contextmenu"!==t.type||Q(o.onClick,[t,r,i],i)),l=!tt(r,n),(l||e)&&(i._active=r,i._updateHoverStyles(r,n,e)),i._lastEvent=c,l}}const so=()=>J(oo.instances,(t=>t._plugins.invalidate())),ao=!0;function ro(){throw new Error("This method is not implemented: Check that a complete date adapter is provided.")}Object.defineProperties(oo,{defaults:{enumerable:ao,value:xt},instances:{enumerable:ao,value:io},overrides:{enumerable:ao,value:ft},registry:{enumerable:ao,value:zn},version:{enumerable:ao,value:"3.5.0"},getChart:{enumerable:ao,value:no},register:{enumerable:ao,value:(...t)=>{zn.add(...t),so()}},unregister:{enumerable:ao,value:(...t)=>{zn.remove(...t),so()}}});class lo{constructor(t){this.options=t||{}}formats(){return ro()}parse(t,e){return ro()}format(t,e){return ro()}add(t,e,i){return ro()}diff(t,e,i){return ro()}startOf(t,e,i){return ro()}endOf(t,e){return ro()}}lo.override=function(t){Object.assign(lo.prototype,t)};var co={_date:lo};function ho(t){const e=function(t){if(!t._cache.$bar){const e=t.getMatchingVisibleMetas("bar");let i=[];for(let n=0,o=e.length;n<o;n++)i=i.concat(e[n].controller.getAllParsedValues(t));t._cache.$bar=de(i.sort(((t,e)=>t-e)))}return t._cache.$bar}(t);let i,n,o,s,a=t._length;const r=()=>{32767!==o&&-32768!==o&&(ht(s)&&(a=Math.min(a,Math.abs(o-s)||a)),s=o)};for(i=0,n=e.length;i<n;++i)o=t.getPixelForValue(e[i]),r();for(s=void 0,i=0,n=t.ticks.length;i<n;++i)o=t.getPixelForTick(i),r();return a}function uo(t,e,i,n){return Y(t)?function(t,e,i,n){const o=i.parse(t[0],n),s=i.parse(t[1],n),a=Math.min(o,s),r=Math.max(o,s);let l=a,c=r;Math.abs(a)>Math.abs(r)&&(l=r,c=a),e[i.axis]=c,e._custom={barStart:l,barEnd:c,start:o,end:s,min:a,max:r}}(t,e,i,n):e[i.axis]=i.parse(t,n),e}function fo(t,e,i,n){const o=t.iScale,s=t.vScale,a=o.getLabels(),r=o===s,l=[];let c,h,d,u;for(c=i,h=i+n;c<h;++c)u=e[c],d={},d[o.axis]=r||o.parse(a[c],c),l.push(uo(u,d,s,c));return l}function go(t){return t&&void 0!==t.barStart&&void 0!==t.barEnd}function po(t,e,i,n){let o=e.borderSkipped;const s={};if(!o)return void(t.borderSkipped=s);const{start:a,end:r,reverse:l,top:c,bottom:h}=function(t){let e,i,n,o,s;return t.horizontal?(e=t.base>t.x,i="left",n="right"):(e=t.base<t.y,i="bottom",n="top"),e?(o="end",s="start"):(o="start",s="end"),{start:i,end:n,reverse:e,top:o,bottom:s}}(t);"middle"===o&&i&&(t.enableBorderRadius=!0,(i._top||0)===n?o=c:(i._bottom||0)===n?o=h:(s[mo(h,a,r,l)]=!0,o=c)),s[mo(o,a,r,l)]=!0,t.borderSkipped=s}function mo(t,e,i,n){var o,s,a;return n?(a=i,t=xo(t=(o=t)===(s=e)?a:o===a?s:o,i,e)):t=xo(t,e,i),t}function xo(t,e,i){return"start"===t?e:"end"===t?i:t}class bo extends wn{parsePrimitiveData(t,e,i,n){return fo(t,e,i,n)}parseArrayData(t,e,i,n){return fo(t,e,i,n)}parseObjectData(t,e,i,n){const{iScale:o,vScale:s}=t,{xAxisKey:a="x",yAxisKey:r="y"}=this._parsing,l="x"===o.axis?a:r,c="x"===s.axis?a:r,h=[];let d,u,f,g;for(d=i,u=i+n;d<u;++d)g=e[d],f={},f[o.axis]=o.parse(lt(g,l),d),h.push(uo(lt(g,c),f,s,d));return h}updateRangeFromParsed(t,e,i,n){super.updateRangeFromParsed(t,e,i,n);const o=i._custom;o&&e===this._cachedMeta.vScale&&(t.min=Math.min(t.min,o.min),t.max=Math.max(t.max,o.max))}getMaxOverflow(){return 0}getLabelAndValue(t){const e=this._cachedMeta,{iScale:i,vScale:n}=e,o=this.getParsed(t),s=o._custom,a=go(s)?"["+s.start+", "+s.end+"]":""+n.getLabelForValue(o[n.axis]);return{label:""+i.getLabelForValue(o[i.axis]),value:a}}initialize(){const t=this;t.enableOptionSharing=!0,super.initialize();t._cachedMeta.stack=t.getDataset().stack}update(t){const e=this._cachedMeta;this.updateElements(e.data,0,e.data.length,t)}updateElements(t,e,i,n){const o=this,s="reset"===n,{index:a,_cachedMeta:{vScale:r}}=o,l=r.getBasePixel(),c=r.isHorizontal(),h=o._getRuler(),d=o.resolveDataElementOptions(e,n),u=o.getSharedOptions(d),f=o.includeOptions(n,u);o.updateSharedOptions(u,n,d);for(let d=e;d<e+i;d++){const e=o.getParsed(d),i=s||$(e[r.axis])?{base:l,head:l}:o._calculateBarValuePixels(d),g=o._calculateBarIndexPixels(d,h),p=(e._stacks||{})[r.axis],m={horizontal:c,base:i.base,enableBorderRadius:!p||go(e._custom)||a===p._top||a===p._bottom,x:c?i.head:g.center,y:c?g.center:i.head,height:c?g.size:Math.abs(i.size),width:c?Math.abs(i.size):g.size};f&&(m.options=u||o.resolveDataElementOptions(d,t[d].active?"active":n)),po(m,m.options||t[d].options,p,a),o.updateElement(t[d],d,m,n)}}_getStacks(t,e){const i=this._cachedMeta.iScale,n=i.getMatchingVisibleMetas(this._type),o=i.options.stacked,s=n.length,a=[];let r,l;for(r=0;r<s;++r)if(l=n[r],l.controller.options.grouped){if(void 0!==e){const t=l.controller.getParsed(e)[l.controller._cachedMeta.vScale.axis];if($(t)||isNaN(t))continue}if((!1===o||-1===a.indexOf(l.stack)||void 0===o&&void 0===l.stack)&&a.push(l.stack),l.index===t)break}return a.length||a.push(void 0),a}_getStackCount(t){return this._getStacks(void 0,t).length}_getStackIndex(t,e,i){const n=this._getStacks(t,i),o=void 0!==e?n.indexOf(e):-1;return-1===o?n.length-1:o}_getRuler(){const t=this,e=t.options,i=t._cachedMeta,n=i.iScale,o=[];let s,a;for(s=0,a=i.data.length;s<a;++s)o.push(n.getPixelForValue(t.getParsed(s)[n.axis],s));const r=e.barThickness;return{min:r||ho(n),pixels:o,start:n._startPixel,end:n._endPixel,stackCount:t._getStackCount(),scale:n,grouped:e.grouped,ratio:r?1:e.categoryPercentage*e.barPercentage}}_calculateBarValuePixels(t){const e=this,{_cachedMeta:{vScale:i,_stacked:n},options:{base:o,minBarLength:s}}=e,a=o||0,r=e.getParsed(t),l=r._custom,c=go(l);let h,d,u=r[i.axis],f=0,g=n?e.applyStack(i,r,n):u;g!==u&&(f=g-u,g=u),c&&(u=l.barStart,g=l.barEnd-l.barStart,0!==u&&Dt(u)!==Dt(l.barEnd)&&(f=0),f+=u);const p=$(o)||c?f:o;let m=i.getPixelForValue(p);if(h=e.chart.getDataVisibility(t)?i.getPixelForValue(f+g):m,d=h-m,Math.abs(d)<s&&(d=function(t,e,i){return 0!==t?Dt(t):(e.isHorizontal()?1:-1)*(e.min>=i?1:-1)}(d,i,a)*s,u===a&&(m-=d/2),h=m+d),m===i.getPixelForValue(a)){const t=Dt(d)*i.getLineWidthForValue(a)/2;m+=t,d-=t}return{size:d,base:m,head:h,center:h+d/2}}_calculateBarIndexPixels(t,e){const i=this,n=e.scale,o=i.options,s=o.skipNull,a=K(o.maxBarThickness,1/0);let r,l;if(e.grouped){const n=s?i._getStackCount(t):e.stackCount,c="flex"===o.barThickness?function(t,e,i,n){const o=e.pixels,s=o[t];let a=t>0?o[t-1]:null,r=t<o.length-1?o[t+1]:null;const l=i.categoryPercentage;null===a&&(a=s-(null===r?e.end-e.start:r-s)),null===r&&(r=s+s-a);const c=s-(s-Math.min(a,r))/2*l;return{chunk:Math.abs(r-a)/2*l/n,ratio:i.barPercentage,start:c}}(t,e,o,n):function(t,e,i,n){const o=i.barThickness;let s,a;return $(o)?(s=e.min*i.categoryPercentage,a=i.barPercentage):(s=o*n,a=1),{chunk:s/n,ratio:a,start:e.pixels[t]-s/2}}(t,e,o,n),h=i._getStackIndex(i.index,i._cachedMeta.stack,s?t:void 0);r=c.start+c.chunk*h+c.chunk/2,l=Math.min(a,c.chunk*c.ratio)}else r=n.getPixelForValue(i.getParsed(t)[n.axis],t),l=Math.min(a,e.min*e.ratio);return{base:r-l/2,head:r+l/2,center:r,size:l}}draw(){const t=this,e=t._cachedMeta,i=e.vScale,n=e.data,o=n.length;let s=0;for(;s<o;++s)null!==t.getParsed(s)[i.axis]&&n[s].draw(t._ctx)}}bo.id="bar",bo.defaults={datasetElementType:!1,dataElementType:"bar",categoryPercentage:.8,barPercentage:.9,grouped:!0,animations:{numbers:{type:"number",properties:["x","y","base","width","height"]}}},bo.overrides={interaction:{mode:"index"},scales:{_index_:{type:"category",offset:!0,grid:{offset:!0}},_value_:{type:"linear",beginAtZero:!0}}};class _o extends wn{initialize(){this.enableOptionSharing=!0,super.initialize()}parseObjectData(t,e,i,n){const{xScale:o,yScale:s}=t,{xAxisKey:a="x",yAxisKey:r="y"}=this._parsing,l=[];let c,h,d;for(c=i,h=i+n;c<h;++c)d=e[c],l.push({x:o.parse(lt(d,a),c),y:s.parse(lt(d,r),c),_custom:d&&d.r&&+d.r});return l}getMaxOverflow(){const{data:t,_parsed:e}=this._cachedMeta;let i=0;for(let n=t.length-1;n>=0;--n)i=Math.max(i,t[n].size()/2,e[n]._custom);return i>0&&i}getLabelAndValue(t){const e=this._cachedMeta,{xScale:i,yScale:n}=e,o=this.getParsed(t),s=i.getLabelForValue(o.x),a=n.getLabelForValue(o.y),r=o._custom;return{label:e.label,value:"("+s+", "+a+(r?", "+r:"")+")"}}update(t){const e=this._cachedMeta.data;this.updateElements(e,0,e.length,t)}updateElements(t,e,i,n){const o=this,s="reset"===n,{iScale:a,vScale:r}=o._cachedMeta,l=o.resolveDataElementOptions(e,n),c=o.getSharedOptions(l),h=o.includeOptions(n,c),d=a.axis,u=r.axis;for(let l=e;l<e+i;l++){const e=t[l],i=!s&&o.getParsed(l),c={},f=c[d]=s?a.getPixelForDecimal(.5):a.getPixelForValue(i[d]),g=c[u]=s?r.getBasePixel():r.getPixelForValue(i[u]);c.skip=isNaN(f)||isNaN(g),h&&(c.options=o.resolveDataElementOptions(l,e.active?"active":n),s&&(c.options.radius=0)),o.updateElement(e,l,c,n)}o.updateSharedOptions(c,n,l)}resolveDataElementOptions(t,e){const i=this.getParsed(t);let n=super.resolveDataElementOptions(t,e);n.$shared&&(n=Object.assign({},n,{$shared:!1}));const o=n.radius;return"active"!==e&&(n.radius=0),n.radius+=K(i&&i._custom,o),n}}_o.id="bubble",_o.defaults={datasetElementType:!1,dataElementType:"point",animations:{numbers:{type:"number",properties:["x","y","borderWidth","radius"]}}},_o.overrides={scales:{x:{type:"linear"},y:{type:"linear"}},plugins:{tooltip:{callbacks:{title:()=>""}}}};class yo extends wn{constructor(t,e){super(t,e),this.enableOptionSharing=!0,this.innerRadius=void 0,this.outerRadius=void 0,this.offsetX=void 0,this.offsetY=void 0}linkScales(){}parse(t,e){const i=this.getDataset().data,n=this._cachedMeta;let o,s;for(o=t,s=t+e;o<s;++o)n._parsed[o]=+i[o]}_getRotation(){return Et(this.options.rotation-90)}_getCircumference(){return Et(this.options.circumference)}_getRotationExtents(){let t=_t,e=-_t;const i=this;for(let n=0;n<i.chart.data.datasets.length;++n)if(i.chart.isDatasetVisible(n)){const o=i.chart.getDatasetMeta(n).controller,s=o._getRotation(),a=o._getCircumference();t=Math.min(t,s),e=Math.max(e,s+a)}return{rotation:t,circumference:e-t}}update(t){const e=this,i=e.chart,{chartArea:n}=i,o=e._cachedMeta,s=o.data,a=e.getMaxBorderWidth()+e.getMaxOffset(s)+e.options.spacing,r=Math.max((Math.min(n.width,n.height)-a)/2,0),l=Math.min(G(e.options.cutout,r),1),c=e._getRingWeight(e.index),{circumference:h,rotation:d}=e._getRotationExtents(),{ratioX:u,ratioY:f,offsetX:g,offsetY:p}=function(t,e,i){let n=1,o=1,s=0,a=0;if(e<_t){const r=t,l=r+e,c=Math.cos(r),h=Math.sin(r),d=Math.cos(l),u=Math.sin(l),f=(t,e,n)=>Nt(t,r,l,!0)?1:Math.max(e,e*i,n,n*i),g=(t,e,n)=>Nt(t,r,l,!0)?-1:Math.min(e,e*i,n,n*i),p=f(0,c,d),m=f(Mt,h,u),x=g(bt,c,d),b=g(bt+Mt,h,u);n=(p-x)/2,o=(m-b)/2,s=-(p+x)/2,a=-(m+b)/2}return{ratioX:n,ratioY:o,offsetX:s,offsetY:a}}(d,h,l),m=(n.width-a)/u,x=(n.height-a)/f,b=Math.max(Math.min(m,x)/2,0),_=Z(e.options.radius,b),y=(_-Math.max(_*l,0))/e._getVisibleDatasetWeightTotal();e.offsetX=g*_,e.offsetY=p*_,o.total=e.calculateTotal(),e.outerRadius=_-y*e._getRingWeightOffset(e.index),e.innerRadius=Math.max(e.outerRadius-y*c,0),e.updateElements(s,0,s.length,t)}_circumference(t,e){const i=this,n=i.options,o=i._cachedMeta,s=i._getCircumference();return e&&n.animation.animateRotate||!this.chart.getDataVisibility(t)||null===o._parsed[t]||o.data[t].hidden?0:i.calculateCircumference(o._parsed[t]*s/_t)}updateElements(t,e,i,n){const o=this,s="reset"===n,a=o.chart,r=a.chartArea,l=a.options.animation,c=(r.left+r.right)/2,h=(r.top+r.bottom)/2,d=s&&l.animateScale,u=d?0:o.innerRadius,f=d?0:o.outerRadius,g=o.resolveDataElementOptions(e,n),p=o.getSharedOptions(g),m=o.includeOptions(n,p);let x,b=o._getRotation();for(x=0;x<e;++x)b+=o._circumference(x,s);for(x=e;x<e+i;++x){const e=o._circumference(x,s),i=t[x],a={x:c+o.offsetX,y:h+o.offsetY,startAngle:b,endAngle:b+e,circumference:e,outerRadius:f,innerRadius:u};m&&(a.options=p||o.resolveDataElementOptions(x,i.active?"active":n)),b+=e,o.updateElement(i,x,a,n)}o.updateSharedOptions(p,n,g)}calculateTotal(){const t=this._cachedMeta,e=t.data;let i,n=0;for(i=0;i<e.length;i++){const o=t._parsed[i];null===o||isNaN(o)||!this.chart.getDataVisibility(i)||e[i].hidden||(n+=Math.abs(o))}return n}calculateCircumference(t){const e=this._cachedMeta.total;return e>0&&!isNaN(t)?_t*(Math.abs(t)/e):0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,n=i.data.labels||[],o=Oi(e._parsed[t],i.options.locale);return{label:n[t]||"",value:o}}getMaxBorderWidth(t){const e=this;let i=0;const n=e.chart;let o,s,a,r,l;if(!t)for(o=0,s=n.data.datasets.length;o<s;++o)if(n.isDatasetVisible(o)){a=n.getDatasetMeta(o),t=a.data,r=a.controller,r!==e&&r.configure();break}if(!t)return 0;for(o=0,s=t.length;o<s;++o)l=r.resolveDataElementOptions(o),"inner"!==l.borderAlign&&(i=Math.max(i,l.borderWidth||0,l.hoverBorderWidth||0));return i}getMaxOffset(t){let e=0;for(let i=0,n=t.length;i<n;++i){const t=this.resolveDataElementOptions(i);e=Math.max(e,t.offset||0,t.hoverOffset||0)}return e}_getRingWeightOffset(t){let e=0;for(let i=0;i<t;++i)this.chart.isDatasetVisible(i)&&(e+=this._getRingWeight(i));return e}_getRingWeight(t){return Math.max(K(this.chart.data.datasets[t].weight,1),0)}_getVisibleDatasetWeightTotal(){return this._getRingWeightOffset(this.chart.data.datasets.length)||1}}yo.id="doughnut",yo.defaults={datasetElementType:!1,dataElementType:"arc",animation:{animateRotate:!0,animateScale:!1},animations:{numbers:{type:"number",properties:["circumference","endAngle","innerRadius","outerRadius","startAngle","x","y","offset","borderWidth","spacing"]}},cutout:"50%",rotation:0,circumference:360,radius:"100%",spacing:0,indexAxis:"r"},yo.descriptors={_scriptable:t=>"spacing"!==t,_indexable:t=>"spacing"!==t},yo.overrides={aspectRatio:1,plugins:{legend:{labels:{generateLabels(t){const e=t.data;if(e.labels.length&&e.datasets.length){const{labels:{pointStyle:i}}=t.legend.options;return e.labels.map(((e,n)=>{const o=t.getDatasetMeta(0).controller.getStyle(n);return{text:e,fillStyle:o.backgroundColor,strokeStyle:o.borderColor,lineWidth:o.borderWidth,pointStyle:i,hidden:!t.getDataVisibility(n),index:n}}))}return[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}},tooltip:{callbacks:{title:()=>"",label(t){let e=t.label;const i=": "+t.formattedValue;return Y(e)?(e=e.slice(),e[0]+=i):e+=i,e}}}}};class vo extends wn{initialize(){this.enableOptionSharing=!0,super.initialize()}update(t){const e=this,i=e._cachedMeta,{dataset:n,data:o=[],_dataset:s}=i,a=e.chart._animationsDisabled;let{start:r,count:l}=function(t,e,i){const n=e.length;let o=0,s=n;if(t._sorted){const{iScale:a,_parsed:r}=t,l=a.axis,{min:c,max:h,minDefined:d,maxDefined:u}=a.getUserBounds();d&&(o=Ht(Math.min(se(r,a.axis,c).lo,i?n:se(e,l,a.getPixelForValue(c)).lo),0,n-1)),s=u?Ht(Math.max(se(r,a.axis,h).hi+1,i?0:se(e,l,a.getPixelForValue(h)).hi+1),o,n)-o:n-o}return{start:o,count:s}}(i,o,a);e._drawStart=r,e._drawCount=l,function(t){const{xScale:e,yScale:i,_scaleRanges:n}=t,o={xmin:e.min,xmax:e.max,ymin:i.min,ymax:i.max};if(!n)return t._scaleRanges=o,!0;const s=n.xmin!==e.min||n.xmax!==e.max||n.ymin!==i.min||n.ymax!==i.max;return Object.assign(n,o),s}(i)&&(r=0,l=o.length),n._datasetIndex=e.index,n._decimated=!!s._decimated,n.points=o;const c=e.resolveDatasetElementOptions(t);e.options.showLine||(c.borderWidth=0),c.segment=e.options.segment,e.updateElement(n,void 0,{animated:!a,options:c},t),e.updateElements(o,r,l,t)}updateElements(t,e,i,n){const o=this,s="reset"===n,{iScale:a,vScale:r,_stacked:l}=o._cachedMeta,c=o.resolveDataElementOptions(e,n),h=o.getSharedOptions(c),d=o.includeOptions(n,h),u=a.axis,f=r.axis,g=o.options.spanGaps,p=Tt(g)?g:Number.POSITIVE_INFINITY,m=o.chart._animationsDisabled||s||"none"===n;let x=e>0&&o.getParsed(e-1);for(let c=e;c<e+i;++c){const e=t[c],i=o.getParsed(c),g=m?e:{},b=$(i[f]),_=g[u]=a.getPixelForValue(i[u],c),y=g[f]=s||b?r.getBasePixel():r.getPixelForValue(l?o.applyStack(r,i,l):i[f],c);g.skip=isNaN(_)||isNaN(y)||b,g.stop=c>0&&i[u]-x[u]>p,g.parsed=i,d&&(g.options=h||o.resolveDataElementOptions(c,e.active?"active":n)),m||o.updateElement(e,c,g,n),x=i}o.updateSharedOptions(h,n,c)}getMaxOverflow(){const t=this,e=t._cachedMeta,i=e.dataset,n=i.options&&i.options.borderWidth||0,o=e.data||[];if(!o.length)return n;const s=o[0].size(t.resolveDataElementOptions(0)),a=o[o.length-1].size(t.resolveDataElementOptions(o.length-1));return Math.max(n,s,a)/2}draw(){const t=this._cachedMeta;t.dataset.updateControlPoints(this.chart.chartArea,t.iScale.axis),super.draw()}}vo.id="line",vo.defaults={datasetElementType:"line",dataElementType:"point",showLine:!0,spanGaps:!1},vo.overrides={scales:{_index_:{type:"category"},_value_:{type:"linear"}}};class wo extends wn{constructor(t,e){super(t,e),this.innerRadius=void 0,this.outerRadius=void 0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,n=i.data.labels||[],o=Oi(e._parsed[t].r,i.options.locale);return{label:n[t]||"",value:o}}update(t){const e=this._cachedMeta.data;this._updateRadius(),this.updateElements(e,0,e.length,t)}_updateRadius(){const t=this,e=t.chart,i=e.chartArea,n=e.options,o=Math.min(i.right-i.left,i.bottom-i.top),s=Math.max(o/2,0),a=(s-Math.max(n.cutoutPercentage?s/100*n.cutoutPercentage:1,0))/e.getVisibleDatasetCount();t.outerRadius=s-a*t.index,t.innerRadius=t.outerRadius-a}updateElements(t,e,i,n){const o=this,s="reset"===n,a=o.chart,r=o.getDataset(),l=a.options.animation,c=o._cachedMeta.rScale,h=c.xCenter,d=c.yCenter,u=c.getIndexAngle(0)-.5*bt;let f,g=u;const p=360/o.countVisibleElements();for(f=0;f<e;++f)g+=o._computeAngle(f,n,p);for(f=e;f<e+i;f++){const e=t[f];let i=g,m=g+o._computeAngle(f,n,p),x=a.getDataVisibility(f)?c.getDistanceFromCenterForValue(r.data[f]):0;g=m,s&&(l.animateScale&&(x=0),l.animateRotate&&(i=m=u));const b={x:h,y:d,innerRadius:0,outerRadius:x,startAngle:i,endAngle:m,options:o.resolveDataElementOptions(f,e.active?"active":n)};o.updateElement(e,f,b,n)}}countVisibleElements(){const t=this.getDataset(),e=this._cachedMeta;let i=0;return e.data.forEach(((e,n)=>{!isNaN(t.data[n])&&this.chart.getDataVisibility(n)&&i++})),i}_computeAngle(t,e,i){return this.chart.getDataVisibility(t)?Et(this.resolveDataElementOptions(t,e).angle||i):0}}wo.id="polarArea",wo.defaults={dataElementType:"arc",animation:{animateRotate:!0,animateScale:!0},animations:{numbers:{type:"number",properties:["x","y","startAngle","endAngle","innerRadius","outerRadius"]}},indexAxis:"r",startAngle:0},wo.overrides={aspectRatio:1,plugins:{legend:{labels:{generateLabels(t){const e=t.data;if(e.labels.length&&e.datasets.length){const{labels:{pointStyle:i}}=t.legend.options;return e.labels.map(((e,n)=>{const o=t.getDatasetMeta(0).controller.getStyle(n);return{text:e,fillStyle:o.backgroundColor,strokeStyle:o.borderColor,lineWidth:o.borderWidth,pointStyle:i,hidden:!t.getDataVisibility(n),index:n}}))}return[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}},tooltip:{callbacks:{title:()=>"",label:t=>t.chart.data.labels[t.dataIndex]+": "+t.formattedValue}}},scales:{r:{type:"radialLinear",angleLines:{display:!1},beginAtZero:!0,grid:{circular:!0},pointLabels:{display:!1},startAngle:0}}};class Mo extends yo{}Mo.id="pie",Mo.defaults={cutout:0,rotation:0,circumference:360,radius:"100%"};class ko extends wn{getLabelAndValue(t){const e=this._cachedMeta.vScale,i=this.getParsed(t);return{label:e.getLabels()[t],value:""+e.getLabelForValue(i[e.axis])}}update(t){const e=this,i=e._cachedMeta,n=i.dataset,o=i.data||[],s=i.iScale.getLabels();if(n.points=o,"resize"!==t){const i=e.resolveDatasetElementOptions(t);e.options.showLine||(i.borderWidth=0);const a={_loop:!0,_fullLoop:s.length===o.length,options:i};e.updateElement(n,void 0,a,t)}e.updateElements(o,0,o.length,t)}updateElements(t,e,i,n){const o=this,s=o.getDataset(),a=o._cachedMeta.rScale,r="reset"===n;for(let l=e;l<e+i;l++){const e=t[l],i=o.resolveDataElementOptions(l,e.active?"active":n),c=a.getPointPositionForValue(l,s.data[l]),h=r?a.xCenter:c.x,d=r?a.yCenter:c.y,u={x:h,y:d,angle:c.angle,skip:isNaN(h)||isNaN(d),options:i};o.updateElement(e,l,u,n)}}}ko.id="radar",ko.defaults={datasetElementType:"line",dataElementType:"point",indexAxis:"r",showLine:!0,elements:{line:{fill:"start"}}},ko.overrides={aspectRatio:1,scales:{r:{type:"radialLinear"}}};class So extends vo{}So.id="scatter",So.defaults={showLine:!1,fill:!1},So.overrides={interaction:{mode:"point"},plugins:{tooltip:{callbacks:{title:()=>"",label:t=>"("+t.label+", "+t.formattedValue+")"}}},scales:{x:{type:"linear"},y:{type:"linear"}}};var Po=Object.freeze({__proto__:null,BarController:bo,BubbleController:_o,DoughnutController:yo,LineController:vo,PolarAreaController:wo,PieController:Mo,RadarController:ko,ScatterController:So});function Do(t,e,i){const{startAngle:n,pixelMargin:o,x:s,y:a,outerRadius:r,innerRadius:l}=e;let c=o/r;t.beginPath(),t.arc(s,a,r,n-c,i+c),l>o?(c=o/l,t.arc(s,a,l,i+c,n-c,!0)):t.arc(s,a,o,i+Mt,n-Mt),t.closePath(),t.clip()}function Co(t,e,i,n){const o=Ie(t.options.borderRadius,["outerStart","outerEnd","innerStart","innerEnd"]);const s=(i-e)/2,a=Math.min(s,n*e/2),r=t=>{const e=(i-Math.min(s,t))*n/2;return Ht(t,0,Math.min(s,e))};return{outerStart:r(o.outerStart),outerEnd:r(o.outerEnd),innerStart:Ht(o.innerStart,0,a),innerEnd:Ht(o.innerEnd,0,a)}}function Oo(t,e,i,n){return{x:i+t*Math.cos(e),y:n+t*Math.sin(e)}}function To(t,e,i,n,o){const{x:s,y:a,startAngle:r,pixelMargin:l,innerRadius:c}=e,h=Math.max(e.outerRadius+n+i-l,0),d=c>0?c+n+i+l:0;let u=0;const f=o-r;if(n){const t=((c>0?c-n:0)+(h>0?h-n:0))/2;u=(f-(0!==t?f*t/(t+n):f))/2}const g=(f-Math.max(.001,f*h-i/bt)/h)/2,p=r+g+u,m=o-g-u,{outerStart:x,outerEnd:b,innerStart:_,innerEnd:y}=Co(e,d,h,m-p),v=h-x,w=h-b,M=p+x/v,k=m-b/w,S=d+_,P=d+y,D=p+_/S,C=m-y/P;if(t.beginPath(),t.arc(s,a,h,M,k),b>0){const e=Oo(w,k,s,a);t.arc(e.x,e.y,b,k,m+Mt)}const O=Oo(P,m,s,a);if(t.lineTo(O.x,O.y),y>0){const e=Oo(P,C,s,a);t.arc(e.x,e.y,y,m+Mt,C+Math.PI)}if(t.arc(s,a,d,m-y/d,p+_/d,!0),_>0){const e=Oo(S,D,s,a);t.arc(e.x,e.y,_,D+Math.PI,p-Mt)}const T=Oo(v,p,s,a);if(t.lineTo(T.x,T.y),x>0){const e=Oo(v,M,s,a);t.arc(e.x,e.y,x,p-Mt,M)}t.closePath()}function Ao(t,e,i,n,o){const{options:s}=e,a="inner"===s.borderAlign;s.borderWidth&&(a?(t.lineWidth=2*s.borderWidth,t.lineJoin="round"):(t.lineWidth=s.borderWidth,t.lineJoin="bevel"),e.fullCircles&&function(t,e,i){const{x:n,y:o,startAngle:s,pixelMargin:a,fullCircles:r}=e,l=Math.max(e.outerRadius-a,0),c=e.innerRadius+a;let h;for(i&&Do(t,e,s+_t),t.beginPath(),t.arc(n,o,c,s+_t,s,!0),h=0;h<r;++h)t.stroke();for(t.beginPath(),t.arc(n,o,l,s,s+_t),h=0;h<r;++h)t.stroke()}(t,e,a),a&&Do(t,e,o),To(t,e,i,n,o),t.stroke())}class Lo extends Mn{constructor(t){super(),this.options=void 0,this.circumference=void 0,this.startAngle=void 0,this.endAngle=void 0,this.innerRadius=void 0,this.outerRadius=void 0,this.pixelMargin=0,this.fullCircles=0,t&&Object.assign(this,t)}inRange(t,e,i){const n=this.getProps(["x","y"],i),{angle:o,distance:s}=Ft(n,{x:t,y:e}),{startAngle:a,endAngle:r,innerRadius:l,outerRadius:c,circumference:h}=this.getProps(["startAngle","endAngle","innerRadius","outerRadius","circumference"],i),d=this.options.spacing/2;return(h>=_t||Nt(o,a,r))&&(s>=l+d&&s<=c+d)}getCenterPoint(t){const{x:e,y:i,startAngle:n,endAngle:o,innerRadius:s,outerRadius:a}=this.getProps(["x","y","startAngle","endAngle","innerRadius","outerRadius","circumference"],t),{offset:r,spacing:l}=this.options,c=(n+o)/2,h=(s+a+l+r)/2;return{x:e+Math.cos(c)*h,y:i+Math.sin(c)*h}}tooltipPosition(t){return this.getCenterPoint(t)}draw(t){const e=this,{options:i,circumference:n}=e,o=(i.offset||0)/2,s=(i.spacing||0)/2;if(e.pixelMargin="inner"===i.borderAlign?.33:0,e.fullCircles=n>_t?Math.floor(n/_t):0,0===n||e.innerRadius<0||e.outerRadius<0)return;t.save();let a=0;if(o){a=o/2;const i=(e.startAngle+e.endAngle)/2;t.translate(Math.cos(i)*a,Math.sin(i)*a),e.circumference>=bt&&(a=o)}t.fillStyle=i.backgroundColor,t.strokeStyle=i.borderColor;const r=function(t,e,i,n){const{fullCircles:o,startAngle:s,circumference:a}=e;let r=e.endAngle;if(o){To(t,e,i,n,s+_t);for(let e=0;e<o;++e)t.fill();isNaN(a)||(r=s+a%_t,a%_t==0&&(r+=_t))}return To(t,e,i,n,r),t.fill(),r}(t,e,a,s);Ao(t,e,a,s,r),t.restore()}}function Ro(t,e,i=e){t.lineCap=K(i.borderCapStyle,e.borderCapStyle),t.setLineDash(K(i.borderDash,e.borderDash)),t.lineDashOffset=K(i.borderDashOffset,e.borderDashOffset),t.lineJoin=K(i.borderJoinStyle,e.borderJoinStyle),t.lineWidth=K(i.borderWidth,e.borderWidth),t.strokeStyle=K(i.borderColor,e.borderColor)}function Eo(t,e,i){t.lineTo(i.x,i.y)}function Io(t,e,i={}){const n=t.length,{start:o=0,end:s=n-1}=i,{start:a,end:r}=e,l=Math.max(o,a),c=Math.min(s,r),h=o<a&&s<a||o>r&&s>r;return{count:n,start:l,loop:e.loop,ilen:c<l&&!h?n+c-l:c-l}}function zo(t,e,i,n){const{points:o,options:s}=e,{count:a,start:r,loop:l,ilen:c}=Io(o,i,n),h=function(t){return t.stepped?Jt:t.tension||"monotone"===t.cubicInterpolationMode?te:Eo}(s);let d,u,f,{move:g=!0,reverse:p}=n||{};for(d=0;d<=c;++d)u=o[(r+(p?c-d:d))%a],u.skip||(g?(t.moveTo(u.x,u.y),g=!1):h(t,f,u,p,s.stepped),f=u);return l&&(u=o[(r+(p?c:0))%a],h(t,f,u,p,s.stepped)),!!l}function Fo(t,e,i,n){const o=e.points,{count:s,start:a,ilen:r}=Io(o,i,n),{move:l=!0,reverse:c}=n||{};let h,d,u,f,g,p,m=0,x=0;const b=t=>(a+(c?r-t:t))%s,_=()=>{f!==g&&(t.lineTo(m,g),t.lineTo(m,f),t.lineTo(m,p))};for(l&&(d=o[b(0)],t.moveTo(d.x,d.y)),h=0;h<=r;++h){if(d=o[b(h)],d.skip)continue;const e=d.x,i=d.y,n=0|e;n===u?(i<f?f=i:i>g&&(g=i),m=(x*m+e)/++x):(_(),t.lineTo(e,i),u=n,x=0,f=g=i),p=i}_()}function Bo(t){const e=t.options,i=e.borderDash&&e.borderDash.length;return!(t._decimated||t._loop||e.tension||"monotone"===e.cubicInterpolationMode||e.stepped||i)?Fo:zo}Lo.id="arc",Lo.defaults={borderAlign:"center",borderColor:"#fff",borderRadius:0,borderWidth:2,offset:0,spacing:0,angle:void 0},Lo.defaultRoutes={backgroundColor:"backgroundColor"};const Vo="function"==typeof Path2D;function Wo(t,e,i,n){Vo&&1===e.segments.length?function(t,e,i,n){let o=e._path;o||(o=e._path=new Path2D,e.path(o,i,n)&&o.closePath()),Ro(t,e.options),t.stroke(o)}(t,e,i,n):function(t,e,i,n){const{segments:o,options:s}=e,a=Bo(e);for(const r of o)Ro(t,s,r.style),t.beginPath(),a(t,e,r,{start:i,end:i+n-1})&&t.closePath(),t.stroke()}(t,e,i,n)}class No extends Mn{constructor(t){super(),this.animated=!0,this.options=void 0,this._loop=void 0,this._fullLoop=void 0,this._path=void 0,this._points=void 0,this._segments=void 0,this._decimated=!1,this._pointsUpdated=!1,this._datasetIndex=void 0,t&&Object.assign(this,t)}updateControlPoints(t,e){const i=this,n=i.options;if((n.tension||"monotone"===n.cubicInterpolationMode)&&!n.stepped&&!i._pointsUpdated){const o=n.spanGaps?i._loop:i._fullLoop;yi(i._points,n,t,o,e),i._pointsUpdated=!0}}set points(t){const e=this;e._points=t,delete e._segments,delete e._path,e._pointsUpdated=!1}get points(){return this._points}get segments(){return this._segments||(this._segments=Fi(this,this.options.segment))}first(){const t=this.segments,e=this.points;return t.length&&e[t[0].start]}last(){const t=this.segments,e=this.points,i=t.length;return i&&e[t[i-1].end]}interpolate(t,e){const i=this,n=i.options,o=t[e],s=i.points,a=zi(i,{property:e,start:o,end:o});if(!a.length)return;const r=[],l=function(t){return t.stepped?Pi:t.tension||"monotone"===t.cubicInterpolationMode?Di:Si}(n);let c,h;for(c=0,h=a.length;c<h;++c){const{start:i,end:h}=a[c],d=s[i],u=s[h];if(d===u){r.push(d);continue}const f=l(d,u,Math.abs((o-d[e])/(u[e]-d[e])),n.stepped);f[e]=t[e],r.push(f)}return 1===r.length?r[0]:r}pathSegment(t,e,i){return Bo(this)(t,this,e,i)}path(t,e,i){const n=this,o=n.segments,s=Bo(n);let a=n._loop;e=e||0,i=i||n.points.length-e;for(const r of o)a&=s(t,n,r,{start:e,end:e+i-1});return!!a}draw(t,e,i,n){const o=this,s=o.options||{};(o.points||[]).length&&s.borderWidth&&(t.save(),Wo(t,o,i,n),t.restore(),o.animated&&(o._pointsUpdated=!1,o._path=void 0))}}function Ho(t,e,i,n){const o=t.options,{[i]:s}=t.getProps([i],n);return Math.abs(e-s)<o.radius+o.hitRadius}No.id="line",No.defaults={borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",borderWidth:3,capBezierPoints:!0,cubicInterpolationMode:"default",fill:!1,spanGaps:!1,stepped:!1,tension:0},No.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"},No.descriptors={_scriptable:!0,_indexable:t=>"borderDash"!==t&&"fill"!==t};class jo extends Mn{constructor(t){super(),this.options=void 0,this.parsed=void 0,this.skip=void 0,this.stop=void 0,t&&Object.assign(this,t)}inRange(t,e,i){const n=this.options,{x:o,y:s}=this.getProps(["x","y"],i);return Math.pow(t-o,2)+Math.pow(e-s,2)<Math.pow(n.hitRadius+n.radius,2)}inXRange(t,e){return Ho(this,t,"x",e)}inYRange(t,e){return Ho(this,t,"y",e)}getCenterPoint(t){const{x:e,y:i}=this.getProps(["x","y"],t);return{x:e,y:i}}size(t){let e=(t=t||this.options||{}).radius||0;e=Math.max(e,e&&t.hoverRadius||0);return 2*(e+(e&&t.borderWidth||0))}draw(t,e){const i=this,n=i.options;i.skip||n.radius<.1||!Gt(i,e,i.size(n)/2)||(t.strokeStyle=n.borderColor,t.lineWidth=n.borderWidth,t.fillStyle=n.backgroundColor,Kt(t,n,i.x,i.y))}getRange(){const t=this.options||{};return t.radius+t.hitRadius}}function $o(t,e){const{x:i,y:n,base:o,width:s,height:a}=t.getProps(["x","y","base","width","height"],e);let r,l,c,h,d;return t.horizontal?(d=a/2,r=Math.min(i,o),l=Math.max(i,o),c=n-d,h=n+d):(d=s/2,r=i-d,l=i+d,c=Math.min(n,o),h=Math.max(n,o)),{left:r,top:c,right:l,bottom:h}}function Yo(t,e,i,n){return t?0:Ht(e,i,n)}function Uo(t){const e=$o(t),i=e.right-e.left,n=e.bottom-e.top,o=function(t,e,i){const n=t.options.borderWidth,o=t.borderSkipped,s=ze(n);return{t:Yo(o.top,s.top,0,i),r:Yo(o.right,s.right,0,e),b:Yo(o.bottom,s.bottom,0,i),l:Yo(o.left,s.left,0,e)}}(t,i/2,n/2),s=function(t,e,i){const{enableBorderRadius:n}=t.getProps(["enableBorderRadius"]),o=t.options.borderRadius,s=Fe(o),a=Math.min(e,i),r=t.borderSkipped,l=n||U(o);return{topLeft:Yo(!l||r.top||r.left,s.topLeft,0,a),topRight:Yo(!l||r.top||r.right,s.topRight,0,a),bottomLeft:Yo(!l||r.bottom||r.left,s.bottomLeft,0,a),bottomRight:Yo(!l||r.bottom||r.right,s.bottomRight,0,a)}}(t,i/2,n/2);return{outer:{x:e.left,y:e.top,w:i,h:n,radius:s},inner:{x:e.left+o.l,y:e.top+o.t,w:i-o.l-o.r,h:n-o.t-o.b,radius:{topLeft:Math.max(0,s.topLeft-Math.max(o.t,o.l)),topRight:Math.max(0,s.topRight-Math.max(o.t,o.r)),bottomLeft:Math.max(0,s.bottomLeft-Math.max(o.b,o.l)),bottomRight:Math.max(0,s.bottomRight-Math.max(o.b,o.r))}}}}function Xo(t,e,i,n){const o=null===e,s=null===i,a=t&&!(o&&s)&&$o(t,n);return a&&(o||e>=a.left&&e<=a.right)&&(s||i>=a.top&&i<=a.bottom)}function qo(t,e){t.rect(e.x,e.y,e.w,e.h)}function Ko(t,e,i={}){const n=t.x!==i.x?-e:0,o=t.y!==i.y?-e:0,s=(t.x+t.w!==i.x+i.w?e:0)-n,a=(t.y+t.h!==i.y+i.h?e:0)-o;return{x:t.x+n,y:t.y+o,w:t.w+s,h:t.h+a,radius:t.radius}}jo.id="point",jo.defaults={borderWidth:1,hitRadius:1,hoverBorderWidth:1,hoverRadius:4,pointStyle:"circle",radius:3,rotation:0},jo.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};class Go extends Mn{constructor(t){super(),this.options=void 0,this.horizontal=void 0,this.base=void 0,this.width=void 0,this.height=void 0,t&&Object.assign(this,t)}draw(t){const e=this.options,{inner:i,outer:n}=Uo(this),o=(s=n.radius).topLeft||s.topRight||s.bottomLeft||s.bottomRight?ne:qo;var s;const a=.33;t.save(),n.w===i.w&&n.h===i.h||(t.beginPath(),o(t,Ko(n,a,i)),t.clip(),o(t,Ko(i,-.33,n)),t.fillStyle=e.borderColor,t.fill("evenodd")),t.beginPath(),o(t,Ko(i,a,n)),t.fillStyle=e.backgroundColor,t.fill(),t.restore()}inRange(t,e,i){return Xo(this,t,e,i)}inXRange(t,e){return Xo(this,t,null,e)}inYRange(t,e){return Xo(this,null,t,e)}getCenterPoint(t){const{x:e,y:i,base:n,horizontal:o}=this.getProps(["x","y","base","horizontal"],t);return{x:o?(e+n)/2:e,y:o?i:(i+n)/2}}getRange(t){return"x"===t?this.width/2:this.height/2}}Go.id="bar",Go.defaults={borderSkipped:"start",borderWidth:0,borderRadius:0,enableBorderRadius:!0,pointStyle:void 0},Go.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};var Zo=Object.freeze({__proto__:null,ArcElement:Lo,LineElement:No,PointElement:jo,BarElement:Go});function Qo(t){if(t._decimated){const e=t._data;delete t._decimated,delete t._data,Object.defineProperty(t,"data",{value:e})}}function Jo(t){t.data.datasets.forEach((t=>{Qo(t)}))}var ts={id:"decimation",defaults:{algorithm:"min-max",enabled:!1},beforeElementsUpdate:(t,e,i)=>{if(!i.enabled)return void Jo(t);const n=t.width;t.data.datasets.forEach(((e,o)=>{const{_data:s,indexAxis:a}=e,r=t.getDatasetMeta(o),l=s||e.data;if("y"===We([a,t.options.indexAxis]))return;if("line"!==r.type)return;const c=t.scales[r.xAxisID];if("linear"!==c.type&&"time"!==c.type)return;if(t.options.parsing)return;let{start:h,count:d}=function(t,e){const i=e.length;let n,o=0;const{iScale:s}=t,{min:a,max:r,minDefined:l,maxDefined:c}=s.getUserBounds();return l&&(o=Ht(se(e,s.axis,a).lo,0,i-1)),n=c?Ht(se(e,s.axis,r).hi+1,o,i)-o:i-o,{start:o,count:n}}(r,l);if(d<=(i.threshold||4*n))return void Qo(e);let u;switch($(s)&&(e._data=l,delete e.data,Object.defineProperty(e,"data",{configurable:!0,enumerable:!0,get:function(){return this._decimated},set:function(t){this._data=t}})),i.algorithm){case"lttb":u=function(t,e,i,n,o){const s=o.samples||n;if(s>=i)return t.slice(e,e+i);const a=[],r=(i-2)/(s-2);let l=0;const c=e+i-1;let h,d,u,f,g,p=e;for(a[l++]=t[p],h=0;h<s-2;h++){let n,o=0,s=0;const c=Math.floor((h+1)*r)+1+e,m=Math.min(Math.floor((h+2)*r)+1,i)+e,x=m-c;for(n=c;n<m;n++)o+=t[n].x,s+=t[n].y;o/=x,s/=x;const b=Math.floor(h*r)+1+e,_=Math.min(Math.floor((h+1)*r)+1,i)+e,{x:y,y:v}=t[p];for(u=f=-1,n=b;n<_;n++)f=.5*Math.abs((y-o)*(t[n].y-v)-(y-t[n].x)*(s-v)),f>u&&(u=f,d=t[n],g=n);a[l++]=d,p=g}return a[l++]=t[c],a}(l,h,d,n,i);break;case"min-max":u=function(t,e,i,n){let o,s,a,r,l,c,h,d,u,f,g=0,p=0;const m=[],x=e+i-1,b=t[e].x,_=t[x].x-b;for(o=e;o<e+i;++o){s=t[o],a=(s.x-b)/_*n,r=s.y;const e=0|a;if(e===l)r<u?(u=r,c=o):r>f&&(f=r,h=o),g=(p*g+s.x)/++p;else{const i=o-1;if(!$(c)&&!$(h)){const e=Math.min(c,h),n=Math.max(c,h);e!==d&&e!==i&&m.push({...t[e],x:g}),n!==d&&n!==i&&m.push({...t[n],x:g})}o>0&&i!==d&&m.push(t[i]),m.push(s),l=e,p=0,u=f=r,c=h=d=o}}return m}(l,h,d,n);break;default:throw new Error(`Unsupported decimation algorithm '${i.algorithm}'`)}e._decimated=u}))},destroy(t){Jo(t)}};function es(t,e,i){const n=function(t){const e=t.options,i=e.fill;let n=K(i&&i.target,i);return void 0===n&&(n=!!e.backgroundColor),!1!==n&&null!==n&&(!0===n?"origin":n)}(t);if(U(n))return!isNaN(n.value)&&n;let o=parseFloat(n);return X(o)&&Math.floor(o)===o?("-"!==n[0]&&"+"!==n[0]||(o=e+o),!(o===e||o<0||o>=i)&&o):["origin","start","end","stack","shape"].indexOf(n)>=0&&n}class is{constructor(t){this.x=t.x,this.y=t.y,this.radius=t.radius}pathSegment(t,e,i){const{x:n,y:o,radius:s}=this;return e=e||{start:0,end:_t},t.arc(n,o,s,e.end,e.start,!0),!i.bounds}interpolate(t){const{x:e,y:i,radius:n}=this,o=t.angle;return{x:e+Math.cos(o)*n,y:i+Math.sin(o)*n,angle:o}}}function ns(t){return(t.scale||{}).getPointPositionForValue?function(t){const{scale:e,fill:i}=t,n=e.options,o=e.getLabels().length,s=[],a=n.reverse?e.max:e.min,r=n.reverse?e.min:e.max;let l,c,h;if(h="start"===i?a:"end"===i?r:U(i)?i.value:e.getBaseValue(),n.grid.circular)return c=e.getPointPositionForValue(0,a),new is({x:c.x,y:c.y,radius:e.getDistanceFromCenterForValue(h)});for(l=0;l<o;++l)s.push(e.getPointPositionForValue(l,h));return s}(t):function(t){const{scale:e={},fill:i}=t;let n,o=null;return"start"===i?o=e.bottom:"end"===i?o=e.top:U(i)?o=e.getPixelForValue(i.value):e.getBasePixel&&(o=e.getBasePixel()),X(o)?(n=e.isHorizontal(),{x:n?o:null,y:n?null:o}):null}(t)}function os(t,e,i){for(;e>t;e--){const t=i[e];if(!isNaN(t.x)&&!isNaN(t.y))break}return e}function ss(t){const{chart:e,scale:i,index:n,line:o}=t,s=[],a=o.segments,r=o.points,l=function(t,e){const i=[],n=t.getSortedVisibleDatasetMetas();for(let t=0;t<n.length;t++){const o=n[t];if(o.index===e)break;as(o)&&i.unshift(o.dataset)}return i}(e,n);l.push(cs({x:null,y:i.bottom},o));for(let t=0;t<a.length;t++){const e=a[t];for(let t=e.start;t<=e.end;t++)rs(s,r[t],l)}return new No({points:s,options:{}})}const as=t=>"line"===t.type&&!t.hidden;function rs(t,e,i){const n=[];for(let o=0;o<i.length;o++){const s=i[o],{first:a,last:r,point:l}=ls(s,e,"x");if(!(!l||a&&r))if(a)n.unshift(l);else if(t.push(l),!r)break}t.push(...n)}function ls(t,e,i){const n=t.interpolate(e,i);if(!n)return{};const o=n[i],s=t.segments,a=t.points;let r=!1,l=!1;for(let t=0;t<s.length;t++){const e=s[t],n=a[e.start][i],c=a[e.end][i];if(o>=n&&o<=c){r=o===n,l=o===c;break}}return{first:r,last:l,point:n}}function cs(t,e){let i=[],n=!1;return Y(t)?(n=!0,i=t):i=function(t,e){const{x:i=null,y:n=null}=t||{},o=e.points,s=[];return e.segments.forEach((({start:t,end:e})=>{e=os(t,e,o);const a=o[t],r=o[e];null!==n?(s.push({x:a.x,y:n}),s.push({x:r.x,y:n})):null!==i&&(s.push({x:i,y:a.y}),s.push({x:i,y:r.y}))})),s}(t,e),i.length?new No({points:i,options:{tension:0},_loop:n,_fullLoop:n}):null}function hs(t,e,i){let n=t[e].fill;const o=[e];let s;if(!i)return n;for(;!1!==n&&-1===o.indexOf(n);){if(!X(n))return n;if(s=t[n],!s)return!1;if(s.visible)return n;o.push(n),n=s.fill}return!1}function ds(t,e,i){t.beginPath(),e.path(t),t.lineTo(e.last().x,i),t.lineTo(e.first().x,i),t.closePath(),t.clip()}function us(t,e,i,n){if(n)return;let o=e[t],s=i[t];return"angle"===t&&(o=Wt(o),s=Wt(s)),{property:t,start:o,end:s}}function fs(t,e,i,n){return t&&e?n(t[i],e[i]):t?t[i]:e?e[i]:0}function gs(t,e,i){const{top:n,bottom:o}=e.chart.chartArea,{property:s,start:a,end:r}=i||{};"x"===s&&(t.beginPath(),t.rect(a,n,r-a,o-n),t.clip())}function ps(t,e,i,n){const o=e.interpolate(i,n);o&&t.lineTo(o.x,o.y)}function ms(t,e){const{line:i,target:n,property:o,color:s,scale:a}=e,r=function(t,e,i){const n=t.segments,o=t.points,s=e.points,a=[];for(const t of n){let{start:n,end:r}=t;r=os(n,r,o);const l=us(i,o[n],o[r],t.loop);if(!e.segments){a.push({source:t,target:l,start:o[n],end:o[r]});continue}const c=zi(e,l);for(const e of c){const n=us(i,s[e.start],s[e.end],e.loop),r=Ii(t,o,n);for(const t of r)a.push({source:t,target:e,start:{[i]:fs(l,n,"start",Math.max)},end:{[i]:fs(l,n,"end",Math.min)}})}}return a}(i,n,o);for(const{source:e,target:l,start:c,end:h}of r){const{style:{backgroundColor:r=s}={}}=e,d=!0!==n;t.save(),t.fillStyle=r,gs(t,a,d&&us(o,c,h)),t.beginPath();const u=!!i.pathSegment(t,e);let f;if(d){u?t.closePath():ps(t,n,h,o);const e=!!n.pathSegment(t,l,{move:u,reverse:!0});f=u&&e,f||ps(t,n,c,o)}t.closePath(),t.fill(f?"evenodd":"nonzero"),t.restore()}}function xs(t,e,i){const n=function(t){const{chart:e,fill:i,line:n}=t;if(X(i))return function(t,e){const i=t.getDatasetMeta(e);return i&&t.isDatasetVisible(e)?i.dataset:null}(e,i);if("stack"===i)return ss(t);if("shape"===i)return!0;const o=ns(t);return o instanceof is?o:cs(o,n)}(e),{line:o,scale:s,axis:a}=e,r=o.options,l=r.fill,c=r.backgroundColor,{above:h=c,below:d=c}=l||{};n&&o.points.length&&(Zt(t,i),function(t,e){const{line:i,target:n,above:o,below:s,area:a,scale:r}=e,l=i._loop?"angle":e.axis;t.save(),"x"===l&&s!==o&&(ds(t,n,a.top),ms(t,{line:i,target:n,color:o,scale:r,property:l}),t.restore(),t.save(),ds(t,n,a.bottom)),ms(t,{line:i,target:n,color:s,scale:r,property:l}),t.restore()}(t,{line:o,target:n,above:h,below:d,area:i,scale:s,axis:a}),Qt(t))}var bs={id:"filler",afterDatasetsUpdate(t,e,i){const n=(t.data.datasets||[]).length,o=[];let s,a,r,l;for(a=0;a<n;++a)s=t.getDatasetMeta(a),r=s.dataset,l=null,r&&r.options&&r instanceof No&&(l={visible:t.isDatasetVisible(a),index:a,fill:es(r,a,n),chart:t,axis:s.controller.options.indexAxis,scale:s.vScale,line:r}),s.$filler=l,o.push(l);for(a=0;a<n;++a)l=o[a],l&&!1!==l.fill&&(l.fill=hs(o,a,i.propagate))},beforeDraw(t,e,i){const n="beforeDraw"===i.drawTime,o=t.getSortedVisibleDatasetMetas(),s=t.chartArea;for(let e=o.length-1;e>=0;--e){const i=o[e].$filler;i&&(i.line.updateControlPoints(s,i.axis),n&&xs(t.ctx,i,s))}},beforeDatasetsDraw(t,e,i){if("beforeDatasetsDraw"!==i.drawTime)return;const n=t.getSortedVisibleDatasetMetas();for(let e=n.length-1;e>=0;--e){const i=n[e].$filler;i&&xs(t.ctx,i,t.chartArea)}},beforeDatasetDraw(t,e,i){const n=e.meta.$filler;n&&!1!==n.fill&&"beforeDatasetDraw"===i.drawTime&&xs(t.ctx,n,t.chartArea)},defaults:{propagate:!0,drawTime:"beforeDatasetDraw"}};const _s=(t,e)=>{let{boxHeight:i=e,boxWidth:n=e}=t;return t.usePointStyle&&(i=Math.min(i,e),n=Math.min(n,e)),{boxWidth:n,boxHeight:i,itemHeight:Math.max(e,i)}};class ys extends Mn{constructor(t){super(),this._added=!1,this.legendHitBoxes=[],this._hoveredItem=null,this.doughnutMode=!1,this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this.legendItems=void 0,this.columnSizes=void 0,this.lineWidths=void 0,this.maxHeight=void 0,this.maxWidth=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.height=void 0,this.width=void 0,this._margins=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e,i){const n=this;n.maxWidth=t,n.maxHeight=e,n._margins=i,n.setDimensions(),n.buildLabels(),n.fit()}setDimensions(){const t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=t._margins.left,t.right=t.width):(t.height=t.maxHeight,t.top=t._margins.top,t.bottom=t.height)}buildLabels(){const t=this,e=t.options.labels||{};let i=Q(e.generateLabels,[t.chart],t)||[];e.filter&&(i=i.filter((i=>e.filter(i,t.chart.data)))),e.sort&&(i=i.sort(((i,n)=>e.sort(i,n,t.chart.data)))),t.options.reverse&&i.reverse(),t.legendItems=i}fit(){const t=this,{options:e,ctx:i}=t;if(!e.display)return void(t.width=t.height=0);const n=e.labels,o=Ve(n.font),s=o.size,a=t._computeTitleHeight(),{boxWidth:r,itemHeight:l}=_s(n,s);let c,h;i.font=o.string,t.isHorizontal()?(c=t.maxWidth,h=t._fitRows(a,s,r,l)+10):(h=t.maxHeight,c=t._fitCols(a,s,r,l)+10),t.width=Math.min(c,e.maxWidth||t.maxWidth),t.height=Math.min(h,e.maxHeight||t.maxHeight)}_fitRows(t,e,i,n){const o=this,{ctx:s,maxWidth:a,options:{labels:{padding:r}}}=o,l=o.legendHitBoxes=[],c=o.lineWidths=[0],h=n+r;let d=t;s.textAlign="left",s.textBaseline="middle";let u=-1,f=-h;return o.legendItems.forEach(((t,o)=>{const g=i+e/2+s.measureText(t.text).width;(0===o||c[c.length-1]+g+2*r>a)&&(d+=h,c[c.length-(o>0?0:1)]=0,f+=h,u++),l[o]={left:0,top:f,row:u,width:g,height:n},c[c.length-1]+=g+r})),d}_fitCols(t,e,i,n){const o=this,{ctx:s,maxHeight:a,options:{labels:{padding:r}}}=o,l=o.legendHitBoxes=[],c=o.columnSizes=[],h=a-t;let d=r,u=0,f=0,g=0,p=0;return o.legendItems.forEach(((t,o)=>{const a=i+e/2+s.measureText(t.text).width;o>0&&f+n+2*r>h&&(d+=u+r,c.push({width:u,height:f}),g+=u+r,p++,u=f=0),l[o]={left:g,top:f,col:p,width:a,height:n},u=Math.max(u,a),f+=n+r})),d+=u,c.push({width:u,height:f}),d}adjustHitBoxes(){const t=this;if(!t.options.display)return;const e=t._computeTitleHeight(),{legendHitBoxes:i,options:{align:n,labels:{padding:s},rtl:a}}=t,r=Ti(a,t.left,t.width);if(this.isHorizontal()){let a=0,l=o(n,t.left+s,t.right-t.lineWidths[a]);for(const c of i)a!==c.row&&(a=c.row,l=o(n,t.left+s,t.right-t.lineWidths[a])),c.top+=t.top+e+s,c.left=r.leftForLtr(r.x(l),c.width),l+=c.width+s}else{let a=0,l=o(n,t.top+e+s,t.bottom-t.columnSizes[a].height);for(const c of i)c.col!==a&&(a=c.col,l=o(n,t.top+e+s,t.bottom-t.columnSizes[a].height)),c.top=l,c.left+=t.left+s,c.left=r.leftForLtr(r.x(c.left),c.width),l+=c.height+s}}isHorizontal(){return"top"===this.options.position||"bottom"===this.options.position}draw(){const t=this;if(t.options.display){const e=t.ctx;Zt(e,t),t._draw(),Qt(e)}}_draw(){const t=this,{options:e,columnSizes:i,lineWidths:n,ctx:a}=t,{align:r,labels:l}=e,c=xt.color,h=Ti(e.rtl,t.left,t.width),d=Ve(l.font),{color:u,padding:f}=l,g=d.size,p=g/2;let m;t.drawTitle(),a.textAlign=h.textAlign("left"),a.textBaseline="middle",a.lineWidth=.5,a.font=d.string;const{boxWidth:x,boxHeight:b,itemHeight:_}=_s(l,g),y=t.isHorizontal(),v=this._computeTitleHeight();m=y?{x:o(r,t.left+f,t.right-n[0]),y:t.top+f+v,line:0}:{x:t.left+f,y:o(r,t.top+v+f,t.bottom-i[0].height),line:0},Ai(t.ctx,e.textDirection);const w=_+f;t.legendItems.forEach(((M,k)=>{a.strokeStyle=M.fontColor||u,a.fillStyle=M.fontColor||u;const S=a.measureText(M.text).width,P=h.textAlign(M.textAlign||(M.textAlign=l.textAlign)),D=x+p+S;let C=m.x,O=m.y;h.setWidth(t.width),y?k>0&&C+D+f>t.right&&(O=m.y+=w,m.line++,C=m.x=o(r,t.left+f,t.right-n[m.line])):k>0&&O+w>t.bottom&&(C=m.x=C+i[m.line].width+f,m.line++,O=m.y=o(r,t.top+v+f,t.bottom-i[m.line].height));!function(t,e,i){if(isNaN(x)||x<=0||isNaN(b)||b<0)return;a.save();const n=K(i.lineWidth,1);if(a.fillStyle=K(i.fillStyle,c),a.lineCap=K(i.lineCap,"butt"),a.lineDashOffset=K(i.lineDashOffset,0),a.lineJoin=K(i.lineJoin,"miter"),a.lineWidth=n,a.strokeStyle=K(i.strokeStyle,c),a.setLineDash(K(i.lineDash,[])),l.usePointStyle){const o={radius:x*Math.SQRT2/2,pointStyle:i.pointStyle,rotation:i.rotation,borderWidth:n},s=h.xPlus(t,x/2);Kt(a,o,s,e+p)}else{const o=e+Math.max((g-b)/2,0),s=h.leftForLtr(t,x),r=Fe(i.borderRadius);a.beginPath(),Object.values(r).some((t=>0!==t))?ne(a,{x:s,y:o,w:x,h:b,radius:r}):a.rect(s,o,x,b),a.fill(),0!==n&&a.stroke()}a.restore()}(h.x(C),O,M),C=s(P,C+x+p,y?C+D:t.right,e.rtl),function(t,e,i){ee(a,i.text,t,e+_/2,d,{strikethrough:i.hidden,textAlign:h.textAlign(i.textAlign)})}(h.x(C),O,M),y?m.x+=D+f:m.y+=w})),Li(t.ctx,e.textDirection)}drawTitle(){const t=this,e=t.options,i=e.title,s=Ve(i.font),a=Be(i.padding);if(!i.display)return;const r=Ti(e.rtl,t.left,t.width),l=t.ctx,c=i.position,h=s.size/2,d=a.top+h;let u,f=t.left,g=t.width;if(this.isHorizontal())g=Math.max(...t.lineWidths),u=t.top+d,f=o(e.align,f,t.right-g);else{const i=t.columnSizes.reduce(((t,e)=>Math.max(t,e.height)),0);u=d+o(e.align,t.top,t.bottom-i-e.labels.padding-t._computeTitleHeight())}const p=o(c,f,f+g);l.textAlign=r.textAlign(n(c)),l.textBaseline="middle",l.strokeStyle=i.color,l.fillStyle=i.color,l.font=s.string,ee(l,i.text,p,u,s)}_computeTitleHeight(){const t=this.options.title,e=Ve(t.font),i=Be(t.padding);return t.display?e.lineHeight+i.height:0}_getLegendItemAt(t,e){const i=this;let n,o,s;if(t>=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom)for(s=i.legendHitBoxes,n=0;n<s.length;++n)if(o=s[n],t>=o.left&&t<=o.left+o.width&&e>=o.top&&e<=o.top+o.height)return i.legendItems[n];return null}handleEvent(t){const e=this,i=e.options;if(!function(t,e){if("mousemove"===t&&(e.onHover||e.onLeave))return!0;if(e.onClick&&("click"===t||"mouseup"===t))return!0;return!1}(t.type,i))return;const n=e._getLegendItemAt(t.x,t.y);if("mousemove"===t.type){const a=e._hoveredItem,r=(s=n,null!==(o=a)&&null!==s&&o.datasetIndex===s.datasetIndex&&o.index===s.index);a&&!r&&Q(i.onLeave,[t,a,e],e),e._hoveredItem=n,n&&!r&&Q(i.onHover,[t,n,e],e)}else n&&Q(i.onClick,[t,n,e],e);var o,s}}var vs={id:"legend",_element:ys,start(t,e,i){const n=t.legend=new ys({ctx:t.ctx,options:i,chart:t});ti.configure(t,n,i),ti.addBox(t,n)},stop(t){ti.removeBox(t,t.legend),delete t.legend},beforeUpdate(t,e,i){const n=t.legend;ti.configure(t,n,i),n.options=i},afterUpdate(t){const e=t.legend;e.buildLabels(),e.adjustHitBoxes()},afterEvent(t,e){e.replay||t.legend.handleEvent(e.event)},defaults:{display:!0,position:"top",align:"center",fullSize:!0,reverse:!1,weight:1e3,onClick(t,e,i){const n=e.datasetIndex,o=i.chart;o.isDatasetVisible(n)?(o.hide(n),e.hidden=!0):(o.show(n),e.hidden=!1)},onHover:null,onLeave:null,labels:{color:t=>t.chart.options.color,boxWidth:40,padding:10,generateLabels(t){const e=t.data.datasets,{labels:{usePointStyle:i,pointStyle:n,textAlign:o,color:s}}=t.legend.options;return t._getSortedDatasetMetas().map((t=>{const a=t.controller.getStyle(i?0:void 0),r=Be(a.borderWidth);return{text:e[t.index].label,fillStyle:a.backgroundColor,fontColor:s,hidden:!t.visible,lineCap:a.borderCapStyle,lineDash:a.borderDash,lineDashOffset:a.borderDashOffset,lineJoin:a.borderJoinStyle,lineWidth:(r.width+r.height)/4,strokeStyle:a.borderColor,pointStyle:n||a.pointStyle,rotation:a.rotation,textAlign:o||a.textAlign,borderRadius:0,datasetIndex:t.index}}),this)}},title:{color:t=>t.chart.options.color,display:!1,position:"center",text:""}},descriptors:{_scriptable:t=>!t.startsWith("on"),labels:{_scriptable:t=>!["generateLabels","filter","sort"].includes(t)}}};class ws extends Mn{constructor(t){super(),this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this._padding=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e){const i=this,n=i.options;if(i.left=0,i.top=0,!n.display)return void(i.width=i.height=i.right=i.bottom=0);i.width=i.right=t,i.height=i.bottom=e;const o=Y(n.text)?n.text.length:1;i._padding=Be(n.padding);const s=o*Ve(n.font).lineHeight+i._padding.height;i.isHorizontal()?i.height=s:i.width=s}isHorizontal(){const t=this.options.position;return"top"===t||"bottom"===t}_drawArgs(t){const{top:e,left:i,bottom:n,right:s,options:a}=this,r=a.align;let l,c,h,d=0;return this.isHorizontal()?(c=o(r,i,s),h=e+t,l=s-i):("left"===a.position?(c=i+t,h=o(r,n,e),d=-.5*bt):(c=s-t,h=o(r,e,n),d=.5*bt),l=n-e),{titleX:c,titleY:h,maxWidth:l,rotation:d}}draw(){const t=this,e=t.ctx,i=t.options;if(!i.display)return;const o=Ve(i.font),s=o.lineHeight/2+t._padding.top,{titleX:a,titleY:r,maxWidth:l,rotation:c}=t._drawArgs(s);ee(e,i.text,0,0,o,{color:i.color,maxWidth:l,rotation:c,textAlign:n(i.align),textBaseline:"middle",translation:[a,r]})}}var Ms={id:"title",_element:ws,start(t,e,i){!function(t,e){const i=new ws({ctx:t.ctx,options:e,chart:t});ti.configure(t,i,e),ti.addBox(t,i),t.titleBlock=i}(t,i)},stop(t){const e=t.titleBlock;ti.removeBox(t,e),delete t.titleBlock},beforeUpdate(t,e,i){const n=t.titleBlock;ti.configure(t,n,i),n.options=i},defaults:{align:"center",display:!1,font:{weight:"bold"},fullSize:!0,padding:10,position:"top",text:"",weight:2e3},defaultRoutes:{color:"color"},descriptors:{_scriptable:!0,_indexable:!1}};const ks=new WeakMap;var Ss={id:"subtitle",start(t,e,i){const n=new ws({ctx:t.ctx,options:i,chart:t});ti.configure(t,n,i),ti.addBox(t,n),ks.set(t,n)},stop(t){ti.removeBox(t,ks.get(t)),ks.delete(t)},beforeUpdate(t,e,i){const n=ks.get(t);ti.configure(t,n,i),n.options=i},defaults:{align:"center",display:!1,font:{weight:"normal"},fullSize:!0,padding:0,position:"top",text:"",weight:1500},defaultRoutes:{color:"color"},descriptors:{_scriptable:!0,_indexable:!1}};const Ps={average(t){if(!t.length)return!1;let e,i,n=0,o=0,s=0;for(e=0,i=t.length;e<i;++e){const i=t[e].element;if(i&&i.hasValue()){const t=i.tooltipPosition();n+=t.x,o+=t.y,++s}}return{x:n/s,y:o/s}},nearest(t,e){if(!t.length)return!1;let i,n,o,s=e.x,a=e.y,r=Number.POSITIVE_INFINITY;for(i=0,n=t.length;i<n;++i){const n=t[i].element;if(n&&n.hasValue()){const t=Bt(e,n.getCenterPoint());t<r&&(r=t,o=n)}}if(o){const t=o.tooltipPosition();s=t.x,a=t.y}return{x:s,y:a}}};function Ds(t,e){return e&&(Y(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function Cs(t){return("string"==typeof t||t instanceof String)&&t.indexOf("\n")>-1?t.split("\n"):t}function Os(t,e){const{element:i,datasetIndex:n,index:o}=e,s=t.getDatasetMeta(n).controller,{label:a,value:r}=s.getLabelAndValue(o);return{chart:t,label:a,parsed:s.getParsed(o),raw:t.data.datasets[n].data[o],formattedValue:r,dataset:s.getDataset(),dataIndex:o,datasetIndex:n,element:i}}function Ts(t,e){const i=t._chart.ctx,{body:n,footer:o,title:s}=t,{boxWidth:a,boxHeight:r}=e,l=Ve(e.bodyFont),c=Ve(e.titleFont),h=Ve(e.footerFont),d=s.length,u=o.length,f=n.length,g=Be(e.padding);let p=g.height,m=0,x=n.reduce(((t,e)=>t+e.before.length+e.lines.length+e.after.length),0);if(x+=t.beforeBody.length+t.afterBody.length,d&&(p+=d*c.lineHeight+(d-1)*e.titleSpacing+e.titleMarginBottom),x){p+=f*(e.displayColors?Math.max(r,l.lineHeight):l.lineHeight)+(x-f)*l.lineHeight+(x-1)*e.bodySpacing}u&&(p+=e.footerMarginTop+u*h.lineHeight+(u-1)*e.footerSpacing);let b=0;const _=function(t){m=Math.max(m,i.measureText(t).width+b)};return i.save(),i.font=c.string,J(t.title,_),i.font=l.string,J(t.beforeBody.concat(t.afterBody),_),b=e.displayColors?a+2:0,J(n,(t=>{J(t.before,_),J(t.lines,_),J(t.after,_)})),b=0,i.font=h.string,J(t.footer,_),i.restore(),m+=g.width,{width:m,height:p}}function As(t,e,i,n){const{x:o,width:s}=i,{width:a,chartArea:{left:r,right:l}}=t;let c="center";return"center"===n?c=o<=(r+l)/2?"left":"right":o<=s/2?c="left":o>=a-s/2&&(c="right"),function(t,e,i,n){const{x:o,width:s}=n,a=i.caretSize+i.caretPadding;return"left"===t&&o+s+a>e.width||"right"===t&&o-s-a<0||void 0}(c,t,e,i)&&(c="center"),c}function Ls(t,e,i){const n=e.yAlign||function(t,e){const{y:i,height:n}=e;return i<n/2?"top":i>t.height-n/2?"bottom":"center"}(t,i);return{xAlign:e.xAlign||As(t,e,i,n),yAlign:n}}function Rs(t,e,i,n){const{caretSize:o,caretPadding:s,cornerRadius:a}=t,{xAlign:r,yAlign:l}=i,c=o+s,h=a+s;let d=function(t,e){let{x:i,width:n}=t;return"right"===e?i-=n:"center"===e&&(i-=n/2),i}(e,r);const u=function(t,e,i){let{y:n,height:o}=t;return"top"===e?n+=i:n-="bottom"===e?o+i:o/2,n}(e,l,c);return"center"===l?"left"===r?d+=c:"right"===r&&(d-=c):"left"===r?d-=h:"right"===r&&(d+=h),{x:Ht(d,0,n.width-e.width),y:Ht(u,0,n.height-e.height)}}function Es(t,e,i){const n=Be(i.padding);return"center"===e?t.x+t.width/2:"right"===e?t.x+t.width-n.right:t.x+n.left}function Is(t){return Ds([],Cs(t))}function zs(t,e){const i=e&&e.dataset&&e.dataset.tooltip&&e.dataset.tooltip.callbacks;return i?t.override(i):t}class Fs extends Mn{constructor(t){super(),this.opacity=0,this._active=[],this._chart=t._chart,this._eventPosition=void 0,this._size=void 0,this._cachedAnimations=void 0,this._tooltipItems=[],this.$animations=void 0,this.$context=void 0,this.options=t.options,this.dataPoints=void 0,this.title=void 0,this.beforeBody=void 0,this.body=void 0,this.afterBody=void 0,this.footer=void 0,this.xAlign=void 0,this.yAlign=void 0,this.x=void 0,this.y=void 0,this.height=void 0,this.width=void 0,this.caretX=void 0,this.caretY=void 0,this.labelColors=void 0,this.labelPointStyles=void 0,this.labelTextColors=void 0}initialize(t){this.options=t,this._cachedAnimations=void 0,this.$context=void 0}_resolveAnimations(){const t=this,e=t._cachedAnimations;if(e)return e;const i=t._chart,n=t.options.setContext(t.getContext()),o=n.enabled&&i.options.animation&&n.animations,s=new hn(t._chart,o);return o._cacheable&&(t._cachedAnimations=Object.freeze(s)),s}getContext(){const t=this;return t.$context||(t.$context=(e=t._chart.getContext(),i=t,n=t._tooltipItems,Object.assign(Object.create(e),{tooltip:i,tooltipItems:n,type:"tooltip"})));var e,i,n}getTitle(t,e){const i=this,{callbacks:n}=e,o=n.beforeTitle.apply(i,[t]),s=n.title.apply(i,[t]),a=n.afterTitle.apply(i,[t]);let r=[];return r=Ds(r,Cs(o)),r=Ds(r,Cs(s)),r=Ds(r,Cs(a)),r}getBeforeBody(t,e){return Is(e.callbacks.beforeBody.apply(this,[t]))}getBody(t,e){const i=this,{callbacks:n}=e,o=[];return J(t,(t=>{const e={before:[],lines:[],after:[]},s=zs(n,t);Ds(e.before,Cs(s.beforeLabel.call(i,t))),Ds(e.lines,s.label.call(i,t)),Ds(e.after,Cs(s.afterLabel.call(i,t))),o.push(e)})),o}getAfterBody(t,e){return Is(e.callbacks.afterBody.apply(this,[t]))}getFooter(t,e){const i=this,{callbacks:n}=e,o=n.beforeFooter.apply(i,[t]),s=n.footer.apply(i,[t]),a=n.afterFooter.apply(i,[t]);let r=[];return r=Ds(r,Cs(o)),r=Ds(r,Cs(s)),r=Ds(r,Cs(a)),r}_createItems(t){const e=this,i=e._active,n=e._chart.data,o=[],s=[],a=[];let r,l,c=[];for(r=0,l=i.length;r<l;++r)c.push(Os(e._chart,i[r]));return t.filter&&(c=c.filter(((e,i,o)=>t.filter(e,i,o,n)))),t.itemSort&&(c=c.sort(((e,i)=>t.itemSort(e,i,n)))),J(c,(i=>{const n=zs(t.callbacks,i);o.push(n.labelColor.call(e,i)),s.push(n.labelPointStyle.call(e,i)),a.push(n.labelTextColor.call(e,i))})),e.labelColors=o,e.labelPointStyles=s,e.labelTextColors=a,e.dataPoints=c,c}update(t,e){const i=this,n=i.options.setContext(i.getContext()),o=i._active;let s,a=[];if(o.length){const t=Ps[n.position].call(i,o,i._eventPosition);a=i._createItems(n),i.title=i.getTitle(a,n),i.beforeBody=i.getBeforeBody(a,n),i.body=i.getBody(a,n),i.afterBody=i.getAfterBody(a,n),i.footer=i.getFooter(a,n);const e=i._size=Ts(i,n),r=Object.assign({},t,e),l=Ls(i._chart,n,r),c=Rs(n,r,l,i._chart);i.xAlign=l.xAlign,i.yAlign=l.yAlign,s={opacity:1,x:c.x,y:c.y,width:e.width,height:e.height,caretX:t.x,caretY:t.y}}else 0!==i.opacity&&(s={opacity:0});i._tooltipItems=a,i.$context=void 0,s&&i._resolveAnimations().update(i,s),t&&n.external&&n.external.call(i,{chart:i._chart,tooltip:i,replay:e})}drawCaret(t,e,i,n){const o=this.getCaretPosition(t,i,n);e.lineTo(o.x1,o.y1),e.lineTo(o.x2,o.y2),e.lineTo(o.x3,o.y3)}getCaretPosition(t,e,i){const{xAlign:n,yAlign:o}=this,{cornerRadius:s,caretSize:a}=i,{x:r,y:l}=t,{width:c,height:h}=e;let d,u,f,g,p,m;return"center"===o?(p=l+h/2,"left"===n?(d=r,u=d-a,g=p+a,m=p-a):(d=r+c,u=d+a,g=p-a,m=p+a),f=d):(u="left"===n?r+s+a:"right"===n?r+c-s-a:this.caretX,"top"===o?(g=l,p=g-a,d=u-a,f=u+a):(g=l+h,p=g+a,d=u+a,f=u-a),m=g),{x1:d,x2:u,x3:f,y1:g,y2:p,y3:m}}drawTitle(t,e,i){const n=this,o=n.title,s=o.length;let a,r,l;if(s){const c=Ti(i.rtl,n.x,n.width);for(t.x=Es(n,i.titleAlign,i),e.textAlign=c.textAlign(i.titleAlign),e.textBaseline="middle",a=Ve(i.titleFont),r=i.titleSpacing,e.fillStyle=i.titleColor,e.font=a.string,l=0;l<s;++l)e.fillText(o[l],c.x(t.x),t.y+a.lineHeight/2),t.y+=a.lineHeight+r,l+1===s&&(t.y+=i.titleMarginBottom-r)}}_drawColorBox(t,e,i,n,o){const s=this,a=s.labelColors[i],r=s.labelPointStyles[i],{boxHeight:l,boxWidth:c}=o,h=Ve(o.bodyFont),d=Es(s,"left",o),u=n.x(d),f=l<h.lineHeight?(h.lineHeight-l)/2:0,g=e.y+f;if(o.usePointStyle){const e={radius:Math.min(c,l)/2,pointStyle:r.pointStyle,rotation:r.rotation,borderWidth:1},i=n.leftForLtr(u,c)+c/2,s=g+l/2;t.strokeStyle=o.multiKeyBackground,t.fillStyle=o.multiKeyBackground,Kt(t,e,i,s),t.strokeStyle=a.borderColor,t.fillStyle=a.backgroundColor,Kt(t,e,i,s)}else{t.lineWidth=a.borderWidth||1,t.strokeStyle=a.borderColor,t.setLineDash(a.borderDash||[]),t.lineDashOffset=a.borderDashOffset||0;const e=n.leftForLtr(u,c),i=n.leftForLtr(n.xPlus(u,1),c-2),s=Fe(a.borderRadius);Object.values(s).some((t=>0!==t))?(t.beginPath(),t.fillStyle=o.multiKeyBackground,ne(t,{x:e,y:g,w:c,h:l,radius:s}),t.fill(),t.stroke(),t.fillStyle=a.backgroundColor,t.beginPath(),ne(t,{x:i,y:g+1,w:c-2,h:l-2,radius:s}),t.fill()):(t.fillStyle=o.multiKeyBackground,t.fillRect(e,g,c,l),t.strokeRect(e,g,c,l),t.fillStyle=a.backgroundColor,t.fillRect(i,g+1,c-2,l-2))}t.fillStyle=s.labelTextColors[i]}drawBody(t,e,i){const n=this,{body:o}=n,{bodySpacing:s,bodyAlign:a,displayColors:r,boxHeight:l,boxWidth:c}=i,h=Ve(i.bodyFont);let d=h.lineHeight,u=0;const f=Ti(i.rtl,n.x,n.width),g=function(i){e.fillText(i,f.x(t.x+u),t.y+d/2),t.y+=d+s},p=f.textAlign(a);let m,x,b,_,y,v,w;for(e.textAlign=a,e.textBaseline="middle",e.font=h.string,t.x=Es(n,p,i),e.fillStyle=i.bodyColor,J(n.beforeBody,g),u=r&&"right"!==p?"center"===a?c/2+1:c+2:0,_=0,v=o.length;_<v;++_){for(m=o[_],x=n.labelTextColors[_],e.fillStyle=x,J(m.before,g),b=m.lines,r&&b.length&&(n._drawColorBox(e,t,_,f,i),d=Math.max(h.lineHeight,l)),y=0,w=b.length;y<w;++y)g(b[y]),d=h.lineHeight;J(m.after,g)}u=0,d=h.lineHeight,J(n.afterBody,g),t.y-=s}drawFooter(t,e,i){const n=this,o=n.footer,s=o.length;let a,r;if(s){const l=Ti(i.rtl,n.x,n.width);for(t.x=Es(n,i.footerAlign,i),t.y+=i.footerMarginTop,e.textAlign=l.textAlign(i.footerAlign),e.textBaseline="middle",a=Ve(i.footerFont),e.fillStyle=i.footerColor,e.font=a.string,r=0;r<s;++r)e.fillText(o[r],l.x(t.x),t.y+a.lineHeight/2),t.y+=a.lineHeight+i.footerSpacing}}drawBackground(t,e,i,n){const{xAlign:o,yAlign:s}=this,{x:a,y:r}=t,{width:l,height:c}=i,h=n.cornerRadius;e.fillStyle=n.backgroundColor,e.strokeStyle=n.borderColor,e.lineWidth=n.borderWidth,e.beginPath(),e.moveTo(a+h,r),"top"===s&&this.drawCaret(t,e,i,n),e.lineTo(a+l-h,r),e.quadraticCurveTo(a+l,r,a+l,r+h),"center"===s&&"right"===o&&this.drawCaret(t,e,i,n),e.lineTo(a+l,r+c-h),e.quadraticCurveTo(a+l,r+c,a+l-h,r+c),"bottom"===s&&this.drawCaret(t,e,i,n),e.lineTo(a+h,r+c),e.quadraticCurveTo(a,r+c,a,r+c-h),"center"===s&&"left"===o&&this.drawCaret(t,e,i,n),e.lineTo(a,r+h),e.quadraticCurveTo(a,r,a+h,r),e.closePath(),e.fill(),n.borderWidth>0&&e.stroke()}_updateAnimationTarget(t){const e=this,i=e._chart,n=e.$animations,o=n&&n.x,s=n&&n.y;if(o||s){const n=Ps[t.position].call(e,e._active,e._eventPosition);if(!n)return;const a=e._size=Ts(e,t),r=Object.assign({},n,e._size),l=Ls(i,t,r),c=Rs(t,r,l,i);o._to===c.x&&s._to===c.y||(e.xAlign=l.xAlign,e.yAlign=l.yAlign,e.width=a.width,e.height=a.height,e.caretX=n.x,e.caretY=n.y,e._resolveAnimations().update(e,c))}}draw(t){const e=this,i=e.options.setContext(e.getContext());let n=e.opacity;if(!n)return;e._updateAnimationTarget(i);const o={width:e.width,height:e.height},s={x:e.x,y:e.y};n=Math.abs(n)<.001?0:n;const a=Be(i.padding),r=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;i.enabled&&r&&(t.save(),t.globalAlpha=n,e.drawBackground(s,t,o,i),Ai(t,i.textDirection),s.y+=a.top,e.drawTitle(s,t,i),e.drawBody(s,t,i),e.drawFooter(s,t,i),Li(t,i.textDirection),t.restore())}getActiveElements(){return this._active||[]}setActiveElements(t,e){const i=this,n=i._active,o=t.map((({datasetIndex:t,index:e})=>{const n=i._chart.getDatasetMeta(t);if(!n)throw new Error("Cannot find a dataset at index "+t);return{datasetIndex:t,element:n.data[e],index:e}})),s=!tt(n,o),a=i._positionChanged(o,e);(s||a)&&(i._active=o,i._eventPosition=e,i.update(!0))}handleEvent(t,e){const i=this,n=i.options,o=i._active||[];let s=!1,a=[];"mouseout"!==t.type&&(a=i._chart.getElementsAtEventForMode(t,n.mode,n,e),n.reverse&&a.reverse());const r=i._positionChanged(a,t);return s=e||!tt(a,o)||r,s&&(i._active=a,(n.enabled||n.external)&&(i._eventPosition={x:t.x,y:t.y},i.update(!0,e))),s}_positionChanged(t,e){const{caretX:i,caretY:n,options:o}=this,s=Ps[o.position].call(this,t,e);return!1!==s&&(i!==s.x||n!==s.y)}}Fs.positioners=Ps;var Bs={id:"tooltip",_element:Fs,positioners:Ps,afterInit(t,e,i){i&&(t.tooltip=new Fs({_chart:t,options:i}))},beforeUpdate(t,e,i){t.tooltip&&t.tooltip.initialize(i)},reset(t,e,i){t.tooltip&&t.tooltip.initialize(i)},afterDraw(t){const e=t.tooltip,i={tooltip:e};!1!==t.notifyPlugins("beforeTooltipDraw",i)&&(e&&e.draw(t.ctx),t.notifyPlugins("afterTooltipDraw",i))},afterEvent(t,e){if(t.tooltip){const i=e.replay;t.tooltip.handleEvent(e.event,i)&&(e.changed=!0)}},defaults:{enabled:!0,external:null,position:"average",backgroundColor:"rgba(0,0,0,0.8)",titleColor:"#fff",titleFont:{weight:"bold"},titleSpacing:2,titleMarginBottom:6,titleAlign:"left",bodyColor:"#fff",bodySpacing:2,bodyFont:{},bodyAlign:"left",footerColor:"#fff",footerSpacing:2,footerMarginTop:6,footerFont:{weight:"bold"},footerAlign:"left",padding:6,caretPadding:2,caretSize:5,cornerRadius:6,boxHeight:(t,e)=>e.bodyFont.size,boxWidth:(t,e)=>e.bodyFont.size,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,animation:{duration:400,easing:"easeOutQuart"},animations:{numbers:{type:"number",properties:["x","y","width","height","caretX","caretY"]},opacity:{easing:"linear",duration:200}},callbacks:{beforeTitle:H,title(t){if(t.length>0){const e=t[0],i=e.chart.data.labels,n=i?i.length:0;if(this&&this.options&&"dataset"===this.options.mode)return e.dataset.label||"";if(e.label)return e.label;if(n>0&&e.dataIndex<n)return i[e.dataIndex]}return""},afterTitle:H,beforeBody:H,beforeLabel:H,label(t){if(this&&this.options&&"dataset"===this.options.mode)return t.label+": "+t.formattedValue||t.formattedValue;let e=t.dataset.label||"";e&&(e+=": ");const i=t.formattedValue;return $(i)||(e+=i),e},labelColor(t){const e=t.chart.getDatasetMeta(t.datasetIndex).controller.getStyle(t.dataIndex);return{borderColor:e.borderColor,backgroundColor:e.backgroundColor,borderWidth:e.borderWidth,borderDash:e.borderDash,borderDashOffset:e.borderDashOffset,borderRadius:0}},labelTextColor(){return this.options.bodyColor},labelPointStyle(t){const e=t.chart.getDatasetMeta(t.datasetIndex).controller.getStyle(t.dataIndex);return{pointStyle:e.pointStyle,rotation:e.rotation}},afterLabel:H,afterBody:H,beforeFooter:H,footer:H,afterFooter:H}},defaultRoutes:{bodyFont:"font",footerFont:"font",titleFont:"font"},descriptors:{_scriptable:t=>"filter"!==t&&"itemSort"!==t&&"external"!==t,_indexable:!1,callbacks:{_scriptable:!1,_indexable:!1},animation:{_fallback:!1},animations:{_fallback:"animation"}},additionalOptionScopes:["interaction"]},Vs=Object.freeze({__proto__:null,Decimation:ts,Filler:bs,Legend:vs,SubTitle:Ss,Title:Ms,Tooltip:Bs});function Ws(t,e,i){const n=t.indexOf(e);if(-1===n)return((t,e,i)=>"string"==typeof e?t.push(e)-1:isNaN(e)?null:i)(t,e,i);return n!==t.lastIndexOf(e)?i:n}class Ns extends En{constructor(t){super(t),this._startValue=void 0,this._valueRange=0}parse(t,e){if($(t))return null;const i=this.getLabels();return((t,e)=>null===t?null:Ht(Math.round(t),0,e))(e=isFinite(e)&&i[e]===t?e:Ws(i,t,K(e,t)),i.length-1)}determineDataLimits(){const t=this,{minDefined:e,maxDefined:i}=t.getUserBounds();let{min:n,max:o}=t.getMinMax(!0);"ticks"===t.options.bounds&&(e||(n=0),i||(o=t.getLabels().length-1)),t.min=n,t.max=o}buildTicks(){const t=this,e=t.min,i=t.max,n=t.options.offset,o=[];let s=t.getLabels();s=0===e&&i===s.length-1?s:s.slice(e,i+1),t._valueRange=Math.max(s.length-(n?0:1),1),t._startValue=t.min-(n?.5:0);for(let t=e;t<=i;t++)o.push({value:t});return o}getLabelForValue(t){const e=this.getLabels();return t>=0&&t<e.length?e[t]:t}configure(){const t=this;super.configure(),t.isHorizontal()||(t._reversePixels=!t._reversePixels)}getPixelForValue(t){const e=this;return"number"!=typeof t&&(t=e.parse(t)),null===t?NaN:e.getPixelForDecimal((t-e._startValue)/e._valueRange)}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getValueForPixel(t){const e=this;return Math.round(e._startValue+e.getDecimalForPixel(t)*e._valueRange)}getBasePixel(){return this.bottom}}function Hs(t,e,{horizontal:i,minRotation:n}){const o=Et(n),s=(i?Math.sin(o):Math.cos(o))||.001,a=.75*e*(""+t).length;return Math.min(e/s,a)}Ns.id="category",Ns.defaults={ticks:{callback:Ns.prototype.getLabelForValue}};class js extends En{constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._endValue=void 0,this._valueRange=0}parse(t,e){return $(t)||("number"==typeof t||t instanceof Number)&&!isFinite(+t)?null:+t}handleTickRangeOptions(){const t=this,{beginAtZero:e}=t.options,{minDefined:i,maxDefined:n}=t.getUserBounds();let{min:o,max:s}=t;const a=t=>o=i?o:t,r=t=>s=n?s:t;if(e){const t=Dt(o),e=Dt(s);t<0&&e<0?r(0):t>0&&e>0&&a(0)}if(o===s){let t=1;(s>=Number.MAX_SAFE_INTEGER||o<=Number.MIN_SAFE_INTEGER)&&(t=Math.abs(.05*s)),r(s+t),e||a(o-t)}t.min=o,t.max=s}getTickLimit(){const t=this,e=t.options.ticks;let i,{maxTicksLimit:n,stepSize:o}=e;return o?i=Math.ceil(t.max/o)-Math.floor(t.min/o)+1:(i=t.computeTickLimit(),n=n||11),n&&(i=Math.min(n,i)),i}computeTickLimit(){return Number.POSITIVE_INFINITY}buildTicks(){const t=this,e=t.options,i=e.ticks;let n=t.getTickLimit();n=Math.max(2,n);const o=function(t,e){const i=[],{bounds:n,step:o,min:s,max:a,precision:r,count:l,maxTicks:c,maxDigits:h,includeBounds:d}=t,u=o||1,f=c-1,{min:g,max:p}=e,m=!$(s),x=!$(a),b=!$(l),_=(p-g)/(h+1);let y,v,w,M,k=Ct((p-g)/f/u)*u;if(k<1e-14&&!m&&!x)return[{value:g},{value:p}];M=Math.ceil(p/k)-Math.floor(g/k),M>f&&(k=Ct(M*k/f/u)*u),$(r)||(y=Math.pow(10,r),k=Math.ceil(k*y)/y),"ticks"===n?(v=Math.floor(g/k)*k,w=Math.ceil(p/k)*k):(v=g,w=p),m&&x&&o&&Lt((a-s)/o,k/1e3)?(M=Math.round(Math.min((a-s)/k,c)),k=(a-s)/M,v=s,w=a):b?(v=m?s:v,w=x?a:w,M=l-1,k=(w-v)/M):(M=(w-v)/k,M=At(M,Math.round(M),k/1e3)?Math.round(M):Math.ceil(M));const S=Math.max(zt(k),zt(v));y=Math.pow(10,$(r)?S:r),v=Math.round(v*y)/y,w=Math.round(w*y)/y;let P=0;for(m&&(d&&v!==s?(i.push({value:s}),v<s&&P++,At(Math.round((v+P*k)*y)/y,s,Hs(s,_,t))&&P++):v<s&&P++);P<M;++P)i.push({value:Math.round((v+P*k)*y)/y});return x&&d&&w!==a?At(i[i.length-1].value,a,Hs(a,_,t))?i[i.length-1].value=a:i.push({value:a}):x&&w!==a||i.push({value:w}),i}({maxTicks:n,bounds:e.bounds,min:e.min,max:e.max,precision:i.precision,step:i.stepSize,count:i.count,maxDigits:t._maxDigits(),horizontal:t.isHorizontal(),minRotation:i.minRotation||0,includeBounds:!1!==i.includeBounds},t._range||t);return"ticks"===e.bounds&&Rt(o,t,"value"),e.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max),o}configure(){const t=this,e=t.ticks;let i=t.min,n=t.max;if(super.configure(),t.options.offset&&e.length){const t=(n-i)/Math.max(e.length-1,1)/2;i-=t,n+=t}t._startValue=i,t._endValue=n,t._valueRange=n-i}getLabelForValue(t){return Oi(t,this.chart.options.locale)}}class $s extends js{determineDataLimits(){const t=this,{min:e,max:i}=t.getMinMax(!0);t.min=X(e)?e:0,t.max=X(i)?i:1,t.handleTickRangeOptions()}computeTickLimit(){const t=this,e=t.isHorizontal(),i=e?t.width:t.height,n=Et(t.options.ticks.minRotation),o=(e?Math.sin(n):Math.cos(n))||.001,s=t._resolveTickFontOptions(0);return Math.ceil(i/Math.min(40,s.lineHeight/o))}getPixelForValue(t){return null===t?NaN:this.getPixelForDecimal((t-this._startValue)/this._valueRange)}getValueForPixel(t){return this._startValue+this.getDecimalForPixel(t)*this._valueRange}}function Ys(t){return 1===t/Math.pow(10,Math.floor(Pt(t)))}$s.id="linear",$s.defaults={ticks:{callback:Sn.formatters.numeric}};class Us extends En{constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._valueRange=0}parse(t,e){const i=js.prototype.parse.apply(this,[t,e]);if(0!==i)return X(i)&&i>0?i:null;this._zero=!0}determineDataLimits(){const t=this,{min:e,max:i}=t.getMinMax(!0);t.min=X(e)?Math.max(0,e):null,t.max=X(i)?Math.max(0,i):null,t.options.beginAtZero&&(t._zero=!0),t.handleTickRangeOptions()}handleTickRangeOptions(){const t=this,{minDefined:e,maxDefined:i}=t.getUserBounds();let n=t.min,o=t.max;const s=t=>n=e?n:t,a=t=>o=i?o:t,r=(t,e)=>Math.pow(10,Math.floor(Pt(t))+e);n===o&&(n<=0?(s(1),a(10)):(s(r(n,-1)),a(r(o,1)))),n<=0&&s(r(o,-1)),o<=0&&a(r(n,1)),t._zero&&t.min!==t._suggestedMin&&n===r(t.min,0)&&s(r(n,-1)),t.min=n,t.max=o}buildTicks(){const t=this,e=t.options,i=function(t,e){const i=Math.floor(Pt(e.max)),n=Math.ceil(e.max/Math.pow(10,i)),o=[];let s=q(t.min,Math.pow(10,Math.floor(Pt(e.min)))),a=Math.floor(Pt(s)),r=Math.floor(s/Math.pow(10,a)),l=a<0?Math.pow(10,Math.abs(a)):1;do{o.push({value:s,major:Ys(s)}),++r,10===r&&(r=1,++a,l=a>=0?1:l),s=Math.round(r*Math.pow(10,a)*l)/l}while(a<i||a===i&&r<n);const c=q(t.max,s);return o.push({value:c,major:Ys(s)}),o}({min:t._userMin,max:t._userMax},t);return"ticks"===e.bounds&&Rt(i,t,"value"),e.reverse?(i.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max),i}getLabelForValue(t){return void 0===t?"0":Oi(t,this.chart.options.locale)}configure(){const t=this,e=t.min;super.configure(),t._startValue=Pt(e),t._valueRange=Pt(t.max)-Pt(e)}getPixelForValue(t){const e=this;return void 0!==t&&0!==t||(t=e.min),null===t||isNaN(t)?NaN:e.getPixelForDecimal(t===e.min?0:(Pt(t)-e._startValue)/e._valueRange)}getValueForPixel(t){const e=this,i=e.getDecimalForPixel(t);return Math.pow(10,e._startValue+i*e._valueRange)}}function Xs(t){const e=t.ticks;if(e.display&&t.display){const t=Be(e.backdropPadding);return K(e.font&&e.font.size,xt.font.size)+t.height}return 0}function qs(t,e,i,n,o){return t===n||t===o?{start:e-i/2,end:e+i/2}:t<n||t>o?{start:e-i,end:e}:{start:e,end:e+i}}function Ks(t){const e={l:0,r:t.width,t:0,b:t.height-t.paddingTop},i={},n=[],o=[],s=t.getLabels().length;for(let c=0;c<s;c++){const s=t.options.pointLabels.setContext(t.getPointLabelContext(c));o[c]=s.padding;const h=t.getPointPosition(c,t.drawingArea+o[c]),d=Ve(s.font),u=(a=t.ctx,r=d,l=Y(l=t._pointLabels[c])?l:[l],{w:Ut(a,r.string,l),h:l.length*r.lineHeight});n[c]=u;const f=t.getIndexAngle(c),g=It(f),p=qs(g,h.x,u.w,0,180),m=qs(g,h.y,u.h,90,270);p.start<e.l&&(e.l=p.start,i.l=f),p.end>e.r&&(e.r=p.end,i.r=f),m.start<e.t&&(e.t=m.start,i.t=f),m.end>e.b&&(e.b=m.end,i.b=f)}var a,r,l;t._setReductions(t.drawingArea,e,i),t._pointLabelItems=function(t,e,i){const n=[],o=t.getLabels().length,s=t.options,a=Xs(s),r=t.getDistanceFromCenterForValue(s.ticks.reverse?t.min:t.max);for(let s=0;s<o;s++){const o=0===s?a/2:0,l=t.getPointPosition(s,r+o+i[s]),c=It(t.getIndexAngle(s)),h=e[s],d=Qs(l.y,h.h,c),u=Gs(c),f=Zs(l.x,h.w,u);n.push({x:l.x,y:d,textAlign:u,left:f,top:d,right:f+h.w,bottom:d+h.h})}return n}(t,n,o)}function Gs(t){return 0===t||180===t?"center":t<180?"left":"right"}function Zs(t,e,i){return"right"===i?t-=e:"center"===i&&(t-=e/2),t}function Qs(t,e,i){return 90===i||270===i?t-=e/2:(i>270||i<90)&&(t-=e),t}function Js(t,e,i,n){const{ctx:o}=t;if(i)o.arc(t.xCenter,t.yCenter,e,0,_t);else{let i=t.getPointPosition(0,e);o.moveTo(i.x,i.y);for(let s=1;s<n;s++)i=t.getPointPosition(s,e),o.lineTo(i.x,i.y)}}function ta(t){return Tt(t)?t:0}Us.id="logarithmic",Us.defaults={ticks:{callback:Sn.formatters.logarithmic,major:{enabled:!0}}};class ea extends js{constructor(t){super(t),this.xCenter=void 0,this.yCenter=void 0,this.drawingArea=void 0,this._pointLabels=[],this._pointLabelItems=[]}setDimensions(){const t=this;t.width=t.maxWidth,t.height=t.maxHeight,t.paddingTop=Xs(t.options)/2,t.xCenter=Math.floor(t.width/2),t.yCenter=Math.floor((t.height-t.paddingTop)/2),t.drawingArea=Math.min(t.height-t.paddingTop,t.width)/2}determineDataLimits(){const t=this,{min:e,max:i}=t.getMinMax(!1);t.min=X(e)&&!isNaN(e)?e:0,t.max=X(i)&&!isNaN(i)?i:0,t.handleTickRangeOptions()}computeTickLimit(){return Math.ceil(this.drawingArea/Xs(this.options))}generateTickLabels(t){const e=this;js.prototype.generateTickLabels.call(e,t),e._pointLabels=e.getLabels().map(((t,i)=>{const n=Q(e.options.pointLabels.callback,[t,i],e);return n||0===n?n:""}))}fit(){const t=this,e=t.options;e.display&&e.pointLabels.display?Ks(t):t.setCenterPoint(0,0,0,0)}_setReductions(t,e,i){const n=this;let o=e.l/Math.sin(i.l),s=Math.max(e.r-n.width,0)/Math.sin(i.r),a=-e.t/Math.cos(i.t),r=-Math.max(e.b-(n.height-n.paddingTop),0)/Math.cos(i.b);o=ta(o),s=ta(s),a=ta(a),r=ta(r),n.drawingArea=Math.max(t/2,Math.min(Math.floor(t-(o+s)/2),Math.floor(t-(a+r)/2))),n.setCenterPoint(o,s,a,r)}setCenterPoint(t,e,i,n){const o=this,s=o.width-e-o.drawingArea,a=t+o.drawingArea,r=i+o.drawingArea,l=o.height-o.paddingTop-n-o.drawingArea;o.xCenter=Math.floor((a+s)/2+o.left),o.yCenter=Math.floor((r+l)/2+o.top+o.paddingTop)}getIndexAngle(t){return Wt(t*(_t/this.getLabels().length)+Et(this.options.startAngle||0))}getDistanceFromCenterForValue(t){const e=this;if($(t))return NaN;const i=e.drawingArea/(e.max-e.min);return e.options.reverse?(e.max-t)*i:(t-e.min)*i}getValueForDistanceFromCenter(t){if($(t))return NaN;const e=this,i=t/(e.drawingArea/(e.max-e.min));return e.options.reverse?e.max-i:e.min+i}getPointLabelContext(t){const e=this,i=e._pointLabels||[];if(t>=0&&t<i.length){const n=i[t];return function(t,e,i){return Object.assign(Object.create(t),{label:i,index:e,type:"pointLabel"})}(e.getContext(),t,n)}}getPointPosition(t,e){const i=this,n=i.getIndexAngle(t)-Mt;return{x:Math.cos(n)*e+i.xCenter,y:Math.sin(n)*e+i.yCenter,angle:n}}getPointPositionForValue(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))}getBasePosition(t){return this.getPointPositionForValue(t||0,this.getBaseValue())}getPointLabelPosition(t){const{left:e,top:i,right:n,bottom:o}=this._pointLabelItems[t];return{left:e,top:i,right:n,bottom:o}}drawBackground(){const t=this,{backgroundColor:e,grid:{circular:i}}=t.options;if(e){const n=t.ctx;n.save(),n.beginPath(),Js(t,t.getDistanceFromCenterForValue(t._endValue),i,t.getLabels().length),n.closePath(),n.fillStyle=e,n.fill(),n.restore()}}drawGrid(){const t=this,e=t.ctx,i=t.options,{angleLines:n,grid:o}=i,s=t.getLabels().length;let a,r,l;if(i.pointLabels.display&&function(t,e){const{ctx:i,options:{pointLabels:n}}=t;for(let o=e-1;o>=0;o--){const e=n.setContext(t.getPointLabelContext(o)),s=Ve(e.font),{x:a,y:r,textAlign:l,left:c,top:h,right:d,bottom:u}=t._pointLabelItems[o],{backdropColor:f}=e;if(!$(f)){const t=Be(e.backdropPadding);i.fillStyle=f,i.fillRect(c-t.left,h-t.top,d-c+t.width,u-h+t.height)}ee(i,t._pointLabels[o],a,r+s.lineHeight/2,s,{color:e.color,textAlign:l,textBaseline:"middle"})}}(t,s),o.display&&t.ticks.forEach(((e,i)=>{if(0!==i){r=t.getDistanceFromCenterForValue(e.value);const n=o.setContext(t.getContext(i-1));!function(t,e,i,n){const o=t.ctx,s=e.circular,{color:a,lineWidth:r}=e;!s&&!n||!a||!r||i<0||(o.save(),o.strokeStyle=a,o.lineWidth=r,o.setLineDash(e.borderDash),o.lineDashOffset=e.borderDashOffset,o.beginPath(),Js(t,i,s,n),o.closePath(),o.stroke(),o.restore())}(t,n,r,s)}})),n.display){for(e.save(),a=t.getLabels().length-1;a>=0;a--){const o=n.setContext(t.getPointLabelContext(a)),{color:s,lineWidth:c}=o;c&&s&&(e.lineWidth=c,e.strokeStyle=s,e.setLineDash(o.borderDash),e.lineDashOffset=o.borderDashOffset,r=t.getDistanceFromCenterForValue(i.ticks.reverse?t.min:t.max),l=t.getPointPosition(a,r),e.beginPath(),e.moveTo(t.xCenter,t.yCenter),e.lineTo(l.x,l.y),e.stroke())}e.restore()}}drawBorder(){}drawLabels(){const t=this,e=t.ctx,i=t.options,n=i.ticks;if(!n.display)return;const o=t.getIndexAngle(0);let s,a;e.save(),e.translate(t.xCenter,t.yCenter),e.rotate(o),e.textAlign="center",e.textBaseline="middle",t.ticks.forEach(((o,r)=>{if(0===r&&!i.reverse)return;const l=n.setContext(t.getContext(r)),c=Ve(l.font);if(s=t.getDistanceFromCenterForValue(t.ticks[r].value),l.showLabelBackdrop){e.font=c.string,a=e.measureText(o.label).width,e.fillStyle=l.backdropColor;const t=Be(l.backdropPadding);e.fillRect(-a/2-t.left,-s-c.size/2-t.top,a+t.width,c.size+t.height)}ee(e,o.label,0,-s,c,{color:l.color})})),e.restore()}drawTitle(){}}ea.id="radialLinear",ea.defaults={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,lineWidth:1,borderDash:[],borderDashOffset:0},grid:{circular:!1},startAngle:0,ticks:{showLabelBackdrop:!0,callback:Sn.formatters.numeric},pointLabels:{backdropColor:void 0,backdropPadding:2,display:!0,font:{size:10},callback:t=>t,padding:5}},ea.defaultRoutes={"angleLines.color":"borderColor","pointLabels.color":"color","ticks.color":"color"},ea.descriptors={angleLines:{_fallback:"grid"}};const ia={millisecond:{common:!0,size:1,steps:1e3},second:{common:!0,size:1e3,steps:60},minute:{common:!0,size:6e4,steps:60},hour:{common:!0,size:36e5,steps:24},day:{common:!0,size:864e5,steps:30},week:{common:!1,size:6048e5,steps:4},month:{common:!0,size:2628e6,steps:12},quarter:{common:!1,size:7884e6,steps:4},year:{common:!0,size:3154e7}},na=Object.keys(ia);function oa(t,e){return t-e}function sa(t,e){if($(e))return null;const i=t._adapter,{parser:n,round:o,isoWeekday:s}=t._parseOpts;let a=e;return"function"==typeof n&&(a=n(a)),X(a)||(a="string"==typeof n?i.parse(a,n):i.parse(a)),null===a?null:(o&&(a="week"!==o||!Tt(s)&&!0!==s?i.startOf(a,o):i.startOf(a,"isoWeek",s)),+a)}function aa(t,e,i,n){const o=na.length;for(let s=na.indexOf(t);s<o-1;++s){const t=ia[na[s]],o=t.steps?t.steps:Number.MAX_SAFE_INTEGER;if(t.common&&Math.ceil((i-e)/(o*t.size))<=n)return na[s]}return na[o-1]}function ra(t,e,i){if(i){if(i.length){const{lo:n,hi:o}=oe(i,e);t[i[n]>=e?i[n]:i[o]]=!0}}else t[e]=!0}function la(t,e,i){const n=[],o={},s=e.length;let a,r;for(a=0;a<s;++a)r=e[a],o[r]=a,n.push({value:r,major:!1});return 0!==s&&i?function(t,e,i,n){const o=t._adapter,s=+o.startOf(e[0].value,n),a=e[e.length-1].value;let r,l;for(r=s;r<=a;r=+o.add(r,1,n))l=i[r],l>=0&&(e[l].major=!0);return e}(t,n,o,i):n}class ca extends En{constructor(t){super(t),this._cache={data:[],labels:[],all:[]},this._unit="day",this._majorUnit=void 0,this._offsets={},this._normalized=!1,this._parseOpts=void 0}init(t,e){const i=t.time||(t.time={}),n=this._adapter=new co._date(t.adapters.date);st(i.displayFormats,n.formats()),this._parseOpts={parser:i.parser,round:i.round,isoWeekday:i.isoWeekday},super.init(t),this._normalized=e.normalized}parse(t,e){return void 0===t?null:sa(this,t)}beforeLayout(){super.beforeLayout(),this._cache={data:[],labels:[],all:[]}}determineDataLimits(){const t=this,e=t.options,i=t._adapter,n=e.time.unit||"day";let{min:o,max:s,minDefined:a,maxDefined:r}=t.getUserBounds();function l(t){a||isNaN(t.min)||(o=Math.min(o,t.min)),r||isNaN(t.max)||(s=Math.max(s,t.max))}a&&r||(l(t._getLabelBounds()),"ticks"===e.bounds&&"labels"===e.ticks.source||l(t.getMinMax(!1))),o=X(o)&&!isNaN(o)?o:+i.startOf(Date.now(),n),s=X(s)&&!isNaN(s)?s:+i.endOf(Date.now(),n)+1,t.min=Math.min(o,s-1),t.max=Math.max(o+1,s)}_getLabelBounds(){const t=this.getLabelTimestamps();let e=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;return t.length&&(e=t[0],i=t[t.length-1]),{min:e,max:i}}buildTicks(){const t=this,e=t.options,i=e.time,n=e.ticks,o="labels"===n.source?t.getLabelTimestamps():t._generate();"ticks"===e.bounds&&o.length&&(t.min=t._userMin||o[0],t.max=t._userMax||o[o.length-1]);const s=t.min,a=re(o,s,t.max);return t._unit=i.unit||(n.autoSkip?aa(i.minUnit,t.min,t.max,t._getLabelCapacity(s)):function(t,e,i,n,o){for(let s=na.length-1;s>=na.indexOf(i);s--){const i=na[s];if(ia[i].common&&t._adapter.diff(o,n,i)>=e-1)return i}return na[i?na.indexOf(i):0]}(t,a.length,i.minUnit,t.min,t.max)),t._majorUnit=n.major.enabled&&"year"!==t._unit?function(t){for(let e=na.indexOf(t)+1,i=na.length;e<i;++e)if(ia[na[e]].common)return na[e]}(t._unit):void 0,t.initOffsets(o),e.reverse&&a.reverse(),la(t,a,t._majorUnit)}initOffsets(t){const e=this;let i,n,o=0,s=0;e.options.offset&&t.length&&(i=e.getDecimalForValue(t[0]),o=1===t.length?1-i:(e.getDecimalForValue(t[1])-i)/2,n=e.getDecimalForValue(t[t.length-1]),s=1===t.length?n:(n-e.getDecimalForValue(t[t.length-2]))/2);const a=t.length<3?.5:.25;o=Ht(o,0,a),s=Ht(s,0,a),e._offsets={start:o,end:s,factor:1/(o+1+s)}}_generate(){const t=this,e=t._adapter,i=t.min,n=t.max,o=t.options,s=o.time,a=s.unit||aa(s.minUnit,i,n,t._getLabelCapacity(i)),r=K(s.stepSize,1),l="week"===a&&s.isoWeekday,c=Tt(l)||!0===l,h={};let d,u,f=i;if(c&&(f=+e.startOf(f,"isoWeek",l)),f=+e.startOf(f,c?"day":a),e.diff(n,i,a)>1e5*r)throw new Error(i+" and "+n+" are too far apart with stepSize of "+r+" "+a);const g="data"===o.ticks.source&&t.getDataTimestamps();for(d=f,u=0;d<n;d=+e.add(d,r,a),u++)ra(h,d,g);return d!==n&&"ticks"!==o.bounds&&1!==u||ra(h,d,g),Object.keys(h).sort(((t,e)=>t-e)).map((t=>+t))}getLabelForValue(t){const e=this._adapter,i=this.options.time;return i.tooltipFormat?e.format(t,i.tooltipFormat):e.format(t,i.displayFormats.datetime)}_tickFormatFunction(t,e,i,n){const o=this,s=o.options,a=s.time.displayFormats,r=o._unit,l=o._majorUnit,c=r&&a[r],h=l&&a[l],d=i[e],u=l&&h&&d&&d.major,f=o._adapter.format(t,n||(u?h:c)),g=s.ticks.callback;return g?Q(g,[f,e,i],o):f}generateTickLabels(t){let e,i,n;for(e=0,i=t.length;e<i;++e)n=t[e],n.label=this._tickFormatFunction(n.value,e,t)}getDecimalForValue(t){const e=this;return null===t?NaN:(t-e.min)/(e.max-e.min)}getPixelForValue(t){const e=this,i=e._offsets,n=e.getDecimalForValue(t);return e.getPixelForDecimal((i.start+n)*i.factor)}getValueForPixel(t){const e=this,i=e._offsets,n=e.getDecimalForPixel(t)/i.factor-i.end;return e.min+n*(e.max-e.min)}_getLabelSize(t){const e=this,i=e.options.ticks,n=e.ctx.measureText(t).width,o=Et(e.isHorizontal()?i.maxRotation:i.minRotation),s=Math.cos(o),a=Math.sin(o),r=e._resolveTickFontOptions(0).size;return{w:n*s+r*a,h:n*a+r*s}}_getLabelCapacity(t){const e=this,i=e.options.time,n=i.displayFormats,o=n[i.unit]||n.millisecond,s=e._tickFormatFunction(t,0,la(e,[t],e._majorUnit),o),a=e._getLabelSize(s),r=Math.floor(e.isHorizontal()?e.width/a.w:e.height/a.h)-1;return r>0?r:1}getDataTimestamps(){const t=this;let e,i,n=t._cache.data||[];if(n.length)return n;const o=t.getMatchingVisibleMetas();if(t._normalized&&o.length)return t._cache.data=o[0].controller.getAllParsedValues(t);for(e=0,i=o.length;e<i;++e)n=n.concat(o[e].controller.getAllParsedValues(t));return t._cache.data=t.normalize(n)}getLabelTimestamps(){const t=this,e=t._cache.labels||[];let i,n;if(e.length)return e;const o=t.getLabels();for(i=0,n=o.length;i<n;++i)e.push(sa(t,o[i]));return t._cache.labels=t._normalized?e:t.normalize(e)}normalize(t){return de(t.sort(oa))}}function ha(t,e,i){let n,o,s,a,r=0,l=t.length-1;i?(e>=t[r].pos&&e<=t[l].pos&&({lo:r,hi:l}=se(t,"pos",e)),({pos:n,time:s}=t[r]),({pos:o,time:a}=t[l])):(e>=t[r].time&&e<=t[l].time&&({lo:r,hi:l}=se(t,"time",e)),({time:n,pos:s}=t[r]),({time:o,pos:a}=t[l]));const c=o-n;return c?s+(a-s)*(e-n)/c:s}ca.id="time",ca.defaults={bounds:"data",adapters:{},time:{parser:!1,unit:!1,round:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{}},ticks:{source:"auto",major:{enabled:!1}}};class da extends ca{constructor(t){super(t),this._table=[],this._minPos=void 0,this._tableRange=void 0}initOffsets(){const t=this,e=t._getTimestampsForTable(),i=t._table=t.buildLookupTable(e);t._minPos=ha(i,t.min),t._tableRange=ha(i,t.max)-t._minPos,super.initOffsets(e)}buildLookupTable(t){const{min:e,max:i}=this,n=[],o=[];let s,a,r,l,c;for(s=0,a=t.length;s<a;++s)l=t[s],l>=e&&l<=i&&n.push(l);if(n.length<2)return[{time:e,pos:0},{time:i,pos:1}];for(s=0,a=n.length;s<a;++s)c=n[s+1],r=n[s-1],l=n[s],Math.round((c+r)/2)!==l&&o.push({time:l,pos:s/(a-1)});return o}_getTimestampsForTable(){const t=this;let e=t._cache.all||[];if(e.length)return e;const i=t.getDataTimestamps(),n=t.getLabelTimestamps();return e=i.length&&n.length?t.normalize(i.concat(n)):i.length?i:n,e=t._cache.all=e,e}getDecimalForValue(t){return(ha(this._table,t)-this._minPos)/this._tableRange}getValueForPixel(t){const e=this,i=e._offsets,n=e.getDecimalForPixel(t)/i.factor-i.end;return ha(e._table,n*e._tableRange+e._minPos,!0)}}da.id="timeseries",da.defaults=ca.defaults;var ua=Object.freeze({__proto__:null,CategoryScale:Ns,LinearScale:$s,LogarithmicScale:Us,RadialLinearScale:ea,TimeScale:ca,TimeSeriesScale:da});return oo.register(Po,ua,Zo,Vs),oo.helpers={...Ni},oo._adapters=co,oo.Animation=ln,oo.Animations=hn,oo.animator=a,oo.controllers=zn.controllers.items,oo.DatasetController=wn,oo.Element=Mn,oo.elements=Zo,oo.Interaction=Ae,oo.layouts=ti,oo.platforms=sn,oo.Scale=En,oo.Ticks=Sn,Object.assign(oo,Po,ua,Zo,Vs,sn),oo.Chart=oo,"undefined"!=typeof window&&(window.Chart=oo),oo}));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  /*!
2
+ * Chart.js v3.7.1
3
  * https://www.chartjs.org
4
+ * (c) 2022 Chart.js Contributors
5
  * Released under the MIT License
6
  */
7
+ !(function (t, e) {
8
+ "object" == typeof exports && "undefined" != typeof module
9
+ ? (module.exports = e())
10
+ : "function" == typeof define && define.amd
11
+ ? define(e)
12
+ : ((t = "undefined" != typeof globalThis ? globalThis : t || self).Chart =
13
+ e());
14
+ })(this, function () {
15
+ "use strict";
16
+ const t =
17
+ "undefined" == typeof window
18
+ ? function (t) {
19
+ return t();
20
+ }
21
+ : window.requestAnimationFrame;
22
+ function e(e, i, s) {
23
+ const n = s || ((t) => Array.prototype.slice.call(t));
24
+ let o = !1,
25
+ a = [];
26
+ return function (...s) {
27
+ (a = n(s)),
28
+ o ||
29
+ ((o = !0),
30
+ t.call(window, () => {
31
+ (o = !1), e.apply(i, a);
32
+ }));
33
+ };
34
+ }
35
+ function i(t, e) {
36
+ let i;
37
+ return function (...s) {
38
+ return (
39
+ e ? (clearTimeout(i), (i = setTimeout(t, e, s))) : t.apply(this, s), e
40
+ );
41
+ };
42
+ }
43
+ const s = (t) => ("start" === t ? "left" : "end" === t ? "right" : "center"),
44
+ n = (t, e, i) => ("start" === t ? e : "end" === t ? i : (e + i) / 2),
45
+ o = (t, e, i, s) =>
46
+ t === (s ? "left" : "right") ? i : "center" === t ? (e + i) / 2 : e;
47
+ var a = new (class {
48
+ constructor() {
49
+ (this._request = null),
50
+ (this._charts = new Map()),
51
+ (this._running = !1),
52
+ (this._lastDate = void 0);
53
+ }
54
+ _notify(t, e, i, s) {
55
+ const n = e.listeners[s],
56
+ o = e.duration;
57
+ n.forEach((s) =>
58
+ s({
59
+ chart: t,
60
+ initial: e.initial,
61
+ numSteps: o,
62
+ currentStep: Math.min(i - e.start, o),
63
+ })
64
+ );
65
+ }
66
+ _refresh() {
67
+ this._request ||
68
+ ((this._running = !0),
69
+ (this._request = t.call(window, () => {
70
+ this._update(),
71
+ (this._request = null),
72
+ this._running && this._refresh();
73
+ })));
74
+ }
75
+ _update(t = Date.now()) {
76
+ let e = 0;
77
+ this._charts.forEach((i, s) => {
78
+ if (!i.running || !i.items.length) return;
79
+ const n = i.items;
80
+ let o,
81
+ a = n.length - 1,
82
+ r = !1;
83
+ for (; a >= 0; --a)
84
+ (o = n[a]),
85
+ o._active
86
+ ? (o._total > i.duration && (i.duration = o._total),
87
+ o.tick(t),
88
+ (r = !0))
89
+ : ((n[a] = n[n.length - 1]), n.pop());
90
+ r && (s.draw(), this._notify(s, i, t, "progress")),
91
+ n.length ||
92
+ ((i.running = !1),
93
+ this._notify(s, i, t, "complete"),
94
+ (i.initial = !1)),
95
+ (e += n.length);
96
+ }),
97
+ (this._lastDate = t),
98
+ 0 === e && (this._running = !1);
99
+ }
100
+ _getAnims(t) {
101
+ const e = this._charts;
102
+ let i = e.get(t);
103
+ return (
104
+ i ||
105
+ ((i = {
106
+ running: !1,
107
+ initial: !0,
108
+ items: [],
109
+ listeners: { complete: [], progress: [] },
110
+ }),
111
+ e.set(t, i)),
112
+ i
113
+ );
114
+ }
115
+ listen(t, e, i) {
116
+ this._getAnims(t).listeners[e].push(i);
117
+ }
118
+ add(t, e) {
119
+ e && e.length && this._getAnims(t).items.push(...e);
120
+ }
121
+ has(t) {
122
+ return this._getAnims(t).items.length > 0;
123
+ }
124
+ start(t) {
125
+ const e = this._charts.get(t);
126
+ e &&
127
+ ((e.running = !0),
128
+ (e.start = Date.now()),
129
+ (e.duration = e.items.reduce((t, e) => Math.max(t, e._duration), 0)),
130
+ this._refresh());
131
+ }
132
+ running(t) {
133
+ if (!this._running) return !1;
134
+ const e = this._charts.get(t);
135
+ return !!(e && e.running && e.items.length);
136
+ }
137
+ stop(t) {
138
+ const e = this._charts.get(t);
139
+ if (!e || !e.items.length) return;
140
+ const i = e.items;
141
+ let s = i.length - 1;
142
+ for (; s >= 0; --s) i[s].cancel();
143
+ (e.items = []), this._notify(t, e, Date.now(), "complete");
144
+ }
145
+ remove(t) {
146
+ return this._charts.delete(t);
147
+ }
148
+ })();
149
+ /*!
150
+ * @kurkle/color v0.1.9
151
+ * https://github.com/kurkle/color#readme
152
+ * (c) 2020 Jukka Kurkela
153
+ * Released under the MIT License
154
+ */ const r = {
155
+ 0: 0,
156
+ 1: 1,
157
+ 2: 2,
158
+ 3: 3,
159
+ 4: 4,
160
+ 5: 5,
161
+ 6: 6,
162
+ 7: 7,
163
+ 8: 8,
164
+ 9: 9,
165
+ A: 10,
166
+ B: 11,
167
+ C: 12,
168
+ D: 13,
169
+ E: 14,
170
+ F: 15,
171
+ a: 10,
172
+ b: 11,
173
+ c: 12,
174
+ d: 13,
175
+ e: 14,
176
+ f: 15,
177
+ },
178
+ l = "0123456789ABCDEF",
179
+ h = (t) => l[15 & t],
180
+ c = (t) => l[(240 & t) >> 4] + l[15 & t],
181
+ d = (t) => (240 & t) >> 4 == (15 & t);
182
+ function u(t) {
183
+ var e = (function (t) {
184
+ return d(t.r) && d(t.g) && d(t.b) && d(t.a);
185
+ })(t)
186
+ ? h
187
+ : c;
188
+ return t ? "#" + e(t.r) + e(t.g) + e(t.b) + (t.a < 255 ? e(t.a) : "") : t;
189
+ }
190
+ function f(t) {
191
+ return (t + 0.5) | 0;
192
+ }
193
+ const g = (t, e, i) => Math.max(Math.min(t, i), e);
194
+ function p(t) {
195
+ return g(f(2.55 * t), 0, 255);
196
+ }
197
+ function m(t) {
198
+ return g(f(255 * t), 0, 255);
199
+ }
200
+ function x(t) {
201
+ return g(f(t / 2.55) / 100, 0, 1);
202
+ }
203
+ function b(t) {
204
+ return g(f(100 * t), 0, 100);
205
+ }
206
+ const _ =
207
+ /^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/;
208
+ const y =
209
+ /^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;
210
+ function v(t, e, i) {
211
+ const s = e * Math.min(i, 1 - i),
212
+ n = (e, n = (e + t / 30) % 12) =>
213
+ i - s * Math.max(Math.min(n - 3, 9 - n, 1), -1);
214
+ return [n(0), n(8), n(4)];
215
+ }
216
+ function w(t, e, i) {
217
+ const s = (s, n = (s + t / 60) % 6) =>
218
+ i - i * e * Math.max(Math.min(n, 4 - n, 1), 0);
219
+ return [s(5), s(3), s(1)];
220
+ }
221
+ function M(t, e, i) {
222
+ const s = v(t, 1, 0.5);
223
+ let n;
224
+ for (
225
+ e + i > 1 && ((n = 1 / (e + i)), (e *= n), (i *= n)), n = 0;
226
+ n < 3;
227
+ n++
228
+ )
229
+ (s[n] *= 1 - e - i), (s[n] += e);
230
+ return s;
231
+ }
232
+ function k(t) {
233
+ const e = t.r / 255,
234
+ i = t.g / 255,
235
+ s = t.b / 255,
236
+ n = Math.max(e, i, s),
237
+ o = Math.min(e, i, s),
238
+ a = (n + o) / 2;
239
+ let r, l, h;
240
+ return (
241
+ n !== o &&
242
+ ((h = n - o),
243
+ (l = a > 0.5 ? h / (2 - n - o) : h / (n + o)),
244
+ (r =
245
+ n === e
246
+ ? (i - s) / h + (i < s ? 6 : 0)
247
+ : n === i
248
+ ? (s - e) / h + 2
249
+ : (e - i) / h + 4),
250
+ (r = 60 * r + 0.5)),
251
+ [0 | r, l || 0, a]
252
+ );
253
+ }
254
+ function S(t, e, i, s) {
255
+ return (Array.isArray(e) ? t(e[0], e[1], e[2]) : t(e, i, s)).map(m);
256
+ }
257
+ function P(t, e, i) {
258
+ return S(v, t, e, i);
259
+ }
260
+ function D(t) {
261
+ return ((t % 360) + 360) % 360;
262
+ }
263
+ function C(t) {
264
+ const e = y.exec(t);
265
+ let i,
266
+ s = 255;
267
+ if (!e) return;
268
+ e[5] !== i && (s = e[6] ? p(+e[5]) : m(+e[5]));
269
+ const n = D(+e[2]),
270
+ o = +e[3] / 100,
271
+ a = +e[4] / 100;
272
+ return (
273
+ (i =
274
+ "hwb" === e[1]
275
+ ? (function (t, e, i) {
276
+ return S(M, t, e, i);
277
+ })(n, o, a)
278
+ : "hsv" === e[1]
279
+ ? (function (t, e, i) {
280
+ return S(w, t, e, i);
281
+ })(n, o, a)
282
+ : P(n, o, a)),
283
+ { r: i[0], g: i[1], b: i[2], a: s }
284
+ );
285
+ }
286
+ const O = {
287
+ x: "dark",
288
+ Z: "light",
289
+ Y: "re",
290
+ X: "blu",
291
+ W: "gr",
292
+ V: "medium",
293
+ U: "slate",
294
+ A: "ee",
295
+ T: "ol",
296
+ S: "or",
297
+ B: "ra",
298
+ C: "lateg",
299
+ D: "ights",
300
+ R: "in",
301
+ Q: "turquois",
302
+ E: "hi",
303
+ P: "ro",
304
+ O: "al",
305
+ N: "le",
306
+ M: "de",
307
+ L: "yello",
308
+ F: "en",
309
+ K: "ch",
310
+ G: "arks",
311
+ H: "ea",
312
+ I: "ightg",
313
+ J: "wh",
314
+ },
315
+ A = {
316
+ OiceXe: "f0f8ff",
317
+ antiquewEte: "faebd7",
318
+ aqua: "ffff",
319
+ aquamarRe: "7fffd4",
320
+ azuY: "f0ffff",
321
+ beige: "f5f5dc",
322
+ bisque: "ffe4c4",
323
+ black: "0",
324
+ blanKedOmond: "ffebcd",
325
+ Xe: "ff",
326
+ XeviTet: "8a2be2",
327
+ bPwn: "a52a2a",
328
+ burlywood: "deb887",
329
+ caMtXe: "5f9ea0",
330
+ KartYuse: "7fff00",
331
+ KocTate: "d2691e",
332
+ cSO: "ff7f50",
333
+ cSnflowerXe: "6495ed",
334
+ cSnsilk: "fff8dc",
335
+ crimson: "dc143c",
336
+ cyan: "ffff",
337
+ xXe: "8b",
338
+ xcyan: "8b8b",
339
+ xgTMnPd: "b8860b",
340
+ xWay: "a9a9a9",
341
+ xgYF: "6400",
342
+ xgYy: "a9a9a9",
343
+ xkhaki: "bdb76b",
344
+ xmagFta: "8b008b",
345
+ xTivegYF: "556b2f",
346
+ xSange: "ff8c00",
347
+ xScEd: "9932cc",
348
+ xYd: "8b0000",
349
+ xsOmon: "e9967a",
350
+ xsHgYF: "8fbc8f",
351
+ xUXe: "483d8b",
352
+ xUWay: "2f4f4f",
353
+ xUgYy: "2f4f4f",
354
+ xQe: "ced1",
355
+ xviTet: "9400d3",
356
+ dAppRk: "ff1493",
357
+ dApskyXe: "bfff",
358
+ dimWay: "696969",
359
+ dimgYy: "696969",
360
+ dodgerXe: "1e90ff",
361
+ fiYbrick: "b22222",
362
+ flSOwEte: "fffaf0",
363
+ foYstWAn: "228b22",
364
+ fuKsia: "ff00ff",
365
+ gaRsbSo: "dcdcdc",
366
+ ghostwEte: "f8f8ff",
367
+ gTd: "ffd700",
368
+ gTMnPd: "daa520",
369
+ Way: "808080",
370
+ gYF: "8000",
371
+ gYFLw: "adff2f",
372
+ gYy: "808080",
373
+ honeyMw: "f0fff0",
374
+ hotpRk: "ff69b4",
375
+ RdianYd: "cd5c5c",
376
+ Rdigo: "4b0082",
377
+ ivSy: "fffff0",
378
+ khaki: "f0e68c",
379
+ lavFMr: "e6e6fa",
380
+ lavFMrXsh: "fff0f5",
381
+ lawngYF: "7cfc00",
382
+ NmoncEffon: "fffacd",
383
+ ZXe: "add8e6",
384
+ ZcSO: "f08080",
385
+ Zcyan: "e0ffff",
386
+ ZgTMnPdLw: "fafad2",
387
+ ZWay: "d3d3d3",
388
+ ZgYF: "90ee90",
389
+ ZgYy: "d3d3d3",
390
+ ZpRk: "ffb6c1",
391
+ ZsOmon: "ffa07a",
392
+ ZsHgYF: "20b2aa",
393
+ ZskyXe: "87cefa",
394
+ ZUWay: "778899",
395
+ ZUgYy: "778899",
396
+ ZstAlXe: "b0c4de",
397
+ ZLw: "ffffe0",
398
+ lime: "ff00",
399
+ limegYF: "32cd32",
400
+ lRF: "faf0e6",
401
+ magFta: "ff00ff",
402
+ maPon: "800000",
403
+ VaquamarRe: "66cdaa",
404
+ VXe: "cd",
405
+ VScEd: "ba55d3",
406
+ VpurpN: "9370db",
407
+ VsHgYF: "3cb371",
408
+ VUXe: "7b68ee",
409
+ VsprRggYF: "fa9a",
410
+ VQe: "48d1cc",
411
+ VviTetYd: "c71585",
412
+ midnightXe: "191970",
413
+ mRtcYam: "f5fffa",
414
+ mistyPse: "ffe4e1",
415
+ moccasR: "ffe4b5",
416
+ navajowEte: "ffdead",
417
+ navy: "80",
418
+ Tdlace: "fdf5e6",
419
+ Tive: "808000",
420
+ TivedBb: "6b8e23",
421
+ Sange: "ffa500",
422
+ SangeYd: "ff4500",
423
+ ScEd: "da70d6",
424
+ pOegTMnPd: "eee8aa",
425
+ pOegYF: "98fb98",
426
+ pOeQe: "afeeee",
427
+ pOeviTetYd: "db7093",
428
+ papayawEp: "ffefd5",
429
+ pHKpuff: "ffdab9",
430
+ peru: "cd853f",
431
+ pRk: "ffc0cb",
432
+ plum: "dda0dd",
433
+ powMrXe: "b0e0e6",
434
+ purpN: "800080",
435
+ YbeccapurpN: "663399",
436
+ Yd: "ff0000",
437
+ Psybrown: "bc8f8f",
438
+ PyOXe: "4169e1",
439
+ saddNbPwn: "8b4513",
440
+ sOmon: "fa8072",
441
+ sandybPwn: "f4a460",
442
+ sHgYF: "2e8b57",
443
+ sHshell: "fff5ee",
444
+ siFna: "a0522d",
445
+ silver: "c0c0c0",
446
+ skyXe: "87ceeb",
447
+ UXe: "6a5acd",
448
+ UWay: "708090",
449
+ UgYy: "708090",
450
+ snow: "fffafa",
451
+ sprRggYF: "ff7f",
452
+ stAlXe: "4682b4",
453
+ tan: "d2b48c",
454
+ teO: "8080",
455
+ tEstN: "d8bfd8",
456
+ tomato: "ff6347",
457
+ Qe: "40e0d0",
458
+ viTet: "ee82ee",
459
+ JHt: "f5deb3",
460
+ wEte: "ffffff",
461
+ wEtesmoke: "f5f5f5",
462
+ Lw: "ffff00",
463
+ LwgYF: "9acd32",
464
+ };
465
+ let T;
466
+ function L(t) {
467
+ T ||
468
+ ((T = (function () {
469
+ const t = {},
470
+ e = Object.keys(A),
471
+ i = Object.keys(O);
472
+ let s, n, o, a, r;
473
+ for (s = 0; s < e.length; s++) {
474
+ for (a = r = e[s], n = 0; n < i.length; n++)
475
+ (o = i[n]), (r = r.replace(o, O[o]));
476
+ (o = parseInt(A[a], 16)),
477
+ (t[r] = [(o >> 16) & 255, (o >> 8) & 255, 255 & o]);
478
+ }
479
+ return t;
480
+ })()),
481
+ (T.transparent = [0, 0, 0, 0]));
482
+ const e = T[t.toLowerCase()];
483
+ return e && { r: e[0], g: e[1], b: e[2], a: 4 === e.length ? e[3] : 255 };
484
+ }
485
+ function R(t, e, i) {
486
+ if (t) {
487
+ let s = k(t);
488
+ (s[e] = Math.max(0, Math.min(s[e] + s[e] * i, 0 === e ? 360 : 1))),
489
+ (s = P(s)),
490
+ (t.r = s[0]),
491
+ (t.g = s[1]),
492
+ (t.b = s[2]);
493
+ }
494
+ }
495
+ function E(t, e) {
496
+ return t ? Object.assign(e || {}, t) : t;
497
+ }
498
+ function I(t) {
499
+ var e = { r: 0, g: 0, b: 0, a: 255 };
500
+ return (
501
+ Array.isArray(t)
502
+ ? t.length >= 3 &&
503
+ ((e = { r: t[0], g: t[1], b: t[2], a: 255 }),
504
+ t.length > 3 && (e.a = m(t[3])))
505
+ : ((e = E(t, { r: 0, g: 0, b: 0, a: 1 })).a = m(e.a)),
506
+ e
507
+ );
508
+ }
509
+ function z(t) {
510
+ return "r" === t.charAt(0)
511
+ ? (function (t) {
512
+ const e = _.exec(t);
513
+ let i,
514
+ s,
515
+ n,
516
+ o = 255;
517
+ if (e) {
518
+ if (e[7] !== i) {
519
+ const t = +e[7];
520
+ o = 255 & (e[8] ? p(t) : 255 * t);
521
+ }
522
+ return (
523
+ (i = +e[1]),
524
+ (s = +e[3]),
525
+ (n = +e[5]),
526
+ (i = 255 & (e[2] ? p(i) : i)),
527
+ (s = 255 & (e[4] ? p(s) : s)),
528
+ (n = 255 & (e[6] ? p(n) : n)),
529
+ { r: i, g: s, b: n, a: o }
530
+ );
531
+ }
532
+ })(t)
533
+ : C(t);
534
+ }
535
+ class F {
536
+ constructor(t) {
537
+ if (t instanceof F) return t;
538
+ const e = typeof t;
539
+ let i;
540
+ var s, n, o;
541
+ "object" === e
542
+ ? (i = I(t))
543
+ : "string" === e &&
544
+ ((o = (s = t).length),
545
+ "#" === s[0] &&
546
+ (4 === o || 5 === o
547
+ ? (n = {
548
+ r: 255 & (17 * r[s[1]]),
549
+ g: 255 & (17 * r[s[2]]),
550
+ b: 255 & (17 * r[s[3]]),
551
+ a: 5 === o ? 17 * r[s[4]] : 255,
552
+ })
553
+ : (7 !== o && 9 !== o) ||
554
+ (n = {
555
+ r: (r[s[1]] << 4) | r[s[2]],
556
+ g: (r[s[3]] << 4) | r[s[4]],
557
+ b: (r[s[5]] << 4) | r[s[6]],
558
+ a: 9 === o ? (r[s[7]] << 4) | r[s[8]] : 255,
559
+ })),
560
+ (i = n || L(t) || z(t))),
561
+ (this._rgb = i),
562
+ (this._valid = !!i);
563
+ }
564
+ get valid() {
565
+ return this._valid;
566
+ }
567
+ get rgb() {
568
+ var t = E(this._rgb);
569
+ return t && (t.a = x(t.a)), t;
570
+ }
571
+ set rgb(t) {
572
+ this._rgb = I(t);
573
+ }
574
+ rgbString() {
575
+ return this._valid
576
+ ? (t = this._rgb) &&
577
+ (t.a < 255
578
+ ? `rgba(${t.r}, ${t.g}, ${t.b}, ${x(t.a)})`
579
+ : `rgb(${t.r}, ${t.g}, ${t.b})`)
580
+ : this._rgb;
581
+ var t;
582
+ }
583
+ hexString() {
584
+ return this._valid ? u(this._rgb) : this._rgb;
585
+ }
586
+ hslString() {
587
+ return this._valid
588
+ ? (function (t) {
589
+ if (!t) return;
590
+ const e = k(t),
591
+ i = e[0],
592
+ s = b(e[1]),
593
+ n = b(e[2]);
594
+ return t.a < 255
595
+ ? `hsla(${i}, ${s}%, ${n}%, ${x(t.a)})`
596
+ : `hsl(${i}, ${s}%, ${n}%)`;
597
+ })(this._rgb)
598
+ : this._rgb;
599
+ }
600
+ mix(t, e) {
601
+ const i = this;
602
+ if (t) {
603
+ const s = i.rgb,
604
+ n = t.rgb;
605
+ let o;
606
+ const a = e === o ? 0.5 : e,
607
+ r = 2 * a - 1,
608
+ l = s.a - n.a,
609
+ h = ((r * l == -1 ? r : (r + l) / (1 + r * l)) + 1) / 2;
610
+ (o = 1 - h),
611
+ (s.r = 255 & (h * s.r + o * n.r + 0.5)),
612
+ (s.g = 255 & (h * s.g + o * n.g + 0.5)),
613
+ (s.b = 255 & (h * s.b + o * n.b + 0.5)),
614
+ (s.a = a * s.a + (1 - a) * n.a),
615
+ (i.rgb = s);
616
+ }
617
+ return i;
618
+ }
619
+ clone() {
620
+ return new F(this.rgb);
621
+ }
622
+ alpha(t) {
623
+ return (this._rgb.a = m(t)), this;
624
+ }
625
+ clearer(t) {
626
+ return (this._rgb.a *= 1 - t), this;
627
+ }
628
+ greyscale() {
629
+ const t = this._rgb,
630
+ e = f(0.3 * t.r + 0.59 * t.g + 0.11 * t.b);
631
+ return (t.r = t.g = t.b = e), this;
632
+ }
633
+ opaquer(t) {
634
+ return (this._rgb.a *= 1 + t), this;
635
+ }
636
+ negate() {
637
+ const t = this._rgb;
638
+ return (t.r = 255 - t.r), (t.g = 255 - t.g), (t.b = 255 - t.b), this;
639
+ }
640
+ lighten(t) {
641
+ return R(this._rgb, 2, t), this;
642
+ }
643
+ darken(t) {
644
+ return R(this._rgb, 2, -t), this;
645
+ }
646
+ saturate(t) {
647
+ return R(this._rgb, 1, t), this;
648
+ }
649
+ desaturate(t) {
650
+ return R(this._rgb, 1, -t), this;
651
+ }
652
+ rotate(t) {
653
+ return (
654
+ (function (t, e) {
655
+ var i = k(t);
656
+ (i[0] = D(i[0] + e)),
657
+ (i = P(i)),
658
+ (t.r = i[0]),
659
+ (t.g = i[1]),
660
+ (t.b = i[2]);
661
+ })(this._rgb, t),
662
+ this
663
+ );
664
+ }
665
+ }
666
+ function B(t) {
667
+ return new F(t);
668
+ }
669
+ const V = (t) => t instanceof CanvasGradient || t instanceof CanvasPattern;
670
+ function W(t) {
671
+ return V(t) ? t : B(t);
672
+ }
673
+ function N(t) {
674
+ return V(t) ? t : B(t).saturate(0.5).darken(0.1).hexString();
675
+ }
676
+ function H() {}
677
+ const j = (function () {
678
+ let t = 0;
679
+ return function () {
680
+ return t++;
681
+ };
682
+ })();
683
+ function $(t) {
684
+ return null == t;
685
+ }
686
+ function Y(t) {
687
+ if (Array.isArray && Array.isArray(t)) return !0;
688
+ const e = Object.prototype.toString.call(t);
689
+ return "[object" === e.substr(0, 7) && "Array]" === e.substr(-6);
690
+ }
691
+ function U(t) {
692
+ return (
693
+ null !== t && "[object Object]" === Object.prototype.toString.call(t)
694
+ );
695
+ }
696
+ const X = (t) =>
697
+ ("number" == typeof t || t instanceof Number) && isFinite(+t);
698
+ function q(t, e) {
699
+ return X(t) ? t : e;
700
+ }
701
+ function K(t, e) {
702
+ return void 0 === t ? e : t;
703
+ }
704
+ const G = (t, e) =>
705
+ "string" == typeof t && t.endsWith("%") ? parseFloat(t) / 100 : t / e,
706
+ Z = (t, e) =>
707
+ "string" == typeof t && t.endsWith("%") ? (parseFloat(t) / 100) * e : +t;
708
+ function J(t, e, i) {
709
+ if (t && "function" == typeof t.call) return t.apply(i, e);
710
+ }
711
+ function Q(t, e, i, s) {
712
+ let n, o, a;
713
+ if (Y(t))
714
+ if (((o = t.length), s)) for (n = o - 1; n >= 0; n--) e.call(i, t[n], n);
715
+ else for (n = 0; n < o; n++) e.call(i, t[n], n);
716
+ else if (U(t))
717
+ for (a = Object.keys(t), o = a.length, n = 0; n < o; n++)
718
+ e.call(i, t[a[n]], a[n]);
719
+ }
720
+ function tt(t, e) {
721
+ let i, s, n, o;
722
+ if (!t || !e || t.length !== e.length) return !1;
723
+ for (i = 0, s = t.length; i < s; ++i)
724
+ if (
725
+ ((n = t[i]),
726
+ (o = e[i]),
727
+ n.datasetIndex !== o.datasetIndex || n.index !== o.index)
728
+ )
729
+ return !1;
730
+ return !0;
731
+ }
732
+ function et(t) {
733
+ if (Y(t)) return t.map(et);
734
+ if (U(t)) {
735
+ const e = Object.create(null),
736
+ i = Object.keys(t),
737
+ s = i.length;
738
+ let n = 0;
739
+ for (; n < s; ++n) e[i[n]] = et(t[i[n]]);
740
+ return e;
741
+ }
742
+ return t;
743
+ }
744
+ function it(t) {
745
+ return -1 === ["__proto__", "prototype", "constructor"].indexOf(t);
746
+ }
747
+ function st(t, e, i, s) {
748
+ if (!it(t)) return;
749
+ const n = e[t],
750
+ o = i[t];
751
+ U(n) && U(o) ? nt(n, o, s) : (e[t] = et(o));
752
+ }
753
+ function nt(t, e, i) {
754
+ const s = Y(e) ? e : [e],
755
+ n = s.length;
756
+ if (!U(t)) return t;
757
+ const o = (i = i || {}).merger || st;
758
+ for (let a = 0; a < n; ++a) {
759
+ if (!U((e = s[a]))) continue;
760
+ const n = Object.keys(e);
761
+ for (let s = 0, a = n.length; s < a; ++s) o(n[s], t, e, i);
762
+ }
763
+ return t;
764
+ }
765
+ function ot(t, e) {
766
+ return nt(t, e, { merger: at });
767
+ }
768
+ function at(t, e, i) {
769
+ if (!it(t)) return;
770
+ const s = e[t],
771
+ n = i[t];
772
+ U(s) && U(n)
773
+ ? ot(s, n)
774
+ : Object.prototype.hasOwnProperty.call(e, t) || (e[t] = et(n));
775
+ }
776
+ function rt(t, e) {
777
+ const i = t.indexOf(".", e);
778
+ return -1 === i ? t.length : i;
779
+ }
780
+ function lt(t, e) {
781
+ if ("" === e) return t;
782
+ let i = 0,
783
+ s = rt(e, i);
784
+ for (; t && s > i; )
785
+ (t = t[e.substr(i, s - i)]), (i = s + 1), (s = rt(e, i));
786
+ return t;
787
+ }
788
+ function ht(t) {
789
+ return t.charAt(0).toUpperCase() + t.slice(1);
790
+ }
791
+ const ct = (t) => void 0 !== t,
792
+ dt = (t) => "function" == typeof t,
793
+ ut = (t, e) => {
794
+ if (t.size !== e.size) return !1;
795
+ for (const i of t) if (!e.has(i)) return !1;
796
+ return !0;
797
+ };
798
+ function ft(t) {
799
+ return (
800
+ "mouseup" === t.type || "click" === t.type || "contextmenu" === t.type
801
+ );
802
+ }
803
+ const gt = Object.create(null),
804
+ pt = Object.create(null);
805
+ function mt(t, e) {
806
+ if (!e) return t;
807
+ const i = e.split(".");
808
+ for (let e = 0, s = i.length; e < s; ++e) {
809
+ const s = i[e];
810
+ t = t[s] || (t[s] = Object.create(null));
811
+ }
812
+ return t;
813
+ }
814
+ function xt(t, e, i) {
815
+ return "string" == typeof e ? nt(mt(t, e), i) : nt(mt(t, ""), e);
816
+ }
817
+ var bt = new (class {
818
+ constructor(t) {
819
+ (this.animation = void 0),
820
+ (this.backgroundColor = "rgba(0,0,0,0.1)"),
821
+ (this.borderColor = "rgba(0,0,0,0.1)"),
822
+ (this.color = "#666"),
823
+ (this.datasets = {}),
824
+ (this.devicePixelRatio = (t) => t.chart.platform.getDevicePixelRatio()),
825
+ (this.elements = {}),
826
+ (this.events = [
827
+ "mousemove",
828
+ "mouseout",
829
+ "click",
830
+ "touchstart",
831
+ "touchmove",
832
+ ]),
833
+ (this.font = {
834
+ family: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
835
+ size: 12,
836
+ style: "normal",
837
+ lineHeight: 1.2,
838
+ weight: null,
839
+ }),
840
+ (this.hover = {}),
841
+ (this.hoverBackgroundColor = (t, e) => N(e.backgroundColor)),
842
+ (this.hoverBorderColor = (t, e) => N(e.borderColor)),
843
+ (this.hoverColor = (t, e) => N(e.color)),
844
+ (this.indexAxis = "x"),
845
+ (this.interaction = { mode: "nearest", intersect: !0 }),
846
+ (this.maintainAspectRatio = !0),
847
+ (this.onHover = null),
848
+ (this.onClick = null),
849
+ (this.parsing = !0),
850
+ (this.plugins = {}),
851
+ (this.responsive = !0),
852
+ (this.scale = void 0),
853
+ (this.scales = {}),
854
+ (this.showLine = !0),
855
+ (this.drawActiveElementsOnTop = !0),
856
+ this.describe(t);
857
+ }
858
+ set(t, e) {
859
+ return xt(this, t, e);
860
+ }
861
+ get(t) {
862
+ return mt(this, t);
863
+ }
864
+ describe(t, e) {
865
+ return xt(pt, t, e);
866
+ }
867
+ override(t, e) {
868
+ return xt(gt, t, e);
869
+ }
870
+ route(t, e, i, s) {
871
+ const n = mt(this, t),
872
+ o = mt(this, i),
873
+ a = "_" + e;
874
+ Object.defineProperties(n, {
875
+ [a]: { value: n[e], writable: !0 },
876
+ [e]: {
877
+ enumerable: !0,
878
+ get() {
879
+ const t = this[a],
880
+ e = o[s];
881
+ return U(t) ? Object.assign({}, e, t) : K(t, e);
882
+ },
883
+ set(t) {
884
+ this[a] = t;
885
+ },
886
+ },
887
+ });
888
+ }
889
+ })({
890
+ _scriptable: (t) => !t.startsWith("on"),
891
+ _indexable: (t) => "events" !== t,
892
+ hover: { _fallback: "interaction" },
893
+ interaction: { _scriptable: !1, _indexable: !1 },
894
+ });
895
+ const _t = Math.PI,
896
+ yt = 2 * _t,
897
+ vt = yt + _t,
898
+ wt = Number.POSITIVE_INFINITY,
899
+ Mt = _t / 180,
900
+ kt = _t / 2,
901
+ St = _t / 4,
902
+ Pt = (2 * _t) / 3,
903
+ Dt = Math.log10,
904
+ Ct = Math.sign;
905
+ function Ot(t) {
906
+ const e = Math.round(t);
907
+ t = Lt(t, e, t / 1e3) ? e : t;
908
+ const i = Math.pow(10, Math.floor(Dt(t))),
909
+ s = t / i;
910
+ return (s <= 1 ? 1 : s <= 2 ? 2 : s <= 5 ? 5 : 10) * i;
911
+ }
912
+ function At(t) {
913
+ const e = [],
914
+ i = Math.sqrt(t);
915
+ let s;
916
+ for (s = 1; s < i; s++) t % s == 0 && (e.push(s), e.push(t / s));
917
+ return i === (0 | i) && e.push(i), e.sort((t, e) => t - e).pop(), e;
918
+ }
919
+ function Tt(t) {
920
+ return !isNaN(parseFloat(t)) && isFinite(t);
921
+ }
922
+ function Lt(t, e, i) {
923
+ return Math.abs(t - e) < i;
924
+ }
925
+ function Rt(t, e) {
926
+ const i = Math.round(t);
927
+ return i - e <= t && i + e >= t;
928
+ }
929
+ function Et(t, e, i) {
930
+ let s, n, o;
931
+ for (s = 0, n = t.length; s < n; s++)
932
+ (o = t[s][i]),
933
+ isNaN(o) ||
934
+ ((e.min = Math.min(e.min, o)), (e.max = Math.max(e.max, o)));
935
+ }
936
+ function It(t) {
937
+ return t * (_t / 180);
938
+ }
939
+ function zt(t) {
940
+ return t * (180 / _t);
941
+ }
942
+ function Ft(t) {
943
+ if (!X(t)) return;
944
+ let e = 1,
945
+ i = 0;
946
+ for (; Math.round(t * e) / e !== t; ) (e *= 10), i++;
947
+ return i;
948
+ }
949
+ function Bt(t, e) {
950
+ const i = e.x - t.x,
951
+ s = e.y - t.y,
952
+ n = Math.sqrt(i * i + s * s);
953
+ let o = Math.atan2(s, i);
954
+ return o < -0.5 * _t && (o += yt), { angle: o, distance: n };
955
+ }
956
+ function Vt(t, e) {
957
+ return Math.sqrt(Math.pow(e.x - t.x, 2) + Math.pow(e.y - t.y, 2));
958
+ }
959
+ function Wt(t, e) {
960
+ return ((t - e + vt) % yt) - _t;
961
+ }
962
+ function Nt(t) {
963
+ return ((t % yt) + yt) % yt;
964
+ }
965
+ function Ht(t, e, i, s) {
966
+ const n = Nt(t),
967
+ o = Nt(e),
968
+ a = Nt(i),
969
+ r = Nt(o - n),
970
+ l = Nt(a - n),
971
+ h = Nt(n - o),
972
+ c = Nt(n - a);
973
+ return n === o || n === a || (s && o === a) || (r > l && h < c);
974
+ }
975
+ function jt(t, e, i) {
976
+ return Math.max(e, Math.min(i, t));
977
+ }
978
+ function $t(t) {
979
+ return jt(t, -32768, 32767);
980
+ }
981
+ function Yt(t, e, i, s = 1e-6) {
982
+ return t >= Math.min(e, i) - s && t <= Math.max(e, i) + s;
983
+ }
984
+ function Ut(t) {
985
+ return !t || $(t.size) || $(t.family)
986
+ ? null
987
+ : (t.style ? t.style + " " : "") +
988
+ (t.weight ? t.weight + " " : "") +
989
+ t.size +
990
+ "px " +
991
+ t.family;
992
+ }
993
+ function Xt(t, e, i, s, n) {
994
+ let o = e[n];
995
+ return (
996
+ o || ((o = e[n] = t.measureText(n).width), i.push(n)), o > s && (s = o), s
997
+ );
998
+ }
999
+ function qt(t, e, i, s) {
1000
+ let n = ((s = s || {}).data = s.data || {}),
1001
+ o = (s.garbageCollect = s.garbageCollect || []);
1002
+ s.font !== e &&
1003
+ ((n = s.data = {}), (o = s.garbageCollect = []), (s.font = e)),
1004
+ t.save(),
1005
+ (t.font = e);
1006
+ let a = 0;
1007
+ const r = i.length;
1008
+ let l, h, c, d, u;
1009
+ for (l = 0; l < r; l++)
1010
+ if (((d = i[l]), null != d && !0 !== Y(d))) a = Xt(t, n, o, a, d);
1011
+ else if (Y(d))
1012
+ for (h = 0, c = d.length; h < c; h++)
1013
+ (u = d[h]), null == u || Y(u) || (a = Xt(t, n, o, a, u));
1014
+ t.restore();
1015
+ const f = o.length / 2;
1016
+ if (f > i.length) {
1017
+ for (l = 0; l < f; l++) delete n[o[l]];
1018
+ o.splice(0, f);
1019
+ }
1020
+ return a;
1021
+ }
1022
+ function Kt(t, e, i) {
1023
+ const s = t.currentDevicePixelRatio,
1024
+ n = 0 !== i ? Math.max(i / 2, 0.5) : 0;
1025
+ return Math.round((e - n) * s) / s + n;
1026
+ }
1027
+ function Gt(t, e) {
1028
+ (e = e || t.getContext("2d")).save(),
1029
+ e.resetTransform(),
1030
+ e.clearRect(0, 0, t.width, t.height),
1031
+ e.restore();
1032
+ }
1033
+ function Zt(t, e, i, s) {
1034
+ let n, o, a, r, l;
1035
+ const h = e.pointStyle,
1036
+ c = e.rotation,
1037
+ d = e.radius;
1038
+ let u = (c || 0) * Mt;
1039
+ if (
1040
+ h &&
1041
+ "object" == typeof h &&
1042
+ ((n = h.toString()),
1043
+ "[object HTMLImageElement]" === n || "[object HTMLCanvasElement]" === n)
1044
+ )
1045
+ return (
1046
+ t.save(),
1047
+ t.translate(i, s),
1048
+ t.rotate(u),
1049
+ t.drawImage(h, -h.width / 2, -h.height / 2, h.width, h.height),
1050
+ void t.restore()
1051
+ );
1052
+ if (!(isNaN(d) || d <= 0)) {
1053
+ switch ((t.beginPath(), h)) {
1054
+ default:
1055
+ t.arc(i, s, d, 0, yt), t.closePath();
1056
+ break;
1057
+ case "triangle":
1058
+ t.moveTo(i + Math.sin(u) * d, s - Math.cos(u) * d),
1059
+ (u += Pt),
1060
+ t.lineTo(i + Math.sin(u) * d, s - Math.cos(u) * d),
1061
+ (u += Pt),
1062
+ t.lineTo(i + Math.sin(u) * d, s - Math.cos(u) * d),
1063
+ t.closePath();
1064
+ break;
1065
+ case "rectRounded":
1066
+ (l = 0.516 * d),
1067
+ (r = d - l),
1068
+ (o = Math.cos(u + St) * r),
1069
+ (a = Math.sin(u + St) * r),
1070
+ t.arc(i - o, s - a, l, u - _t, u - kt),
1071
+ t.arc(i + a, s - o, l, u - kt, u),
1072
+ t.arc(i + o, s + a, l, u, u + kt),
1073
+ t.arc(i - a, s + o, l, u + kt, u + _t),
1074
+ t.closePath();
1075
+ break;
1076
+ case "rect":
1077
+ if (!c) {
1078
+ (r = Math.SQRT1_2 * d), t.rect(i - r, s - r, 2 * r, 2 * r);
1079
+ break;
1080
+ }
1081
+ u += St;
1082
+ case "rectRot":
1083
+ (o = Math.cos(u) * d),
1084
+ (a = Math.sin(u) * d),
1085
+ t.moveTo(i - o, s - a),
1086
+ t.lineTo(i + a, s - o),
1087
+ t.lineTo(i + o, s + a),
1088
+ t.lineTo(i - a, s + o),
1089
+ t.closePath();
1090
+ break;
1091
+ case "crossRot":
1092
+ u += St;
1093
+ case "cross":
1094
+ (o = Math.cos(u) * d),
1095
+ (a = Math.sin(u) * d),
1096
+ t.moveTo(i - o, s - a),
1097
+ t.lineTo(i + o, s + a),
1098
+ t.moveTo(i + a, s - o),
1099
+ t.lineTo(i - a, s + o);
1100
+ break;
1101
+ case "star":
1102
+ (o = Math.cos(u) * d),
1103
+ (a = Math.sin(u) * d),
1104
+ t.moveTo(i - o, s - a),
1105
+ t.lineTo(i + o, s + a),
1106
+ t.moveTo(i + a, s - o),
1107
+ t.lineTo(i - a, s + o),
1108
+ (u += St),
1109
+ (o = Math.cos(u) * d),
1110
+ (a = Math.sin(u) * d),
1111
+ t.moveTo(i - o, s - a),
1112
+ t.lineTo(i + o, s + a),
1113
+ t.moveTo(i + a, s - o),
1114
+ t.lineTo(i - a, s + o);
1115
+ break;
1116
+ case "line":
1117
+ (o = Math.cos(u) * d),
1118
+ (a = Math.sin(u) * d),
1119
+ t.moveTo(i - o, s - a),
1120
+ t.lineTo(i + o, s + a);
1121
+ break;
1122
+ case "dash":
1123
+ t.moveTo(i, s), t.lineTo(i + Math.cos(u) * d, s + Math.sin(u) * d);
1124
+ }
1125
+ t.fill(), e.borderWidth > 0 && t.stroke();
1126
+ }
1127
+ }
1128
+ function Jt(t, e, i) {
1129
+ return (
1130
+ (i = i || 0.5),
1131
+ !e ||
1132
+ (t &&
1133
+ t.x > e.left - i &&
1134
+ t.x < e.right + i &&
1135
+ t.y > e.top - i &&
1136
+ t.y < e.bottom + i)
1137
+ );
1138
+ }
1139
+ function Qt(t, e) {
1140
+ t.save(),
1141
+ t.beginPath(),
1142
+ t.rect(e.left, e.top, e.right - e.left, e.bottom - e.top),
1143
+ t.clip();
1144
+ }
1145
+ function te(t) {
1146
+ t.restore();
1147
+ }
1148
+ function ee(t, e, i, s, n) {
1149
+ if (!e) return t.lineTo(i.x, i.y);
1150
+ if ("middle" === n) {
1151
+ const s = (e.x + i.x) / 2;
1152
+ t.lineTo(s, e.y), t.lineTo(s, i.y);
1153
+ } else ("after" === n) != !!s ? t.lineTo(e.x, i.y) : t.lineTo(i.x, e.y);
1154
+ t.lineTo(i.x, i.y);
1155
+ }
1156
+ function ie(t, e, i, s) {
1157
+ if (!e) return t.lineTo(i.x, i.y);
1158
+ t.bezierCurveTo(
1159
+ s ? e.cp1x : e.cp2x,
1160
+ s ? e.cp1y : e.cp2y,
1161
+ s ? i.cp2x : i.cp1x,
1162
+ s ? i.cp2y : i.cp1y,
1163
+ i.x,
1164
+ i.y
1165
+ );
1166
+ }
1167
+ function se(t, e, i, s, n, o = {}) {
1168
+ const a = Y(e) ? e : [e],
1169
+ r = o.strokeWidth > 0 && "" !== o.strokeColor;
1170
+ let l, h;
1171
+ for (
1172
+ t.save(),
1173
+ t.font = n.string,
1174
+ (function (t, e) {
1175
+ e.translation && t.translate(e.translation[0], e.translation[1]);
1176
+ $(e.rotation) || t.rotate(e.rotation);
1177
+ e.color && (t.fillStyle = e.color);
1178
+ e.textAlign && (t.textAlign = e.textAlign);
1179
+ e.textBaseline && (t.textBaseline = e.textBaseline);
1180
+ })(t, o),
1181
+ l = 0;
1182
+ l < a.length;
1183
+ ++l
1184
+ )
1185
+ (h = a[l]),
1186
+ r &&
1187
+ (o.strokeColor && (t.strokeStyle = o.strokeColor),
1188
+ $(o.strokeWidth) || (t.lineWidth = o.strokeWidth),
1189
+ t.strokeText(h, i, s, o.maxWidth)),
1190
+ t.fillText(h, i, s, o.maxWidth),
1191
+ ne(t, i, s, h, o),
1192
+ (s += n.lineHeight);
1193
+ t.restore();
1194
+ }
1195
+ function ne(t, e, i, s, n) {
1196
+ if (n.strikethrough || n.underline) {
1197
+ const o = t.measureText(s),
1198
+ a = e - o.actualBoundingBoxLeft,
1199
+ r = e + o.actualBoundingBoxRight,
1200
+ l = i - o.actualBoundingBoxAscent,
1201
+ h = i + o.actualBoundingBoxDescent,
1202
+ c = n.strikethrough ? (l + h) / 2 : h;
1203
+ (t.strokeStyle = t.fillStyle),
1204
+ t.beginPath(),
1205
+ (t.lineWidth = n.decorationWidth || 2),
1206
+ t.moveTo(a, c),
1207
+ t.lineTo(r, c),
1208
+ t.stroke();
1209
+ }
1210
+ }
1211
+ function oe(t, e) {
1212
+ const { x: i, y: s, w: n, h: o, radius: a } = e;
1213
+ t.arc(i + a.topLeft, s + a.topLeft, a.topLeft, -kt, _t, !0),
1214
+ t.lineTo(i, s + o - a.bottomLeft),
1215
+ t.arc(i + a.bottomLeft, s + o - a.bottomLeft, a.bottomLeft, _t, kt, !0),
1216
+ t.lineTo(i + n - a.bottomRight, s + o),
1217
+ t.arc(
1218
+ i + n - a.bottomRight,
1219
+ s + o - a.bottomRight,
1220
+ a.bottomRight,
1221
+ kt,
1222
+ 0,
1223
+ !0
1224
+ ),
1225
+ t.lineTo(i + n, s + a.topRight),
1226
+ t.arc(i + n - a.topRight, s + a.topRight, a.topRight, 0, -kt, !0),
1227
+ t.lineTo(i + a.topLeft, s);
1228
+ }
1229
+ function ae(t, e, i) {
1230
+ i = i || ((i) => t[i] < e);
1231
+ let s,
1232
+ n = t.length - 1,
1233
+ o = 0;
1234
+ for (; n - o > 1; ) (s = (o + n) >> 1), i(s) ? (o = s) : (n = s);
1235
+ return { lo: o, hi: n };
1236
+ }
1237
+ const re = (t, e, i) => ae(t, i, (s) => t[s][e] < i),
1238
+ le = (t, e, i) => ae(t, i, (s) => t[s][e] >= i);
1239
+ function he(t, e, i) {
1240
+ let s = 0,
1241
+ n = t.length;
1242
+ for (; s < n && t[s] < e; ) s++;
1243
+ for (; n > s && t[n - 1] > i; ) n--;
1244
+ return s > 0 || n < t.length ? t.slice(s, n) : t;
1245
+ }
1246
+ const ce = ["push", "pop", "shift", "splice", "unshift"];
1247
+ function de(t, e) {
1248
+ t._chartjs
1249
+ ? t._chartjs.listeners.push(e)
1250
+ : (Object.defineProperty(t, "_chartjs", {
1251
+ configurable: !0,
1252
+ enumerable: !1,
1253
+ value: { listeners: [e] },
1254
+ }),
1255
+ ce.forEach((e) => {
1256
+ const i = "_onData" + ht(e),
1257
+ s = t[e];
1258
+ Object.defineProperty(t, e, {
1259
+ configurable: !0,
1260
+ enumerable: !1,
1261
+ value(...e) {
1262
+ const n = s.apply(this, e);
1263
+ return (
1264
+ t._chartjs.listeners.forEach((t) => {
1265
+ "function" == typeof t[i] && t[i](...e);
1266
+ }),
1267
+ n
1268
+ );
1269
+ },
1270
+ });
1271
+ }));
1272
+ }
1273
+ function ue(t, e) {
1274
+ const i = t._chartjs;
1275
+ if (!i) return;
1276
+ const s = i.listeners,
1277
+ n = s.indexOf(e);
1278
+ -1 !== n && s.splice(n, 1),
1279
+ s.length > 0 ||
1280
+ (ce.forEach((e) => {
1281
+ delete t[e];
1282
+ }),
1283
+ delete t._chartjs);
1284
+ }
1285
+ function fe(t) {
1286
+ const e = new Set();
1287
+ let i, s;
1288
+ for (i = 0, s = t.length; i < s; ++i) e.add(t[i]);
1289
+ return e.size === s ? t : Array.from(e);
1290
+ }
1291
+ function ge() {
1292
+ return "undefined" != typeof window && "undefined" != typeof document;
1293
+ }
1294
+ function pe(t) {
1295
+ let e = t.parentNode;
1296
+ return e && "[object ShadowRoot]" === e.toString() && (e = e.host), e;
1297
+ }
1298
+ function me(t, e, i) {
1299
+ let s;
1300
+ return (
1301
+ "string" == typeof t
1302
+ ? ((s = parseInt(t, 10)),
1303
+ -1 !== t.indexOf("%") && (s = (s / 100) * e.parentNode[i]))
1304
+ : (s = t),
1305
+ s
1306
+ );
1307
+ }
1308
+ const xe = (t) => window.getComputedStyle(t, null);
1309
+ function be(t, e) {
1310
+ return xe(t).getPropertyValue(e);
1311
+ }
1312
+ const _e = ["top", "right", "bottom", "left"];
1313
+ function ye(t, e, i) {
1314
+ const s = {};
1315
+ i = i ? "-" + i : "";
1316
+ for (let n = 0; n < 4; n++) {
1317
+ const o = _e[n];
1318
+ s[o] = parseFloat(t[e + "-" + o + i]) || 0;
1319
+ }
1320
+ return (s.width = s.left + s.right), (s.height = s.top + s.bottom), s;
1321
+ }
1322
+ function ve(t, e) {
1323
+ const { canvas: i, currentDevicePixelRatio: s } = e,
1324
+ n = xe(i),
1325
+ o = "border-box" === n.boxSizing,
1326
+ a = ye(n, "padding"),
1327
+ r = ye(n, "border", "width"),
1328
+ {
1329
+ x: l,
1330
+ y: h,
1331
+ box: c,
1332
+ } = (function (t, e) {
1333
+ const i = t.native || t,
1334
+ s = i.touches,
1335
+ n = s && s.length ? s[0] : i,
1336
+ { offsetX: o, offsetY: a } = n;
1337
+ let r,
1338
+ l,
1339
+ h = !1;
1340
+ if (
1341
+ ((t, e, i) => (t > 0 || e > 0) && (!i || !i.shadowRoot))(
1342
+ o,
1343
+ a,
1344
+ i.target
1345
+ )
1346
+ )
1347
+ (r = o), (l = a);
1348
+ else {
1349
+ const t = e.getBoundingClientRect();
1350
+ (r = n.clientX - t.left), (l = n.clientY - t.top), (h = !0);
1351
+ }
1352
+ return { x: r, y: l, box: h };
1353
+ })(t, i),
1354
+ d = a.left + (c && r.left),
1355
+ u = a.top + (c && r.top);
1356
+ let { width: f, height: g } = e;
1357
+ return (
1358
+ o && ((f -= a.width + r.width), (g -= a.height + r.height)),
1359
+ {
1360
+ x: Math.round((((l - d) / f) * i.width) / s),
1361
+ y: Math.round((((h - u) / g) * i.height) / s),
1362
+ }
1363
+ );
1364
+ }
1365
+ const we = (t) => Math.round(10 * t) / 10;
1366
+ function Me(t, e, i, s) {
1367
+ const n = xe(t),
1368
+ o = ye(n, "margin"),
1369
+ a = me(n.maxWidth, t, "clientWidth") || wt,
1370
+ r = me(n.maxHeight, t, "clientHeight") || wt,
1371
+ l = (function (t, e, i) {
1372
+ let s, n;
1373
+ if (void 0 === e || void 0 === i) {
1374
+ const o = pe(t);
1375
+ if (o) {
1376
+ const t = o.getBoundingClientRect(),
1377
+ a = xe(o),
1378
+ r = ye(a, "border", "width"),
1379
+ l = ye(a, "padding");
1380
+ (e = t.width - l.width - r.width),
1381
+ (i = t.height - l.height - r.height),
1382
+ (s = me(a.maxWidth, o, "clientWidth")),
1383
+ (n = me(a.maxHeight, o, "clientHeight"));
1384
+ } else (e = t.clientWidth), (i = t.clientHeight);
1385
+ }
1386
+ return { width: e, height: i, maxWidth: s || wt, maxHeight: n || wt };
1387
+ })(t, e, i);
1388
+ let { width: h, height: c } = l;
1389
+ if ("content-box" === n.boxSizing) {
1390
+ const t = ye(n, "border", "width"),
1391
+ e = ye(n, "padding");
1392
+ (h -= e.width + t.width), (c -= e.height + t.height);
1393
+ }
1394
+ return (
1395
+ (h = Math.max(0, h - o.width)),
1396
+ (c = Math.max(0, s ? Math.floor(h / s) : c - o.height)),
1397
+ (h = we(Math.min(h, a, l.maxWidth))),
1398
+ (c = we(Math.min(c, r, l.maxHeight))),
1399
+ h && !c && (c = we(h / 2)),
1400
+ { width: h, height: c }
1401
+ );
1402
+ }
1403
+ function ke(t, e, i) {
1404
+ const s = e || 1,
1405
+ n = Math.floor(t.height * s),
1406
+ o = Math.floor(t.width * s);
1407
+ (t.height = n / s), (t.width = o / s);
1408
+ const a = t.canvas;
1409
+ return (
1410
+ a.style &&
1411
+ (i || (!a.style.height && !a.style.width)) &&
1412
+ ((a.style.height = `${t.height}px`), (a.style.width = `${t.width}px`)),
1413
+ (t.currentDevicePixelRatio !== s || a.height !== n || a.width !== o) &&
1414
+ ((t.currentDevicePixelRatio = s),
1415
+ (a.height = n),
1416
+ (a.width = o),
1417
+ t.ctx.setTransform(s, 0, 0, s, 0, 0),
1418
+ !0)
1419
+ );
1420
+ }
1421
+ const Se = (function () {
1422
+ let t = !1;
1423
+ try {
1424
+ const e = {
1425
+ get passive() {
1426
+ return (t = !0), !1;
1427
+ },
1428
+ };
1429
+ window.addEventListener("test", null, e),
1430
+ window.removeEventListener("test", null, e);
1431
+ } catch (t) {}
1432
+ return t;
1433
+ })();
1434
+ function Pe(t, e) {
1435
+ const i = be(t, e),
1436
+ s = i && i.match(/^(\d+)(\.\d+)?px$/);
1437
+ return s ? +s[1] : void 0;
1438
+ }
1439
+ function De(t, e) {
1440
+ return "native" in t ? { x: t.x, y: t.y } : ve(t, e);
1441
+ }
1442
+ function Ce(t, e, i, s) {
1443
+ const { controller: n, data: o, _sorted: a } = t,
1444
+ r = n._cachedMeta.iScale;
1445
+ if (r && e === r.axis && "r" !== e && a && o.length) {
1446
+ const t = r._reversePixels ? le : re;
1447
+ if (!s) return t(o, e, i);
1448
+ if (n._sharedOptions) {
1449
+ const s = o[0],
1450
+ n = "function" == typeof s.getRange && s.getRange(e);
1451
+ if (n) {
1452
+ const s = t(o, e, i - n),
1453
+ a = t(o, e, i + n);
1454
+ return { lo: s.lo, hi: a.hi };
1455
+ }
1456
+ }
1457
+ }
1458
+ return { lo: 0, hi: o.length - 1 };
1459
+ }
1460
+ function Oe(t, e, i, s, n) {
1461
+ const o = t.getSortedVisibleDatasetMetas(),
1462
+ a = i[e];
1463
+ for (let t = 0, i = o.length; t < i; ++t) {
1464
+ const { index: i, data: r } = o[t],
1465
+ { lo: l, hi: h } = Ce(o[t], e, a, n);
1466
+ for (let t = l; t <= h; ++t) {
1467
+ const e = r[t];
1468
+ e.skip || s(e, i, t);
1469
+ }
1470
+ }
1471
+ }
1472
+ function Ae(t, e, i, s) {
1473
+ const n = [];
1474
+ if (!Jt(e, t.chartArea, t._minPadding)) return n;
1475
+ return (
1476
+ Oe(
1477
+ t,
1478
+ i,
1479
+ e,
1480
+ function (t, i, o) {
1481
+ t.inRange(e.x, e.y, s) &&
1482
+ n.push({ element: t, datasetIndex: i, index: o });
1483
+ },
1484
+ !0
1485
+ ),
1486
+ n
1487
+ );
1488
+ }
1489
+ function Te(t, e, i, s, n) {
1490
+ let o = [];
1491
+ const a = (function (t) {
1492
+ const e = -1 !== t.indexOf("x"),
1493
+ i = -1 !== t.indexOf("y");
1494
+ return function (t, s) {
1495
+ const n = e ? Math.abs(t.x - s.x) : 0,
1496
+ o = i ? Math.abs(t.y - s.y) : 0;
1497
+ return Math.sqrt(Math.pow(n, 2) + Math.pow(o, 2));
1498
+ };
1499
+ })(i);
1500
+ let r = Number.POSITIVE_INFINITY;
1501
+ return (
1502
+ Oe(t, i, e, function (i, l, h) {
1503
+ const c = i.inRange(e.x, e.y, n);
1504
+ if (s && !c) return;
1505
+ const d = i.getCenterPoint(n);
1506
+ if (!Jt(d, t.chartArea, t._minPadding) && !c) return;
1507
+ const u = a(e, d);
1508
+ u < r
1509
+ ? ((o = [{ element: i, datasetIndex: l, index: h }]), (r = u))
1510
+ : u === r && o.push({ element: i, datasetIndex: l, index: h });
1511
+ }),
1512
+ o
1513
+ );
1514
+ }
1515
+ function Le(t, e, i, s, n) {
1516
+ return Jt(e, t.chartArea, t._minPadding)
1517
+ ? "r" !== i || s
1518
+ ? Te(t, e, i, s, n)
1519
+ : (function (t, e, i, s) {
1520
+ let n = [];
1521
+ return (
1522
+ Oe(t, i, e, function (t, i, o) {
1523
+ const { startAngle: a, endAngle: r } = t.getProps(
1524
+ ["startAngle", "endAngle"],
1525
+ s
1526
+ ),
1527
+ { angle: l } = Bt(t, { x: e.x, y: e.y });
1528
+ Ht(l, a, r) &&
1529
+ n.push({ element: t, datasetIndex: i, index: o });
1530
+ }),
1531
+ n
1532
+ );
1533
+ })(t, e, i, n)
1534
+ : [];
1535
+ }
1536
+ function Re(t, e, i, s) {
1537
+ const n = De(e, t),
1538
+ o = [],
1539
+ a = i.axis,
1540
+ r = "x" === a ? "inXRange" : "inYRange";
1541
+ let l = !1;
1542
+ return (
1543
+ (function (t, e) {
1544
+ const i = t.getSortedVisibleDatasetMetas();
1545
+ let s, n, o;
1546
+ for (let t = 0, a = i.length; t < a; ++t) {
1547
+ ({ index: s, data: n } = i[t]);
1548
+ for (let t = 0, i = n.length; t < i; ++t)
1549
+ (o = n[t]), o.skip || e(o, s, t);
1550
+ }
1551
+ })(t, (t, e, i) => {
1552
+ t[r](n[a], s) && o.push({ element: t, datasetIndex: e, index: i }),
1553
+ t.inRange(n.x, n.y, s) && (l = !0);
1554
+ }),
1555
+ i.intersect && !l ? [] : o
1556
+ );
1557
+ }
1558
+ var Ee = {
1559
+ modes: {
1560
+ index(t, e, i, s) {
1561
+ const n = De(e, t),
1562
+ o = i.axis || "x",
1563
+ a = i.intersect ? Ae(t, n, o, s) : Le(t, n, o, !1, s),
1564
+ r = [];
1565
+ return a.length
1566
+ ? (t.getSortedVisibleDatasetMetas().forEach((t) => {
1567
+ const e = a[0].index,
1568
+ i = t.data[e];
1569
+ i &&
1570
+ !i.skip &&
1571
+ r.push({ element: i, datasetIndex: t.index, index: e });
1572
+ }),
1573
+ r)
1574
+ : [];
1575
+ },
1576
+ dataset(t, e, i, s) {
1577
+ const n = De(e, t),
1578
+ o = i.axis || "xy";
1579
+ let a = i.intersect ? Ae(t, n, o, s) : Le(t, n, o, !1, s);
1580
+ if (a.length > 0) {
1581
+ const e = a[0].datasetIndex,
1582
+ i = t.getDatasetMeta(e).data;
1583
+ a = [];
1584
+ for (let t = 0; t < i.length; ++t)
1585
+ a.push({ element: i[t], datasetIndex: e, index: t });
1586
+ }
1587
+ return a;
1588
+ },
1589
+ point: (t, e, i, s) => Ae(t, De(e, t), i.axis || "xy", s),
1590
+ nearest: (t, e, i, s) => Le(t, De(e, t), i.axis || "xy", i.intersect, s),
1591
+ x: (t, e, i, s) => Re(t, e, { axis: "x", intersect: i.intersect }, s),
1592
+ y: (t, e, i, s) => Re(t, e, { axis: "y", intersect: i.intersect }, s),
1593
+ },
1594
+ };
1595
+ const Ie = new RegExp(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/),
1596
+ ze = new RegExp(
1597
+ /^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/
1598
+ );
1599
+ function Fe(t, e) {
1600
+ const i = ("" + t).match(Ie);
1601
+ if (!i || "normal" === i[1]) return 1.2 * e;
1602
+ switch (((t = +i[2]), i[3])) {
1603
+ case "px":
1604
+ return t;
1605
+ case "%":
1606
+ t /= 100;
1607
+ }
1608
+ return e * t;
1609
+ }
1610
+ function Be(t, e) {
1611
+ const i = {},
1612
+ s = U(e),
1613
+ n = s ? Object.keys(e) : e,
1614
+ o = U(t) ? (s ? (i) => K(t[i], t[e[i]]) : (e) => t[e]) : () => t;
1615
+ for (const t of n) i[t] = +o(t) || 0;
1616
+ return i;
1617
+ }
1618
+ function Ve(t) {
1619
+ return Be(t, { top: "y", right: "x", bottom: "y", left: "x" });
1620
+ }
1621
+ function We(t) {
1622
+ return Be(t, ["topLeft", "topRight", "bottomLeft", "bottomRight"]);
1623
+ }
1624
+ function Ne(t) {
1625
+ const e = Ve(t);
1626
+ return (e.width = e.left + e.right), (e.height = e.top + e.bottom), e;
1627
+ }
1628
+ function He(t, e) {
1629
+ (t = t || {}), (e = e || bt.font);
1630
+ let i = K(t.size, e.size);
1631
+ "string" == typeof i && (i = parseInt(i, 10));
1632
+ let s = K(t.style, e.style);
1633
+ s &&
1634
+ !("" + s).match(ze) &&
1635
+ (console.warn('Invalid font style specified: "' + s + '"'), (s = ""));
1636
+ const n = {
1637
+ family: K(t.family, e.family),
1638
+ lineHeight: Fe(K(t.lineHeight, e.lineHeight), i),
1639
+ size: i,
1640
+ style: s,
1641
+ weight: K(t.weight, e.weight),
1642
+ string: "",
1643
+ };
1644
+ return (n.string = Ut(n)), n;
1645
+ }
1646
+ function je(t, e, i, s) {
1647
+ let n,
1648
+ o,
1649
+ a,
1650
+ r = !0;
1651
+ for (n = 0, o = t.length; n < o; ++n)
1652
+ if (
1653
+ ((a = t[n]),
1654
+ void 0 !== a &&
1655
+ (void 0 !== e && "function" == typeof a && ((a = a(e)), (r = !1)),
1656
+ void 0 !== i && Y(a) && ((a = a[i % a.length]), (r = !1)),
1657
+ void 0 !== a))
1658
+ )
1659
+ return s && !r && (s.cacheable = !1), a;
1660
+ }
1661
+ function $e(t, e, i) {
1662
+ const { min: s, max: n } = t,
1663
+ o = Z(e, (n - s) / 2),
1664
+ a = (t, e) => (i && 0 === t ? 0 : t + e);
1665
+ return { min: a(s, -Math.abs(o)), max: a(n, o) };
1666
+ }
1667
+ function Ye(t, e) {
1668
+ return Object.assign(Object.create(t), e);
1669
+ }
1670
+ const Ue = ["left", "top", "right", "bottom"];
1671
+ function Xe(t, e) {
1672
+ return t.filter((t) => t.pos === e);
1673
+ }
1674
+ function qe(t, e) {
1675
+ return t.filter((t) => -1 === Ue.indexOf(t.pos) && t.box.axis === e);
1676
+ }
1677
+ function Ke(t, e) {
1678
+ return t.sort((t, i) => {
1679
+ const s = e ? i : t,
1680
+ n = e ? t : i;
1681
+ return s.weight === n.weight ? s.index - n.index : s.weight - n.weight;
1682
+ });
1683
+ }
1684
+ function Ge(t, e) {
1685
+ const i = (function (t) {
1686
+ const e = {};
1687
+ for (const i of t) {
1688
+ const { stack: t, pos: s, stackWeight: n } = i;
1689
+ if (!t || !Ue.includes(s)) continue;
1690
+ const o =
1691
+ e[t] || (e[t] = { count: 0, placed: 0, weight: 0, size: 0 });
1692
+ o.count++, (o.weight += n);
1693
+ }
1694
+ return e;
1695
+ })(t),
1696
+ { vBoxMaxWidth: s, hBoxMaxHeight: n } = e;
1697
+ let o, a, r;
1698
+ for (o = 0, a = t.length; o < a; ++o) {
1699
+ r = t[o];
1700
+ const { fullSize: a } = r.box,
1701
+ l = i[r.stack],
1702
+ h = l && r.stackWeight / l.weight;
1703
+ r.horizontal
1704
+ ? ((r.width = h ? h * s : a && e.availableWidth), (r.height = n))
1705
+ : ((r.width = s), (r.height = h ? h * n : a && e.availableHeight));
1706
+ }
1707
+ return i;
1708
+ }
1709
+ function Ze(t, e, i, s) {
1710
+ return Math.max(t[i], e[i]) + Math.max(t[s], e[s]);
1711
+ }
1712
+ function Je(t, e) {
1713
+ (t.top = Math.max(t.top, e.top)),
1714
+ (t.left = Math.max(t.left, e.left)),
1715
+ (t.bottom = Math.max(t.bottom, e.bottom)),
1716
+ (t.right = Math.max(t.right, e.right));
1717
+ }
1718
+ function Qe(t, e, i, s) {
1719
+ const { pos: n, box: o } = i,
1720
+ a = t.maxPadding;
1721
+ if (!U(n)) {
1722
+ i.size && (t[n] -= i.size);
1723
+ const e = s[i.stack] || { size: 0, count: 1 };
1724
+ (e.size = Math.max(e.size, i.horizontal ? o.height : o.width)),
1725
+ (i.size = e.size / e.count),
1726
+ (t[n] += i.size);
1727
+ }
1728
+ o.getPadding && Je(a, o.getPadding());
1729
+ const r = Math.max(0, e.outerWidth - Ze(a, t, "left", "right")),
1730
+ l = Math.max(0, e.outerHeight - Ze(a, t, "top", "bottom")),
1731
+ h = r !== t.w,
1732
+ c = l !== t.h;
1733
+ return (
1734
+ (t.w = r),
1735
+ (t.h = l),
1736
+ i.horizontal ? { same: h, other: c } : { same: c, other: h }
1737
+ );
1738
+ }
1739
+ function ti(t, e) {
1740
+ const i = e.maxPadding;
1741
+ function s(t) {
1742
+ const s = { left: 0, top: 0, right: 0, bottom: 0 };
1743
+ return (
1744
+ t.forEach((t) => {
1745
+ s[t] = Math.max(e[t], i[t]);
1746
+ }),
1747
+ s
1748
+ );
1749
+ }
1750
+ return s(t ? ["left", "right"] : ["top", "bottom"]);
1751
+ }
1752
+ function ei(t, e, i, s) {
1753
+ const n = [];
1754
+ let o, a, r, l, h, c;
1755
+ for (o = 0, a = t.length, h = 0; o < a; ++o) {
1756
+ (r = t[o]),
1757
+ (l = r.box),
1758
+ l.update(r.width || e.w, r.height || e.h, ti(r.horizontal, e));
1759
+ const { same: a, other: d } = Qe(e, i, r, s);
1760
+ (h |= a && n.length), (c = c || d), l.fullSize || n.push(r);
1761
+ }
1762
+ return (h && ei(n, e, i, s)) || c;
1763
+ }
1764
+ function ii(t, e, i, s, n) {
1765
+ (t.top = i),
1766
+ (t.left = e),
1767
+ (t.right = e + s),
1768
+ (t.bottom = i + n),
1769
+ (t.width = s),
1770
+ (t.height = n);
1771
+ }
1772
+ function si(t, e, i, s) {
1773
+ const n = i.padding;
1774
+ let { x: o, y: a } = e;
1775
+ for (const r of t) {
1776
+ const t = r.box,
1777
+ l = s[r.stack] || { count: 1, placed: 0, weight: 1 },
1778
+ h = r.stackWeight / l.weight || 1;
1779
+ if (r.horizontal) {
1780
+ const s = e.w * h,
1781
+ o = l.size || t.height;
1782
+ ct(l.start) && (a = l.start),
1783
+ t.fullSize
1784
+ ? ii(t, n.left, a, i.outerWidth - n.right - n.left, o)
1785
+ : ii(t, e.left + l.placed, a, s, o),
1786
+ (l.start = a),
1787
+ (l.placed += s),
1788
+ (a = t.bottom);
1789
+ } else {
1790
+ const s = e.h * h,
1791
+ a = l.size || t.width;
1792
+ ct(l.start) && (o = l.start),
1793
+ t.fullSize
1794
+ ? ii(t, o, n.top, a, i.outerHeight - n.bottom - n.top)
1795
+ : ii(t, o, e.top + l.placed, a, s),
1796
+ (l.start = o),
1797
+ (l.placed += s),
1798
+ (o = t.right);
1799
+ }
1800
+ }
1801
+ (e.x = o), (e.y = a);
1802
+ }
1803
+ bt.set("layout", {
1804
+ autoPadding: !0,
1805
+ padding: { top: 0, right: 0, bottom: 0, left: 0 },
1806
+ });
1807
+ var ni = {
1808
+ addBox(t, e) {
1809
+ t.boxes || (t.boxes = []),
1810
+ (e.fullSize = e.fullSize || !1),
1811
+ (e.position = e.position || "top"),
1812
+ (e.weight = e.weight || 0),
1813
+ (e._layers =
1814
+ e._layers ||
1815
+ function () {
1816
+ return [
1817
+ {
1818
+ z: 0,
1819
+ draw(t) {
1820
+ e.draw(t);
1821
+ },
1822
+ },
1823
+ ];
1824
+ }),
1825
+ t.boxes.push(e);
1826
+ },
1827
+ removeBox(t, e) {
1828
+ const i = t.boxes ? t.boxes.indexOf(e) : -1;
1829
+ -1 !== i && t.boxes.splice(i, 1);
1830
+ },
1831
+ configure(t, e, i) {
1832
+ (e.fullSize = i.fullSize),
1833
+ (e.position = i.position),
1834
+ (e.weight = i.weight);
1835
+ },
1836
+ update(t, e, i, s) {
1837
+ if (!t) return;
1838
+ const n = Ne(t.options.layout.padding),
1839
+ o = Math.max(e - n.width, 0),
1840
+ a = Math.max(i - n.height, 0),
1841
+ r = (function (t) {
1842
+ const e = (function (t) {
1843
+ const e = [];
1844
+ let i, s, n, o, a, r;
1845
+ for (i = 0, s = (t || []).length; i < s; ++i)
1846
+ (n = t[i]),
1847
+ ({
1848
+ position: o,
1849
+ options: { stack: a, stackWeight: r = 1 },
1850
+ } = n),
1851
+ e.push({
1852
+ index: i,
1853
+ box: n,
1854
+ pos: o,
1855
+ horizontal: n.isHorizontal(),
1856
+ weight: n.weight,
1857
+ stack: a && o + a,
1858
+ stackWeight: r,
1859
+ });
1860
+ return e;
1861
+ })(t),
1862
+ i = Ke(
1863
+ e.filter((t) => t.box.fullSize),
1864
+ !0
1865
+ ),
1866
+ s = Ke(Xe(e, "left"), !0),
1867
+ n = Ke(Xe(e, "right")),
1868
+ o = Ke(Xe(e, "top"), !0),
1869
+ a = Ke(Xe(e, "bottom")),
1870
+ r = qe(e, "x"),
1871
+ l = qe(e, "y");
1872
+ return {
1873
+ fullSize: i,
1874
+ leftAndTop: s.concat(o),
1875
+ rightAndBottom: n.concat(l).concat(a).concat(r),
1876
+ chartArea: Xe(e, "chartArea"),
1877
+ vertical: s.concat(n).concat(l),
1878
+ horizontal: o.concat(a).concat(r),
1879
+ };
1880
+ })(t.boxes),
1881
+ l = r.vertical,
1882
+ h = r.horizontal;
1883
+ Q(t.boxes, (t) => {
1884
+ "function" == typeof t.beforeLayout && t.beforeLayout();
1885
+ });
1886
+ const c =
1887
+ l.reduce(
1888
+ (t, e) =>
1889
+ e.box.options && !1 === e.box.options.display ? t : t + 1,
1890
+ 0
1891
+ ) || 1,
1892
+ d = Object.freeze({
1893
+ outerWidth: e,
1894
+ outerHeight: i,
1895
+ padding: n,
1896
+ availableWidth: o,
1897
+ availableHeight: a,
1898
+ vBoxMaxWidth: o / 2 / c,
1899
+ hBoxMaxHeight: a / 2,
1900
+ }),
1901
+ u = Object.assign({}, n);
1902
+ Je(u, Ne(s));
1903
+ const f = Object.assign(
1904
+ { maxPadding: u, w: o, h: a, x: n.left, y: n.top },
1905
+ n
1906
+ ),
1907
+ g = Ge(l.concat(h), d);
1908
+ ei(r.fullSize, f, d, g),
1909
+ ei(l, f, d, g),
1910
+ ei(h, f, d, g) && ei(l, f, d, g),
1911
+ (function (t) {
1912
+ const e = t.maxPadding;
1913
+ function i(i) {
1914
+ const s = Math.max(e[i] - t[i], 0);
1915
+ return (t[i] += s), s;
1916
+ }
1917
+ (t.y += i("top")), (t.x += i("left")), i("right"), i("bottom");
1918
+ })(f),
1919
+ si(r.leftAndTop, f, d, g),
1920
+ (f.x += f.w),
1921
+ (f.y += f.h),
1922
+ si(r.rightAndBottom, f, d, g),
1923
+ (t.chartArea = {
1924
+ left: f.left,
1925
+ top: f.top,
1926
+ right: f.left + f.w,
1927
+ bottom: f.top + f.h,
1928
+ height: f.h,
1929
+ width: f.w,
1930
+ }),
1931
+ Q(r.chartArea, (e) => {
1932
+ const i = e.box;
1933
+ Object.assign(i, t.chartArea),
1934
+ i.update(f.w, f.h, { left: 0, top: 0, right: 0, bottom: 0 });
1935
+ });
1936
+ },
1937
+ };
1938
+ function oi(t, e = [""], i = t, s, n = () => t[0]) {
1939
+ ct(s) || (s = mi("_fallback", t));
1940
+ const o = {
1941
+ [Symbol.toStringTag]: "Object",
1942
+ _cacheable: !0,
1943
+ _scopes: t,
1944
+ _rootScopes: i,
1945
+ _fallback: s,
1946
+ _getTarget: n,
1947
+ override: (n) => oi([n, ...t], e, i, s),
1948
+ };
1949
+ return new Proxy(o, {
1950
+ deleteProperty: (e, i) => (
1951
+ delete e[i], delete e._keys, delete t[0][i], !0
1952
+ ),
1953
+ get: (i, s) =>
1954
+ ci(i, s, () =>
1955
+ (function (t, e, i, s) {
1956
+ let n;
1957
+ for (const o of e)
1958
+ if (((n = mi(li(o, t), i)), ct(n)))
1959
+ return hi(t, n) ? gi(i, s, t, n) : n;
1960
+ })(s, e, t, i)
1961
+ ),
1962
+ getOwnPropertyDescriptor: (t, e) =>
1963
+ Reflect.getOwnPropertyDescriptor(t._scopes[0], e),
1964
+ getPrototypeOf: () => Reflect.getPrototypeOf(t[0]),
1965
+ has: (t, e) => xi(t).includes(e),
1966
+ ownKeys: (t) => xi(t),
1967
+ set(t, e, i) {
1968
+ const s = t._storage || (t._storage = n());
1969
+ return (t[e] = s[e] = i), delete t._keys, !0;
1970
+ },
1971
+ });
1972
+ }
1973
+ function ai(t, e, i, s) {
1974
+ const n = {
1975
+ _cacheable: !1,
1976
+ _proxy: t,
1977
+ _context: e,
1978
+ _subProxy: i,
1979
+ _stack: new Set(),
1980
+ _descriptors: ri(t, s),
1981
+ setContext: (e) => ai(t, e, i, s),
1982
+ override: (n) => ai(t.override(n), e, i, s),
1983
+ };
1984
+ return new Proxy(n, {
1985
+ deleteProperty: (e, i) => (delete e[i], delete t[i], !0),
1986
+ get: (t, e, i) =>
1987
+ ci(t, e, () =>
1988
+ (function (t, e, i) {
1989
+ const { _proxy: s, _context: n, _subProxy: o, _descriptors: a } = t;
1990
+ let r = s[e];
1991
+ dt(r) &&
1992
+ a.isScriptable(e) &&
1993
+ (r = (function (t, e, i, s) {
1994
+ const { _proxy: n, _context: o, _subProxy: a, _stack: r } = i;
1995
+ if (r.has(t))
1996
+ throw new Error(
1997
+ "Recursion detected: " + Array.from(r).join("->") + "->" + t
1998
+ );
1999
+ r.add(t),
2000
+ (e = e(o, a || s)),
2001
+ r.delete(t),
2002
+ hi(t, e) && (e = gi(n._scopes, n, t, e));
2003
+ return e;
2004
+ })(e, r, t, i));
2005
+ Y(r) &&
2006
+ r.length &&
2007
+ (r = (function (t, e, i, s) {
2008
+ const {
2009
+ _proxy: n,
2010
+ _context: o,
2011
+ _subProxy: a,
2012
+ _descriptors: r,
2013
+ } = i;
2014
+ if (ct(o.index) && s(t)) e = e[o.index % e.length];
2015
+ else if (U(e[0])) {
2016
+ const i = e,
2017
+ s = n._scopes.filter((t) => t !== i);
2018
+ e = [];
2019
+ for (const l of i) {
2020
+ const i = gi(s, n, t, l);
2021
+ e.push(ai(i, o, a && a[t], r));
2022
+ }
2023
+ }
2024
+ return e;
2025
+ })(e, r, t, a.isIndexable));
2026
+ hi(e, r) && (r = ai(r, n, o && o[e], a));
2027
+ return r;
2028
+ })(t, e, i)
2029
+ ),
2030
+ getOwnPropertyDescriptor: (e, i) =>
2031
+ e._descriptors.allKeys
2032
+ ? Reflect.has(t, i)
2033
+ ? { enumerable: !0, configurable: !0 }
2034
+ : void 0
2035
+ : Reflect.getOwnPropertyDescriptor(t, i),
2036
+ getPrototypeOf: () => Reflect.getPrototypeOf(t),
2037
+ has: (e, i) => Reflect.has(t, i),
2038
+ ownKeys: () => Reflect.ownKeys(t),
2039
+ set: (e, i, s) => ((t[i] = s), delete e[i], !0),
2040
+ });
2041
+ }
2042
+ function ri(t, e = { scriptable: !0, indexable: !0 }) {
2043
+ const {
2044
+ _scriptable: i = e.scriptable,
2045
+ _indexable: s = e.indexable,
2046
+ _allKeys: n = e.allKeys,
2047
+ } = t;
2048
+ return {
2049
+ allKeys: n,
2050
+ scriptable: i,
2051
+ indexable: s,
2052
+ isScriptable: dt(i) ? i : () => i,
2053
+ isIndexable: dt(s) ? s : () => s,
2054
+ };
2055
+ }
2056
+ const li = (t, e) => (t ? t + ht(e) : e),
2057
+ hi = (t, e) =>
2058
+ U(e) &&
2059
+ "adapters" !== t &&
2060
+ (null === Object.getPrototypeOf(e) || e.constructor === Object);
2061
+ function ci(t, e, i) {
2062
+ if (Object.prototype.hasOwnProperty.call(t, e)) return t[e];
2063
+ const s = i();
2064
+ return (t[e] = s), s;
2065
+ }
2066
+ function di(t, e, i) {
2067
+ return dt(t) ? t(e, i) : t;
2068
+ }
2069
+ const ui = (t, e) =>
2070
+ !0 === t ? e : "string" == typeof t ? lt(e, t) : void 0;
2071
+ function fi(t, e, i, s, n) {
2072
+ for (const o of e) {
2073
+ const e = ui(i, o);
2074
+ if (e) {
2075
+ t.add(e);
2076
+ const o = di(e._fallback, i, n);
2077
+ if (ct(o) && o !== i && o !== s) return o;
2078
+ } else if (!1 === e && ct(s) && i !== s) return null;
2079
+ }
2080
+ return !1;
2081
+ }
2082
+ function gi(t, e, i, s) {
2083
+ const n = e._rootScopes,
2084
+ o = di(e._fallback, i, s),
2085
+ a = [...t, ...n],
2086
+ r = new Set();
2087
+ r.add(s);
2088
+ let l = pi(r, a, i, o || i, s);
2089
+ return (
2090
+ null !== l &&
2091
+ (!ct(o) || o === i || ((l = pi(r, a, o, l, s)), null !== l)) &&
2092
+ oi(Array.from(r), [""], n, o, () =>
2093
+ (function (t, e, i) {
2094
+ const s = t._getTarget();
2095
+ e in s || (s[e] = {});
2096
+ const n = s[e];
2097
+ if (Y(n) && U(i)) return i;
2098
+ return n;
2099
+ })(e, i, s)
2100
+ )
2101
+ );
2102
+ }
2103
+ function pi(t, e, i, s, n) {
2104
+ for (; i; ) i = fi(t, e, i, s, n);
2105
+ return i;
2106
+ }
2107
+ function mi(t, e) {
2108
+ for (const i of e) {
2109
+ if (!i) continue;
2110
+ const e = i[t];
2111
+ if (ct(e)) return e;
2112
+ }
2113
+ }
2114
+ function xi(t) {
2115
+ let e = t._keys;
2116
+ return (
2117
+ e ||
2118
+ (e = t._keys =
2119
+ (function (t) {
2120
+ const e = new Set();
2121
+ for (const i of t)
2122
+ for (const t of Object.keys(i).filter((t) => !t.startsWith("_")))
2123
+ e.add(t);
2124
+ return Array.from(e);
2125
+ })(t._scopes)),
2126
+ e
2127
+ );
2128
+ }
2129
+ const bi = Number.EPSILON || 1e-14,
2130
+ _i = (t, e) => e < t.length && !t[e].skip && t[e],
2131
+ yi = (t) => ("x" === t ? "y" : "x");
2132
+ function vi(t, e, i, s) {
2133
+ const n = t.skip ? e : t,
2134
+ o = e,
2135
+ a = i.skip ? e : i,
2136
+ r = Vt(o, n),
2137
+ l = Vt(a, o);
2138
+ let h = r / (r + l),
2139
+ c = l / (r + l);
2140
+ (h = isNaN(h) ? 0 : h), (c = isNaN(c) ? 0 : c);
2141
+ const d = s * h,
2142
+ u = s * c;
2143
+ return {
2144
+ previous: { x: o.x - d * (a.x - n.x), y: o.y - d * (a.y - n.y) },
2145
+ next: { x: o.x + u * (a.x - n.x), y: o.y + u * (a.y - n.y) },
2146
+ };
2147
+ }
2148
+ function wi(t, e = "x") {
2149
+ const i = yi(e),
2150
+ s = t.length,
2151
+ n = Array(s).fill(0),
2152
+ o = Array(s);
2153
+ let a,
2154
+ r,
2155
+ l,
2156
+ h = _i(t, 0);
2157
+ for (a = 0; a < s; ++a)
2158
+ if (((r = l), (l = h), (h = _i(t, a + 1)), l)) {
2159
+ if (h) {
2160
+ const t = h[e] - l[e];
2161
+ n[a] = 0 !== t ? (h[i] - l[i]) / t : 0;
2162
+ }
2163
+ o[a] = r
2164
+ ? h
2165
+ ? Ct(n[a - 1]) !== Ct(n[a])
2166
+ ? 0
2167
+ : (n[a - 1] + n[a]) / 2
2168
+ : n[a - 1]
2169
+ : n[a];
2170
+ }
2171
+ !(function (t, e, i) {
2172
+ const s = t.length;
2173
+ let n,
2174
+ o,
2175
+ a,
2176
+ r,
2177
+ l,
2178
+ h = _i(t, 0);
2179
+ for (let c = 0; c < s - 1; ++c)
2180
+ (l = h),
2181
+ (h = _i(t, c + 1)),
2182
+ l &&
2183
+ h &&
2184
+ (Lt(e[c], 0, bi)
2185
+ ? (i[c] = i[c + 1] = 0)
2186
+ : ((n = i[c] / e[c]),
2187
+ (o = i[c + 1] / e[c]),
2188
+ (r = Math.pow(n, 2) + Math.pow(o, 2)),
2189
+ r <= 9 ||
2190
+ ((a = 3 / Math.sqrt(r)),
2191
+ (i[c] = n * a * e[c]),
2192
+ (i[c + 1] = o * a * e[c]))));
2193
+ })(t, n, o),
2194
+ (function (t, e, i = "x") {
2195
+ const s = yi(i),
2196
+ n = t.length;
2197
+ let o,
2198
+ a,
2199
+ r,
2200
+ l = _i(t, 0);
2201
+ for (let h = 0; h < n; ++h) {
2202
+ if (((a = r), (r = l), (l = _i(t, h + 1)), !r)) continue;
2203
+ const n = r[i],
2204
+ c = r[s];
2205
+ a &&
2206
+ ((o = (n - a[i]) / 3),
2207
+ (r[`cp1${i}`] = n - o),
2208
+ (r[`cp1${s}`] = c - o * e[h])),
2209
+ l &&
2210
+ ((o = (l[i] - n) / 3),
2211
+ (r[`cp2${i}`] = n + o),
2212
+ (r[`cp2${s}`] = c + o * e[h]));
2213
+ }
2214
+ })(t, o, e);
2215
+ }
2216
+ function Mi(t, e, i) {
2217
+ return Math.max(Math.min(t, i), e);
2218
+ }
2219
+ function ki(t, e, i, s, n) {
2220
+ let o, a, r, l;
2221
+ if (
2222
+ (e.spanGaps && (t = t.filter((t) => !t.skip)),
2223
+ "monotone" === e.cubicInterpolationMode)
2224
+ )
2225
+ wi(t, n);
2226
+ else {
2227
+ let i = s ? t[t.length - 1] : t[0];
2228
+ for (o = 0, a = t.length; o < a; ++o)
2229
+ (r = t[o]),
2230
+ (l = vi(i, r, t[Math.min(o + 1, a - (s ? 0 : 1)) % a], e.tension)),
2231
+ (r.cp1x = l.previous.x),
2232
+ (r.cp1y = l.previous.y),
2233
+ (r.cp2x = l.next.x),
2234
+ (r.cp2y = l.next.y),
2235
+ (i = r);
2236
+ }
2237
+ e.capBezierPoints &&
2238
+ (function (t, e) {
2239
+ let i,
2240
+ s,
2241
+ n,
2242
+ o,
2243
+ a,
2244
+ r = Jt(t[0], e);
2245
+ for (i = 0, s = t.length; i < s; ++i)
2246
+ (a = o),
2247
+ (o = r),
2248
+ (r = i < s - 1 && Jt(t[i + 1], e)),
2249
+ o &&
2250
+ ((n = t[i]),
2251
+ a &&
2252
+ ((n.cp1x = Mi(n.cp1x, e.left, e.right)),
2253
+ (n.cp1y = Mi(n.cp1y, e.top, e.bottom))),
2254
+ r &&
2255
+ ((n.cp2x = Mi(n.cp2x, e.left, e.right)),
2256
+ (n.cp2y = Mi(n.cp2y, e.top, e.bottom))));
2257
+ })(t, i);
2258
+ }
2259
+ const Si = (t) => 0 === t || 1 === t,
2260
+ Pi = (t, e, i) =>
2261
+ -Math.pow(2, 10 * (t -= 1)) * Math.sin(((t - e) * yt) / i),
2262
+ Di = (t, e, i) => Math.pow(2, -10 * t) * Math.sin(((t - e) * yt) / i) + 1,
2263
+ Ci = {
2264
+ linear: (t) => t,
2265
+ easeInQuad: (t) => t * t,
2266
+ easeOutQuad: (t) => -t * (t - 2),
2267
+ easeInOutQuad: (t) =>
2268
+ (t /= 0.5) < 1 ? 0.5 * t * t : -0.5 * (--t * (t - 2) - 1),
2269
+ easeInCubic: (t) => t * t * t,
2270
+ easeOutCubic: (t) => (t -= 1) * t * t + 1,
2271
+ easeInOutCubic: (t) =>
2272
+ (t /= 0.5) < 1 ? 0.5 * t * t * t : 0.5 * ((t -= 2) * t * t + 2),
2273
+ easeInQuart: (t) => t * t * t * t,
2274
+ easeOutQuart: (t) => -((t -= 1) * t * t * t - 1),
2275
+ easeInOutQuart: (t) =>
2276
+ (t /= 0.5) < 1
2277
+ ? 0.5 * t * t * t * t
2278
+ : -0.5 * ((t -= 2) * t * t * t - 2),
2279
+ easeInQuint: (t) => t * t * t * t * t,
2280
+ easeOutQuint: (t) => (t -= 1) * t * t * t * t + 1,
2281
+ easeInOutQuint: (t) =>
2282
+ (t /= 0.5) < 1
2283
+ ? 0.5 * t * t * t * t * t
2284
+ : 0.5 * ((t -= 2) * t * t * t * t + 2),
2285
+ easeInSine: (t) => 1 - Math.cos(t * kt),
2286
+ easeOutSine: (t) => Math.sin(t * kt),
2287
+ easeInOutSine: (t) => -0.5 * (Math.cos(_t * t) - 1),
2288
+ easeInExpo: (t) => (0 === t ? 0 : Math.pow(2, 10 * (t - 1))),
2289
+ easeOutExpo: (t) => (1 === t ? 1 : 1 - Math.pow(2, -10 * t)),
2290
+ easeInOutExpo: (t) =>
2291
+ Si(t)
2292
+ ? t
2293
+ : t < 0.5
2294
+ ? 0.5 * Math.pow(2, 10 * (2 * t - 1))
2295
+ : 0.5 * (2 - Math.pow(2, -10 * (2 * t - 1))),
2296
+ easeInCirc: (t) => (t >= 1 ? t : -(Math.sqrt(1 - t * t) - 1)),
2297
+ easeOutCirc: (t) => Math.sqrt(1 - (t -= 1) * t),
2298
+ easeInOutCirc: (t) =>
2299
+ (t /= 0.5) < 1
2300
+ ? -0.5 * (Math.sqrt(1 - t * t) - 1)
2301
+ : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1),
2302
+ easeInElastic: (t) => (Si(t) ? t : Pi(t, 0.075, 0.3)),
2303
+ easeOutElastic: (t) => (Si(t) ? t : Di(t, 0.075, 0.3)),
2304
+ easeInOutElastic(t) {
2305
+ const e = 0.1125;
2306
+ return Si(t)
2307
+ ? t
2308
+ : t < 0.5
2309
+ ? 0.5 * Pi(2 * t, e, 0.45)
2310
+ : 0.5 + 0.5 * Di(2 * t - 1, e, 0.45);
2311
+ },
2312
+ easeInBack(t) {
2313
+ const e = 1.70158;
2314
+ return t * t * ((e + 1) * t - e);
2315
+ },
2316
+ easeOutBack(t) {
2317
+ const e = 1.70158;
2318
+ return (t -= 1) * t * ((e + 1) * t + e) + 1;
2319
+ },
2320
+ easeInOutBack(t) {
2321
+ let e = 1.70158;
2322
+ return (t /= 0.5) < 1
2323
+ ? t * t * ((1 + (e *= 1.525)) * t - e) * 0.5
2324
+ : 0.5 * ((t -= 2) * t * ((1 + (e *= 1.525)) * t + e) + 2);
2325
+ },
2326
+ easeInBounce: (t) => 1 - Ci.easeOutBounce(1 - t),
2327
+ easeOutBounce(t) {
2328
+ const e = 7.5625,
2329
+ i = 2.75;
2330
+ return t < 1 / i
2331
+ ? e * t * t
2332
+ : t < 2 / i
2333
+ ? e * (t -= 1.5 / i) * t + 0.75
2334
+ : t < 2.5 / i
2335
+ ? e * (t -= 2.25 / i) * t + 0.9375
2336
+ : e * (t -= 2.625 / i) * t + 0.984375;
2337
+ },
2338
+ easeInOutBounce: (t) =>
2339
+ t < 0.5
2340
+ ? 0.5 * Ci.easeInBounce(2 * t)
2341
+ : 0.5 * Ci.easeOutBounce(2 * t - 1) + 0.5,
2342
+ };
2343
+ function Oi(t, e, i, s) {
2344
+ return { x: t.x + i * (e.x - t.x), y: t.y + i * (e.y - t.y) };
2345
+ }
2346
+ function Ai(t, e, i, s) {
2347
+ return {
2348
+ x: t.x + i * (e.x - t.x),
2349
+ y:
2350
+ "middle" === s
2351
+ ? i < 0.5
2352
+ ? t.y
2353
+ : e.y
2354
+ : "after" === s
2355
+ ? i < 1
2356
+ ? t.y
2357
+ : e.y
2358
+ : i > 0
2359
+ ? e.y
2360
+ : t.y,
2361
+ };
2362
+ }
2363
+ function Ti(t, e, i, s) {
2364
+ const n = { x: t.cp2x, y: t.cp2y },
2365
+ o = { x: e.cp1x, y: e.cp1y },
2366
+ a = Oi(t, n, i),
2367
+ r = Oi(n, o, i),
2368
+ l = Oi(o, e, i),
2369
+ h = Oi(a, r, i),
2370
+ c = Oi(r, l, i);
2371
+ return Oi(h, c, i);
2372
+ }
2373
+ const Li = new Map();
2374
+ function Ri(t, e, i) {
2375
+ return (function (t, e) {
2376
+ e = e || {};
2377
+ const i = t + JSON.stringify(e);
2378
+ let s = Li.get(i);
2379
+ return s || ((s = new Intl.NumberFormat(t, e)), Li.set(i, s)), s;
2380
+ })(e, i).format(t);
2381
+ }
2382
+ function Ei(t, e, i) {
2383
+ return t
2384
+ ? (function (t, e) {
2385
+ return {
2386
+ x: (i) => t + t + e - i,
2387
+ setWidth(t) {
2388
+ e = t;
2389
+ },
2390
+ textAlign: (t) =>
2391
+ "center" === t ? t : "right" === t ? "left" : "right",
2392
+ xPlus: (t, e) => t - e,
2393
+ leftForLtr: (t, e) => t - e,
2394
+ };
2395
+ })(e, i)
2396
+ : {
2397
+ x: (t) => t,
2398
+ setWidth(t) {},
2399
+ textAlign: (t) => t,
2400
+ xPlus: (t, e) => t + e,
2401
+ leftForLtr: (t, e) => t,
2402
+ };
2403
+ }
2404
+ function Ii(t, e) {
2405
+ let i, s;
2406
+ ("ltr" !== e && "rtl" !== e) ||
2407
+ ((i = t.canvas.style),
2408
+ (s = [
2409
+ i.getPropertyValue("direction"),
2410
+ i.getPropertyPriority("direction"),
2411
+ ]),
2412
+ i.setProperty("direction", e, "important"),
2413
+ (t.prevTextDirection = s));
2414
+ }
2415
+ function zi(t, e) {
2416
+ void 0 !== e &&
2417
+ (delete t.prevTextDirection,
2418
+ t.canvas.style.setProperty("direction", e[0], e[1]));
2419
+ }
2420
+ function Fi(t) {
2421
+ return "angle" === t
2422
+ ? { between: Ht, compare: Wt, normalize: Nt }
2423
+ : { between: Yt, compare: (t, e) => t - e, normalize: (t) => t };
2424
+ }
2425
+ function Bi({ start: t, end: e, count: i, loop: s, style: n }) {
2426
+ return {
2427
+ start: t % i,
2428
+ end: e % i,
2429
+ loop: s && (e - t + 1) % i == 0,
2430
+ style: n,
2431
+ };
2432
+ }
2433
+ function Vi(t, e, i) {
2434
+ if (!i) return [t];
2435
+ const { property: s, start: n, end: o } = i,
2436
+ a = e.length,
2437
+ { compare: r, between: l, normalize: h } = Fi(s),
2438
+ {
2439
+ start: c,
2440
+ end: d,
2441
+ loop: u,
2442
+ style: f,
2443
+ } = (function (t, e, i) {
2444
+ const { property: s, start: n, end: o } = i,
2445
+ { between: a, normalize: r } = Fi(s),
2446
+ l = e.length;
2447
+ let h,
2448
+ c,
2449
+ { start: d, end: u, loop: f } = t;
2450
+ if (f) {
2451
+ for (
2452
+ d += l, u += l, h = 0, c = l;
2453
+ h < c && a(r(e[d % l][s]), n, o);
2454
+ ++h
2455
+ )
2456
+ d--, u--;
2457
+ (d %= l), (u %= l);
2458
+ }
2459
+ return u < d && (u += l), { start: d, end: u, loop: f, style: t.style };
2460
+ })(t, e, i),
2461
+ g = [];
2462
+ let p,
2463
+ m,
2464
+ x,
2465
+ b = !1,
2466
+ _ = null;
2467
+ const y = () => b || (l(n, x, p) && 0 !== r(n, x)),
2468
+ v = () => !b || 0 === r(o, p) || l(o, x, p);
2469
+ for (let t = c, i = c; t <= d; ++t)
2470
+ (m = e[t % a]),
2471
+ m.skip ||
2472
+ ((p = h(m[s])),
2473
+ p !== x &&
2474
+ ((b = l(p, n, o)),
2475
+ null === _ && y() && (_ = 0 === r(p, n) ? t : i),
2476
+ null !== _ &&
2477
+ v() &&
2478
+ (g.push(Bi({ start: _, end: t, loop: u, count: a, style: f })),
2479
+ (_ = null)),
2480
+ (i = t),
2481
+ (x = p)));
2482
+ return (
2483
+ null !== _ &&
2484
+ g.push(Bi({ start: _, end: d, loop: u, count: a, style: f })),
2485
+ g
2486
+ );
2487
+ }
2488
+ function Wi(t, e) {
2489
+ const i = [],
2490
+ s = t.segments;
2491
+ for (let n = 0; n < s.length; n++) {
2492
+ const o = Vi(s[n], t.points, e);
2493
+ o.length && i.push(...o);
2494
+ }
2495
+ return i;
2496
+ }
2497
+ function Ni(t, e) {
2498
+ const i = t.points,
2499
+ s = t.options.spanGaps,
2500
+ n = i.length;
2501
+ if (!n) return [];
2502
+ const o = !!t._loop,
2503
+ { start: a, end: r } = (function (t, e, i, s) {
2504
+ let n = 0,
2505
+ o = e - 1;
2506
+ if (i && !s) for (; n < e && !t[n].skip; ) n++;
2507
+ for (; n < e && t[n].skip; ) n++;
2508
+ for (n %= e, i && (o += n); o > n && t[o % e].skip; ) o--;
2509
+ return (o %= e), { start: n, end: o };
2510
+ })(i, n, o, s);
2511
+ if (!0 === s) return Hi(t, [{ start: a, end: r, loop: o }], i, e);
2512
+ return Hi(
2513
+ t,
2514
+ (function (t, e, i, s) {
2515
+ const n = t.length,
2516
+ o = [];
2517
+ let a,
2518
+ r = e,
2519
+ l = t[e];
2520
+ for (a = e + 1; a <= i; ++a) {
2521
+ const i = t[a % n];
2522
+ i.skip || i.stop
2523
+ ? l.skip ||
2524
+ ((s = !1),
2525
+ o.push({ start: e % n, end: (a - 1) % n, loop: s }),
2526
+ (e = r = i.stop ? a : null))
2527
+ : ((r = a), l.skip && (e = a)),
2528
+ (l = i);
2529
+ }
2530
+ return null !== r && o.push({ start: e % n, end: r % n, loop: s }), o;
2531
+ })(i, a, r < a ? r + n : r, !!t._fullLoop && 0 === a && r === n - 1),
2532
+ i,
2533
+ e
2534
+ );
2535
+ }
2536
+ function Hi(t, e, i, s) {
2537
+ return s && s.setContext && i
2538
+ ? (function (t, e, i, s) {
2539
+ const n = t._chart.getContext(),
2540
+ o = ji(t.options),
2541
+ {
2542
+ _datasetIndex: a,
2543
+ options: { spanGaps: r },
2544
+ } = t,
2545
+ l = i.length,
2546
+ h = [];
2547
+ let c = o,
2548
+ d = e[0].start,
2549
+ u = d;
2550
+ function f(t, e, s, n) {
2551
+ const o = r ? -1 : 1;
2552
+ if (t !== e) {
2553
+ for (t += l; i[t % l].skip; ) t -= o;
2554
+ for (; i[e % l].skip; ) e += o;
2555
+ t % l != e % l &&
2556
+ (h.push({ start: t % l, end: e % l, loop: s, style: n }),
2557
+ (c = n),
2558
+ (d = e % l));
2559
+ }
2560
+ }
2561
+ for (const t of e) {
2562
+ d = r ? d : t.start;
2563
+ let e,
2564
+ o = i[d % l];
2565
+ for (u = d + 1; u <= t.end; u++) {
2566
+ const r = i[u % l];
2567
+ (e = ji(
2568
+ s.setContext(
2569
+ Ye(n, {
2570
+ type: "segment",
2571
+ p0: o,
2572
+ p1: r,
2573
+ p0DataIndex: (u - 1) % l,
2574
+ p1DataIndex: u % l,
2575
+ datasetIndex: a,
2576
+ })
2577
+ )
2578
+ )),
2579
+ $i(e, c) && f(d, u - 1, t.loop, c),
2580
+ (o = r),
2581
+ (c = e);
2582
+ }
2583
+ d < u - 1 && f(d, u - 1, t.loop, c);
2584
+ }
2585
+ return h;
2586
+ })(t, e, i, s)
2587
+ : e;
2588
+ }
2589
+ function ji(t) {
2590
+ return {
2591
+ backgroundColor: t.backgroundColor,
2592
+ borderCapStyle: t.borderCapStyle,
2593
+ borderDash: t.borderDash,
2594
+ borderDashOffset: t.borderDashOffset,
2595
+ borderJoinStyle: t.borderJoinStyle,
2596
+ borderWidth: t.borderWidth,
2597
+ borderColor: t.borderColor,
2598
+ };
2599
+ }
2600
+ function $i(t, e) {
2601
+ return e && JSON.stringify(t) !== JSON.stringify(e);
2602
+ }
2603
+ var Yi = Object.freeze({
2604
+ __proto__: null,
2605
+ easingEffects: Ci,
2606
+ color: W,
2607
+ getHoverColor: N,
2608
+ noop: H,
2609
+ uid: j,
2610
+ isNullOrUndef: $,
2611
+ isArray: Y,
2612
+ isObject: U,
2613
+ isFinite: X,
2614
+ finiteOrDefault: q,
2615
+ valueOrDefault: K,
2616
+ toPercentage: G,
2617
+ toDimension: Z,
2618
+ callback: J,
2619
+ each: Q,
2620
+ _elementsEqual: tt,
2621
+ clone: et,
2622
+ _merger: st,
2623
+ merge: nt,
2624
+ mergeIf: ot,
2625
+ _mergerIf: at,
2626
+ _deprecated: function (t, e, i, s) {
2627
+ void 0 !== e &&
2628
+ console.warn(
2629
+ t + ': "' + i + '" is deprecated. Please use "' + s + '" instead'
2630
+ );
2631
+ },
2632
+ resolveObjectKey: lt,
2633
+ _capitalize: ht,
2634
+ defined: ct,
2635
+ isFunction: dt,
2636
+ setsEqual: ut,
2637
+ _isClickEvent: ft,
2638
+ toFontString: Ut,
2639
+ _measureText: Xt,
2640
+ _longestText: qt,
2641
+ _alignPixel: Kt,
2642
+ clearCanvas: Gt,
2643
+ drawPoint: Zt,
2644
+ _isPointInArea: Jt,
2645
+ clipArea: Qt,
2646
+ unclipArea: te,
2647
+ _steppedLineTo: ee,
2648
+ _bezierCurveTo: ie,
2649
+ renderText: se,
2650
+ addRoundedRectPath: oe,
2651
+ _lookup: ae,
2652
+ _lookupByKey: re,
2653
+ _rlookupByKey: le,
2654
+ _filterBetween: he,
2655
+ listenArrayEvents: de,
2656
+ unlistenArrayEvents: ue,
2657
+ _arrayUnique: fe,
2658
+ _createResolver: oi,
2659
+ _attachContext: ai,
2660
+ _descriptors: ri,
2661
+ splineCurve: vi,
2662
+ splineCurveMonotone: wi,
2663
+ _updateBezierControlPoints: ki,
2664
+ _isDomSupported: ge,
2665
+ _getParentNode: pe,
2666
+ getStyle: be,
2667
+ getRelativePosition: ve,
2668
+ getMaximumSize: Me,
2669
+ retinaScale: ke,
2670
+ supportsEventListenerOptions: Se,
2671
+ readUsedSize: Pe,
2672
+ fontString: function (t, e, i) {
2673
+ return e + " " + t + "px " + i;
2674
+ },
2675
+ requestAnimFrame: t,
2676
+ throttled: e,
2677
+ debounce: i,
2678
+ _toLeftRightCenter: s,
2679
+ _alignStartEnd: n,
2680
+ _textX: o,
2681
+ _pointInLine: Oi,
2682
+ _steppedInterpolation: Ai,
2683
+ _bezierInterpolation: Ti,
2684
+ formatNumber: Ri,
2685
+ toLineHeight: Fe,
2686
+ _readValueToProps: Be,
2687
+ toTRBL: Ve,
2688
+ toTRBLCorners: We,
2689
+ toPadding: Ne,
2690
+ toFont: He,
2691
+ resolve: je,
2692
+ _addGrace: $e,
2693
+ createContext: Ye,
2694
+ PI: _t,
2695
+ TAU: yt,
2696
+ PITAU: vt,
2697
+ INFINITY: wt,
2698
+ RAD_PER_DEG: Mt,
2699
+ HALF_PI: kt,
2700
+ QUARTER_PI: St,
2701
+ TWO_THIRDS_PI: Pt,
2702
+ log10: Dt,
2703
+ sign: Ct,
2704
+ niceNum: Ot,
2705
+ _factorize: At,
2706
+ isNumber: Tt,
2707
+ almostEquals: Lt,
2708
+ almostWhole: Rt,
2709
+ _setMinAndMaxByKey: Et,
2710
+ toRadians: It,
2711
+ toDegrees: zt,
2712
+ _decimalPlaces: Ft,
2713
+ getAngleFromPoint: Bt,
2714
+ distanceBetweenPoints: Vt,
2715
+ _angleDiff: Wt,
2716
+ _normalizeAngle: Nt,
2717
+ _angleBetween: Ht,
2718
+ _limitValue: jt,
2719
+ _int16Range: $t,
2720
+ _isBetween: Yt,
2721
+ getRtlAdapter: Ei,
2722
+ overrideTextDirection: Ii,
2723
+ restoreTextDirection: zi,
2724
+ _boundSegment: Vi,
2725
+ _boundSegments: Wi,
2726
+ _computeSegments: Ni,
2727
+ });
2728
+ class Ui {
2729
+ acquireContext(t, e) {}
2730
+ releaseContext(t) {
2731
+ return !1;
2732
+ }
2733
+ addEventListener(t, e, i) {}
2734
+ removeEventListener(t, e, i) {}
2735
+ getDevicePixelRatio() {
2736
+ return 1;
2737
+ }
2738
+ getMaximumSize(t, e, i, s) {
2739
+ return (
2740
+ (e = Math.max(0, e || t.width)),
2741
+ (i = i || t.height),
2742
+ { width: e, height: Math.max(0, s ? Math.floor(e / s) : i) }
2743
+ );
2744
+ }
2745
+ isAttached(t) {
2746
+ return !0;
2747
+ }
2748
+ updateConfig(t) {}
2749
+ }
2750
+ class Xi extends Ui {
2751
+ acquireContext(t) {
2752
+ return (t && t.getContext && t.getContext("2d")) || null;
2753
+ }
2754
+ updateConfig(t) {
2755
+ t.options.animation = !1;
2756
+ }
2757
+ }
2758
+ const qi = {
2759
+ touchstart: "mousedown",
2760
+ touchmove: "mousemove",
2761
+ touchend: "mouseup",
2762
+ pointerenter: "mouseenter",
2763
+ pointerdown: "mousedown",
2764
+ pointermove: "mousemove",
2765
+ pointerup: "mouseup",
2766
+ pointerleave: "mouseout",
2767
+ pointerout: "mouseout",
2768
+ },
2769
+ Ki = (t) => null === t || "" === t;
2770
+ const Gi = !!Se && { passive: !0 };
2771
+ function Zi(t, e, i) {
2772
+ t.canvas.removeEventListener(e, i, Gi);
2773
+ }
2774
+ function Ji(t, e) {
2775
+ for (const i of t) if (i === e || i.contains(e)) return !0;
2776
+ }
2777
+ function Qi(t, e, i) {
2778
+ const s = t.canvas,
2779
+ n = new MutationObserver((t) => {
2780
+ let e = !1;
2781
+ for (const i of t)
2782
+ (e = e || Ji(i.addedNodes, s)), (e = e && !Ji(i.removedNodes, s));
2783
+ e && i();
2784
+ });
2785
+ return n.observe(document, { childList: !0, subtree: !0 }), n;
2786
+ }
2787
+ function ts(t, e, i) {
2788
+ const s = t.canvas,
2789
+ n = new MutationObserver((t) => {
2790
+ let e = !1;
2791
+ for (const i of t)
2792
+ (e = e || Ji(i.removedNodes, s)), (e = e && !Ji(i.addedNodes, s));
2793
+ e && i();
2794
+ });
2795
+ return n.observe(document, { childList: !0, subtree: !0 }), n;
2796
+ }
2797
+ const es = new Map();
2798
+ let is = 0;
2799
+ function ss() {
2800
+ const t = window.devicePixelRatio;
2801
+ t !== is &&
2802
+ ((is = t),
2803
+ es.forEach((e, i) => {
2804
+ i.currentDevicePixelRatio !== t && e();
2805
+ }));
2806
+ }
2807
+ function ns(t, i, s) {
2808
+ const n = t.canvas,
2809
+ o = n && pe(n);
2810
+ if (!o) return;
2811
+ const a = e((t, e) => {
2812
+ const i = o.clientWidth;
2813
+ s(t, e), i < o.clientWidth && s();
2814
+ }, window),
2815
+ r = new ResizeObserver((t) => {
2816
+ const e = t[0],
2817
+ i = e.contentRect.width,
2818
+ s = e.contentRect.height;
2819
+ (0 === i && 0 === s) || a(i, s);
2820
+ });
2821
+ return (
2822
+ r.observe(o),
2823
+ (function (t, e) {
2824
+ es.size || window.addEventListener("resize", ss), es.set(t, e);
2825
+ })(t, a),
2826
+ r
2827
+ );
2828
+ }
2829
+ function os(t, e, i) {
2830
+ i && i.disconnect(),
2831
+ "resize" === e &&
2832
+ (function (t) {
2833
+ es.delete(t), es.size || window.removeEventListener("resize", ss);
2834
+ })(t);
2835
+ }
2836
+ function as(t, i, s) {
2837
+ const n = t.canvas,
2838
+ o = e(
2839
+ (e) => {
2840
+ null !== t.ctx &&
2841
+ s(
2842
+ (function (t, e) {
2843
+ const i = qi[t.type] || t.type,
2844
+ { x: s, y: n } = ve(t, e);
2845
+ return {
2846
+ type: i,
2847
+ chart: e,
2848
+ native: t,
2849
+ x: void 0 !== s ? s : null,
2850
+ y: void 0 !== n ? n : null,
2851
+ };
2852
+ })(e, t)
2853
+ );
2854
+ },
2855
+ t,
2856
+ (t) => {
2857
+ const e = t[0];
2858
+ return [e, e.offsetX, e.offsetY];
2859
+ }
2860
+ );
2861
+ return (
2862
+ (function (t, e, i) {
2863
+ t.addEventListener(e, i, Gi);
2864
+ })(n, i, o),
2865
+ o
2866
+ );
2867
+ }
2868
+ class rs extends Ui {
2869
+ acquireContext(t, e) {
2870
+ const i = t && t.getContext && t.getContext("2d");
2871
+ return i && i.canvas === t
2872
+ ? ((function (t, e) {
2873
+ const i = t.style,
2874
+ s = t.getAttribute("height"),
2875
+ n = t.getAttribute("width");
2876
+ if (
2877
+ ((t.$chartjs = {
2878
+ initial: {
2879
+ height: s,
2880
+ width: n,
2881
+ style: {
2882
+ display: i.display,
2883
+ height: i.height,
2884
+ width: i.width,
2885
+ },
2886
+ },
2887
+ }),
2888
+ (i.display = i.display || "block"),
2889
+ (i.boxSizing = i.boxSizing || "border-box"),
2890
+ Ki(n))
2891
+ ) {
2892
+ const e = Pe(t, "width");
2893
+ void 0 !== e && (t.width = e);
2894
+ }
2895
+ if (Ki(s))
2896
+ if ("" === t.style.height) t.height = t.width / (e || 2);
2897
+ else {
2898
+ const e = Pe(t, "height");
2899
+ void 0 !== e && (t.height = e);
2900
+ }
2901
+ })(t, e),
2902
+ i)
2903
+ : null;
2904
+ }
2905
+ releaseContext(t) {
2906
+ const e = t.canvas;
2907
+ if (!e.$chartjs) return !1;
2908
+ const i = e.$chartjs.initial;
2909
+ ["height", "width"].forEach((t) => {
2910
+ const s = i[t];
2911
+ $(s) ? e.removeAttribute(t) : e.setAttribute(t, s);
2912
+ });
2913
+ const s = i.style || {};
2914
+ return (
2915
+ Object.keys(s).forEach((t) => {
2916
+ e.style[t] = s[t];
2917
+ }),
2918
+ (e.width = e.width),
2919
+ delete e.$chartjs,
2920
+ !0
2921
+ );
2922
+ }
2923
+ addEventListener(t, e, i) {
2924
+ this.removeEventListener(t, e);
2925
+ const s = t.$proxies || (t.$proxies = {}),
2926
+ n = { attach: Qi, detach: ts, resize: ns }[e] || as;
2927
+ s[e] = n(t, e, i);
2928
+ }
2929
+ removeEventListener(t, e) {
2930
+ const i = t.$proxies || (t.$proxies = {}),
2931
+ s = i[e];
2932
+ if (!s) return;
2933
+ (({ attach: os, detach: os, resize: os }[e] || Zi)(t, e, s),
2934
+ (i[e] = void 0));
2935
+ }
2936
+ getDevicePixelRatio() {
2937
+ return window.devicePixelRatio;
2938
+ }
2939
+ getMaximumSize(t, e, i, s) {
2940
+ return Me(t, e, i, s);
2941
+ }
2942
+ isAttached(t) {
2943
+ const e = pe(t);
2944
+ return !(!e || !e.isConnected);
2945
+ }
2946
+ }
2947
+ function ls(t) {
2948
+ return !ge() ||
2949
+ ("undefined" != typeof OffscreenCanvas && t instanceof OffscreenCanvas)
2950
+ ? Xi
2951
+ : rs;
2952
+ }
2953
+ var hs = Object.freeze({
2954
+ __proto__: null,
2955
+ _detectPlatform: ls,
2956
+ BasePlatform: Ui,
2957
+ BasicPlatform: Xi,
2958
+ DomPlatform: rs,
2959
+ });
2960
+ const cs = "transparent",
2961
+ ds = {
2962
+ boolean: (t, e, i) => (i > 0.5 ? e : t),
2963
+ color(t, e, i) {
2964
+ const s = W(t || cs),
2965
+ n = s.valid && W(e || cs);
2966
+ return n && n.valid ? n.mix(s, i).hexString() : e;
2967
+ },
2968
+ number: (t, e, i) => t + (e - t) * i,
2969
+ };
2970
+ class us {
2971
+ constructor(t, e, i, s) {
2972
+ const n = e[i];
2973
+ s = je([t.to, s, n, t.from]);
2974
+ const o = je([t.from, n, s]);
2975
+ (this._active = !0),
2976
+ (this._fn = t.fn || ds[t.type || typeof o]),
2977
+ (this._easing = Ci[t.easing] || Ci.linear),
2978
+ (this._start = Math.floor(Date.now() + (t.delay || 0))),
2979
+ (this._duration = this._total = Math.floor(t.duration)),
2980
+ (this._loop = !!t.loop),
2981
+ (this._target = e),
2982
+ (this._prop = i),
2983
+ (this._from = o),
2984
+ (this._to = s),
2985
+ (this._promises = void 0);
2986
+ }
2987
+ active() {
2988
+ return this._active;
2989
+ }
2990
+ update(t, e, i) {
2991
+ if (this._active) {
2992
+ this._notify(!1);
2993
+ const s = this._target[this._prop],
2994
+ n = i - this._start,
2995
+ o = this._duration - n;
2996
+ (this._start = i),
2997
+ (this._duration = Math.floor(Math.max(o, t.duration))),
2998
+ (this._total += n),
2999
+ (this._loop = !!t.loop),
3000
+ (this._to = je([t.to, e, s, t.from])),
3001
+ (this._from = je([t.from, s, e]));
3002
+ }
3003
+ }
3004
+ cancel() {
3005
+ this._active &&
3006
+ (this.tick(Date.now()), (this._active = !1), this._notify(!1));
3007
+ }
3008
+ tick(t) {
3009
+ const e = t - this._start,
3010
+ i = this._duration,
3011
+ s = this._prop,
3012
+ n = this._from,
3013
+ o = this._loop,
3014
+ a = this._to;
3015
+ let r;
3016
+ if (((this._active = n !== a && (o || e < i)), !this._active))
3017
+ return (this._target[s] = a), void this._notify(!0);
3018
+ e < 0
3019
+ ? (this._target[s] = n)
3020
+ : ((r = (e / i) % 2),
3021
+ (r = o && r > 1 ? 2 - r : r),
3022
+ (r = this._easing(Math.min(1, Math.max(0, r)))),
3023
+ (this._target[s] = this._fn(n, a, r)));
3024
+ }
3025
+ wait() {
3026
+ const t = this._promises || (this._promises = []);
3027
+ return new Promise((e, i) => {
3028
+ t.push({ res: e, rej: i });
3029
+ });
3030
+ }
3031
+ _notify(t) {
3032
+ const e = t ? "res" : "rej",
3033
+ i = this._promises || [];
3034
+ for (let t = 0; t < i.length; t++) i[t][e]();
3035
+ }
3036
+ }
3037
+ bt.set("animation", {
3038
+ delay: void 0,
3039
+ duration: 1e3,
3040
+ easing: "easeOutQuart",
3041
+ fn: void 0,
3042
+ from: void 0,
3043
+ loop: void 0,
3044
+ to: void 0,
3045
+ type: void 0,
3046
+ });
3047
+ const fs = Object.keys(bt.animation);
3048
+ bt.describe("animation", {
3049
+ _fallback: !1,
3050
+ _indexable: !1,
3051
+ _scriptable: (t) => "onProgress" !== t && "onComplete" !== t && "fn" !== t,
3052
+ }),
3053
+ bt.set("animations", {
3054
+ colors: {
3055
+ type: "color",
3056
+ properties: ["color", "borderColor", "backgroundColor"],
3057
+ },
3058
+ numbers: {
3059
+ type: "number",
3060
+ properties: ["x", "y", "borderWidth", "radius", "tension"],
3061
+ },
3062
+ }),
3063
+ bt.describe("animations", { _fallback: "animation" }),
3064
+ bt.set("transitions", {
3065
+ active: { animation: { duration: 400 } },
3066
+ resize: { animation: { duration: 0 } },
3067
+ show: {
3068
+ animations: {
3069
+ colors: { from: "transparent" },
3070
+ visible: { type: "boolean", duration: 0 },
3071
+ },
3072
+ },
3073
+ hide: {
3074
+ animations: {
3075
+ colors: { to: "transparent" },
3076
+ visible: { type: "boolean", easing: "linear", fn: (t) => 0 | t },
3077
+ },
3078
+ },
3079
+ });
3080
+ class gs {
3081
+ constructor(t, e) {
3082
+ (this._chart = t), (this._properties = new Map()), this.configure(e);
3083
+ }
3084
+ configure(t) {
3085
+ if (!U(t)) return;
3086
+ const e = this._properties;
3087
+ Object.getOwnPropertyNames(t).forEach((i) => {
3088
+ const s = t[i];
3089
+ if (!U(s)) return;
3090
+ const n = {};
3091
+ for (const t of fs) n[t] = s[t];
3092
+ ((Y(s.properties) && s.properties) || [i]).forEach((t) => {
3093
+ (t !== i && e.has(t)) || e.set(t, n);
3094
+ });
3095
+ });
3096
+ }
3097
+ _animateOptions(t, e) {
3098
+ const i = e.options,
3099
+ s = (function (t, e) {
3100
+ if (!e) return;
3101
+ let i = t.options;
3102
+ if (!i) return void (t.options = e);
3103
+ i.$shared &&
3104
+ (t.options = i =
3105
+ Object.assign({}, i, { $shared: !1, $animations: {} }));
3106
+ return i;
3107
+ })(t, i);
3108
+ if (!s) return [];
3109
+ const n = this._createAnimations(s, i);
3110
+ return (
3111
+ i.$shared &&
3112
+ (function (t, e) {
3113
+ const i = [],
3114
+ s = Object.keys(e);
3115
+ for (let e = 0; e < s.length; e++) {
3116
+ const n = t[s[e]];
3117
+ n && n.active() && i.push(n.wait());
3118
+ }
3119
+ return Promise.all(i);
3120
+ })(t.options.$animations, i).then(
3121
+ () => {
3122
+ t.options = i;
3123
+ },
3124
+ () => {}
3125
+ ),
3126
+ n
3127
+ );
3128
+ }
3129
+ _createAnimations(t, e) {
3130
+ const i = this._properties,
3131
+ s = [],
3132
+ n = t.$animations || (t.$animations = {}),
3133
+ o = Object.keys(e),
3134
+ a = Date.now();
3135
+ let r;
3136
+ for (r = o.length - 1; r >= 0; --r) {
3137
+ const l = o[r];
3138
+ if ("$" === l.charAt(0)) continue;
3139
+ if ("options" === l) {
3140
+ s.push(...this._animateOptions(t, e));
3141
+ continue;
3142
+ }
3143
+ const h = e[l];
3144
+ let c = n[l];
3145
+ const d = i.get(l);
3146
+ if (c) {
3147
+ if (d && c.active()) {
3148
+ c.update(d, h, a);
3149
+ continue;
3150
+ }
3151
+ c.cancel();
3152
+ }
3153
+ d && d.duration
3154
+ ? ((n[l] = c = new us(d, t, l, h)), s.push(c))
3155
+ : (t[l] = h);
3156
+ }
3157
+ return s;
3158
+ }
3159
+ update(t, e) {
3160
+ if (0 === this._properties.size) return void Object.assign(t, e);
3161
+ const i = this._createAnimations(t, e);
3162
+ return i.length ? (a.add(this._chart, i), !0) : void 0;
3163
+ }
3164
+ }
3165
+ function ps(t, e) {
3166
+ const i = (t && t.options) || {},
3167
+ s = i.reverse,
3168
+ n = void 0 === i.min ? e : 0,
3169
+ o = void 0 === i.max ? e : 0;
3170
+ return { start: s ? o : n, end: s ? n : o };
3171
+ }
3172
+ function ms(t, e) {
3173
+ const i = [],
3174
+ s = t._getSortedDatasetMetas(e);
3175
+ let n, o;
3176
+ for (n = 0, o = s.length; n < o; ++n) i.push(s[n].index);
3177
+ return i;
3178
+ }
3179
+ function xs(t, e, i, s = {}) {
3180
+ const n = t.keys,
3181
+ o = "single" === s.mode;
3182
+ let a, r, l, h;
3183
+ if (null !== e) {
3184
+ for (a = 0, r = n.length; a < r; ++a) {
3185
+ if (((l = +n[a]), l === i)) {
3186
+ if (s.all) continue;
3187
+ break;
3188
+ }
3189
+ (h = t.values[l]),
3190
+ X(h) && (o || 0 === e || Ct(e) === Ct(h)) && (e += h);
3191
+ }
3192
+ return e;
3193
+ }
3194
+ }
3195
+ function bs(t, e) {
3196
+ const i = t && t.options.stacked;
3197
+ return i || (void 0 === i && void 0 !== e.stack);
3198
+ }
3199
+ function _s(t, e, i) {
3200
+ const s = t[e] || (t[e] = {});
3201
+ return s[i] || (s[i] = {});
3202
+ }
3203
+ function ys(t, e, i, s) {
3204
+ for (const n of e.getMatchingVisibleMetas(s).reverse()) {
3205
+ const e = t[n.index];
3206
+ if ((i && e > 0) || (!i && e < 0)) return n.index;
3207
+ }
3208
+ return null;
3209
+ }
3210
+ function vs(t, e) {
3211
+ const { chart: i, _cachedMeta: s } = t,
3212
+ n = i._stacks || (i._stacks = {}),
3213
+ { iScale: o, vScale: a, index: r } = s,
3214
+ l = o.axis,
3215
+ h = a.axis,
3216
+ c = (function (t, e, i) {
3217
+ return `${t.id}.${e.id}.${i.stack || i.type}`;
3218
+ })(o, a, s),
3219
+ d = e.length;
3220
+ let u;
3221
+ for (let t = 0; t < d; ++t) {
3222
+ const i = e[t],
3223
+ { [l]: o, [h]: d } = i;
3224
+ (u = (i._stacks || (i._stacks = {}))[h] = _s(n, c, o)),
3225
+ (u[r] = d),
3226
+ (u._top = ys(u, a, !0, s.type)),
3227
+ (u._bottom = ys(u, a, !1, s.type));
3228
+ }
3229
+ }
3230
+ function ws(t, e) {
3231
+ const i = t.scales;
3232
+ return Object.keys(i)
3233
+ .filter((t) => i[t].axis === e)
3234
+ .shift();
3235
+ }
3236
+ function Ms(t, e) {
3237
+ const i = t.controller.index,
3238
+ s = t.vScale && t.vScale.axis;
3239
+ if (s) {
3240
+ e = e || t._parsed;
3241
+ for (const t of e) {
3242
+ const e = t._stacks;
3243
+ if (!e || void 0 === e[s] || void 0 === e[s][i]) return;
3244
+ delete e[s][i];
3245
+ }
3246
+ }
3247
+ }
3248
+ const ks = (t) => "reset" === t || "none" === t,
3249
+ Ss = (t, e) => (e ? t : Object.assign({}, t));
3250
+ class Ps {
3251
+ constructor(t, e) {
3252
+ (this.chart = t),
3253
+ (this._ctx = t.ctx),
3254
+ (this.index = e),
3255
+ (this._cachedDataOpts = {}),
3256
+ (this._cachedMeta = this.getMeta()),
3257
+ (this._type = this._cachedMeta.type),
3258
+ (this.options = void 0),
3259
+ (this._parsing = !1),
3260
+ (this._data = void 0),
3261
+ (this._objectData = void 0),
3262
+ (this._sharedOptions = void 0),
3263
+ (this._drawStart = void 0),
3264
+ (this._drawCount = void 0),
3265
+ (this.enableOptionSharing = !1),
3266
+ (this.$context = void 0),
3267
+ (this._syncList = []),
3268
+ this.initialize();
3269
+ }
3270
+ initialize() {
3271
+ const t = this._cachedMeta;
3272
+ this.configure(),
3273
+ this.linkScales(),
3274
+ (t._stacked = bs(t.vScale, t)),
3275
+ this.addElements();
3276
+ }
3277
+ updateIndex(t) {
3278
+ this.index !== t && Ms(this._cachedMeta), (this.index = t);
3279
+ }
3280
+ linkScales() {
3281
+ const t = this.chart,
3282
+ e = this._cachedMeta,
3283
+ i = this.getDataset(),
3284
+ s = (t, e, i, s) => ("x" === t ? e : "r" === t ? s : i),
3285
+ n = (e.xAxisID = K(i.xAxisID, ws(t, "x"))),
3286
+ o = (e.yAxisID = K(i.yAxisID, ws(t, "y"))),
3287
+ a = (e.rAxisID = K(i.rAxisID, ws(t, "r"))),
3288
+ r = e.indexAxis,
3289
+ l = (e.iAxisID = s(r, n, o, a)),
3290
+ h = (e.vAxisID = s(r, o, n, a));
3291
+ (e.xScale = this.getScaleForId(n)),
3292
+ (e.yScale = this.getScaleForId(o)),
3293
+ (e.rScale = this.getScaleForId(a)),
3294
+ (e.iScale = this.getScaleForId(l)),
3295
+ (e.vScale = this.getScaleForId(h));
3296
+ }
3297
+ getDataset() {
3298
+ return this.chart.data.datasets[this.index];
3299
+ }
3300
+ getMeta() {
3301
+ return this.chart.getDatasetMeta(this.index);
3302
+ }
3303
+ getScaleForId(t) {
3304
+ return this.chart.scales[t];
3305
+ }
3306
+ _getOtherScale(t) {
3307
+ const e = this._cachedMeta;
3308
+ return t === e.iScale ? e.vScale : e.iScale;
3309
+ }
3310
+ reset() {
3311
+ this._update("reset");
3312
+ }
3313
+ _destroy() {
3314
+ const t = this._cachedMeta;
3315
+ this._data && ue(this._data, this), t._stacked && Ms(t);
3316
+ }
3317
+ _dataCheck() {
3318
+ const t = this.getDataset(),
3319
+ e = t.data || (t.data = []),
3320
+ i = this._data;
3321
+ if (U(e))
3322
+ this._data = (function (t) {
3323
+ const e = Object.keys(t),
3324
+ i = new Array(e.length);
3325
+ let s, n, o;
3326
+ for (s = 0, n = e.length; s < n; ++s)
3327
+ (o = e[s]), (i[s] = { x: o, y: t[o] });
3328
+ return i;
3329
+ })(e);
3330
+ else if (i !== e) {
3331
+ if (i) {
3332
+ ue(i, this);
3333
+ const t = this._cachedMeta;
3334
+ Ms(t), (t._parsed = []);
3335
+ }
3336
+ e && Object.isExtensible(e) && de(e, this),
3337
+ (this._syncList = []),
3338
+ (this._data = e);
3339
+ }
3340
+ }
3341
+ addElements() {
3342
+ const t = this._cachedMeta;
3343
+ this._dataCheck(),
3344
+ this.datasetElementType && (t.dataset = new this.datasetElementType());
3345
+ }
3346
+ buildOrUpdateElements(t) {
3347
+ const e = this._cachedMeta,
3348
+ i = this.getDataset();
3349
+ let s = !1;
3350
+ this._dataCheck();
3351
+ const n = e._stacked;
3352
+ (e._stacked = bs(e.vScale, e)),
3353
+ e.stack !== i.stack && ((s = !0), Ms(e), (e.stack = i.stack)),
3354
+ this._resyncElements(t),
3355
+ (s || n !== e._stacked) && vs(this, e._parsed);
3356
+ }
3357
+ configure() {
3358
+ const t = this.chart.config,
3359
+ e = t.datasetScopeKeys(this._type),
3360
+ i = t.getOptionScopes(this.getDataset(), e, !0);
3361
+ (this.options = t.createResolver(i, this.getContext())),
3362
+ (this._parsing = this.options.parsing),
3363
+ (this._cachedDataOpts = {});
3364
+ }
3365
+ parse(t, e) {
3366
+ const { _cachedMeta: i, _data: s } = this,
3367
+ { iScale: n, _stacked: o } = i,
3368
+ a = n.axis;
3369
+ let r,
3370
+ l,
3371
+ h,
3372
+ c = (0 === t && e === s.length) || i._sorted,
3373
+ d = t > 0 && i._parsed[t - 1];
3374
+ if (!1 === this._parsing) (i._parsed = s), (i._sorted = !0), (h = s);
3375
+ else {
3376
+ h = Y(s[t])
3377
+ ? this.parseArrayData(i, s, t, e)
3378
+ : U(s[t])
3379
+ ? this.parseObjectData(i, s, t, e)
3380
+ : this.parsePrimitiveData(i, s, t, e);
3381
+ const n = () => null === l[a] || (d && l[a] < d[a]);
3382
+ for (r = 0; r < e; ++r)
3383
+ (i._parsed[r + t] = l = h[r]), c && (n() && (c = !1), (d = l));
3384
+ i._sorted = c;
3385
+ }
3386
+ o && vs(this, h);
3387
+ }
3388
+ parsePrimitiveData(t, e, i, s) {
3389
+ const { iScale: n, vScale: o } = t,
3390
+ a = n.axis,
3391
+ r = o.axis,
3392
+ l = n.getLabels(),
3393
+ h = n === o,
3394
+ c = new Array(s);
3395
+ let d, u, f;
3396
+ for (d = 0, u = s; d < u; ++d)
3397
+ (f = d + i),
3398
+ (c[d] = { [a]: h || n.parse(l[f], f), [r]: o.parse(e[f], f) });
3399
+ return c;
3400
+ }
3401
+ parseArrayData(t, e, i, s) {
3402
+ const { xScale: n, yScale: o } = t,
3403
+ a = new Array(s);
3404
+ let r, l, h, c;
3405
+ for (r = 0, l = s; r < l; ++r)
3406
+ (h = r + i),
3407
+ (c = e[h]),
3408
+ (a[r] = { x: n.parse(c[0], h), y: o.parse(c[1], h) });
3409
+ return a;
3410
+ }
3411
+ parseObjectData(t, e, i, s) {
3412
+ const { xScale: n, yScale: o } = t,
3413
+ { xAxisKey: a = "x", yAxisKey: r = "y" } = this._parsing,
3414
+ l = new Array(s);
3415
+ let h, c, d, u;
3416
+ for (h = 0, c = s; h < c; ++h)
3417
+ (d = h + i),
3418
+ (u = e[d]),
3419
+ (l[h] = { x: n.parse(lt(u, a), d), y: o.parse(lt(u, r), d) });
3420
+ return l;
3421
+ }
3422
+ getParsed(t) {
3423
+ return this._cachedMeta._parsed[t];
3424
+ }
3425
+ getDataElement(t) {
3426
+ return this._cachedMeta.data[t];
3427
+ }
3428
+ applyStack(t, e, i) {
3429
+ const s = this.chart,
3430
+ n = this._cachedMeta,
3431
+ o = e[t.axis];
3432
+ return xs({ keys: ms(s, !0), values: e._stacks[t.axis] }, o, n.index, {
3433
+ mode: i,
3434
+ });
3435
+ }
3436
+ updateRangeFromParsed(t, e, i, s) {
3437
+ const n = i[e.axis];
3438
+ let o = null === n ? NaN : n;
3439
+ const a = s && i._stacks[e.axis];
3440
+ s && a && ((s.values = a), (o = xs(s, n, this._cachedMeta.index))),
3441
+ (t.min = Math.min(t.min, o)),
3442
+ (t.max = Math.max(t.max, o));
3443
+ }
3444
+ getMinMax(t, e) {
3445
+ const i = this._cachedMeta,
3446
+ s = i._parsed,
3447
+ n = i._sorted && t === i.iScale,
3448
+ o = s.length,
3449
+ a = this._getOtherScale(t),
3450
+ r = ((t, e, i) =>
3451
+ t && !e.hidden && e._stacked && { keys: ms(i, !0), values: null })(
3452
+ e,
3453
+ i,
3454
+ this.chart
3455
+ ),
3456
+ l = { min: Number.POSITIVE_INFINITY, max: Number.NEGATIVE_INFINITY },
3457
+ { min: h, max: c } = (function (t) {
3458
+ const {
3459
+ min: e,
3460
+ max: i,
3461
+ minDefined: s,
3462
+ maxDefined: n,
3463
+ } = t.getUserBounds();
3464
+ return {
3465
+ min: s ? e : Number.NEGATIVE_INFINITY,
3466
+ max: n ? i : Number.POSITIVE_INFINITY,
3467
+ };
3468
+ })(a);
3469
+ let d, u;
3470
+ function f() {
3471
+ u = s[d];
3472
+ const e = u[a.axis];
3473
+ return !X(u[t.axis]) || h > e || c < e;
3474
+ }
3475
+ for (
3476
+ d = 0;
3477
+ d < o && (f() || (this.updateRangeFromParsed(l, t, u, r), !n));
3478
+ ++d
3479
+ );
3480
+ if (n)
3481
+ for (d = o - 1; d >= 0; --d)
3482
+ if (!f()) {
3483
+ this.updateRangeFromParsed(l, t, u, r);
3484
+ break;
3485
+ }
3486
+ return l;
3487
+ }
3488
+ getAllParsedValues(t) {
3489
+ const e = this._cachedMeta._parsed,
3490
+ i = [];
3491
+ let s, n, o;
3492
+ for (s = 0, n = e.length; s < n; ++s)
3493
+ (o = e[s][t.axis]), X(o) && i.push(o);
3494
+ return i;
3495
+ }
3496
+ getMaxOverflow() {
3497
+ return !1;
3498
+ }
3499
+ getLabelAndValue(t) {
3500
+ const e = this._cachedMeta,
3501
+ i = e.iScale,
3502
+ s = e.vScale,
3503
+ n = this.getParsed(t);
3504
+ return {
3505
+ label: i ? "" + i.getLabelForValue(n[i.axis]) : "",
3506
+ value: s ? "" + s.getLabelForValue(n[s.axis]) : "",
3507
+ };
3508
+ }
3509
+ _update(t) {
3510
+ const e = this._cachedMeta;
3511
+ this.update(t || "default"),
3512
+ (e._clip = (function (t) {
3513
+ let e, i, s, n;
3514
+ return (
3515
+ U(t)
3516
+ ? ((e = t.top), (i = t.right), (s = t.bottom), (n = t.left))
3517
+ : (e = i = s = n = t),
3518
+ { top: e, right: i, bottom: s, left: n, disabled: !1 === t }
3519
+ );
3520
+ })(
3521
+ K(
3522
+ this.options.clip,
3523
+ (function (t, e, i) {
3524
+ if (!1 === i) return !1;
3525
+ const s = ps(t, i),
3526
+ n = ps(e, i);
3527
+ return {
3528
+ top: n.end,
3529
+ right: s.end,
3530
+ bottom: n.start,
3531
+ left: s.start,
3532
+ };
3533
+ })(e.xScale, e.yScale, this.getMaxOverflow())
3534
+ )
3535
+ ));
3536
+ }
3537
+ update(t) {}
3538
+ draw() {
3539
+ const t = this._ctx,
3540
+ e = this.chart,
3541
+ i = this._cachedMeta,
3542
+ s = i.data || [],
3543
+ n = e.chartArea,
3544
+ o = [],
3545
+ a = this._drawStart || 0,
3546
+ r = this._drawCount || s.length - a,
3547
+ l = this.options.drawActiveElementsOnTop;
3548
+ let h;
3549
+ for (i.dataset && i.dataset.draw(t, n, a, r), h = a; h < a + r; ++h) {
3550
+ const e = s[h];
3551
+ e.hidden || (e.active && l ? o.push(e) : e.draw(t, n));
3552
+ }
3553
+ for (h = 0; h < o.length; ++h) o[h].draw(t, n);
3554
+ }
3555
+ getStyle(t, e) {
3556
+ const i = e ? "active" : "default";
3557
+ return void 0 === t && this._cachedMeta.dataset
3558
+ ? this.resolveDatasetElementOptions(i)
3559
+ : this.resolveDataElementOptions(t || 0, i);
3560
+ }
3561
+ getContext(t, e, i) {
3562
+ const s = this.getDataset();
3563
+ let n;
3564
+ if (t >= 0 && t < this._cachedMeta.data.length) {
3565
+ const e = this._cachedMeta.data[t];
3566
+ (n =
3567
+ e.$context ||
3568
+ (e.$context = (function (t, e, i) {
3569
+ return Ye(t, {
3570
+ active: !1,
3571
+ dataIndex: e,
3572
+ parsed: void 0,
3573
+ raw: void 0,
3574
+ element: i,
3575
+ index: e,
3576
+ mode: "default",
3577
+ type: "data",
3578
+ });
3579
+ })(this.getContext(), t, e))),
3580
+ (n.parsed = this.getParsed(t)),
3581
+ (n.raw = s.data[t]),
3582
+ (n.index = n.dataIndex = t);
3583
+ } else
3584
+ (n =
3585
+ this.$context ||
3586
+ (this.$context = (function (t, e) {
3587
+ return Ye(t, {
3588
+ active: !1,
3589
+ dataset: void 0,
3590
+ datasetIndex: e,
3591
+ index: e,
3592
+ mode: "default",
3593
+ type: "dataset",
3594
+ });
3595
+ })(this.chart.getContext(), this.index))),
3596
+ (n.dataset = s),
3597
+ (n.index = n.datasetIndex = this.index);
3598
+ return (n.active = !!e), (n.mode = i), n;
3599
+ }
3600
+ resolveDatasetElementOptions(t) {
3601
+ return this._resolveElementOptions(this.datasetElementType.id, t);
3602
+ }
3603
+ resolveDataElementOptions(t, e) {
3604
+ return this._resolveElementOptions(this.dataElementType.id, e, t);
3605
+ }
3606
+ _resolveElementOptions(t, e = "default", i) {
3607
+ const s = "active" === e,
3608
+ n = this._cachedDataOpts,
3609
+ o = t + "-" + e,
3610
+ a = n[o],
3611
+ r = this.enableOptionSharing && ct(i);
3612
+ if (a) return Ss(a, r);
3613
+ const l = this.chart.config,
3614
+ h = l.datasetElementScopeKeys(this._type, t),
3615
+ c = s ? [`${t}Hover`, "hover", t, ""] : [t, ""],
3616
+ d = l.getOptionScopes(this.getDataset(), h),
3617
+ u = Object.keys(bt.elements[t]),
3618
+ f = l.resolveNamedOptions(d, u, () => this.getContext(i, s), c);
3619
+ return (
3620
+ f.$shared && ((f.$shared = r), (n[o] = Object.freeze(Ss(f, r)))), f
3621
+ );
3622
+ }
3623
+ _resolveAnimations(t, e, i) {
3624
+ const s = this.chart,
3625
+ n = this._cachedDataOpts,
3626
+ o = `animation-${e}`,
3627
+ a = n[o];
3628
+ if (a) return a;
3629
+ let r;
3630
+ if (!1 !== s.options.animation) {
3631
+ const s = this.chart.config,
3632
+ n = s.datasetAnimationScopeKeys(this._type, e),
3633
+ o = s.getOptionScopes(this.getDataset(), n);
3634
+ r = s.createResolver(o, this.getContext(t, i, e));
3635
+ }
3636
+ const l = new gs(s, r && r.animations);
3637
+ return r && r._cacheable && (n[o] = Object.freeze(l)), l;
3638
+ }
3639
+ getSharedOptions(t) {
3640
+ if (t.$shared)
3641
+ return (
3642
+ this._sharedOptions || (this._sharedOptions = Object.assign({}, t))
3643
+ );
3644
+ }
3645
+ includeOptions(t, e) {
3646
+ return !e || ks(t) || this.chart._animationsDisabled;
3647
+ }
3648
+ updateElement(t, e, i, s) {
3649
+ ks(s) ? Object.assign(t, i) : this._resolveAnimations(e, s).update(t, i);
3650
+ }
3651
+ updateSharedOptions(t, e, i) {
3652
+ t && !ks(e) && this._resolveAnimations(void 0, e).update(t, i);
3653
+ }
3654
+ _setStyle(t, e, i, s) {
3655
+ t.active = s;
3656
+ const n = this.getStyle(e, s);
3657
+ this._resolveAnimations(e, i, s).update(t, {
3658
+ options: (!s && this.getSharedOptions(n)) || n,
3659
+ });
3660
+ }
3661
+ removeHoverStyle(t, e, i) {
3662
+ this._setStyle(t, i, "active", !1);
3663
+ }
3664
+ setHoverStyle(t, e, i) {
3665
+ this._setStyle(t, i, "active", !0);
3666
+ }
3667
+ _removeDatasetHoverStyle() {
3668
+ const t = this._cachedMeta.dataset;
3669
+ t && this._setStyle(t, void 0, "active", !1);
3670
+ }
3671
+ _setDatasetHoverStyle() {
3672
+ const t = this._cachedMeta.dataset;
3673
+ t && this._setStyle(t, void 0, "active", !0);
3674
+ }
3675
+ _resyncElements(t) {
3676
+ const e = this._data,
3677
+ i = this._cachedMeta.data;
3678
+ for (const [t, e, i] of this._syncList) this[t](e, i);
3679
+ this._syncList = [];
3680
+ const s = i.length,
3681
+ n = e.length,
3682
+ o = Math.min(n, s);
3683
+ o && this.parse(0, o),
3684
+ n > s
3685
+ ? this._insertElements(s, n - s, t)
3686
+ : n < s && this._removeElements(n, s - n);
3687
+ }
3688
+ _insertElements(t, e, i = !0) {
3689
+ const s = this._cachedMeta,
3690
+ n = s.data,
3691
+ o = t + e;
3692
+ let a;
3693
+ const r = (t) => {
3694
+ for (t.length += e, a = t.length - 1; a >= o; a--) t[a] = t[a - e];
3695
+ };
3696
+ for (r(n), a = t; a < o; ++a) n[a] = new this.dataElementType();
3697
+ this._parsing && r(s._parsed),
3698
+ this.parse(t, e),
3699
+ i && this.updateElements(n, t, e, "reset");
3700
+ }
3701
+ updateElements(t, e, i, s) {}
3702
+ _removeElements(t, e) {
3703
+ const i = this._cachedMeta;
3704
+ if (this._parsing) {
3705
+ const s = i._parsed.splice(t, e);
3706
+ i._stacked && Ms(i, s);
3707
+ }
3708
+ i.data.splice(t, e);
3709
+ }
3710
+ _sync(t) {
3711
+ if (this._parsing) this._syncList.push(t);
3712
+ else {
3713
+ const [e, i, s] = t;
3714
+ this[e](i, s);
3715
+ }
3716
+ this.chart._dataChanges.push([this.index, ...t]);
3717
+ }
3718
+ _onDataPush() {
3719
+ const t = arguments.length;
3720
+ this._sync(["_insertElements", this.getDataset().data.length - t, t]);
3721
+ }
3722
+ _onDataPop() {
3723
+ this._sync(["_removeElements", this._cachedMeta.data.length - 1, 1]);
3724
+ }
3725
+ _onDataShift() {
3726
+ this._sync(["_removeElements", 0, 1]);
3727
+ }
3728
+ _onDataSplice(t, e) {
3729
+ e && this._sync(["_removeElements", t, e]);
3730
+ const i = arguments.length - 2;
3731
+ i && this._sync(["_insertElements", t, i]);
3732
+ }
3733
+ _onDataUnshift() {
3734
+ this._sync(["_insertElements", 0, arguments.length]);
3735
+ }
3736
+ }
3737
+ (Ps.defaults = {}),
3738
+ (Ps.prototype.datasetElementType = null),
3739
+ (Ps.prototype.dataElementType = null);
3740
+ class Ds {
3741
+ constructor() {
3742
+ (this.x = void 0),
3743
+ (this.y = void 0),
3744
+ (this.active = !1),
3745
+ (this.options = void 0),
3746
+ (this.$animations = void 0);
3747
+ }
3748
+ tooltipPosition(t) {
3749
+ const { x: e, y: i } = this.getProps(["x", "y"], t);
3750
+ return { x: e, y: i };
3751
+ }
3752
+ hasValue() {
3753
+ return Tt(this.x) && Tt(this.y);
3754
+ }
3755
+ getProps(t, e) {
3756
+ const i = this.$animations;
3757
+ if (!e || !i) return this;
3758
+ const s = {};
3759
+ return (
3760
+ t.forEach((t) => {
3761
+ s[t] = i[t] && i[t].active() ? i[t]._to : this[t];
3762
+ }),
3763
+ s
3764
+ );
3765
+ }
3766
+ }
3767
+ (Ds.defaults = {}), (Ds.defaultRoutes = void 0);
3768
+ const Cs = {
3769
+ values: (t) => (Y(t) ? t : "" + t),
3770
+ numeric(t, e, i) {
3771
+ if (0 === t) return "0";
3772
+ const s = this.chart.options.locale;
3773
+ let n,
3774
+ o = t;
3775
+ if (i.length > 1) {
3776
+ const e = Math.max(
3777
+ Math.abs(i[0].value),
3778
+ Math.abs(i[i.length - 1].value)
3779
+ );
3780
+ (e < 1e-4 || e > 1e15) && (n = "scientific"),
3781
+ (o = (function (t, e) {
3782
+ let i =
3783
+ e.length > 3 ? e[2].value - e[1].value : e[1].value - e[0].value;
3784
+ Math.abs(i) >= 1 && t !== Math.floor(t) && (i = t - Math.floor(t));
3785
+ return i;
3786
+ })(t, i));
3787
+ }
3788
+ const a = Dt(Math.abs(o)),
3789
+ r = Math.max(Math.min(-1 * Math.floor(a), 20), 0),
3790
+ l = { notation: n, minimumFractionDigits: r, maximumFractionDigits: r };
3791
+ return Object.assign(l, this.options.ticks.format), Ri(t, s, l);
3792
+ },
3793
+ logarithmic(t, e, i) {
3794
+ if (0 === t) return "0";
3795
+ const s = t / Math.pow(10, Math.floor(Dt(t)));
3796
+ return 1 === s || 2 === s || 5 === s
3797
+ ? Cs.numeric.call(this, t, e, i)
3798
+ : "";
3799
+ },
3800
+ };
3801
+ var Os = { formatters: Cs };
3802
+ function As(t, e) {
3803
+ const i = t.options.ticks,
3804
+ s =
3805
+ i.maxTicksLimit ||
3806
+ (function (t) {
3807
+ const e = t.options.offset,
3808
+ i = t._tickSize(),
3809
+ s = t._length / i + (e ? 0 : 1),
3810
+ n = t._maxLength / i;
3811
+ return Math.floor(Math.min(s, n));
3812
+ })(t),
3813
+ n = i.major.enabled
3814
+ ? (function (t) {
3815
+ const e = [];
3816
+ let i, s;
3817
+ for (i = 0, s = t.length; i < s; i++) t[i].major && e.push(i);
3818
+ return e;
3819
+ })(e)
3820
+ : [],
3821
+ o = n.length,
3822
+ a = n[0],
3823
+ r = n[o - 1],
3824
+ l = [];
3825
+ if (o > s)
3826
+ return (
3827
+ (function (t, e, i, s) {
3828
+ let n,
3829
+ o = 0,
3830
+ a = i[0];
3831
+ for (s = Math.ceil(s), n = 0; n < t.length; n++)
3832
+ n === a && (e.push(t[n]), o++, (a = i[o * s]));
3833
+ })(e, l, n, o / s),
3834
+ l
3835
+ );
3836
+ const h = (function (t, e, i) {
3837
+ const s = (function (t) {
3838
+ const e = t.length;
3839
+ let i, s;
3840
+ if (e < 2) return !1;
3841
+ for (s = t[0], i = 1; i < e; ++i)
3842
+ if (t[i] - t[i - 1] !== s) return !1;
3843
+ return s;
3844
+ })(t),
3845
+ n = e.length / i;
3846
+ if (!s) return Math.max(n, 1);
3847
+ const o = At(s);
3848
+ for (let t = 0, e = o.length - 1; t < e; t++) {
3849
+ const e = o[t];
3850
+ if (e > n) return e;
3851
+ }
3852
+ return Math.max(n, 1);
3853
+ })(n, e, s);
3854
+ if (o > 0) {
3855
+ let t, i;
3856
+ const s = o > 1 ? Math.round((r - a) / (o - 1)) : null;
3857
+ for (Ts(e, l, h, $(s) ? 0 : a - s, a), t = 0, i = o - 1; t < i; t++)
3858
+ Ts(e, l, h, n[t], n[t + 1]);
3859
+ return Ts(e, l, h, r, $(s) ? e.length : r + s), l;
3860
+ }
3861
+ return Ts(e, l, h), l;
3862
+ }
3863
+ function Ts(t, e, i, s, n) {
3864
+ const o = K(s, 0),
3865
+ a = Math.min(K(n, t.length), t.length);
3866
+ let r,
3867
+ l,
3868
+ h,
3869
+ c = 0;
3870
+ for (
3871
+ i = Math.ceil(i), n && ((r = n - s), (i = r / Math.floor(r / i))), h = o;
3872
+ h < 0;
3873
+
3874
+ )
3875
+ c++, (h = Math.round(o + c * i));
3876
+ for (l = Math.max(o, 0); l < a; l++)
3877
+ l === h && (e.push(t[l]), c++, (h = Math.round(o + c * i)));
3878
+ }
3879
+ bt.set("scale", {
3880
+ display: !0,
3881
+ offset: !1,
3882
+ reverse: !1,
3883
+ beginAtZero: !1,
3884
+ bounds: "ticks",
3885
+ grace: 0,
3886
+ grid: {
3887
+ display: !0,
3888
+ lineWidth: 1,
3889
+ drawBorder: !0,
3890
+ drawOnChartArea: !0,
3891
+ drawTicks: !0,
3892
+ tickLength: 8,
3893
+ tickWidth: (t, e) => e.lineWidth,
3894
+ tickColor: (t, e) => e.color,
3895
+ offset: !1,
3896
+ borderDash: [],
3897
+ borderDashOffset: 0,
3898
+ borderWidth: 1,
3899
+ },
3900
+ title: { display: !1, text: "", padding: { top: 4, bottom: 4 } },
3901
+ ticks: {
3902
+ minRotation: 0,
3903
+ maxRotation: 50,
3904
+ mirror: !1,
3905
+ textStrokeWidth: 0,
3906
+ textStrokeColor: "",
3907
+ padding: 3,
3908
+ display: !0,
3909
+ autoSkip: !0,
3910
+ autoSkipPadding: 3,
3911
+ labelOffset: 0,
3912
+ callback: Os.formatters.values,
3913
+ minor: {},
3914
+ major: {},
3915
+ align: "center",
3916
+ crossAlign: "near",
3917
+ showLabelBackdrop: !1,
3918
+ backdropColor: "rgba(255, 255, 255, 0.75)",
3919
+ backdropPadding: 2,
3920
+ },
3921
+ }),
3922
+ bt.route("scale.ticks", "color", "", "color"),
3923
+ bt.route("scale.grid", "color", "", "borderColor"),
3924
+ bt.route("scale.grid", "borderColor", "", "borderColor"),
3925
+ bt.route("scale.title", "color", "", "color"),
3926
+ bt.describe("scale", {
3927
+ _fallback: !1,
3928
+ _scriptable: (t) =>
3929
+ !t.startsWith("before") &&
3930
+ !t.startsWith("after") &&
3931
+ "callback" !== t &&
3932
+ "parser" !== t,
3933
+ _indexable: (t) => "borderDash" !== t && "tickBorderDash" !== t,
3934
+ }),
3935
+ bt.describe("scales", { _fallback: "scale" }),
3936
+ bt.describe("scale.ticks", {
3937
+ _scriptable: (t) => "backdropPadding" !== t && "callback" !== t,
3938
+ _indexable: (t) => "backdropPadding" !== t,
3939
+ });
3940
+ const Ls = (t, e, i) => ("top" === e || "left" === e ? t[e] + i : t[e] - i);
3941
+ function Rs(t, e) {
3942
+ const i = [],
3943
+ s = t.length / e,
3944
+ n = t.length;
3945
+ let o = 0;
3946
+ for (; o < n; o += s) i.push(t[Math.floor(o)]);
3947
+ return i;
3948
+ }
3949
+ function Es(t, e, i) {
3950
+ const s = t.ticks.length,
3951
+ n = Math.min(e, s - 1),
3952
+ o = t._startPixel,
3953
+ a = t._endPixel,
3954
+ r = 1e-6;
3955
+ let l,
3956
+ h = t.getPixelForTick(n);
3957
+ if (
3958
+ !(
3959
+ i &&
3960
+ ((l =
3961
+ 1 === s
3962
+ ? Math.max(h - o, a - h)
3963
+ : 0 === e
3964
+ ? (t.getPixelForTick(1) - h) / 2
3965
+ : (h - t.getPixelForTick(n - 1)) / 2),
3966
+ (h += n < e ? l : -l),
3967
+ h < o - r || h > a + r)
3968
+ )
3969
+ )
3970
+ return h;
3971
+ }
3972
+ function Is(t) {
3973
+ return t.drawTicks ? t.tickLength : 0;
3974
+ }
3975
+ function zs(t, e) {
3976
+ if (!t.display) return 0;
3977
+ const i = He(t.font, e),
3978
+ s = Ne(t.padding);
3979
+ return (Y(t.text) ? t.text.length : 1) * i.lineHeight + s.height;
3980
+ }
3981
+ function Fs(t, e, i) {
3982
+ let n = s(t);
3983
+ return (
3984
+ ((i && "right" !== e) || (!i && "right" === e)) &&
3985
+ (n = ((t) => ("left" === t ? "right" : "right" === t ? "left" : t))(n)),
3986
+ n
3987
+ );
3988
+ }
3989
+ class Bs extends Ds {
3990
+ constructor(t) {
3991
+ super(),
3992
+ (this.id = t.id),
3993
+ (this.type = t.type),
3994
+ (this.options = void 0),
3995
+ (this.ctx = t.ctx),
3996
+ (this.chart = t.chart),
3997
+ (this.top = void 0),
3998
+ (this.bottom = void 0),
3999
+ (this.left = void 0),
4000
+ (this.right = void 0),
4001
+ (this.width = void 0),
4002
+ (this.height = void 0),
4003
+ (this._margins = { left: 0, right: 0, top: 0, bottom: 0 }),
4004
+ (this.maxWidth = void 0),
4005
+ (this.maxHeight = void 0),
4006
+ (this.paddingTop = void 0),
4007
+ (this.paddingBottom = void 0),
4008
+ (this.paddingLeft = void 0),
4009
+ (this.paddingRight = void 0),
4010
+ (this.axis = void 0),
4011
+ (this.labelRotation = void 0),
4012
+ (this.min = void 0),
4013
+ (this.max = void 0),
4014
+ (this._range = void 0),
4015
+ (this.ticks = []),
4016
+ (this._gridLineItems = null),
4017
+ (this._labelItems = null),
4018
+ (this._labelSizes = null),
4019
+ (this._length = 0),
4020
+ (this._maxLength = 0),
4021
+ (this._longestTextCache = {}),
4022
+ (this._startPixel = void 0),
4023
+ (this._endPixel = void 0),
4024
+ (this._reversePixels = !1),
4025
+ (this._userMax = void 0),
4026
+ (this._userMin = void 0),
4027
+ (this._suggestedMax = void 0),
4028
+ (this._suggestedMin = void 0),
4029
+ (this._ticksLength = 0),
4030
+ (this._borderValue = 0),
4031
+ (this._cache = {}),
4032
+ (this._dataLimitsCached = !1),
4033
+ (this.$context = void 0);
4034
+ }
4035
+ init(t) {
4036
+ (this.options = t.setContext(this.getContext())),
4037
+ (this.axis = t.axis),
4038
+ (this._userMin = this.parse(t.min)),
4039
+ (this._userMax = this.parse(t.max)),
4040
+ (this._suggestedMin = this.parse(t.suggestedMin)),
4041
+ (this._suggestedMax = this.parse(t.suggestedMax));
4042
+ }
4043
+ parse(t, e) {
4044
+ return t;
4045
+ }
4046
+ getUserBounds() {
4047
+ let {
4048
+ _userMin: t,
4049
+ _userMax: e,
4050
+ _suggestedMin: i,
4051
+ _suggestedMax: s,
4052
+ } = this;
4053
+ return (
4054
+ (t = q(t, Number.POSITIVE_INFINITY)),
4055
+ (e = q(e, Number.NEGATIVE_INFINITY)),
4056
+ (i = q(i, Number.POSITIVE_INFINITY)),
4057
+ (s = q(s, Number.NEGATIVE_INFINITY)),
4058
+ { min: q(t, i), max: q(e, s), minDefined: X(t), maxDefined: X(e) }
4059
+ );
4060
+ }
4061
+ getMinMax(t) {
4062
+ let e,
4063
+ { min: i, max: s, minDefined: n, maxDefined: o } = this.getUserBounds();
4064
+ if (n && o) return { min: i, max: s };
4065
+ const a = this.getMatchingVisibleMetas();
4066
+ for (let r = 0, l = a.length; r < l; ++r)
4067
+ (e = a[r].controller.getMinMax(this, t)),
4068
+ n || (i = Math.min(i, e.min)),
4069
+ o || (s = Math.max(s, e.max));
4070
+ return (
4071
+ (i = o && i > s ? s : i),
4072
+ (s = n && i > s ? i : s),
4073
+ { min: q(i, q(s, i)), max: q(s, q(i, s)) }
4074
+ );
4075
+ }
4076
+ getPadding() {
4077
+ return {
4078
+ left: this.paddingLeft || 0,
4079
+ top: this.paddingTop || 0,
4080
+ right: this.paddingRight || 0,
4081
+ bottom: this.paddingBottom || 0,
4082
+ };
4083
+ }
4084
+ getTicks() {
4085
+ return this.ticks;
4086
+ }
4087
+ getLabels() {
4088
+ const t = this.chart.data;
4089
+ return (
4090
+ this.options.labels ||
4091
+ (this.isHorizontal() ? t.xLabels : t.yLabels) ||
4092
+ t.labels ||
4093
+ []
4094
+ );
4095
+ }
4096
+ beforeLayout() {
4097
+ (this._cache = {}), (this._dataLimitsCached = !1);
4098
+ }
4099
+ beforeUpdate() {
4100
+ J(this.options.beforeUpdate, [this]);
4101
+ }
4102
+ update(t, e, i) {
4103
+ const { beginAtZero: s, grace: n, ticks: o } = this.options,
4104
+ a = o.sampleSize;
4105
+ this.beforeUpdate(),
4106
+ (this.maxWidth = t),
4107
+ (this.maxHeight = e),
4108
+ (this._margins = i =
4109
+ Object.assign({ left: 0, right: 0, top: 0, bottom: 0 }, i)),
4110
+ (this.ticks = null),
4111
+ (this._labelSizes = null),
4112
+ (this._gridLineItems = null),
4113
+ (this._labelItems = null),
4114
+ this.beforeSetDimensions(),
4115
+ this.setDimensions(),
4116
+ this.afterSetDimensions(),
4117
+ (this._maxLength = this.isHorizontal()
4118
+ ? this.width + i.left + i.right
4119
+ : this.height + i.top + i.bottom),
4120
+ this._dataLimitsCached ||
4121
+ (this.beforeDataLimits(),
4122
+ this.determineDataLimits(),
4123
+ this.afterDataLimits(),
4124
+ (this._range = $e(this, n, s)),
4125
+ (this._dataLimitsCached = !0)),
4126
+ this.beforeBuildTicks(),
4127
+ (this.ticks = this.buildTicks() || []),
4128
+ this.afterBuildTicks();
4129
+ const r = a < this.ticks.length;
4130
+ this._convertTicksToLabels(r ? Rs(this.ticks, a) : this.ticks),
4131
+ this.configure(),
4132
+ this.beforeCalculateLabelRotation(),
4133
+ this.calculateLabelRotation(),
4134
+ this.afterCalculateLabelRotation(),
4135
+ o.display &&
4136
+ (o.autoSkip || "auto" === o.source) &&
4137
+ ((this.ticks = As(this, this.ticks)), (this._labelSizes = null)),
4138
+ r && this._convertTicksToLabels(this.ticks),
4139
+ this.beforeFit(),
4140
+ this.fit(),
4141
+ this.afterFit(),
4142
+ this.afterUpdate();
4143
+ }
4144
+ configure() {
4145
+ let t,
4146
+ e,
4147
+ i = this.options.reverse;
4148
+ this.isHorizontal()
4149
+ ? ((t = this.left), (e = this.right))
4150
+ : ((t = this.top), (e = this.bottom), (i = !i)),
4151
+ (this._startPixel = t),
4152
+ (this._endPixel = e),
4153
+ (this._reversePixels = i),
4154
+ (this._length = e - t),
4155
+ (this._alignToPixels = this.options.alignToPixels);
4156
+ }
4157
+ afterUpdate() {
4158
+ J(this.options.afterUpdate, [this]);
4159
+ }
4160
+ beforeSetDimensions() {
4161
+ J(this.options.beforeSetDimensions, [this]);
4162
+ }
4163
+ setDimensions() {
4164
+ this.isHorizontal()
4165
+ ? ((this.width = this.maxWidth),
4166
+ (this.left = 0),
4167
+ (this.right = this.width))
4168
+ : ((this.height = this.maxHeight),
4169
+ (this.top = 0),
4170
+ (this.bottom = this.height)),
4171
+ (this.paddingLeft = 0),
4172
+ (this.paddingTop = 0),
4173
+ (this.paddingRight = 0),
4174
+ (this.paddingBottom = 0);
4175
+ }
4176
+ afterSetDimensions() {
4177
+ J(this.options.afterSetDimensions, [this]);
4178
+ }
4179
+ _callHooks(t) {
4180
+ this.chart.notifyPlugins(t, this.getContext()),
4181
+ J(this.options[t], [this]);
4182
+ }
4183
+ beforeDataLimits() {
4184
+ this._callHooks("beforeDataLimits");
4185
+ }
4186
+ determineDataLimits() {}
4187
+ afterDataLimits() {
4188
+ this._callHooks("afterDataLimits");
4189
+ }
4190
+ beforeBuildTicks() {
4191
+ this._callHooks("beforeBuildTicks");
4192
+ }
4193
+ buildTicks() {
4194
+ return [];
4195
+ }
4196
+ afterBuildTicks() {
4197
+ this._callHooks("afterBuildTicks");
4198
+ }
4199
+ beforeTickToLabelConversion() {
4200
+ J(this.options.beforeTickToLabelConversion, [this]);
4201
+ }
4202
+ generateTickLabels(t) {
4203
+ const e = this.options.ticks;
4204
+ let i, s, n;
4205
+ for (i = 0, s = t.length; i < s; i++)
4206
+ (n = t[i]), (n.label = J(e.callback, [n.value, i, t], this));
4207
+ }
4208
+ afterTickToLabelConversion() {
4209
+ J(this.options.afterTickToLabelConversion, [this]);
4210
+ }
4211
+ beforeCalculateLabelRotation() {
4212
+ J(this.options.beforeCalculateLabelRotation, [this]);
4213
+ }
4214
+ calculateLabelRotation() {
4215
+ const t = this.options,
4216
+ e = t.ticks,
4217
+ i = this.ticks.length,
4218
+ s = e.minRotation || 0,
4219
+ n = e.maxRotation;
4220
+ let o,
4221
+ a,
4222
+ r,
4223
+ l = s;
4224
+ if (
4225
+ !this._isVisible() ||
4226
+ !e.display ||
4227
+ s >= n ||
4228
+ i <= 1 ||
4229
+ !this.isHorizontal()
4230
+ )
4231
+ return void (this.labelRotation = s);
4232
+ const h = this._getLabelSizes(),
4233
+ c = h.widest.width,
4234
+ d = h.highest.height,
4235
+ u = jt(this.chart.width - c, 0, this.maxWidth);
4236
+ (o = t.offset ? this.maxWidth / i : u / (i - 1)),
4237
+ c + 6 > o &&
4238
+ ((o = u / (i - (t.offset ? 0.5 : 1))),
4239
+ (a =
4240
+ this.maxHeight -
4241
+ Is(t.grid) -
4242
+ e.padding -
4243
+ zs(t.title, this.chart.options.font)),
4244
+ (r = Math.sqrt(c * c + d * d)),
4245
+ (l = zt(
4246
+ Math.min(
4247
+ Math.asin(jt((h.highest.height + 6) / o, -1, 1)),
4248
+ Math.asin(jt(a / r, -1, 1)) - Math.asin(jt(d / r, -1, 1))
4249
+ )
4250
+ )),
4251
+ (l = Math.max(s, Math.min(n, l)))),
4252
+ (this.labelRotation = l);
4253
+ }
4254
+ afterCalculateLabelRotation() {
4255
+ J(this.options.afterCalculateLabelRotation, [this]);
4256
+ }
4257
+ beforeFit() {
4258
+ J(this.options.beforeFit, [this]);
4259
+ }
4260
+ fit() {
4261
+ const t = { width: 0, height: 0 },
4262
+ {
4263
+ chart: e,
4264
+ options: { ticks: i, title: s, grid: n },
4265
+ } = this,
4266
+ o = this._isVisible(),
4267
+ a = this.isHorizontal();
4268
+ if (o) {
4269
+ const o = zs(s, e.options.font);
4270
+ if (
4271
+ (a
4272
+ ? ((t.width = this.maxWidth), (t.height = Is(n) + o))
4273
+ : ((t.height = this.maxHeight), (t.width = Is(n) + o)),
4274
+ i.display && this.ticks.length)
4275
+ ) {
4276
+ const {
4277
+ first: e,
4278
+ last: s,
4279
+ widest: n,
4280
+ highest: o,
4281
+ } = this._getLabelSizes(),
4282
+ r = 2 * i.padding,
4283
+ l = It(this.labelRotation),
4284
+ h = Math.cos(l),
4285
+ c = Math.sin(l);
4286
+ if (a) {
4287
+ const e = i.mirror ? 0 : c * n.width + h * o.height;
4288
+ t.height = Math.min(this.maxHeight, t.height + e + r);
4289
+ } else {
4290
+ const e = i.mirror ? 0 : h * n.width + c * o.height;
4291
+ t.width = Math.min(this.maxWidth, t.width + e + r);
4292
+ }
4293
+ this._calculatePadding(e, s, c, h);
4294
+ }
4295
+ }
4296
+ this._handleMargins(),
4297
+ a
4298
+ ? ((this.width = this._length =
4299
+ e.width - this._margins.left - this._margins.right),
4300
+ (this.height = t.height))
4301
+ : ((this.width = t.width),
4302
+ (this.height = this._length =
4303
+ e.height - this._margins.top - this._margins.bottom));
4304
+ }
4305
+ _calculatePadding(t, e, i, s) {
4306
+ const {
4307
+ ticks: { align: n, padding: o },
4308
+ position: a,
4309
+ } = this.options,
4310
+ r = 0 !== this.labelRotation,
4311
+ l = "top" !== a && "x" === this.axis;
4312
+ if (this.isHorizontal()) {
4313
+ const a = this.getPixelForTick(0) - this.left,
4314
+ h = this.right - this.getPixelForTick(this.ticks.length - 1);
4315
+ let c = 0,
4316
+ d = 0;
4317
+ r
4318
+ ? l
4319
+ ? ((c = s * t.width), (d = i * e.height))
4320
+ : ((c = i * t.height), (d = s * e.width))
4321
+ : "start" === n
4322
+ ? (d = e.width)
4323
+ : "end" === n
4324
+ ? (c = t.width)
4325
+ : ((c = t.width / 2), (d = e.width / 2)),
4326
+ (this.paddingLeft = Math.max(
4327
+ ((c - a + o) * this.width) / (this.width - a),
4328
+ 0
4329
+ )),
4330
+ (this.paddingRight = Math.max(
4331
+ ((d - h + o) * this.width) / (this.width - h),
4332
+ 0
4333
+ ));
4334
+ } else {
4335
+ let i = e.height / 2,
4336
+ s = t.height / 2;
4337
+ "start" === n
4338
+ ? ((i = 0), (s = t.height))
4339
+ : "end" === n && ((i = e.height), (s = 0)),
4340
+ (this.paddingTop = i + o),
4341
+ (this.paddingBottom = s + o);
4342
+ }
4343
+ }
4344
+ _handleMargins() {
4345
+ this._margins &&
4346
+ ((this._margins.left = Math.max(this.paddingLeft, this._margins.left)),
4347
+ (this._margins.top = Math.max(this.paddingTop, this._margins.top)),
4348
+ (this._margins.right = Math.max(
4349
+ this.paddingRight,
4350
+ this._margins.right
4351
+ )),
4352
+ (this._margins.bottom = Math.max(
4353
+ this.paddingBottom,
4354
+ this._margins.bottom
4355
+ )));
4356
+ }
4357
+ afterFit() {
4358
+ J(this.options.afterFit, [this]);
4359
+ }
4360
+ isHorizontal() {
4361
+ const { axis: t, position: e } = this.options;
4362
+ return "top" === e || "bottom" === e || "x" === t;
4363
+ }
4364
+ isFullSize() {
4365
+ return this.options.fullSize;
4366
+ }
4367
+ _convertTicksToLabels(t) {
4368
+ let e, i;
4369
+ for (
4370
+ this.beforeTickToLabelConversion(),
4371
+ this.generateTickLabels(t),
4372
+ e = 0,
4373
+ i = t.length;
4374
+ e < i;
4375
+ e++
4376
+ )
4377
+ $(t[e].label) && (t.splice(e, 1), i--, e--);
4378
+ this.afterTickToLabelConversion();
4379
+ }
4380
+ _getLabelSizes() {
4381
+ let t = this._labelSizes;
4382
+ if (!t) {
4383
+ const e = this.options.ticks.sampleSize;
4384
+ let i = this.ticks;
4385
+ e < i.length && (i = Rs(i, e)),
4386
+ (this._labelSizes = t = this._computeLabelSizes(i, i.length));
4387
+ }
4388
+ return t;
4389
+ }
4390
+ _computeLabelSizes(t, e) {
4391
+ const { ctx: i, _longestTextCache: s } = this,
4392
+ n = [],
4393
+ o = [];
4394
+ let a,
4395
+ r,
4396
+ l,
4397
+ h,
4398
+ c,
4399
+ d,
4400
+ u,
4401
+ f,
4402
+ g,
4403
+ p,
4404
+ m,
4405
+ x = 0,
4406
+ b = 0;
4407
+ for (a = 0; a < e; ++a) {
4408
+ if (
4409
+ ((h = t[a].label),
4410
+ (c = this._resolveTickFontOptions(a)),
4411
+ (i.font = d = c.string),
4412
+ (u = s[d] = s[d] || { data: {}, gc: [] }),
4413
+ (f = c.lineHeight),
4414
+ (g = p = 0),
4415
+ $(h) || Y(h))
4416
+ ) {
4417
+ if (Y(h))
4418
+ for (r = 0, l = h.length; r < l; ++r)
4419
+ (m = h[r]),
4420
+ $(m) || Y(m) || ((g = Xt(i, u.data, u.gc, g, m)), (p += f));
4421
+ } else (g = Xt(i, u.data, u.gc, g, h)), (p = f);
4422
+ n.push(g), o.push(p), (x = Math.max(g, x)), (b = Math.max(p, b));
4423
+ }
4424
+ !(function (t, e) {
4425
+ Q(t, (t) => {
4426
+ const i = t.gc,
4427
+ s = i.length / 2;
4428
+ let n;
4429
+ if (s > e) {
4430
+ for (n = 0; n < s; ++n) delete t.data[i[n]];
4431
+ i.splice(0, s);
4432
+ }
4433
+ });
4434
+ })(s, e);
4435
+ const _ = n.indexOf(x),
4436
+ y = o.indexOf(b),
4437
+ v = (t) => ({ width: n[t] || 0, height: o[t] || 0 });
4438
+ return {
4439
+ first: v(0),
4440
+ last: v(e - 1),
4441
+ widest: v(_),
4442
+ highest: v(y),
4443
+ widths: n,
4444
+ heights: o,
4445
+ };
4446
+ }
4447
+ getLabelForValue(t) {
4448
+ return t;
4449
+ }
4450
+ getPixelForValue(t, e) {
4451
+ return NaN;
4452
+ }
4453
+ getValueForPixel(t) {}
4454
+ getPixelForTick(t) {
4455
+ const e = this.ticks;
4456
+ return t < 0 || t > e.length - 1
4457
+ ? null
4458
+ : this.getPixelForValue(e[t].value);
4459
+ }
4460
+ getPixelForDecimal(t) {
4461
+ this._reversePixels && (t = 1 - t);
4462
+ const e = this._startPixel + t * this._length;
4463
+ return $t(this._alignToPixels ? Kt(this.chart, e, 0) : e);
4464
+ }
4465
+ getDecimalForPixel(t) {
4466
+ const e = (t - this._startPixel) / this._length;
4467
+ return this._reversePixels ? 1 - e : e;
4468
+ }
4469
+ getBasePixel() {
4470
+ return this.getPixelForValue(this.getBaseValue());
4471
+ }
4472
+ getBaseValue() {
4473
+ const { min: t, max: e } = this;
4474
+ return t < 0 && e < 0 ? e : t > 0 && e > 0 ? t : 0;
4475
+ }
4476
+ getContext(t) {
4477
+ const e = this.ticks || [];
4478
+ if (t >= 0 && t < e.length) {
4479
+ const i = e[t];
4480
+ return (
4481
+ i.$context ||
4482
+ (i.$context = (function (t, e, i) {
4483
+ return Ye(t, { tick: i, index: e, type: "tick" });
4484
+ })(this.getContext(), t, i))
4485
+ );
4486
+ }
4487
+ return (
4488
+ this.$context ||
4489
+ (this.$context = Ye(this.chart.getContext(), {
4490
+ scale: this,
4491
+ type: "scale",
4492
+ }))
4493
+ );
4494
+ }
4495
+ _tickSize() {
4496
+ const t = this.options.ticks,
4497
+ e = It(this.labelRotation),
4498
+ i = Math.abs(Math.cos(e)),
4499
+ s = Math.abs(Math.sin(e)),
4500
+ n = this._getLabelSizes(),
4501
+ o = t.autoSkipPadding || 0,
4502
+ a = n ? n.widest.width + o : 0,
4503
+ r = n ? n.highest.height + o : 0;
4504
+ return this.isHorizontal()
4505
+ ? r * i > a * s
4506
+ ? a / i
4507
+ : r / s
4508
+ : r * s < a * i
4509
+ ? r / i
4510
+ : a / s;
4511
+ }
4512
+ _isVisible() {
4513
+ const t = this.options.display;
4514
+ return "auto" !== t ? !!t : this.getMatchingVisibleMetas().length > 0;
4515
+ }
4516
+ _computeGridLineItems(t) {
4517
+ const e = this.axis,
4518
+ i = this.chart,
4519
+ s = this.options,
4520
+ { grid: n, position: o } = s,
4521
+ a = n.offset,
4522
+ r = this.isHorizontal(),
4523
+ l = this.ticks.length + (a ? 1 : 0),
4524
+ h = Is(n),
4525
+ c = [],
4526
+ d = n.setContext(this.getContext()),
4527
+ u = d.drawBorder ? d.borderWidth : 0,
4528
+ f = u / 2,
4529
+ g = function (t) {
4530
+ return Kt(i, t, u);
4531
+ };
4532
+ let p, m, x, b, _, y, v, w, M, k, S, P;
4533
+ if ("top" === o)
4534
+ (p = g(this.bottom)),
4535
+ (y = this.bottom - h),
4536
+ (w = p - f),
4537
+ (k = g(t.top) + f),
4538
+ (P = t.bottom);
4539
+ else if ("bottom" === o)
4540
+ (p = g(this.top)),
4541
+ (k = t.top),
4542
+ (P = g(t.bottom) - f),
4543
+ (y = p + f),
4544
+ (w = this.top + h);
4545
+ else if ("left" === o)
4546
+ (p = g(this.right)),
4547
+ (_ = this.right - h),
4548
+ (v = p - f),
4549
+ (M = g(t.left) + f),
4550
+ (S = t.right);
4551
+ else if ("right" === o)
4552
+ (p = g(this.left)),
4553
+ (M = t.left),
4554
+ (S = g(t.right) - f),
4555
+ (_ = p + f),
4556
+ (v = this.left + h);
4557
+ else if ("x" === e) {
4558
+ if ("center" === o) p = g((t.top + t.bottom) / 2 + 0.5);
4559
+ else if (U(o)) {
4560
+ const t = Object.keys(o)[0],
4561
+ e = o[t];
4562
+ p = g(this.chart.scales[t].getPixelForValue(e));
4563
+ }
4564
+ (k = t.top), (P = t.bottom), (y = p + f), (w = y + h);
4565
+ } else if ("y" === e) {
4566
+ if ("center" === o) p = g((t.left + t.right) / 2);
4567
+ else if (U(o)) {
4568
+ const t = Object.keys(o)[0],
4569
+ e = o[t];
4570
+ p = g(this.chart.scales[t].getPixelForValue(e));
4571
+ }
4572
+ (_ = p - f), (v = _ - h), (M = t.left), (S = t.right);
4573
+ }
4574
+ const D = K(s.ticks.maxTicksLimit, l),
4575
+ C = Math.max(1, Math.ceil(l / D));
4576
+ for (m = 0; m < l; m += C) {
4577
+ const t = n.setContext(this.getContext(m)),
4578
+ e = t.lineWidth,
4579
+ s = t.color,
4580
+ o = n.borderDash || [],
4581
+ l = t.borderDashOffset,
4582
+ h = t.tickWidth,
4583
+ d = t.tickColor,
4584
+ u = t.tickBorderDash || [],
4585
+ f = t.tickBorderDashOffset;
4586
+ (x = Es(this, m, a)),
4587
+ void 0 !== x &&
4588
+ ((b = Kt(i, x, e)),
4589
+ r ? (_ = v = M = S = b) : (y = w = k = P = b),
4590
+ c.push({
4591
+ tx1: _,
4592
+ ty1: y,
4593
+ tx2: v,
4594
+ ty2: w,
4595
+ x1: M,
4596
+ y1: k,
4597
+ x2: S,
4598
+ y2: P,
4599
+ width: e,
4600
+ color: s,
4601
+ borderDash: o,
4602
+ borderDashOffset: l,
4603
+ tickWidth: h,
4604
+ tickColor: d,
4605
+ tickBorderDash: u,
4606
+ tickBorderDashOffset: f,
4607
+ }));
4608
+ }
4609
+ return (this._ticksLength = l), (this._borderValue = p), c;
4610
+ }
4611
+ _computeLabelItems(t) {
4612
+ const e = this.axis,
4613
+ i = this.options,
4614
+ { position: s, ticks: n } = i,
4615
+ o = this.isHorizontal(),
4616
+ a = this.ticks,
4617
+ { align: r, crossAlign: l, padding: h, mirror: c } = n,
4618
+ d = Is(i.grid),
4619
+ u = d + h,
4620
+ f = c ? -h : u,
4621
+ g = -It(this.labelRotation),
4622
+ p = [];
4623
+ let m,
4624
+ x,
4625
+ b,
4626
+ _,
4627
+ y,
4628
+ v,
4629
+ w,
4630
+ M,
4631
+ k,
4632
+ S,
4633
+ P,
4634
+ D,
4635
+ C = "middle";
4636
+ if ("top" === s)
4637
+ (v = this.bottom - f), (w = this._getXAxisLabelAlignment());
4638
+ else if ("bottom" === s)
4639
+ (v = this.top + f), (w = this._getXAxisLabelAlignment());
4640
+ else if ("left" === s) {
4641
+ const t = this._getYAxisLabelAlignment(d);
4642
+ (w = t.textAlign), (y = t.x);
4643
+ } else if ("right" === s) {
4644
+ const t = this._getYAxisLabelAlignment(d);
4645
+ (w = t.textAlign), (y = t.x);
4646
+ } else if ("x" === e) {
4647
+ if ("center" === s) v = (t.top + t.bottom) / 2 + u;
4648
+ else if (U(s)) {
4649
+ const t = Object.keys(s)[0],
4650
+ e = s[t];
4651
+ v = this.chart.scales[t].getPixelForValue(e) + u;
4652
+ }
4653
+ w = this._getXAxisLabelAlignment();
4654
+ } else if ("y" === e) {
4655
+ if ("center" === s) y = (t.left + t.right) / 2 - u;
4656
+ else if (U(s)) {
4657
+ const t = Object.keys(s)[0],
4658
+ e = s[t];
4659
+ y = this.chart.scales[t].getPixelForValue(e);
4660
+ }
4661
+ w = this._getYAxisLabelAlignment(d).textAlign;
4662
+ }
4663
+ "y" === e &&
4664
+ ("start" === r ? (C = "top") : "end" === r && (C = "bottom"));
4665
+ const O = this._getLabelSizes();
4666
+ for (m = 0, x = a.length; m < x; ++m) {
4667
+ (b = a[m]), (_ = b.label);
4668
+ const t = n.setContext(this.getContext(m));
4669
+ (M = this.getPixelForTick(m) + n.labelOffset),
4670
+ (k = this._resolveTickFontOptions(m)),
4671
+ (S = k.lineHeight),
4672
+ (P = Y(_) ? _.length : 1);
4673
+ const e = P / 2,
4674
+ i = t.color,
4675
+ r = t.textStrokeColor,
4676
+ h = t.textStrokeWidth;
4677
+ let d;
4678
+ if (
4679
+ (o
4680
+ ? ((y = M),
4681
+ (D =
4682
+ "top" === s
4683
+ ? "near" === l || 0 !== g
4684
+ ? -P * S + S / 2
4685
+ : "center" === l
4686
+ ? -O.highest.height / 2 - e * S + S
4687
+ : -O.highest.height + S / 2
4688
+ : "near" === l || 0 !== g
4689
+ ? S / 2
4690
+ : "center" === l
4691
+ ? O.highest.height / 2 - e * S
4692
+ : O.highest.height - P * S),
4693
+ c && (D *= -1))
4694
+ : ((v = M), (D = ((1 - P) * S) / 2)),
4695
+ t.showLabelBackdrop)
4696
+ ) {
4697
+ const e = Ne(t.backdropPadding),
4698
+ i = O.heights[m],
4699
+ s = O.widths[m];
4700
+ let n = v + D - e.top,
4701
+ o = y - e.left;
4702
+ switch (C) {
4703
+ case "middle":
4704
+ n -= i / 2;
4705
+ break;
4706
+ case "bottom":
4707
+ n -= i;
4708
+ }
4709
+ switch (w) {
4710
+ case "center":
4711
+ o -= s / 2;
4712
+ break;
4713
+ case "right":
4714
+ o -= s;
4715
+ }
4716
+ d = {
4717
+ left: o,
4718
+ top: n,
4719
+ width: s + e.width,
4720
+ height: i + e.height,
4721
+ color: t.backdropColor,
4722
+ };
4723
+ }
4724
+ p.push({
4725
+ rotation: g,
4726
+ label: _,
4727
+ font: k,
4728
+ color: i,
4729
+ strokeColor: r,
4730
+ strokeWidth: h,
4731
+ textOffset: D,
4732
+ textAlign: w,
4733
+ textBaseline: C,
4734
+ translation: [y, v],
4735
+ backdrop: d,
4736
+ });
4737
+ }
4738
+ return p;
4739
+ }
4740
+ _getXAxisLabelAlignment() {
4741
+ const { position: t, ticks: e } = this.options;
4742
+ if (-It(this.labelRotation)) return "top" === t ? "left" : "right";
4743
+ let i = "center";
4744
+ return (
4745
+ "start" === e.align ? (i = "left") : "end" === e.align && (i = "right"),
4746
+ i
4747
+ );
4748
+ }
4749
+ _getYAxisLabelAlignment(t) {
4750
+ const {
4751
+ position: e,
4752
+ ticks: { crossAlign: i, mirror: s, padding: n },
4753
+ } = this.options,
4754
+ o = t + n,
4755
+ a = this._getLabelSizes().widest.width;
4756
+ let r, l;
4757
+ return (
4758
+ "left" === e
4759
+ ? s
4760
+ ? ((l = this.right + n),
4761
+ "near" === i
4762
+ ? (r = "left")
4763
+ : "center" === i
4764
+ ? ((r = "center"), (l += a / 2))
4765
+ : ((r = "right"), (l += a)))
4766
+ : ((l = this.right - o),
4767
+ "near" === i
4768
+ ? (r = "right")
4769
+ : "center" === i
4770
+ ? ((r = "center"), (l -= a / 2))
4771
+ : ((r = "left"), (l = this.left)))
4772
+ : "right" === e
4773
+ ? s
4774
+ ? ((l = this.left + n),
4775
+ "near" === i
4776
+ ? (r = "right")
4777
+ : "center" === i
4778
+ ? ((r = "center"), (l -= a / 2))
4779
+ : ((r = "left"), (l -= a)))
4780
+ : ((l = this.left + o),
4781
+ "near" === i
4782
+ ? (r = "left")
4783
+ : "center" === i
4784
+ ? ((r = "center"), (l += a / 2))
4785
+ : ((r = "right"), (l = this.right)))
4786
+ : (r = "right"),
4787
+ { textAlign: r, x: l }
4788
+ );
4789
+ }
4790
+ _computeLabelArea() {
4791
+ if (this.options.ticks.mirror) return;
4792
+ const t = this.chart,
4793
+ e = this.options.position;
4794
+ return "left" === e || "right" === e
4795
+ ? { top: 0, left: this.left, bottom: t.height, right: this.right }
4796
+ : "top" === e || "bottom" === e
4797
+ ? { top: this.top, left: 0, bottom: this.bottom, right: t.width }
4798
+ : void 0;
4799
+ }
4800
+ drawBackground() {
4801
+ const {
4802
+ ctx: t,
4803
+ options: { backgroundColor: e },
4804
+ left: i,
4805
+ top: s,
4806
+ width: n,
4807
+ height: o,
4808
+ } = this;
4809
+ e && (t.save(), (t.fillStyle = e), t.fillRect(i, s, n, o), t.restore());
4810
+ }
4811
+ getLineWidthForValue(t) {
4812
+ const e = this.options.grid;
4813
+ if (!this._isVisible() || !e.display) return 0;
4814
+ const i = this.ticks.findIndex((e) => e.value === t);
4815
+ if (i >= 0) {
4816
+ return e.setContext(this.getContext(i)).lineWidth;
4817
+ }
4818
+ return 0;
4819
+ }
4820
+ drawGrid(t) {
4821
+ const e = this.options.grid,
4822
+ i = this.ctx,
4823
+ s =
4824
+ this._gridLineItems ||
4825
+ (this._gridLineItems = this._computeGridLineItems(t));
4826
+ let n, o;
4827
+ const a = (t, e, s) => {
4828
+ s.width &&
4829
+ s.color &&
4830
+ (i.save(),
4831
+ (i.lineWidth = s.width),
4832
+ (i.strokeStyle = s.color),
4833
+ i.setLineDash(s.borderDash || []),
4834
+ (i.lineDashOffset = s.borderDashOffset),
4835
+ i.beginPath(),
4836
+ i.moveTo(t.x, t.y),
4837
+ i.lineTo(e.x, e.y),
4838
+ i.stroke(),
4839
+ i.restore());
4840
+ };
4841
+ if (e.display)
4842
+ for (n = 0, o = s.length; n < o; ++n) {
4843
+ const t = s[n];
4844
+ e.drawOnChartArea && a({ x: t.x1, y: t.y1 }, { x: t.x2, y: t.y2 }, t),
4845
+ e.drawTicks &&
4846
+ a(
4847
+ { x: t.tx1, y: t.ty1 },
4848
+ { x: t.tx2, y: t.ty2 },
4849
+ {
4850
+ color: t.tickColor,
4851
+ width: t.tickWidth,
4852
+ borderDash: t.tickBorderDash,
4853
+ borderDashOffset: t.tickBorderDashOffset,
4854
+ }
4855
+ );
4856
+ }
4857
+ }
4858
+ drawBorder() {
4859
+ const {
4860
+ chart: t,
4861
+ ctx: e,
4862
+ options: { grid: i },
4863
+ } = this,
4864
+ s = i.setContext(this.getContext()),
4865
+ n = i.drawBorder ? s.borderWidth : 0;
4866
+ if (!n) return;
4867
+ const o = i.setContext(this.getContext(0)).lineWidth,
4868
+ a = this._borderValue;
4869
+ let r, l, h, c;
4870
+ this.isHorizontal()
4871
+ ? ((r = Kt(t, this.left, n) - n / 2),
4872
+ (l = Kt(t, this.right, o) + o / 2),
4873
+ (h = c = a))
4874
+ : ((h = Kt(t, this.top, n) - n / 2),
4875
+ (c = Kt(t, this.bottom, o) + o / 2),
4876
+ (r = l = a)),
4877
+ e.save(),
4878
+ (e.lineWidth = s.borderWidth),
4879
+ (e.strokeStyle = s.borderColor),
4880
+ e.beginPath(),
4881
+ e.moveTo(r, h),
4882
+ e.lineTo(l, c),
4883
+ e.stroke(),
4884
+ e.restore();
4885
+ }
4886
+ drawLabels(t) {
4887
+ if (!this.options.ticks.display) return;
4888
+ const e = this.ctx,
4889
+ i = this._computeLabelArea();
4890
+ i && Qt(e, i);
4891
+ const s =
4892
+ this._labelItems || (this._labelItems = this._computeLabelItems(t));
4893
+ let n, o;
4894
+ for (n = 0, o = s.length; n < o; ++n) {
4895
+ const t = s[n],
4896
+ i = t.font,
4897
+ o = t.label;
4898
+ t.backdrop &&
4899
+ ((e.fillStyle = t.backdrop.color),
4900
+ e.fillRect(
4901
+ t.backdrop.left,
4902
+ t.backdrop.top,
4903
+ t.backdrop.width,
4904
+ t.backdrop.height
4905
+ )),
4906
+ se(e, o, 0, t.textOffset, i, t);
4907
+ }
4908
+ i && te(e);
4909
+ }
4910
+ drawTitle() {
4911
+ const {
4912
+ ctx: t,
4913
+ options: { position: e, title: i, reverse: s },
4914
+ } = this;
4915
+ if (!i.display) return;
4916
+ const o = He(i.font),
4917
+ a = Ne(i.padding),
4918
+ r = i.align;
4919
+ let l = o.lineHeight / 2;
4920
+ "bottom" === e || "center" === e || U(e)
4921
+ ? ((l += a.bottom),
4922
+ Y(i.text) && (l += o.lineHeight * (i.text.length - 1)))
4923
+ : (l += a.top);
4924
+ const {
4925
+ titleX: h,
4926
+ titleY: c,
4927
+ maxWidth: d,
4928
+ rotation: u,
4929
+ } = (function (t, e, i, s) {
4930
+ const { top: o, left: a, bottom: r, right: l, chart: h } = t,
4931
+ { chartArea: c, scales: d } = h;
4932
+ let u,
4933
+ f,
4934
+ g,
4935
+ p = 0;
4936
+ const m = r - o,
4937
+ x = l - a;
4938
+ if (t.isHorizontal()) {
4939
+ if (((f = n(s, a, l)), U(i))) {
4940
+ const t = Object.keys(i)[0],
4941
+ s = i[t];
4942
+ g = d[t].getPixelForValue(s) + m - e;
4943
+ } else
4944
+ g = "center" === i ? (c.bottom + c.top) / 2 + m - e : Ls(t, i, e);
4945
+ u = l - a;
4946
+ } else {
4947
+ if (U(i)) {
4948
+ const t = Object.keys(i)[0],
4949
+ s = i[t];
4950
+ f = d[t].getPixelForValue(s) - x + e;
4951
+ } else
4952
+ f = "center" === i ? (c.left + c.right) / 2 - x + e : Ls(t, i, e);
4953
+ (g = n(s, r, o)), (p = "left" === i ? -kt : kt);
4954
+ }
4955
+ return { titleX: f, titleY: g, maxWidth: u, rotation: p };
4956
+ })(this, l, e, r);
4957
+ se(t, i.text, 0, 0, o, {
4958
+ color: i.color,
4959
+ maxWidth: d,
4960
+ rotation: u,
4961
+ textAlign: Fs(r, e, s),
4962
+ textBaseline: "middle",
4963
+ translation: [h, c],
4964
+ });
4965
+ }
4966
+ draw(t) {
4967
+ this._isVisible() &&
4968
+ (this.drawBackground(),
4969
+ this.drawGrid(t),
4970
+ this.drawBorder(),
4971
+ this.drawTitle(),
4972
+ this.drawLabels(t));
4973
+ }
4974
+ _layers() {
4975
+ const t = this.options,
4976
+ e = (t.ticks && t.ticks.z) || 0,
4977
+ i = K(t.grid && t.grid.z, -1);
4978
+ return this._isVisible() && this.draw === Bs.prototype.draw
4979
+ ? [
4980
+ {
4981
+ z: i,
4982
+ draw: (t) => {
4983
+ this.drawBackground(), this.drawGrid(t), this.drawTitle();
4984
+ },
4985
+ },
4986
+ {
4987
+ z: i + 1,
4988
+ draw: () => {
4989
+ this.drawBorder();
4990
+ },
4991
+ },
4992
+ {
4993
+ z: e,
4994
+ draw: (t) => {
4995
+ this.drawLabels(t);
4996
+ },
4997
+ },
4998
+ ]
4999
+ : [
5000
+ {
5001
+ z: e,
5002
+ draw: (t) => {
5003
+ this.draw(t);
5004
+ },
5005
+ },
5006
+ ];
5007
+ }
5008
+ getMatchingVisibleMetas(t) {
5009
+ const e = this.chart.getSortedVisibleDatasetMetas(),
5010
+ i = this.axis + "AxisID",
5011
+ s = [];
5012
+ let n, o;
5013
+ for (n = 0, o = e.length; n < o; ++n) {
5014
+ const o = e[n];
5015
+ o[i] !== this.id || (t && o.type !== t) || s.push(o);
5016
+ }
5017
+ return s;
5018
+ }
5019
+ _resolveTickFontOptions(t) {
5020
+ return He(this.options.ticks.setContext(this.getContext(t)).font);
5021
+ }
5022
+ _maxDigits() {
5023
+ const t = this._resolveTickFontOptions(0).lineHeight;
5024
+ return (this.isHorizontal() ? this.width : this.height) / t;
5025
+ }
5026
+ }
5027
+ class Vs {
5028
+ constructor(t, e, i) {
5029
+ (this.type = t),
5030
+ (this.scope = e),
5031
+ (this.override = i),
5032
+ (this.items = Object.create(null));
5033
+ }
5034
+ isForType(t) {
5035
+ return Object.prototype.isPrototypeOf.call(
5036
+ this.type.prototype,
5037
+ t.prototype
5038
+ );
5039
+ }
5040
+ register(t) {
5041
+ const e = Object.getPrototypeOf(t);
5042
+ let i;
5043
+ (function (t) {
5044
+ return "id" in t && "defaults" in t;
5045
+ })(e) && (i = this.register(e));
5046
+ const s = this.items,
5047
+ n = t.id,
5048
+ o = this.scope + "." + n;
5049
+ if (!n) throw new Error("class does not have id: " + t);
5050
+ return (
5051
+ n in s ||
5052
+ ((s[n] = t),
5053
+ (function (t, e, i) {
5054
+ const s = nt(Object.create(null), [
5055
+ i ? bt.get(i) : {},
5056
+ bt.get(e),
5057
+ t.defaults,
5058
+ ]);
5059
+ bt.set(e, s),
5060
+ t.defaultRoutes &&
5061
+ (function (t, e) {
5062
+ Object.keys(e).forEach((i) => {
5063
+ const s = i.split("."),
5064
+ n = s.pop(),
5065
+ o = [t].concat(s).join("."),
5066
+ a = e[i].split("."),
5067
+ r = a.pop(),
5068
+ l = a.join(".");
5069
+ bt.route(o, n, l, r);
5070
+ });
5071
+ })(e, t.defaultRoutes);
5072
+ t.descriptors && bt.describe(e, t.descriptors);
5073
+ })(t, o, i),
5074
+ this.override && bt.override(t.id, t.overrides)),
5075
+ o
5076
+ );
5077
+ }
5078
+ get(t) {
5079
+ return this.items[t];
5080
+ }
5081
+ unregister(t) {
5082
+ const e = this.items,
5083
+ i = t.id,
5084
+ s = this.scope;
5085
+ i in e && delete e[i],
5086
+ s && i in bt[s] && (delete bt[s][i], this.override && delete gt[i]);
5087
+ }
5088
+ }
5089
+ var Ws = new (class {
5090
+ constructor() {
5091
+ (this.controllers = new Vs(Ps, "datasets", !0)),
5092
+ (this.elements = new Vs(Ds, "elements")),
5093
+ (this.plugins = new Vs(Object, "plugins")),
5094
+ (this.scales = new Vs(Bs, "scales")),
5095
+ (this._typedRegistries = [
5096
+ this.controllers,
5097
+ this.scales,
5098
+ this.elements,
5099
+ ]);
5100
+ }
5101
+ add(...t) {
5102
+ this._each("register", t);
5103
+ }
5104
+ remove(...t) {
5105
+ this._each("unregister", t);
5106
+ }
5107
+ addControllers(...t) {
5108
+ this._each("register", t, this.controllers);
5109
+ }
5110
+ addElements(...t) {
5111
+ this._each("register", t, this.elements);
5112
+ }
5113
+ addPlugins(...t) {
5114
+ this._each("register", t, this.plugins);
5115
+ }
5116
+ addScales(...t) {
5117
+ this._each("register", t, this.scales);
5118
+ }
5119
+ getController(t) {
5120
+ return this._get(t, this.controllers, "controller");
5121
+ }
5122
+ getElement(t) {
5123
+ return this._get(t, this.elements, "element");
5124
+ }
5125
+ getPlugin(t) {
5126
+ return this._get(t, this.plugins, "plugin");
5127
+ }
5128
+ getScale(t) {
5129
+ return this._get(t, this.scales, "scale");
5130
+ }
5131
+ removeControllers(...t) {
5132
+ this._each("unregister", t, this.controllers);
5133
+ }
5134
+ removeElements(...t) {
5135
+ this._each("unregister", t, this.elements);
5136
+ }
5137
+ removePlugins(...t) {
5138
+ this._each("unregister", t, this.plugins);
5139
+ }
5140
+ removeScales(...t) {
5141
+ this._each("unregister", t, this.scales);
5142
+ }
5143
+ _each(t, e, i) {
5144
+ [...e].forEach((e) => {
5145
+ const s = i || this._getRegistryForType(e);
5146
+ i || s.isForType(e) || (s === this.plugins && e.id)
5147
+ ? this._exec(t, s, e)
5148
+ : Q(e, (e) => {
5149
+ const s = i || this._getRegistryForType(e);
5150
+ this._exec(t, s, e);
5151
+ });
5152
+ });
5153
+ }
5154
+ _exec(t, e, i) {
5155
+ const s = ht(t);
5156
+ J(i["before" + s], [], i), e[t](i), J(i["after" + s], [], i);
5157
+ }
5158
+ _getRegistryForType(t) {
5159
+ for (let e = 0; e < this._typedRegistries.length; e++) {
5160
+ const i = this._typedRegistries[e];
5161
+ if (i.isForType(t)) return i;
5162
+ }
5163
+ return this.plugins;
5164
+ }
5165
+ _get(t, e, i) {
5166
+ const s = e.get(t);
5167
+ if (void 0 === s)
5168
+ throw new Error('"' + t + '" is not a registered ' + i + ".");
5169
+ return s;
5170
+ }
5171
+ })();
5172
+ class Ns {
5173
+ constructor() {
5174
+ this._init = [];
5175
+ }
5176
+ notify(t, e, i, s) {
5177
+ "beforeInit" === e &&
5178
+ ((this._init = this._createDescriptors(t, !0)),
5179
+ this._notify(this._init, t, "install"));
5180
+ const n = s ? this._descriptors(t).filter(s) : this._descriptors(t),
5181
+ o = this._notify(n, t, e, i);
5182
+ return (
5183
+ "afterDestroy" === e &&
5184
+ (this._notify(n, t, "stop"),
5185
+ this._notify(this._init, t, "uninstall")),
5186
+ o
5187
+ );
5188
+ }
5189
+ _notify(t, e, i, s) {
5190
+ s = s || {};
5191
+ for (const n of t) {
5192
+ const t = n.plugin;
5193
+ if (!1 === J(t[i], [e, s, n.options], t) && s.cancelable) return !1;
5194
+ }
5195
+ return !0;
5196
+ }
5197
+ invalidate() {
5198
+ $(this._cache) ||
5199
+ ((this._oldCache = this._cache), (this._cache = void 0));
5200
+ }
5201
+ _descriptors(t) {
5202
+ if (this._cache) return this._cache;
5203
+ const e = (this._cache = this._createDescriptors(t));
5204
+ return this._notifyStateChanges(t), e;
5205
+ }
5206
+ _createDescriptors(t, e) {
5207
+ const i = t && t.config,
5208
+ s = K(i.options && i.options.plugins, {}),
5209
+ n = (function (t) {
5210
+ const e = [],
5211
+ i = Object.keys(Ws.plugins.items);
5212
+ for (let t = 0; t < i.length; t++) e.push(Ws.getPlugin(i[t]));
5213
+ const s = t.plugins || [];
5214
+ for (let t = 0; t < s.length; t++) {
5215
+ const i = s[t];
5216
+ -1 === e.indexOf(i) && e.push(i);
5217
+ }
5218
+ return e;
5219
+ })(i);
5220
+ return !1 !== s || e
5221
+ ? (function (t, e, i, s) {
5222
+ const n = [],
5223
+ o = t.getContext();
5224
+ for (let a = 0; a < e.length; a++) {
5225
+ const r = e[a],
5226
+ l = Hs(i[r.id], s);
5227
+ null !== l &&
5228
+ n.push({ plugin: r, options: js(t.config, r, l, o) });
5229
+ }
5230
+ return n;
5231
+ })(t, n, s, e)
5232
+ : [];
5233
+ }
5234
+ _notifyStateChanges(t) {
5235
+ const e = this._oldCache || [],
5236
+ i = this._cache,
5237
+ s = (t, e) =>
5238
+ t.filter((t) => !e.some((e) => t.plugin.id === e.plugin.id));
5239
+ this._notify(s(e, i), t, "stop"), this._notify(s(i, e), t, "start");
5240
+ }
5241
+ }
5242
+ function Hs(t, e) {
5243
+ return e || !1 !== t ? (!0 === t ? {} : t) : null;
5244
+ }
5245
+ function js(t, e, i, s) {
5246
+ const n = t.pluginScopeKeys(e),
5247
+ o = t.getOptionScopes(i, n);
5248
+ return t.createResolver(o, s, [""], {
5249
+ scriptable: !1,
5250
+ indexable: !1,
5251
+ allKeys: !0,
5252
+ });
5253
+ }
5254
+ function $s(t, e) {
5255
+ const i = bt.datasets[t] || {};
5256
+ return (
5257
+ ((e.datasets || {})[t] || {}).indexAxis ||
5258
+ e.indexAxis ||
5259
+ i.indexAxis ||
5260
+ "x"
5261
+ );
5262
+ }
5263
+ function Ys(t, e) {
5264
+ return "x" === t || "y" === t
5265
+ ? t
5266
+ : e.axis ||
5267
+ ("top" === (i = e.position) || "bottom" === i
5268
+ ? "x"
5269
+ : "left" === i || "right" === i
5270
+ ? "y"
5271
+ : void 0) ||
5272
+ t.charAt(0).toLowerCase();
5273
+ var i;
5274
+ }
5275
+ function Us(t) {
5276
+ const e = t.options || (t.options = {});
5277
+ (e.plugins = K(e.plugins, {})),
5278
+ (e.scales = (function (t, e) {
5279
+ const i = gt[t.type] || { scales: {} },
5280
+ s = e.scales || {},
5281
+ n = $s(t.type, e),
5282
+ o = Object.create(null),
5283
+ a = Object.create(null);
5284
+ return (
5285
+ Object.keys(s).forEach((t) => {
5286
+ const e = s[t];
5287
+ if (!U(e))
5288
+ return console.error(
5289
+ `Invalid scale configuration for scale: ${t}`
5290
+ );
5291
+ if (e._proxy)
5292
+ return console.warn(
5293
+ `Ignoring resolver passed as options for scale: ${t}`
5294
+ );
5295
+ const r = Ys(t, e),
5296
+ l = (function (t, e) {
5297
+ return t === e ? "_index_" : "_value_";
5298
+ })(r, n),
5299
+ h = i.scales || {};
5300
+ (o[r] = o[r] || t),
5301
+ (a[t] = ot(Object.create(null), [{ axis: r }, e, h[r], h[l]]));
5302
+ }),
5303
+ t.data.datasets.forEach((i) => {
5304
+ const n = i.type || t.type,
5305
+ r = i.indexAxis || $s(n, e),
5306
+ l = (gt[n] || {}).scales || {};
5307
+ Object.keys(l).forEach((t) => {
5308
+ const e = (function (t, e) {
5309
+ let i = t;
5310
+ return (
5311
+ "_index_" === t
5312
+ ? (i = e)
5313
+ : "_value_" === t && (i = "x" === e ? "y" : "x"),
5314
+ i
5315
+ );
5316
+ })(t, r),
5317
+ n = i[e + "AxisID"] || o[e] || e;
5318
+ (a[n] = a[n] || Object.create(null)),
5319
+ ot(a[n], [{ axis: e }, s[n], l[t]]);
5320
+ });
5321
+ }),
5322
+ Object.keys(a).forEach((t) => {
5323
+ const e = a[t];
5324
+ ot(e, [bt.scales[e.type], bt.scale]);
5325
+ }),
5326
+ a
5327
+ );
5328
+ })(t, e));
5329
+ }
5330
+ function Xs(t) {
5331
+ return (
5332
+ ((t = t || {}).datasets = t.datasets || []),
5333
+ (t.labels = t.labels || []),
5334
+ t
5335
+ );
5336
+ }
5337
+ const qs = new Map(),
5338
+ Ks = new Set();
5339
+ function Gs(t, e) {
5340
+ let i = qs.get(t);
5341
+ return i || ((i = e()), qs.set(t, i), Ks.add(i)), i;
5342
+ }
5343
+ const Zs = (t, e, i) => {
5344
+ const s = lt(e, i);
5345
+ void 0 !== s && t.add(s);
5346
+ };
5347
+ class Js {
5348
+ constructor(t) {
5349
+ (this._config = (function (t) {
5350
+ return ((t = t || {}).data = Xs(t.data)), Us(t), t;
5351
+ })(t)),
5352
+ (this._scopeCache = new Map()),
5353
+ (this._resolverCache = new Map());
5354
+ }
5355
+ get platform() {
5356
+ return this._config.platform;
5357
+ }
5358
+ get type() {
5359
+ return this._config.type;
5360
+ }
5361
+ set type(t) {
5362
+ this._config.type = t;
5363
+ }
5364
+ get data() {
5365
+ return this._config.data;
5366
+ }
5367
+ set data(t) {
5368
+ this._config.data = Xs(t);
5369
+ }
5370
+ get options() {
5371
+ return this._config.options;
5372
+ }
5373
+ set options(t) {
5374
+ this._config.options = t;
5375
+ }
5376
+ get plugins() {
5377
+ return this._config.plugins;
5378
+ }
5379
+ update() {
5380
+ const t = this._config;
5381
+ this.clearCache(), Us(t);
5382
+ }
5383
+ clearCache() {
5384
+ this._scopeCache.clear(), this._resolverCache.clear();
5385
+ }
5386
+ datasetScopeKeys(t) {
5387
+ return Gs(t, () => [[`datasets.${t}`, ""]]);
5388
+ }
5389
+ datasetAnimationScopeKeys(t, e) {
5390
+ return Gs(`${t}.transition.${e}`, () => [
5391
+ [`datasets.${t}.transitions.${e}`, `transitions.${e}`],
5392
+ [`datasets.${t}`, ""],
5393
+ ]);
5394
+ }
5395
+ datasetElementScopeKeys(t, e) {
5396
+ return Gs(`${t}-${e}`, () => [
5397
+ [`datasets.${t}.elements.${e}`, `datasets.${t}`, `elements.${e}`, ""],
5398
+ ]);
5399
+ }
5400
+ pluginScopeKeys(t) {
5401
+ const e = t.id;
5402
+ return Gs(`${this.type}-plugin-${e}`, () => [
5403
+ [`plugins.${e}`, ...(t.additionalOptionScopes || [])],
5404
+ ]);
5405
+ }
5406
+ _cachedScopes(t, e) {
5407
+ const i = this._scopeCache;
5408
+ let s = i.get(t);
5409
+ return (s && !e) || ((s = new Map()), i.set(t, s)), s;
5410
+ }
5411
+ getOptionScopes(t, e, i) {
5412
+ const { options: s, type: n } = this,
5413
+ o = this._cachedScopes(t, i),
5414
+ a = o.get(e);
5415
+ if (a) return a;
5416
+ const r = new Set();
5417
+ e.forEach((e) => {
5418
+ t && (r.add(t), e.forEach((e) => Zs(r, t, e))),
5419
+ e.forEach((t) => Zs(r, s, t)),
5420
+ e.forEach((t) => Zs(r, gt[n] || {}, t)),
5421
+ e.forEach((t) => Zs(r, bt, t)),
5422
+ e.forEach((t) => Zs(r, pt, t));
5423
+ });
5424
+ const l = Array.from(r);
5425
+ return (
5426
+ 0 === l.length && l.push(Object.create(null)),
5427
+ Ks.has(e) && o.set(e, l),
5428
+ l
5429
+ );
5430
+ }
5431
+ chartOptionScopes() {
5432
+ const { options: t, type: e } = this;
5433
+ return [t, gt[e] || {}, bt.datasets[e] || {}, { type: e }, bt, pt];
5434
+ }
5435
+ resolveNamedOptions(t, e, i, s = [""]) {
5436
+ const n = { $shared: !0 },
5437
+ { resolver: o, subPrefixes: a } = Qs(this._resolverCache, t, s);
5438
+ let r = o;
5439
+ if (
5440
+ (function (t, e) {
5441
+ const { isScriptable: i, isIndexable: s } = ri(t);
5442
+ for (const n of e) {
5443
+ const e = i(n),
5444
+ o = s(n),
5445
+ a = (o || e) && t[n];
5446
+ if ((e && (dt(a) || tn(a))) || (o && Y(a))) return !0;
5447
+ }
5448
+ return !1;
5449
+ })(o, e)
5450
+ ) {
5451
+ n.$shared = !1;
5452
+ r = ai(o, (i = dt(i) ? i() : i), this.createResolver(t, i, a));
5453
+ }
5454
+ for (const t of e) n[t] = r[t];
5455
+ return n;
5456
+ }
5457
+ createResolver(t, e, i = [""], s) {
5458
+ const { resolver: n } = Qs(this._resolverCache, t, i);
5459
+ return U(e) ? ai(n, e, void 0, s) : n;
5460
+ }
5461
+ }
5462
+ function Qs(t, e, i) {
5463
+ let s = t.get(e);
5464
+ s || ((s = new Map()), t.set(e, s));
5465
+ const n = i.join();
5466
+ let o = s.get(n);
5467
+ if (!o) {
5468
+ (o = {
5469
+ resolver: oi(e, i),
5470
+ subPrefixes: i.filter((t) => !t.toLowerCase().includes("hover")),
5471
+ }),
5472
+ s.set(n, o);
5473
+ }
5474
+ return o;
5475
+ }
5476
+ const tn = (t) =>
5477
+ U(t) && Object.getOwnPropertyNames(t).reduce((e, i) => e || dt(t[i]), !1);
5478
+ const en = ["top", "bottom", "left", "right", "chartArea"];
5479
+ function sn(t, e) {
5480
+ return "top" === t || "bottom" === t || (-1 === en.indexOf(t) && "x" === e);
5481
+ }
5482
+ function nn(t, e) {
5483
+ return function (i, s) {
5484
+ return i[t] === s[t] ? i[e] - s[e] : i[t] - s[t];
5485
+ };
5486
+ }
5487
+ function on(t) {
5488
+ const e = t.chart,
5489
+ i = e.options.animation;
5490
+ e.notifyPlugins("afterRender"), J(i && i.onComplete, [t], e);
5491
+ }
5492
+ function an(t) {
5493
+ const e = t.chart,
5494
+ i = e.options.animation;
5495
+ J(i && i.onProgress, [t], e);
5496
+ }
5497
+ function rn(t) {
5498
+ return (
5499
+ ge() && "string" == typeof t
5500
+ ? (t = document.getElementById(t))
5501
+ : t && t.length && (t = t[0]),
5502
+ t && t.canvas && (t = t.canvas),
5503
+ t
5504
+ );
5505
+ }
5506
+ const ln = {},
5507
+ hn = (t) => {
5508
+ const e = rn(t);
5509
+ return Object.values(ln)
5510
+ .filter((t) => t.canvas === e)
5511
+ .pop();
5512
+ };
5513
+ function cn(t, e, i) {
5514
+ const s = Object.keys(t);
5515
+ for (const n of s) {
5516
+ const s = +n;
5517
+ if (s >= e) {
5518
+ const o = t[n];
5519
+ delete t[n], (i > 0 || s > e) && (t[s + i] = o);
5520
+ }
5521
+ }
5522
+ }
5523
+ class dn {
5524
+ constructor(t, e) {
5525
+ const s = (this.config = new Js(e)),
5526
+ n = rn(t),
5527
+ o = hn(n);
5528
+ if (o)
5529
+ throw new Error(
5530
+ "Canvas is already in use. Chart with ID '" +
5531
+ o.id +
5532
+ "' must be destroyed before the canvas can be reused."
5533
+ );
5534
+ const r = s.createResolver(s.chartOptionScopes(), this.getContext());
5535
+ (this.platform = new (s.platform || ls(n))()),
5536
+ this.platform.updateConfig(s);
5537
+ const l = this.platform.acquireContext(n, r.aspectRatio),
5538
+ h = l && l.canvas,
5539
+ c = h && h.height,
5540
+ d = h && h.width;
5541
+ (this.id = j()),
5542
+ (this.ctx = l),
5543
+ (this.canvas = h),
5544
+ (this.width = d),
5545
+ (this.height = c),
5546
+ (this._options = r),
5547
+ (this._aspectRatio = this.aspectRatio),
5548
+ (this._layers = []),
5549
+ (this._metasets = []),
5550
+ (this._stacks = void 0),
5551
+ (this.boxes = []),
5552
+ (this.currentDevicePixelRatio = void 0),
5553
+ (this.chartArea = void 0),
5554
+ (this._active = []),
5555
+ (this._lastEvent = void 0),
5556
+ (this._listeners = {}),
5557
+ (this._responsiveListeners = void 0),
5558
+ (this._sortedMetasets = []),
5559
+ (this.scales = {}),
5560
+ (this._plugins = new Ns()),
5561
+ (this.$proxies = {}),
5562
+ (this._hiddenIndices = {}),
5563
+ (this.attached = !1),
5564
+ (this._animationsDisabled = void 0),
5565
+ (this.$context = void 0),
5566
+ (this._doResize = i((t) => this.update(t), r.resizeDelay || 0)),
5567
+ (this._dataChanges = []),
5568
+ (ln[this.id] = this),
5569
+ l && h
5570
+ ? (a.listen(this, "complete", on),
5571
+ a.listen(this, "progress", an),
5572
+ this._initialize(),
5573
+ this.attached && this.update())
5574
+ : console.error(
5575
+ "Failed to create chart: can't acquire context from the given item"
5576
+ );
5577
+ }
5578
+ get aspectRatio() {
5579
+ const {
5580
+ options: { aspectRatio: t, maintainAspectRatio: e },
5581
+ width: i,
5582
+ height: s,
5583
+ _aspectRatio: n,
5584
+ } = this;
5585
+ return $(t) ? (e && n ? n : s ? i / s : null) : t;
5586
+ }
5587
+ get data() {
5588
+ return this.config.data;
5589
+ }
5590
+ set data(t) {
5591
+ this.config.data = t;
5592
+ }
5593
+ get options() {
5594
+ return this._options;
5595
+ }
5596
+ set options(t) {
5597
+ this.config.options = t;
5598
+ }
5599
+ _initialize() {
5600
+ return (
5601
+ this.notifyPlugins("beforeInit"),
5602
+ this.options.responsive
5603
+ ? this.resize()
5604
+ : ke(this, this.options.devicePixelRatio),
5605
+ this.bindEvents(),
5606
+ this.notifyPlugins("afterInit"),
5607
+ this
5608
+ );
5609
+ }
5610
+ clear() {
5611
+ return Gt(this.canvas, this.ctx), this;
5612
+ }
5613
+ stop() {
5614
+ return a.stop(this), this;
5615
+ }
5616
+ resize(t, e) {
5617
+ a.running(this)
5618
+ ? (this._resizeBeforeDraw = { width: t, height: e })
5619
+ : this._resize(t, e);
5620
+ }
5621
+ _resize(t, e) {
5622
+ const i = this.options,
5623
+ s = this.canvas,
5624
+ n = i.maintainAspectRatio && this.aspectRatio,
5625
+ o = this.platform.getMaximumSize(s, t, e, n),
5626
+ a = i.devicePixelRatio || this.platform.getDevicePixelRatio(),
5627
+ r = this.width ? "resize" : "attach";
5628
+ (this.width = o.width),
5629
+ (this.height = o.height),
5630
+ (this._aspectRatio = this.aspectRatio),
5631
+ ke(this, a, !0) &&
5632
+ (this.notifyPlugins("resize", { size: o }),
5633
+ J(i.onResize, [this, o], this),
5634
+ this.attached && this._doResize(r) && this.render());
5635
+ }
5636
+ ensureScalesHaveIDs() {
5637
+ Q(this.options.scales || {}, (t, e) => {
5638
+ t.id = e;
5639
+ });
5640
+ }
5641
+ buildOrUpdateScales() {
5642
+ const t = this.options,
5643
+ e = t.scales,
5644
+ i = this.scales,
5645
+ s = Object.keys(i).reduce((t, e) => ((t[e] = !1), t), {});
5646
+ let n = [];
5647
+ e &&
5648
+ (n = n.concat(
5649
+ Object.keys(e).map((t) => {
5650
+ const i = e[t],
5651
+ s = Ys(t, i),
5652
+ n = "r" === s,
5653
+ o = "x" === s;
5654
+ return {
5655
+ options: i,
5656
+ dposition: n ? "chartArea" : o ? "bottom" : "left",
5657
+ dtype: n ? "radialLinear" : o ? "category" : "linear",
5658
+ };
5659
+ })
5660
+ )),
5661
+ Q(n, (e) => {
5662
+ const n = e.options,
5663
+ o = n.id,
5664
+ a = Ys(o, n),
5665
+ r = K(n.type, e.dtype);
5666
+ (void 0 !== n.position && sn(n.position, a) === sn(e.dposition)) ||
5667
+ (n.position = e.dposition),
5668
+ (s[o] = !0);
5669
+ let l = null;
5670
+ if (o in i && i[o].type === r) l = i[o];
5671
+ else {
5672
+ (l = new (Ws.getScale(r))({
5673
+ id: o,
5674
+ type: r,
5675
+ ctx: this.ctx,
5676
+ chart: this,
5677
+ })),
5678
+ (i[l.id] = l);
5679
+ }
5680
+ l.init(n, t);
5681
+ }),
5682
+ Q(s, (t, e) => {
5683
+ t || delete i[e];
5684
+ }),
5685
+ Q(i, (t) => {
5686
+ ni.configure(this, t, t.options), ni.addBox(this, t);
5687
+ });
5688
+ }
5689
+ _updateMetasets() {
5690
+ const t = this._metasets,
5691
+ e = this.data.datasets.length,
5692
+ i = t.length;
5693
+ if ((t.sort((t, e) => t.index - e.index), i > e)) {
5694
+ for (let t = e; t < i; ++t) this._destroyDatasetMeta(t);
5695
+ t.splice(e, i - e);
5696
+ }
5697
+ this._sortedMetasets = t.slice(0).sort(nn("order", "index"));
5698
+ }
5699
+ _removeUnreferencedMetasets() {
5700
+ const {
5701
+ _metasets: t,
5702
+ data: { datasets: e },
5703
+ } = this;
5704
+ t.length > e.length && delete this._stacks,
5705
+ t.forEach((t, i) => {
5706
+ 0 === e.filter((e) => e === t._dataset).length &&
5707
+ this._destroyDatasetMeta(i);
5708
+ });
5709
+ }
5710
+ buildOrUpdateControllers() {
5711
+ const t = [],
5712
+ e = this.data.datasets;
5713
+ let i, s;
5714
+ for (
5715
+ this._removeUnreferencedMetasets(), i = 0, s = e.length;
5716
+ i < s;
5717
+ i++
5718
+ ) {
5719
+ const s = e[i];
5720
+ let n = this.getDatasetMeta(i);
5721
+ const o = s.type || this.config.type;
5722
+ if (
5723
+ (n.type &&
5724
+ n.type !== o &&
5725
+ (this._destroyDatasetMeta(i), (n = this.getDatasetMeta(i))),
5726
+ (n.type = o),
5727
+ (n.indexAxis = s.indexAxis || $s(o, this.options)),
5728
+ (n.order = s.order || 0),
5729
+ (n.index = i),
5730
+ (n.label = "" + s.label),
5731
+ (n.visible = this.isDatasetVisible(i)),
5732
+ n.controller)
5733
+ )
5734
+ n.controller.updateIndex(i), n.controller.linkScales();
5735
+ else {
5736
+ const e = Ws.getController(o),
5737
+ { datasetElementType: s, dataElementType: a } = bt.datasets[o];
5738
+ Object.assign(e.prototype, {
5739
+ dataElementType: Ws.getElement(a),
5740
+ datasetElementType: s && Ws.getElement(s),
5741
+ }),
5742
+ (n.controller = new e(this, i)),
5743
+ t.push(n.controller);
5744
+ }
5745
+ }
5746
+ return this._updateMetasets(), t;
5747
+ }
5748
+ _resetElements() {
5749
+ Q(
5750
+ this.data.datasets,
5751
+ (t, e) => {
5752
+ this.getDatasetMeta(e).controller.reset();
5753
+ },
5754
+ this
5755
+ );
5756
+ }
5757
+ reset() {
5758
+ this._resetElements(), this.notifyPlugins("reset");
5759
+ }
5760
+ update(t) {
5761
+ const e = this.config;
5762
+ e.update();
5763
+ const i = (this._options = e.createResolver(
5764
+ e.chartOptionScopes(),
5765
+ this.getContext()
5766
+ )),
5767
+ s = (this._animationsDisabled = !i.animation);
5768
+ if (
5769
+ (this._updateScales(),
5770
+ this._checkEventBindings(),
5771
+ this._updateHiddenIndices(),
5772
+ this._plugins.invalidate(),
5773
+ !1 === this.notifyPlugins("beforeUpdate", { mode: t, cancelable: !0 }))
5774
+ )
5775
+ return;
5776
+ const n = this.buildOrUpdateControllers();
5777
+ this.notifyPlugins("beforeElementsUpdate");
5778
+ let o = 0;
5779
+ for (let t = 0, e = this.data.datasets.length; t < e; t++) {
5780
+ const { controller: e } = this.getDatasetMeta(t),
5781
+ i = !s && -1 === n.indexOf(e);
5782
+ e.buildOrUpdateElements(i), (o = Math.max(+e.getMaxOverflow(), o));
5783
+ }
5784
+ (o = this._minPadding = i.layout.autoPadding ? o : 0),
5785
+ this._updateLayout(o),
5786
+ s ||
5787
+ Q(n, (t) => {
5788
+ t.reset();
5789
+ }),
5790
+ this._updateDatasets(t),
5791
+ this.notifyPlugins("afterUpdate", { mode: t }),
5792
+ this._layers.sort(nn("z", "_idx"));
5793
+ const { _active: a, _lastEvent: r } = this;
5794
+ r
5795
+ ? this._eventHandler(r, !0)
5796
+ : a.length && this._updateHoverStyles(a, a, !0),
5797
+ this.render();
5798
+ }
5799
+ _updateScales() {
5800
+ Q(this.scales, (t) => {
5801
+ ni.removeBox(this, t);
5802
+ }),
5803
+ this.ensureScalesHaveIDs(),
5804
+ this.buildOrUpdateScales();
5805
+ }
5806
+ _checkEventBindings() {
5807
+ const t = this.options,
5808
+ e = new Set(Object.keys(this._listeners)),
5809
+ i = new Set(t.events);
5810
+ (ut(e, i) && !!this._responsiveListeners === t.responsive) ||
5811
+ (this.unbindEvents(), this.bindEvents());
5812
+ }
5813
+ _updateHiddenIndices() {
5814
+ const { _hiddenIndices: t } = this,
5815
+ e = this._getUniformDataChanges() || [];
5816
+ for (const { method: i, start: s, count: n } of e) {
5817
+ cn(t, s, "_removeElements" === i ? -n : n);
5818
+ }
5819
+ }
5820
+ _getUniformDataChanges() {
5821
+ const t = this._dataChanges;
5822
+ if (!t || !t.length) return;
5823
+ this._dataChanges = [];
5824
+ const e = this.data.datasets.length,
5825
+ i = (e) =>
5826
+ new Set(
5827
+ t
5828
+ .filter((t) => t[0] === e)
5829
+ .map((t, e) => e + "," + t.splice(1).join(","))
5830
+ ),
5831
+ s = i(0);
5832
+ for (let t = 1; t < e; t++) if (!ut(s, i(t))) return;
5833
+ return Array.from(s)
5834
+ .map((t) => t.split(","))
5835
+ .map((t) => ({ method: t[1], start: +t[2], count: +t[3] }));
5836
+ }
5837
+ _updateLayout(t) {
5838
+ if (!1 === this.notifyPlugins("beforeLayout", { cancelable: !0 })) return;
5839
+ ni.update(this, this.width, this.height, t);
5840
+ const e = this.chartArea,
5841
+ i = e.width <= 0 || e.height <= 0;
5842
+ (this._layers = []),
5843
+ Q(
5844
+ this.boxes,
5845
+ (t) => {
5846
+ (i && "chartArea" === t.position) ||
5847
+ (t.configure && t.configure(), this._layers.push(...t._layers()));
5848
+ },
5849
+ this
5850
+ ),
5851
+ this._layers.forEach((t, e) => {
5852
+ t._idx = e;
5853
+ }),
5854
+ this.notifyPlugins("afterLayout");
5855
+ }
5856
+ _updateDatasets(t) {
5857
+ if (
5858
+ !1 !==
5859
+ this.notifyPlugins("beforeDatasetsUpdate", { mode: t, cancelable: !0 })
5860
+ ) {
5861
+ for (let t = 0, e = this.data.datasets.length; t < e; ++t)
5862
+ this.getDatasetMeta(t).controller.configure();
5863
+ for (let e = 0, i = this.data.datasets.length; e < i; ++e)
5864
+ this._updateDataset(e, dt(t) ? t({ datasetIndex: e }) : t);
5865
+ this.notifyPlugins("afterDatasetsUpdate", { mode: t });
5866
+ }
5867
+ }
5868
+ _updateDataset(t, e) {
5869
+ const i = this.getDatasetMeta(t),
5870
+ s = { meta: i, index: t, mode: e, cancelable: !0 };
5871
+ !1 !== this.notifyPlugins("beforeDatasetUpdate", s) &&
5872
+ (i.controller._update(e),
5873
+ (s.cancelable = !1),
5874
+ this.notifyPlugins("afterDatasetUpdate", s));
5875
+ }
5876
+ render() {
5877
+ !1 !== this.notifyPlugins("beforeRender", { cancelable: !0 }) &&
5878
+ (a.has(this)
5879
+ ? this.attached && !a.running(this) && a.start(this)
5880
+ : (this.draw(), on({ chart: this })));
5881
+ }
5882
+ draw() {
5883
+ let t;
5884
+ if (this._resizeBeforeDraw) {
5885
+ const { width: t, height: e } = this._resizeBeforeDraw;
5886
+ this._resize(t, e), (this._resizeBeforeDraw = null);
5887
+ }
5888
+ if ((this.clear(), this.width <= 0 || this.height <= 0)) return;
5889
+ if (!1 === this.notifyPlugins("beforeDraw", { cancelable: !0 })) return;
5890
+ const e = this._layers;
5891
+ for (t = 0; t < e.length && e[t].z <= 0; ++t) e[t].draw(this.chartArea);
5892
+ for (this._drawDatasets(); t < e.length; ++t) e[t].draw(this.chartArea);
5893
+ this.notifyPlugins("afterDraw");
5894
+ }
5895
+ _getSortedDatasetMetas(t) {
5896
+ const e = this._sortedMetasets,
5897
+ i = [];
5898
+ let s, n;
5899
+ for (s = 0, n = e.length; s < n; ++s) {
5900
+ const n = e[s];
5901
+ (t && !n.visible) || i.push(n);
5902
+ }
5903
+ return i;
5904
+ }
5905
+ getSortedVisibleDatasetMetas() {
5906
+ return this._getSortedDatasetMetas(!0);
5907
+ }
5908
+ _drawDatasets() {
5909
+ if (!1 === this.notifyPlugins("beforeDatasetsDraw", { cancelable: !0 }))
5910
+ return;
5911
+ const t = this.getSortedVisibleDatasetMetas();
5912
+ for (let e = t.length - 1; e >= 0; --e) this._drawDataset(t[e]);
5913
+ this.notifyPlugins("afterDatasetsDraw");
5914
+ }
5915
+ _drawDataset(t) {
5916
+ const e = this.ctx,
5917
+ i = t._clip,
5918
+ s = !i.disabled,
5919
+ n = this.chartArea,
5920
+ o = { meta: t, index: t.index, cancelable: !0 };
5921
+ !1 !== this.notifyPlugins("beforeDatasetDraw", o) &&
5922
+ (s &&
5923
+ Qt(e, {
5924
+ left: !1 === i.left ? 0 : n.left - i.left,
5925
+ right: !1 === i.right ? this.width : n.right + i.right,
5926
+ top: !1 === i.top ? 0 : n.top - i.top,
5927
+ bottom: !1 === i.bottom ? this.height : n.bottom + i.bottom,
5928
+ }),
5929
+ t.controller.draw(),
5930
+ s && te(e),
5931
+ (o.cancelable = !1),
5932
+ this.notifyPlugins("afterDatasetDraw", o));
5933
+ }
5934
+ getElementsAtEventForMode(t, e, i, s) {
5935
+ const n = Ee.modes[e];
5936
+ return "function" == typeof n ? n(this, t, i, s) : [];
5937
+ }
5938
+ getDatasetMeta(t) {
5939
+ const e = this.data.datasets[t],
5940
+ i = this._metasets;
5941
+ let s = i.filter((t) => t && t._dataset === e).pop();
5942
+ return (
5943
+ s ||
5944
+ ((s = {
5945
+ type: null,
5946
+ data: [],
5947
+ dataset: null,
5948
+ controller: null,
5949
+ hidden: null,
5950
+ xAxisID: null,
5951
+ yAxisID: null,
5952
+ order: (e && e.order) || 0,
5953
+ index: t,
5954
+ _dataset: e,
5955
+ _parsed: [],
5956
+ _sorted: !1,
5957
+ }),
5958
+ i.push(s)),
5959
+ s
5960
+ );
5961
+ }
5962
+ getContext() {
5963
+ return (
5964
+ this.$context ||
5965
+ (this.$context = Ye(null, { chart: this, type: "chart" }))
5966
+ );
5967
+ }
5968
+ getVisibleDatasetCount() {
5969
+ return this.getSortedVisibleDatasetMetas().length;
5970
+ }
5971
+ isDatasetVisible(t) {
5972
+ const e = this.data.datasets[t];
5973
+ if (!e) return !1;
5974
+ const i = this.getDatasetMeta(t);
5975
+ return "boolean" == typeof i.hidden ? !i.hidden : !e.hidden;
5976
+ }
5977
+ setDatasetVisibility(t, e) {
5978
+ this.getDatasetMeta(t).hidden = !e;
5979
+ }
5980
+ toggleDataVisibility(t) {
5981
+ this._hiddenIndices[t] = !this._hiddenIndices[t];
5982
+ }
5983
+ getDataVisibility(t) {
5984
+ return !this._hiddenIndices[t];
5985
+ }
5986
+ _updateVisibility(t, e, i) {
5987
+ const s = i ? "show" : "hide",
5988
+ n = this.getDatasetMeta(t),
5989
+ o = n.controller._resolveAnimations(void 0, s);
5990
+ ct(e)
5991
+ ? ((n.data[e].hidden = !i), this.update())
5992
+ : (this.setDatasetVisibility(t, i),
5993
+ o.update(n, { visible: i }),
5994
+ this.update((e) => (e.datasetIndex === t ? s : void 0)));
5995
+ }
5996
+ hide(t, e) {
5997
+ this._updateVisibility(t, e, !1);
5998
+ }
5999
+ show(t, e) {
6000
+ this._updateVisibility(t, e, !0);
6001
+ }
6002
+ _destroyDatasetMeta(t) {
6003
+ const e = this._metasets[t];
6004
+ e && e.controller && e.controller._destroy(), delete this._metasets[t];
6005
+ }
6006
+ _stop() {
6007
+ let t, e;
6008
+ for (
6009
+ this.stop(), a.remove(this), t = 0, e = this.data.datasets.length;
6010
+ t < e;
6011
+ ++t
6012
+ )
6013
+ this._destroyDatasetMeta(t);
6014
+ }
6015
+ destroy() {
6016
+ this.notifyPlugins("beforeDestroy");
6017
+ const { canvas: t, ctx: e } = this;
6018
+ this._stop(),
6019
+ this.config.clearCache(),
6020
+ t &&
6021
+ (this.unbindEvents(),
6022
+ Gt(t, e),
6023
+ this.platform.releaseContext(e),
6024
+ (this.canvas = null),
6025
+ (this.ctx = null)),
6026
+ this.notifyPlugins("destroy"),
6027
+ delete ln[this.id],
6028
+ this.notifyPlugins("afterDestroy");
6029
+ }
6030
+ toBase64Image(...t) {
6031
+ return this.canvas.toDataURL(...t);
6032
+ }
6033
+ bindEvents() {
6034
+ this.bindUserEvents(),
6035
+ this.options.responsive
6036
+ ? this.bindResponsiveEvents()
6037
+ : (this.attached = !0);
6038
+ }
6039
+ bindUserEvents() {
6040
+ const t = this._listeners,
6041
+ e = this.platform,
6042
+ i = (i, s) => {
6043
+ e.addEventListener(this, i, s), (t[i] = s);
6044
+ },
6045
+ s = (t, e, i) => {
6046
+ (t.offsetX = e), (t.offsetY = i), this._eventHandler(t);
6047
+ };
6048
+ Q(this.options.events, (t) => i(t, s));
6049
+ }
6050
+ bindResponsiveEvents() {
6051
+ this._responsiveListeners || (this._responsiveListeners = {});
6052
+ const t = this._responsiveListeners,
6053
+ e = this.platform,
6054
+ i = (i, s) => {
6055
+ e.addEventListener(this, i, s), (t[i] = s);
6056
+ },
6057
+ s = (i, s) => {
6058
+ t[i] && (e.removeEventListener(this, i, s), delete t[i]);
6059
+ },
6060
+ n = (t, e) => {
6061
+ this.canvas && this.resize(t, e);
6062
+ };
6063
+ let o;
6064
+ const a = () => {
6065
+ s("attach", a),
6066
+ (this.attached = !0),
6067
+ this.resize(),
6068
+ i("resize", n),
6069
+ i("detach", o);
6070
+ };
6071
+ (o = () => {
6072
+ (this.attached = !1),
6073
+ s("resize", n),
6074
+ this._stop(),
6075
+ this._resize(0, 0),
6076
+ i("attach", a);
6077
+ }),
6078
+ e.isAttached(this.canvas) ? a() : o();
6079
+ }
6080
+ unbindEvents() {
6081
+ Q(this._listeners, (t, e) => {
6082
+ this.platform.removeEventListener(this, e, t);
6083
+ }),
6084
+ (this._listeners = {}),
6085
+ Q(this._responsiveListeners, (t, e) => {
6086
+ this.platform.removeEventListener(this, e, t);
6087
+ }),
6088
+ (this._responsiveListeners = void 0);
6089
+ }
6090
+ updateHoverStyle(t, e, i) {
6091
+ const s = i ? "set" : "remove";
6092
+ let n, o, a, r;
6093
+ for (
6094
+ "dataset" === e &&
6095
+ ((n = this.getDatasetMeta(t[0].datasetIndex)),
6096
+ n.controller["_" + s + "DatasetHoverStyle"]()),
6097
+ a = 0,
6098
+ r = t.length;
6099
+ a < r;
6100
+ ++a
6101
+ ) {
6102
+ o = t[a];
6103
+ const e = o && this.getDatasetMeta(o.datasetIndex).controller;
6104
+ e && e[s + "HoverStyle"](o.element, o.datasetIndex, o.index);
6105
+ }
6106
+ }
6107
+ getActiveElements() {
6108
+ return this._active || [];
6109
+ }
6110
+ setActiveElements(t) {
6111
+ const e = this._active || [],
6112
+ i = t.map(({ datasetIndex: t, index: e }) => {
6113
+ const i = this.getDatasetMeta(t);
6114
+ if (!i) throw new Error("No dataset found at index " + t);
6115
+ return { datasetIndex: t, element: i.data[e], index: e };
6116
+ });
6117
+ !tt(i, e) &&
6118
+ ((this._active = i),
6119
+ (this._lastEvent = null),
6120
+ this._updateHoverStyles(i, e));
6121
+ }
6122
+ notifyPlugins(t, e, i) {
6123
+ return this._plugins.notify(this, t, e, i);
6124
+ }
6125
+ _updateHoverStyles(t, e, i) {
6126
+ const s = this.options.hover,
6127
+ n = (t, e) =>
6128
+ t.filter(
6129
+ (t) =>
6130
+ !e.some(
6131
+ (e) => t.datasetIndex === e.datasetIndex && t.index === e.index
6132
+ )
6133
+ ),
6134
+ o = n(e, t),
6135
+ a = i ? t : n(t, e);
6136
+ o.length && this.updateHoverStyle(o, s.mode, !1),
6137
+ a.length && s.mode && this.updateHoverStyle(a, s.mode, !0);
6138
+ }
6139
+ _eventHandler(t, e) {
6140
+ const i = {
6141
+ event: t,
6142
+ replay: e,
6143
+ cancelable: !0,
6144
+ inChartArea: Jt(t, this.chartArea, this._minPadding),
6145
+ },
6146
+ s = (e) =>
6147
+ (e.options.events || this.options.events).includes(t.native.type);
6148
+ if (!1 === this.notifyPlugins("beforeEvent", i, s)) return;
6149
+ const n = this._handleEvent(t, e, i.inChartArea);
6150
+ return (
6151
+ (i.cancelable = !1),
6152
+ this.notifyPlugins("afterEvent", i, s),
6153
+ (n || i.changed) && this.render(),
6154
+ this
6155
+ );
6156
+ }
6157
+ _handleEvent(t, e, i) {
6158
+ const { _active: s = [], options: n } = this,
6159
+ o = e,
6160
+ a = this._getActiveElements(t, s, i, o),
6161
+ r = ft(t),
6162
+ l = (function (t, e, i, s) {
6163
+ return i && "mouseout" !== t.type ? (s ? e : t) : null;
6164
+ })(t, this._lastEvent, i, r);
6165
+ i &&
6166
+ ((this._lastEvent = null),
6167
+ J(n.onHover, [t, a, this], this),
6168
+ r && J(n.onClick, [t, a, this], this));
6169
+ const h = !tt(a, s);
6170
+ return (
6171
+ (h || e) && ((this._active = a), this._updateHoverStyles(a, s, e)),
6172
+ (this._lastEvent = l),
6173
+ h
6174
+ );
6175
+ }
6176
+ _getActiveElements(t, e, i, s) {
6177
+ if ("mouseout" === t.type) return [];
6178
+ if (!i) return e;
6179
+ const n = this.options.hover;
6180
+ return this.getElementsAtEventForMode(t, n.mode, n, s);
6181
+ }
6182
+ }
6183
+ const un = () => Q(dn.instances, (t) => t._plugins.invalidate()),
6184
+ fn = !0;
6185
+ function gn() {
6186
+ throw new Error(
6187
+ "This method is not implemented: Check that a complete date adapter is provided."
6188
+ );
6189
+ }
6190
+ Object.defineProperties(dn, {
6191
+ defaults: { enumerable: fn, value: bt },
6192
+ instances: { enumerable: fn, value: ln },
6193
+ overrides: { enumerable: fn, value: gt },
6194
+ registry: { enumerable: fn, value: Ws },
6195
+ version: { enumerable: fn, value: "3.7.1" },
6196
+ getChart: { enumerable: fn, value: hn },
6197
+ register: {
6198
+ enumerable: fn,
6199
+ value: (...t) => {
6200
+ Ws.add(...t), un();
6201
+ },
6202
+ },
6203
+ unregister: {
6204
+ enumerable: fn,
6205
+ value: (...t) => {
6206
+ Ws.remove(...t), un();
6207
+ },
6208
+ },
6209
+ });
6210
+ class pn {
6211
+ constructor(t) {
6212
+ this.options = t || {};
6213
+ }
6214
+ formats() {
6215
+ return gn();
6216
+ }
6217
+ parse(t, e) {
6218
+ return gn();
6219
+ }
6220
+ format(t, e) {
6221
+ return gn();
6222
+ }
6223
+ add(t, e, i) {
6224
+ return gn();
6225
+ }
6226
+ diff(t, e, i) {
6227
+ return gn();
6228
+ }
6229
+ startOf(t, e, i) {
6230
+ return gn();
6231
+ }
6232
+ endOf(t, e) {
6233
+ return gn();
6234
+ }
6235
+ }
6236
+ pn.override = function (t) {
6237
+ Object.assign(pn.prototype, t);
6238
+ };
6239
+ var mn = { _date: pn };
6240
+ function xn(t) {
6241
+ const e = t.iScale,
6242
+ i = (function (t, e) {
6243
+ if (!t._cache.$bar) {
6244
+ const i = t.getMatchingVisibleMetas(e);
6245
+ let s = [];
6246
+ for (let e = 0, n = i.length; e < n; e++)
6247
+ s = s.concat(i[e].controller.getAllParsedValues(t));
6248
+ t._cache.$bar = fe(s.sort((t, e) => t - e));
6249
+ }
6250
+ return t._cache.$bar;
6251
+ })(e, t.type);
6252
+ let s,
6253
+ n,
6254
+ o,
6255
+ a,
6256
+ r = e._length;
6257
+ const l = () => {
6258
+ 32767 !== o &&
6259
+ -32768 !== o &&
6260
+ (ct(a) && (r = Math.min(r, Math.abs(o - a) || r)), (a = o));
6261
+ };
6262
+ for (s = 0, n = i.length; s < n; ++s) (o = e.getPixelForValue(i[s])), l();
6263
+ for (a = void 0, s = 0, n = e.ticks.length; s < n; ++s)
6264
+ (o = e.getPixelForTick(s)), l();
6265
+ return r;
6266
+ }
6267
+ function bn(t, e, i, s) {
6268
+ return (
6269
+ Y(t)
6270
+ ? (function (t, e, i, s) {
6271
+ const n = i.parse(t[0], s),
6272
+ o = i.parse(t[1], s),
6273
+ a = Math.min(n, o),
6274
+ r = Math.max(n, o);
6275
+ let l = a,
6276
+ h = r;
6277
+ Math.abs(a) > Math.abs(r) && ((l = r), (h = a)),
6278
+ (e[i.axis] = h),
6279
+ (e._custom = {
6280
+ barStart: l,
6281
+ barEnd: h,
6282
+ start: n,
6283
+ end: o,
6284
+ min: a,
6285
+ max: r,
6286
+ });
6287
+ })(t, e, i, s)
6288
+ : (e[i.axis] = i.parse(t, s)),
6289
+ e
6290
+ );
6291
+ }
6292
+ function _n(t, e, i, s) {
6293
+ const n = t.iScale,
6294
+ o = t.vScale,
6295
+ a = n.getLabels(),
6296
+ r = n === o,
6297
+ l = [];
6298
+ let h, c, d, u;
6299
+ for (h = i, c = i + s; h < c; ++h)
6300
+ (u = e[h]),
6301
+ (d = {}),
6302
+ (d[n.axis] = r || n.parse(a[h], h)),
6303
+ l.push(bn(u, d, o, h));
6304
+ return l;
6305
+ }
6306
+ function yn(t) {
6307
+ return t && void 0 !== t.barStart && void 0 !== t.barEnd;
6308
+ }
6309
+ function vn(t, e, i, s) {
6310
+ let n = e.borderSkipped;
6311
+ const o = {};
6312
+ if (!n) return void (t.borderSkipped = o);
6313
+ const {
6314
+ start: a,
6315
+ end: r,
6316
+ reverse: l,
6317
+ top: h,
6318
+ bottom: c,
6319
+ } = (function (t) {
6320
+ let e, i, s, n, o;
6321
+ return (
6322
+ t.horizontal
6323
+ ? ((e = t.base > t.x), (i = "left"), (s = "right"))
6324
+ : ((e = t.base < t.y), (i = "bottom"), (s = "top")),
6325
+ e ? ((n = "end"), (o = "start")) : ((n = "start"), (o = "end")),
6326
+ { start: i, end: s, reverse: e, top: n, bottom: o }
6327
+ );
6328
+ })(t);
6329
+ "middle" === n &&
6330
+ i &&
6331
+ ((t.enableBorderRadius = !0),
6332
+ (i._top || 0) === s
6333
+ ? (n = h)
6334
+ : (i._bottom || 0) === s
6335
+ ? (n = c)
6336
+ : ((o[wn(c, a, r, l)] = !0), (n = h))),
6337
+ (o[wn(n, a, r, l)] = !0),
6338
+ (t.borderSkipped = o);
6339
+ }
6340
+ function wn(t, e, i, s) {
6341
+ var n, o, a;
6342
+ return (
6343
+ s
6344
+ ? ((a = i),
6345
+ (t = Mn((t = (n = t) === (o = e) ? a : n === a ? o : n), i, e)))
6346
+ : (t = Mn(t, e, i)),
6347
+ t
6348
+ );
6349
+ }
6350
+ function Mn(t, e, i) {
6351
+ return "start" === t ? e : "end" === t ? i : t;
6352
+ }
6353
+ function kn(t, { inflateAmount: e }, i) {
6354
+ t.inflateAmount = "auto" === e ? (1 === i ? 0.33 : 0) : e;
6355
+ }
6356
+ class Sn extends Ps {
6357
+ parsePrimitiveData(t, e, i, s) {
6358
+ return _n(t, e, i, s);
6359
+ }
6360
+ parseArrayData(t, e, i, s) {
6361
+ return _n(t, e, i, s);
6362
+ }
6363
+ parseObjectData(t, e, i, s) {
6364
+ const { iScale: n, vScale: o } = t,
6365
+ { xAxisKey: a = "x", yAxisKey: r = "y" } = this._parsing,
6366
+ l = "x" === n.axis ? a : r,
6367
+ h = "x" === o.axis ? a : r,
6368
+ c = [];
6369
+ let d, u, f, g;
6370
+ for (d = i, u = i + s; d < u; ++d)
6371
+ (g = e[d]),
6372
+ (f = {}),
6373
+ (f[n.axis] = n.parse(lt(g, l), d)),
6374
+ c.push(bn(lt(g, h), f, o, d));
6375
+ return c;
6376
+ }
6377
+ updateRangeFromParsed(t, e, i, s) {
6378
+ super.updateRangeFromParsed(t, e, i, s);
6379
+ const n = i._custom;
6380
+ n &&
6381
+ e === this._cachedMeta.vScale &&
6382
+ ((t.min = Math.min(t.min, n.min)), (t.max = Math.max(t.max, n.max)));
6383
+ }
6384
+ getMaxOverflow() {
6385
+ return 0;
6386
+ }
6387
+ getLabelAndValue(t) {
6388
+ const e = this._cachedMeta,
6389
+ { iScale: i, vScale: s } = e,
6390
+ n = this.getParsed(t),
6391
+ o = n._custom,
6392
+ a = yn(o)
6393
+ ? "[" + o.start + ", " + o.end + "]"
6394
+ : "" + s.getLabelForValue(n[s.axis]);
6395
+ return { label: "" + i.getLabelForValue(n[i.axis]), value: a };
6396
+ }
6397
+ initialize() {
6398
+ (this.enableOptionSharing = !0), super.initialize();
6399
+ this._cachedMeta.stack = this.getDataset().stack;
6400
+ }
6401
+ update(t) {
6402
+ const e = this._cachedMeta;
6403
+ this.updateElements(e.data, 0, e.data.length, t);
6404
+ }
6405
+ updateElements(t, e, i, s) {
6406
+ const n = "reset" === s,
6407
+ {
6408
+ index: o,
6409
+ _cachedMeta: { vScale: a },
6410
+ } = this,
6411
+ r = a.getBasePixel(),
6412
+ l = a.isHorizontal(),
6413
+ h = this._getRuler(),
6414
+ c = this.resolveDataElementOptions(e, s),
6415
+ d = this.getSharedOptions(c),
6416
+ u = this.includeOptions(s, d);
6417
+ this.updateSharedOptions(d, s, c);
6418
+ for (let c = e; c < e + i; c++) {
6419
+ const e = this.getParsed(c),
6420
+ i =
6421
+ n || $(e[a.axis])
6422
+ ? { base: r, head: r }
6423
+ : this._calculateBarValuePixels(c),
6424
+ f = this._calculateBarIndexPixels(c, h),
6425
+ g = (e._stacks || {})[a.axis],
6426
+ p = {
6427
+ horizontal: l,
6428
+ base: i.base,
6429
+ enableBorderRadius:
6430
+ !g || yn(e._custom) || o === g._top || o === g._bottom,
6431
+ x: l ? i.head : f.center,
6432
+ y: l ? f.center : i.head,
6433
+ height: l ? f.size : Math.abs(i.size),
6434
+ width: l ? Math.abs(i.size) : f.size,
6435
+ };
6436
+ u &&
6437
+ (p.options =
6438
+ d || this.resolveDataElementOptions(c, t[c].active ? "active" : s));
6439
+ const m = p.options || t[c].options;
6440
+ vn(p, m, g, o), kn(p, m, h.ratio), this.updateElement(t[c], c, p, s);
6441
+ }
6442
+ }
6443
+ _getStacks(t, e) {
6444
+ const i = this._cachedMeta.iScale,
6445
+ s = i.getMatchingVisibleMetas(this._type),
6446
+ n = i.options.stacked,
6447
+ o = s.length,
6448
+ a = [];
6449
+ let r, l;
6450
+ for (r = 0; r < o; ++r)
6451
+ if (((l = s[r]), l.controller.options.grouped)) {
6452
+ if (void 0 !== e) {
6453
+ const t =
6454
+ l.controller.getParsed(e)[l.controller._cachedMeta.vScale.axis];
6455
+ if ($(t) || isNaN(t)) continue;
6456
+ }
6457
+ if (
6458
+ ((!1 === n ||
6459
+ -1 === a.indexOf(l.stack) ||
6460
+ (void 0 === n && void 0 === l.stack)) &&
6461
+ a.push(l.stack),
6462
+ l.index === t)
6463
+ )
6464
+ break;
6465
+ }
6466
+ return a.length || a.push(void 0), a;
6467
+ }
6468
+ _getStackCount(t) {
6469
+ return this._getStacks(void 0, t).length;
6470
+ }
6471
+ _getStackIndex(t, e, i) {
6472
+ const s = this._getStacks(t, i),
6473
+ n = void 0 !== e ? s.indexOf(e) : -1;
6474
+ return -1 === n ? s.length - 1 : n;
6475
+ }
6476
+ _getRuler() {
6477
+ const t = this.options,
6478
+ e = this._cachedMeta,
6479
+ i = e.iScale,
6480
+ s = [];
6481
+ let n, o;
6482
+ for (n = 0, o = e.data.length; n < o; ++n)
6483
+ s.push(i.getPixelForValue(this.getParsed(n)[i.axis], n));
6484
+ const a = t.barThickness;
6485
+ return {
6486
+ min: a || xn(e),
6487
+ pixels: s,
6488
+ start: i._startPixel,
6489
+ end: i._endPixel,
6490
+ stackCount: this._getStackCount(),
6491
+ scale: i,
6492
+ grouped: t.grouped,
6493
+ ratio: a ? 1 : t.categoryPercentage * t.barPercentage,
6494
+ };
6495
+ }
6496
+ _calculateBarValuePixels(t) {
6497
+ const {
6498
+ _cachedMeta: { vScale: e, _stacked: i },
6499
+ options: { base: s, minBarLength: n },
6500
+ } = this,
6501
+ o = s || 0,
6502
+ a = this.getParsed(t),
6503
+ r = a._custom,
6504
+ l = yn(r);
6505
+ let h,
6506
+ c,
6507
+ d = a[e.axis],
6508
+ u = 0,
6509
+ f = i ? this.applyStack(e, a, i) : d;
6510
+ f !== d && ((u = f - d), (f = d)),
6511
+ l &&
6512
+ ((d = r.barStart),
6513
+ (f = r.barEnd - r.barStart),
6514
+ 0 !== d && Ct(d) !== Ct(r.barEnd) && (u = 0),
6515
+ (u += d));
6516
+ const g = $(s) || l ? u : s;
6517
+ let p = e.getPixelForValue(g);
6518
+ if (
6519
+ ((h = this.chart.getDataVisibility(t) ? e.getPixelForValue(u + f) : p),
6520
+ (c = h - p),
6521
+ Math.abs(c) < n &&
6522
+ ((c =
6523
+ (function (t, e, i) {
6524
+ return 0 !== t
6525
+ ? Ct(t)
6526
+ : (e.isHorizontal() ? 1 : -1) * (e.min >= i ? 1 : -1);
6527
+ })(c, e, o) * n),
6528
+ d === o && (p -= c / 2),
6529
+ (h = p + c)),
6530
+ p === e.getPixelForValue(o))
6531
+ ) {
6532
+ const t = (Ct(c) * e.getLineWidthForValue(o)) / 2;
6533
+ (p += t), (c -= t);
6534
+ }
6535
+ return { size: c, base: p, head: h, center: h + c / 2 };
6536
+ }
6537
+ _calculateBarIndexPixels(t, e) {
6538
+ const i = e.scale,
6539
+ s = this.options,
6540
+ n = s.skipNull,
6541
+ o = K(s.maxBarThickness, 1 / 0);
6542
+ let a, r;
6543
+ if (e.grouped) {
6544
+ const i = n ? this._getStackCount(t) : e.stackCount,
6545
+ l =
6546
+ "flex" === s.barThickness
6547
+ ? (function (t, e, i, s) {
6548
+ const n = e.pixels,
6549
+ o = n[t];
6550
+ let a = t > 0 ? n[t - 1] : null,
6551
+ r = t < n.length - 1 ? n[t + 1] : null;
6552
+ const l = i.categoryPercentage;
6553
+ null === a &&
6554
+ (a = o - (null === r ? e.end - e.start : r - o)),
6555
+ null === r && (r = o + o - a);
6556
+ const h = o - ((o - Math.min(a, r)) / 2) * l;
6557
+ return {
6558
+ chunk: ((Math.abs(r - a) / 2) * l) / s,
6559
+ ratio: i.barPercentage,
6560
+ start: h,
6561
+ };
6562
+ })(t, e, s, i)
6563
+ : (function (t, e, i, s) {
6564
+ const n = i.barThickness;
6565
+ let o, a;
6566
+ return (
6567
+ $(n)
6568
+ ? ((o = e.min * i.categoryPercentage),
6569
+ (a = i.barPercentage))
6570
+ : ((o = n * s), (a = 1)),
6571
+ { chunk: o / s, ratio: a, start: e.pixels[t] - o / 2 }
6572
+ );
6573
+ })(t, e, s, i),
6574
+ h = this._getStackIndex(
6575
+ this.index,
6576
+ this._cachedMeta.stack,
6577
+ n ? t : void 0
6578
+ );
6579
+ (a = l.start + l.chunk * h + l.chunk / 2),
6580
+ (r = Math.min(o, l.chunk * l.ratio));
6581
+ } else (a = i.getPixelForValue(this.getParsed(t)[i.axis], t)), (r = Math.min(o, e.min * e.ratio));
6582
+ return { base: a - r / 2, head: a + r / 2, center: a, size: r };
6583
+ }
6584
+ draw() {
6585
+ const t = this._cachedMeta,
6586
+ e = t.vScale,
6587
+ i = t.data,
6588
+ s = i.length;
6589
+ let n = 0;
6590
+ for (; n < s; ++n)
6591
+ null !== this.getParsed(n)[e.axis] && i[n].draw(this._ctx);
6592
+ }
6593
+ }
6594
+ (Sn.id = "bar"),
6595
+ (Sn.defaults = {
6596
+ datasetElementType: !1,
6597
+ dataElementType: "bar",
6598
+ categoryPercentage: 0.8,
6599
+ barPercentage: 0.9,
6600
+ grouped: !0,
6601
+ animations: {
6602
+ numbers: {
6603
+ type: "number",
6604
+ properties: ["x", "y", "base", "width", "height"],
6605
+ },
6606
+ },
6607
+ }),
6608
+ (Sn.overrides = {
6609
+ scales: {
6610
+ _index_: { type: "category", offset: !0, grid: { offset: !0 } },
6611
+ _value_: { type: "linear", beginAtZero: !0 },
6612
+ },
6613
+ });
6614
+ class Pn extends Ps {
6615
+ initialize() {
6616
+ (this.enableOptionSharing = !0), super.initialize();
6617
+ }
6618
+ parsePrimitiveData(t, e, i, s) {
6619
+ const n = super.parsePrimitiveData(t, e, i, s);
6620
+ for (let t = 0; t < n.length; t++)
6621
+ n[t]._custom = this.resolveDataElementOptions(t + i).radius;
6622
+ return n;
6623
+ }
6624
+ parseArrayData(t, e, i, s) {
6625
+ const n = super.parseArrayData(t, e, i, s);
6626
+ for (let t = 0; t < n.length; t++) {
6627
+ const s = e[i + t];
6628
+ n[t]._custom = K(s[2], this.resolveDataElementOptions(t + i).radius);
6629
+ }
6630
+ return n;
6631
+ }
6632
+ parseObjectData(t, e, i, s) {
6633
+ const n = super.parseObjectData(t, e, i, s);
6634
+ for (let t = 0; t < n.length; t++) {
6635
+ const s = e[i + t];
6636
+ n[t]._custom = K(
6637
+ s && s.r && +s.r,
6638
+ this.resolveDataElementOptions(t + i).radius
6639
+ );
6640
+ }
6641
+ return n;
6642
+ }
6643
+ getMaxOverflow() {
6644
+ const t = this._cachedMeta.data;
6645
+ let e = 0;
6646
+ for (let i = t.length - 1; i >= 0; --i)
6647
+ e = Math.max(e, t[i].size(this.resolveDataElementOptions(i)) / 2);
6648
+ return e > 0 && e;
6649
+ }
6650
+ getLabelAndValue(t) {
6651
+ const e = this._cachedMeta,
6652
+ { xScale: i, yScale: s } = e,
6653
+ n = this.getParsed(t),
6654
+ o = i.getLabelForValue(n.x),
6655
+ a = s.getLabelForValue(n.y),
6656
+ r = n._custom;
6657
+ return {
6658
+ label: e.label,
6659
+ value: "(" + o + ", " + a + (r ? ", " + r : "") + ")",
6660
+ };
6661
+ }
6662
+ update(t) {
6663
+ const e = this._cachedMeta.data;
6664
+ this.updateElements(e, 0, e.length, t);
6665
+ }
6666
+ updateElements(t, e, i, s) {
6667
+ const n = "reset" === s,
6668
+ { iScale: o, vScale: a } = this._cachedMeta,
6669
+ r = this.resolveDataElementOptions(e, s),
6670
+ l = this.getSharedOptions(r),
6671
+ h = this.includeOptions(s, l),
6672
+ c = o.axis,
6673
+ d = a.axis;
6674
+ for (let r = e; r < e + i; r++) {
6675
+ const e = t[r],
6676
+ i = !n && this.getParsed(r),
6677
+ l = {},
6678
+ u = (l[c] = n ? o.getPixelForDecimal(0.5) : o.getPixelForValue(i[c])),
6679
+ f = (l[d] = n ? a.getBasePixel() : a.getPixelForValue(i[d]));
6680
+ (l.skip = isNaN(u) || isNaN(f)),
6681
+ h &&
6682
+ ((l.options = this.resolveDataElementOptions(
6683
+ r,
6684
+ e.active ? "active" : s
6685
+ )),
6686
+ n && (l.options.radius = 0)),
6687
+ this.updateElement(e, r, l, s);
6688
+ }
6689
+ this.updateSharedOptions(l, s, r);
6690
+ }
6691
+ resolveDataElementOptions(t, e) {
6692
+ const i = this.getParsed(t);
6693
+ let s = super.resolveDataElementOptions(t, e);
6694
+ s.$shared && (s = Object.assign({}, s, { $shared: !1 }));
6695
+ const n = s.radius;
6696
+ return (
6697
+ "active" !== e && (s.radius = 0), (s.radius += K(i && i._custom, n)), s
6698
+ );
6699
+ }
6700
+ }
6701
+ (Pn.id = "bubble"),
6702
+ (Pn.defaults = {
6703
+ datasetElementType: !1,
6704
+ dataElementType: "point",
6705
+ animations: {
6706
+ numbers: {
6707
+ type: "number",
6708
+ properties: ["x", "y", "borderWidth", "radius"],
6709
+ },
6710
+ },
6711
+ }),
6712
+ (Pn.overrides = {
6713
+ scales: { x: { type: "linear" }, y: { type: "linear" } },
6714
+ plugins: { tooltip: { callbacks: { title: () => "" } } },
6715
+ });
6716
+ class Dn extends Ps {
6717
+ constructor(t, e) {
6718
+ super(t, e),
6719
+ (this.enableOptionSharing = !0),
6720
+ (this.innerRadius = void 0),
6721
+ (this.outerRadius = void 0),
6722
+ (this.offsetX = void 0),
6723
+ (this.offsetY = void 0);
6724
+ }
6725
+ linkScales() {}
6726
+ parse(t, e) {
6727
+ const i = this.getDataset().data,
6728
+ s = this._cachedMeta;
6729
+ if (!1 === this._parsing) s._parsed = i;
6730
+ else {
6731
+ let n,
6732
+ o,
6733
+ a = (t) => +i[t];
6734
+ if (U(i[t])) {
6735
+ const { key: t = "value" } = this._parsing;
6736
+ a = (e) => +lt(i[e], t);
6737
+ }
6738
+ for (n = t, o = t + e; n < o; ++n) s._parsed[n] = a(n);
6739
+ }
6740
+ }
6741
+ _getRotation() {
6742
+ return It(this.options.rotation - 90);
6743
+ }
6744
+ _getCircumference() {
6745
+ return It(this.options.circumference);
6746
+ }
6747
+ _getRotationExtents() {
6748
+ let t = yt,
6749
+ e = -yt;
6750
+ for (let i = 0; i < this.chart.data.datasets.length; ++i)
6751
+ if (this.chart.isDatasetVisible(i)) {
6752
+ const s = this.chart.getDatasetMeta(i).controller,
6753
+ n = s._getRotation(),
6754
+ o = s._getCircumference();
6755
+ (t = Math.min(t, n)), (e = Math.max(e, n + o));
6756
+ }
6757
+ return { rotation: t, circumference: e - t };
6758
+ }
6759
+ update(t) {
6760
+ const e = this.chart,
6761
+ { chartArea: i } = e,
6762
+ s = this._cachedMeta,
6763
+ n = s.data,
6764
+ o =
6765
+ this.getMaxBorderWidth() +
6766
+ this.getMaxOffset(n) +
6767
+ this.options.spacing,
6768
+ a = Math.max((Math.min(i.width, i.height) - o) / 2, 0),
6769
+ r = Math.min(G(this.options.cutout, a), 1),
6770
+ l = this._getRingWeight(this.index),
6771
+ { circumference: h, rotation: c } = this._getRotationExtents(),
6772
+ {
6773
+ ratioX: d,
6774
+ ratioY: u,
6775
+ offsetX: f,
6776
+ offsetY: g,
6777
+ } = (function (t, e, i) {
6778
+ let s = 1,
6779
+ n = 1,
6780
+ o = 0,
6781
+ a = 0;
6782
+ if (e < yt) {
6783
+ const r = t,
6784
+ l = r + e,
6785
+ h = Math.cos(r),
6786
+ c = Math.sin(r),
6787
+ d = Math.cos(l),
6788
+ u = Math.sin(l),
6789
+ f = (t, e, s) =>
6790
+ Ht(t, r, l, !0) ? 1 : Math.max(e, e * i, s, s * i),
6791
+ g = (t, e, s) =>
6792
+ Ht(t, r, l, !0) ? -1 : Math.min(e, e * i, s, s * i),
6793
+ p = f(0, h, d),
6794
+ m = f(kt, c, u),
6795
+ x = g(_t, h, d),
6796
+ b = g(_t + kt, c, u);
6797
+ (s = (p - x) / 2),
6798
+ (n = (m - b) / 2),
6799
+ (o = -(p + x) / 2),
6800
+ (a = -(m + b) / 2);
6801
+ }
6802
+ return { ratioX: s, ratioY: n, offsetX: o, offsetY: a };
6803
+ })(c, h, r),
6804
+ p = (i.width - o) / d,
6805
+ m = (i.height - o) / u,
6806
+ x = Math.max(Math.min(p, m) / 2, 0),
6807
+ b = Z(this.options.radius, x),
6808
+ _ = (b - Math.max(b * r, 0)) / this._getVisibleDatasetWeightTotal();
6809
+ (this.offsetX = f * b),
6810
+ (this.offsetY = g * b),
6811
+ (s.total = this.calculateTotal()),
6812
+ (this.outerRadius = b - _ * this._getRingWeightOffset(this.index)),
6813
+ (this.innerRadius = Math.max(this.outerRadius - _ * l, 0)),
6814
+ this.updateElements(n, 0, n.length, t);
6815
+ }
6816
+ _circumference(t, e) {
6817
+ const i = this.options,
6818
+ s = this._cachedMeta,
6819
+ n = this._getCircumference();
6820
+ return (e && i.animation.animateRotate) ||
6821
+ !this.chart.getDataVisibility(t) ||
6822
+ null === s._parsed[t] ||
6823
+ s.data[t].hidden
6824
+ ? 0
6825
+ : this.calculateCircumference((s._parsed[t] * n) / yt);
6826
+ }
6827
+ updateElements(t, e, i, s) {
6828
+ const n = "reset" === s,
6829
+ o = this.chart,
6830
+ a = o.chartArea,
6831
+ r = o.options.animation,
6832
+ l = (a.left + a.right) / 2,
6833
+ h = (a.top + a.bottom) / 2,
6834
+ c = n && r.animateScale,
6835
+ d = c ? 0 : this.innerRadius,
6836
+ u = c ? 0 : this.outerRadius,
6837
+ f = this.resolveDataElementOptions(e, s),
6838
+ g = this.getSharedOptions(f),
6839
+ p = this.includeOptions(s, g);
6840
+ let m,
6841
+ x = this._getRotation();
6842
+ for (m = 0; m < e; ++m) x += this._circumference(m, n);
6843
+ for (m = e; m < e + i; ++m) {
6844
+ const e = this._circumference(m, n),
6845
+ i = t[m],
6846
+ o = {
6847
+ x: l + this.offsetX,
6848
+ y: h + this.offsetY,
6849
+ startAngle: x,
6850
+ endAngle: x + e,
6851
+ circumference: e,
6852
+ outerRadius: u,
6853
+ innerRadius: d,
6854
+ };
6855
+ p &&
6856
+ (o.options =
6857
+ g || this.resolveDataElementOptions(m, i.active ? "active" : s)),
6858
+ (x += e),
6859
+ this.updateElement(i, m, o, s);
6860
+ }
6861
+ this.updateSharedOptions(g, s, f);
6862
+ }
6863
+ calculateTotal() {
6864
+ const t = this._cachedMeta,
6865
+ e = t.data;
6866
+ let i,
6867
+ s = 0;
6868
+ for (i = 0; i < e.length; i++) {
6869
+ const n = t._parsed[i];
6870
+ null === n ||
6871
+ isNaN(n) ||
6872
+ !this.chart.getDataVisibility(i) ||
6873
+ e[i].hidden ||
6874
+ (s += Math.abs(n));
6875
+ }
6876
+ return s;
6877
+ }
6878
+ calculateCircumference(t) {
6879
+ const e = this._cachedMeta.total;
6880
+ return e > 0 && !isNaN(t) ? yt * (Math.abs(t) / e) : 0;
6881
+ }
6882
+ getLabelAndValue(t) {
6883
+ const e = this._cachedMeta,
6884
+ i = this.chart,
6885
+ s = i.data.labels || [],
6886
+ n = Ri(e._parsed[t], i.options.locale);
6887
+ return { label: s[t] || "", value: n };
6888
+ }
6889
+ getMaxBorderWidth(t) {
6890
+ let e = 0;
6891
+ const i = this.chart;
6892
+ let s, n, o, a, r;
6893
+ if (!t)
6894
+ for (s = 0, n = i.data.datasets.length; s < n; ++s)
6895
+ if (i.isDatasetVisible(s)) {
6896
+ (o = i.getDatasetMeta(s)), (t = o.data), (a = o.controller);
6897
+ break;
6898
+ }
6899
+ if (!t) return 0;
6900
+ for (s = 0, n = t.length; s < n; ++s)
6901
+ (r = a.resolveDataElementOptions(s)),
6902
+ "inner" !== r.borderAlign &&
6903
+ (e = Math.max(e, r.borderWidth || 0, r.hoverBorderWidth || 0));
6904
+ return e;
6905
+ }
6906
+ getMaxOffset(t) {
6907
+ let e = 0;
6908
+ for (let i = 0, s = t.length; i < s; ++i) {
6909
+ const t = this.resolveDataElementOptions(i);
6910
+ e = Math.max(e, t.offset || 0, t.hoverOffset || 0);
6911
+ }
6912
+ return e;
6913
+ }
6914
+ _getRingWeightOffset(t) {
6915
+ let e = 0;
6916
+ for (let i = 0; i < t; ++i)
6917
+ this.chart.isDatasetVisible(i) && (e += this._getRingWeight(i));
6918
+ return e;
6919
+ }
6920
+ _getRingWeight(t) {
6921
+ return Math.max(K(this.chart.data.datasets[t].weight, 1), 0);
6922
+ }
6923
+ _getVisibleDatasetWeightTotal() {
6924
+ return this._getRingWeightOffset(this.chart.data.datasets.length) || 1;
6925
+ }
6926
+ }
6927
+ (Dn.id = "doughnut"),
6928
+ (Dn.defaults = {
6929
+ datasetElementType: !1,
6930
+ dataElementType: "arc",
6931
+ animation: { animateRotate: !0, animateScale: !1 },
6932
+ animations: {
6933
+ numbers: {
6934
+ type: "number",
6935
+ properties: [
6936
+ "circumference",
6937
+ "endAngle",
6938
+ "innerRadius",
6939
+ "outerRadius",
6940
+ "startAngle",
6941
+ "x",
6942
+ "y",
6943
+ "offset",
6944
+ "borderWidth",
6945
+ "spacing",
6946
+ ],
6947
+ },
6948
+ },
6949
+ cutout: "50%",
6950
+ rotation: 0,
6951
+ circumference: 360,
6952
+ radius: "100%",
6953
+ spacing: 0,
6954
+ indexAxis: "r",
6955
+ }),
6956
+ (Dn.descriptors = {
6957
+ _scriptable: (t) => "spacing" !== t,
6958
+ _indexable: (t) => "spacing" !== t,
6959
+ }),
6960
+ (Dn.overrides = {
6961
+ aspectRatio: 1,
6962
+ plugins: {
6963
+ legend: {
6964
+ labels: {
6965
+ generateLabels(t) {
6966
+ const e = t.data;
6967
+ if (e.labels.length && e.datasets.length) {
6968
+ const {
6969
+ labels: { pointStyle: i },
6970
+ } = t.legend.options;
6971
+ return e.labels.map((e, s) => {
6972
+ const n = t.getDatasetMeta(0).controller.getStyle(s);
6973
+ return {
6974
+ text: e,
6975
+ fillStyle: n.backgroundColor,
6976
+ strokeStyle: n.borderColor,
6977
+ lineWidth: n.borderWidth,
6978
+ pointStyle: i,
6979
+ hidden: !t.getDataVisibility(s),
6980
+ index: s,
6981
+ };
6982
+ });
6983
+ }
6984
+ return [];
6985
+ },
6986
+ },
6987
+ onClick(t, e, i) {
6988
+ i.chart.toggleDataVisibility(e.index), i.chart.update();
6989
+ },
6990
+ },
6991
+ tooltip: {
6992
+ callbacks: {
6993
+ title: () => "",
6994
+ label(t) {
6995
+ let e = t.label;
6996
+ const i = ": " + t.formattedValue;
6997
+ return Y(e) ? ((e = e.slice()), (e[0] += i)) : (e += i), e;
6998
+ },
6999
+ },
7000
+ },
7001
+ },
7002
+ });
7003
+ class Cn extends Ps {
7004
+ initialize() {
7005
+ (this.enableOptionSharing = !0), super.initialize();
7006
+ }
7007
+ update(t) {
7008
+ const e = this._cachedMeta,
7009
+ { dataset: i, data: s = [], _dataset: n } = e,
7010
+ o = this.chart._animationsDisabled;
7011
+ let { start: a, count: r } = (function (t, e, i) {
7012
+ const s = e.length;
7013
+ let n = 0,
7014
+ o = s;
7015
+ if (t._sorted) {
7016
+ const { iScale: a, _parsed: r } = t,
7017
+ l = a.axis,
7018
+ {
7019
+ min: h,
7020
+ max: c,
7021
+ minDefined: d,
7022
+ maxDefined: u,
7023
+ } = a.getUserBounds();
7024
+ d &&
7025
+ (n = jt(
7026
+ Math.min(
7027
+ re(r, a.axis, h).lo,
7028
+ i ? s : re(e, l, a.getPixelForValue(h)).lo
7029
+ ),
7030
+ 0,
7031
+ s - 1
7032
+ )),
7033
+ (o = u
7034
+ ? jt(
7035
+ Math.max(
7036
+ re(r, a.axis, c).hi + 1,
7037
+ i ? 0 : re(e, l, a.getPixelForValue(c)).hi + 1
7038
+ ),
7039
+ n,
7040
+ s
7041
+ ) - n
7042
+ : s - n);
7043
+ }
7044
+ return { start: n, count: o };
7045
+ })(e, s, o);
7046
+ (this._drawStart = a),
7047
+ (this._drawCount = r),
7048
+ (function (t) {
7049
+ const { xScale: e, yScale: i, _scaleRanges: s } = t,
7050
+ n = { xmin: e.min, xmax: e.max, ymin: i.min, ymax: i.max };
7051
+ if (!s) return (t._scaleRanges = n), !0;
7052
+ const o =
7053
+ s.xmin !== e.min ||
7054
+ s.xmax !== e.max ||
7055
+ s.ymin !== i.min ||
7056
+ s.ymax !== i.max;
7057
+ return Object.assign(s, n), o;
7058
+ })(e) && ((a = 0), (r = s.length)),
7059
+ (i._chart = this.chart),
7060
+ (i._datasetIndex = this.index),
7061
+ (i._decimated = !!n._decimated),
7062
+ (i.points = s);
7063
+ const l = this.resolveDatasetElementOptions(t);
7064
+ this.options.showLine || (l.borderWidth = 0),
7065
+ (l.segment = this.options.segment),
7066
+ this.updateElement(i, void 0, { animated: !o, options: l }, t),
7067
+ this.updateElements(s, a, r, t);
7068
+ }
7069
+ updateElements(t, e, i, s) {
7070
+ const n = "reset" === s,
7071
+ { iScale: o, vScale: a, _stacked: r, _dataset: l } = this._cachedMeta,
7072
+ h = this.resolveDataElementOptions(e, s),
7073
+ c = this.getSharedOptions(h),
7074
+ d = this.includeOptions(s, c),
7075
+ u = o.axis,
7076
+ f = a.axis,
7077
+ { spanGaps: g, segment: p } = this.options,
7078
+ m = Tt(g) ? g : Number.POSITIVE_INFINITY,
7079
+ x = this.chart._animationsDisabled || n || "none" === s;
7080
+ let b = e > 0 && this.getParsed(e - 1);
7081
+ for (let h = e; h < e + i; ++h) {
7082
+ const e = t[h],
7083
+ i = this.getParsed(h),
7084
+ g = x ? e : {},
7085
+ _ = $(i[f]),
7086
+ y = (g[u] = o.getPixelForValue(i[u], h)),
7087
+ v = (g[f] =
7088
+ n || _
7089
+ ? a.getBasePixel()
7090
+ : a.getPixelForValue(r ? this.applyStack(a, i, r) : i[f], h));
7091
+ (g.skip = isNaN(y) || isNaN(v) || _),
7092
+ (g.stop = h > 0 && i[u] - b[u] > m),
7093
+ p && ((g.parsed = i), (g.raw = l.data[h])),
7094
+ d &&
7095
+ (g.options =
7096
+ c || this.resolveDataElementOptions(h, e.active ? "active" : s)),
7097
+ x || this.updateElement(e, h, g, s),
7098
+ (b = i);
7099
+ }
7100
+ this.updateSharedOptions(c, s, h);
7101
+ }
7102
+ getMaxOverflow() {
7103
+ const t = this._cachedMeta,
7104
+ e = t.dataset,
7105
+ i = (e.options && e.options.borderWidth) || 0,
7106
+ s = t.data || [];
7107
+ if (!s.length) return i;
7108
+ const n = s[0].size(this.resolveDataElementOptions(0)),
7109
+ o = s[s.length - 1].size(this.resolveDataElementOptions(s.length - 1));
7110
+ return Math.max(i, n, o) / 2;
7111
+ }
7112
+ draw() {
7113
+ const t = this._cachedMeta;
7114
+ t.dataset.updateControlPoints(this.chart.chartArea, t.iScale.axis),
7115
+ super.draw();
7116
+ }
7117
+ }
7118
+ (Cn.id = "line"),
7119
+ (Cn.defaults = {
7120
+ datasetElementType: "line",
7121
+ dataElementType: "point",
7122
+ showLine: !0,
7123
+ spanGaps: !1,
7124
+ }),
7125
+ (Cn.overrides = {
7126
+ scales: { _index_: { type: "category" }, _value_: { type: "linear" } },
7127
+ });
7128
+ class On extends Ps {
7129
+ constructor(t, e) {
7130
+ super(t, e), (this.innerRadius = void 0), (this.outerRadius = void 0);
7131
+ }
7132
+ getLabelAndValue(t) {
7133
+ const e = this._cachedMeta,
7134
+ i = this.chart,
7135
+ s = i.data.labels || [],
7136
+ n = Ri(e._parsed[t].r, i.options.locale);
7137
+ return { label: s[t] || "", value: n };
7138
+ }
7139
+ update(t) {
7140
+ const e = this._cachedMeta.data;
7141
+ this._updateRadius(), this.updateElements(e, 0, e.length, t);
7142
+ }
7143
+ _updateRadius() {
7144
+ const t = this.chart,
7145
+ e = t.chartArea,
7146
+ i = t.options,
7147
+ s = Math.min(e.right - e.left, e.bottom - e.top),
7148
+ n = Math.max(s / 2, 0),
7149
+ o =
7150
+ (n -
7151
+ Math.max(
7152
+ i.cutoutPercentage ? (n / 100) * i.cutoutPercentage : 1,
7153
+ 0
7154
+ )) /
7155
+ t.getVisibleDatasetCount();
7156
+ (this.outerRadius = n - o * this.index),
7157
+ (this.innerRadius = this.outerRadius - o);
7158
+ }
7159
+ updateElements(t, e, i, s) {
7160
+ const n = "reset" === s,
7161
+ o = this.chart,
7162
+ a = this.getDataset(),
7163
+ r = o.options.animation,
7164
+ l = this._cachedMeta.rScale,
7165
+ h = l.xCenter,
7166
+ c = l.yCenter,
7167
+ d = l.getIndexAngle(0) - 0.5 * _t;
7168
+ let u,
7169
+ f = d;
7170
+ const g = 360 / this.countVisibleElements();
7171
+ for (u = 0; u < e; ++u) f += this._computeAngle(u, s, g);
7172
+ for (u = e; u < e + i; u++) {
7173
+ const e = t[u];
7174
+ let i = f,
7175
+ p = f + this._computeAngle(u, s, g),
7176
+ m = o.getDataVisibility(u)
7177
+ ? l.getDistanceFromCenterForValue(a.data[u])
7178
+ : 0;
7179
+ (f = p),
7180
+ n && (r.animateScale && (m = 0), r.animateRotate && (i = p = d));
7181
+ const x = {
7182
+ x: h,
7183
+ y: c,
7184
+ innerRadius: 0,
7185
+ outerRadius: m,
7186
+ startAngle: i,
7187
+ endAngle: p,
7188
+ options: this.resolveDataElementOptions(u, e.active ? "active" : s),
7189
+ };
7190
+ this.updateElement(e, u, x, s);
7191
+ }
7192
+ }
7193
+ countVisibleElements() {
7194
+ const t = this.getDataset(),
7195
+ e = this._cachedMeta;
7196
+ let i = 0;
7197
+ return (
7198
+ e.data.forEach((e, s) => {
7199
+ !isNaN(t.data[s]) && this.chart.getDataVisibility(s) && i++;
7200
+ }),
7201
+ i
7202
+ );
7203
+ }
7204
+ _computeAngle(t, e, i) {
7205
+ return this.chart.getDataVisibility(t)
7206
+ ? It(this.resolveDataElementOptions(t, e).angle || i)
7207
+ : 0;
7208
+ }
7209
+ }
7210
+ (On.id = "polarArea"),
7211
+ (On.defaults = {
7212
+ dataElementType: "arc",
7213
+ animation: { animateRotate: !0, animateScale: !0 },
7214
+ animations: {
7215
+ numbers: {
7216
+ type: "number",
7217
+ properties: [
7218
+ "x",
7219
+ "y",
7220
+ "startAngle",
7221
+ "endAngle",
7222
+ "innerRadius",
7223
+ "outerRadius",
7224
+ ],
7225
+ },
7226
+ },
7227
+ indexAxis: "r",
7228
+ startAngle: 0,
7229
+ }),
7230
+ (On.overrides = {
7231
+ aspectRatio: 1,
7232
+ plugins: {
7233
+ legend: {
7234
+ labels: {
7235
+ generateLabels(t) {
7236
+ const e = t.data;
7237
+ if (e.labels.length && e.datasets.length) {
7238
+ const {
7239
+ labels: { pointStyle: i },
7240
+ } = t.legend.options;
7241
+ return e.labels.map((e, s) => {
7242
+ const n = t.getDatasetMeta(0).controller.getStyle(s);
7243
+ return {
7244
+ text: e,
7245
+ fillStyle: n.backgroundColor,
7246
+ strokeStyle: n.borderColor,
7247
+ lineWidth: n.borderWidth,
7248
+ pointStyle: i,
7249
+ hidden: !t.getDataVisibility(s),
7250
+ index: s,
7251
+ };
7252
+ });
7253
+ }
7254
+ return [];
7255
+ },
7256
+ },
7257
+ onClick(t, e, i) {
7258
+ i.chart.toggleDataVisibility(e.index), i.chart.update();
7259
+ },
7260
+ },
7261
+ tooltip: {
7262
+ callbacks: {
7263
+ title: () => "",
7264
+ label: (t) =>
7265
+ t.chart.data.labels[t.dataIndex] + ": " + t.formattedValue,
7266
+ },
7267
+ },
7268
+ },
7269
+ scales: {
7270
+ r: {
7271
+ type: "radialLinear",
7272
+ angleLines: { display: !1 },
7273
+ beginAtZero: !0,
7274
+ grid: { circular: !0 },
7275
+ pointLabels: { display: !1 },
7276
+ startAngle: 0,
7277
+ },
7278
+ },
7279
+ });
7280
+ class An extends Dn {}
7281
+ (An.id = "pie"),
7282
+ (An.defaults = {
7283
+ cutout: 0,
7284
+ rotation: 0,
7285
+ circumference: 360,
7286
+ radius: "100%",
7287
+ });
7288
+ class Tn extends Ps {
7289
+ getLabelAndValue(t) {
7290
+ const e = this._cachedMeta.vScale,
7291
+ i = this.getParsed(t);
7292
+ return {
7293
+ label: e.getLabels()[t],
7294
+ value: "" + e.getLabelForValue(i[e.axis]),
7295
+ };
7296
+ }
7297
+ update(t) {
7298
+ const e = this._cachedMeta,
7299
+ i = e.dataset,
7300
+ s = e.data || [],
7301
+ n = e.iScale.getLabels();
7302
+ if (((i.points = s), "resize" !== t)) {
7303
+ const e = this.resolveDatasetElementOptions(t);
7304
+ this.options.showLine || (e.borderWidth = 0);
7305
+ const o = { _loop: !0, _fullLoop: n.length === s.length, options: e };
7306
+ this.updateElement(i, void 0, o, t);
7307
+ }
7308
+ this.updateElements(s, 0, s.length, t);
7309
+ }
7310
+ updateElements(t, e, i, s) {
7311
+ const n = this.getDataset(),
7312
+ o = this._cachedMeta.rScale,
7313
+ a = "reset" === s;
7314
+ for (let r = e; r < e + i; r++) {
7315
+ const e = t[r],
7316
+ i = this.resolveDataElementOptions(r, e.active ? "active" : s),
7317
+ l = o.getPointPositionForValue(r, n.data[r]),
7318
+ h = a ? o.xCenter : l.x,
7319
+ c = a ? o.yCenter : l.y,
7320
+ d = {
7321
+ x: h,
7322
+ y: c,
7323
+ angle: l.angle,
7324
+ skip: isNaN(h) || isNaN(c),
7325
+ options: i,
7326
+ };
7327
+ this.updateElement(e, r, d, s);
7328
+ }
7329
+ }
7330
+ }
7331
+ (Tn.id = "radar"),
7332
+ (Tn.defaults = {
7333
+ datasetElementType: "line",
7334
+ dataElementType: "point",
7335
+ indexAxis: "r",
7336
+ showLine: !0,
7337
+ elements: { line: { fill: "start" } },
7338
+ }),
7339
+ (Tn.overrides = {
7340
+ aspectRatio: 1,
7341
+ scales: { r: { type: "radialLinear" } },
7342
+ });
7343
+ class Ln extends Cn {}
7344
+ (Ln.id = "scatter"),
7345
+ (Ln.defaults = { showLine: !1, fill: !1 }),
7346
+ (Ln.overrides = {
7347
+ interaction: { mode: "point" },
7348
+ plugins: {
7349
+ tooltip: {
7350
+ callbacks: {
7351
+ title: () => "",
7352
+ label: (t) => "(" + t.label + ", " + t.formattedValue + ")",
7353
+ },
7354
+ },
7355
+ },
7356
+ scales: { x: { type: "linear" }, y: { type: "linear" } },
7357
+ });
7358
+ var Rn = Object.freeze({
7359
+ __proto__: null,
7360
+ BarController: Sn,
7361
+ BubbleController: Pn,
7362
+ DoughnutController: Dn,
7363
+ LineController: Cn,
7364
+ PolarAreaController: On,
7365
+ PieController: An,
7366
+ RadarController: Tn,
7367
+ ScatterController: Ln,
7368
+ });
7369
+ function En(t, e, i) {
7370
+ const {
7371
+ startAngle: s,
7372
+ pixelMargin: n,
7373
+ x: o,
7374
+ y: a,
7375
+ outerRadius: r,
7376
+ innerRadius: l,
7377
+ } = e;
7378
+ let h = n / r;
7379
+ t.beginPath(),
7380
+ t.arc(o, a, r, s - h, i + h),
7381
+ l > n
7382
+ ? ((h = n / l), t.arc(o, a, l, i + h, s - h, !0))
7383
+ : t.arc(o, a, n, i + kt, s - kt),
7384
+ t.closePath(),
7385
+ t.clip();
7386
+ }
7387
+ function In(t, e, i, s) {
7388
+ const n = Be(t.options.borderRadius, [
7389
+ "outerStart",
7390
+ "outerEnd",
7391
+ "innerStart",
7392
+ "innerEnd",
7393
+ ]);
7394
+ const o = (i - e) / 2,
7395
+ a = Math.min(o, (s * e) / 2),
7396
+ r = (t) => {
7397
+ const e = ((i - Math.min(o, t)) * s) / 2;
7398
+ return jt(t, 0, Math.min(o, e));
7399
+ };
7400
+ return {
7401
+ outerStart: r(n.outerStart),
7402
+ outerEnd: r(n.outerEnd),
7403
+ innerStart: jt(n.innerStart, 0, a),
7404
+ innerEnd: jt(n.innerEnd, 0, a),
7405
+ };
7406
+ }
7407
+ function zn(t, e, i, s) {
7408
+ return { x: i + t * Math.cos(e), y: s + t * Math.sin(e) };
7409
+ }
7410
+ function Fn(t, e, i, s, n) {
7411
+ const { x: o, y: a, startAngle: r, pixelMargin: l, innerRadius: h } = e,
7412
+ c = Math.max(e.outerRadius + s + i - l, 0),
7413
+ d = h > 0 ? h + s + i + l : 0;
7414
+ let u = 0;
7415
+ const f = n - r;
7416
+ if (s) {
7417
+ const t = ((h > 0 ? h - s : 0) + (c > 0 ? c - s : 0)) / 2;
7418
+ u = (f - (0 !== t ? (f * t) / (t + s) : f)) / 2;
7419
+ }
7420
+ const g = (f - Math.max(0.001, f * c - i / _t) / c) / 2,
7421
+ p = r + g + u,
7422
+ m = n - g - u,
7423
+ {
7424
+ outerStart: x,
7425
+ outerEnd: b,
7426
+ innerStart: _,
7427
+ innerEnd: y,
7428
+ } = In(e, d, c, m - p),
7429
+ v = c - x,
7430
+ w = c - b,
7431
+ M = p + x / v,
7432
+ k = m - b / w,
7433
+ S = d + _,
7434
+ P = d + y,
7435
+ D = p + _ / S,
7436
+ C = m - y / P;
7437
+ if ((t.beginPath(), t.arc(o, a, c, M, k), b > 0)) {
7438
+ const e = zn(w, k, o, a);
7439
+ t.arc(e.x, e.y, b, k, m + kt);
7440
+ }
7441
+ const O = zn(P, m, o, a);
7442
+ if ((t.lineTo(O.x, O.y), y > 0)) {
7443
+ const e = zn(P, C, o, a);
7444
+ t.arc(e.x, e.y, y, m + kt, C + Math.PI);
7445
+ }
7446
+ if ((t.arc(o, a, d, m - y / d, p + _ / d, !0), _ > 0)) {
7447
+ const e = zn(S, D, o, a);
7448
+ t.arc(e.x, e.y, _, D + Math.PI, p - kt);
7449
+ }
7450
+ const A = zn(v, p, o, a);
7451
+ if ((t.lineTo(A.x, A.y), x > 0)) {
7452
+ const e = zn(v, M, o, a);
7453
+ t.arc(e.x, e.y, x, p - kt, M);
7454
+ }
7455
+ t.closePath();
7456
+ }
7457
+ function Bn(t, e, i, s, n) {
7458
+ const { options: o } = e,
7459
+ { borderWidth: a, borderJoinStyle: r } = o,
7460
+ l = "inner" === o.borderAlign;
7461
+ a &&
7462
+ (l
7463
+ ? ((t.lineWidth = 2 * a), (t.lineJoin = r || "round"))
7464
+ : ((t.lineWidth = a), (t.lineJoin = r || "bevel")),
7465
+ e.fullCircles &&
7466
+ (function (t, e, i) {
7467
+ const {
7468
+ x: s,
7469
+ y: n,
7470
+ startAngle: o,
7471
+ pixelMargin: a,
7472
+ fullCircles: r,
7473
+ } = e,
7474
+ l = Math.max(e.outerRadius - a, 0),
7475
+ h = e.innerRadius + a;
7476
+ let c;
7477
+ for (
7478
+ i && En(t, e, o + yt),
7479
+ t.beginPath(),
7480
+ t.arc(s, n, h, o + yt, o, !0),
7481
+ c = 0;
7482
+ c < r;
7483
+ ++c
7484
+ )
7485
+ t.stroke();
7486
+ for (t.beginPath(), t.arc(s, n, l, o, o + yt), c = 0; c < r; ++c)
7487
+ t.stroke();
7488
+ })(t, e, l),
7489
+ l && En(t, e, n),
7490
+ Fn(t, e, i, s, n),
7491
+ t.stroke());
7492
+ }
7493
+ class Vn extends Ds {
7494
+ constructor(t) {
7495
+ super(),
7496
+ (this.options = void 0),
7497
+ (this.circumference = void 0),
7498
+ (this.startAngle = void 0),
7499
+ (this.endAngle = void 0),
7500
+ (this.innerRadius = void 0),
7501
+ (this.outerRadius = void 0),
7502
+ (this.pixelMargin = 0),
7503
+ (this.fullCircles = 0),
7504
+ t && Object.assign(this, t);
7505
+ }
7506
+ inRange(t, e, i) {
7507
+ const s = this.getProps(["x", "y"], i),
7508
+ { angle: n, distance: o } = Bt(s, { x: t, y: e }),
7509
+ {
7510
+ startAngle: a,
7511
+ endAngle: r,
7512
+ innerRadius: l,
7513
+ outerRadius: h,
7514
+ circumference: c,
7515
+ } = this.getProps(
7516
+ [
7517
+ "startAngle",
7518
+ "endAngle",
7519
+ "innerRadius",
7520
+ "outerRadius",
7521
+ "circumference",
7522
+ ],
7523
+ i
7524
+ ),
7525
+ d = this.options.spacing / 2,
7526
+ u = K(c, r - a) >= yt || Ht(n, a, r),
7527
+ f = Yt(o, l + d, h + d);
7528
+ return u && f;
7529
+ }
7530
+ getCenterPoint(t) {
7531
+ const {
7532
+ x: e,
7533
+ y: i,
7534
+ startAngle: s,
7535
+ endAngle: n,
7536
+ innerRadius: o,
7537
+ outerRadius: a,
7538
+ } = this.getProps(
7539
+ [
7540
+ "x",
7541
+ "y",
7542
+ "startAngle",
7543
+ "endAngle",
7544
+ "innerRadius",
7545
+ "outerRadius",
7546
+ "circumference",
7547
+ ],
7548
+ t
7549
+ ),
7550
+ { offset: r, spacing: l } = this.options,
7551
+ h = (s + n) / 2,
7552
+ c = (o + a + l + r) / 2;
7553
+ return { x: e + Math.cos(h) * c, y: i + Math.sin(h) * c };
7554
+ }
7555
+ tooltipPosition(t) {
7556
+ return this.getCenterPoint(t);
7557
+ }
7558
+ draw(t) {
7559
+ const { options: e, circumference: i } = this,
7560
+ s = (e.offset || 0) / 2,
7561
+ n = (e.spacing || 0) / 2;
7562
+ if (
7563
+ ((this.pixelMargin = "inner" === e.borderAlign ? 0.33 : 0),
7564
+ (this.fullCircles = i > yt ? Math.floor(i / yt) : 0),
7565
+ 0 === i || this.innerRadius < 0 || this.outerRadius < 0)
7566
+ )
7567
+ return;
7568
+ t.save();
7569
+ let o = 0;
7570
+ if (s) {
7571
+ o = s / 2;
7572
+ const e = (this.startAngle + this.endAngle) / 2;
7573
+ t.translate(Math.cos(e) * o, Math.sin(e) * o),
7574
+ this.circumference >= _t && (o = s);
7575
+ }
7576
+ (t.fillStyle = e.backgroundColor), (t.strokeStyle = e.borderColor);
7577
+ const a = (function (t, e, i, s) {
7578
+ const { fullCircles: n, startAngle: o, circumference: a } = e;
7579
+ let r = e.endAngle;
7580
+ if (n) {
7581
+ Fn(t, e, i, s, o + yt);
7582
+ for (let e = 0; e < n; ++e) t.fill();
7583
+ isNaN(a) || ((r = o + (a % yt)), a % yt == 0 && (r += yt));
7584
+ }
7585
+ return Fn(t, e, i, s, r), t.fill(), r;
7586
+ })(t, this, o, n);
7587
+ Bn(t, this, o, n, a), t.restore();
7588
+ }
7589
+ }
7590
+ function Wn(t, e, i = e) {
7591
+ (t.lineCap = K(i.borderCapStyle, e.borderCapStyle)),
7592
+ t.setLineDash(K(i.borderDash, e.borderDash)),
7593
+ (t.lineDashOffset = K(i.borderDashOffset, e.borderDashOffset)),
7594
+ (t.lineJoin = K(i.borderJoinStyle, e.borderJoinStyle)),
7595
+ (t.lineWidth = K(i.borderWidth, e.borderWidth)),
7596
+ (t.strokeStyle = K(i.borderColor, e.borderColor));
7597
+ }
7598
+ function Nn(t, e, i) {
7599
+ t.lineTo(i.x, i.y);
7600
+ }
7601
+ function Hn(t, e, i = {}) {
7602
+ const s = t.length,
7603
+ { start: n = 0, end: o = s - 1 } = i,
7604
+ { start: a, end: r } = e,
7605
+ l = Math.max(n, a),
7606
+ h = Math.min(o, r),
7607
+ c = (n < a && o < a) || (n > r && o > r);
7608
+ return {
7609
+ count: s,
7610
+ start: l,
7611
+ loop: e.loop,
7612
+ ilen: h < l && !c ? s + h - l : h - l,
7613
+ };
7614
+ }
7615
+ function jn(t, e, i, s) {
7616
+ const { points: n, options: o } = e,
7617
+ { count: a, start: r, loop: l, ilen: h } = Hn(n, i, s),
7618
+ c = (function (t) {
7619
+ return t.stepped
7620
+ ? ee
7621
+ : t.tension || "monotone" === t.cubicInterpolationMode
7622
+ ? ie
7623
+ : Nn;
7624
+ })(o);
7625
+ let d,
7626
+ u,
7627
+ f,
7628
+ { move: g = !0, reverse: p } = s || {};
7629
+ for (d = 0; d <= h; ++d)
7630
+ (u = n[(r + (p ? h - d : d)) % a]),
7631
+ u.skip ||
7632
+ (g ? (t.moveTo(u.x, u.y), (g = !1)) : c(t, f, u, p, o.stepped),
7633
+ (f = u));
7634
+ return l && ((u = n[(r + (p ? h : 0)) % a]), c(t, f, u, p, o.stepped)), !!l;
7635
+ }
7636
+ function $n(t, e, i, s) {
7637
+ const n = e.points,
7638
+ { count: o, start: a, ilen: r } = Hn(n, i, s),
7639
+ { move: l = !0, reverse: h } = s || {};
7640
+ let c,
7641
+ d,
7642
+ u,
7643
+ f,
7644
+ g,
7645
+ p,
7646
+ m = 0,
7647
+ x = 0;
7648
+ const b = (t) => (a + (h ? r - t : t)) % o,
7649
+ _ = () => {
7650
+ f !== g && (t.lineTo(m, g), t.lineTo(m, f), t.lineTo(m, p));
7651
+ };
7652
+ for (l && ((d = n[b(0)]), t.moveTo(d.x, d.y)), c = 0; c <= r; ++c) {
7653
+ if (((d = n[b(c)]), d.skip)) continue;
7654
+ const e = d.x,
7655
+ i = d.y,
7656
+ s = 0 | e;
7657
+ s === u
7658
+ ? (i < f ? (f = i) : i > g && (g = i), (m = (x * m + e) / ++x))
7659
+ : (_(), t.lineTo(e, i), (u = s), (x = 0), (f = g = i)),
7660
+ (p = i);
7661
+ }
7662
+ _();
7663
+ }
7664
+ function Yn(t) {
7665
+ const e = t.options,
7666
+ i = e.borderDash && e.borderDash.length;
7667
+ return !(
7668
+ t._decimated ||
7669
+ t._loop ||
7670
+ e.tension ||
7671
+ "monotone" === e.cubicInterpolationMode ||
7672
+ e.stepped ||
7673
+ i
7674
+ )
7675
+ ? $n
7676
+ : jn;
7677
+ }
7678
+ (Vn.id = "arc"),
7679
+ (Vn.defaults = {
7680
+ borderAlign: "center",
7681
+ borderColor: "#fff",
7682
+ borderJoinStyle: void 0,
7683
+ borderRadius: 0,
7684
+ borderWidth: 2,
7685
+ offset: 0,
7686
+ spacing: 0,
7687
+ angle: void 0,
7688
+ }),
7689
+ (Vn.defaultRoutes = { backgroundColor: "backgroundColor" });
7690
+ const Un = "function" == typeof Path2D;
7691
+ function Xn(t, e, i, s) {
7692
+ Un && !e.options.segment
7693
+ ? (function (t, e, i, s) {
7694
+ let n = e._path;
7695
+ n || ((n = e._path = new Path2D()), e.path(n, i, s) && n.closePath()),
7696
+ Wn(t, e.options),
7697
+ t.stroke(n);
7698
+ })(t, e, i, s)
7699
+ : (function (t, e, i, s) {
7700
+ const { segments: n, options: o } = e,
7701
+ a = Yn(e);
7702
+ for (const r of n)
7703
+ Wn(t, o, r.style),
7704
+ t.beginPath(),
7705
+ a(t, e, r, { start: i, end: i + s - 1 }) && t.closePath(),
7706
+ t.stroke();
7707
+ })(t, e, i, s);
7708
+ }
7709
+ class qn extends Ds {
7710
+ constructor(t) {
7711
+ super(),
7712
+ (this.animated = !0),
7713
+ (this.options = void 0),
7714
+ (this._chart = void 0),
7715
+ (this._loop = void 0),
7716
+ (this._fullLoop = void 0),
7717
+ (this._path = void 0),
7718
+ (this._points = void 0),
7719
+ (this._segments = void 0),
7720
+ (this._decimated = !1),
7721
+ (this._pointsUpdated = !1),
7722
+ (this._datasetIndex = void 0),
7723
+ t && Object.assign(this, t);
7724
+ }
7725
+ updateControlPoints(t, e) {
7726
+ const i = this.options;
7727
+ if (
7728
+ (i.tension || "monotone" === i.cubicInterpolationMode) &&
7729
+ !i.stepped &&
7730
+ !this._pointsUpdated
7731
+ ) {
7732
+ const s = i.spanGaps ? this._loop : this._fullLoop;
7733
+ ki(this._points, i, t, s, e), (this._pointsUpdated = !0);
7734
+ }
7735
+ }
7736
+ set points(t) {
7737
+ (this._points = t),
7738
+ delete this._segments,
7739
+ delete this._path,
7740
+ (this._pointsUpdated = !1);
7741
+ }
7742
+ get points() {
7743
+ return this._points;
7744
+ }
7745
+ get segments() {
7746
+ return (
7747
+ this._segments || (this._segments = Ni(this, this.options.segment))
7748
+ );
7749
+ }
7750
+ first() {
7751
+ const t = this.segments,
7752
+ e = this.points;
7753
+ return t.length && e[t[0].start];
7754
+ }
7755
+ last() {
7756
+ const t = this.segments,
7757
+ e = this.points,
7758
+ i = t.length;
7759
+ return i && e[t[i - 1].end];
7760
+ }
7761
+ interpolate(t, e) {
7762
+ const i = this.options,
7763
+ s = t[e],
7764
+ n = this.points,
7765
+ o = Wi(this, { property: e, start: s, end: s });
7766
+ if (!o.length) return;
7767
+ const a = [],
7768
+ r = (function (t) {
7769
+ return t.stepped
7770
+ ? Ai
7771
+ : t.tension || "monotone" === t.cubicInterpolationMode
7772
+ ? Ti
7773
+ : Oi;
7774
+ })(i);
7775
+ let l, h;
7776
+ for (l = 0, h = o.length; l < h; ++l) {
7777
+ const { start: h, end: c } = o[l],
7778
+ d = n[h],
7779
+ u = n[c];
7780
+ if (d === u) {
7781
+ a.push(d);
7782
+ continue;
7783
+ }
7784
+ const f = r(d, u, Math.abs((s - d[e]) / (u[e] - d[e])), i.stepped);
7785
+ (f[e] = t[e]), a.push(f);
7786
+ }
7787
+ return 1 === a.length ? a[0] : a;
7788
+ }
7789
+ pathSegment(t, e, i) {
7790
+ return Yn(this)(t, this, e, i);
7791
+ }
7792
+ path(t, e, i) {
7793
+ const s = this.segments,
7794
+ n = Yn(this);
7795
+ let o = this._loop;
7796
+ (e = e || 0), (i = i || this.points.length - e);
7797
+ for (const a of s) o &= n(t, this, a, { start: e, end: e + i - 1 });
7798
+ return !!o;
7799
+ }
7800
+ draw(t, e, i, s) {
7801
+ const n = this.options || {};
7802
+ (this.points || []).length &&
7803
+ n.borderWidth &&
7804
+ (t.save(), Xn(t, this, i, s), t.restore()),
7805
+ this.animated && ((this._pointsUpdated = !1), (this._path = void 0));
7806
+ }
7807
+ }
7808
+ function Kn(t, e, i, s) {
7809
+ const n = t.options,
7810
+ { [i]: o } = t.getProps([i], s);
7811
+ return Math.abs(e - o) < n.radius + n.hitRadius;
7812
+ }
7813
+ (qn.id = "line"),
7814
+ (qn.defaults = {
7815
+ borderCapStyle: "butt",
7816
+ borderDash: [],
7817
+ borderDashOffset: 0,
7818
+ borderJoinStyle: "miter",
7819
+ borderWidth: 3,
7820
+ capBezierPoints: !0,
7821
+ cubicInterpolationMode: "default",
7822
+ fill: !1,
7823
+ spanGaps: !1,
7824
+ stepped: !1,
7825
+ tension: 0,
7826
+ }),
7827
+ (qn.defaultRoutes = {
7828
+ backgroundColor: "backgroundColor",
7829
+ borderColor: "borderColor",
7830
+ }),
7831
+ (qn.descriptors = {
7832
+ _scriptable: !0,
7833
+ _indexable: (t) => "borderDash" !== t && "fill" !== t,
7834
+ });
7835
+ class Gn extends Ds {
7836
+ constructor(t) {
7837
+ super(),
7838
+ (this.options = void 0),
7839
+ (this.parsed = void 0),
7840
+ (this.skip = void 0),
7841
+ (this.stop = void 0),
7842
+ t && Object.assign(this, t);
7843
+ }
7844
+ inRange(t, e, i) {
7845
+ const s = this.options,
7846
+ { x: n, y: o } = this.getProps(["x", "y"], i);
7847
+ return (
7848
+ Math.pow(t - n, 2) + Math.pow(e - o, 2) <
7849
+ Math.pow(s.hitRadius + s.radius, 2)
7850
+ );
7851
+ }
7852
+ inXRange(t, e) {
7853
+ return Kn(this, t, "x", e);
7854
+ }
7855
+ inYRange(t, e) {
7856
+ return Kn(this, t, "y", e);
7857
+ }
7858
+ getCenterPoint(t) {
7859
+ const { x: e, y: i } = this.getProps(["x", "y"], t);
7860
+ return { x: e, y: i };
7861
+ }
7862
+ size(t) {
7863
+ let e = (t = t || this.options || {}).radius || 0;
7864
+ e = Math.max(e, (e && t.hoverRadius) || 0);
7865
+ return 2 * (e + ((e && t.borderWidth) || 0));
7866
+ }
7867
+ draw(t, e) {
7868
+ const i = this.options;
7869
+ this.skip ||
7870
+ i.radius < 0.1 ||
7871
+ !Jt(this, e, this.size(i) / 2) ||
7872
+ ((t.strokeStyle = i.borderColor),
7873
+ (t.lineWidth = i.borderWidth),
7874
+ (t.fillStyle = i.backgroundColor),
7875
+ Zt(t, i, this.x, this.y));
7876
+ }
7877
+ getRange() {
7878
+ const t = this.options || {};
7879
+ return t.radius + t.hitRadius;
7880
+ }
7881
+ }
7882
+ function Zn(t, e) {
7883
+ const {
7884
+ x: i,
7885
+ y: s,
7886
+ base: n,
7887
+ width: o,
7888
+ height: a,
7889
+ } = t.getProps(["x", "y", "base", "width", "height"], e);
7890
+ let r, l, h, c, d;
7891
+ return (
7892
+ t.horizontal
7893
+ ? ((d = a / 2),
7894
+ (r = Math.min(i, n)),
7895
+ (l = Math.max(i, n)),
7896
+ (h = s - d),
7897
+ (c = s + d))
7898
+ : ((d = o / 2),
7899
+ (r = i - d),
7900
+ (l = i + d),
7901
+ (h = Math.min(s, n)),
7902
+ (c = Math.max(s, n))),
7903
+ { left: r, top: h, right: l, bottom: c }
7904
+ );
7905
+ }
7906
+ function Jn(t, e, i, s) {
7907
+ return t ? 0 : jt(e, i, s);
7908
+ }
7909
+ function Qn(t) {
7910
+ const e = Zn(t),
7911
+ i = e.right - e.left,
7912
+ s = e.bottom - e.top,
7913
+ n = (function (t, e, i) {
7914
+ const s = t.options.borderWidth,
7915
+ n = t.borderSkipped,
7916
+ o = Ve(s);
7917
+ return {
7918
+ t: Jn(n.top, o.top, 0, i),
7919
+ r: Jn(n.right, o.right, 0, e),
7920
+ b: Jn(n.bottom, o.bottom, 0, i),
7921
+ l: Jn(n.left, o.left, 0, e),
7922
+ };
7923
+ })(t, i / 2, s / 2),
7924
+ o = (function (t, e, i) {
7925
+ const { enableBorderRadius: s } = t.getProps(["enableBorderRadius"]),
7926
+ n = t.options.borderRadius,
7927
+ o = We(n),
7928
+ a = Math.min(e, i),
7929
+ r = t.borderSkipped,
7930
+ l = s || U(n);
7931
+ return {
7932
+ topLeft: Jn(!l || r.top || r.left, o.topLeft, 0, a),
7933
+ topRight: Jn(!l || r.top || r.right, o.topRight, 0, a),
7934
+ bottomLeft: Jn(!l || r.bottom || r.left, o.bottomLeft, 0, a),
7935
+ bottomRight: Jn(!l || r.bottom || r.right, o.bottomRight, 0, a),
7936
+ };
7937
+ })(t, i / 2, s / 2);
7938
+ return {
7939
+ outer: { x: e.left, y: e.top, w: i, h: s, radius: o },
7940
+ inner: {
7941
+ x: e.left + n.l,
7942
+ y: e.top + n.t,
7943
+ w: i - n.l - n.r,
7944
+ h: s - n.t - n.b,
7945
+ radius: {
7946
+ topLeft: Math.max(0, o.topLeft - Math.max(n.t, n.l)),
7947
+ topRight: Math.max(0, o.topRight - Math.max(n.t, n.r)),
7948
+ bottomLeft: Math.max(0, o.bottomLeft - Math.max(n.b, n.l)),
7949
+ bottomRight: Math.max(0, o.bottomRight - Math.max(n.b, n.r)),
7950
+ },
7951
+ },
7952
+ };
7953
+ }
7954
+ function to(t, e, i, s) {
7955
+ const n = null === e,
7956
+ o = null === i,
7957
+ a = t && !(n && o) && Zn(t, s);
7958
+ return a && (n || Yt(e, a.left, a.right)) && (o || Yt(i, a.top, a.bottom));
7959
+ }
7960
+ function eo(t, e) {
7961
+ t.rect(e.x, e.y, e.w, e.h);
7962
+ }
7963
+ function io(t, e, i = {}) {
7964
+ const s = t.x !== i.x ? -e : 0,
7965
+ n = t.y !== i.y ? -e : 0,
7966
+ o = (t.x + t.w !== i.x + i.w ? e : 0) - s,
7967
+ a = (t.y + t.h !== i.y + i.h ? e : 0) - n;
7968
+ return { x: t.x + s, y: t.y + n, w: t.w + o, h: t.h + a, radius: t.radius };
7969
+ }
7970
+ (Gn.id = "point"),
7971
+ (Gn.defaults = {
7972
+ borderWidth: 1,
7973
+ hitRadius: 1,
7974
+ hoverBorderWidth: 1,
7975
+ hoverRadius: 4,
7976
+ pointStyle: "circle",
7977
+ radius: 3,
7978
+ rotation: 0,
7979
+ }),
7980
+ (Gn.defaultRoutes = {
7981
+ backgroundColor: "backgroundColor",
7982
+ borderColor: "borderColor",
7983
+ });
7984
+ class so extends Ds {
7985
+ constructor(t) {
7986
+ super(),
7987
+ (this.options = void 0),
7988
+ (this.horizontal = void 0),
7989
+ (this.base = void 0),
7990
+ (this.width = void 0),
7991
+ (this.height = void 0),
7992
+ (this.inflateAmount = void 0),
7993
+ t && Object.assign(this, t);
7994
+ }
7995
+ draw(t) {
7996
+ const {
7997
+ inflateAmount: e,
7998
+ options: { borderColor: i, backgroundColor: s },
7999
+ } = this,
8000
+ { inner: n, outer: o } = Qn(this),
8001
+ a =
8002
+ (r = o.radius).topLeft || r.topRight || r.bottomLeft || r.bottomRight
8003
+ ? oe
8004
+ : eo;
8005
+ var r;
8006
+ t.save(),
8007
+ (o.w === n.w && o.h === n.h) ||
8008
+ (t.beginPath(),
8009
+ a(t, io(o, e, n)),
8010
+ t.clip(),
8011
+ a(t, io(n, -e, o)),
8012
+ (t.fillStyle = i),
8013
+ t.fill("evenodd")),
8014
+ t.beginPath(),
8015
+ a(t, io(n, e)),
8016
+ (t.fillStyle = s),
8017
+ t.fill(),
8018
+ t.restore();
8019
+ }
8020
+ inRange(t, e, i) {
8021
+ return to(this, t, e, i);
8022
+ }
8023
+ inXRange(t, e) {
8024
+ return to(this, t, null, e);
8025
+ }
8026
+ inYRange(t, e) {
8027
+ return to(this, null, t, e);
8028
+ }
8029
+ getCenterPoint(t) {
8030
+ const {
8031
+ x: e,
8032
+ y: i,
8033
+ base: s,
8034
+ horizontal: n,
8035
+ } = this.getProps(["x", "y", "base", "horizontal"], t);
8036
+ return { x: n ? (e + s) / 2 : e, y: n ? i : (i + s) / 2 };
8037
+ }
8038
+ getRange(t) {
8039
+ return "x" === t ? this.width / 2 : this.height / 2;
8040
+ }
8041
+ }
8042
+ (so.id = "bar"),
8043
+ (so.defaults = {
8044
+ borderSkipped: "start",
8045
+ borderWidth: 0,
8046
+ borderRadius: 0,
8047
+ inflateAmount: "auto",
8048
+ pointStyle: void 0,
8049
+ }),
8050
+ (so.defaultRoutes = {
8051
+ backgroundColor: "backgroundColor",
8052
+ borderColor: "borderColor",
8053
+ });
8054
+ var no = Object.freeze({
8055
+ __proto__: null,
8056
+ ArcElement: Vn,
8057
+ LineElement: qn,
8058
+ PointElement: Gn,
8059
+ BarElement: so,
8060
+ });
8061
+ function oo(t) {
8062
+ if (t._decimated) {
8063
+ const e = t._data;
8064
+ delete t._decimated,
8065
+ delete t._data,
8066
+ Object.defineProperty(t, "data", { value: e });
8067
+ }
8068
+ }
8069
+ function ao(t) {
8070
+ t.data.datasets.forEach((t) => {
8071
+ oo(t);
8072
+ });
8073
+ }
8074
+ var ro = {
8075
+ id: "decimation",
8076
+ defaults: { algorithm: "min-max", enabled: !1 },
8077
+ beforeElementsUpdate: (t, e, i) => {
8078
+ if (!i.enabled) return void ao(t);
8079
+ const s = t.width;
8080
+ t.data.datasets.forEach((e, n) => {
8081
+ const { _data: o, indexAxis: a } = e,
8082
+ r = t.getDatasetMeta(n),
8083
+ l = o || e.data;
8084
+ if ("y" === je([a, t.options.indexAxis])) return;
8085
+ if ("line" !== r.type) return;
8086
+ const h = t.scales[r.xAxisID];
8087
+ if ("linear" !== h.type && "time" !== h.type) return;
8088
+ if (t.options.parsing) return;
8089
+ let { start: c, count: d } = (function (t, e) {
8090
+ const i = e.length;
8091
+ let s,
8092
+ n = 0;
8093
+ const { iScale: o } = t,
8094
+ {
8095
+ min: a,
8096
+ max: r,
8097
+ minDefined: l,
8098
+ maxDefined: h,
8099
+ } = o.getUserBounds();
8100
+ return (
8101
+ l && (n = jt(re(e, o.axis, a).lo, 0, i - 1)),
8102
+ (s = h ? jt(re(e, o.axis, r).hi + 1, n, i) - n : i - n),
8103
+ { start: n, count: s }
8104
+ );
8105
+ })(r, l);
8106
+ if (d <= (i.threshold || 4 * s)) return void oo(e);
8107
+ let u;
8108
+ switch (
8109
+ ($(o) &&
8110
+ ((e._data = l),
8111
+ delete e.data,
8112
+ Object.defineProperty(e, "data", {
8113
+ configurable: !0,
8114
+ enumerable: !0,
8115
+ get: function () {
8116
+ return this._decimated;
8117
+ },
8118
+ set: function (t) {
8119
+ this._data = t;
8120
+ },
8121
+ })),
8122
+ i.algorithm)
8123
+ ) {
8124
+ case "lttb":
8125
+ u = (function (t, e, i, s, n) {
8126
+ const o = n.samples || s;
8127
+ if (o >= i) return t.slice(e, e + i);
8128
+ const a = [],
8129
+ r = (i - 2) / (o - 2);
8130
+ let l = 0;
8131
+ const h = e + i - 1;
8132
+ let c,
8133
+ d,
8134
+ u,
8135
+ f,
8136
+ g,
8137
+ p = e;
8138
+ for (a[l++] = t[p], c = 0; c < o - 2; c++) {
8139
+ let s,
8140
+ n = 0,
8141
+ o = 0;
8142
+ const h = Math.floor((c + 1) * r) + 1 + e,
8143
+ m = Math.min(Math.floor((c + 2) * r) + 1, i) + e,
8144
+ x = m - h;
8145
+ for (s = h; s < m; s++) (n += t[s].x), (o += t[s].y);
8146
+ (n /= x), (o /= x);
8147
+ const b = Math.floor(c * r) + 1 + e,
8148
+ _ = Math.min(Math.floor((c + 1) * r) + 1, i) + e,
8149
+ { x: y, y: v } = t[p];
8150
+ for (u = f = -1, s = b; s < _; s++)
8151
+ (f =
8152
+ 0.5 *
8153
+ Math.abs((y - n) * (t[s].y - v) - (y - t[s].x) * (o - v))),
8154
+ f > u && ((u = f), (d = t[s]), (g = s));
8155
+ (a[l++] = d), (p = g);
8156
+ }
8157
+ return (a[l++] = t[h]), a;
8158
+ })(l, c, d, s, i);
8159
+ break;
8160
+ case "min-max":
8161
+ u = (function (t, e, i, s) {
8162
+ let n,
8163
+ o,
8164
+ a,
8165
+ r,
8166
+ l,
8167
+ h,
8168
+ c,
8169
+ d,
8170
+ u,
8171
+ f,
8172
+ g = 0,
8173
+ p = 0;
8174
+ const m = [],
8175
+ x = e + i - 1,
8176
+ b = t[e].x,
8177
+ _ = t[x].x - b;
8178
+ for (n = e; n < e + i; ++n) {
8179
+ (o = t[n]), (a = ((o.x - b) / _) * s), (r = o.y);
8180
+ const e = 0 | a;
8181
+ if (e === l)
8182
+ r < u ? ((u = r), (h = n)) : r > f && ((f = r), (c = n)),
8183
+ (g = (p * g + o.x) / ++p);
8184
+ else {
8185
+ const i = n - 1;
8186
+ if (!$(h) && !$(c)) {
8187
+ const e = Math.min(h, c),
8188
+ s = Math.max(h, c);
8189
+ e !== d && e !== i && m.push({ ...t[e], x: g }),
8190
+ s !== d && s !== i && m.push({ ...t[s], x: g });
8191
+ }
8192
+ n > 0 && i !== d && m.push(t[i]),
8193
+ m.push(o),
8194
+ (l = e),
8195
+ (p = 0),
8196
+ (u = f = r),
8197
+ (h = c = d = n);
8198
+ }
8199
+ }
8200
+ return m;
8201
+ })(l, c, d, s);
8202
+ break;
8203
+ default:
8204
+ throw new Error(
8205
+ `Unsupported decimation algorithm '${i.algorithm}'`
8206
+ );
8207
+ }
8208
+ e._decimated = u;
8209
+ });
8210
+ },
8211
+ destroy(t) {
8212
+ ao(t);
8213
+ },
8214
+ };
8215
+ function lo(t, e, i) {
8216
+ const s = (function (t) {
8217
+ const e = t.options,
8218
+ i = e.fill;
8219
+ let s = K(i && i.target, i);
8220
+ return (
8221
+ void 0 === s && (s = !!e.backgroundColor),
8222
+ !1 !== s && null !== s && (!0 === s ? "origin" : s)
8223
+ );
8224
+ })(t);
8225
+ if (U(s)) return !isNaN(s.value) && s;
8226
+ let n = parseFloat(s);
8227
+ return X(n) && Math.floor(n) === n
8228
+ ? (("-" !== s[0] && "+" !== s[0]) || (n = e + n),
8229
+ !(n === e || n < 0 || n >= i) && n)
8230
+ : ["origin", "start", "end", "stack", "shape"].indexOf(s) >= 0 && s;
8231
+ }
8232
+ class ho {
8233
+ constructor(t) {
8234
+ (this.x = t.x), (this.y = t.y), (this.radius = t.radius);
8235
+ }
8236
+ pathSegment(t, e, i) {
8237
+ const { x: s, y: n, radius: o } = this;
8238
+ return (
8239
+ (e = e || { start: 0, end: yt }),
8240
+ t.arc(s, n, o, e.end, e.start, !0),
8241
+ !i.bounds
8242
+ );
8243
+ }
8244
+ interpolate(t) {
8245
+ const { x: e, y: i, radius: s } = this,
8246
+ n = t.angle;
8247
+ return { x: e + Math.cos(n) * s, y: i + Math.sin(n) * s, angle: n };
8248
+ }
8249
+ }
8250
+ function co(t) {
8251
+ return (t.scale || {}).getPointPositionForValue
8252
+ ? (function (t) {
8253
+ const { scale: e, fill: i } = t,
8254
+ s = e.options,
8255
+ n = e.getLabels().length,
8256
+ o = [],
8257
+ a = s.reverse ? e.max : e.min,
8258
+ r = s.reverse ? e.min : e.max;
8259
+ let l, h, c;
8260
+ if (
8261
+ ((c =
8262
+ "start" === i
8263
+ ? a
8264
+ : "end" === i
8265
+ ? r
8266
+ : U(i)
8267
+ ? i.value
8268
+ : e.getBaseValue()),
8269
+ s.grid.circular)
8270
+ )
8271
+ return (
8272
+ (h = e.getPointPositionForValue(0, a)),
8273
+ new ho({
8274
+ x: h.x,
8275
+ y: h.y,
8276
+ radius: e.getDistanceFromCenterForValue(c),
8277
+ })
8278
+ );
8279
+ for (l = 0; l < n; ++l) o.push(e.getPointPositionForValue(l, c));
8280
+ return o;
8281
+ })(t)
8282
+ : (function (t) {
8283
+ const { scale: e = {}, fill: i } = t;
8284
+ let s,
8285
+ n = null;
8286
+ return (
8287
+ "start" === i
8288
+ ? (n = e.bottom)
8289
+ : "end" === i
8290
+ ? (n = e.top)
8291
+ : U(i)
8292
+ ? (n = e.getPixelForValue(i.value))
8293
+ : e.getBasePixel && (n = e.getBasePixel()),
8294
+ X(n)
8295
+ ? ((s = e.isHorizontal()), { x: s ? n : null, y: s ? null : n })
8296
+ : null
8297
+ );
8298
+ })(t);
8299
+ }
8300
+ function uo(t, e, i) {
8301
+ for (; e > t; e--) {
8302
+ const t = i[e];
8303
+ if (!isNaN(t.x) && !isNaN(t.y)) break;
8304
+ }
8305
+ return e;
8306
+ }
8307
+ function fo(t, e, i) {
8308
+ const s = [];
8309
+ for (let n = 0; n < i.length; n++) {
8310
+ const o = i[n],
8311
+ { first: a, last: r, point: l } = go(o, e, "x");
8312
+ if (!(!l || (a && r)))
8313
+ if (a) s.unshift(l);
8314
+ else if ((t.push(l), !r)) break;
8315
+ }
8316
+ t.push(...s);
8317
+ }
8318
+ function go(t, e, i) {
8319
+ const s = t.interpolate(e, i);
8320
+ if (!s) return {};
8321
+ const n = s[i],
8322
+ o = t.segments,
8323
+ a = t.points;
8324
+ let r = !1,
8325
+ l = !1;
8326
+ for (let t = 0; t < o.length; t++) {
8327
+ const e = o[t],
8328
+ s = a[e.start][i],
8329
+ h = a[e.end][i];
8330
+ if (Yt(n, s, h)) {
8331
+ (r = n === s), (l = n === h);
8332
+ break;
8333
+ }
8334
+ }
8335
+ return { first: r, last: l, point: s };
8336
+ }
8337
+ function po(t) {
8338
+ const { chart: e, fill: i, line: s } = t;
8339
+ if (X(i))
8340
+ return (function (t, e) {
8341
+ const i = t.getDatasetMeta(e);
8342
+ return i && t.isDatasetVisible(e) ? i.dataset : null;
8343
+ })(e, i);
8344
+ if ("stack" === i)
8345
+ return (function (t) {
8346
+ const { scale: e, index: i, line: s } = t,
8347
+ n = [],
8348
+ o = s.segments,
8349
+ a = s.points,
8350
+ r = (function (t, e) {
8351
+ const i = [],
8352
+ s = t.getMatchingVisibleMetas("line");
8353
+ for (let t = 0; t < s.length; t++) {
8354
+ const n = s[t];
8355
+ if (n.index === e) break;
8356
+ n.hidden || i.unshift(n.dataset);
8357
+ }
8358
+ return i;
8359
+ })(e, i);
8360
+ r.push(mo({ x: null, y: e.bottom }, s));
8361
+ for (let t = 0; t < o.length; t++) {
8362
+ const e = o[t];
8363
+ for (let t = e.start; t <= e.end; t++) fo(n, a[t], r);
8364
+ }
8365
+ return new qn({ points: n, options: {} });
8366
+ })(t);
8367
+ if ("shape" === i) return !0;
8368
+ const n = co(t);
8369
+ return n instanceof ho ? n : mo(n, s);
8370
+ }
8371
+ function mo(t, e) {
8372
+ let i = [],
8373
+ s = !1;
8374
+ return (
8375
+ Y(t)
8376
+ ? ((s = !0), (i = t))
8377
+ : (i = (function (t, e) {
8378
+ const { x: i = null, y: s = null } = t || {},
8379
+ n = e.points,
8380
+ o = [];
8381
+ return (
8382
+ e.segments.forEach(({ start: t, end: e }) => {
8383
+ e = uo(t, e, n);
8384
+ const a = n[t],
8385
+ r = n[e];
8386
+ null !== s
8387
+ ? (o.push({ x: a.x, y: s }), o.push({ x: r.x, y: s }))
8388
+ : null !== i &&
8389
+ (o.push({ x: i, y: a.y }), o.push({ x: i, y: r.y }));
8390
+ }),
8391
+ o
8392
+ );
8393
+ })(t, e)),
8394
+ i.length
8395
+ ? new qn({ points: i, options: { tension: 0 }, _loop: s, _fullLoop: s })
8396
+ : null
8397
+ );
8398
+ }
8399
+ function xo(t, e, i) {
8400
+ let s = t[e].fill;
8401
+ const n = [e];
8402
+ let o;
8403
+ if (!i) return s;
8404
+ for (; !1 !== s && -1 === n.indexOf(s); ) {
8405
+ if (!X(s)) return s;
8406
+ if (((o = t[s]), !o)) return !1;
8407
+ if (o.visible) return s;
8408
+ n.push(s), (s = o.fill);
8409
+ }
8410
+ return !1;
8411
+ }
8412
+ function bo(t, e, i) {
8413
+ const { segments: s, points: n } = e;
8414
+ let o = !0,
8415
+ a = !1;
8416
+ t.beginPath();
8417
+ for (const r of s) {
8418
+ const { start: s, end: l } = r,
8419
+ h = n[s],
8420
+ c = n[uo(s, l, n)];
8421
+ o
8422
+ ? (t.moveTo(h.x, h.y), (o = !1))
8423
+ : (t.lineTo(h.x, i), t.lineTo(h.x, h.y)),
8424
+ (a = !!e.pathSegment(t, r, { move: a })),
8425
+ a ? t.closePath() : t.lineTo(c.x, i);
8426
+ }
8427
+ t.lineTo(e.first().x, i), t.closePath(), t.clip();
8428
+ }
8429
+ function _o(t, e, i, s) {
8430
+ if (s) return;
8431
+ let n = e[t],
8432
+ o = i[t];
8433
+ return (
8434
+ "angle" === t && ((n = Nt(n)), (o = Nt(o))),
8435
+ { property: t, start: n, end: o }
8436
+ );
8437
+ }
8438
+ function yo(t, e, i, s) {
8439
+ return t && e ? s(t[i], e[i]) : t ? t[i] : e ? e[i] : 0;
8440
+ }
8441
+ function vo(t, e, i) {
8442
+ const { top: s, bottom: n } = e.chart.chartArea,
8443
+ { property: o, start: a, end: r } = i || {};
8444
+ "x" === o && (t.beginPath(), t.rect(a, s, r - a, n - s), t.clip());
8445
+ }
8446
+ function wo(t, e, i, s) {
8447
+ const n = e.interpolate(i, s);
8448
+ n && t.lineTo(n.x, n.y);
8449
+ }
8450
+ function Mo(t, e) {
8451
+ const { line: i, target: s, property: n, color: o, scale: a } = e,
8452
+ r = (function (t, e, i) {
8453
+ const s = t.segments,
8454
+ n = t.points,
8455
+ o = e.points,
8456
+ a = [];
8457
+ for (const t of s) {
8458
+ let { start: s, end: r } = t;
8459
+ r = uo(s, r, n);
8460
+ const l = _o(i, n[s], n[r], t.loop);
8461
+ if (!e.segments) {
8462
+ a.push({ source: t, target: l, start: n[s], end: n[r] });
8463
+ continue;
8464
+ }
8465
+ const h = Wi(e, l);
8466
+ for (const e of h) {
8467
+ const s = _o(i, o[e.start], o[e.end], e.loop),
8468
+ r = Vi(t, n, s);
8469
+ for (const t of r)
8470
+ a.push({
8471
+ source: t,
8472
+ target: e,
8473
+ start: { [i]: yo(l, s, "start", Math.max) },
8474
+ end: { [i]: yo(l, s, "end", Math.min) },
8475
+ });
8476
+ }
8477
+ }
8478
+ return a;
8479
+ })(i, s, n);
8480
+ for (const { source: e, target: l, start: h, end: c } of r) {
8481
+ const { style: { backgroundColor: r = o } = {} } = e,
8482
+ d = !0 !== s;
8483
+ t.save(), (t.fillStyle = r), vo(t, a, d && _o(n, h, c)), t.beginPath();
8484
+ const u = !!i.pathSegment(t, e);
8485
+ let f;
8486
+ if (d) {
8487
+ u ? t.closePath() : wo(t, s, c, n);
8488
+ const e = !!s.pathSegment(t, l, { move: u, reverse: !0 });
8489
+ (f = u && e), f || wo(t, s, h, n);
8490
+ }
8491
+ t.closePath(), t.fill(f ? "evenodd" : "nonzero"), t.restore();
8492
+ }
8493
+ }
8494
+ function ko(t, e, i) {
8495
+ const s = po(e),
8496
+ { line: n, scale: o, axis: a } = e,
8497
+ r = n.options,
8498
+ l = r.fill,
8499
+ h = r.backgroundColor,
8500
+ { above: c = h, below: d = h } = l || {};
8501
+ s &&
8502
+ n.points.length &&
8503
+ (Qt(t, i),
8504
+ (function (t, e) {
8505
+ const { line: i, target: s, above: n, below: o, area: a, scale: r } = e,
8506
+ l = i._loop ? "angle" : e.axis;
8507
+ t.save(),
8508
+ "x" === l &&
8509
+ o !== n &&
8510
+ (bo(t, s, a.top),
8511
+ Mo(t, { line: i, target: s, color: n, scale: r, property: l }),
8512
+ t.restore(),
8513
+ t.save(),
8514
+ bo(t, s, a.bottom)),
8515
+ Mo(t, { line: i, target: s, color: o, scale: r, property: l }),
8516
+ t.restore();
8517
+ })(t, {
8518
+ line: n,
8519
+ target: s,
8520
+ above: c,
8521
+ below: d,
8522
+ area: i,
8523
+ scale: o,
8524
+ axis: a,
8525
+ }),
8526
+ te(t));
8527
+ }
8528
+ var So = {
8529
+ id: "filler",
8530
+ afterDatasetsUpdate(t, e, i) {
8531
+ const s = (t.data.datasets || []).length,
8532
+ n = [];
8533
+ let o, a, r, l;
8534
+ for (a = 0; a < s; ++a)
8535
+ (o = t.getDatasetMeta(a)),
8536
+ (r = o.dataset),
8537
+ (l = null),
8538
+ r &&
8539
+ r.options &&
8540
+ r instanceof qn &&
8541
+ (l = {
8542
+ visible: t.isDatasetVisible(a),
8543
+ index: a,
8544
+ fill: lo(r, a, s),
8545
+ chart: t,
8546
+ axis: o.controller.options.indexAxis,
8547
+ scale: o.vScale,
8548
+ line: r,
8549
+ }),
8550
+ (o.$filler = l),
8551
+ n.push(l);
8552
+ for (a = 0; a < s; ++a)
8553
+ (l = n[a]), l && !1 !== l.fill && (l.fill = xo(n, a, i.propagate));
8554
+ },
8555
+ beforeDraw(t, e, i) {
8556
+ const s = "beforeDraw" === i.drawTime,
8557
+ n = t.getSortedVisibleDatasetMetas(),
8558
+ o = t.chartArea;
8559
+ for (let e = n.length - 1; e >= 0; --e) {
8560
+ const i = n[e].$filler;
8561
+ i && (i.line.updateControlPoints(o, i.axis), s && ko(t.ctx, i, o));
8562
+ }
8563
+ },
8564
+ beforeDatasetsDraw(t, e, i) {
8565
+ if ("beforeDatasetsDraw" !== i.drawTime) return;
8566
+ const s = t.getSortedVisibleDatasetMetas();
8567
+ for (let e = s.length - 1; e >= 0; --e) {
8568
+ const i = s[e].$filler;
8569
+ i && ko(t.ctx, i, t.chartArea);
8570
+ }
8571
+ },
8572
+ beforeDatasetDraw(t, e, i) {
8573
+ const s = e.meta.$filler;
8574
+ s &&
8575
+ !1 !== s.fill &&
8576
+ "beforeDatasetDraw" === i.drawTime &&
8577
+ ko(t.ctx, s, t.chartArea);
8578
+ },
8579
+ defaults: { propagate: !0, drawTime: "beforeDatasetDraw" },
8580
+ };
8581
+ const Po = (t, e) => {
8582
+ let { boxHeight: i = e, boxWidth: s = e } = t;
8583
+ return (
8584
+ t.usePointStyle && ((i = Math.min(i, e)), (s = Math.min(s, e))),
8585
+ { boxWidth: s, boxHeight: i, itemHeight: Math.max(e, i) }
8586
+ );
8587
+ };
8588
+ class Do extends Ds {
8589
+ constructor(t) {
8590
+ super(),
8591
+ (this._added = !1),
8592
+ (this.legendHitBoxes = []),
8593
+ (this._hoveredItem = null),
8594
+ (this.doughnutMode = !1),
8595
+ (this.chart = t.chart),
8596
+ (this.options = t.options),
8597
+ (this.ctx = t.ctx),
8598
+ (this.legendItems = void 0),
8599
+ (this.columnSizes = void 0),
8600
+ (this.lineWidths = void 0),
8601
+ (this.maxHeight = void 0),
8602
+ (this.maxWidth = void 0),
8603
+ (this.top = void 0),
8604
+ (this.bottom = void 0),
8605
+ (this.left = void 0),
8606
+ (this.right = void 0),
8607
+ (this.height = void 0),
8608
+ (this.width = void 0),
8609
+ (this._margins = void 0),
8610
+ (this.position = void 0),
8611
+ (this.weight = void 0),
8612
+ (this.fullSize = void 0);
8613
+ }
8614
+ update(t, e, i) {
8615
+ (this.maxWidth = t),
8616
+ (this.maxHeight = e),
8617
+ (this._margins = i),
8618
+ this.setDimensions(),
8619
+ this.buildLabels(),
8620
+ this.fit();
8621
+ }
8622
+ setDimensions() {
8623
+ this.isHorizontal()
8624
+ ? ((this.width = this.maxWidth),
8625
+ (this.left = this._margins.left),
8626
+ (this.right = this.width))
8627
+ : ((this.height = this.maxHeight),
8628
+ (this.top = this._margins.top),
8629
+ (this.bottom = this.height));
8630
+ }
8631
+ buildLabels() {
8632
+ const t = this.options.labels || {};
8633
+ let e = J(t.generateLabels, [this.chart], this) || [];
8634
+ t.filter && (e = e.filter((e) => t.filter(e, this.chart.data))),
8635
+ t.sort && (e = e.sort((e, i) => t.sort(e, i, this.chart.data))),
8636
+ this.options.reverse && e.reverse(),
8637
+ (this.legendItems = e);
8638
+ }
8639
+ fit() {
8640
+ const { options: t, ctx: e } = this;
8641
+ if (!t.display) return void (this.width = this.height = 0);
8642
+ const i = t.labels,
8643
+ s = He(i.font),
8644
+ n = s.size,
8645
+ o = this._computeTitleHeight(),
8646
+ { boxWidth: a, itemHeight: r } = Po(i, n);
8647
+ let l, h;
8648
+ (e.font = s.string),
8649
+ this.isHorizontal()
8650
+ ? ((l = this.maxWidth), (h = this._fitRows(o, n, a, r) + 10))
8651
+ : ((h = this.maxHeight), (l = this._fitCols(o, n, a, r) + 10)),
8652
+ (this.width = Math.min(l, t.maxWidth || this.maxWidth)),
8653
+ (this.height = Math.min(h, t.maxHeight || this.maxHeight));
8654
+ }
8655
+ _fitRows(t, e, i, s) {
8656
+ const {
8657
+ ctx: n,
8658
+ maxWidth: o,
8659
+ options: {
8660
+ labels: { padding: a },
8661
+ },
8662
+ } = this,
8663
+ r = (this.legendHitBoxes = []),
8664
+ l = (this.lineWidths = [0]),
8665
+ h = s + a;
8666
+ let c = t;
8667
+ (n.textAlign = "left"), (n.textBaseline = "middle");
8668
+ let d = -1,
8669
+ u = -h;
8670
+ return (
8671
+ this.legendItems.forEach((t, f) => {
8672
+ const g = i + e / 2 + n.measureText(t.text).width;
8673
+ (0 === f || l[l.length - 1] + g + 2 * a > o) &&
8674
+ ((c += h), (l[l.length - (f > 0 ? 0 : 1)] = 0), (u += h), d++),
8675
+ (r[f] = { left: 0, top: u, row: d, width: g, height: s }),
8676
+ (l[l.length - 1] += g + a);
8677
+ }),
8678
+ c
8679
+ );
8680
+ }
8681
+ _fitCols(t, e, i, s) {
8682
+ const {
8683
+ ctx: n,
8684
+ maxHeight: o,
8685
+ options: {
8686
+ labels: { padding: a },
8687
+ },
8688
+ } = this,
8689
+ r = (this.legendHitBoxes = []),
8690
+ l = (this.columnSizes = []),
8691
+ h = o - t;
8692
+ let c = a,
8693
+ d = 0,
8694
+ u = 0,
8695
+ f = 0,
8696
+ g = 0;
8697
+ return (
8698
+ this.legendItems.forEach((t, o) => {
8699
+ const p = i + e / 2 + n.measureText(t.text).width;
8700
+ o > 0 &&
8701
+ u + s + 2 * a > h &&
8702
+ ((c += d + a),
8703
+ l.push({ width: d, height: u }),
8704
+ (f += d + a),
8705
+ g++,
8706
+ (d = u = 0)),
8707
+ (r[o] = { left: f, top: u, col: g, width: p, height: s }),
8708
+ (d = Math.max(d, p)),
8709
+ (u += s + a);
8710
+ }),
8711
+ (c += d),
8712
+ l.push({ width: d, height: u }),
8713
+ c
8714
+ );
8715
+ }
8716
+ adjustHitBoxes() {
8717
+ if (!this.options.display) return;
8718
+ const t = this._computeTitleHeight(),
8719
+ {
8720
+ legendHitBoxes: e,
8721
+ options: {
8722
+ align: i,
8723
+ labels: { padding: s },
8724
+ rtl: o,
8725
+ },
8726
+ } = this,
8727
+ a = Ei(o, this.left, this.width);
8728
+ if (this.isHorizontal()) {
8729
+ let o = 0,
8730
+ r = n(i, this.left + s, this.right - this.lineWidths[o]);
8731
+ for (const l of e)
8732
+ o !== l.row &&
8733
+ ((o = l.row),
8734
+ (r = n(i, this.left + s, this.right - this.lineWidths[o]))),
8735
+ (l.top += this.top + t + s),
8736
+ (l.left = a.leftForLtr(a.x(r), l.width)),
8737
+ (r += l.width + s);
8738
+ } else {
8739
+ let o = 0,
8740
+ r = n(i, this.top + t + s, this.bottom - this.columnSizes[o].height);
8741
+ for (const l of e)
8742
+ l.col !== o &&
8743
+ ((o = l.col),
8744
+ (r = n(
8745
+ i,
8746
+ this.top + t + s,
8747
+ this.bottom - this.columnSizes[o].height
8748
+ ))),
8749
+ (l.top = r),
8750
+ (l.left += this.left + s),
8751
+ (l.left = a.leftForLtr(a.x(l.left), l.width)),
8752
+ (r += l.height + s);
8753
+ }
8754
+ }
8755
+ isHorizontal() {
8756
+ return (
8757
+ "top" === this.options.position || "bottom" === this.options.position
8758
+ );
8759
+ }
8760
+ draw() {
8761
+ if (this.options.display) {
8762
+ const t = this.ctx;
8763
+ Qt(t, this), this._draw(), te(t);
8764
+ }
8765
+ }
8766
+ _draw() {
8767
+ const { options: t, columnSizes: e, lineWidths: i, ctx: s } = this,
8768
+ { align: a, labels: r } = t,
8769
+ l = bt.color,
8770
+ h = Ei(t.rtl, this.left, this.width),
8771
+ c = He(r.font),
8772
+ { color: d, padding: u } = r,
8773
+ f = c.size,
8774
+ g = f / 2;
8775
+ let p;
8776
+ this.drawTitle(),
8777
+ (s.textAlign = h.textAlign("left")),
8778
+ (s.textBaseline = "middle"),
8779
+ (s.lineWidth = 0.5),
8780
+ (s.font = c.string);
8781
+ const { boxWidth: m, boxHeight: x, itemHeight: b } = Po(r, f),
8782
+ _ = this.isHorizontal(),
8783
+ y = this._computeTitleHeight();
8784
+ (p = _
8785
+ ? {
8786
+ x: n(a, this.left + u, this.right - i[0]),
8787
+ y: this.top + u + y,
8788
+ line: 0,
8789
+ }
8790
+ : {
8791
+ x: this.left + u,
8792
+ y: n(a, this.top + y + u, this.bottom - e[0].height),
8793
+ line: 0,
8794
+ }),
8795
+ Ii(this.ctx, t.textDirection);
8796
+ const v = b + u;
8797
+ this.legendItems.forEach((w, M) => {
8798
+ (s.strokeStyle = w.fontColor || d), (s.fillStyle = w.fontColor || d);
8799
+ const k = s.measureText(w.text).width,
8800
+ S = h.textAlign(w.textAlign || (w.textAlign = r.textAlign)),
8801
+ P = m + g + k;
8802
+ let D = p.x,
8803
+ C = p.y;
8804
+ h.setWidth(this.width),
8805
+ _
8806
+ ? M > 0 &&
8807
+ D + P + u > this.right &&
8808
+ ((C = p.y += v),
8809
+ p.line++,
8810
+ (D = p.x = n(a, this.left + u, this.right - i[p.line])))
8811
+ : M > 0 &&
8812
+ C + v > this.bottom &&
8813
+ ((D = p.x = D + e[p.line].width + u),
8814
+ p.line++,
8815
+ (C = p.y =
8816
+ n(a, this.top + y + u, this.bottom - e[p.line].height)));
8817
+ !(function (t, e, i) {
8818
+ if (isNaN(m) || m <= 0 || isNaN(x) || x < 0) return;
8819
+ s.save();
8820
+ const n = K(i.lineWidth, 1);
8821
+ if (
8822
+ ((s.fillStyle = K(i.fillStyle, l)),
8823
+ (s.lineCap = K(i.lineCap, "butt")),
8824
+ (s.lineDashOffset = K(i.lineDashOffset, 0)),
8825
+ (s.lineJoin = K(i.lineJoin, "miter")),
8826
+ (s.lineWidth = n),
8827
+ (s.strokeStyle = K(i.strokeStyle, l)),
8828
+ s.setLineDash(K(i.lineDash, [])),
8829
+ r.usePointStyle)
8830
+ ) {
8831
+ const o = {
8832
+ radius: (m * Math.SQRT2) / 2,
8833
+ pointStyle: i.pointStyle,
8834
+ rotation: i.rotation,
8835
+ borderWidth: n,
8836
+ },
8837
+ a = h.xPlus(t, m / 2);
8838
+ Zt(s, o, a, e + g);
8839
+ } else {
8840
+ const o = e + Math.max((f - x) / 2, 0),
8841
+ a = h.leftForLtr(t, m),
8842
+ r = We(i.borderRadius);
8843
+ s.beginPath(),
8844
+ Object.values(r).some((t) => 0 !== t)
8845
+ ? oe(s, { x: a, y: o, w: m, h: x, radius: r })
8846
+ : s.rect(a, o, m, x),
8847
+ s.fill(),
8848
+ 0 !== n && s.stroke();
8849
+ }
8850
+ s.restore();
8851
+ })(h.x(D), C, w),
8852
+ (D = o(S, D + m + g, _ ? D + P : this.right, t.rtl)),
8853
+ (function (t, e, i) {
8854
+ se(s, i.text, t, e + b / 2, c, {
8855
+ strikethrough: i.hidden,
8856
+ textAlign: h.textAlign(i.textAlign),
8857
+ });
8858
+ })(h.x(D), C, w),
8859
+ _ ? (p.x += P + u) : (p.y += v);
8860
+ }),
8861
+ zi(this.ctx, t.textDirection);
8862
+ }
8863
+ drawTitle() {
8864
+ const t = this.options,
8865
+ e = t.title,
8866
+ i = He(e.font),
8867
+ o = Ne(e.padding);
8868
+ if (!e.display) return;
8869
+ const a = Ei(t.rtl, this.left, this.width),
8870
+ r = this.ctx,
8871
+ l = e.position,
8872
+ h = i.size / 2,
8873
+ c = o.top + h;
8874
+ let d,
8875
+ u = this.left,
8876
+ f = this.width;
8877
+ if (this.isHorizontal())
8878
+ (f = Math.max(...this.lineWidths)),
8879
+ (d = this.top + c),
8880
+ (u = n(t.align, u, this.right - f));
8881
+ else {
8882
+ const e = this.columnSizes.reduce((t, e) => Math.max(t, e.height), 0);
8883
+ d =
8884
+ c +
8885
+ n(
8886
+ t.align,
8887
+ this.top,
8888
+ this.bottom - e - t.labels.padding - this._computeTitleHeight()
8889
+ );
8890
+ }
8891
+ const g = n(l, u, u + f);
8892
+ (r.textAlign = a.textAlign(s(l))),
8893
+ (r.textBaseline = "middle"),
8894
+ (r.strokeStyle = e.color),
8895
+ (r.fillStyle = e.color),
8896
+ (r.font = i.string),
8897
+ se(r, e.text, g, d, i);
8898
+ }
8899
+ _computeTitleHeight() {
8900
+ const t = this.options.title,
8901
+ e = He(t.font),
8902
+ i = Ne(t.padding);
8903
+ return t.display ? e.lineHeight + i.height : 0;
8904
+ }
8905
+ _getLegendItemAt(t, e) {
8906
+ let i, s, n;
8907
+ if (Yt(t, this.left, this.right) && Yt(e, this.top, this.bottom))
8908
+ for (n = this.legendHitBoxes, i = 0; i < n.length; ++i)
8909
+ if (
8910
+ ((s = n[i]),
8911
+ Yt(t, s.left, s.left + s.width) && Yt(e, s.top, s.top + s.height))
8912
+ )
8913
+ return this.legendItems[i];
8914
+ return null;
8915
+ }
8916
+ handleEvent(t) {
8917
+ const e = this.options;
8918
+ if (
8919
+ !(function (t, e) {
8920
+ if ("mousemove" === t && (e.onHover || e.onLeave)) return !0;
8921
+ if (e.onClick && ("click" === t || "mouseup" === t)) return !0;
8922
+ return !1;
8923
+ })(t.type, e)
8924
+ )
8925
+ return;
8926
+ const i = this._getLegendItemAt(t.x, t.y);
8927
+ if ("mousemove" === t.type) {
8928
+ const o = this._hoveredItem,
8929
+ a =
8930
+ ((n = i),
8931
+ null !== (s = o) &&
8932
+ null !== n &&
8933
+ s.datasetIndex === n.datasetIndex &&
8934
+ s.index === n.index);
8935
+ o && !a && J(e.onLeave, [t, o, this], this),
8936
+ (this._hoveredItem = i),
8937
+ i && !a && J(e.onHover, [t, i, this], this);
8938
+ } else i && J(e.onClick, [t, i, this], this);
8939
+ var s, n;
8940
+ }
8941
+ }
8942
+ var Co = {
8943
+ id: "legend",
8944
+ _element: Do,
8945
+ start(t, e, i) {
8946
+ const s = (t.legend = new Do({ ctx: t.ctx, options: i, chart: t }));
8947
+ ni.configure(t, s, i), ni.addBox(t, s);
8948
+ },
8949
+ stop(t) {
8950
+ ni.removeBox(t, t.legend), delete t.legend;
8951
+ },
8952
+ beforeUpdate(t, e, i) {
8953
+ const s = t.legend;
8954
+ ni.configure(t, s, i), (s.options = i);
8955
+ },
8956
+ afterUpdate(t) {
8957
+ const e = t.legend;
8958
+ e.buildLabels(), e.adjustHitBoxes();
8959
+ },
8960
+ afterEvent(t, e) {
8961
+ e.replay || t.legend.handleEvent(e.event);
8962
+ },
8963
+ defaults: {
8964
+ display: !0,
8965
+ position: "top",
8966
+ align: "center",
8967
+ fullSize: !0,
8968
+ reverse: !1,
8969
+ weight: 1e3,
8970
+ onClick(t, e, i) {
8971
+ const s = e.datasetIndex,
8972
+ n = i.chart;
8973
+ n.isDatasetVisible(s)
8974
+ ? (n.hide(s), (e.hidden = !0))
8975
+ : (n.show(s), (e.hidden = !1));
8976
+ },
8977
+ onHover: null,
8978
+ onLeave: null,
8979
+ labels: {
8980
+ color: (t) => t.chart.options.color,
8981
+ boxWidth: 40,
8982
+ padding: 10,
8983
+ generateLabels(t) {
8984
+ const e = t.data.datasets,
8985
+ {
8986
+ labels: {
8987
+ usePointStyle: i,
8988
+ pointStyle: s,
8989
+ textAlign: n,
8990
+ color: o,
8991
+ },
8992
+ } = t.legend.options;
8993
+ return t._getSortedDatasetMetas().map((t) => {
8994
+ const a = t.controller.getStyle(i ? 0 : void 0),
8995
+ r = Ne(a.borderWidth);
8996
+ return {
8997
+ text: e[t.index].label,
8998
+ fillStyle: a.backgroundColor,
8999
+ fontColor: o,
9000
+ hidden: !t.visible,
9001
+ lineCap: a.borderCapStyle,
9002
+ lineDash: a.borderDash,
9003
+ lineDashOffset: a.borderDashOffset,
9004
+ lineJoin: a.borderJoinStyle,
9005
+ lineWidth: (r.width + r.height) / 4,
9006
+ strokeStyle: a.borderColor,
9007
+ pointStyle: s || a.pointStyle,
9008
+ rotation: a.rotation,
9009
+ textAlign: n || a.textAlign,
9010
+ borderRadius: 0,
9011
+ datasetIndex: t.index,
9012
+ };
9013
+ }, this);
9014
+ },
9015
+ },
9016
+ title: {
9017
+ color: (t) => t.chart.options.color,
9018
+ display: !1,
9019
+ position: "center",
9020
+ text: "",
9021
+ },
9022
+ },
9023
+ descriptors: {
9024
+ _scriptable: (t) => !t.startsWith("on"),
9025
+ labels: {
9026
+ _scriptable: (t) => !["generateLabels", "filter", "sort"].includes(t),
9027
+ },
9028
+ },
9029
+ };
9030
+ class Oo extends Ds {
9031
+ constructor(t) {
9032
+ super(),
9033
+ (this.chart = t.chart),
9034
+ (this.options = t.options),
9035
+ (this.ctx = t.ctx),
9036
+ (this._padding = void 0),
9037
+ (this.top = void 0),
9038
+ (this.bottom = void 0),
9039
+ (this.left = void 0),
9040
+ (this.right = void 0),
9041
+ (this.width = void 0),
9042
+ (this.height = void 0),
9043
+ (this.position = void 0),
9044
+ (this.weight = void 0),
9045
+ (this.fullSize = void 0);
9046
+ }
9047
+ update(t, e) {
9048
+ const i = this.options;
9049
+ if (((this.left = 0), (this.top = 0), !i.display))
9050
+ return void (this.width = this.height = this.right = this.bottom = 0);
9051
+ (this.width = this.right = t), (this.height = this.bottom = e);
9052
+ const s = Y(i.text) ? i.text.length : 1;
9053
+ this._padding = Ne(i.padding);
9054
+ const n = s * He(i.font).lineHeight + this._padding.height;
9055
+ this.isHorizontal() ? (this.height = n) : (this.width = n);
9056
+ }
9057
+ isHorizontal() {
9058
+ const t = this.options.position;
9059
+ return "top" === t || "bottom" === t;
9060
+ }
9061
+ _drawArgs(t) {
9062
+ const { top: e, left: i, bottom: s, right: o, options: a } = this,
9063
+ r = a.align;
9064
+ let l,
9065
+ h,
9066
+ c,
9067
+ d = 0;
9068
+ return (
9069
+ this.isHorizontal()
9070
+ ? ((h = n(r, i, o)), (c = e + t), (l = o - i))
9071
+ : ("left" === a.position
9072
+ ? ((h = i + t), (c = n(r, s, e)), (d = -0.5 * _t))
9073
+ : ((h = o - t), (c = n(r, e, s)), (d = 0.5 * _t)),
9074
+ (l = s - e)),
9075
+ { titleX: h, titleY: c, maxWidth: l, rotation: d }
9076
+ );
9077
+ }
9078
+ draw() {
9079
+ const t = this.ctx,
9080
+ e = this.options;
9081
+ if (!e.display) return;
9082
+ const i = He(e.font),
9083
+ n = i.lineHeight / 2 + this._padding.top,
9084
+ { titleX: o, titleY: a, maxWidth: r, rotation: l } = this._drawArgs(n);
9085
+ se(t, e.text, 0, 0, i, {
9086
+ color: e.color,
9087
+ maxWidth: r,
9088
+ rotation: l,
9089
+ textAlign: s(e.align),
9090
+ textBaseline: "middle",
9091
+ translation: [o, a],
9092
+ });
9093
+ }
9094
+ }
9095
+ var Ao = {
9096
+ id: "title",
9097
+ _element: Oo,
9098
+ start(t, e, i) {
9099
+ !(function (t, e) {
9100
+ const i = new Oo({ ctx: t.ctx, options: e, chart: t });
9101
+ ni.configure(t, i, e), ni.addBox(t, i), (t.titleBlock = i);
9102
+ })(t, i);
9103
+ },
9104
+ stop(t) {
9105
+ const e = t.titleBlock;
9106
+ ni.removeBox(t, e), delete t.titleBlock;
9107
+ },
9108
+ beforeUpdate(t, e, i) {
9109
+ const s = t.titleBlock;
9110
+ ni.configure(t, s, i), (s.options = i);
9111
+ },
9112
+ defaults: {
9113
+ align: "center",
9114
+ display: !1,
9115
+ font: { weight: "bold" },
9116
+ fullSize: !0,
9117
+ padding: 10,
9118
+ position: "top",
9119
+ text: "",
9120
+ weight: 2e3,
9121
+ },
9122
+ defaultRoutes: { color: "color" },
9123
+ descriptors: { _scriptable: !0, _indexable: !1 },
9124
+ };
9125
+ const To = new WeakMap();
9126
+ var Lo = {
9127
+ id: "subtitle",
9128
+ start(t, e, i) {
9129
+ const s = new Oo({ ctx: t.ctx, options: i, chart: t });
9130
+ ni.configure(t, s, i), ni.addBox(t, s), To.set(t, s);
9131
+ },
9132
+ stop(t) {
9133
+ ni.removeBox(t, To.get(t)), To.delete(t);
9134
+ },
9135
+ beforeUpdate(t, e, i) {
9136
+ const s = To.get(t);
9137
+ ni.configure(t, s, i), (s.options = i);
9138
+ },
9139
+ defaults: {
9140
+ align: "center",
9141
+ display: !1,
9142
+ font: { weight: "normal" },
9143
+ fullSize: !0,
9144
+ padding: 0,
9145
+ position: "top",
9146
+ text: "",
9147
+ weight: 1500,
9148
+ },
9149
+ defaultRoutes: { color: "color" },
9150
+ descriptors: { _scriptable: !0, _indexable: !1 },
9151
+ };
9152
+ const Ro = {
9153
+ average(t) {
9154
+ if (!t.length) return !1;
9155
+ let e,
9156
+ i,
9157
+ s = 0,
9158
+ n = 0,
9159
+ o = 0;
9160
+ for (e = 0, i = t.length; e < i; ++e) {
9161
+ const i = t[e].element;
9162
+ if (i && i.hasValue()) {
9163
+ const t = i.tooltipPosition();
9164
+ (s += t.x), (n += t.y), ++o;
9165
+ }
9166
+ }
9167
+ return { x: s / o, y: n / o };
9168
+ },
9169
+ nearest(t, e) {
9170
+ if (!t.length) return !1;
9171
+ let i,
9172
+ s,
9173
+ n,
9174
+ o = e.x,
9175
+ a = e.y,
9176
+ r = Number.POSITIVE_INFINITY;
9177
+ for (i = 0, s = t.length; i < s; ++i) {
9178
+ const s = t[i].element;
9179
+ if (s && s.hasValue()) {
9180
+ const t = Vt(e, s.getCenterPoint());
9181
+ t < r && ((r = t), (n = s));
9182
+ }
9183
+ }
9184
+ if (n) {
9185
+ const t = n.tooltipPosition();
9186
+ (o = t.x), (a = t.y);
9187
+ }
9188
+ return { x: o, y: a };
9189
+ },
9190
+ };
9191
+ function Eo(t, e) {
9192
+ return e && (Y(e) ? Array.prototype.push.apply(t, e) : t.push(e)), t;
9193
+ }
9194
+ function Io(t) {
9195
+ return ("string" == typeof t || t instanceof String) && t.indexOf("\n") > -1
9196
+ ? t.split("\n")
9197
+ : t;
9198
+ }
9199
+ function zo(t, e) {
9200
+ const { element: i, datasetIndex: s, index: n } = e,
9201
+ o = t.getDatasetMeta(s).controller,
9202
+ { label: a, value: r } = o.getLabelAndValue(n);
9203
+ return {
9204
+ chart: t,
9205
+ label: a,
9206
+ parsed: o.getParsed(n),
9207
+ raw: t.data.datasets[s].data[n],
9208
+ formattedValue: r,
9209
+ dataset: o.getDataset(),
9210
+ dataIndex: n,
9211
+ datasetIndex: s,
9212
+ element: i,
9213
+ };
9214
+ }
9215
+ function Fo(t, e) {
9216
+ const i = t.chart.ctx,
9217
+ { body: s, footer: n, title: o } = t,
9218
+ { boxWidth: a, boxHeight: r } = e,
9219
+ l = He(e.bodyFont),
9220
+ h = He(e.titleFont),
9221
+ c = He(e.footerFont),
9222
+ d = o.length,
9223
+ u = n.length,
9224
+ f = s.length,
9225
+ g = Ne(e.padding);
9226
+ let p = g.height,
9227
+ m = 0,
9228
+ x = s.reduce(
9229
+ (t, e) => t + e.before.length + e.lines.length + e.after.length,
9230
+ 0
9231
+ );
9232
+ if (
9233
+ ((x += t.beforeBody.length + t.afterBody.length),
9234
+ d &&
9235
+ (p +=
9236
+ d * h.lineHeight + (d - 1) * e.titleSpacing + e.titleMarginBottom),
9237
+ x)
9238
+ ) {
9239
+ p +=
9240
+ f * (e.displayColors ? Math.max(r, l.lineHeight) : l.lineHeight) +
9241
+ (x - f) * l.lineHeight +
9242
+ (x - 1) * e.bodySpacing;
9243
+ }
9244
+ u &&
9245
+ (p += e.footerMarginTop + u * c.lineHeight + (u - 1) * e.footerSpacing);
9246
+ let b = 0;
9247
+ const _ = function (t) {
9248
+ m = Math.max(m, i.measureText(t).width + b);
9249
+ };
9250
+ return (
9251
+ i.save(),
9252
+ (i.font = h.string),
9253
+ Q(t.title, _),
9254
+ (i.font = l.string),
9255
+ Q(t.beforeBody.concat(t.afterBody), _),
9256
+ (b = e.displayColors ? a + 2 + e.boxPadding : 0),
9257
+ Q(s, (t) => {
9258
+ Q(t.before, _), Q(t.lines, _), Q(t.after, _);
9259
+ }),
9260
+ (b = 0),
9261
+ (i.font = c.string),
9262
+ Q(t.footer, _),
9263
+ i.restore(),
9264
+ (m += g.width),
9265
+ { width: m, height: p }
9266
+ );
9267
+ }
9268
+ function Bo(t, e, i, s) {
9269
+ const { x: n, width: o } = i,
9270
+ {
9271
+ width: a,
9272
+ chartArea: { left: r, right: l },
9273
+ } = t;
9274
+ let h = "center";
9275
+ return (
9276
+ "center" === s
9277
+ ? (h = n <= (r + l) / 2 ? "left" : "right")
9278
+ : n <= o / 2
9279
+ ? (h = "left")
9280
+ : n >= a - o / 2 && (h = "right"),
9281
+ (function (t, e, i, s) {
9282
+ const { x: n, width: o } = s,
9283
+ a = i.caretSize + i.caretPadding;
9284
+ return (
9285
+ ("left" === t && n + o + a > e.width) ||
9286
+ ("right" === t && n - o - a < 0) ||
9287
+ void 0
9288
+ );
9289
+ })(h, t, e, i) && (h = "center"),
9290
+ h
9291
+ );
9292
+ }
9293
+ function Vo(t, e, i) {
9294
+ const s =
9295
+ i.yAlign ||
9296
+ e.yAlign ||
9297
+ (function (t, e) {
9298
+ const { y: i, height: s } = e;
9299
+ return i < s / 2 ? "top" : i > t.height - s / 2 ? "bottom" : "center";
9300
+ })(t, i);
9301
+ return { xAlign: i.xAlign || e.xAlign || Bo(t, e, i, s), yAlign: s };
9302
+ }
9303
+ function Wo(t, e, i, s) {
9304
+ const { caretSize: n, caretPadding: o, cornerRadius: a } = t,
9305
+ { xAlign: r, yAlign: l } = i,
9306
+ h = n + o,
9307
+ { topLeft: c, topRight: d, bottomLeft: u, bottomRight: f } = We(a);
9308
+ let g = (function (t, e) {
9309
+ let { x: i, width: s } = t;
9310
+ return "right" === e ? (i -= s) : "center" === e && (i -= s / 2), i;
9311
+ })(e, r);
9312
+ const p = (function (t, e, i) {
9313
+ let { y: s, height: n } = t;
9314
+ return "top" === e ? (s += i) : (s -= "bottom" === e ? n + i : n / 2), s;
9315
+ })(e, l, h);
9316
+ return (
9317
+ "center" === l
9318
+ ? "left" === r
9319
+ ? (g += h)
9320
+ : "right" === r && (g -= h)
9321
+ : "left" === r
9322
+ ? (g -= Math.max(c, u) + n)
9323
+ : "right" === r && (g += Math.max(d, f) + n),
9324
+ { x: jt(g, 0, s.width - e.width), y: jt(p, 0, s.height - e.height) }
9325
+ );
9326
+ }
9327
+ function No(t, e, i) {
9328
+ const s = Ne(i.padding);
9329
+ return "center" === e
9330
+ ? t.x + t.width / 2
9331
+ : "right" === e
9332
+ ? t.x + t.width - s.right
9333
+ : t.x + s.left;
9334
+ }
9335
+ function Ho(t) {
9336
+ return Eo([], Io(t));
9337
+ }
9338
+ function jo(t, e) {
9339
+ const i =
9340
+ e && e.dataset && e.dataset.tooltip && e.dataset.tooltip.callbacks;
9341
+ return i ? t.override(i) : t;
9342
+ }
9343
+ class $o extends Ds {
9344
+ constructor(t) {
9345
+ super(),
9346
+ (this.opacity = 0),
9347
+ (this._active = []),
9348
+ (this._eventPosition = void 0),
9349
+ (this._size = void 0),
9350
+ (this._cachedAnimations = void 0),
9351
+ (this._tooltipItems = []),
9352
+ (this.$animations = void 0),
9353
+ (this.$context = void 0),
9354
+ (this.chart = t.chart || t._chart),
9355
+ (this._chart = this.chart),
9356
+ (this.options = t.options),
9357
+ (this.dataPoints = void 0),
9358
+ (this.title = void 0),
9359
+ (this.beforeBody = void 0),
9360
+ (this.body = void 0),
9361
+ (this.afterBody = void 0),
9362
+ (this.footer = void 0),
9363
+ (this.xAlign = void 0),
9364
+ (this.yAlign = void 0),
9365
+ (this.x = void 0),
9366
+ (this.y = void 0),
9367
+ (this.height = void 0),
9368
+ (this.width = void 0),
9369
+ (this.caretX = void 0),
9370
+ (this.caretY = void 0),
9371
+ (this.labelColors = void 0),
9372
+ (this.labelPointStyles = void 0),
9373
+ (this.labelTextColors = void 0);
9374
+ }
9375
+ initialize(t) {
9376
+ (this.options = t),
9377
+ (this._cachedAnimations = void 0),
9378
+ (this.$context = void 0);
9379
+ }
9380
+ _resolveAnimations() {
9381
+ const t = this._cachedAnimations;
9382
+ if (t) return t;
9383
+ const e = this.chart,
9384
+ i = this.options.setContext(this.getContext()),
9385
+ s = i.enabled && e.options.animation && i.animations,
9386
+ n = new gs(this.chart, s);
9387
+ return s._cacheable && (this._cachedAnimations = Object.freeze(n)), n;
9388
+ }
9389
+ getContext() {
9390
+ return (
9391
+ this.$context ||
9392
+ (this.$context =
9393
+ ((t = this.chart.getContext()),
9394
+ (e = this),
9395
+ (i = this._tooltipItems),
9396
+ Ye(t, { tooltip: e, tooltipItems: i, type: "tooltip" })))
9397
+ );
9398
+ var t, e, i;
9399
+ }
9400
+ getTitle(t, e) {
9401
+ const { callbacks: i } = e,
9402
+ s = i.beforeTitle.apply(this, [t]),
9403
+ n = i.title.apply(this, [t]),
9404
+ o = i.afterTitle.apply(this, [t]);
9405
+ let a = [];
9406
+ return (a = Eo(a, Io(s))), (a = Eo(a, Io(n))), (a = Eo(a, Io(o))), a;
9407
+ }
9408
+ getBeforeBody(t, e) {
9409
+ return Ho(e.callbacks.beforeBody.apply(this, [t]));
9410
+ }
9411
+ getBody(t, e) {
9412
+ const { callbacks: i } = e,
9413
+ s = [];
9414
+ return (
9415
+ Q(t, (t) => {
9416
+ const e = { before: [], lines: [], after: [] },
9417
+ n = jo(i, t);
9418
+ Eo(e.before, Io(n.beforeLabel.call(this, t))),
9419
+ Eo(e.lines, n.label.call(this, t)),
9420
+ Eo(e.after, Io(n.afterLabel.call(this, t))),
9421
+ s.push(e);
9422
+ }),
9423
+ s
9424
+ );
9425
+ }
9426
+ getAfterBody(t, e) {
9427
+ return Ho(e.callbacks.afterBody.apply(this, [t]));
9428
+ }
9429
+ getFooter(t, e) {
9430
+ const { callbacks: i } = e,
9431
+ s = i.beforeFooter.apply(this, [t]),
9432
+ n = i.footer.apply(this, [t]),
9433
+ o = i.afterFooter.apply(this, [t]);
9434
+ let a = [];
9435
+ return (a = Eo(a, Io(s))), (a = Eo(a, Io(n))), (a = Eo(a, Io(o))), a;
9436
+ }
9437
+ _createItems(t) {
9438
+ const e = this._active,
9439
+ i = this.chart.data,
9440
+ s = [],
9441
+ n = [],
9442
+ o = [];
9443
+ let a,
9444
+ r,
9445
+ l = [];
9446
+ for (a = 0, r = e.length; a < r; ++a) l.push(zo(this.chart, e[a]));
9447
+ return (
9448
+ t.filter && (l = l.filter((e, s, n) => t.filter(e, s, n, i))),
9449
+ t.itemSort && (l = l.sort((e, s) => t.itemSort(e, s, i))),
9450
+ Q(l, (e) => {
9451
+ const i = jo(t.callbacks, e);
9452
+ s.push(i.labelColor.call(this, e)),
9453
+ n.push(i.labelPointStyle.call(this, e)),
9454
+ o.push(i.labelTextColor.call(this, e));
9455
+ }),
9456
+ (this.labelColors = s),
9457
+ (this.labelPointStyles = n),
9458
+ (this.labelTextColors = o),
9459
+ (this.dataPoints = l),
9460
+ l
9461
+ );
9462
+ }
9463
+ update(t, e) {
9464
+ const i = this.options.setContext(this.getContext()),
9465
+ s = this._active;
9466
+ let n,
9467
+ o = [];
9468
+ if (s.length) {
9469
+ const t = Ro[i.position].call(this, s, this._eventPosition);
9470
+ (o = this._createItems(i)),
9471
+ (this.title = this.getTitle(o, i)),
9472
+ (this.beforeBody = this.getBeforeBody(o, i)),
9473
+ (this.body = this.getBody(o, i)),
9474
+ (this.afterBody = this.getAfterBody(o, i)),
9475
+ (this.footer = this.getFooter(o, i));
9476
+ const e = (this._size = Fo(this, i)),
9477
+ a = Object.assign({}, t, e),
9478
+ r = Vo(this.chart, i, a),
9479
+ l = Wo(i, a, r, this.chart);
9480
+ (this.xAlign = r.xAlign),
9481
+ (this.yAlign = r.yAlign),
9482
+ (n = {
9483
+ opacity: 1,
9484
+ x: l.x,
9485
+ y: l.y,
9486
+ width: e.width,
9487
+ height: e.height,
9488
+ caretX: t.x,
9489
+ caretY: t.y,
9490
+ });
9491
+ } else 0 !== this.opacity && (n = { opacity: 0 });
9492
+ (this._tooltipItems = o),
9493
+ (this.$context = void 0),
9494
+ n && this._resolveAnimations().update(this, n),
9495
+ t &&
9496
+ i.external &&
9497
+ i.external.call(this, {
9498
+ chart: this.chart,
9499
+ tooltip: this,
9500
+ replay: e,
9501
+ });
9502
+ }
9503
+ drawCaret(t, e, i, s) {
9504
+ const n = this.getCaretPosition(t, i, s);
9505
+ e.lineTo(n.x1, n.y1), e.lineTo(n.x2, n.y2), e.lineTo(n.x3, n.y3);
9506
+ }
9507
+ getCaretPosition(t, e, i) {
9508
+ const { xAlign: s, yAlign: n } = this,
9509
+ { caretSize: o, cornerRadius: a } = i,
9510
+ { topLeft: r, topRight: l, bottomLeft: h, bottomRight: c } = We(a),
9511
+ { x: d, y: u } = t,
9512
+ { width: f, height: g } = e;
9513
+ let p, m, x, b, _, y;
9514
+ return (
9515
+ "center" === n
9516
+ ? ((_ = u + g / 2),
9517
+ "left" === s
9518
+ ? ((p = d), (m = p - o), (b = _ + o), (y = _ - o))
9519
+ : ((p = d + f), (m = p + o), (b = _ - o), (y = _ + o)),
9520
+ (x = p))
9521
+ : ((m =
9522
+ "left" === s
9523
+ ? d + Math.max(r, h) + o
9524
+ : "right" === s
9525
+ ? d + f - Math.max(l, c) - o
9526
+ : this.caretX),
9527
+ "top" === n
9528
+ ? ((b = u), (_ = b - o), (p = m - o), (x = m + o))
9529
+ : ((b = u + g), (_ = b + o), (p = m + o), (x = m - o)),
9530
+ (y = b)),
9531
+ { x1: p, x2: m, x3: x, y1: b, y2: _, y3: y }
9532
+ );
9533
+ }
9534
+ drawTitle(t, e, i) {
9535
+ const s = this.title,
9536
+ n = s.length;
9537
+ let o, a, r;
9538
+ if (n) {
9539
+ const l = Ei(i.rtl, this.x, this.width);
9540
+ for (
9541
+ t.x = No(this, i.titleAlign, i),
9542
+ e.textAlign = l.textAlign(i.titleAlign),
9543
+ e.textBaseline = "middle",
9544
+ o = He(i.titleFont),
9545
+ a = i.titleSpacing,
9546
+ e.fillStyle = i.titleColor,
9547
+ e.font = o.string,
9548
+ r = 0;
9549
+ r < n;
9550
+ ++r
9551
+ )
9552
+ e.fillText(s[r], l.x(t.x), t.y + o.lineHeight / 2),
9553
+ (t.y += o.lineHeight + a),
9554
+ r + 1 === n && (t.y += i.titleMarginBottom - a);
9555
+ }
9556
+ }
9557
+ _drawColorBox(t, e, i, s, n) {
9558
+ const o = this.labelColors[i],
9559
+ a = this.labelPointStyles[i],
9560
+ { boxHeight: r, boxWidth: l, boxPadding: h } = n,
9561
+ c = He(n.bodyFont),
9562
+ d = No(this, "left", n),
9563
+ u = s.x(d),
9564
+ f = r < c.lineHeight ? (c.lineHeight - r) / 2 : 0,
9565
+ g = e.y + f;
9566
+ if (n.usePointStyle) {
9567
+ const e = {
9568
+ radius: Math.min(l, r) / 2,
9569
+ pointStyle: a.pointStyle,
9570
+ rotation: a.rotation,
9571
+ borderWidth: 1,
9572
+ },
9573
+ i = s.leftForLtr(u, l) + l / 2,
9574
+ h = g + r / 2;
9575
+ (t.strokeStyle = n.multiKeyBackground),
9576
+ (t.fillStyle = n.multiKeyBackground),
9577
+ Zt(t, e, i, h),
9578
+ (t.strokeStyle = o.borderColor),
9579
+ (t.fillStyle = o.backgroundColor),
9580
+ Zt(t, e, i, h);
9581
+ } else {
9582
+ (t.lineWidth = o.borderWidth || 1),
9583
+ (t.strokeStyle = o.borderColor),
9584
+ t.setLineDash(o.borderDash || []),
9585
+ (t.lineDashOffset = o.borderDashOffset || 0);
9586
+ const e = s.leftForLtr(u, l - h),
9587
+ i = s.leftForLtr(s.xPlus(u, 1), l - h - 2),
9588
+ a = We(o.borderRadius);
9589
+ Object.values(a).some((t) => 0 !== t)
9590
+ ? (t.beginPath(),
9591
+ (t.fillStyle = n.multiKeyBackground),
9592
+ oe(t, { x: e, y: g, w: l, h: r, radius: a }),
9593
+ t.fill(),
9594
+ t.stroke(),
9595
+ (t.fillStyle = o.backgroundColor),
9596
+ t.beginPath(),
9597
+ oe(t, { x: i, y: g + 1, w: l - 2, h: r - 2, radius: a }),
9598
+ t.fill())
9599
+ : ((t.fillStyle = n.multiKeyBackground),
9600
+ t.fillRect(e, g, l, r),
9601
+ t.strokeRect(e, g, l, r),
9602
+ (t.fillStyle = o.backgroundColor),
9603
+ t.fillRect(i, g + 1, l - 2, r - 2));
9604
+ }
9605
+ t.fillStyle = this.labelTextColors[i];
9606
+ }
9607
+ drawBody(t, e, i) {
9608
+ const { body: s } = this,
9609
+ {
9610
+ bodySpacing: n,
9611
+ bodyAlign: o,
9612
+ displayColors: a,
9613
+ boxHeight: r,
9614
+ boxWidth: l,
9615
+ boxPadding: h,
9616
+ } = i,
9617
+ c = He(i.bodyFont);
9618
+ let d = c.lineHeight,
9619
+ u = 0;
9620
+ const f = Ei(i.rtl, this.x, this.width),
9621
+ g = function (i) {
9622
+ e.fillText(i, f.x(t.x + u), t.y + d / 2), (t.y += d + n);
9623
+ },
9624
+ p = f.textAlign(o);
9625
+ let m, x, b, _, y, v, w;
9626
+ for (
9627
+ e.textAlign = o,
9628
+ e.textBaseline = "middle",
9629
+ e.font = c.string,
9630
+ t.x = No(this, p, i),
9631
+ e.fillStyle = i.bodyColor,
9632
+ Q(this.beforeBody, g),
9633
+ u = a && "right" !== p ? ("center" === o ? l / 2 + h : l + 2 + h) : 0,
9634
+ _ = 0,
9635
+ v = s.length;
9636
+ _ < v;
9637
+ ++_
9638
+ ) {
9639
+ for (
9640
+ m = s[_],
9641
+ x = this.labelTextColors[_],
9642
+ e.fillStyle = x,
9643
+ Q(m.before, g),
9644
+ b = m.lines,
9645
+ a &&
9646
+ b.length &&
9647
+ (this._drawColorBox(e, t, _, f, i),
9648
+ (d = Math.max(c.lineHeight, r))),
9649
+ y = 0,
9650
+ w = b.length;
9651
+ y < w;
9652
+ ++y
9653
+ )
9654
+ g(b[y]), (d = c.lineHeight);
9655
+ Q(m.after, g);
9656
+ }
9657
+ (u = 0), (d = c.lineHeight), Q(this.afterBody, g), (t.y -= n);
9658
+ }
9659
+ drawFooter(t, e, i) {
9660
+ const s = this.footer,
9661
+ n = s.length;
9662
+ let o, a;
9663
+ if (n) {
9664
+ const r = Ei(i.rtl, this.x, this.width);
9665
+ for (
9666
+ t.x = No(this, i.footerAlign, i),
9667
+ t.y += i.footerMarginTop,
9668
+ e.textAlign = r.textAlign(i.footerAlign),
9669
+ e.textBaseline = "middle",
9670
+ o = He(i.footerFont),
9671
+ e.fillStyle = i.footerColor,
9672
+ e.font = o.string,
9673
+ a = 0;
9674
+ a < n;
9675
+ ++a
9676
+ )
9677
+ e.fillText(s[a], r.x(t.x), t.y + o.lineHeight / 2),
9678
+ (t.y += o.lineHeight + i.footerSpacing);
9679
+ }
9680
+ }
9681
+ drawBackground(t, e, i, s) {
9682
+ const { xAlign: n, yAlign: o } = this,
9683
+ { x: a, y: r } = t,
9684
+ { width: l, height: h } = i,
9685
+ {
9686
+ topLeft: c,
9687
+ topRight: d,
9688
+ bottomLeft: u,
9689
+ bottomRight: f,
9690
+ } = We(s.cornerRadius);
9691
+ (e.fillStyle = s.backgroundColor),
9692
+ (e.strokeStyle = s.borderColor),
9693
+ (e.lineWidth = s.borderWidth),
9694
+ e.beginPath(),
9695
+ e.moveTo(a + c, r),
9696
+ "top" === o && this.drawCaret(t, e, i, s),
9697
+ e.lineTo(a + l - d, r),
9698
+ e.quadraticCurveTo(a + l, r, a + l, r + d),
9699
+ "center" === o && "right" === n && this.drawCaret(t, e, i, s),
9700
+ e.lineTo(a + l, r + h - f),
9701
+ e.quadraticCurveTo(a + l, r + h, a + l - f, r + h),
9702
+ "bottom" === o && this.drawCaret(t, e, i, s),
9703
+ e.lineTo(a + u, r + h),
9704
+ e.quadraticCurveTo(a, r + h, a, r + h - u),
9705
+ "center" === o && "left" === n && this.drawCaret(t, e, i, s),
9706
+ e.lineTo(a, r + c),
9707
+ e.quadraticCurveTo(a, r, a + c, r),
9708
+ e.closePath(),
9709
+ e.fill(),
9710
+ s.borderWidth > 0 && e.stroke();
9711
+ }
9712
+ _updateAnimationTarget(t) {
9713
+ const e = this.chart,
9714
+ i = this.$animations,
9715
+ s = i && i.x,
9716
+ n = i && i.y;
9717
+ if (s || n) {
9718
+ const i = Ro[t.position].call(this, this._active, this._eventPosition);
9719
+ if (!i) return;
9720
+ const o = (this._size = Fo(this, t)),
9721
+ a = Object.assign({}, i, this._size),
9722
+ r = Vo(e, t, a),
9723
+ l = Wo(t, a, r, e);
9724
+ (s._to === l.x && n._to === l.y) ||
9725
+ ((this.xAlign = r.xAlign),
9726
+ (this.yAlign = r.yAlign),
9727
+ (this.width = o.width),
9728
+ (this.height = o.height),
9729
+ (this.caretX = i.x),
9730
+ (this.caretY = i.y),
9731
+ this._resolveAnimations().update(this, l));
9732
+ }
9733
+ }
9734
+ draw(t) {
9735
+ const e = this.options.setContext(this.getContext());
9736
+ let i = this.opacity;
9737
+ if (!i) return;
9738
+ this._updateAnimationTarget(e);
9739
+ const s = { width: this.width, height: this.height },
9740
+ n = { x: this.x, y: this.y };
9741
+ i = Math.abs(i) < 0.001 ? 0 : i;
9742
+ const o = Ne(e.padding),
9743
+ a =
9744
+ this.title.length ||
9745
+ this.beforeBody.length ||
9746
+ this.body.length ||
9747
+ this.afterBody.length ||
9748
+ this.footer.length;
9749
+ e.enabled &&
9750
+ a &&
9751
+ (t.save(),
9752
+ (t.globalAlpha = i),
9753
+ this.drawBackground(n, t, s, e),
9754
+ Ii(t, e.textDirection),
9755
+ (n.y += o.top),
9756
+ this.drawTitle(n, t, e),
9757
+ this.drawBody(n, t, e),
9758
+ this.drawFooter(n, t, e),
9759
+ zi(t, e.textDirection),
9760
+ t.restore());
9761
+ }
9762
+ getActiveElements() {
9763
+ return this._active || [];
9764
+ }
9765
+ setActiveElements(t, e) {
9766
+ const i = this._active,
9767
+ s = t.map(({ datasetIndex: t, index: e }) => {
9768
+ const i = this.chart.getDatasetMeta(t);
9769
+ if (!i) throw new Error("Cannot find a dataset at index " + t);
9770
+ return { datasetIndex: t, element: i.data[e], index: e };
9771
+ }),
9772
+ n = !tt(i, s),
9773
+ o = this._positionChanged(s, e);
9774
+ (n || o) &&
9775
+ ((this._active = s),
9776
+ (this._eventPosition = e),
9777
+ (this._ignoreReplayEvents = !0),
9778
+ this.update(!0));
9779
+ }
9780
+ handleEvent(t, e, i = !0) {
9781
+ if (e && this._ignoreReplayEvents) return !1;
9782
+ this._ignoreReplayEvents = !1;
9783
+ const s = this.options,
9784
+ n = this._active || [],
9785
+ o = this._getActiveElements(t, n, e, i),
9786
+ a = this._positionChanged(o, t),
9787
+ r = e || !tt(o, n) || a;
9788
+ return (
9789
+ r &&
9790
+ ((this._active = o),
9791
+ (s.enabled || s.external) &&
9792
+ ((this._eventPosition = { x: t.x, y: t.y }), this.update(!0, e))),
9793
+ r
9794
+ );
9795
+ }
9796
+ _getActiveElements(t, e, i, s) {
9797
+ const n = this.options;
9798
+ if ("mouseout" === t.type) return [];
9799
+ if (!s) return e;
9800
+ const o = this.chart.getElementsAtEventForMode(t, n.mode, n, i);
9801
+ return n.reverse && o.reverse(), o;
9802
+ }
9803
+ _positionChanged(t, e) {
9804
+ const { caretX: i, caretY: s, options: n } = this,
9805
+ o = Ro[n.position].call(this, t, e);
9806
+ return !1 !== o && (i !== o.x || s !== o.y);
9807
+ }
9808
+ }
9809
+ $o.positioners = Ro;
9810
+ var Yo = {
9811
+ id: "tooltip",
9812
+ _element: $o,
9813
+ positioners: Ro,
9814
+ afterInit(t, e, i) {
9815
+ i && (t.tooltip = new $o({ chart: t, options: i }));
9816
+ },
9817
+ beforeUpdate(t, e, i) {
9818
+ t.tooltip && t.tooltip.initialize(i);
9819
+ },
9820
+ reset(t, e, i) {
9821
+ t.tooltip && t.tooltip.initialize(i);
9822
+ },
9823
+ afterDraw(t) {
9824
+ const e = t.tooltip,
9825
+ i = { tooltip: e };
9826
+ !1 !== t.notifyPlugins("beforeTooltipDraw", i) &&
9827
+ (e && e.draw(t.ctx), t.notifyPlugins("afterTooltipDraw", i));
9828
+ },
9829
+ afterEvent(t, e) {
9830
+ if (t.tooltip) {
9831
+ const i = e.replay;
9832
+ t.tooltip.handleEvent(e.event, i, e.inChartArea) && (e.changed = !0);
9833
+ }
9834
+ },
9835
+ defaults: {
9836
+ enabled: !0,
9837
+ external: null,
9838
+ position: "average",
9839
+ backgroundColor: "rgba(0,0,0,0.8)",
9840
+ titleColor: "#fff",
9841
+ titleFont: { weight: "bold" },
9842
+ titleSpacing: 2,
9843
+ titleMarginBottom: 6,
9844
+ titleAlign: "left",
9845
+ bodyColor: "#fff",
9846
+ bodySpacing: 2,
9847
+ bodyFont: {},
9848
+ bodyAlign: "left",
9849
+ footerColor: "#fff",
9850
+ footerSpacing: 2,
9851
+ footerMarginTop: 6,
9852
+ footerFont: { weight: "bold" },
9853
+ footerAlign: "left",
9854
+ padding: 6,
9855
+ caretPadding: 2,
9856
+ caretSize: 5,
9857
+ cornerRadius: 6,
9858
+ boxHeight: (t, e) => e.bodyFont.size,
9859
+ boxWidth: (t, e) => e.bodyFont.size,
9860
+ multiKeyBackground: "#fff",
9861
+ displayColors: !0,
9862
+ boxPadding: 0,
9863
+ borderColor: "rgba(0,0,0,0)",
9864
+ borderWidth: 0,
9865
+ animation: { duration: 400, easing: "easeOutQuart" },
9866
+ animations: {
9867
+ numbers: {
9868
+ type: "number",
9869
+ properties: ["x", "y", "width", "height", "caretX", "caretY"],
9870
+ },
9871
+ opacity: { easing: "linear", duration: 200 },
9872
+ },
9873
+ callbacks: {
9874
+ beforeTitle: H,
9875
+ title(t) {
9876
+ if (t.length > 0) {
9877
+ const e = t[0],
9878
+ i = e.chart.data.labels,
9879
+ s = i ? i.length : 0;
9880
+ if (this && this.options && "dataset" === this.options.mode)
9881
+ return e.dataset.label || "";
9882
+ if (e.label) return e.label;
9883
+ if (s > 0 && e.dataIndex < s) return i[e.dataIndex];
9884
+ }
9885
+ return "";
9886
+ },
9887
+ afterTitle: H,
9888
+ beforeBody: H,
9889
+ beforeLabel: H,
9890
+ label(t) {
9891
+ if (this && this.options && "dataset" === this.options.mode)
9892
+ return t.label + ": " + t.formattedValue || t.formattedValue;
9893
+ let e = t.dataset.label || "";
9894
+ e && (e += ": ");
9895
+ const i = t.formattedValue;
9896
+ return $(i) || (e += i), e;
9897
+ },
9898
+ labelColor(t) {
9899
+ const e = t.chart
9900
+ .getDatasetMeta(t.datasetIndex)
9901
+ .controller.getStyle(t.dataIndex);
9902
+ return {
9903
+ borderColor: e.borderColor,
9904
+ backgroundColor: e.backgroundColor,
9905
+ borderWidth: e.borderWidth,
9906
+ borderDash: e.borderDash,
9907
+ borderDashOffset: e.borderDashOffset,
9908
+ borderRadius: 0,
9909
+ };
9910
+ },
9911
+ labelTextColor() {
9912
+ return this.options.bodyColor;
9913
+ },
9914
+ labelPointStyle(t) {
9915
+ const e = t.chart
9916
+ .getDatasetMeta(t.datasetIndex)
9917
+ .controller.getStyle(t.dataIndex);
9918
+ return { pointStyle: e.pointStyle, rotation: e.rotation };
9919
+ },
9920
+ afterLabel: H,
9921
+ afterBody: H,
9922
+ beforeFooter: H,
9923
+ footer: H,
9924
+ afterFooter: H,
9925
+ },
9926
+ },
9927
+ defaultRoutes: {
9928
+ bodyFont: "font",
9929
+ footerFont: "font",
9930
+ titleFont: "font",
9931
+ },
9932
+ descriptors: {
9933
+ _scriptable: (t) =>
9934
+ "filter" !== t && "itemSort" !== t && "external" !== t,
9935
+ _indexable: !1,
9936
+ callbacks: { _scriptable: !1, _indexable: !1 },
9937
+ animation: { _fallback: !1 },
9938
+ animations: { _fallback: "animation" },
9939
+ },
9940
+ additionalOptionScopes: ["interaction"],
9941
+ },
9942
+ Uo = Object.freeze({
9943
+ __proto__: null,
9944
+ Decimation: ro,
9945
+ Filler: So,
9946
+ Legend: Co,
9947
+ SubTitle: Lo,
9948
+ Title: Ao,
9949
+ Tooltip: Yo,
9950
+ });
9951
+ function Xo(t, e, i, s) {
9952
+ const n = t.indexOf(e);
9953
+ if (-1 === n)
9954
+ return ((t, e, i, s) => (
9955
+ "string" == typeof e
9956
+ ? ((i = t.push(e) - 1), s.unshift({ index: i, label: e }))
9957
+ : isNaN(e) && (i = null),
9958
+ i
9959
+ ))(t, e, i, s);
9960
+ return n !== t.lastIndexOf(e) ? i : n;
9961
+ }
9962
+ class qo extends Bs {
9963
+ constructor(t) {
9964
+ super(t),
9965
+ (this._startValue = void 0),
9966
+ (this._valueRange = 0),
9967
+ (this._addedLabels = []);
9968
+ }
9969
+ init(t) {
9970
+ const e = this._addedLabels;
9971
+ if (e.length) {
9972
+ const t = this.getLabels();
9973
+ for (const { index: i, label: s } of e) t[i] === s && t.splice(i, 1);
9974
+ this._addedLabels = [];
9975
+ }
9976
+ super.init(t);
9977
+ }
9978
+ parse(t, e) {
9979
+ if ($(t)) return null;
9980
+ const i = this.getLabels();
9981
+ return ((t, e) =>
9982
+ null === t
9983
+ ? null
9984
+ : jt(
9985
+ Math.round(t),
9986
+ 0,
9987
+ e
9988
+ ))((e = isFinite(e) && i[e] === t ? e : Xo(i, t, K(e, t), this._addedLabels)), i.length - 1);
9989
+ }
9990
+ determineDataLimits() {
9991
+ const { minDefined: t, maxDefined: e } = this.getUserBounds();
9992
+ let { min: i, max: s } = this.getMinMax(!0);
9993
+ "ticks" === this.options.bounds &&
9994
+ (t || (i = 0), e || (s = this.getLabels().length - 1)),
9995
+ (this.min = i),
9996
+ (this.max = s);
9997
+ }
9998
+ buildTicks() {
9999
+ const t = this.min,
10000
+ e = this.max,
10001
+ i = this.options.offset,
10002
+ s = [];
10003
+ let n = this.getLabels();
10004
+ (n = 0 === t && e === n.length - 1 ? n : n.slice(t, e + 1)),
10005
+ (this._valueRange = Math.max(n.length - (i ? 0 : 1), 1)),
10006
+ (this._startValue = this.min - (i ? 0.5 : 0));
10007
+ for (let i = t; i <= e; i++) s.push({ value: i });
10008
+ return s;
10009
+ }
10010
+ getLabelForValue(t) {
10011
+ const e = this.getLabels();
10012
+ return t >= 0 && t < e.length ? e[t] : t;
10013
+ }
10014
+ configure() {
10015
+ super.configure(),
10016
+ this.isHorizontal() || (this._reversePixels = !this._reversePixels);
10017
+ }
10018
+ getPixelForValue(t) {
10019
+ return (
10020
+ "number" != typeof t && (t = this.parse(t)),
10021
+ null === t
10022
+ ? NaN
10023
+ : this.getPixelForDecimal((t - this._startValue) / this._valueRange)
10024
+ );
10025
+ }
10026
+ getPixelForTick(t) {
10027
+ const e = this.ticks;
10028
+ return t < 0 || t > e.length - 1
10029
+ ? null
10030
+ : this.getPixelForValue(e[t].value);
10031
+ }
10032
+ getValueForPixel(t) {
10033
+ return Math.round(
10034
+ this._startValue + this.getDecimalForPixel(t) * this._valueRange
10035
+ );
10036
+ }
10037
+ getBasePixel() {
10038
+ return this.bottom;
10039
+ }
10040
+ }
10041
+ function Ko(t, e, { horizontal: i, minRotation: s }) {
10042
+ const n = It(s),
10043
+ o = (i ? Math.sin(n) : Math.cos(n)) || 0.001,
10044
+ a = 0.75 * e * ("" + t).length;
10045
+ return Math.min(e / o, a);
10046
+ }
10047
+ (qo.id = "category"),
10048
+ (qo.defaults = { ticks: { callback: qo.prototype.getLabelForValue } });
10049
+ class Go extends Bs {
10050
+ constructor(t) {
10051
+ super(t),
10052
+ (this.start = void 0),
10053
+ (this.end = void 0),
10054
+ (this._startValue = void 0),
10055
+ (this._endValue = void 0),
10056
+ (this._valueRange = 0);
10057
+ }
10058
+ parse(t, e) {
10059
+ return $(t) ||
10060
+ (("number" == typeof t || t instanceof Number) && !isFinite(+t))
10061
+ ? null
10062
+ : +t;
10063
+ }
10064
+ handleTickRangeOptions() {
10065
+ const { beginAtZero: t } = this.options,
10066
+ { minDefined: e, maxDefined: i } = this.getUserBounds();
10067
+ let { min: s, max: n } = this;
10068
+ const o = (t) => (s = e ? s : t),
10069
+ a = (t) => (n = i ? n : t);
10070
+ if (t) {
10071
+ const t = Ct(s),
10072
+ e = Ct(n);
10073
+ t < 0 && e < 0 ? a(0) : t > 0 && e > 0 && o(0);
10074
+ }
10075
+ if (s === n) {
10076
+ let e = 1;
10077
+ (n >= Number.MAX_SAFE_INTEGER || s <= Number.MIN_SAFE_INTEGER) &&
10078
+ (e = Math.abs(0.05 * n)),
10079
+ a(n + e),
10080
+ t || o(s - e);
10081
+ }
10082
+ (this.min = s), (this.max = n);
10083
+ }
10084
+ getTickLimit() {
10085
+ const t = this.options.ticks;
10086
+ let e,
10087
+ { maxTicksLimit: i, stepSize: s } = t;
10088
+ return (
10089
+ s
10090
+ ? ((e = Math.ceil(this.max / s) - Math.floor(this.min / s) + 1),
10091
+ e > 1e3 &&
10092
+ (console.warn(
10093
+ `scales.${this.id}.ticks.stepSize: ${s} would result generating up to ${e} ticks. Limiting to 1000.`
10094
+ ),
10095
+ (e = 1e3)))
10096
+ : ((e = this.computeTickLimit()), (i = i || 11)),
10097
+ i && (e = Math.min(i, e)),
10098
+ e
10099
+ );
10100
+ }
10101
+ computeTickLimit() {
10102
+ return Number.POSITIVE_INFINITY;
10103
+ }
10104
+ buildTicks() {
10105
+ const t = this.options,
10106
+ e = t.ticks;
10107
+ let i = this.getTickLimit();
10108
+ i = Math.max(2, i);
10109
+ const s = (function (t, e) {
10110
+ const i = [],
10111
+ {
10112
+ bounds: s,
10113
+ step: n,
10114
+ min: o,
10115
+ max: a,
10116
+ precision: r,
10117
+ count: l,
10118
+ maxTicks: h,
10119
+ maxDigits: c,
10120
+ includeBounds: d,
10121
+ } = t,
10122
+ u = n || 1,
10123
+ f = h - 1,
10124
+ { min: g, max: p } = e,
10125
+ m = !$(o),
10126
+ x = !$(a),
10127
+ b = !$(l),
10128
+ _ = (p - g) / (c + 1);
10129
+ let y,
10130
+ v,
10131
+ w,
10132
+ M,
10133
+ k = Ot((p - g) / f / u) * u;
10134
+ if (k < 1e-14 && !m && !x) return [{ value: g }, { value: p }];
10135
+ (M = Math.ceil(p / k) - Math.floor(g / k)),
10136
+ M > f && (k = Ot((M * k) / f / u) * u),
10137
+ $(r) || ((y = Math.pow(10, r)), (k = Math.ceil(k * y) / y)),
10138
+ "ticks" === s
10139
+ ? ((v = Math.floor(g / k) * k), (w = Math.ceil(p / k) * k))
10140
+ : ((v = g), (w = p)),
10141
+ m && x && n && Rt((a - o) / n, k / 1e3)
10142
+ ? ((M = Math.round(Math.min((a - o) / k, h))),
10143
+ (k = (a - o) / M),
10144
+ (v = o),
10145
+ (w = a))
10146
+ : b
10147
+ ? ((v = m ? o : v), (w = x ? a : w), (M = l - 1), (k = (w - v) / M))
10148
+ : ((M = (w - v) / k),
10149
+ (M = Lt(M, Math.round(M), k / 1e3)
10150
+ ? Math.round(M)
10151
+ : Math.ceil(M)));
10152
+ const S = Math.max(Ft(k), Ft(v));
10153
+ (y = Math.pow(10, $(r) ? S : r)),
10154
+ (v = Math.round(v * y) / y),
10155
+ (w = Math.round(w * y) / y);
10156
+ let P = 0;
10157
+ for (
10158
+ m &&
10159
+ (d && v !== o
10160
+ ? (i.push({ value: o }),
10161
+ v < o && P++,
10162
+ Lt(Math.round((v + P * k) * y) / y, o, Ko(o, _, t)) && P++)
10163
+ : v < o && P++);
10164
+ P < M;
10165
+ ++P
10166
+ )
10167
+ i.push({ value: Math.round((v + P * k) * y) / y });
10168
+ return (
10169
+ x && d && w !== a
10170
+ ? i.length && Lt(i[i.length - 1].value, a, Ko(a, _, t))
10171
+ ? (i[i.length - 1].value = a)
10172
+ : i.push({ value: a })
10173
+ : (x && w !== a) || i.push({ value: w }),
10174
+ i
10175
+ );
10176
+ })(
10177
+ {
10178
+ maxTicks: i,
10179
+ bounds: t.bounds,
10180
+ min: t.min,
10181
+ max: t.max,
10182
+ precision: e.precision,
10183
+ step: e.stepSize,
10184
+ count: e.count,
10185
+ maxDigits: this._maxDigits(),
10186
+ horizontal: this.isHorizontal(),
10187
+ minRotation: e.minRotation || 0,
10188
+ includeBounds: !1 !== e.includeBounds,
10189
+ },
10190
+ this._range || this
10191
+ );
10192
+ return (
10193
+ "ticks" === t.bounds && Et(s, this, "value"),
10194
+ t.reverse
10195
+ ? (s.reverse(), (this.start = this.max), (this.end = this.min))
10196
+ : ((this.start = this.min), (this.end = this.max)),
10197
+ s
10198
+ );
10199
+ }
10200
+ configure() {
10201
+ const t = this.ticks;
10202
+ let e = this.min,
10203
+ i = this.max;
10204
+ if ((super.configure(), this.options.offset && t.length)) {
10205
+ const s = (i - e) / Math.max(t.length - 1, 1) / 2;
10206
+ (e -= s), (i += s);
10207
+ }
10208
+ (this._startValue = e), (this._endValue = i), (this._valueRange = i - e);
10209
+ }
10210
+ getLabelForValue(t) {
10211
+ return Ri(t, this.chart.options.locale, this.options.ticks.format);
10212
+ }
10213
+ }
10214
+ class Zo extends Go {
10215
+ determineDataLimits() {
10216
+ const { min: t, max: e } = this.getMinMax(!0);
10217
+ (this.min = X(t) ? t : 0),
10218
+ (this.max = X(e) ? e : 1),
10219
+ this.handleTickRangeOptions();
10220
+ }
10221
+ computeTickLimit() {
10222
+ const t = this.isHorizontal(),
10223
+ e = t ? this.width : this.height,
10224
+ i = It(this.options.ticks.minRotation),
10225
+ s = (t ? Math.sin(i) : Math.cos(i)) || 0.001,
10226
+ n = this._resolveTickFontOptions(0);
10227
+ return Math.ceil(e / Math.min(40, n.lineHeight / s));
10228
+ }
10229
+ getPixelForValue(t) {
10230
+ return null === t
10231
+ ? NaN
10232
+ : this.getPixelForDecimal((t - this._startValue) / this._valueRange);
10233
+ }
10234
+ getValueForPixel(t) {
10235
+ return this._startValue + this.getDecimalForPixel(t) * this._valueRange;
10236
+ }
10237
+ }
10238
+ function Jo(t) {
10239
+ return 1 === t / Math.pow(10, Math.floor(Dt(t)));
10240
+ }
10241
+ (Zo.id = "linear"),
10242
+ (Zo.defaults = { ticks: { callback: Os.formatters.numeric } });
10243
+ class Qo extends Bs {
10244
+ constructor(t) {
10245
+ super(t),
10246
+ (this.start = void 0),
10247
+ (this.end = void 0),
10248
+ (this._startValue = void 0),
10249
+ (this._valueRange = 0);
10250
+ }
10251
+ parse(t, e) {
10252
+ const i = Go.prototype.parse.apply(this, [t, e]);
10253
+ if (0 !== i) return X(i) && i > 0 ? i : null;
10254
+ this._zero = !0;
10255
+ }
10256
+ determineDataLimits() {
10257
+ const { min: t, max: e } = this.getMinMax(!0);
10258
+ (this.min = X(t) ? Math.max(0, t) : null),
10259
+ (this.max = X(e) ? Math.max(0, e) : null),
10260
+ this.options.beginAtZero && (this._zero = !0),
10261
+ this.handleTickRangeOptions();
10262
+ }
10263
+ handleTickRangeOptions() {
10264
+ const { minDefined: t, maxDefined: e } = this.getUserBounds();
10265
+ let i = this.min,
10266
+ s = this.max;
10267
+ const n = (e) => (i = t ? i : e),
10268
+ o = (t) => (s = e ? s : t),
10269
+ a = (t, e) => Math.pow(10, Math.floor(Dt(t)) + e);
10270
+ i === s && (i <= 0 ? (n(1), o(10)) : (n(a(i, -1)), o(a(s, 1)))),
10271
+ i <= 0 && n(a(s, -1)),
10272
+ s <= 0 && o(a(i, 1)),
10273
+ this._zero &&
10274
+ this.min !== this._suggestedMin &&
10275
+ i === a(this.min, 0) &&
10276
+ n(a(i, -1)),
10277
+ (this.min = i),
10278
+ (this.max = s);
10279
+ }
10280
+ buildTicks() {
10281
+ const t = this.options,
10282
+ e = (function (t, e) {
10283
+ const i = Math.floor(Dt(e.max)),
10284
+ s = Math.ceil(e.max / Math.pow(10, i)),
10285
+ n = [];
10286
+ let o = q(t.min, Math.pow(10, Math.floor(Dt(e.min)))),
10287
+ a = Math.floor(Dt(o)),
10288
+ r = Math.floor(o / Math.pow(10, a)),
10289
+ l = a < 0 ? Math.pow(10, Math.abs(a)) : 1;
10290
+ do {
10291
+ n.push({ value: o, major: Jo(o) }),
10292
+ ++r,
10293
+ 10 === r && ((r = 1), ++a, (l = a >= 0 ? 1 : l)),
10294
+ (o = Math.round(r * Math.pow(10, a) * l) / l);
10295
+ } while (a < i || (a === i && r < s));
10296
+ const h = q(t.max, o);
10297
+ return n.push({ value: h, major: Jo(o) }), n;
10298
+ })({ min: this._userMin, max: this._userMax }, this);
10299
+ return (
10300
+ "ticks" === t.bounds && Et(e, this, "value"),
10301
+ t.reverse
10302
+ ? (e.reverse(), (this.start = this.max), (this.end = this.min))
10303
+ : ((this.start = this.min), (this.end = this.max)),
10304
+ e
10305
+ );
10306
+ }
10307
+ getLabelForValue(t) {
10308
+ return void 0 === t
10309
+ ? "0"
10310
+ : Ri(t, this.chart.options.locale, this.options.ticks.format);
10311
+ }
10312
+ configure() {
10313
+ const t = this.min;
10314
+ super.configure(),
10315
+ (this._startValue = Dt(t)),
10316
+ (this._valueRange = Dt(this.max) - Dt(t));
10317
+ }
10318
+ getPixelForValue(t) {
10319
+ return (
10320
+ (void 0 !== t && 0 !== t) || (t = this.min),
10321
+ null === t || isNaN(t)
10322
+ ? NaN
10323
+ : this.getPixelForDecimal(
10324
+ t === this.min ? 0 : (Dt(t) - this._startValue) / this._valueRange
10325
+ )
10326
+ );
10327
+ }
10328
+ getValueForPixel(t) {
10329
+ const e = this.getDecimalForPixel(t);
10330
+ return Math.pow(10, this._startValue + e * this._valueRange);
10331
+ }
10332
+ }
10333
+ function ta(t) {
10334
+ const e = t.ticks;
10335
+ if (e.display && t.display) {
10336
+ const t = Ne(e.backdropPadding);
10337
+ return K(e.font && e.font.size, bt.font.size) + t.height;
10338
+ }
10339
+ return 0;
10340
+ }
10341
+ function ea(t, e, i, s, n) {
10342
+ return t === s || t === n
10343
+ ? { start: e - i / 2, end: e + i / 2 }
10344
+ : t < s || t > n
10345
+ ? { start: e - i, end: e }
10346
+ : { start: e, end: e + i };
10347
+ }
10348
+ function ia(t) {
10349
+ const e = {
10350
+ l: t.left + t._padding.left,
10351
+ r: t.right - t._padding.right,
10352
+ t: t.top + t._padding.top,
10353
+ b: t.bottom - t._padding.bottom,
10354
+ },
10355
+ i = Object.assign({}, e),
10356
+ s = [],
10357
+ n = [],
10358
+ o = t._pointLabels.length,
10359
+ a = t.options.pointLabels,
10360
+ r = a.centerPointLabels ? _t / o : 0;
10361
+ for (let d = 0; d < o; d++) {
10362
+ const o = a.setContext(t.getPointLabelContext(d));
10363
+ n[d] = o.padding;
10364
+ const u = t.getPointPosition(d, t.drawingArea + n[d], r),
10365
+ f = He(o.font),
10366
+ g =
10367
+ ((l = t.ctx),
10368
+ (h = f),
10369
+ (c = Y((c = t._pointLabels[d])) ? c : [c]),
10370
+ { w: qt(l, h.string, c), h: c.length * h.lineHeight });
10371
+ s[d] = g;
10372
+ const p = Nt(t.getIndexAngle(d) + r),
10373
+ m = Math.round(zt(p));
10374
+ sa(i, e, p, ea(m, u.x, g.w, 0, 180), ea(m, u.y, g.h, 90, 270));
10375
+ }
10376
+ var l, h, c;
10377
+ t.setCenterPoint(e.l - i.l, i.r - e.r, e.t - i.t, i.b - e.b),
10378
+ (t._pointLabelItems = (function (t, e, i) {
10379
+ const s = [],
10380
+ n = t._pointLabels.length,
10381
+ o = t.options,
10382
+ a = ta(o) / 2,
10383
+ r = t.drawingArea,
10384
+ l = o.pointLabels.centerPointLabels ? _t / n : 0;
10385
+ for (let o = 0; o < n; o++) {
10386
+ const n = t.getPointPosition(o, r + a + i[o], l),
10387
+ h = Math.round(zt(Nt(n.angle + kt))),
10388
+ c = e[o],
10389
+ d = aa(n.y, c.h, h),
10390
+ u = na(h),
10391
+ f = oa(n.x, c.w, u);
10392
+ s.push({
10393
+ x: n.x,
10394
+ y: d,
10395
+ textAlign: u,
10396
+ left: f,
10397
+ top: d,
10398
+ right: f + c.w,
10399
+ bottom: d + c.h,
10400
+ });
10401
+ }
10402
+ return s;
10403
+ })(t, s, n));
10404
+ }
10405
+ function sa(t, e, i, s, n) {
10406
+ const o = Math.abs(Math.sin(i)),
10407
+ a = Math.abs(Math.cos(i));
10408
+ let r = 0,
10409
+ l = 0;
10410
+ s.start < e.l
10411
+ ? ((r = (e.l - s.start) / o), (t.l = Math.min(t.l, e.l - r)))
10412
+ : s.end > e.r &&
10413
+ ((r = (s.end - e.r) / o), (t.r = Math.max(t.r, e.r + r))),
10414
+ n.start < e.t
10415
+ ? ((l = (e.t - n.start) / a), (t.t = Math.min(t.t, e.t - l)))
10416
+ : n.end > e.b &&
10417
+ ((l = (n.end - e.b) / a), (t.b = Math.max(t.b, e.b + l)));
10418
+ }
10419
+ function na(t) {
10420
+ return 0 === t || 180 === t ? "center" : t < 180 ? "left" : "right";
10421
+ }
10422
+ function oa(t, e, i) {
10423
+ return "right" === i ? (t -= e) : "center" === i && (t -= e / 2), t;
10424
+ }
10425
+ function aa(t, e, i) {
10426
+ return (
10427
+ 90 === i || 270 === i ? (t -= e / 2) : (i > 270 || i < 90) && (t -= e), t
10428
+ );
10429
+ }
10430
+ function ra(t, e, i, s) {
10431
+ const { ctx: n } = t;
10432
+ if (i) n.arc(t.xCenter, t.yCenter, e, 0, yt);
10433
+ else {
10434
+ let i = t.getPointPosition(0, e);
10435
+ n.moveTo(i.x, i.y);
10436
+ for (let o = 1; o < s; o++)
10437
+ (i = t.getPointPosition(o, e)), n.lineTo(i.x, i.y);
10438
+ }
10439
+ }
10440
+ (Qo.id = "logarithmic"),
10441
+ (Qo.defaults = {
10442
+ ticks: { callback: Os.formatters.logarithmic, major: { enabled: !0 } },
10443
+ });
10444
+ class la extends Go {
10445
+ constructor(t) {
10446
+ super(t),
10447
+ (this.xCenter = void 0),
10448
+ (this.yCenter = void 0),
10449
+ (this.drawingArea = void 0),
10450
+ (this._pointLabels = []),
10451
+ (this._pointLabelItems = []);
10452
+ }
10453
+ setDimensions() {
10454
+ const t = (this._padding = Ne(ta(this.options) / 2)),
10455
+ e = (this.width = this.maxWidth - t.width),
10456
+ i = (this.height = this.maxHeight - t.height);
10457
+ (this.xCenter = Math.floor(this.left + e / 2 + t.left)),
10458
+ (this.yCenter = Math.floor(this.top + i / 2 + t.top)),
10459
+ (this.drawingArea = Math.floor(Math.min(e, i) / 2));
10460
+ }
10461
+ determineDataLimits() {
10462
+ const { min: t, max: e } = this.getMinMax(!1);
10463
+ (this.min = X(t) && !isNaN(t) ? t : 0),
10464
+ (this.max = X(e) && !isNaN(e) ? e : 0),
10465
+ this.handleTickRangeOptions();
10466
+ }
10467
+ computeTickLimit() {
10468
+ return Math.ceil(this.drawingArea / ta(this.options));
10469
+ }
10470
+ generateTickLabels(t) {
10471
+ Go.prototype.generateTickLabels.call(this, t),
10472
+ (this._pointLabels = this.getLabels()
10473
+ .map((t, e) => {
10474
+ const i = J(this.options.pointLabels.callback, [t, e], this);
10475
+ return i || 0 === i ? i : "";
10476
+ })
10477
+ .filter((t, e) => this.chart.getDataVisibility(e)));
10478
+ }
10479
+ fit() {
10480
+ const t = this.options;
10481
+ t.display && t.pointLabels.display
10482
+ ? ia(this)
10483
+ : this.setCenterPoint(0, 0, 0, 0);
10484
+ }
10485
+ setCenterPoint(t, e, i, s) {
10486
+ (this.xCenter += Math.floor((t - e) / 2)),
10487
+ (this.yCenter += Math.floor((i - s) / 2)),
10488
+ (this.drawingArea -= Math.min(
10489
+ this.drawingArea / 2,
10490
+ Math.max(t, e, i, s)
10491
+ ));
10492
+ }
10493
+ getIndexAngle(t) {
10494
+ return Nt(
10495
+ t * (yt / (this._pointLabels.length || 1)) +
10496
+ It(this.options.startAngle || 0)
10497
+ );
10498
+ }
10499
+ getDistanceFromCenterForValue(t) {
10500
+ if ($(t)) return NaN;
10501
+ const e = this.drawingArea / (this.max - this.min);
10502
+ return this.options.reverse ? (this.max - t) * e : (t - this.min) * e;
10503
+ }
10504
+ getValueForDistanceFromCenter(t) {
10505
+ if ($(t)) return NaN;
10506
+ const e = t / (this.drawingArea / (this.max - this.min));
10507
+ return this.options.reverse ? this.max - e : this.min + e;
10508
+ }
10509
+ getPointLabelContext(t) {
10510
+ const e = this._pointLabels || [];
10511
+ if (t >= 0 && t < e.length) {
10512
+ const i = e[t];
10513
+ return (function (t, e, i) {
10514
+ return Ye(t, { label: i, index: e, type: "pointLabel" });
10515
+ })(this.getContext(), t, i);
10516
+ }
10517
+ }
10518
+ getPointPosition(t, e, i = 0) {
10519
+ const s = this.getIndexAngle(t) - kt + i;
10520
+ return {
10521
+ x: Math.cos(s) * e + this.xCenter,
10522
+ y: Math.sin(s) * e + this.yCenter,
10523
+ angle: s,
10524
+ };
10525
+ }
10526
+ getPointPositionForValue(t, e) {
10527
+ return this.getPointPosition(t, this.getDistanceFromCenterForValue(e));
10528
+ }
10529
+ getBasePosition(t) {
10530
+ return this.getPointPositionForValue(t || 0, this.getBaseValue());
10531
+ }
10532
+ getPointLabelPosition(t) {
10533
+ const { left: e, top: i, right: s, bottom: n } = this._pointLabelItems[t];
10534
+ return { left: e, top: i, right: s, bottom: n };
10535
+ }
10536
+ drawBackground() {
10537
+ const {
10538
+ backgroundColor: t,
10539
+ grid: { circular: e },
10540
+ } = this.options;
10541
+ if (t) {
10542
+ const i = this.ctx;
10543
+ i.save(),
10544
+ i.beginPath(),
10545
+ ra(
10546
+ this,
10547
+ this.getDistanceFromCenterForValue(this._endValue),
10548
+ e,
10549
+ this._pointLabels.length
10550
+ ),
10551
+ i.closePath(),
10552
+ (i.fillStyle = t),
10553
+ i.fill(),
10554
+ i.restore();
10555
+ }
10556
+ }
10557
+ drawGrid() {
10558
+ const t = this.ctx,
10559
+ e = this.options,
10560
+ { angleLines: i, grid: s } = e,
10561
+ n = this._pointLabels.length;
10562
+ let o, a, r;
10563
+ if (
10564
+ (e.pointLabels.display &&
10565
+ (function (t, e) {
10566
+ const {
10567
+ ctx: i,
10568
+ options: { pointLabels: s },
10569
+ } = t;
10570
+ for (let n = e - 1; n >= 0; n--) {
10571
+ const e = s.setContext(t.getPointLabelContext(n)),
10572
+ o = He(e.font),
10573
+ {
10574
+ x: a,
10575
+ y: r,
10576
+ textAlign: l,
10577
+ left: h,
10578
+ top: c,
10579
+ right: d,
10580
+ bottom: u,
10581
+ } = t._pointLabelItems[n],
10582
+ { backdropColor: f } = e;
10583
+ if (!$(f)) {
10584
+ const t = Ne(e.backdropPadding);
10585
+ (i.fillStyle = f),
10586
+ i.fillRect(
10587
+ h - t.left,
10588
+ c - t.top,
10589
+ d - h + t.width,
10590
+ u - c + t.height
10591
+ );
10592
+ }
10593
+ se(i, t._pointLabels[n], a, r + o.lineHeight / 2, o, {
10594
+ color: e.color,
10595
+ textAlign: l,
10596
+ textBaseline: "middle",
10597
+ });
10598
+ }
10599
+ })(this, n),
10600
+ s.display &&
10601
+ this.ticks.forEach((t, e) => {
10602
+ if (0 !== e) {
10603
+ a = this.getDistanceFromCenterForValue(t.value);
10604
+ !(function (t, e, i, s) {
10605
+ const n = t.ctx,
10606
+ o = e.circular,
10607
+ { color: a, lineWidth: r } = e;
10608
+ (!o && !s) ||
10609
+ !a ||
10610
+ !r ||
10611
+ i < 0 ||
10612
+ (n.save(),
10613
+ (n.strokeStyle = a),
10614
+ (n.lineWidth = r),
10615
+ n.setLineDash(e.borderDash),
10616
+ (n.lineDashOffset = e.borderDashOffset),
10617
+ n.beginPath(),
10618
+ ra(t, i, o, s),
10619
+ n.closePath(),
10620
+ n.stroke(),
10621
+ n.restore());
10622
+ })(this, s.setContext(this.getContext(e - 1)), a, n);
10623
+ }
10624
+ }),
10625
+ i.display)
10626
+ ) {
10627
+ for (t.save(), o = n - 1; o >= 0; o--) {
10628
+ const s = i.setContext(this.getPointLabelContext(o)),
10629
+ { color: n, lineWidth: l } = s;
10630
+ l &&
10631
+ n &&
10632
+ ((t.lineWidth = l),
10633
+ (t.strokeStyle = n),
10634
+ t.setLineDash(s.borderDash),
10635
+ (t.lineDashOffset = s.borderDashOffset),
10636
+ (a = this.getDistanceFromCenterForValue(
10637
+ e.ticks.reverse ? this.min : this.max
10638
+ )),
10639
+ (r = this.getPointPosition(o, a)),
10640
+ t.beginPath(),
10641
+ t.moveTo(this.xCenter, this.yCenter),
10642
+ t.lineTo(r.x, r.y),
10643
+ t.stroke());
10644
+ }
10645
+ t.restore();
10646
+ }
10647
+ }
10648
+ drawBorder() {}
10649
+ drawLabels() {
10650
+ const t = this.ctx,
10651
+ e = this.options,
10652
+ i = e.ticks;
10653
+ if (!i.display) return;
10654
+ const s = this.getIndexAngle(0);
10655
+ let n, o;
10656
+ t.save(),
10657
+ t.translate(this.xCenter, this.yCenter),
10658
+ t.rotate(s),
10659
+ (t.textAlign = "center"),
10660
+ (t.textBaseline = "middle"),
10661
+ this.ticks.forEach((s, a) => {
10662
+ if (0 === a && !e.reverse) return;
10663
+ const r = i.setContext(this.getContext(a)),
10664
+ l = He(r.font);
10665
+ if (
10666
+ ((n = this.getDistanceFromCenterForValue(this.ticks[a].value)),
10667
+ r.showLabelBackdrop)
10668
+ ) {
10669
+ (t.font = l.string),
10670
+ (o = t.measureText(s.label).width),
10671
+ (t.fillStyle = r.backdropColor);
10672
+ const e = Ne(r.backdropPadding);
10673
+ t.fillRect(
10674
+ -o / 2 - e.left,
10675
+ -n - l.size / 2 - e.top,
10676
+ o + e.width,
10677
+ l.size + e.height
10678
+ );
10679
+ }
10680
+ se(t, s.label, 0, -n, l, { color: r.color });
10681
+ }),
10682
+ t.restore();
10683
+ }
10684
+ drawTitle() {}
10685
+ }
10686
+ (la.id = "radialLinear"),
10687
+ (la.defaults = {
10688
+ display: !0,
10689
+ animate: !0,
10690
+ position: "chartArea",
10691
+ angleLines: {
10692
+ display: !0,
10693
+ lineWidth: 1,
10694
+ borderDash: [],
10695
+ borderDashOffset: 0,
10696
+ },
10697
+ grid: { circular: !1 },
10698
+ startAngle: 0,
10699
+ ticks: { showLabelBackdrop: !0, callback: Os.formatters.numeric },
10700
+ pointLabels: {
10701
+ backdropColor: void 0,
10702
+ backdropPadding: 2,
10703
+ display: !0,
10704
+ font: { size: 10 },
10705
+ callback: (t) => t,
10706
+ padding: 5,
10707
+ centerPointLabels: !1,
10708
+ },
10709
+ }),
10710
+ (la.defaultRoutes = {
10711
+ "angleLines.color": "borderColor",
10712
+ "pointLabels.color": "color",
10713
+ "ticks.color": "color",
10714
+ }),
10715
+ (la.descriptors = { angleLines: { _fallback: "grid" } });
10716
+ const ha = {
10717
+ millisecond: { common: !0, size: 1, steps: 1e3 },
10718
+ second: { common: !0, size: 1e3, steps: 60 },
10719
+ minute: { common: !0, size: 6e4, steps: 60 },
10720
+ hour: { common: !0, size: 36e5, steps: 24 },
10721
+ day: { common: !0, size: 864e5, steps: 30 },
10722
+ week: { common: !1, size: 6048e5, steps: 4 },
10723
+ month: { common: !0, size: 2628e6, steps: 12 },
10724
+ quarter: { common: !1, size: 7884e6, steps: 4 },
10725
+ year: { common: !0, size: 3154e7 },
10726
+ },
10727
+ ca = Object.keys(ha);
10728
+ function da(t, e) {
10729
+ return t - e;
10730
+ }
10731
+ function ua(t, e) {
10732
+ if ($(e)) return null;
10733
+ const i = t._adapter,
10734
+ { parser: s, round: n, isoWeekday: o } = t._parseOpts;
10735
+ let a = e;
10736
+ return (
10737
+ "function" == typeof s && (a = s(a)),
10738
+ X(a) || (a = "string" == typeof s ? i.parse(a, s) : i.parse(a)),
10739
+ null === a
10740
+ ? null
10741
+ : (n &&
10742
+ (a =
10743
+ "week" !== n || (!Tt(o) && !0 !== o)
10744
+ ? i.startOf(a, n)
10745
+ : i.startOf(a, "isoWeek", o)),
10746
+ +a)
10747
+ );
10748
+ }
10749
+ function fa(t, e, i, s) {
10750
+ const n = ca.length;
10751
+ for (let o = ca.indexOf(t); o < n - 1; ++o) {
10752
+ const t = ha[ca[o]],
10753
+ n = t.steps ? t.steps : Number.MAX_SAFE_INTEGER;
10754
+ if (t.common && Math.ceil((i - e) / (n * t.size)) <= s) return ca[o];
10755
+ }
10756
+ return ca[n - 1];
10757
+ }
10758
+ function ga(t, e, i) {
10759
+ if (i) {
10760
+ if (i.length) {
10761
+ const { lo: s, hi: n } = ae(i, e);
10762
+ t[i[s] >= e ? i[s] : i[n]] = !0;
10763
+ }
10764
+ } else t[e] = !0;
10765
+ }
10766
+ function pa(t, e, i) {
10767
+ const s = [],
10768
+ n = {},
10769
+ o = e.length;
10770
+ let a, r;
10771
+ for (a = 0; a < o; ++a)
10772
+ (r = e[a]), (n[r] = a), s.push({ value: r, major: !1 });
10773
+ return 0 !== o && i
10774
+ ? (function (t, e, i, s) {
10775
+ const n = t._adapter,
10776
+ o = +n.startOf(e[0].value, s),
10777
+ a = e[e.length - 1].value;
10778
+ let r, l;
10779
+ for (r = o; r <= a; r = +n.add(r, 1, s))
10780
+ (l = i[r]), l >= 0 && (e[l].major = !0);
10781
+ return e;
10782
+ })(t, s, n, i)
10783
+ : s;
10784
+ }
10785
+ class ma extends Bs {
10786
+ constructor(t) {
10787
+ super(t),
10788
+ (this._cache = { data: [], labels: [], all: [] }),
10789
+ (this._unit = "day"),
10790
+ (this._majorUnit = void 0),
10791
+ (this._offsets = {}),
10792
+ (this._normalized = !1),
10793
+ (this._parseOpts = void 0);
10794
+ }
10795
+ init(t, e) {
10796
+ const i = t.time || (t.time = {}),
10797
+ s = (this._adapter = new mn._date(t.adapters.date));
10798
+ ot(i.displayFormats, s.formats()),
10799
+ (this._parseOpts = {
10800
+ parser: i.parser,
10801
+ round: i.round,
10802
+ isoWeekday: i.isoWeekday,
10803
+ }),
10804
+ super.init(t),
10805
+ (this._normalized = e.normalized);
10806
+ }
10807
+ parse(t, e) {
10808
+ return void 0 === t ? null : ua(this, t);
10809
+ }
10810
+ beforeLayout() {
10811
+ super.beforeLayout(), (this._cache = { data: [], labels: [], all: [] });
10812
+ }
10813
+ determineDataLimits() {
10814
+ const t = this.options,
10815
+ e = this._adapter,
10816
+ i = t.time.unit || "day";
10817
+ let {
10818
+ min: s,
10819
+ max: n,
10820
+ minDefined: o,
10821
+ maxDefined: a,
10822
+ } = this.getUserBounds();
10823
+ function r(t) {
10824
+ o || isNaN(t.min) || (s = Math.min(s, t.min)),
10825
+ a || isNaN(t.max) || (n = Math.max(n, t.max));
10826
+ }
10827
+ (o && a) ||
10828
+ (r(this._getLabelBounds()),
10829
+ ("ticks" === t.bounds && "labels" === t.ticks.source) ||
10830
+ r(this.getMinMax(!1))),
10831
+ (s = X(s) && !isNaN(s) ? s : +e.startOf(Date.now(), i)),
10832
+ (n = X(n) && !isNaN(n) ? n : +e.endOf(Date.now(), i) + 1),
10833
+ (this.min = Math.min(s, n - 1)),
10834
+ (this.max = Math.max(s + 1, n));
10835
+ }
10836
+ _getLabelBounds() {
10837
+ const t = this.getLabelTimestamps();
10838
+ let e = Number.POSITIVE_INFINITY,
10839
+ i = Number.NEGATIVE_INFINITY;
10840
+ return (
10841
+ t.length && ((e = t[0]), (i = t[t.length - 1])), { min: e, max: i }
10842
+ );
10843
+ }
10844
+ buildTicks() {
10845
+ const t = this.options,
10846
+ e = t.time,
10847
+ i = t.ticks,
10848
+ s =
10849
+ "labels" === i.source ? this.getLabelTimestamps() : this._generate();
10850
+ "ticks" === t.bounds &&
10851
+ s.length &&
10852
+ ((this.min = this._userMin || s[0]),
10853
+ (this.max = this._userMax || s[s.length - 1]));
10854
+ const n = this.min,
10855
+ o = he(s, n, this.max);
10856
+ return (
10857
+ (this._unit =
10858
+ e.unit ||
10859
+ (i.autoSkip
10860
+ ? fa(e.minUnit, this.min, this.max, this._getLabelCapacity(n))
10861
+ : (function (t, e, i, s, n) {
10862
+ for (let o = ca.length - 1; o >= ca.indexOf(i); o--) {
10863
+ const i = ca[o];
10864
+ if (ha[i].common && t._adapter.diff(n, s, i) >= e - 1)
10865
+ return i;
10866
+ }
10867
+ return ca[i ? ca.indexOf(i) : 0];
10868
+ })(this, o.length, e.minUnit, this.min, this.max))),
10869
+ (this._majorUnit =
10870
+ i.major.enabled && "year" !== this._unit
10871
+ ? (function (t) {
10872
+ for (let e = ca.indexOf(t) + 1, i = ca.length; e < i; ++e)
10873
+ if (ha[ca[e]].common) return ca[e];
10874
+ })(this._unit)
10875
+ : void 0),
10876
+ this.initOffsets(s),
10877
+ t.reverse && o.reverse(),
10878
+ pa(this, o, this._majorUnit)
10879
+ );
10880
+ }
10881
+ initOffsets(t) {
10882
+ let e,
10883
+ i,
10884
+ s = 0,
10885
+ n = 0;
10886
+ this.options.offset &&
10887
+ t.length &&
10888
+ ((e = this.getDecimalForValue(t[0])),
10889
+ (s = 1 === t.length ? 1 - e : (this.getDecimalForValue(t[1]) - e) / 2),
10890
+ (i = this.getDecimalForValue(t[t.length - 1])),
10891
+ (n =
10892
+ 1 === t.length
10893
+ ? i
10894
+ : (i - this.getDecimalForValue(t[t.length - 2])) / 2));
10895
+ const o = t.length < 3 ? 0.5 : 0.25;
10896
+ (s = jt(s, 0, o)),
10897
+ (n = jt(n, 0, o)),
10898
+ (this._offsets = { start: s, end: n, factor: 1 / (s + 1 + n) });
10899
+ }
10900
+ _generate() {
10901
+ const t = this._adapter,
10902
+ e = this.min,
10903
+ i = this.max,
10904
+ s = this.options,
10905
+ n = s.time,
10906
+ o = n.unit || fa(n.minUnit, e, i, this._getLabelCapacity(e)),
10907
+ a = K(n.stepSize, 1),
10908
+ r = "week" === o && n.isoWeekday,
10909
+ l = Tt(r) || !0 === r,
10910
+ h = {};
10911
+ let c,
10912
+ d,
10913
+ u = e;
10914
+ if (
10915
+ (l && (u = +t.startOf(u, "isoWeek", r)),
10916
+ (u = +t.startOf(u, l ? "day" : o)),
10917
+ t.diff(i, e, o) > 1e5 * a)
10918
+ )
10919
+ throw new Error(
10920
+ e + " and " + i + " are too far apart with stepSize of " + a + " " + o
10921
+ );
10922
+ const f = "data" === s.ticks.source && this.getDataTimestamps();
10923
+ for (c = u, d = 0; c < i; c = +t.add(c, a, o), d++) ga(h, c, f);
10924
+ return (
10925
+ (c !== i && "ticks" !== s.bounds && 1 !== d) || ga(h, c, f),
10926
+ Object.keys(h)
10927
+ .sort((t, e) => t - e)
10928
+ .map((t) => +t)
10929
+ );
10930
+ }
10931
+ getLabelForValue(t) {
10932
+ const e = this._adapter,
10933
+ i = this.options.time;
10934
+ return i.tooltipFormat
10935
+ ? e.format(t, i.tooltipFormat)
10936
+ : e.format(t, i.displayFormats.datetime);
10937
+ }
10938
+ _tickFormatFunction(t, e, i, s) {
10939
+ const n = this.options,
10940
+ o = n.time.displayFormats,
10941
+ a = this._unit,
10942
+ r = this._majorUnit,
10943
+ l = a && o[a],
10944
+ h = r && o[r],
10945
+ c = i[e],
10946
+ d = r && h && c && c.major,
10947
+ u = this._adapter.format(t, s || (d ? h : l)),
10948
+ f = n.ticks.callback;
10949
+ return f ? J(f, [u, e, i], this) : u;
10950
+ }
10951
+ generateTickLabels(t) {
10952
+ let e, i, s;
10953
+ for (e = 0, i = t.length; e < i; ++e)
10954
+ (s = t[e]), (s.label = this._tickFormatFunction(s.value, e, t));
10955
+ }
10956
+ getDecimalForValue(t) {
10957
+ return null === t ? NaN : (t - this.min) / (this.max - this.min);
10958
+ }
10959
+ getPixelForValue(t) {
10960
+ const e = this._offsets,
10961
+ i = this.getDecimalForValue(t);
10962
+ return this.getPixelForDecimal((e.start + i) * e.factor);
10963
+ }
10964
+ getValueForPixel(t) {
10965
+ const e = this._offsets,
10966
+ i = this.getDecimalForPixel(t) / e.factor - e.end;
10967
+ return this.min + i * (this.max - this.min);
10968
+ }
10969
+ _getLabelSize(t) {
10970
+ const e = this.options.ticks,
10971
+ i = this.ctx.measureText(t).width,
10972
+ s = It(this.isHorizontal() ? e.maxRotation : e.minRotation),
10973
+ n = Math.cos(s),
10974
+ o = Math.sin(s),
10975
+ a = this._resolveTickFontOptions(0).size;
10976
+ return { w: i * n + a * o, h: i * o + a * n };
10977
+ }
10978
+ _getLabelCapacity(t) {
10979
+ const e = this.options.time,
10980
+ i = e.displayFormats,
10981
+ s = i[e.unit] || i.millisecond,
10982
+ n = this._tickFormatFunction(t, 0, pa(this, [t], this._majorUnit), s),
10983
+ o = this._getLabelSize(n),
10984
+ a =
10985
+ Math.floor(
10986
+ this.isHorizontal() ? this.width / o.w : this.height / o.h
10987
+ ) - 1;
10988
+ return a > 0 ? a : 1;
10989
+ }
10990
+ getDataTimestamps() {
10991
+ let t,
10992
+ e,
10993
+ i = this._cache.data || [];
10994
+ if (i.length) return i;
10995
+ const s = this.getMatchingVisibleMetas();
10996
+ if (this._normalized && s.length)
10997
+ return (this._cache.data = s[0].controller.getAllParsedValues(this));
10998
+ for (t = 0, e = s.length; t < e; ++t)
10999
+ i = i.concat(s[t].controller.getAllParsedValues(this));
11000
+ return (this._cache.data = this.normalize(i));
11001
+ }
11002
+ getLabelTimestamps() {
11003
+ const t = this._cache.labels || [];
11004
+ let e, i;
11005
+ if (t.length) return t;
11006
+ const s = this.getLabels();
11007
+ for (e = 0, i = s.length; e < i; ++e) t.push(ua(this, s[e]));
11008
+ return (this._cache.labels = this._normalized ? t : this.normalize(t));
11009
+ }
11010
+ normalize(t) {
11011
+ return fe(t.sort(da));
11012
+ }
11013
+ }
11014
+ function xa(t, e, i) {
11015
+ let s,
11016
+ n,
11017
+ o,
11018
+ a,
11019
+ r = 0,
11020
+ l = t.length - 1;
11021
+ i
11022
+ ? (e >= t[r].pos && e <= t[l].pos && ({ lo: r, hi: l } = re(t, "pos", e)),
11023
+ ({ pos: s, time: o } = t[r]),
11024
+ ({ pos: n, time: a } = t[l]))
11025
+ : (e >= t[r].time &&
11026
+ e <= t[l].time &&
11027
+ ({ lo: r, hi: l } = re(t, "time", e)),
11028
+ ({ time: s, pos: o } = t[r]),
11029
+ ({ time: n, pos: a } = t[l]));
11030
+ const h = n - s;
11031
+ return h ? o + ((a - o) * (e - s)) / h : o;
11032
+ }
11033
+ (ma.id = "time"),
11034
+ (ma.defaults = {
11035
+ bounds: "data",
11036
+ adapters: {},
11037
+ time: {
11038
+ parser: !1,
11039
+ unit: !1,
11040
+ round: !1,
11041
+ isoWeekday: !1,
11042
+ minUnit: "millisecond",
11043
+ displayFormats: {},
11044
+ },
11045
+ ticks: { source: "auto", major: { enabled: !1 } },
11046
+ });
11047
+ class ba extends ma {
11048
+ constructor(t) {
11049
+ super(t),
11050
+ (this._table = []),
11051
+ (this._minPos = void 0),
11052
+ (this._tableRange = void 0);
11053
+ }
11054
+ initOffsets() {
11055
+ const t = this._getTimestampsForTable(),
11056
+ e = (this._table = this.buildLookupTable(t));
11057
+ (this._minPos = xa(e, this.min)),
11058
+ (this._tableRange = xa(e, this.max) - this._minPos),
11059
+ super.initOffsets(t);
11060
+ }
11061
+ buildLookupTable(t) {
11062
+ const { min: e, max: i } = this,
11063
+ s = [],
11064
+ n = [];
11065
+ let o, a, r, l, h;
11066
+ for (o = 0, a = t.length; o < a; ++o)
11067
+ (l = t[o]), l >= e && l <= i && s.push(l);
11068
+ if (s.length < 2)
11069
+ return [
11070
+ { time: e, pos: 0 },
11071
+ { time: i, pos: 1 },
11072
+ ];
11073
+ for (o = 0, a = s.length; o < a; ++o)
11074
+ (h = s[o + 1]),
11075
+ (r = s[o - 1]),
11076
+ (l = s[o]),
11077
+ Math.round((h + r) / 2) !== l &&
11078
+ n.push({ time: l, pos: o / (a - 1) });
11079
+ return n;
11080
+ }
11081
+ _getTimestampsForTable() {
11082
+ let t = this._cache.all || [];
11083
+ if (t.length) return t;
11084
+ const e = this.getDataTimestamps(),
11085
+ i = this.getLabelTimestamps();
11086
+ return (
11087
+ (t =
11088
+ e.length && i.length
11089
+ ? this.normalize(e.concat(i))
11090
+ : e.length
11091
+ ? e
11092
+ : i),
11093
+ (t = this._cache.all = t),
11094
+ t
11095
+ );
11096
+ }
11097
+ getDecimalForValue(t) {
11098
+ return (xa(this._table, t) - this._minPos) / this._tableRange;
11099
+ }
11100
+ getValueForPixel(t) {
11101
+ const e = this._offsets,
11102
+ i = this.getDecimalForPixel(t) / e.factor - e.end;
11103
+ return xa(this._table, i * this._tableRange + this._minPos, !0);
11104
+ }
11105
+ }
11106
+ (ba.id = "timeseries"), (ba.defaults = ma.defaults);
11107
+ var _a = Object.freeze({
11108
+ __proto__: null,
11109
+ CategoryScale: qo,
11110
+ LinearScale: Zo,
11111
+ LogarithmicScale: Qo,
11112
+ RadialLinearScale: la,
11113
+ TimeScale: ma,
11114
+ TimeSeriesScale: ba,
11115
+ });
11116
+ return (
11117
+ dn.register(Rn, _a, no, Uo),
11118
+ (dn.helpers = { ...Yi }),
11119
+ (dn._adapters = mn),
11120
+ (dn.Animation = us),
11121
+ (dn.Animations = gs),
11122
+ (dn.animator = a),
11123
+ (dn.controllers = Ws.controllers.items),
11124
+ (dn.DatasetController = Ps),
11125
+ (dn.Element = Ds),
11126
+ (dn.elements = no),
11127
+ (dn.Interaction = Ee),
11128
+ (dn.layouts = ni),
11129
+ (dn.platforms = hs),
11130
+ (dn.Scale = Bs),
11131
+ (dn.Ticks = Os),
11132
+ Object.assign(dn, Rn, _a, no, Uo, hs),
11133
+ (dn.Chart = dn),
11134
+ "undefined" != typeof window && (window.Chart = dn),
11135
+ dn
11136
+ );
11137
+ });
core/admin/class-admin.php CHANGED
@@ -48,7 +48,7 @@ class Admin {
48
  if ( ! empty( array_intersect( $roles, $selected_user_roles ) ) ) {
49
  wp_add_dashboard_widget(
50
  'zerospam_dashboard_widget',
51
- __( 'WordPress Zero Spam', 'zerospam' ),
52
  array( $this, 'dashboard_widget' )
53
  );
54
  }
@@ -70,7 +70,7 @@ class Admin {
70
  echo sprintf(
71
  wp_kses(
72
  /* translators: %s: Zero Spam API link */
73
- __( '<strong>Super-charge WordPress Zero Spam with a <a href="%s" target="_blank" rel="noopener noreferrer">Zero Spam API License</a>.</strong>', 'zerospam' ),
74
  array(
75
  'a' => array(
76
  'target' => array(),
@@ -88,7 +88,7 @@ class Admin {
88
  echo sprintf(
89
  wp_kses(
90
  /* translators: %s: Zero Spam API link */
91
- __( '<p><strong>Enable enhanced protection</strong> and super-charge your site with the power of a global detection network that monitors traffic and usage in real-time to detect malicious activity.</p>', 'zerospam' ),
92
  array(
93
  'a' => array(
94
  'target' => array(),
@@ -102,8 +102,8 @@ class Admin {
102
  )
103
  );
104
  ?>
105
- <a href="<?php echo esc_url( ZEROSPAM_URL ); ?>subscribe/?utm_source=wordpress_zero_spam&utm_medium=dashboard_widget&utm_campaign=license" target="_blank" rel="noreferrer noopener" class="button button-primary"><?php esc_html_e( 'Get a Zero Spam License', 'zerospam' ); ?></a>
106
- <a href="<?php echo esc_url( ZEROSPAM_URL ); ?>?utm_source=wordpress_zero_spam&utm_medium=dashboard_widget&utm_campaign=license" target="_blank" rel="noreferrer noopener" class="button button-secondary"><?php esc_html_e( 'Learn More', 'zerospam' ); ?></a>
107
  </div>
108
  <?php
109
  }
@@ -118,7 +118,7 @@ class Admin {
118
  $messages = array();
119
 
120
  // Check Zero Spam license key.
121
- $zerospam_protection = \ZeroSpam\Core\Settings::get_settings( 'zerospam' );
122
  if ( 'enabled' === $zerospam_protection ) {
123
  $zerospam_license_key = \ZeroSpam\Core\Settings::get_settings( 'zerospam_license' );
124
  if ( ! $zerospam_license_key ) {
@@ -128,7 +128,7 @@ class Admin {
128
  'content' => sprintf(
129
  wp_kses(
130
  /* translators: %1$s: Replaced with the Zero Spam settings page URL */
131
- __( 'Zero Spam Enhanced Protection is currenlty enabled, but <strong>missing a valid license key</strong>. <a href="%1$s">Add your license key</a> to enable enhanced site protection.', 'zerospam' ),
132
  array(
133
  'strong' => array(),
134
  'a' => array(
@@ -138,7 +138,7 @@ class Admin {
138
  )
139
  ),
140
  esc_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings' ) ),
141
- wp_nonce_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=autoconfigure' ), 'autoconfigure', 'zerospam' ),
142
  esc_url( ZEROSPAM_URL . 'product/premium/' )
143
  ),
144
  );
@@ -154,7 +154,7 @@ class Admin {
154
  'content' => sprintf(
155
  wp_kses(
156
  /* translators: %1$s: Replaced with the Zero Spam settings page URL */
157
- __( '<strong>Thanks for installing WordPress Zero Spam!</strong> Visit the <a href="%1$s">setting page</a> to configure your site\'s protection level or <strong><a href="%2$s">click here</a> to automatically configure recommended settings</strong>. For enhanced protection, get a <a href="%3$s" target="_blank">Zero Spam premium license</a>.', 'zerospam' ),
158
  array(
159
  'strong' => array(),
160
  'a' => array(
@@ -223,7 +223,7 @@ class Admin {
223
  * @param array $links An array of plugin action links.
224
  */
225
  public function plugin_action_links( $links ) {
226
- $settings_link = sprintf( '<a href="%1$s">%2$s</a>', admin_url( 'options-general.php?page=wordpress-zero-spam-settings' ), __( 'Settings', 'zerospam' ) );
227
 
228
  array_unshift( $links, $settings_link );
229
 
@@ -245,7 +245,7 @@ class Admin {
245
  public function plugin_row_meta( $plugin_meta, $plugin_file ) {
246
  if ( ZEROSPAM_PLUGIN_BASE === $plugin_file ) {
247
  $row_meta = array(
248
- 'docs' => '<a href="https://github.com/bmarshall511/wordpress-zero-spam/wiki" aria-label="' . esc_attr( __( 'View WordPress Zero Spam Documentation', 'zerospam' ) ) . '" target="_blank">' . __( 'Docs & FAQs', 'zerospam' ) . '</a>',
249
  );
250
 
251
  $plugin_meta = array_merge( $plugin_meta, $row_meta );
@@ -270,8 +270,8 @@ class Admin {
270
  if ( $is_zerospam_screen ) {
271
  $footer_text = sprintf(
272
  /* translators: 1: Elementor, 2: Link to plugin review */
273
- __( 'Enjoyed %1$s? Please leave us a %2$s rating. We really appreciate your support!', 'zerospam' ),
274
- '<strong>' . __( 'WordPress Zero Spam', 'zerospam' ) . '</strong>',
275
  '<a href="https://wordpress.org/plugins/zero-spam/#reviews" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
276
  );
277
  }
48
  if ( ! empty( array_intersect( $roles, $selected_user_roles ) ) ) {
49
  wp_add_dashboard_widget(
50
  'zerospam_dashboard_widget',
51
+ __( 'WordPress Zero Spam', 'zero-spam' ),
52
  array( $this, 'dashboard_widget' )
53
  );
54
  }
70
  echo sprintf(
71
  wp_kses(
72
  /* translators: %s: Zero Spam API link */
73
+ __( '<strong>Super-charge WordPress Zero Spam with a <a href="%s" target="_blank" rel="noopener noreferrer">Zero Spam API License</a>.</strong>', 'zero-spam' ),
74
  array(
75
  'a' => array(
76
  'target' => array(),
88
  echo sprintf(
89
  wp_kses(
90
  /* translators: %s: Zero Spam API link */
91
+ __( '<p><strong>Enable enhanced protection</strong> and super-charge your site with the power of a global detection network that monitors traffic and usage in real-time to detect malicious activity.</p>', 'zero-spam' ),
92
  array(
93
  'a' => array(
94
  'target' => array(),
102
  )
103
  );
104
  ?>
105
+ <a href="<?php echo esc_url( ZEROSPAM_URL ); ?>subscribe/?utm_source=wordpress_zero_spam&utm_medium=dashboard_widget&utm_campaign=license" target="_blank" rel="noreferrer noopener" class="button button-primary"><?php esc_html_e( 'Get a Zero Spam License', 'zero-spam' ); ?></a>
106
+ <a href="<?php echo esc_url( ZEROSPAM_URL ); ?>?utm_source=wordpress_zero_spam&utm_medium=dashboard_widget&utm_campaign=license" target="_blank" rel="noreferrer noopener" class="button button-secondary"><?php esc_html_e( 'Learn More', 'zero-spam' ); ?></a>
107
  </div>
108
  <?php
109
  }
118
  $messages = array();
119
 
120
  // Check Zero Spam license key.
121
+ $zerospam_protection = \ZeroSpam\Core\Settings::get_settings( 'zero-spam' );
122
  if ( 'enabled' === $zerospam_protection ) {
123
  $zerospam_license_key = \ZeroSpam\Core\Settings::get_settings( 'zerospam_license' );
124
  if ( ! $zerospam_license_key ) {
128
  'content' => sprintf(
129
  wp_kses(
130
  /* translators: %1$s: Replaced with the Zero Spam settings page URL */
131
+ __( 'Zero Spam Enhanced Protection is currenlty enabled, but <strong>missing a valid license key</strong>. <a href="%1$s">Add your license key</a> to enable enhanced site protection.', 'zero-spam' ),
132
  array(
133
  'strong' => array(),
134
  'a' => array(
138
  )
139
  ),
140
  esc_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings' ) ),
141
+ wp_nonce_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=autoconfigure' ), 'autoconfigure', 'zero-spam' ),
142
  esc_url( ZEROSPAM_URL . 'product/premium/' )
143
  ),
144
  );
154
  'content' => sprintf(
155
  wp_kses(
156
  /* translators: %1$s: Replaced with the Zero Spam settings page URL */
157
+ __( '<strong>Thanks for installing WordPress Zero Spam!</strong> Visit the <a href="%1$s">setting page</a> to configure your site\'s protection level or <strong><a href="%2$s">click here</a> to automatically configure recommended settings</strong>. For enhanced protection, get a <a href="%3$s" target="_blank">Zero Spam premium license</a>.', 'zero-spam' ),
158
  array(
159
  'strong' => array(),
160
  'a' => array(
223
  * @param array $links An array of plugin action links.
224
  */
225
  public function plugin_action_links( $links ) {
226
+ $settings_link = sprintf( '<a href="%1$s">%2$s</a>', admin_url( 'options-general.php?page=wordpress-zero-spam-settings' ), __( 'Settings', 'zero-spam' ) );
227
 
228
  array_unshift( $links, $settings_link );
229
 
245
  public function plugin_row_meta( $plugin_meta, $plugin_file ) {
246
  if ( ZEROSPAM_PLUGIN_BASE === $plugin_file ) {
247
  $row_meta = array(
248
+ 'docs' => '<a href="https://github.com/bmarshall511/wordpress-zero-spam/wiki" aria-label="' . esc_attr( __( 'View WordPress Zero Spam Documentation', 'zero-spam' ) ) . '" target="_blank">' . __( 'Docs & FAQs', 'zero-spam' ) . '</a>',
249
  );
250
 
251
  $plugin_meta = array_merge( $plugin_meta, $row_meta );
270
  if ( $is_zerospam_screen ) {
271
  $footer_text = sprintf(
272
  /* translators: 1: Elementor, 2: Link to plugin review */
273
+ __( 'Enjoyed %1$s? Please leave us a %2$s rating. We really appreciate your support!', 'zero-spam' ),
274
+ '<strong>' . __( 'WordPress Zero Spam', 'zero-spam' ) . '</strong>',
275
  '<a href="https://wordpress.org/plugins/zero-spam/#reviews" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
276
  );
277
  }
core/admin/class-dashboard.php CHANGED
@@ -13,14 +13,12 @@ use ZeroSpam;
13
  defined( 'ABSPATH' ) || die();
14
 
15
  /**
16
- * Dashboard.
17
- *
18
- * @since 5.0.0
19
  */
20
  class Dashboard {
21
 
22
  /**
23
- * Dashboard constructor
24
  */
25
  public function __construct() {
26
  add_action( 'admin_init', array( $this, 'admin_init' ) );
@@ -35,13 +33,11 @@ class Dashboard {
35
  }
36
 
37
  /**
38
- * Block IP handler.
39
- *
40
- * @since 5.0.0
41
- * @access public
42
  */
43
  public function block_ip() {
44
- $url = parse_url( $_POST['redirect'] );
 
45
  $url['query'] = str_replace(
46
  array(
47
  'zerospam-success=1',
@@ -59,7 +55,7 @@ class Dashboard {
59
 
60
  $url = $url['scheme'] . '://' . $url['host'] . ( ! empty( $url['port'] ) ? ':' . $url['port'] : '' ) . $url['path'] . '?' . $url['query'];
61
 
62
- if ( ! isset( $_POST['zerospam'] ) || ! wp_verify_nonce( $_POST['zerospam'], 'zerospam' ) ) {
63
  wp_redirect( $url . '&zerospam-error=1' );
64
  exit;
65
  }
@@ -135,16 +131,13 @@ class Dashboard {
135
  }
136
 
137
  /**
138
- * Admin menu.
139
- *
140
- * @since 5.0.0
141
- * @access public
142
  */
143
  public function admin_menu() {
144
  add_submenu_page(
145
  'index.php',
146
- __( 'WordPress Zero Spam Dashboard', 'zerospam' ),
147
- __( 'Zero Spam', 'zerospam' ),
148
  'manage_options',
149
  'wordpress-zero-spam-dashboard',
150
  array( $this, 'dashboard_page' )
@@ -152,10 +145,7 @@ class Dashboard {
152
  }
153
 
154
  /**
155
- * Dashboard page.
156
- *
157
- * @since 5.0.0
158
- * @access public
159
  */
160
  public function dashboard_page() {
161
  if ( ! current_user_can( 'manage_options' ) ) {
@@ -172,35 +162,35 @@ class Dashboard {
172
  <?php
173
  switch( intval( $_GET['zerospam-error'] ) ) :
174
  case 1:
175
- esc_html_e( 'Please enter a valid IP address.', 'zerospam' );
176
  break;
177
  case 2:
178
- esc_html_e( 'Please select a valid type.', 'zerospam' );
179
  break;
180
  case 3:
181
- esc_html_e( 'Please select a date & time when the temporary block should end.', 'zerospam' );
182
  break;
183
  case 4:
184
- esc_html_e( 'There was a problem adding the record to the database. Please try again.', 'zerospam' );
185
  break;
186
  case 5:
187
- esc_html_e( 'Temporary blocks require an end date.', 'zerospam' );
188
  break;
189
  case 6:
190
- esc_html_e( 'You must enter a valid location key (ex. US, TX, etc.).', 'zerospam' );
191
  break;
192
  case 7:
193
- esc_html_e( 'Missing required fields. Please try again.', 'zerospam' );
194
  break;
195
  endswitch;
196
  ?>
197
  </strong></p>
198
- <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'zerospam' ); ?></span></button>
199
  </div>
200
  <?php elseif ( ! empty( $_GET['zerospam-success'] ) ): ?>
201
  <div class="notice notice-success is-dismissible">
202
  <p><strong><?php _e( 'The blocked record has been successfully added.', 'wpzerospam' ); ?></strong></p>
203
- <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'zerospam' ); ?>.</span></button>
204
  </div>
205
  <?php endif; ?>
206
 
@@ -211,10 +201,10 @@ class Dashboard {
211
  }
212
  ?>
213
  <div class="nav-tab-wrapper">
214
- <a id="zerospam-settings-tab-stats" class="nav-tab<?php if ( 'stats' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=stats' ) ); ?>"><?php echo __( 'Statistics', 'zerospam' ); ?></a>
215
- <a id="zerospam-settings-tab-log" class="nav-tab<?php if ( 'log' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=log' ) ); ?>"><?php echo __( 'Log', 'zerospam' ); ?></a>
216
- <a id="zerospam-settings-tab-blocked-ips" class="nav-tab<?php if ( 'blocked' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=blocked' ) ); ?>"><?php echo __( 'Blocked IPs', 'zerospam' ); ?></a>
217
- <a id="zerospam-settings-tab-blocked-locations" class="nav-tab<?php if ( 'blocked-locations' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=blocked-locations' ) ); ?>"><?php echo __( 'Blocked Locations', 'zerospam' ); ?></a>
218
  </div>
219
 
220
  <div class="zerospam-tabs">
@@ -228,7 +218,7 @@ class Dashboard {
228
  echo '<div class="zerospam-module zerospam-module-map">';
229
  echo sprintf(
230
  wp_kses(
231
- __( '<h3>Detections World Map</h3>', 'zerospam' ),
232
  array(
233
  'h3' => array(),
234
  )
@@ -239,17 +229,17 @@ class Dashboard {
239
 
240
  ?>
241
  <div class="zerospam-module zerospam-module-ip">
242
- <h3><?php esc_html_e( 'Most Detections by IP Address', 'zerospam' ); ?></h3>
243
  <?php require ZEROSPAM_PATH . 'includes/templates/admin-ips.php'; ?>
244
  </div>
245
 
246
  <div class="zerospam-module zerospam-module-pie">
247
- <h3><?php esc_html_e( 'Detections by Location', 'zerospam' ); ?></h3>
248
  <?php require ZEROSPAM_PATH . 'includes/templates/admin-pie.php'; ?>
249
  </div>
250
 
251
  <div class="zerospam-module zerospam-module-line-chart">
252
- <h3><?php esc_html_e( 'Detection History', 'zerospam' ); ?></h3>
253
  <?php require ZEROSPAM_PATH . 'includes/templates/admin-line-chart.php'; ?>
254
  </div>
255
  <?php
@@ -262,7 +252,7 @@ class Dashboard {
262
  echo sprintf(
263
  wp_kses(
264
  /* translators: %s: url */
265
- __( 'WordPress Zero Spam logging is currently <strong>disabled</strong>. It can be enabled on the <a href="%s">settings page</a>.', 'zerospam' ),
266
  array(
267
  'strong' => array(),
268
  'a' => array(
@@ -283,7 +273,7 @@ class Dashboard {
283
  <div id="tab-log" class="zerospam-tab is-active">
284
  <?php if ( 'enabled' === ZeroSpam\Core\Settings::get_settings( 'log_blocked_ips' ) ) : ?>
285
 
286
- <h2><?php echo __( 'WordPress Zero Spam Log', 'zerospam' ); ?></h2>
287
  <?php
288
  $table_data = new ZeroSpam\Core\Admin\Tables\LogTable();
289
  $table_data->prepare_items();
@@ -291,7 +281,7 @@ class Dashboard {
291
  <form id="zerospam-log-table" method="post">
292
  <?php wp_nonce_field( 'zerospam_nonce', 'zerospam_nonce' ); ?>
293
  <input type="hidden" name="paged" value="1" />
294
- <?php $table_data->search_box( __( 'Search IPs', 'zerospam' ), 'search-ip' ); ?>
295
  <?php $table_data->display(); ?>
296
  </form>
297
 
@@ -301,7 +291,7 @@ class Dashboard {
301
  echo sprintf(
302
  wp_kses(
303
  /* translators: %s: url */
304
- __( 'WordPress Zero Spam logging is currently <strong>disabled</strong>. It can be enabled on the <a href="%s">settings page</a>.', 'zerospam' ),
305
  array(
306
  'strong' => array(),
307
  'a' => array(
@@ -319,14 +309,14 @@ class Dashboard {
319
 
320
  <?php if ( 'blocked' === $active_tab ) : ?>
321
  <div id="tab-blocked-ips" class="zerospam-tab is-active">
322
- <h2><?php echo __( 'Blocked IPs', 'zerospam' ); ?></h2>
323
  <?php
324
  $block_method = \ZeroSpam\Core\Settings::get_settings( 'block_method' );
325
  if ( ! empty( $block_method ) && 'php' !== $block_method ) :
326
  echo sprintf(
327
  wp_kses(
328
  /* translators: %s: url */
329
- __( '<p>When using .htaccess &amp; due to <a href="%s" target="_blank" rel="noreferrer noopener">character limit restrictions</a>, <strong>no more than 170 blocked IP addresses recommended</strong>.</p>', 'zerospam' ),
330
  array(
331
  'strong' => array(),
332
  'a' => array(
@@ -346,7 +336,7 @@ class Dashboard {
346
  <form id="zerospam-blocked-table" method="post">
347
  <?php wp_nonce_field( 'zerospam_nonce', 'zerospam_nonce' ); ?>
348
  <input type="hidden" name="paged" value="1" />
349
- <?php $table_data->search_box( __( 'Search IPs', 'zerospam' ), 'search-ip' ); ?>
350
  <?php $table_data->display(); ?>
351
  </form>
352
  </div>
@@ -354,13 +344,13 @@ class Dashboard {
354
 
355
  <?php if ( 'blocked-locations' === $active_tab ) : ?>
356
  <div id="tab-blocked-locations" class="zerospam-tab is-active">
357
- <h2><?php echo __( 'Blocked Locations', 'zerospam' ); ?></h2>
358
  <?php
359
  if (
360
  ! ZeroSpam\Core\Settings::get_settings( 'ipstack_api' ) &&
361
  ! ZeroSpam\Core\Settings::get_settings( 'ipinfo_access_token' )
362
  ) {
363
- _e( '<strong>Blocking locations is currently disabled.</strong> A valid ipstack API key or IPinfo access token is required (defined in the plugin settings).', 'zerospam' );
364
  }
365
 
366
  $table_data = new ZeroSpam\Core\Admin\Tables\BlockedLocations();
@@ -369,7 +359,7 @@ class Dashboard {
369
  <form id="zerospam-blocked-table" method="post">
370
  <?php wp_nonce_field( 'zerospam_nonce', 'zerospam_nonce' ); ?>
371
  <input type="hidden" name="paged" value="1" />
372
- <?php $table_data->search_box( __( 'Search IPs', 'zerospam' ), 'search-ip' ); ?>
373
  <?php $table_data->display(); ?>
374
  </form>
375
  </div>
@@ -377,10 +367,10 @@ class Dashboard {
377
  </div>
378
 
379
  <div class="zerospam-modal zerospam-modal-block" id="zerospam-block-ip">
380
- <button class="zerospam-close-modal" aria-label="<?php echo esc_attr( __( 'Close Modal', 'zerospam' ) ); ?>"></button>
381
  <div class="zerospam-modal-details">
382
  <div class="zerospam-modal-title">
383
- <h3><?php echo __( 'Add/Update Blocked IP', 'zerospam' ); ?></h3>
384
  </div>
385
  <div class="zerospam-modal-subtitle">
386
 
@@ -391,10 +381,10 @@ class Dashboard {
391
  </div>
392
 
393
  <div class="zerospam-modal zerospam-modal-block" id="zerospam-block-location">
394
- <button class="zerospam-close-modal" aria-label="<?php echo esc_attr( __( 'Close Modal', 'zerospam' ) ); ?>"></button>
395
  <div class="zerospam-modal-details">
396
  <div class="zerospam-modal-title">
397
- <h3><?php echo __( 'Add/Update Blocked Location', 'zerospam' ); ?></h3>
398
  </div>
399
  <div class="zerospam-modal-subtitle">
400
 
13
  defined( 'ABSPATH' ) || die();
14
 
15
  /**
16
+ * Admin Dashboard
 
 
17
  */
18
  class Dashboard {
19
 
20
  /**
21
+ * Constructor
22
  */
23
  public function __construct() {
24
  add_action( 'admin_init', array( $this, 'admin_init' ) );
33
  }
34
 
35
  /**
36
+ * Block IP handler
 
 
 
37
  */
38
  public function block_ip() {
39
+ $url = parse_url( sanitize_url( $_POST['redirect'] ) );
40
+
41
  $url['query'] = str_replace(
42
  array(
43
  'zerospam-success=1',
55
 
56
  $url = $url['scheme'] . '://' . $url['host'] . ( ! empty( $url['port'] ) ? ':' . $url['port'] : '' ) . $url['path'] . '?' . $url['query'];
57
 
58
+ if ( ! isset( $_POST['zerospam'] ) || ! wp_verify_nonce( $_POST['zerospam'], 'zero-spam' ) ) {
59
  wp_redirect( $url . '&zerospam-error=1' );
60
  exit;
61
  }
131
  }
132
 
133
  /**
134
+ * Admin menu
 
 
 
135
  */
136
  public function admin_menu() {
137
  add_submenu_page(
138
  'index.php',
139
+ __( 'Zero Spam for WordPress Dashboard', 'zero-spam' ),
140
+ __( 'Zero Spam', 'zero-spam' ),
141
  'manage_options',
142
  'wordpress-zero-spam-dashboard',
143
  array( $this, 'dashboard_page' )
145
  }
146
 
147
  /**
148
+ * Dashboard page
 
 
 
149
  */
150
  public function dashboard_page() {
151
  if ( ! current_user_can( 'manage_options' ) ) {
162
  <?php
163
  switch( intval( $_GET['zerospam-error'] ) ) :
164
  case 1:
165
+ esc_html_e( 'Please enter a valid IP address.', 'zero-spam' );
166
  break;
167
  case 2:
168
+ esc_html_e( 'Please select a valid type.', 'zero-spam' );
169
  break;
170
  case 3:
171
+ esc_html_e( 'Please select a date & time when the temporary block should end.', 'zero-spam' );
172
  break;
173
  case 4:
174
+ esc_html_e( 'There was a problem adding the record to the database. Please try again.', 'zero-spam' );
175
  break;
176
  case 5:
177
+ esc_html_e( 'Temporary blocks require an end date.', 'zero-spam' );
178
  break;
179
  case 6:
180
+ esc_html_e( 'You must enter a valid location key (ex. US, TX, etc.).', 'zero-spam' );
181
  break;
182
  case 7:
183
+ esc_html_e( 'Missing required fields. Please try again.', 'zero-spam' );
184
  break;
185
  endswitch;
186
  ?>
187
  </strong></p>
188
+ <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'zero-spam' ); ?></span></button>
189
  </div>
190
  <?php elseif ( ! empty( $_GET['zerospam-success'] ) ): ?>
191
  <div class="notice notice-success is-dismissible">
192
  <p><strong><?php _e( 'The blocked record has been successfully added.', 'wpzerospam' ); ?></strong></p>
193
+ <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'zero-spam' ); ?>.</span></button>
194
  </div>
195
  <?php endif; ?>
196
 
201
  }
202
  ?>
203
  <div class="nav-tab-wrapper">
204
+ <a id="zerospam-settings-tab-stats" class="nav-tab<?php if ( 'stats' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=stats' ) ); ?>"><?php echo __( 'Statistics', 'zero-spam' ); ?></a>
205
+ <a id="zerospam-settings-tab-log" class="nav-tab<?php if ( 'log' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=log' ) ); ?>"><?php echo __( 'Log', 'zero-spam' ); ?></a>
206
+ <a id="zerospam-settings-tab-blocked-ips" class="nav-tab<?php if ( 'blocked' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=blocked' ) ); ?>"><?php echo __( 'Blocked IPs', 'zero-spam' ); ?></a>
207
+ <a id="zerospam-settings-tab-blocked-locations" class="nav-tab<?php if ( 'blocked-locations' === $active_tab ) : ?> nav-tab-active<?php endif; ?>" href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=blocked-locations' ) ); ?>"><?php echo __( 'Blocked Locations', 'zero-spam' ); ?></a>
208
  </div>
209
 
210
  <div class="zerospam-tabs">
218
  echo '<div class="zerospam-module zerospam-module-map">';
219
  echo sprintf(
220
  wp_kses(
221
+ __( '<h3>Detections World Map</h3>', 'zero-spam' ),
222
  array(
223
  'h3' => array(),
224
  )
229
 
230
  ?>
231
  <div class="zerospam-module zerospam-module-ip">
232
+ <h3><?php esc_html_e( 'Most Detections by IP Address', 'zero-spam' ); ?></h3>
233
  <?php require ZEROSPAM_PATH . 'includes/templates/admin-ips.php'; ?>
234
  </div>
235
 
236
  <div class="zerospam-module zerospam-module-pie">
237
+ <h3><?php esc_html_e( 'Detections by Location', 'zero-spam' ); ?></h3>
238
  <?php require ZEROSPAM_PATH . 'includes/templates/admin-pie.php'; ?>
239
  </div>
240
 
241
  <div class="zerospam-module zerospam-module-line-chart">
242
+ <h3><?php esc_html_e( 'Detection History', 'zero-spam' ); ?></h3>
243
  <?php require ZEROSPAM_PATH . 'includes/templates/admin-line-chart.php'; ?>
244
  </div>
245
  <?php
252
  echo sprintf(
253
  wp_kses(
254
  /* translators: %s: url */
255
+ __( 'Zero Spam for WordPress logging is currently <strong>disabled</strong>. It can be enabled on the <a href="%s">settings page</a>.', 'zero-spam' ),
256
  array(
257
  'strong' => array(),
258
  'a' => array(
273
  <div id="tab-log" class="zerospam-tab is-active">
274
  <?php if ( 'enabled' === ZeroSpam\Core\Settings::get_settings( 'log_blocked_ips' ) ) : ?>
275
 
276
+ <h2><?php echo __( 'Zero Spam for WordPress Log', 'zero-spam' ); ?></h2>
277
  <?php
278
  $table_data = new ZeroSpam\Core\Admin\Tables\LogTable();
279
  $table_data->prepare_items();
281
  <form id="zerospam-log-table" method="post">
282
  <?php wp_nonce_field( 'zerospam_nonce', 'zerospam_nonce' ); ?>
283
  <input type="hidden" name="paged" value="1" />
284
+ <?php $table_data->search_box( __( 'Search IPs', 'zero-spam' ), 'search-ip' ); ?>
285
  <?php $table_data->display(); ?>
286
  </form>
287
 
291
  echo sprintf(
292
  wp_kses(
293
  /* translators: %s: url */
294
+ __( 'Zero Spam for WordPress logging is currently <strong>disabled</strong>. It can be enabled on the <a href="%s">settings page</a>.', 'zero-spam' ),
295
  array(
296
  'strong' => array(),
297
  'a' => array(
309
 
310
  <?php if ( 'blocked' === $active_tab ) : ?>
311
  <div id="tab-blocked-ips" class="zerospam-tab is-active">
312
+ <h2><?php echo __( 'Blocked IPs', 'zero-spam' ); ?></h2>
313
  <?php
314
  $block_method = \ZeroSpam\Core\Settings::get_settings( 'block_method' );
315
  if ( ! empty( $block_method ) && 'php' !== $block_method ) :
316
  echo sprintf(
317
  wp_kses(
318
  /* translators: %s: url */
319
+ __( '<p>When using .htaccess &amp; due to <a href="%s" target="_blank" rel="noreferrer noopener">character limit restrictions</a>, <strong>no more than 170 blocked IP addresses recommended</strong>.</p>', 'zero-spam' ),
320
  array(
321
  'strong' => array(),
322
  'a' => array(
336
  <form id="zerospam-blocked-table" method="post">
337
  <?php wp_nonce_field( 'zerospam_nonce', 'zerospam_nonce' ); ?>
338
  <input type="hidden" name="paged" value="1" />
339
+ <?php $table_data->search_box( __( 'Search IPs', 'zero-spam' ), 'search-ip' ); ?>
340
  <?php $table_data->display(); ?>
341
  </form>
342
  </div>
344
 
345
  <?php if ( 'blocked-locations' === $active_tab ) : ?>
346
  <div id="tab-blocked-locations" class="zerospam-tab is-active">
347
+ <h2><?php echo __( 'Blocked Locations', 'zero-spam' ); ?></h2>
348
  <?php
349
  if (
350
  ! ZeroSpam\Core\Settings::get_settings( 'ipstack_api' ) &&
351
  ! ZeroSpam\Core\Settings::get_settings( 'ipinfo_access_token' )
352
  ) {
353
+ _e( '<strong>Blocking locations is currently disabled.</strong> A valid ipstack API key or IPinfo access token is required (defined in the plugin settings).', 'zero-spam' );
354
  }
355
 
356
  $table_data = new ZeroSpam\Core\Admin\Tables\BlockedLocations();
359
  <form id="zerospam-blocked-table" method="post">
360
  <?php wp_nonce_field( 'zerospam_nonce', 'zerospam_nonce' ); ?>
361
  <input type="hidden" name="paged" value="1" />
362
+ <?php $table_data->search_box( __( 'Search IPs', 'zero-spam' ), 'search-ip' ); ?>
363
  <?php $table_data->display(); ?>
364
  </form>
365
  </div>
367
  </div>
368
 
369
  <div class="zerospam-modal zerospam-modal-block" id="zerospam-block-ip">
370
+ <button class="zerospam-close-modal" aria-label="<?php echo esc_attr( __( 'Close Modal', 'zero-spam' ) ); ?>"></button>
371
  <div class="zerospam-modal-details">
372
  <div class="zerospam-modal-title">
373
+ <h3><?php echo __( 'Add/Update Blocked IP', 'zero-spam' ); ?></h3>
374
  </div>
375
  <div class="zerospam-modal-subtitle">
376
 
381
  </div>
382
 
383
  <div class="zerospam-modal zerospam-modal-block" id="zerospam-block-location">
384
+ <button class="zerospam-close-modal" aria-label="<?php echo esc_attr( __( 'Close Modal', 'zero-spam' ) ); ?>"></button>
385
  <div class="zerospam-modal-details">
386
  <div class="zerospam-modal-title">
387
+ <h3><?php echo __( 'Add/Update Blocked Location', 'zero-spam' ); ?></h3>
388
  </div>
389
  <div class="zerospam-modal-subtitle">
390
 
core/admin/class-settings.php CHANGED
@@ -87,11 +87,11 @@ class Settings {
87
  if (
88
  ! empty( $_REQUEST['zerospam-action'] ) &&
89
  'autoconfigure' === $_REQUEST['zerospam-action'] &&
90
- check_admin_referer( 'autoconfigure', 'zerospam' )
91
  ) {
92
  \ZeroSpam\Core\Settings::auto_configure();
93
 
94
- $message = __( 'WordPress Zero Spam has successfully been auto-configured with the recommended settings.', 'zerospam' );
95
  $redirect_url = 'options-general.php?page=wordpress-zero-spam-settings&tab=settings&zerospam-msg=' . $message;
96
 
97
  wp_safe_redirect( $redirect_url );
@@ -99,11 +99,11 @@ class Settings {
99
  } elseif (
100
  ! empty( $_REQUEST['zerospam-action'] ) &&
101
  'update-blocked-emails' === $_REQUEST['zerospam-action'] &&
102
- check_admin_referer( 'update-blocked-emails', 'zerospam' )
103
  ) {
104
  \ZeroSpam\Core\Settings::update_blocked_email_domains();
105
 
106
- $message = __( 'WordPress Zero Spam\'s blocked email domains have been successfully updated to the recommended.', 'zerospam' );
107
  $redirect_url = 'options-general.php?page=wordpress-zero-spam-settings&tab=settings&zerospam-msg=' . $message;
108
 
109
  wp_safe_redirect( $redirect_url );
@@ -111,11 +111,11 @@ class Settings {
111
  } elseif (
112
  ! empty( $_REQUEST['zerospam-action'] ) &&
113
  'regenerate-honeypot' === $_REQUEST['zerospam-action'] &&
114
- check_admin_referer( 'regenerate-honeypot', 'zerospam' )
115
  ) {
116
  self::regenerate_honeypot();
117
 
118
- $message = __( 'WordPress Zero Spam\'s honeypot ID has been successfully reset.', 'zerospam' );
119
  $redirect_url = 'options-general.php?page=wordpress-zero-spam-settings&tab=settings&zerospam-msg=' . $message;
120
 
121
  wp_safe_redirect( $redirect_url );
@@ -123,11 +123,11 @@ class Settings {
123
  } elseif (
124
  ! empty( $_REQUEST['zerospam-action'] ) &&
125
  'update-disallowed-words' === $_REQUEST['zerospam-action'] &&
126
- check_admin_referer( 'update-disallowed-words', 'zerospam' )
127
  ) {
128
  \ZeroSpam\Core\Settings::update_disallowed_words();
129
 
130
- $message = __( 'WordPress\'s disallowed words list has been successfully updated to the recommended.', 'zerospam' );
131
  $redirect_url = 'options-general.php?page=wordpress-zero-spam-settings&tab=settings&zerospam-msg=' . $message;
132
 
133
  wp_safe_redirect( $redirect_url );
@@ -135,11 +135,11 @@ class Settings {
135
  } elseif (
136
  ! empty( $_REQUEST['zerospam-action'] ) &&
137
  'delete-error-log' === $_REQUEST['zerospam-action'] &&
138
- check_admin_referer( 'delete-error-log', 'zerospam' )
139
  ) {
140
  \ZeroSpam\Core\Utilities::delete_error_log();
141
 
142
- $message = __( 'WordPress Zero Spam\'s error log has been successfully deleted.', 'zerospam' );
143
  $redirect_url = 'options-general.php?page=wordpress-zero-spam-settings&tab=error&zerospam-msg=' . $message;
144
 
145
  wp_safe_redirect( $redirect_url );
@@ -155,8 +155,8 @@ class Settings {
155
 
156
  add_submenu_page(
157
  'options-general.php',
158
- __( 'Zero Spam Settings', 'zerospam' ),
159
- __( 'Zero Spam', 'zerospam' ),
160
  'manage_options',
161
  'wordpress-zero-spam-settings',
162
  array( $this, 'settings_page' )
@@ -498,18 +498,18 @@ class Settings {
498
 
499
  $base_admin_link = 'options-general.php?page=wordpress-zero-spam-settings';
500
  // @codingStandardsIgnoreLine
501
- $current_tab = ! empty( $_REQUEST['tab'] ) ? esc_html( $_REQUEST['tab'] ) : 'settings';
502
  $admin_tabs = array(
503
  'settings' => array(
504
- 'title' => __( 'Settings', 'zerospam' ),
505
  'template' => 'settings',
506
  ),
507
  'export' => array(
508
- 'title' => __( 'Export/Import Settings', 'zerospam' ),
509
  'template' => 'export',
510
  ),
511
  'error' => array(
512
- 'title' => __( 'Error Log', 'zerospam' ),
513
  'template' => 'errors',
514
  ),
515
  );
87
  if (
88
  ! empty( $_REQUEST['zerospam-action'] ) &&
89
  'autoconfigure' === $_REQUEST['zerospam-action'] &&
90
+ check_admin_referer( 'autoconfigure', 'zero-spam' )
91
  ) {
92
  \ZeroSpam\Core\Settings::auto_configure();
93
 
94
+ $message = __( 'WordPress Zero Spam has successfully been auto-configured with the recommended settings.', 'zero-spam' );
95
  $redirect_url = 'options-general.php?page=wordpress-zero-spam-settings&tab=settings&zerospam-msg=' . $message;
96
 
97
  wp_safe_redirect( $redirect_url );
99
  } elseif (
100
  ! empty( $_REQUEST['zerospam-action'] ) &&
101
  'update-blocked-emails' === $_REQUEST['zerospam-action'] &&
102
+ check_admin_referer( 'update-blocked-emails', 'zero-spam' )
103
  ) {
104
  \ZeroSpam\Core\Settings::update_blocked_email_domains();
105
 
106
+ $message = __( 'WordPress Zero Spam\'s blocked email domains have been successfully updated to the recommended.', 'zero-spam' );
107
  $redirect_url = 'options-general.php?page=wordpress-zero-spam-settings&tab=settings&zerospam-msg=' . $message;
108
 
109
  wp_safe_redirect( $redirect_url );
111
  } elseif (
112
  ! empty( $_REQUEST['zerospam-action'] ) &&
113
  'regenerate-honeypot' === $_REQUEST['zerospam-action'] &&
114
+ check_admin_referer( 'regenerate-honeypot', 'zero-spam' )
115
  ) {
116
  self::regenerate_honeypot();
117
 
118
+ $message = __( 'WordPress Zero Spam\'s honeypot ID has been successfully reset.', 'zero-spam' );
119
  $redirect_url = 'options-general.php?page=wordpress-zero-spam-settings&tab=settings&zerospam-msg=' . $message;
120
 
121
  wp_safe_redirect( $redirect_url );
123
  } elseif (
124
  ! empty( $_REQUEST['zerospam-action'] ) &&
125
  'update-disallowed-words' === $_REQUEST['zerospam-action'] &&
126
+ check_admin_referer( 'update-disallowed-words', 'zero-spam' )
127
  ) {
128
  \ZeroSpam\Core\Settings::update_disallowed_words();
129
 
130
+ $message = __( 'WordPress\'s disallowed words list has been successfully updated to the recommended.', 'zero-spam' );
131
  $redirect_url = 'options-general.php?page=wordpress-zero-spam-settings&tab=settings&zerospam-msg=' . $message;
132
 
133
  wp_safe_redirect( $redirect_url );
135
  } elseif (
136
  ! empty( $_REQUEST['zerospam-action'] ) &&
137
  'delete-error-log' === $_REQUEST['zerospam-action'] &&
138
+ check_admin_referer( 'delete-error-log', 'zero-spam' )
139
  ) {
140
  \ZeroSpam\Core\Utilities::delete_error_log();
141
 
142
+ $message = __( 'WordPress Zero Spam\'s error log has been successfully deleted.', 'zero-spam' );
143
  $redirect_url = 'options-general.php?page=wordpress-zero-spam-settings&tab=error&zerospam-msg=' . $message;
144
 
145
  wp_safe_redirect( $redirect_url );
155
 
156
  add_submenu_page(
157
  'options-general.php',
158
+ __( 'Zero Spam Settings', 'zero-spam' ),
159
+ __( 'Zero Spam', 'zero-spam' ),
160
  'manage_options',
161
  'wordpress-zero-spam-settings',
162
  array( $this, 'settings_page' )
498
 
499
  $base_admin_link = 'options-general.php?page=wordpress-zero-spam-settings';
500
  // @codingStandardsIgnoreLine
501
+ $current_tab = ! empty( $_REQUEST['tab'] ) ? sanitize_text_field( $_REQUEST['tab'] ) : 'settings';
502
  $admin_tabs = array(
503
  'settings' => array(
504
+ 'title' => __( 'Settings', 'zero-spam' ),
505
  'template' => 'settings',
506
  ),
507
  'export' => array(
508
+ 'title' => __( 'Export/Import Settings', 'zero-spam' ),
509
  'template' => 'export',
510
  ),
511
  'error' => array(
512
+ 'title' => __( 'Error Log', 'zero-spam' ),
513
  'template' => 'errors',
514
  ),
515
  );
core/admin/tables/class-blockedlocations.php CHANGED
@@ -19,26 +19,20 @@ defined( 'ABSPATH' ) || die();
19
  class BlockedLocations extends WP_List_Table {
20
 
21
  /**
22
- * Log table constructor.
23
- *
24
- * @since 5.0.0
25
- * @access public
26
  */
27
  public function __construct() {
28
  global $status, $page;
29
 
30
  $args = array(
31
- 'singular' => __( 'WordPress Zero Spam Blocked Location', 'zerospam' ),
32
- 'plural' => __( 'WordPress Zero Spam Blocked Locations', 'zerospam' ),
33
  );
34
  parent::__construct( $args );
35
  }
36
 
37
  /**
38
- * Column values.
39
- *
40
- * @since 5.0.0
41
- * @access public
42
  */
43
  public function column_default( $item, $column_name ) {
44
  switch ( $column_name ) {
@@ -83,7 +77,7 @@ class BlockedLocations extends WP_List_Table {
83
  data-end="<?php echo esc_attr( gmdate( 'Y-m-d', strtotime( $item['end_block'] ) ) ); ?>T<?php echo esc_attr( gmdate( 'H:i', strtotime( $item['end_block'] ) ) ); ?>"
84
  data-type="<?php echo esc_attr( $item['blocked_type'] ); ?>"
85
  >
86
- <?php _e( 'Update Block', 'zerospam' ); ?>
87
  </button>
88
  <?php
89
  return ob_get_clean();
@@ -98,35 +92,26 @@ class BlockedLocations extends WP_List_Table {
98
  }
99
 
100
  /**
101
- * Bulk actions.
102
- *
103
- * @since 5.0.0
104
- * @access public
105
  */
106
  public function get_bulk_actions() {
107
  $actions = array(
108
- 'delete' => __( 'Delete Selected', 'zerospam' ),
109
- //'delete_all' => __( 'Delete All Locations', 'zerospam' ),
110
  );
111
 
112
  return $actions;
113
  }
114
 
115
  /**
116
- * Hidable columns.
117
- *
118
- * @since 5.0.0
119
- * @access public
120
  */
121
  public function get_hidden_columns() {
122
  return array();
123
  }
124
 
125
  /**
126
- * Prepare log items.
127
- *
128
- * @since 5.0.0
129
- * @access public
130
  */
131
  public function prepare_items( $args = array() ) {
132
  $this->process_bulk_action();
@@ -205,10 +190,7 @@ class BlockedLocations extends WP_List_Table {
205
  }
206
 
207
  /**
208
- * Add more filters.
209
- *
210
- * @since 5.0.0
211
- * @access public
212
  */
213
  public function extra_tablenav( $which ) {
214
  if ( 'top' !== $which ) {
@@ -218,51 +200,45 @@ class BlockedLocations extends WP_List_Table {
218
  <div class="alignleft actions">
219
  <?php
220
  /*
221
- echo '<label class="screen-reader-text" for="filter-by-type">' . __( 'Filter by type', 'zerospam' ) . '</label>';
222
  $options = apply_filters( 'zerospam_types', array() );
223
  $current_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
224
  ?>
225
  <select name="type" id="filter-by-type">
226
- <option value=""><?php _e( 'All types', 'zerospam' ); ?></option>
227
  <?php foreach ( $options as $key => $value ) : ?>
228
  <option<?php if ( $current_type === $key ) : ?> selected="selected"<?php endif; ?> value="<?php echo esc_attr( $key ); ?>"><?php echo $value; ?></option>
229
  <?php endforeach; ?>
230
  </select>
231
  <?php
232
- submit_button( __( 'Filter', 'zerospam' ), '', 'filter_action', false );
233
  */
234
  ?>
235
- <button class="button zerospam-block-location-trigger"><?php echo __( 'Add Blocked Location', 'zerospam' ); ?></button>
236
  </div>
237
  <?php
238
  }
239
 
240
  /**
241
- * Define table columns.
242
- *
243
- * @since 5.0.0
244
- * @access public
245
  */
246
  public function get_columns() {
247
  $columns = array(
248
  'cb' => '<input type="checkbox" />',
249
- 'date_added' => __( 'Date', 'zerospam' ),
250
- 'location' => __( 'Location', 'zerospam' ),
251
- 'blocked_type' => __( 'Type', 'zerospam' ),
252
- 'start_block' => __( 'Starts', 'zerospam' ),
253
- 'end_block' => __( 'Ends', 'zerospam' ),
254
- 'reason' => __( 'Reason', 'zerospam' ),
255
- 'actions' => __( 'Actions', 'zerospam' ),
256
  );
257
 
258
  return $columns;
259
  }
260
 
261
  /**
262
- * Sortable columns.
263
- *
264
- * @since 5.0.0
265
- * @access public
266
  */
267
  public function get_sortable_columns() {
268
  $sortable_columns = array(
@@ -277,10 +253,7 @@ class BlockedLocations extends WP_List_Table {
277
  }
278
 
279
  /**
280
- * Column contact.
281
- *
282
- * @since 5.0.0
283
- * @access public
284
  */
285
  public function column_cb( $item ) {
286
  return sprintf(
@@ -291,19 +264,16 @@ class BlockedLocations extends WP_List_Table {
291
  }
292
 
293
  /**
294
- * Process bulk actions.
295
- *
296
- * @since 5.0.0
297
- * @access public
298
  */
299
  public function process_bulk_action() {
300
  global $wpdb;
301
 
302
- $ids = ( isset( $_REQUEST['ids'] ) ) ? $_REQUEST['ids'] : '';
303
 
304
  switch( $this->current_action() ) {
305
  case 'delete':
306
- $nonce = ( isset( $_REQUEST['zerospam_nonce'] ) ) ? sanitize_text_field( $_REQUEST['zerospam_nonce'] ) : '';
307
  if ( ! wp_verify_nonce( $nonce, 'zerospam_nonce' ) ) {
308
  return false;
309
  }
19
  class BlockedLocations extends WP_List_Table {
20
 
21
  /**
22
+ * Log table constructor
 
 
 
23
  */
24
  public function __construct() {
25
  global $status, $page;
26
 
27
  $args = array(
28
+ 'singular' => __( 'WordPress Zero Spam Blocked Location', 'zero-spam' ),
29
+ 'plural' => __( 'WordPress Zero Spam Blocked Locations', 'zero-spam' ),
30
  );
31
  parent::__construct( $args );
32
  }
33
 
34
  /**
35
+ * Column values
 
 
 
36
  */
37
  public function column_default( $item, $column_name ) {
38
  switch ( $column_name ) {
77
  data-end="<?php echo esc_attr( gmdate( 'Y-m-d', strtotime( $item['end_block'] ) ) ); ?>T<?php echo esc_attr( gmdate( 'H:i', strtotime( $item['end_block'] ) ) ); ?>"
78
  data-type="<?php echo esc_attr( $item['blocked_type'] ); ?>"
79
  >
80
+ <?php esc_html_e( 'Update Block', 'zero-spam' ); ?>
81
  </button>
82
  <?php
83
  return ob_get_clean();
92
  }
93
 
94
  /**
95
+ * Bulk actions
 
 
 
96
  */
97
  public function get_bulk_actions() {
98
  $actions = array(
99
+ 'delete' => __( 'Delete Selected', 'zero-spam' ),
100
+ //'delete_all' => __( 'Delete All Locations', 'zero-spam' ),
101
  );
102
 
103
  return $actions;
104
  }
105
 
106
  /**
107
+ * Hidable columns
 
 
 
108
  */
109
  public function get_hidden_columns() {
110
  return array();
111
  }
112
 
113
  /**
114
+ * Prepare log items
 
 
 
115
  */
116
  public function prepare_items( $args = array() ) {
117
  $this->process_bulk_action();
190
  }
191
 
192
  /**
193
+ * Add more filters
 
 
 
194
  */
195
  public function extra_tablenav( $which ) {
196
  if ( 'top' !== $which ) {
200
  <div class="alignleft actions">
201
  <?php
202
  /*
203
+ echo '<label class="screen-reader-text" for="filter-by-type">' . __( 'Filter by type', 'zero-spam' ) . '</label>';
204
  $options = apply_filters( 'zerospam_types', array() );
205
  $current_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
206
  ?>
207
  <select name="type" id="filter-by-type">
208
+ <option value=""><?php _e( 'All types', 'zero-spam' ); ?></option>
209
  <?php foreach ( $options as $key => $value ) : ?>
210
  <option<?php if ( $current_type === $key ) : ?> selected="selected"<?php endif; ?> value="<?php echo esc_attr( $key ); ?>"><?php echo $value; ?></option>
211
  <?php endforeach; ?>
212
  </select>
213
  <?php
214
+ submit_button( __( 'Filter', 'zero-spam' ), '', 'filter_action', false );
215
  */
216
  ?>
217
+ <button class="button zerospam-block-location-trigger"><?php echo __( 'Add Blocked Location', 'zero-spam' ); ?></button>
218
  </div>
219
  <?php
220
  }
221
 
222
  /**
223
+ * Define table columns
 
 
 
224
  */
225
  public function get_columns() {
226
  $columns = array(
227
  'cb' => '<input type="checkbox" />',
228
+ 'date_added' => __( 'Date', 'zero-spam' ),
229
+ 'location' => __( 'Location', 'zero-spam' ),
230
+ 'blocked_type' => __( 'Type', 'zero-spam' ),
231
+ 'start_block' => __( 'Starts', 'zero-spam' ),
232
+ 'end_block' => __( 'Ends', 'zero-spam' ),
233
+ 'reason' => __( 'Reason', 'zero-spam' ),
234
+ 'actions' => __( 'Actions', 'zero-spam' ),
235
  );
236
 
237
  return $columns;
238
  }
239
 
240
  /**
241
+ * Sortable columns
 
 
 
242
  */
243
  public function get_sortable_columns() {
244
  $sortable_columns = array(
253
  }
254
 
255
  /**
256
+ * Column contact
 
 
 
257
  */
258
  public function column_cb( $item ) {
259
  return sprintf(
264
  }
265
 
266
  /**
267
+ * Process bulk actions
 
 
 
268
  */
269
  public function process_bulk_action() {
270
  global $wpdb;
271
 
272
+ $ids = ( isset( $_REQUEST['ids'] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['ids'] ) ) : '';
273
 
274
  switch( $this->current_action() ) {
275
  case 'delete':
276
+ $nonce = ( isset( $_REQUEST['zerospam_nonce'] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['zerospam_nonce'] ) ) : '';
277
  if ( ! wp_verify_nonce( $nonce, 'zerospam_nonce' ) ) {
278
  return false;
279
  }
core/admin/tables/class-blockedtable.php CHANGED
@@ -30,8 +30,8 @@ class BlockedTable extends WP_List_Table {
30
  global $status, $page;
31
 
32
  $args = array(
33
- 'singular' => __( 'WordPress Zero Spam Blocked IP', 'zerospam' ),
34
- 'plural' => __( 'WordPress Zero Spam Blocked IPs', 'zerospam' ),
35
  );
36
  parent::__construct( $args );
37
  }
@@ -75,7 +75,7 @@ class BlockedTable extends WP_List_Table {
75
  data-end="<?php echo esc_attr( gmdate( 'Y-m-d', strtotime( $item['end_block'] ) ) ); ?>T<?php echo esc_attr( gmdate( 'H:i', strtotime( $item['end_block'] ) ) ); ?>"
76
  data-type="<?php echo esc_attr( $item['blocked_type'] ); ?>"
77
  >
78
- <?php _e( 'Update Block', 'zerospam' ); ?>
79
  </button>
80
  <?php
81
  return ob_get_clean();
@@ -97,8 +97,8 @@ class BlockedTable extends WP_List_Table {
97
  */
98
  public function get_bulk_actions() {
99
  $actions = array(
100
- 'delete' => __( 'Delete Selected', 'zerospam' ),
101
- //'delete_all' => __( 'Delete All IPs', 'zerospam' ),
102
  );
103
 
104
  return $actions;
@@ -215,27 +215,27 @@ class BlockedTable extends WP_List_Table {
215
  <div class="alignleft actions">
216
  <?php
217
  /*
218
- echo '<label class="screen-reader-text" for="filter-by-type">' . __( 'Filter by type', 'zerospam' ) . '</label>';
219
  $options = apply_filters( 'zerospam_types', array() );
220
  $current_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
221
  ?>
222
  <select name="type" id="filter-by-type">
223
- <option value=""><?php _e( 'All types', 'zerospam' ); ?></option>
224
  <?php foreach ( $options as $key => $value ) : ?>
225
  <option<?php if ( $current_type === $key ) : ?> selected="selected"<?php endif; ?> value="<?php echo esc_attr( $key ); ?>"><?php echo $value; ?></option>
226
  <?php endforeach; ?>
227
  </select>
228
  <?php
229
- submit_button( __( 'Filter', 'zerospam' ), '', 'filter_action', false );
230
  */
231
  ?>
232
- <button class="button zerospam-block-trigger"><?php echo __( 'Add Blocked IP Address', 'zerospam' ); ?></button>
233
  <?php
234
  $settings = \ZeroSpam\Core\Settings::get_settings( 'block_method' );
235
 
236
  if ( ! empty( $settings ) && 'php' !== $settings ) :
237
  ?>
238
- <a href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=blocked&zerospam-refresh-htaccess=1' ) ); ?>" class="button"><?php esc_html_e( 'Refresh .htaccess', 'zerospam' ); ?></a>
239
  <?php endif; ?>
240
  </div>
241
  <?php
@@ -250,13 +250,13 @@ class BlockedTable extends WP_List_Table {
250
  public function get_columns() {
251
  $columns = array(
252
  'cb' => '<input type="checkbox" />',
253
- 'date_added' => __( 'Date', 'zerospam' ),
254
- 'blocked_type' => __( 'Type', 'zerospam' ),
255
- 'user_ip' => __( 'IP Address', 'zerospam' ),
256
- 'start_block' => __( 'Starts', 'zerospam' ),
257
- 'end_block' => __( 'Ends', 'zerospam' ),
258
- 'reason' => __( 'Reason', 'zerospam' ),
259
- 'actions' => __( 'Actions', 'zerospam' ),
260
  );
261
 
262
  return $columns;
30
  global $status, $page;
31
 
32
  $args = array(
33
+ 'singular' => __( 'WordPress Zero Spam Blocked IP', 'zero-spam' ),
34
+ 'plural' => __( 'WordPress Zero Spam Blocked IPs', 'zero-spam' ),
35
  );
36
  parent::__construct( $args );
37
  }
75
  data-end="<?php echo esc_attr( gmdate( 'Y-m-d', strtotime( $item['end_block'] ) ) ); ?>T<?php echo esc_attr( gmdate( 'H:i', strtotime( $item['end_block'] ) ) ); ?>"
76
  data-type="<?php echo esc_attr( $item['blocked_type'] ); ?>"
77
  >
78
+ <?php esc_html_e( 'Update Block', 'zero-spam' ); ?>
79
  </button>
80
  <?php
81
  return ob_get_clean();
97
  */
98
  public function get_bulk_actions() {
99
  $actions = array(
100
+ 'delete' => __( 'Delete Selected', 'zero-spam' ),
101
+ //'delete_all' => __( 'Delete All IPs', 'zero-spam' ),
102
  );
103
 
104
  return $actions;
215
  <div class="alignleft actions">
216
  <?php
217
  /*
218
+ echo '<label class="screen-reader-text" for="filter-by-type">' . __( 'Filter by type', 'zero-spam' ) . '</label>';
219
  $options = apply_filters( 'zerospam_types', array() );
220
  $current_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
221
  ?>
222
  <select name="type" id="filter-by-type">
223
+ <option value=""><?php _e( 'All types', 'zero-spam' ); ?></option>
224
  <?php foreach ( $options as $key => $value ) : ?>
225
  <option<?php if ( $current_type === $key ) : ?> selected="selected"<?php endif; ?> value="<?php echo esc_attr( $key ); ?>"><?php echo $value; ?></option>
226
  <?php endforeach; ?>
227
  </select>
228
  <?php
229
+ submit_button( __( 'Filter', 'zero-spam' ), '', 'filter_action', false );
230
  */
231
  ?>
232
+ <button class="button zerospam-block-trigger"><?php echo __( 'Add Blocked IP Address', 'zero-spam' ); ?></button>
233
  <?php
234
  $settings = \ZeroSpam\Core\Settings::get_settings( 'block_method' );
235
 
236
  if ( ! empty( $settings ) && 'php' !== $settings ) :
237
  ?>
238
+ <a href="<?php echo esc_url( admin_url( 'index.php?page=wordpress-zero-spam-dashboard&tab=blocked&zerospam-refresh-htaccess=1' ) ); ?>" class="button"><?php esc_html_e( 'Refresh .htaccess', 'zero-spam' ); ?></a>
239
  <?php endif; ?>
240
  </div>
241
  <?php
250
  public function get_columns() {
251
  $columns = array(
252
  'cb' => '<input type="checkbox" />',
253
+ 'date_added' => __( 'Date', 'zero-spam' ),
254
+ 'blocked_type' => __( 'Type', 'zero-spam' ),
255
+ 'user_ip' => __( 'IP Address', 'zero-spam' ),
256
+ 'start_block' => __( 'Starts', 'zero-spam' ),
257
+ 'end_block' => __( 'Ends', 'zero-spam' ),
258
+ 'reason' => __( 'Reason', 'zero-spam' ),
259
+ 'actions' => __( 'Actions', 'zero-spam' ),
260
  );
261
 
262
  return $columns;
core/admin/tables/class-logtable.php CHANGED
@@ -25,8 +25,8 @@ class LogTable extends WP_List_Table {
25
  global $status, $page;
26
 
27
  $args = array(
28
- 'singular' => __( 'WordPress Zero Spam Log', 'zerospam' ),
29
- 'plural' => __( 'WordPress Zero Spam Logs', 'zerospam' ),
30
  );
31
  parent::__construct( $args );
32
  }
@@ -64,9 +64,9 @@ class LogTable extends WP_List_Table {
64
  case 'actions':
65
  ob_start();
66
  ?>
67
- <button class="button zerospam-details-trigger" data-id="<?php echo esc_attr( $item['log_id'] ); ?>"><?php esc_html_e( 'Details', 'zerospam' ); ?></button>
68
  <div class="zerospam-modal" id="zerospam-details-<?php echo esc_attr( $item['log_id'] ); ?>">
69
- <button class="zerospam-close-modal" aria-label="<?php echo esc_attr( __( 'Close Modal', 'zerospam' ) ); ?>"></button>
70
  <?php require ZEROSPAM_PATH . 'includes/templates/admin-modal-details.php'; ?>
71
  </div>
72
  <?php
@@ -81,12 +81,12 @@ class LogTable extends WP_List_Table {
81
  data-end="<?php echo esc_attr( gmdate( 'Y-m-d', strtotime( $blocked['end_block'] ) ) ); ?>T<?php echo esc_attr( gmdate( 'H:i', strtotime( $blocked['end_block'] ) ) ); ?>"
82
  data-type="<?php echo esc_attr( $blocked['blocked_type'] ); ?>"
83
  >
84
- <?php esc_html_e( 'Update Block', 'zerospam' ); ?>
85
  </button>
86
  <?php
87
  else :
88
  ?>
89
- <button class="button zerospam-block-trigger" data-ip="<?php echo esc_attr( $item['user_ip'] ); ?>"><?php esc_html_e( 'Block IP', 'zerospam' ); ?></button>
90
  <?php
91
  endif;
92
 
@@ -122,8 +122,8 @@ class LogTable extends WP_List_Table {
122
  */
123
  public function get_bulk_actions() {
124
  $actions = array(
125
- 'delete' => __( 'Delete Selected', 'zerospam' ),
126
- 'delete_all' => __( 'Delete All Logs', 'zerospam' ),
127
  );
128
 
129
  return $actions;
@@ -285,29 +285,29 @@ class LogTable extends WP_List_Table {
285
  ?>
286
  <div class="alignleft actions">
287
  <?php
288
- echo '<label class="screen-reader-text" for="filter-by-type">' . __( 'Filter by type', 'zerospam' ) . '</label>';
289
  $options = apply_filters( 'zerospam_types', array() );
290
  $current_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
291
  ?>
292
  <select name="type" id="filter-by-type">
293
- <option value=""><?php _e( 'All types', 'zerospam' ); ?></option>
294
  <?php foreach ( $options as $key => $value ) : ?>
295
- <option<?php if ( $current_type === $key ) : ?> selected="selected"<?php endif; ?> value="<?php echo esc_attr( $key ); ?>"><?php echo $value; ?></option>
296
  <?php endforeach; ?>
297
  </select>
298
 
299
  <?php
300
- echo '<label class="screen-reader-text" for="filter-by-country">' . __( 'Filter by country', 'zerospam' ) . '</label>';
301
  $current_country = ! empty( $_REQUEST['country'] ) ? sanitize_text_field( $_REQUEST['country'] ) : false;
302
  ?>
303
  <select name="country" id="filter-by-country">
304
- <option value=""><?php _e( 'All countries', 'zerospam' ); ?></option>
305
  <?php foreach ( ZeroSpam\Core\Utilities::countries() as $key => $value ) : ?>
306
- <option<?php if ( $current_country === $key ) : ?> selected="selected"<?php endif; ?> value="<?php echo esc_attr( $key ); ?>"><?php echo $value; ?></option>
307
  <?php endforeach; ?>
308
  </select>
309
  <?php
310
- submit_button( __( 'Filter', 'zerospam' ), '', 'filter_action', false );
311
  ?>
312
  </div>
313
  <?php
@@ -319,12 +319,12 @@ class LogTable extends WP_List_Table {
319
  public function get_columns() {
320
  $columns = array(
321
  'cb' => '<input type="checkbox" />',
322
- 'date_recorded' => __( 'Date', 'zerospam' ),
323
- 'log_type' => __( 'Type', 'zerospam' ),
324
- 'user_ip' => __( 'IP Address', 'zerospam' ),
325
- 'country' => __( 'Country', 'zerospam' ),
326
- 'region' => __( 'Region', 'zerospam' ),
327
- 'actions' => __( 'Actions', 'zerospam' ),
328
  );
329
 
330
  return $columns;
25
  global $status, $page;
26
 
27
  $args = array(
28
+ 'singular' => __( 'WordPress Zero Spam Log', 'zero-spam' ),
29
+ 'plural' => __( 'WordPress Zero Spam Logs', 'zero-spam' ),
30
  );
31
  parent::__construct( $args );
32
  }
64
  case 'actions':
65
  ob_start();
66
  ?>
67
+ <button class="button zerospam-details-trigger" data-id="<?php echo esc_attr( $item['log_id'] ); ?>"><?php esc_html_e( 'Details', 'zero-spam' ); ?></button>
68
  <div class="zerospam-modal" id="zerospam-details-<?php echo esc_attr( $item['log_id'] ); ?>">
69
+ <button class="zerospam-close-modal" aria-label="<?php echo esc_attr( __( 'Close Modal', 'zero-spam' ) ); ?>"></button>
70
  <?php require ZEROSPAM_PATH . 'includes/templates/admin-modal-details.php'; ?>
71
  </div>
72
  <?php
81
  data-end="<?php echo esc_attr( gmdate( 'Y-m-d', strtotime( $blocked['end_block'] ) ) ); ?>T<?php echo esc_attr( gmdate( 'H:i', strtotime( $blocked['end_block'] ) ) ); ?>"
82
  data-type="<?php echo esc_attr( $blocked['blocked_type'] ); ?>"
83
  >
84
+ <?php esc_html_e( 'Update Block', 'zero-spam' ); ?>
85
  </button>
86
  <?php
87
  else :
88
  ?>
89
+ <button class="button zerospam-block-trigger" data-ip="<?php echo esc_attr( $item['user_ip'] ); ?>"><?php esc_html_e( 'Block IP', 'zero-spam' ); ?></button>
90
  <?php
91
  endif;
92
 
122
  */
123
  public function get_bulk_actions() {
124
  $actions = array(
125
+ 'delete' => __( 'Delete Selected', 'zero-spam' ),
126
+ 'delete_all' => __( 'Delete All Logs', 'zero-spam' ),
127
  );
128
 
129
  return $actions;
285
  ?>
286
  <div class="alignleft actions">
287
  <?php
288
+ echo '<label class="screen-reader-text" for="filter-by-type">' . __( 'Filter by type', 'zero-spam' ) . '</label>';
289
  $options = apply_filters( 'zerospam_types', array() );
290
  $current_type = ! empty( $_REQUEST['type'] ) ? sanitize_text_field( $_REQUEST['type'] ) : false;
291
  ?>
292
  <select name="type" id="filter-by-type">
293
+ <option value=""><?php _e( 'All types', 'zero-spam' ); ?></option>
294
  <?php foreach ( $options as $key => $value ) : ?>
295
+ <option<?php if ( $current_type === $key ) : ?> selected="selected"<?php endif; ?> value="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $value ); ?></option>
296
  <?php endforeach; ?>
297
  </select>
298
 
299
  <?php
300
+ echo '<label class="screen-reader-text" for="filter-by-country">' . __( 'Filter by country', 'zero-spam' ) . '</label>';
301
  $current_country = ! empty( $_REQUEST['country'] ) ? sanitize_text_field( $_REQUEST['country'] ) : false;
302
  ?>
303
  <select name="country" id="filter-by-country">
304
+ <option value=""><?php _e( 'All countries', 'zero-spam' ); ?></option>
305
  <?php foreach ( ZeroSpam\Core\Utilities::countries() as $key => $value ) : ?>
306
+ <option<?php if ( $current_country === $key ) : ?> selected="selected"<?php endif; ?> value="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $value ); ?></option>
307
  <?php endforeach; ?>
308
  </select>
309
  <?php
310
+ submit_button( __( 'Filter', 'zero-spam' ), '', 'filter_action', false );
311
  ?>
312
  </div>
313
  <?php
319
  public function get_columns() {
320
  $columns = array(
321
  'cb' => '<input type="checkbox" />',
322
+ 'date_recorded' => __( 'Date', 'zero-spam' ),
323
+ 'log_type' => __( 'Type', 'zero-spam' ),
324
+ 'user_ip' => __( 'IP Address', 'zero-spam' ),
325
+ 'country' => __( 'Country', 'zero-spam' ),
326
+ 'region' => __( 'Region', 'zero-spam' ),
327
+ 'actions' => __( 'Actions', 'zero-spam' ),
328
  );
329
 
330
  return $columns;
core/class-access.php CHANGED
@@ -79,13 +79,13 @@ class Access {
79
  header( 'Pragma: no-cache' );
80
  header( 'Expires: 0' );
81
 
82
- $message = __( 'Your IP address has been blocked due to detected spam/malicious activity.', 'zerospam' );
83
  if ( ! empty( $settings['blocked_message']['value'] ) ) {
84
  $message = $settings['blocked_message']['value'];
85
  }
86
  wp_die(
87
  $message,
88
- __( 'Blocked', 'zerospam' ),
89
  array(
90
  'response' => 403,
91
  )
79
  header( 'Pragma: no-cache' );
80
  header( 'Expires: 0' );
81
 
82
+ $message = __( 'Your IP address has been blocked due to detected spam/malicious activity.', 'zero-spam' );
83
  if ( ! empty( $settings['blocked_message']['value'] ) ) {
84
  $message = $settings['blocked_message']['value'];
85
  }
86
  wp_die(
87
  $message,
88
+ __( 'Blocked', 'zero-spam' ),
89
  array(
90
  'response' => 403,
91
  )
core/class-settings.php CHANGED
@@ -34,7 +34,7 @@ class Settings {
34
  */
35
  public static function get_sections() {
36
  self::$sections['general'] = array(
37
- 'title' => __( 'General Settings', 'zerospam' ),
38
  );
39
 
40
  return apply_filters( 'zerospam_setting_sections', self::$sections );
@@ -106,10 +106,10 @@ class Settings {
106
  $options = get_option( 'wpzerospam' );
107
 
108
  self::$settings['use_recommended_settings'] = array(
109
- 'title' => __( 'Use Recommended Settings', 'zerospam' ),
110
  'desc' => sprintf(
111
  wp_kses(
112
- __( '<strong>WARNING:</strong> This will override all existing settings.', 'zerospam' ),
113
  array(
114
  'strong' => array(),
115
  )
@@ -120,7 +120,7 @@ class Settings {
120
  'html' => sprintf(
121
  wp_kses(
122
  /* translators: %s: url */
123
- __( '<a href="%s" class="button">Override &amp; Update Settings</a>', 'zerospam' ),
124
  array(
125
  'a' => array(
126
  'href' => array(),
@@ -128,19 +128,19 @@ class Settings {
128
  ),
129
  )
130
  ),
131
- wp_nonce_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=autoconfigure' ), 'autoconfigure', 'zerospam' )
132
  ),
133
  );
134
 
135
  self::$settings['share_data'] = array(
136
- 'title' => __( 'Usage Data Sharing', 'zerospam' ),
137
  'section' => 'general',
138
  'type' => 'checkbox',
139
  'options' => array(
140
  'enabled' => sprintf(
141
  wp_kses(
142
  /* translators: %s: url */
143
- __( 'Join <a href="%1$s" target="_blank" rel="noreferrer noopener">Zero Spam\'s global community</a> &amp; report detections by opting in to share non-sensitive data. <a href="%2$s" target="_blank" rel="noreferrer noopener">Learn more</a>.', 'zerospam' ),
144
  array(
145
  'a' => array(
146
  'target' => array(),
@@ -166,10 +166,10 @@ class Settings {
166
  }
167
 
168
  self::$settings['widget_visibility'] = array(
169
- 'title' => __( 'Dashboard Widget Visibility', 'zerospam' ),
170
  'section' => 'general',
171
  'type' => 'select',
172
- 'desc' => __( 'Select which user roles have access to the admin dashboard widget. You may control-click (Windows) or command-click (Mac) to select more than one.', 'zerospam' ),
173
  'options' => $roles_array,
174
  'value' => ! empty( $options['widget_visibility'] ) ? $options['widget_visibility'] : false,
175
  'recommended' => array( 'administrator' ),
@@ -177,16 +177,16 @@ class Settings {
177
  );
178
 
179
  self::$settings['block_handler'] = array(
180
- 'title' => __( 'IP Block Handler', 'zerospam' ),
181
- 'desc' => __( 'Determines how blocked IPs are handled when they attempt to access the site.', 'zerospam' ),
182
  'section' => 'general',
183
  'type' => 'radio',
184
  'options' => array(
185
- 'redirect' => __( 'Redirect user', 'zerospam' ),
186
  '403' => sprintf(
187
  wp_kses(
188
  /* translators: %s: url */
189
- __( 'Display a <a href="%s" target="_blank" rel="noreferrer noopener"><code>403 Forbidden</code></a> error', 'zerospam' ),
190
  array(
191
  'code' => array(),
192
  'a' => array(
@@ -204,11 +204,11 @@ class Settings {
204
  );
205
 
206
  self::$settings['block_method'] = array(
207
- 'title' => __( 'IP Block Method', 'zerospam' ),
208
  'desc' => sprintf(
209
  wp_kses(
210
  /* translators: %1$s: Replaced with the apache docs URL, %2$s: Replaced with Highfivery's website URL */
211
- __( '.htaccess is preferred for performance, however <strong>choosing the wrong Apache version or adding <a href="%1$s" target="_blank" rel="noreferrer noopener">more than 8190 characters</a> could cause the website to crash</strong> and require a manual fix to the .htaccess file. If this happens &amp; you\'re unsure how to fix, contact <a href="%2$s" target="_blank" rel="noreferrer noopener">Highfivery</a> for a rapid response and resolution.', 'zerospam' ),
212
  array(
213
  'strong' => array(),
214
  'a' => array(
@@ -224,19 +224,19 @@ class Settings {
224
  'section' => 'general',
225
  'type' => 'radio',
226
  'options' => array(
227
- 'htaccess_legacy' => __( '.htaccess (Apache servers < 2.4)', 'zerospam' ),
228
- 'htaccess_modern' => __( '.htaccess (Apache servers >= 2.4)', 'zerospam' ),
229
- 'php' => __( 'PHP', 'zerospam' ),
230
  ),
231
  'value' => ! empty( $options['block_method'] ) ? $options['block_method'] : 'php',
232
  'recommended' => 'php',
233
  );
234
 
235
- $message = __( 'Your IP address has been blocked due to detected spam/malicious activity.', 'zerospam' );
236
 
237
  self::$settings['blocked_message'] = array(
238
- 'title' => __( 'Blocked Message', 'zerospam' ),
239
- 'desc' => __( 'The message displayed to blocked users when \'Display a 403 Forbidden error\' is selected.', 'zerospam' ),
240
  'section' => 'general',
241
  'type' => 'text',
242
  'field_class' => 'large-text',
@@ -246,8 +246,8 @@ class Settings {
246
  );
247
 
248
  self::$settings['blocked_redirect_url'] = array(
249
- 'title' => __( 'Blocked Users Redirect', 'zerospam' ),
250
- 'desc' => __( 'The URL blocked users are redirected to when \'Redirect user\' is selected.', 'zerospam' ),
251
  'section' => 'general',
252
  'type' => 'url',
253
  'field_class' => 'regular-text',
@@ -257,20 +257,20 @@ class Settings {
257
  );
258
 
259
  self::$settings['log_blocked_ips'] = array(
260
- 'title' => __( 'Log Blocked IPs', 'zerospam' ),
261
  'section' => 'general',
262
  'type' => 'checkbox',
263
- 'desc' => __( 'Enables logging IPs that are blocked from accessing the site.', 'zerospam' ),
264
  'options' => array(
265
- 'enabled' => __( 'Enabled', 'zerospam' ),
266
  ),
267
  'value' => ! empty( $options['log_blocked_ips'] ) ? $options['log_blocked_ips'] : false,
268
  'recommended' => 'enabled',
269
  );
270
 
271
  self::$settings['max_logs'] = array(
272
- 'title' => __( 'Maximum Log Entries', 'zerospam' ),
273
- 'desc' => __( 'The maximum number of log entries when logging is enabled. When the maximum is reached, the oldest entries will be deleted.', 'zerospam' ),
274
  'section' => 'general',
275
  'type' => 'number',
276
  'field_class' => 'small-text',
@@ -280,8 +280,8 @@ class Settings {
280
  );
281
 
282
  self::$settings['ip_whitelist'] = array(
283
- 'title' => __( 'IP Whitelist', 'zerospam' ),
284
- 'desc' => __( 'Enter IPs that should be whitelisted (IPs that should never be blocked), one per line.', 'zerospam' ),
285
  'section' => 'general',
286
  'type' => 'textarea',
287
  'field_class' => 'regular-text code',
@@ -290,8 +290,8 @@ class Settings {
290
  );
291
 
292
  self::$settings['blocked_email_domains'] = array(
293
- 'title' => __( 'Blocked Email Domains', 'zerospam' ),
294
- 'desc' => __( 'Enter a list of email domains that should be blocked, one per line.', 'zerospam' ),
295
  'section' => 'general',
296
  'type' => 'textarea',
297
  'field_class' => 'regular-text code',
@@ -300,10 +300,10 @@ class Settings {
300
  );
301
 
302
  self::$settings['update_blocked_email_domains'] = array(
303
- 'title' => __( 'Use Blocked Email Domains Recommendation', 'zerospam' ),
304
  'desc' => sprintf(
305
  wp_kses(
306
- __( '<strong>WARNING:</strong> This will override all existing blocked email domains with Zero Spam\'s recommended domains.', 'zerospam' ),
307
  array(
308
  'strong' => array(),
309
  )
@@ -314,7 +314,7 @@ class Settings {
314
  'html' => sprintf(
315
  wp_kses(
316
  /* translators: %s: url */
317
- __( '<a href="%s" class="button">Override &amp; Update Blocked Email Domains</a>', 'zerospam' ),
318
  array(
319
  'a' => array(
320
  'href' => array(),
@@ -322,16 +322,16 @@ class Settings {
322
  ),
323
  )
324
  ),
325
- wp_nonce_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=update-blocked-emails' ), 'update-blocked-emails', 'zerospam' )
326
  ),
327
  );
328
 
329
  self::$settings['regenerate_honeypot'] = array(
330
- 'title' => __( 'Regenerate Honeypot ID', 'zerospam' ),
331
  'desc' => sprintf(
332
  wp_kses(
333
  /* translators: %s: url */
334
- __( 'Helpful if spam is getting through. Current honeypot ID: <code>%s</code>', 'zerospam' ),
335
  array(
336
  'code' => array(),
337
  )
@@ -343,7 +343,7 @@ class Settings {
343
  'html' => sprintf(
344
  wp_kses(
345
  /* translators: %s: admin URL to regenerate the Zero Spam honeypot ID */
346
- __( '<a href="%s" class="button">Regenerate Honeypot ID</a>', 'zerospam' ),
347
  array(
348
  'a' => array(
349
  'href' => array(),
@@ -351,19 +351,19 @@ class Settings {
351
  ),
352
  )
353
  ),
354
- wp_nonce_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=regenerate-honeypot' ), 'regenerate-honeypot', 'zerospam' )
355
  ),
356
  );
357
 
358
  self::$settings['update_disallowed_words'] = array(
359
- 'title' => __( 'Override &amp; Update Core Disallowed Words', 'zerospam' ),
360
- 'desc' => __( 'Update WP core\'s disallowed words option with <a href="https://github.com/splorp/wordpress-comment-blacklist/" target="_blank" rel="noreferrer noopener">splorp\'s Comment Blacklist for WordPress</a>. <strong>WARNING:</strong> This will override any existing words.', 'zerospam' ),
361
  'section' => 'general',
362
  'type' => 'html',
363
  'html' => sprintf(
364
  wp_kses(
365
  /* translators: %s: url */
366
- __( '<a href="%s" class="button">Override &amp; Update Core Disallowed Words</a>', 'zerospam' ),
367
  array(
368
  'a' => array(
369
  'href' => array(),
@@ -371,7 +371,7 @@ class Settings {
371
  ),
372
  )
373
  ),
374
- wp_nonce_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=update-disallowed-words' ), 'update-disallowed-words', 'zerospam' )
375
  ),
376
  );
377
 
34
  */
35
  public static function get_sections() {
36
  self::$sections['general'] = array(
37
+ 'title' => __( 'General Settings', 'zero-spam' ),
38
  );
39
 
40
  return apply_filters( 'zerospam_setting_sections', self::$sections );
106
  $options = get_option( 'wpzerospam' );
107
 
108
  self::$settings['use_recommended_settings'] = array(
109
+ 'title' => __( 'Use Recommended Settings', 'zero-spam' ),
110
  'desc' => sprintf(
111
  wp_kses(
112
+ __( '<strong>WARNING:</strong> This will override all existing settings.', 'zero-spam' ),
113
  array(
114
  'strong' => array(),
115
  )
120
  'html' => sprintf(
121
  wp_kses(
122
  /* translators: %s: url */
123
+ __( '<a href="%s" class="button">Override &amp; Update Settings</a>', 'zero-spam' ),
124
  array(
125
  'a' => array(
126
  'href' => array(),
128
  ),
129
  )
130
  ),
131
+ wp_nonce_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=autoconfigure' ), 'autoconfigure', 'zero-spam' )
132
  ),
133
  );
134
 
135
  self::$settings['share_data'] = array(
136
+ 'title' => __( 'Usage Data Sharing', 'zero-spam' ),
137
  'section' => 'general',
138
  'type' => 'checkbox',
139
  'options' => array(
140
  'enabled' => sprintf(
141
  wp_kses(
142
  /* translators: %s: url */
143
+ __( 'Join <a href="%1$s" target="_blank" rel="noreferrer noopener">Zero Spam\'s global community</a> &amp; report detections by opting in to share non-sensitive data. <a href="%2$s" target="_blank" rel="noreferrer noopener">Learn more</a>.', 'zero-spam' ),
144
  array(
145
  'a' => array(
146
  'target' => array(),
166
  }
167
 
168
  self::$settings['widget_visibility'] = array(
169
+ 'title' => __( 'Dashboard Widget Visibility', 'zero-spam' ),
170
  'section' => 'general',
171
  'type' => 'select',
172
+ 'desc' => __( 'Select which user roles have access to the admin dashboard widget. You may control-click (Windows) or command-click (Mac) to select more than one.', 'zero-spam' ),
173
  'options' => $roles_array,
174
  'value' => ! empty( $options['widget_visibility'] ) ? $options['widget_visibility'] : false,
175
  'recommended' => array( 'administrator' ),
177
  );
178
 
179
  self::$settings['block_handler'] = array(
180
+ 'title' => __( 'IP Block Handler', 'zero-spam' ),
181
+ 'desc' => __( 'Determines how blocked IPs are handled when they attempt to access the site.', 'zero-spam' ),
182
  'section' => 'general',
183
  'type' => 'radio',
184
  'options' => array(
185
+ 'redirect' => __( 'Redirect user', 'zero-spam' ),
186
  '403' => sprintf(
187
  wp_kses(
188
  /* translators: %s: url */
189
+ __( 'Display a <a href="%s" target="_blank" rel="noreferrer noopener"><code>403 Forbidden</code></a> error', 'zero-spam' ),
190
  array(
191
  'code' => array(),
192
  'a' => array(
204
  );
205
 
206
  self::$settings['block_method'] = array(
207
+ 'title' => __( 'IP Block Method', 'zero-spam' ),
208
  'desc' => sprintf(
209
  wp_kses(
210
  /* translators: %1$s: Replaced with the apache docs URL, %2$s: Replaced with Highfivery's website URL */
211
+ __( '.htaccess is preferred for performance, however <strong>choosing the wrong Apache version or adding <a href="%1$s" target="_blank" rel="noreferrer noopener">more than 8190 characters</a> could cause the website to crash</strong> and require a manual fix to the .htaccess file. If this happens &amp; you\'re unsure how to fix, contact <a href="%2$s" target="_blank" rel="noreferrer noopener">Highfivery</a> for a rapid response and resolution.', 'zero-spam' ),
212
  array(
213
  'strong' => array(),
214
  'a' => array(
224
  'section' => 'general',
225
  'type' => 'radio',
226
  'options' => array(
227
+ 'htaccess_legacy' => __( '.htaccess (Apache servers < 2.4)', 'zero-spam' ),
228
+ 'htaccess_modern' => __( '.htaccess (Apache servers >= 2.4)', 'zero-spam' ),
229
+ 'php' => __( 'PHP', 'zero-spam' ),
230
  ),
231
  'value' => ! empty( $options['block_method'] ) ? $options['block_method'] : 'php',
232
  'recommended' => 'php',
233
  );
234
 
235
+ $message = __( 'Your IP address has been blocked due to detected spam/malicious activity.', 'zero-spam' );
236
 
237
  self::$settings['blocked_message'] = array(
238
+ 'title' => __( 'Blocked Message', 'zero-spam' ),
239
+ 'desc' => __( 'The message displayed to blocked users when \'Display a 403 Forbidden error\' is selected.', 'zero-spam' ),
240
  'section' => 'general',
241
  'type' => 'text',
242
  'field_class' => 'large-text',
246
  );
247
 
248
  self::$settings['blocked_redirect_url'] = array(
249
+ 'title' => __( 'Blocked Users Redirect', 'zero-spam' ),
250
+ 'desc' => __( 'The URL blocked users are redirected to when \'Redirect user\' is selected.', 'zero-spam' ),
251
  'section' => 'general',
252
  'type' => 'url',
253
  'field_class' => 'regular-text',
257
  );
258
 
259
  self::$settings['log_blocked_ips'] = array(
260
+ 'title' => __( 'Log Blocked IPs', 'zero-spam' ),
261
  'section' => 'general',
262
  'type' => 'checkbox',
263
+ 'desc' => __( 'Enables logging IPs that are blocked from accessing the site.', 'zero-spam' ),
264
  'options' => array(
265
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
266
  ),
267
  'value' => ! empty( $options['log_blocked_ips'] ) ? $options['log_blocked_ips'] : false,
268
  'recommended' => 'enabled',
269
  );
270
 
271
  self::$settings['max_logs'] = array(
272
+ 'title' => __( 'Maximum Log Entries', 'zero-spam' ),
273
+ 'desc' => __( 'The maximum number of log entries when logging is enabled. When the maximum is reached, the oldest entries will be deleted.', 'zero-spam' ),
274
  'section' => 'general',
275
  'type' => 'number',
276
  'field_class' => 'small-text',
280
  );
281
 
282
  self::$settings['ip_whitelist'] = array(
283
+ 'title' => __( 'IP Whitelist', 'zero-spam' ),
284
+ 'desc' => __( 'Enter IPs that should be whitelisted (IPs that should never be blocked), one per line.', 'zero-spam' ),
285
  'section' => 'general',
286
  'type' => 'textarea',
287
  'field_class' => 'regular-text code',
290
  );
291
 
292
  self::$settings['blocked_email_domains'] = array(
293
+ 'title' => __( 'Blocked Email Domains', 'zero-spam' ),
294
+ 'desc' => __( 'Enter a list of email domains that should be blocked, one per line.', 'zero-spam' ),
295
  'section' => 'general',
296
  'type' => 'textarea',
297
  'field_class' => 'regular-text code',
300
  );
301
 
302
  self::$settings['update_blocked_email_domains'] = array(
303
+ 'title' => __( 'Use Blocked Email Domains Recommendation', 'zero-spam' ),
304
  'desc' => sprintf(
305
  wp_kses(
306
+ __( '<strong>WARNING:</strong> This will override all existing blocked email domains with Zero Spam\'s recommended domains.', 'zero-spam' ),
307
  array(
308
  'strong' => array(),
309
  )
314
  'html' => sprintf(
315
  wp_kses(
316
  /* translators: %s: url */
317
+ __( '<a href="%s" class="button">Override &amp; Update Blocked Email Domains</a>', 'zero-spam' ),
318
  array(
319
  'a' => array(
320
  'href' => array(),
322
  ),
323
  )
324
  ),
325
+ wp_nonce_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=update-blocked-emails' ), 'update-blocked-emails', 'zero-spam' )
326
  ),
327
  );
328
 
329
  self::$settings['regenerate_honeypot'] = array(
330
+ 'title' => __( 'Regenerate Honeypot ID', 'zero-spam' ),
331
  'desc' => sprintf(
332
  wp_kses(
333
  /* translators: %s: url */
334
+ __( 'Helpful if spam is getting through. Current honeypot ID: <code>%s</code>', 'zero-spam' ),
335
  array(
336
  'code' => array(),
337
  )
343
  'html' => sprintf(
344
  wp_kses(
345
  /* translators: %s: admin URL to regenerate the Zero Spam honeypot ID */
346
+ __( '<a href="%s" class="button">Regenerate Honeypot ID</a>', 'zero-spam' ),
347
  array(
348
  'a' => array(
349
  'href' => array(),
351
  ),
352
  )
353
  ),
354
+ wp_nonce_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=regenerate-honeypot' ), 'regenerate-honeypot', 'zero-spam' )
355
  ),
356
  );
357
 
358
  self::$settings['update_disallowed_words'] = array(
359
+ 'title' => __( 'Override &amp; Update Core Disallowed Words', 'zero-spam' ),
360
+ 'desc' => __( 'Update WP core\'s disallowed words option with <a href="https://github.com/splorp/wordpress-comment-blacklist/" target="_blank" rel="noreferrer noopener">splorp\'s Comment Blacklist for WordPress</a>. <strong>WARNING:</strong> This will override any existing words.', 'zero-spam' ),
361
  'section' => 'general',
362
  'type' => 'html',
363
  'html' => sprintf(
364
  wp_kses(
365
  /* translators: %s: url */
366
+ __( '<a href="%s" class="button">Override &amp; Update Core Disallowed Words</a>', 'zero-spam' ),
367
  array(
368
  'a' => array(
369
  'href' => array(),
371
  ),
372
  )
373
  ),
374
+ wp_nonce_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=update-disallowed-words' ), 'update-disallowed-words', 'zero-spam' )
375
  ),
376
  );
377
 
core/class-utilities.php CHANGED
@@ -302,7 +302,7 @@ class Utilities {
302
  * @param string $setting_msg_key Optional. Setting message key.
303
  */
304
  public static function detection_title( $setting_msg_key = false ) {
305
- $title = __( 'Blocked for Suspected Malicious IP/Spam', 'zerospam' );
306
 
307
  return apply_filters( 'zerospam_detection_title', $title, $setting_msg_key );
308
  }
@@ -313,7 +313,7 @@ class Utilities {
313
  * @param string $setting_msg_key Optional. Setting message key.
314
  */
315
  public static function detection_message( $setting_msg_key = false ) {
316
- $message = __( 'You have been flagged as spam/malicious user.', 'zerospam' );
317
 
318
  if ( $setting_msg_key && ! empty( ZeroSpam\Core\Settings::get_settings( $setting_msg_key ) ) ) {
319
  $message = ZeroSpam\Core\Settings::get_settings( $setting_msg_key );
302
  * @param string $setting_msg_key Optional. Setting message key.
303
  */
304
  public static function detection_title( $setting_msg_key = false ) {
305
+ $title = __( 'Blocked for Suspected Malicious IP/Spam', 'zero-spam' );
306
 
307
  return apply_filters( 'zerospam_detection_title', $title, $setting_msg_key );
308
  }
313
  * @param string $setting_msg_key Optional. Setting message key.
314
  */
315
  public static function detection_message( $setting_msg_key = false ) {
316
+ $message = __( 'You have been flagged as spam/malicious user.', 'zero-spam' );
317
 
318
  if ( $setting_msg_key && ! empty( ZeroSpam\Core\Settings::get_settings( $setting_msg_key ) ) ) {
319
  $message = ZeroSpam\Core\Settings::get_settings( $setting_msg_key );
includes/class-cli.php CHANGED
@@ -10,7 +10,7 @@ class ZeroSpamCLI {
10
  */
11
  public function autoconfigure() {
12
  \ZeroSpam\Core\Settings::auto_configure();
13
- WP_CLI::success( __( 'Zero Spam has been successfully auto-configured using the recommended defaults.', 'zerospam' ) );
14
  }
15
 
16
  /**
@@ -53,7 +53,7 @@ class ZeroSpamCLI {
53
  }
54
  }
55
  } else {
56
- WP_CLI::error( __( 'Opps! You didn\'t specify a setting to set (ex. wp zerospam set --share_data=enabled).', 'zerospam' ) );
57
  }
58
  }
59
  }
10
  */
11
  public function autoconfigure() {
12
  \ZeroSpam\Core\Settings::auto_configure();
13
+ WP_CLI::success( __( 'Zero Spam has been successfully auto-configured using the recommended defaults.', 'zero-spam' ) );
14
  }
15
 
16
  /**
53
  }
54
  }
55
  } else {
56
+ WP_CLI::error( __( 'Opps! You didn\'t specify a setting to set (ex. wp zerospam set --share_data=enabled).', 'zero-spam' ) );
57
  }
58
  }
59
  }
includes/class-plugin.php CHANGED
@@ -59,9 +59,9 @@ class Plugin {
59
  * @param array $types Array of failed types.
60
  */
61
  public function failed_types( $types ) {
62
- $types['honeypot'] = __( 'Honeypot', 'zerospam' );
63
- $types['blocked_email_domain'] = __( 'Blocked Email Domain', 'zerospam' );
64
- $types['blocked'] = __( 'Blocked IP', 'zerospam' );
65
 
66
  return $types;
67
  }
@@ -164,7 +164,7 @@ class Plugin {
164
  * @param array $types Types of detections.
165
  */
166
  public function types( $types ) {
167
- $types['blocked'] = __( 'Blocked', 'zerospam' );
168
 
169
  return $types;
170
  }
59
  * @param array $types Array of failed types.
60
  */
61
  public function failed_types( $types ) {
62
+ $types['honeypot'] = __( 'Honeypot', 'zero-spam' );
63
+ $types['blocked_email_domain'] = __( 'Blocked Email Domain', 'zero-spam' );
64
+ $types['blocked'] = __( 'Blocked IP', 'zero-spam' );
65
 
66
  return $types;
67
  }
164
  * @param array $types Types of detections.
165
  */
166
  public function types( $types ) {
167
+ $types['blocked'] = __( 'Blocked', 'zero-spam' );
168
 
169
  return $types;
170
  }
includes/templates/admin-block-ip.php CHANGED
@@ -14,7 +14,7 @@
14
 
15
  <?php if ( empty( $location_form ) ) : ?>
16
  <label for="blocked-ip">
17
- <?php _e( 'IP Address', 'zerospam' ); ?>
18
  <input
19
  type="text"
20
  name="blocked_ip"
@@ -24,17 +24,17 @@
24
  </label>
25
  <?php else: ?>
26
  <label for="location-type">
27
- <?php _e( 'Location Type', 'zerospam' ); ?>
28
  <select id="location-type" name="key_type">
29
- <option value="country_code"><?php _e( 'Country Code', 'zerospam' ); ?></option>
30
- <option value="region_code"><?php _e( 'Region Code', 'zerospam' ); ?></option>
31
- <option value="city"><?php _e( 'City Name', 'zerospam' ); ?></option>
32
- <option value="zip"><?php _e( 'Zip/Postal Code', 'zerospam' ); ?></option>
33
  </select>
34
  </label>
35
 
36
  <label for="location-key">
37
- <?php _e( 'Location Key', 'zerospam' ); ?>
38
  <input
39
  id="location-key"
40
  type="text"
@@ -45,34 +45,34 @@
45
  </label>
46
  <?php endif; ?>
47
 
48
- <label for="blocked-type"><?php _e( 'Type', 'zerospam' ); ?>
49
  <select id="blocked-type" name="blocked_type">
50
- <option value="temporary"><?php _e( 'Temporary', 'zerospam' ); ?></option>
51
- <option value="permanent"><?php _e( 'Permanent', 'zerospam' ); ?></option>
52
  </select>
53
  </label>
54
 
55
  <label for="blocked-reason">
56
- <?php _e( 'Reason', 'zerospam' ); ?>
57
- <input type="text" id="blocked-reason" name="blocked_reason" value="" placeholder="<?php _e( 'e.g. Spammed form', 'zerospam' ); ?>" />
58
  </label>
59
 
60
  <label for="blocked-start-date">
61
- <?php esc_html_e( 'Start Date', 'zerospam' ); ?>
62
  <input
63
  type="datetime-local"
64
  id="blocked-start-date"
65
  name="blocked_start_date"
66
  value=""
67
- placeholder="<?php echo esc_attr( __( 'Optional', 'zerospam' ) ); ?>"
68
  />
69
  </label>
70
 
71
  <label for="blocked-end-date">
72
- <?php _e( 'End Date', 'zerospam' ); ?>
73
- <input type="datetime-local" id="blocked-end-date" name="blocked_end_date" value="" placeholder="<?php _e( 'Optional', 'zerospam' ); ?>" />
74
  </label>
75
 
76
- <input type="submit" class="button button-primary" value="<?php _e( 'Add/Update Blocked IP', 'zerospam' ); ?>" />
77
 
78
  </form>
14
 
15
  <?php if ( empty( $location_form ) ) : ?>
16
  <label for="blocked-ip">
17
+ <?php _e( 'IP Address', 'zero-spam' ); ?>
18
  <input
19
  type="text"
20
  name="blocked_ip"
24
  </label>
25
  <?php else: ?>
26
  <label for="location-type">
27
+ <?php esc_html_e( 'Location Type', 'zero-spam' ); ?>
28
  <select id="location-type" name="key_type">
29
+ <option value="country_code"><?php esc_html_e( 'Country Code', 'zero-spam' ); ?></option>
30
+ <option value="region_code"><?php esc_html_e( 'Region Code', 'zero-spam' ); ?></option>
31
+ <option value="city"><?php esc_html_e( 'City Name', 'zero-spam' ); ?></option>
32
+ <option value="zip"><?php esc_html_e( 'Zip/Postal Code', 'zero-spam' ); ?></option>
33
  </select>
34
  </label>
35
 
36
  <label for="location-key">
37
+ <?php esc_html_e( 'Location Key', 'zero-spam' ); ?>
38
  <input
39
  id="location-key"
40
  type="text"
45
  </label>
46
  <?php endif; ?>
47
 
48
+ <label for="blocked-type"><?php esc_html_e( 'Type', 'zero-spam' ); ?>
49
  <select id="blocked-type" name="blocked_type">
50
+ <option value="temporary"><?php esc_html_e( 'Temporary', 'zero-spam' ); ?></option>
51
+ <option value="permanent"><?php esc_html_e( 'Permanent', 'zero-spam' ); ?></option>
52
  </select>
53
  </label>
54
 
55
  <label for="blocked-reason">
56
+ <?php esc_html_e( 'Reason', 'zero-spam' ); ?>
57
+ <input type="text" id="blocked-reason" name="blocked_reason" value="" placeholder="<?php esc_attr_e( 'e.g. Spammed form', 'zero-spam' ); ?>" />
58
  </label>
59
 
60
  <label for="blocked-start-date">
61
+ <?php esc_html_e( 'Start Date', 'zero-spam' ); ?>
62
  <input
63
  type="datetime-local"
64
  id="blocked-start-date"
65
  name="blocked_start_date"
66
  value=""
67
+ placeholder="<?php echo esc_attr( __( 'Optional', 'zero-spam' ) ); ?>"
68
  />
69
  </label>
70
 
71
  <label for="blocked-end-date">
72
+ <?php esc_html_e( 'End Date', 'zero-spam' ); ?>
73
+ <input type="datetime-local" id="blocked-end-date" name="blocked_end_date" value="" placeholder="<?php esc_attr_e( 'Optional', 'zero-spam' ); ?>" />
74
  </label>
75
 
76
+ <input type="submit" class="button button-primary" value="<?php esc_attr_e( 'Add/Update Blocked IP', 'zero-spam' ); ?>" />
77
 
78
  </form>
includes/templates/admin-callout.php CHANGED
@@ -17,7 +17,7 @@ $settings = \ZeroSpam\Core\Settings::get_settings();
17
  echo sprintf(
18
  wp_kses(
19
  /* translators: %s: Zero Spam API link */
20
- __( 'Super-charge WordPress Zero Spam with a <a href="%s" target="_blank" rel="noopener noreferrer"> Zero Spam API License</a>.', 'zerospam' ),
21
  array(
22
  'a' => array(
23
  'target' => array(),
@@ -34,7 +34,7 @@ $settings = \ZeroSpam\Core\Settings::get_settings();
34
  echo sprintf(
35
  wp_kses(
36
  /* translators: %s: Zero Spam API link */
37
- __( '<p>Enable enhanced protection with a <strong>Zero Spam API license</strong> &mdash; one of the largest, most comprehensive, constantly-growing global malicious IP, email, and username databases available.</p><p><a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam</a> is comprised of a global detection network of over 30,000+ apps and sites that monitor traffic and usage in real-time to detect malicious activity. <a href="%1$s" target="_blank" rel="noopener noreferrer"><strong>Subscribe today</strong></a> for enhanced protection.</p>', 'zerospam' ),
38
  array(
39
  'a' => array(
40
  'target' => array(),
@@ -50,8 +50,8 @@ $settings = \ZeroSpam\Core\Settings::get_settings();
50
  );
51
  ?>
52
  <p style="margin-top: 30px">
53
- <a class="button button-primary" href="<?php echo esc_url( ZEROSPAM_URL ); ?>subscribe/?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=license" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Enable Enhanced Protection', 'zerospam' ); ?></a>
54
- <a href="<?php echo esc_url( ZEROSPAM_URL ); ?>?utm_source=wordpress_zero_spam&utm_medium=dashboard_widget&utm_campaign=license" target="_blank" rel="noreferrer noopener" class="button button-secondary"><?php esc_html_e( 'Learn More', 'zerospam' ); ?></a>
55
  </p>
56
  <?php else : ?>
57
  <h2>
@@ -59,7 +59,7 @@ $settings = \ZeroSpam\Core\Settings::get_settings();
59
  echo sprintf(
60
  wp_kses(
61
  /* translators: %s: Zero Spam link */
62
- __( 'Congratulations, <a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam</a> enhanced protection is enabled!', 'zerospam' ),
63
  array(
64
  'a' => array(
65
  'target' => array(),
@@ -76,7 +76,7 @@ $settings = \ZeroSpam\Core\Settings::get_settings();
76
  echo sprintf(
77
  wp_kses(
78
  /* translators: %s: Zero Spam API link */
79
- __( '<p><a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam</a> is comprised of a global detection network of over 30,000+ apps and sites that monitor traffic and usage in real-time to detect malicious activity.</p>', 'zerospam' ),
80
  array(
81
  'a' => array(
82
  'target' => array(),
@@ -97,21 +97,21 @@ $settings = \ZeroSpam\Core\Settings::get_settings();
97
  <?php if ( 'enabled' !== $settings['zerospam']['value'] || empty( $settings['zerospam_license']['value'] ) ) : ?>
98
  <li style="margin-bottom: 20px;">
99
  <a href="<?php echo esc_url( ZEROSPAM_URL ); ?>subscribe/?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=license" target="_blank">
100
- <strong><?php esc_html_e( 'Get a Zero Spam API License', 'zerospam' ); ?></strong>
101
  </a>
102
  </li>
103
  <?php endif; ?>
104
- <li><a href="https://github.com/bmarshall511/wordpress-zero-spam/issues" target="_blank"><?php esc_html_e( 'Submit a Bug or Feature Request', 'zerospam' ); ?></a></li>
105
- <li><a href="https://github.com/bmarshall511/wordpress-zero-spam/wiki" target="_blank" rel="noreferrer noopener"><?php esc_html_e( 'WordPress Zero Spam Plugin Documentation', 'zerospam' ); ?></a></li>
106
- <li><a href="https://github.com/bmarshall511/wordpress-zero-spam" target="_blank" rel="noreferrer noopener"><?php esc_html_e( 'Become a Contributor &mdash; Fork on Github', 'zerospam' ); ?></a></li>
107
- <li><a href="https://twitter.com/ZeroSpamOrg" target="_blank"><?php _e( 'Follow us on Twitter', 'zerospam' ); ?></a> &amp; <a href="https://www.facebook.com/zerospamorg/" target="_blank"><?php esc_html_e( 'Facebook', 'zerospam' ); ?></a></li>
108
  </ul>
109
  <hr />
110
  <?php
111
  echo sprintf(
112
  wp_kses(
113
  /* translators: %s: Zero Spam API link */
114
- __( '<p><small>WordPress Zero Spam is proudly developed &amp; maintained by <a href="%1$s" target="_blank" rel="noopener noreferrer">Highfivery LLC &mdash; a creative digital agency</a>.</small></p>', 'zerospam' ),
115
  array(
116
  'a' => array(
117
  'target' => array(),
17
  echo sprintf(
18
  wp_kses(
19
  /* translators: %s: Zero Spam API link */
20
+ __( 'Super-charge WordPress Zero Spam with a <a href="%s" target="_blank" rel="noopener noreferrer"> Zero Spam API License</a>.', 'zero-spam' ),
21
  array(
22
  'a' => array(
23
  'target' => array(),
34
  echo sprintf(
35
  wp_kses(
36
  /* translators: %s: Zero Spam API link */
37
+ __( '<p>Enable enhanced protection with a <strong>Zero Spam API license</strong> &mdash; one of the largest, most comprehensive, constantly-growing global malicious IP, email, and username databases available.</p><p><a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam</a> is comprised of a global detection network of over 30,000+ apps and sites that monitor traffic and usage in real-time to detect malicious activity. <a href="%1$s" target="_blank" rel="noopener noreferrer"><strong>Subscribe today</strong></a> for enhanced protection.</p>', 'zero-spam' ),
38
  array(
39
  'a' => array(
40
  'target' => array(),
50
  );
51
  ?>
52
  <p style="margin-top: 30px">
53
+ <a class="button button-primary" href="<?php echo esc_url( ZEROSPAM_URL ); ?>subscribe/?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=license" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Enable Enhanced Protection', 'zero-spam' ); ?></a>
54
+ <a href="<?php echo esc_url( ZEROSPAM_URL ); ?>?utm_source=wordpress_zero_spam&utm_medium=dashboard_widget&utm_campaign=license" target="_blank" rel="noreferrer noopener" class="button button-secondary"><?php esc_html_e( 'Learn More', 'zero-spam' ); ?></a>
55
  </p>
56
  <?php else : ?>
57
  <h2>
59
  echo sprintf(
60
  wp_kses(
61
  /* translators: %s: Zero Spam link */
62
+ __( 'Congratulations, <a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam</a> enhanced protection is enabled!', 'zero-spam' ),
63
  array(
64
  'a' => array(
65
  'target' => array(),
76
  echo sprintf(
77
  wp_kses(
78
  /* translators: %s: Zero Spam API link */
79
+ __( '<p><a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam</a> is comprised of a global detection network of over 30,000+ apps and sites that monitor traffic and usage in real-time to detect malicious activity.</p>', 'zero-spam' ),
80
  array(
81
  'a' => array(
82
  'target' => array(),
97
  <?php if ( 'enabled' !== $settings['zerospam']['value'] || empty( $settings['zerospam_license']['value'] ) ) : ?>
98
  <li style="margin-bottom: 20px;">
99
  <a href="<?php echo esc_url( ZEROSPAM_URL ); ?>subscribe/?utm_source=wordpress_zero_spam&utm_medium=settings_page&utm_campaign=license" target="_blank">
100
+ <strong><?php esc_html_e( 'Get a Zero Spam API License', 'zero-spam' ); ?></strong>
101
  </a>
102
  </li>
103
  <?php endif; ?>
104
+ <li><a href="https://github.com/bmarshall511/wordpress-zero-spam/issues" target="_blank"><?php esc_html_e( 'Submit a Bug or Feature Request', 'zero-spam' ); ?></a></li>
105
+ <li><a href="https://github.com/bmarshall511/wordpress-zero-spam/wiki" target="_blank" rel="noreferrer noopener"><?php esc_html_e( 'WordPress Zero Spam Plugin Documentation', 'zero-spam' ); ?></a></li>
106
+ <li><a href="https://github.com/bmarshall511/wordpress-zero-spam" target="_blank" rel="noreferrer noopener"><?php esc_html_e( 'Become a Contributor &mdash; Fork on Github', 'zero-spam' ); ?></a></li>
107
+ <li><a href="https://twitter.com/ZeroSpamOrg" target="_blank"><?php esc_html_e( 'Follow us on Twitter', 'zero-spam' ); ?></a> &amp; <a href="https://www.facebook.com/zerospamorg/" target="_blank"><?php esc_html_e( 'Facebook', 'zero-spam' ); ?></a></li>
108
  </ul>
109
  <hr />
110
  <?php
111
  echo sprintf(
112
  wp_kses(
113
  /* translators: %s: Zero Spam API link */
114
+ __( '<p><small>WordPress Zero Spam is proudly developed &amp; maintained by <a href="%1$s" target="_blank" rel="noopener noreferrer">Highfivery LLC &mdash; a creative digital agency</a>.</small></p>', 'zero-spam' ),
115
  array(
116
  'a' => array(
117
  'target' => array(),
includes/templates/admin-ips.php CHANGED
@@ -8,7 +8,7 @@
8
  if ( empty( $entries ) ) {
9
  echo sprintf(
10
  wp_kses(
11
- __( 'Nothing to report.', 'zerospam' ),
12
  array(
13
  'strong' => array(),
14
  )
@@ -56,14 +56,14 @@ if ( $ips ) {
56
  />
57
  <?php endif; ?>
58
  <a href="<?php echo esc_url( ZEROSPAM_URL ); ?>ip-lookup/<?php echo urlencode( $ip ); ?>" target="_blank" rel="noopener noreferrer">
59
- <?php echo $ip; ?>
60
  </a>
61
  </span>
62
  <span>
63
  <?php if ( ! empty( $data['country'] ) ) : ?>
64
  <?php echo ZeroSpam\Core\Utilities::countries( $data['country'] ); ?>
65
  <?php else: ?>
66
- <?php esc_html_e( 'Unknown', 'zerospam' ); ?>
67
  <?php endif; ?>
68
  </span>
69
  <span><?php echo number_format( $data['count'], 0 ); ?></span>
@@ -80,12 +80,12 @@ if ( $ips ) {
80
  data-end="<?php echo esc_attr( gmdate( 'Y-m-d', strtotime( $blocked['end_block'] ) ) ); ?>T<?php echo esc_attr( gmdate( 'H:i', strtotime( $blocked['end_block'] ) ) ); ?>"
81
  data-type="<?php echo esc_attr( $blocked['blocked_type'] ); ?>"
82
  >
83
- <?php _e( 'Update Block', 'zerospam' ); ?>
84
  </button>
85
  <?php
86
  else :
87
  ?>
88
- <button class="button zerospam-block-trigger" data-ip="<?php echo esc_attr( $ip ); ?>"><?php _e( 'Block IP', 'zerospam' ); ?></button>
89
  <?php
90
  endif;
91
  ?>
8
  if ( empty( $entries ) ) {
9
  echo sprintf(
10
  wp_kses(
11
+ __( 'Nothing to report.', 'zero-spam' ),
12
  array(
13
  'strong' => array(),
14
  )
56
  />
57
  <?php endif; ?>
58
  <a href="<?php echo esc_url( ZEROSPAM_URL ); ?>ip-lookup/<?php echo urlencode( $ip ); ?>" target="_blank" rel="noopener noreferrer">
59
+ <?php echo esc_html( $ip ); ?>
60
  </a>
61
  </span>
62
  <span>
63
  <?php if ( ! empty( $data['country'] ) ) : ?>
64
  <?php echo ZeroSpam\Core\Utilities::countries( $data['country'] ); ?>
65
  <?php else: ?>
66
+ <?php esc_html_e( 'Unknown', 'zero-spam' ); ?>
67
  <?php endif; ?>
68
  </span>
69
  <span><?php echo number_format( $data['count'], 0 ); ?></span>
80
  data-end="<?php echo esc_attr( gmdate( 'Y-m-d', strtotime( $blocked['end_block'] ) ) ); ?>T<?php echo esc_attr( gmdate( 'H:i', strtotime( $blocked['end_block'] ) ) ); ?>"
81
  data-type="<?php echo esc_attr( $blocked['blocked_type'] ); ?>"
82
  >
83
+ <?php esc_html_e( 'Update Block', 'zero-spam' ); ?>
84
  </button>
85
  <?php
86
  else :
87
  ?>
88
+ <button class="button zerospam-block-trigger" data-ip="<?php echo esc_attr( $ip ); ?>"><?php esc_html_e( 'Block IP', 'zero-spam' ); ?></button>
89
  <?php
90
  endif;
91
  ?>
includes/templates/admin-line-chart.php CHANGED
@@ -8,7 +8,7 @@
8
  if ( empty( $entries ) ) {
9
  echo sprintf(
10
  wp_kses(
11
- __( 'Nothing to report.', 'zerospam' ),
12
  array(
13
  'strong' => array(),
14
  )
@@ -63,7 +63,7 @@ foreach ( $data as $date => $count ) {
63
  data: {
64
  labels: <?php echo wp_json_encode( $labels ); ?>,
65
  datasets: [{
66
- label: '<?php esc_html_e( 'Number of Detections', 'zerospam' ); ?>',
67
  data: <?php echo wp_json_encode( $chart_data ); ?>,
68
  backgroundColor: 'rgba(88, 0, 15, 0.5)',
69
  borderColor: '#63000D',
8
  if ( empty( $entries ) ) {
9
  echo sprintf(
10
  wp_kses(
11
+ __( 'Nothing to report.', 'zero-spam' ),
12
  array(
13
  'strong' => array(),
14
  )
63
  data: {
64
  labels: <?php echo wp_json_encode( $labels ); ?>,
65
  datasets: [{
66
+ label: '<?php esc_html_e( 'Number of Detections', 'zero-spam' ); ?>',
67
  data: <?php echo wp_json_encode( $chart_data ); ?>,
68
  backgroundColor: 'rgba(88, 0, 15, 0.5)',
69
  borderColor: '#63000D',
includes/templates/admin-map.php CHANGED
@@ -8,7 +8,7 @@
8
  if ( empty( $entries ) ) {
9
  echo sprintf(
10
  wp_kses(
11
- __( '<strong>Good news!</strong> There haven\'t been any detections of malicious or spammy IPs yet.', 'zerospam' ),
12
  array(
13
  'strong' => array(),
14
  )
@@ -62,7 +62,7 @@ if ( empty( $locations ) ) :
62
  echo sprintf(
63
  wp_kses(
64
  /* translators: %s: url */
65
- __( 'Current detections have no geolocation information available. Enable ipstack and/or IPinfo on the <a href="%1$s">settings page</a>.', 'zerospam' ),
66
  array(
67
  'a' => array( 'href' => array() ),
68
  )
8
  if ( empty( $entries ) ) {
9
  echo sprintf(
10
  wp_kses(
11
+ __( '<strong>Good news!</strong> There haven\'t been any detections of malicious or spammy IPs yet.', 'zero-spam' ),
12
  array(
13
  'strong' => array(),
14
  )
62
  echo sprintf(
63
  wp_kses(
64
  /* translators: %s: url */
65
+ __( 'Current detections have no geolocation information available. Enable ipstack and/or IPinfo on the <a href="%1$s">settings page</a>.', 'zero-spam' ),
66
  array(
67
  'a' => array( 'href' => array() ),
68
  )
includes/templates/admin-modal-details.php CHANGED
@@ -16,7 +16,7 @@ endif;
16
  ?>
17
  <div class="zerospam-modal-details">
18
  <div class="zerospam-modal-title">
19
- <h3><?php echo esc_html_e( 'Detection ID', 'zerospam' ); ?> #<?php echo esc_html( $item['log_id'] ); ?></h3>
20
  </div>
21
  <div class="zerospam-modal-subtitle">
22
  <?php
@@ -31,7 +31,7 @@ endif;
31
 
32
  <ul class="zerospam-modal-list">
33
  <li>
34
- <strong><?php esc_html_e( 'IP Address', 'zerospam' ); ?></strong>
35
  <span>
36
  <?php
37
  $lookup_url = ZEROSPAM_URL . 'ip-lookup/';
@@ -43,7 +43,7 @@ endif;
43
  echo sprintf(
44
  wp_kses(
45
  /* translators: %1s: Replaced with the IP address, %2$s Replaced with the IP lookup URL */
46
- __( '%1$s &mdash; <a href="%2$s" target="_blank" rel="noreferrer noopener" class="zerospam-new-window-link">IP Lookup</a>', 'zerospam' ),
47
  array(
48
  'a' => array(
49
  'target' => array(),
@@ -60,7 +60,7 @@ endif;
60
  </span>
61
  </li>
62
  <li>
63
- <strong><?php esc_html_e( 'Type', 'zerospam' ); ?></strong>
64
  <span>
65
  <?php
66
  $detection_types = apply_filters( 'zerospam_types', array() );
@@ -77,7 +77,7 @@ endif;
77
  </li>
78
  <?php if ( $submission_data && ! empty( $submission_data['failed'] ) ) : ?>
79
  <li>
80
- <strong><?php esc_html_e( 'Failed', 'zerospam' ); ?></strong>
81
  <span>
82
  <?php
83
  $failed_types = apply_filters( 'zerospam_failed_types', array() );
@@ -99,11 +99,11 @@ endif;
99
  </ul>
100
 
101
  <button class="button action zerospam-block-trigger" data-id="<?php echo esc_attr( $item['log_id'] ); ?>">
102
- <?php esc_html_e( 'Block IP', 'zerospam' ); ?>
103
  </button>
104
 
105
  <?php if ( ! empty( $item['latitude'] ) && ! empty( $item['longitude'] ) ) : ?>
106
- <h4 class="zerospam-modal-headline"><?php esc_html_e( 'Location', 'zerospam' ); ?></h4>
107
  <?php
108
  $coordinates = $item['latitude'] . ',' . $item['longitude'];
109
  do_action( 'zerospam_google_map', $coordinates );
@@ -111,7 +111,7 @@ endif;
111
  <ul class="zerospam-modal-list">
112
  <?php if ( ! empty( $item['country'] ) ) : ?>
113
  <li>
114
- <strong><?php esc_html_e( 'Country', 'zerospam' ); ?></strong>
115
  <span>
116
  <?php
117
  $country_name = ! empty( $item['country_name'] ) ? $item['country_name'] : false;
@@ -141,7 +141,7 @@ endif;
141
  <?php endif; ?>
142
  <?php if ( ! empty( $item['region'] ) || ! empty( $item['region_name'] ) ) : ?>
143
  <li>
144
- <strong><?php esc_html_e( 'Region', 'zerospam' ); ?></strong>
145
  <span>
146
  <?php if ( ! empty( $item['region_name'] ) ) : ?>
147
  <?php echo esc_html( $item['region_name'] ); ?>
@@ -154,21 +154,21 @@ endif;
154
  <?php endif; ?>
155
  <?php if ( ! empty( $item['city'] ) ) : ?>
156
  <li>
157
- <strong><?php echo esc_html_e( 'City', 'zerospam' ); ?></strong>
158
  <span><?php echo esc_html( $item['city'] ); ?>
159
  </span>
160
  </li>
161
  <?php endif; ?>
162
  <?php if ( ! empty( $item['zip'] ) ) : ?>
163
  <li>
164
- <strong><?php echo esc_html_e( 'Zip/Postal Code', 'zerospam' ); ?></strong>
165
  <span><?php echo esc_html( $item['zip'] ); ?>
166
  </span>
167
  </li>
168
  <?php endif; ?>
169
  <?php if ( ! empty( $item['latitude'] ) || ! empty( $item['region_name'] ) ) : ?>
170
  <li>
171
- <strong><?php echo esc_html_e( 'Coordinates', 'zerospam' ); ?></strong>
172
  <span>
173
  <?php if ( ! empty( $item['latitude'] ) ) : ?>
174
  <?php echo esc_html( $item['latitude'] ); ?>&deg;,
@@ -184,7 +184,7 @@ endif;
184
  endif;
185
  ?>
186
 
187
- <h4 class="zerospam-modal-headline"><?php echo esc_html_e( 'Additional Details', 'zerospam' ); ?></h4>
188
  <?php
189
 
190
  if ( $submission_data ) :
16
  ?>
17
  <div class="zerospam-modal-details">
18
  <div class="zerospam-modal-title">
19
+ <h3><?php echo esc_html_e( 'Detection ID', 'zero-spam' ); ?> #<?php echo esc_html( $item['log_id'] ); ?></h3>
20
  </div>
21
  <div class="zerospam-modal-subtitle">
22
  <?php
31
 
32
  <ul class="zerospam-modal-list">
33
  <li>
34
+ <strong><?php esc_html_e( 'IP Address', 'zero-spam' ); ?></strong>
35
  <span>
36
  <?php
37
  $lookup_url = ZEROSPAM_URL . 'ip-lookup/';
43
  echo sprintf(
44
  wp_kses(
45
  /* translators: %1s: Replaced with the IP address, %2$s Replaced with the IP lookup URL */
46
+ __( '%1$s &mdash; <a href="%2$s" target="_blank" rel="noreferrer noopener" class="zerospam-new-window-link">IP Lookup</a>', 'zero-spam' ),
47
  array(
48
  'a' => array(
49
  'target' => array(),
60
  </span>
61
  </li>
62
  <li>
63
+ <strong><?php esc_html_e( 'Type', 'zero-spam' ); ?></strong>
64
  <span>
65
  <?php
66
  $detection_types = apply_filters( 'zerospam_types', array() );
77
  </li>
78
  <?php if ( $submission_data && ! empty( $submission_data['failed'] ) ) : ?>
79
  <li>
80
+ <strong><?php esc_html_e( 'Failed', 'zero-spam' ); ?></strong>
81
  <span>
82
  <?php
83
  $failed_types = apply_filters( 'zerospam_failed_types', array() );
99
  </ul>
100
 
101
  <button class="button action zerospam-block-trigger" data-id="<?php echo esc_attr( $item['log_id'] ); ?>">
102
+ <?php esc_html_e( 'Block IP', 'zero-spam' ); ?>
103
  </button>
104
 
105
  <?php if ( ! empty( $item['latitude'] ) && ! empty( $item['longitude'] ) ) : ?>
106
+ <h4 class="zerospam-modal-headline"><?php esc_html_e( 'Location', 'zero-spam' ); ?></h4>
107
  <?php
108
  $coordinates = $item['latitude'] . ',' . $item['longitude'];
109
  do_action( 'zerospam_google_map', $coordinates );
111
  <ul class="zerospam-modal-list">
112
  <?php if ( ! empty( $item['country'] ) ) : ?>
113
  <li>
114
+ <strong><?php esc_html_e( 'Country', 'zero-spam' ); ?></strong>
115
  <span>
116
  <?php
117
  $country_name = ! empty( $item['country_name'] ) ? $item['country_name'] : false;
141
  <?php endif; ?>
142
  <?php if ( ! empty( $item['region'] ) || ! empty( $item['region_name'] ) ) : ?>
143
  <li>
144
+ <strong><?php esc_html_e( 'Region', 'zero-spam' ); ?></strong>
145
  <span>
146
  <?php if ( ! empty( $item['region_name'] ) ) : ?>
147
  <?php echo esc_html( $item['region_name'] ); ?>
154
  <?php endif; ?>
155
  <?php if ( ! empty( $item['city'] ) ) : ?>
156
  <li>
157
+ <strong><?php echo esc_html_e( 'City', 'zero-spam' ); ?></strong>
158
  <span><?php echo esc_html( $item['city'] ); ?>
159
  </span>
160
  </li>
161
  <?php endif; ?>
162
  <?php if ( ! empty( $item['zip'] ) ) : ?>
163
  <li>
164
+ <strong><?php echo esc_html_e( 'Zip/Postal Code', 'zero-spam' ); ?></strong>
165
  <span><?php echo esc_html( $item['zip'] ); ?>
166
  </span>
167
  </li>
168
  <?php endif; ?>
169
  <?php if ( ! empty( $item['latitude'] ) || ! empty( $item['region_name'] ) ) : ?>
170
  <li>
171
+ <strong><?php echo esc_html_e( 'Coordinates', 'zero-spam' ); ?></strong>
172
  <span>
173
  <?php if ( ! empty( $item['latitude'] ) ) : ?>
174
  <?php echo esc_html( $item['latitude'] ); ?>&deg;,
184
  endif;
185
  ?>
186
 
187
+ <h4 class="zerospam-modal-headline"><?php echo esc_html_e( 'Additional Details', 'zero-spam' ); ?></h4>
188
  <?php
189
 
190
  if ( $submission_data ) :
includes/templates/admin-pie.php CHANGED
@@ -8,7 +8,7 @@
8
  if ( empty( $entries ) ) {
9
  echo sprintf(
10
  wp_kses(
11
- __( 'Nothing to report yet.', 'zerospam' ),
12
  array(
13
  'strong' => array(),
14
  )
@@ -53,7 +53,7 @@ if ( empty( $countries ) ) :
53
  echo sprintf(
54
  wp_kses(
55
  /* translators: %s: url */
56
- __( 'No geolocation information available, enable ipstack and/or IPinfo on the <a href="%1$s">settings page</a>.', 'zerospam' ),
57
  array(
58
  'a' => array( 'href' => array() ),
59
  )
8
  if ( empty( $entries ) ) {
9
  echo sprintf(
10
  wp_kses(
11
+ __( 'Nothing to report yet.', 'zero-spam' ),
12
  array(
13
  'strong' => array(),
14
  )
53
  echo sprintf(
54
  wp_kses(
55
  /* translators: %s: url */
56
+ __( 'No geolocation information available, enable ipstack and/or IPinfo on the <a href="%1$s">settings page</a>.', 'zero-spam' ),
57
  array(
58
  'a' => array( 'href' => array() ),
59
  )
includes/templates/settings/errors.php CHANGED
@@ -7,15 +7,15 @@
7
 
8
  $log = \ZeroSpam\Core\Utilities::get_error_log();
9
  if ( ! $log ) {
10
- esc_html_e( 'Yay! No errors have been reported.', 'zerospam' );
11
  return;
12
  }
13
  ?>
14
 
15
  <textarea readonly class="large-text code" rows="30"><?php echo esc_html( $log ); ?></textarea>
16
  <a
17
- href="<?php echo esc_url( wp_nonce_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=delete-error-log' ), 'delete-error-log', 'zerospam' ) ); ?>"
18
  class="button button-primary"
19
  >
20
- <?php esc_html_e( 'Clear Error Log', 'zerospam' ); ?>
21
  </a>
7
 
8
  $log = \ZeroSpam\Core\Utilities::get_error_log();
9
  if ( ! $log ) {
10
+ esc_html_e( 'Yay! No errors have been reported.', 'zero-spam' );
11
  return;
12
  }
13
  ?>
14
 
15
  <textarea readonly class="large-text code" rows="30"><?php echo esc_html( $log ); ?></textarea>
16
  <a
17
+ href="<?php echo esc_url( wp_nonce_url( admin_url( 'options-general.php?page=wordpress-zero-spam-settings&zerospam-action=delete-error-log' ), 'delete-error-log', 'zero-spam' ) ); ?>"
18
  class="button button-primary"
19
  >
20
+ <?php esc_html_e( 'Clear Error Log', 'zero-spam' ); ?>
21
  </a>
includes/templates/settings/export.php CHANGED
@@ -13,22 +13,22 @@
13
  <?php
14
  switch( intval( $_GET['zerospam-error'] ) ) :
15
  case 1:
16
- esc_html_e( 'There was a problem importing the settings JSON. Please try again.', 'zerospam' );
17
  break;
18
  endswitch;
19
  ?>
20
  </strong></p>
21
- <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'zerospam' ); ?></span></button>
22
  </div>
23
  <?php elseif ( ! empty( $_GET['zerospam-success'] ) ) : ?>
24
  <div class="notice notice-success is-dismissible">
25
- <p><strong><?php esc_html_e( 'The settings JSON has been successfully imported.', 'zerospam' ); ?></strong></p>
26
- <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'zerospam' ); ?>.</span></button>
27
  </div>
28
  <?php endif; ?>
29
 
30
- <h3><?php esc_html_e( 'Settings Import/Export', 'zerospam' ); ?></h3>
31
- <p><?php esc_html_e( 'Quickly export and import your saved settings into other sites below.', 'zerospam' ); ?></p>
32
  <?php
33
  $settings = ZeroSpam\Core\Settings::get_settings();
34
  $settings_json = array();
@@ -40,17 +40,17 @@ endforeach;
40
  ?>
41
  <div class="zerospam-export-import-block">
42
  <div class="zerospam-export-import-block-column">
43
- <h4><?php esc_html_e( 'Settings JSON', 'zerospam' ); ?></h4>
44
  <textarea readonly class="large-text code" rows="10"><?php echo wp_json_encode( $settings_json ); ?></textarea>
45
  </div>
46
  <div class="zerospam-export-import-block-column">
47
- <h4><?php esc_html_e( 'Paste the settings JSON to import.', 'zerospam' ); ?></h4>
48
  <form method="post" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>" class="zerospam-import-settings-form">
49
  <?php wp_nonce_field( 'import_settings', 'zerospam' ); ?>
50
  <input type="hidden" name="action" value="import_settings" />
51
  <input type="hidden" name="redirect" value="<?php echo esc_url( ZeroSpam\Core\Utilities::current_url() ); ?>" />
52
  <textarea class="large-text code" name="settings" rows="10"></textarea>
53
- <input type="submit" class="button button-primary" value="<?php esc_html_e( 'Import Settings', 'zerospam' ); ?>" />
54
  </form>
55
  </div>
56
  </div>
13
  <?php
14
  switch( intval( $_GET['zerospam-error'] ) ) :
15
  case 1:
16
+ esc_html_e( 'There was a problem importing the settings JSON. Please try again.', 'zero-spam' );
17
  break;
18
  endswitch;
19
  ?>
20
  </strong></p>
21
+ <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'zero-spam' ); ?></span></button>
22
  </div>
23
  <?php elseif ( ! empty( $_GET['zerospam-success'] ) ) : ?>
24
  <div class="notice notice-success is-dismissible">
25
+ <p><strong><?php esc_html_e( 'The settings JSON has been successfully imported.', 'zero-spam' ); ?></strong></p>
26
+ <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'zero-spam' ); ?>.</span></button>
27
  </div>
28
  <?php endif; ?>
29
 
30
+ <h3><?php esc_html_e( 'Settings Import/Export', 'zero-spam' ); ?></h3>
31
+ <p><?php esc_html_e( 'Quickly export and import your saved settings into other sites below.', 'zero-spam' ); ?></p>
32
  <?php
33
  $settings = ZeroSpam\Core\Settings::get_settings();
34
  $settings_json = array();
40
  ?>
41
  <div class="zerospam-export-import-block">
42
  <div class="zerospam-export-import-block-column">
43
+ <h4><?php esc_html_e( 'Settings JSON', 'zero-spam' ); ?></h4>
44
  <textarea readonly class="large-text code" rows="10"><?php echo wp_json_encode( $settings_json ); ?></textarea>
45
  </div>
46
  <div class="zerospam-export-import-block-column">
47
+ <h4><?php esc_html_e( 'Paste the settings JSON to import.', 'zero-spam' ); ?></h4>
48
  <form method="post" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>" class="zerospam-import-settings-form">
49
  <?php wp_nonce_field( 'import_settings', 'zerospam' ); ?>
50
  <input type="hidden" name="action" value="import_settings" />
51
  <input type="hidden" name="redirect" value="<?php echo esc_url( ZeroSpam\Core\Utilities::current_url() ); ?>" />
52
  <textarea class="large-text code" name="settings" rows="10"></textarea>
53
+ <input type="submit" class="button button-primary" value="<?php esc_html_e( 'Import Settings', 'zero-spam' ); ?>" />
54
  </form>
55
  </div>
56
  </div>
modules/class-debug.php CHANGED
@@ -55,7 +55,7 @@ class Debug {
55
  */
56
  public function sections( $sections ) {
57
  $sections['debug'] = array(
58
- 'title' => __( 'Debug', 'zerospam' ),
59
  );
60
 
61
  return $sections;
@@ -69,21 +69,21 @@ class Debug {
69
  */
70
  public function settings( $settings, $options ) {
71
  $settings['debug'] = array(
72
- 'title' => __( 'Debug', 'zerospam' ),
73
- 'desc' => __( 'For troubleshooting site issues.', 'zerospam' ),
74
  'section' => 'debug',
75
  'type' => 'checkbox',
76
  'options' => array(
77
- 'enabled' => __( 'Enabled', 'zerospam' ),
78
  ),
79
  'value' => ! empty( $options['debug'] ) ? $options['debug'] : false,
80
  );
81
 
82
  $settings['debug_ip'] = array(
83
- 'title' => __( 'Debug IP', 'zerospam' ),
84
  'desc' => wp_kses(
85
  /* translators: %s: url */
86
- __( 'Mock a IP address for debugging. <strong>WARNING: This overrides all visitor IP addresses and while enabled could block legit visitors from accessing the site.</strong>', 'zerospam' ),
87
  array(
88
  'strong' => array(),
89
  )
55
  */
56
  public function sections( $sections ) {
57
  $sections['debug'] = array(
58
+ 'title' => __( 'Debug', 'zero-spam' ),
59
  );
60
 
61
  return $sections;
69
  */
70
  public function settings( $settings, $options ) {
71
  $settings['debug'] = array(
72
+ 'title' => __( 'Debug', 'zero-spam' ),
73
+ 'desc' => __( 'For troubleshooting site issues.', 'zero-spam' ),
74
  'section' => 'debug',
75
  'type' => 'checkbox',
76
  'options' => array(
77
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
78
  ),
79
  'value' => ! empty( $options['debug'] ) ? $options['debug'] : false,
80
  );
81
 
82
  $settings['debug_ip'] = array(
83
+ 'title' => __( 'Debug IP', 'zero-spam' ),
84
  'desc' => wp_kses(
85
  /* translators: %s: url */
86
+ __( 'Mock a IP address for debugging. <strong>WARNING: This overrides all visitor IP addresses and while enabled could block legit visitors from accessing the site.</strong>', 'zero-spam' ),
87
  array(
88
  'strong' => array(),
89
  )
modules/class-google.php CHANGED
@@ -69,7 +69,7 @@ class Google {
69
  */
70
  public function sections( $sections ) {
71
  $sections['google'] = array(
72
- 'title' => __( 'Google API Integration (geolocation)', 'zerospam' ),
73
  );
74
 
75
  return $sections;
@@ -83,15 +83,15 @@ class Google {
83
  */
84
  public function settings( $settings, $options ) {
85
  $settings['google_api'] = array(
86
- 'title' => __( 'Google API Key', 'zerospam' ),
87
  'section' => 'google',
88
  'type' => 'text',
89
  'field_class' => 'regular-text',
90
- 'placeholder' => __( 'Enter your Google API key.', 'zerospam' ),
91
  'desc' => sprintf(
92
  wp_kses(
93
  /* translators: %1$s: Replaced with the Google API key URL */
94
- __( 'Enter your <a href="%1$s" target="_blank" rel="noopener noreferrer">Google API key</a> for Google Maps integration.', 'zerospam' ),
95
  array(
96
  'a' => array(
97
  'target' => array(),
69
  */
70
  public function sections( $sections ) {
71
  $sections['google'] = array(
72
+ 'title' => __( 'Google API Integration (geolocation)', 'zero-spam' ),
73
  );
74
 
75
  return $sections;
83
  */
84
  public function settings( $settings, $options ) {
85
  $settings['google_api'] = array(
86
+ 'title' => __( 'Google API Key', 'zero-spam' ),
87
  'section' => 'google',
88
  'type' => 'text',
89
  'field_class' => 'regular-text',
90
+ 'placeholder' => __( 'Enter your Google API key.', 'zero-spam' ),
91
  'desc' => sprintf(
92
  wp_kses(
93
  /* translators: %1$s: Replaced with the Google API key URL */
94
+ __( 'Enter your <a href="%1$s" target="_blank" rel="noopener noreferrer">Google API key</a> for Google Maps integration.', 'zero-spam' ),
95
  array(
96
  'a' => array(
97
  'target' => array(),
modules/class-ipinfomodule.php CHANGED
@@ -39,7 +39,7 @@ class IPinfoModule {
39
  */
40
  public function sections( $sections ) {
41
  $sections['ipinfo'] = array(
42
- 'title' => __( 'IPinfo Integration (geolocation)', 'zerospam' ),
43
  );
44
 
45
  return $sections;
@@ -53,11 +53,11 @@ class IPinfoModule {
53
  */
54
  public function settings( $settings, $options ) {
55
  $settings['ipinfo_access_token'] = array(
56
- 'title' => __( 'Access Token', 'zerospam' ),
57
  'desc' => sprintf(
58
  wp_kses(
59
  /* translators: %1$s: Replaced with the IPInfo URL, %2$s: Replaced with the IPinfo signup URL */
60
- __( 'Enter your <a href="%1$s" target="_blank" rel="noopener noreferrer">IPinfo access token</a> to enable geolocation features. Don\'t have an API key? <a href="%2$s" target="_blank" rel="noopener noreferrer"><strong>Get one for free!</strong></a>', 'zerospam' ),
61
  array(
62
  'strong' => array(),
63
  'a' => array(
@@ -73,18 +73,18 @@ class IPinfoModule {
73
  'section' => 'ipinfo',
74
  'type' => 'text',
75
  'field_class' => 'regular-text',
76
- 'placeholder' => __( 'Enter your IPinfo access token.', 'zerospam' ),
77
  'value' => ! empty( $options['ipinfo_access_token'] ) ? $options['ipinfo_access_token'] : false,
78
  );
79
 
80
  $settings['ipinfo_cache'] = array(
81
- 'title' => __( 'Cache Expiration', 'zerospam' ),
82
  'section' => 'ipinfo',
83
  'type' => 'number',
84
  'field_class' => 'small-text',
85
- 'suffix' => __( 'day(s)', 'zerospam' ),
86
- 'placeholder' => __( '14', 'zerospam' ),
87
- 'desc' => __( 'Setting to high could result in outdated information, too low could cause a decrease in performance; recommended 14 days.', 'zerospam' ),
88
  'value' => ! empty( $options['ipinfo_cache'] ) ? $options['ipinfo_cache'] : 14,
89
  'recommended' => 14,
90
  );
39
  */
40
  public function sections( $sections ) {
41
  $sections['ipinfo'] = array(
42
+ 'title' => __( 'IPinfo Integration (geolocation)', 'zero-spam' ),
43
  );
44
 
45
  return $sections;
53
  */
54
  public function settings( $settings, $options ) {
55
  $settings['ipinfo_access_token'] = array(
56
+ 'title' => __( 'Access Token', 'zero-spam' ),
57
  'desc' => sprintf(
58
  wp_kses(
59
  /* translators: %1$s: Replaced with the IPInfo URL, %2$s: Replaced with the IPinfo signup URL */
60
+ __( 'Enter your <a href="%1$s" target="_blank" rel="noopener noreferrer">IPinfo access token</a> to enable geolocation features. Don\'t have an API key? <a href="%2$s" target="_blank" rel="noopener noreferrer"><strong>Get one for free!</strong></a>', 'zero-spam' ),
61
  array(
62
  'strong' => array(),
63
  'a' => array(
73
  'section' => 'ipinfo',
74
  'type' => 'text',
75
  'field_class' => 'regular-text',
76
+ 'placeholder' => __( 'Enter your IPinfo access token.', 'zero-spam' ),
77
  'value' => ! empty( $options['ipinfo_access_token'] ) ? $options['ipinfo_access_token'] : false,
78
  );
79
 
80
  $settings['ipinfo_cache'] = array(
81
+ 'title' => __( 'Cache Expiration', 'zero-spam' ),
82
  'section' => 'ipinfo',
83
  'type' => 'number',
84
  'field_class' => 'small-text',
85
+ 'suffix' => __( 'day(s)', 'zero-spam' ),
86
+ 'placeholder' => __( '14', 'zero-spam' ),
87
+ 'desc' => __( 'Setting to high could result in outdated information, too low could cause a decrease in performance; recommended 14 days.', 'zero-spam' ),
88
  'value' => ! empty( $options['ipinfo_cache'] ) ? $options['ipinfo_cache'] : 14,
89
  'recommended' => 14,
90
  );
modules/class-ipstack.php CHANGED
@@ -37,7 +37,7 @@ class ipstack {
37
  */
38
  public function sections( $sections ) {
39
  $sections['ipstack'] = array(
40
- 'title' => __( 'ipstack Integration (geolocation)', 'zerospam' ),
41
  );
42
 
43
  return $sections;
@@ -51,11 +51,11 @@ class ipstack {
51
  */
52
  public function settings( $settings, $options ) {
53
  $settings['ipstack_api'] = array(
54
- 'title' => __( 'API Key', 'zerospam' ),
55
  'desc' => sprintf(
56
  wp_kses(
57
  /* translators: %1$s: Replaced with the ipstack URL, %2$s: Replaced with the ipstack product URL */
58
- __( 'Enter your <a href="%1$s" target="_blank" rel="noopener noreferrer">ipstack API key</a> to enable geolocation features. Don\'t have an API key? <a href="%2$s" target="_blank" rel="noopener noreferrer"><strong>Get one for free!</strong></a>', 'zerospam' ),
59
  array(
60
  'strong' => array(),
61
  'a' => array(
@@ -71,30 +71,30 @@ class ipstack {
71
  'section' => 'ipstack',
72
  'type' => 'text',
73
  'field_class' => 'regular-text',
74
- 'placeholder' => __( 'Enter your ipstack API key.', 'zerospam' ),
75
  'value' => ! empty( $options['ipstack_api'] ) ? $options['ipstack_api'] : false,
76
  );
77
 
78
  $settings['ipstack_timeout'] = array(
79
- 'title' => __( 'API Timeout', 'zerospam' ),
80
  'section' => 'ipstack',
81
  'type' => 'number',
82
  'field_class' => 'small-text',
83
- 'suffix' => __( 'seconds', 'zerospam' ),
84
- 'placeholder' => __( '5', 'zerospam' ),
85
- 'desc' => __( 'Setting to high could result in degraded site performance, too low won\'t allow to API enough time to respond; recommended 5 seconds.', 'zerospam' ),
86
  'value' => ! empty( $options['ipstack_timeout'] ) ? $options['ipstack_timeout'] : 5,
87
  'recommended' => 5,
88
  );
89
 
90
  $settings['ipstack_cache'] = array(
91
- 'title' => __( 'Cache Expiration', 'zerospam' ),
92
  'section' => 'ipstack',
93
  'type' => 'number',
94
  'field_class' => 'small-text',
95
- 'suffix' => __( 'day(s)', 'zerospam' ),
96
- 'placeholder' => __( '14', 'zerospam' ),
97
- 'desc' => __( 'Setting to high could result in outdated information, too low could cause a decrease in performance; recommended 14 days.', 'zerospam' ),
98
  'value' => ! empty( $options['ipstack_cache'] ) ? $options['ipstack_cache'] : 14,
99
  'recommended' => 14,
100
  );
37
  */
38
  public function sections( $sections ) {
39
  $sections['ipstack'] = array(
40
+ 'title' => __( 'ipstack Integration (geolocation)', 'zero-spam' ),
41
  );
42
 
43
  return $sections;
51
  */
52
  public function settings( $settings, $options ) {
53
  $settings['ipstack_api'] = array(
54
+ 'title' => __( 'API Key', 'zero-spam' ),
55
  'desc' => sprintf(
56
  wp_kses(
57
  /* translators: %1$s: Replaced with the ipstack URL, %2$s: Replaced with the ipstack product URL */
58
+ __( 'Enter your <a href="%1$s" target="_blank" rel="noopener noreferrer">ipstack API key</a> to enable geolocation features. Don\'t have an API key? <a href="%2$s" target="_blank" rel="noopener noreferrer"><strong>Get one for free!</strong></a>', 'zero-spam' ),
59
  array(
60
  'strong' => array(),
61
  'a' => array(
71
  'section' => 'ipstack',
72
  'type' => 'text',
73
  'field_class' => 'regular-text',
74
+ 'placeholder' => __( 'Enter your ipstack API key.', 'zero-spam' ),
75
  'value' => ! empty( $options['ipstack_api'] ) ? $options['ipstack_api'] : false,
76
  );
77
 
78
  $settings['ipstack_timeout'] = array(
79
+ 'title' => __( 'API Timeout', 'zero-spam' ),
80
  'section' => 'ipstack',
81
  'type' => 'number',
82
  'field_class' => 'small-text',
83
+ 'suffix' => __( 'seconds', 'zero-spam' ),
84
+ 'placeholder' => __( '5', 'zero-spam' ),
85
+ 'desc' => __( 'Setting to high could result in degraded site performance, too low won\'t allow to API enough time to respond; recommended 5 seconds.', 'zero-spam' ),
86
  'value' => ! empty( $options['ipstack_timeout'] ) ? $options['ipstack_timeout'] : 5,
87
  'recommended' => 5,
88
  );
89
 
90
  $settings['ipstack_cache'] = array(
91
+ 'title' => __( 'Cache Expiration', 'zero-spam' ),
92
  'section' => 'ipstack',
93
  'type' => 'number',
94
  'field_class' => 'small-text',
95
+ 'suffix' => __( 'day(s)', 'zero-spam' ),
96
+ 'placeholder' => __( '14', 'zero-spam' ),
97
+ 'desc' => __( 'Setting to high could result in outdated information, too low could cause a decrease in performance; recommended 14 days.', 'zero-spam' ),
98
  'value' => ! empty( $options['ipstack_cache'] ) ? $options['ipstack_cache'] : 14,
99
  'recommended' => 14,
100
  );
modules/class-projecthoneypot.php CHANGED
@@ -168,7 +168,7 @@ class ProjectHoneypot {
168
  */
169
  public function sections( $sections ) {
170
  $sections['project_honeypot'] = array(
171
- 'title' => __( 'Project Honeypot Integration', 'zerospam' ),
172
  );
173
 
174
  return $sections;
@@ -182,16 +182,16 @@ class ProjectHoneypot {
182
  */
183
  public function settings( $settings, $options ) {
184
  $settings['project_honeypot'] = array(
185
- 'title' => __( 'Status', 'zerospam' ),
186
  'section' => 'project_honeypot',
187
  'type' => 'checkbox',
188
  'options' => array(
189
- 'enabled' => __( 'Enabled', 'zerospam' ),
190
  ),
191
  'desc' => sprintf(
192
  wp_kses(
193
  /* translators: %s: Replaced with the Project Honeypot URL */
194
- __( 'Blocks visitor IPs that have been reported to <a href="%s" target="_blank" rel="noopener noreferrer">Project Honeypot</a>.', 'zerospam' ),
195
  array(
196
  'strong' => array(),
197
  'a' => array(
@@ -208,11 +208,11 @@ class ProjectHoneypot {
208
  );
209
 
210
  $settings['project_honeypot_access_key'] = array(
211
- 'title' => __( 'Access Key', 'zerospam' ),
212
  'desc' => sprintf(
213
  wp_kses(
214
  /* translators: %1s: Replaced with the Project Honeypot URL, %2s: Replaced with the Project Honeypot account creation URL */
215
- __( 'Enter your <a href="%1$s" target="_blank" rel="noopener noreferrer">Project Honeypot</a> access key. Don\'t have an access key? <a href="%2$s" target="_blank" rel="noopener noreferrer"><strong>Get one for free!</strong></a>', 'zerospam' ),
216
  array(
217
  'strong' => array(),
218
  'a' => array(
@@ -228,36 +228,36 @@ class ProjectHoneypot {
228
  'section' => 'project_honeypot',
229
  'type' => 'text',
230
  'field_class' => 'regular-text',
231
- 'placeholder' => __( 'Enter your Project Honeypot access key.', 'zerospam' ),
232
  'value' => ! empty( $options['project_honeypot_access_key'] ) ? $options['project_honeypot_access_key'] : false,
233
  );
234
 
235
  $settings['project_honeypot_cache'] = array(
236
- 'title' => __( 'Cache Expiration', 'zerospam' ),
237
  'section' => 'project_honeypot',
238
  'type' => 'number',
239
  'field_class' => 'small-text',
240
- 'suffix' => __( 'day(s)', 'zerospam' ),
241
  'placeholder' => WEEK_IN_SECONDS,
242
  'min' => 0,
243
- 'desc' => __( 'Setting to high could result in outdated information, too low could cause a decrease in performance; recommended 14 days.', 'zerospam' ),
244
  'value' => ! empty( $options['project_honeypot_cache'] ) ? $options['project_honeypot_cache'] : 14,
245
  'recommended' => 14,
246
  );
247
 
248
  $settings['project_honeypot_score_min'] = array(
249
- 'title' => __( 'Threat Score Minimum', 'zerospam' ),
250
  'section' => 'project_honeypot',
251
  'type' => 'number',
252
  'field_class' => 'small-text',
253
- 'placeholder' => __( '50', 'zerospam' ),
254
  'min' => 0,
255
  'max' => 255,
256
  'step' => 1,
257
  'desc' => sprintf(
258
  wp_kses(
259
  /* translators: %s: Replaced with the Project Honeypot threat page URL */
260
- __( 'Minimum <a href="%s" target="_blank" rel="noopener noreferrer">threat score</a> an IP must meet before being blocked. Setting this too low could cause users to be blocked that shouldn\'t be; recommended 50.', 'zerospam' ),
261
  array(
262
  'a' => array(
263
  'target' => array(),
168
  */
169
  public function sections( $sections ) {
170
  $sections['project_honeypot'] = array(
171
+ 'title' => __( 'Project Honeypot Integration', 'zero-spam' ),
172
  );
173
 
174
  return $sections;
182
  */
183
  public function settings( $settings, $options ) {
184
  $settings['project_honeypot'] = array(
185
+ 'title' => __( 'Status', 'zero-spam' ),
186
  'section' => 'project_honeypot',
187
  'type' => 'checkbox',
188
  'options' => array(
189
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
190
  ),
191
  'desc' => sprintf(
192
  wp_kses(
193
  /* translators: %s: Replaced with the Project Honeypot URL */
194
+ __( 'Blocks visitor IPs that have been reported to <a href="%s" target="_blank" rel="noopener noreferrer">Project Honeypot</a>.', 'zero-spam' ),
195
  array(
196
  'strong' => array(),
197
  'a' => array(
208
  );
209
 
210
  $settings['project_honeypot_access_key'] = array(
211
+ 'title' => __( 'Access Key', 'zero-spam' ),
212
  'desc' => sprintf(
213
  wp_kses(
214
  /* translators: %1s: Replaced with the Project Honeypot URL, %2s: Replaced with the Project Honeypot account creation URL */
215
+ __( 'Enter your <a href="%1$s" target="_blank" rel="noopener noreferrer">Project Honeypot</a> access key. Don\'t have an access key? <a href="%2$s" target="_blank" rel="noopener noreferrer"><strong>Get one for free!</strong></a>', 'zero-spam' ),
216
  array(
217
  'strong' => array(),
218
  'a' => array(
228
  'section' => 'project_honeypot',
229
  'type' => 'text',
230
  'field_class' => 'regular-text',
231
+ 'placeholder' => __( 'Enter your Project Honeypot access key.', 'zero-spam' ),
232
  'value' => ! empty( $options['project_honeypot_access_key'] ) ? $options['project_honeypot_access_key'] : false,
233
  );
234
 
235
  $settings['project_honeypot_cache'] = array(
236
+ 'title' => __( 'Cache Expiration', 'zero-spam' ),
237
  'section' => 'project_honeypot',
238
  'type' => 'number',
239
  'field_class' => 'small-text',
240
+ 'suffix' => __( 'day(s)', 'zero-spam' ),
241
  'placeholder' => WEEK_IN_SECONDS,
242
  'min' => 0,
243
+ 'desc' => __( 'Setting to high could result in outdated information, too low could cause a decrease in performance; recommended 14 days.', 'zero-spam' ),
244
  'value' => ! empty( $options['project_honeypot_cache'] ) ? $options['project_honeypot_cache'] : 14,
245
  'recommended' => 14,
246
  );
247
 
248
  $settings['project_honeypot_score_min'] = array(
249
+ 'title' => __( 'Threat Score Minimum', 'zero-spam' ),
250
  'section' => 'project_honeypot',
251
  'type' => 'number',
252
  'field_class' => 'small-text',
253
+ 'placeholder' => __( '50', 'zero-spam' ),
254
  'min' => 0,
255
  'max' => 255,
256
  'step' => 1,
257
  'desc' => sprintf(
258
  wp_kses(
259
  /* translators: %s: Replaced with the Project Honeypot threat page URL */
260
+ __( 'Minimum <a href="%s" target="_blank" rel="noopener noreferrer">threat score</a> an IP must meet before being blocked. Setting this too low could cause users to be blocked that shouldn\'t be; recommended 50.', 'zero-spam' ),
261
  array(
262
  'a' => array(
263
  'target' => array(),
modules/class-stopforumspam.php CHANGED
@@ -45,7 +45,7 @@ class StopForumSpam {
45
  */
46
  public function sections( $sections ) {
47
  $sections['stop_forum_spam'] = array(
48
- 'title' => __( 'Stop Forum Spam Integration', 'zerospam' ),
49
  );
50
 
51
  return $sections;
@@ -59,16 +59,16 @@ class StopForumSpam {
59
  */
60
  public function settings( $settings, $options ) {
61
  $settings['stop_forum_spam'] = array(
62
- 'title' => __( 'Status', 'zerospam' ),
63
  'section' => 'stop_forum_spam',
64
  'type' => 'checkbox',
65
  'options' => array(
66
- 'enabled' => __( 'Enabled', 'zerospam' ),
67
  ),
68
  'desc' => sprintf(
69
  wp_kses(
70
  /* translators: %s: Replaced with the Stop Forum Spam URL */
71
- __( 'Blocks visitor IPs that have been reported to <a href="%s" target="_blank" rel="noopener noreferrer">Stop Forum Spam</a>.', 'zerospam' ),
72
  array(
73
  'strong' => array(),
74
  'a' => array(
@@ -85,45 +85,45 @@ class StopForumSpam {
85
  );
86
 
87
  $settings['stop_forum_spam_timeout'] = array(
88
- 'title' => __( 'API Timeout', 'zerospam' ),
89
  'section' => 'stop_forum_spam',
90
  'type' => 'number',
91
  'field_class' => 'small-text',
92
- 'suffix' => __( 'seconds', 'zerospam' ),
93
- 'placeholder' => __( '5', 'zerospam' ),
94
  'min' => 0,
95
- 'desc' => __( 'Setting to high could result in degraded site performance, too low won\'t allow to API enough time to respond; recommended 5 seconds.', 'zerospam' ),
96
  'value' => ! empty( $options['stop_forum_spam_timeout'] ) ? $options['stop_forum_spam_timeout'] : 5,
97
  'recommended' => 5,
98
  );
99
 
100
  $settings['stop_forum_spam_cache'] = array(
101
- 'title' => __( 'Cache Expiration', 'zerospam' ),
102
  'section' => 'stop_forum_spam',
103
  'type' => 'number',
104
  'field_class' => 'small-text',
105
- 'suffix' => __( 'day(s)', 'zerospam' ),
106
  'placeholder' => WEEK_IN_SECONDS,
107
  'min' => 0,
108
- 'desc' => __( 'Setting to high could result in outdated information, too low could cause a decrease in performance; recommended 14 days.', 'zerospam' ),
109
  'value' => ! empty( $options['stop_forum_spam_cache'] ) ? $options['stop_forum_spam_cache'] : 14,
110
  'recommended' => 14,
111
  );
112
 
113
  $settings['stop_forum_spam_confidence_min'] = array(
114
- 'title' => __( 'Confidence Minimum', 'zerospam' ),
115
  'section' => 'stop_forum_spam',
116
  'type' => 'number',
117
  'field_class' => 'small-text',
118
- 'suffix' => __( '%', 'zerospam' ),
119
- 'placeholder' => __( '50', 'zerospam' ),
120
  'min' => 0,
121
  'max' => 100,
122
  'step' => 0.1,
123
  'desc' => sprintf(
124
  wp_kses(
125
  /* translators: %s: Replaced with the Stop Forum Spam URL */
126
- __( 'Minimum <a href="%s" target="_blank" rel="noopener noreferrer">confidence score</a> an IP must meet before being blocked. Setting this too low could cause users to be blocked that shouldn\'t be; recommended 50%%', 'zerospam' ),
127
  array(
128
  'a' => array(
129
  'target' => array(),
45
  */
46
  public function sections( $sections ) {
47
  $sections['stop_forum_spam'] = array(
48
+ 'title' => __( 'Stop Forum Spam Integration', 'zero-spam' ),
49
  );
50
 
51
  return $sections;
59
  */
60
  public function settings( $settings, $options ) {
61
  $settings['stop_forum_spam'] = array(
62
+ 'title' => __( 'Status', 'zero-spam' ),
63
  'section' => 'stop_forum_spam',
64
  'type' => 'checkbox',
65
  'options' => array(
66
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
67
  ),
68
  'desc' => sprintf(
69
  wp_kses(
70
  /* translators: %s: Replaced with the Stop Forum Spam URL */
71
+ __( 'Blocks visitor IPs that have been reported to <a href="%s" target="_blank" rel="noopener noreferrer">Stop Forum Spam</a>.', 'zero-spam' ),
72
  array(
73
  'strong' => array(),
74
  'a' => array(
85
  );
86
 
87
  $settings['stop_forum_spam_timeout'] = array(
88
+ 'title' => __( 'API Timeout', 'zero-spam' ),
89
  'section' => 'stop_forum_spam',
90
  'type' => 'number',
91
  'field_class' => 'small-text',
92
+ 'suffix' => __( 'seconds', 'zero-spam' ),
93
+ 'placeholder' => __( '5', 'zero-spam' ),
94
  'min' => 0,
95
+ 'desc' => __( 'Setting to high could result in degraded site performance, too low won\'t allow to API enough time to respond; recommended 5 seconds.', 'zero-spam' ),
96
  'value' => ! empty( $options['stop_forum_spam_timeout'] ) ? $options['stop_forum_spam_timeout'] : 5,
97
  'recommended' => 5,
98
  );
99
 
100
  $settings['stop_forum_spam_cache'] = array(
101
+ 'title' => __( 'Cache Expiration', 'zero-spam' ),
102
  'section' => 'stop_forum_spam',
103
  'type' => 'number',
104
  'field_class' => 'small-text',
105
+ 'suffix' => __( 'day(s)', 'zero-spam' ),
106
  'placeholder' => WEEK_IN_SECONDS,
107
  'min' => 0,
108
+ 'desc' => __( 'Setting to high could result in outdated information, too low could cause a decrease in performance; recommended 14 days.', 'zero-spam' ),
109
  'value' => ! empty( $options['stop_forum_spam_cache'] ) ? $options['stop_forum_spam_cache'] : 14,
110
  'recommended' => 14,
111
  );
112
 
113
  $settings['stop_forum_spam_confidence_min'] = array(
114
+ 'title' => __( 'Confidence Minimum', 'zero-spam' ),
115
  'section' => 'stop_forum_spam',
116
  'type' => 'number',
117
  'field_class' => 'small-text',
118
+ 'suffix' => __( '%', 'zero-spam' ),
119
+ 'placeholder' => __( '50', 'zero-spam' ),
120
  'min' => 0,
121
  'max' => 100,
122
  'step' => 0.1,
123
  'desc' => sprintf(
124
  wp_kses(
125
  /* translators: %s: Replaced with the Stop Forum Spam URL */
126
+ __( 'Minimum <a href="%s" target="_blank" rel="noopener noreferrer">confidence score</a> an IP must meet before being blocked. Setting this too low could cause users to be blocked that shouldn\'t be; recommended 50%%', 'zero-spam' ),
127
  array(
128
  'a' => array(
129
  'target' => array(),
modules/class-zerospam.php CHANGED
@@ -45,7 +45,7 @@ class Zero_Spam {
45
  */
46
  public function sections( $sections ) {
47
  $sections['zerospam'] = array(
48
- 'title' => __( 'Zero Spam Enhanced Protection', 'zerospam' ),
49
  );
50
 
51
  return $sections;
@@ -64,7 +64,7 @@ class Zero_Spam {
64
  'html' => sprintf(
65
  wp_kses(
66
  /* translators: %1s: Replaced with the Zero Spam URL, %2$s: Replaced with the DDoD attack wiki URL */
67
- __( '<h3 style="margin-top: 0">Enabling enhanced protection is highly recommended.</h3><p>Enhanced protection adds additional checks using one of the largest, most comprehensive, constantly-growing global malicious IP, email, and username databases available, the <a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam Blacklist</a>. Once enabled, all visitors will be checked against this blacklist that includes protected forms containing email and username fields &mdash; giving you the peace of mind that submissions are coming from legitimate. It can also help prevent <a href="%2$s" target="_blank" rel="noopener noreferrer">DDoS attacks</a> &amp; fraudsters looking to test stolen credit card numbers.</p>', 'zerospam' ),
68
  array(
69
  'h3' => array(
70
  'style' => array(),
@@ -83,16 +83,16 @@ class Zero_Spam {
83
  );
84
 
85
  $settings['zerospam'] = array(
86
- 'title' => __( 'Status', 'zerospam' ),
87
  'section' => 'zerospam',
88
  'type' => 'checkbox',
89
  'options' => array(
90
- 'enabled' => __( 'Enabled', 'zerospam' ),
91
  ),
92
  'desc' => sprintf(
93
  wp_kses(
94
  /* translators: %s: Replaced with the Zero Spam URL */
95
- __( 'Blocks visitor IPs, email addresses &amp; usernames that have been reported to <a href="%s" target="_blank" rel="noopener noreferrer">Zero Spam</a>.', 'zerospam' ),
96
  array(
97
  'strong' => array(),
98
  'a' => array(
@@ -109,11 +109,11 @@ class Zero_Spam {
109
  );
110
 
111
  $settings['zerospam_license'] = array(
112
- 'title' => __( 'License Key', 'zerospam' ),
113
  'desc' => sprintf(
114
  wp_kses(
115
  /* translators: 1: the zerospam.org URL 2: the zerospam.org premium product URL */
116
- __( 'Enter your <a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam</a> license key or define it in <code>wp-config.php</code>, using the constant <code>ZEROSPAM_LICENSE_KEY</code> to enable enhanced protection. Don\'t have an license key? <a href="%2$s" target="_blank" rel="noopener noreferrer"><strong>Get one now!</strong></a>', 'zerospam' ),
117
  array(
118
  'strong' => array(),
119
  'a' => array(
@@ -130,7 +130,7 @@ class Zero_Spam {
130
  'section' => 'zerospam',
131
  'type' => 'text',
132
  'field_class' => 'regular-text',
133
- 'placeholder' => __( 'Enter your Zero Spam license key.', 'zerospam' ),
134
  'value' => ! empty( $options['zerospam_license'] ) ? $options['zerospam_license'] : false,
135
  );
136
 
@@ -139,45 +139,45 @@ class Zero_Spam {
139
  }
140
 
141
  $settings['zerospam_timeout'] = array(
142
- 'title' => __( 'API Timeout', 'zerospam' ),
143
  'section' => 'zerospam',
144
  'type' => 'number',
145
  'field_class' => 'small-text',
146
- 'suffix' => __( 'seconds', 'zerospam' ),
147
- 'placeholder' => __( '5', 'zerospam' ),
148
  'min' => 0,
149
- 'desc' => __( 'Setting to high could result in degraded site performance, too low won\'t allow to API enough time to respond; recommended 5 seconds.', 'zerospam' ),
150
  'value' => ! empty( $options['zerospam_timeout'] ) ? $options['zerospam_timeout'] : 5,
151
  'recommended' => 5,
152
  );
153
 
154
  $settings['zerospam_cache'] = array(
155
- 'title' => __( 'Cache Expiration', 'zerospam' ),
156
  'section' => 'zerospam',
157
  'type' => 'number',
158
  'field_class' => 'small-text',
159
- 'suffix' => __( 'day(s)', 'zerospam' ),
160
  'placeholder' => WEEK_IN_SECONDS,
161
  'min' => 0,
162
- 'desc' => __( 'Setting to high could result in outdated information, too low could cause a decrease in performance; recommended 14 days.', 'zerospam' ),
163
  'value' => ! empty( $options['zerospam_cache'] ) ? $options['zerospam_cache'] : 14,
164
  'recommended' => 14,
165
  );
166
 
167
  $settings['zerospam_confidence_min'] = array(
168
- 'title' => __( 'Confidence Minimum', 'zerospam' ),
169
  'section' => 'zerospam',
170
  'type' => 'number',
171
  'field_class' => 'small-text',
172
- 'suffix' => __( '%', 'zerospam' ),
173
- 'placeholder' => __( '30', 'zerospam' ),
174
  'min' => 0,
175
  'max' => 100,
176
  'step' => 0.1,
177
  'desc' => sprintf(
178
  wp_kses(
179
  /* translators: %s: Replaced with the Zero Spam API URL */
180
- __( 'Minimum <a href="%s" target="_blank" rel="noopener noreferrer">confidence score</a> an IP must meet before being blocked. Setting this too low could cause users to be blocked that shouldn\'t be; recommended 20%%.', 'zerospam' ),
181
  array(
182
  'a' => array(
183
  'target' => array(),
@@ -307,7 +307,7 @@ class Zero_Spam {
307
  if ( ! empty( $response['result'] ) ) {
308
  \ZeroSpam\Core\Utilities::log( $response['result'] );
309
  } else {
310
- \ZeroSpam\Core\Utilities::log( __( 'There was a problem querying the Zero Spam Blacklist API.', 'zerospam' ) );
311
  }
312
 
313
  return false;
45
  */
46
  public function sections( $sections ) {
47
  $sections['zerospam'] = array(
48
+ 'title' => __( 'Zero Spam Enhanced Protection', 'zero-spam' ),
49
  );
50
 
51
  return $sections;
64
  'html' => sprintf(
65
  wp_kses(
66
  /* translators: %1s: Replaced with the Zero Spam URL, %2$s: Replaced with the DDoD attack wiki URL */
67
+ __( '<h3 style="margin-top: 0">Enabling enhanced protection is highly recommended.</h3><p>Enhanced protection adds additional checks using one of the largest, most comprehensive, constantly-growing global malicious IP, email, and username databases available, the <a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam Blacklist</a>. Once enabled, all visitors will be checked against this blacklist that includes protected forms containing email and username fields &mdash; giving you the peace of mind that submissions are coming from legitimate. It can also help prevent <a href="%2$s" target="_blank" rel="noopener noreferrer">DDoS attacks</a> &amp; fraudsters looking to test stolen credit card numbers.</p>', 'zero-spam' ),
68
  array(
69
  'h3' => array(
70
  'style' => array(),
83
  );
84
 
85
  $settings['zerospam'] = array(
86
+ 'title' => __( 'Status', 'zero-spam' ),
87
  'section' => 'zerospam',
88
  'type' => 'checkbox',
89
  'options' => array(
90
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
91
  ),
92
  'desc' => sprintf(
93
  wp_kses(
94
  /* translators: %s: Replaced with the Zero Spam URL */
95
+ __( 'Blocks visitor IPs, email addresses &amp; usernames that have been reported to <a href="%s" target="_blank" rel="noopener noreferrer">Zero Spam</a>.', 'zero-spam' ),
96
  array(
97
  'strong' => array(),
98
  'a' => array(
109
  );
110
 
111
  $settings['zerospam_license'] = array(
112
+ 'title' => __( 'License Key', 'zero-spam' ),
113
  'desc' => sprintf(
114
  wp_kses(
115
  /* translators: 1: the zerospam.org URL 2: the zerospam.org premium product URL */
116
+ __( 'Enter your <a href="%1$s" target="_blank" rel="noopener noreferrer">Zero Spam</a> license key or define it in <code>wp-config.php</code>, using the constant <code>ZEROSPAM_LICENSE_KEY</code> to enable enhanced protection. Don\'t have an license key? <a href="%2$s" target="_blank" rel="noopener noreferrer"><strong>Get one now!</strong></a>', 'zero-spam' ),
117
  array(
118
  'strong' => array(),
119
  'a' => array(
130
  'section' => 'zerospam',
131
  'type' => 'text',
132
  'field_class' => 'regular-text',
133
+ 'placeholder' => __( 'Enter your Zero Spam license key.', 'zero-spam' ),
134
  'value' => ! empty( $options['zerospam_license'] ) ? $options['zerospam_license'] : false,
135
  );
136
 
139
  }
140
 
141
  $settings['zerospam_timeout'] = array(
142
+ 'title' => __( 'API Timeout', 'zero-spam' ),
143
  'section' => 'zerospam',
144
  'type' => 'number',
145
  'field_class' => 'small-text',
146
+ 'suffix' => __( 'seconds', 'zero-spam' ),
147
+ 'placeholder' => __( '5', 'zero-spam' ),
148
  'min' => 0,
149
+ 'desc' => __( 'Setting to high could result in degraded site performance, too low won\'t allow to API enough time to respond; recommended 5 seconds.', 'zero-spam' ),
150
  'value' => ! empty( $options['zerospam_timeout'] ) ? $options['zerospam_timeout'] : 5,
151
  'recommended' => 5,
152
  );
153
 
154
  $settings['zerospam_cache'] = array(
155
+ 'title' => __( 'Cache Expiration', 'zero-spam' ),
156
  'section' => 'zerospam',
157
  'type' => 'number',
158
  'field_class' => 'small-text',
159
+ 'suffix' => __( 'day(s)', 'zero-spam' ),
160
  'placeholder' => WEEK_IN_SECONDS,
161
  'min' => 0,
162
+ 'desc' => __( 'Setting to high could result in outdated information, too low could cause a decrease in performance; recommended 14 days.', 'zero-spam' ),
163
  'value' => ! empty( $options['zerospam_cache'] ) ? $options['zerospam_cache'] : 14,
164
  'recommended' => 14,
165
  );
166
 
167
  $settings['zerospam_confidence_min'] = array(
168
+ 'title' => __( 'Confidence Minimum', 'zero-spam' ),
169
  'section' => 'zerospam',
170
  'type' => 'number',
171
  'field_class' => 'small-text',
172
+ 'suffix' => __( '%', 'zero-spam' ),
173
+ 'placeholder' => __( '30', 'zero-spam' ),
174
  'min' => 0,
175
  'max' => 100,
176
  'step' => 0.1,
177
  'desc' => sprintf(
178
  wp_kses(
179
  /* translators: %s: Replaced with the Zero Spam API URL */
180
+ __( 'Minimum <a href="%s" target="_blank" rel="noopener noreferrer">confidence score</a> an IP must meet before being blocked. Setting this too low could cause users to be blocked that shouldn\'t be; recommended 20%%.', 'zero-spam' ),
181
  array(
182
  'a' => array(
183
  'target' => array(),
307
  if ( ! empty( $response['result'] ) ) {
308
  \ZeroSpam\Core\Utilities::log( $response['result'] );
309
  } else {
310
+ \ZeroSpam\Core\Utilities::log( __( 'There was a problem querying the Zero Spam Blacklist API.', 'zero-spam' ) );
311
  }
312
 
313
  return false;
modules/comments/class-comments.php CHANGED
@@ -47,7 +47,7 @@ class Comments {
47
  * @param array $types Array of available detection types.
48
  */
49
  public function types( $types ) {
50
- $types['comment'] = __( 'Comment', 'zerospam' );
51
 
52
  return $types;
53
  }
@@ -186,7 +186,7 @@ class Comments {
186
  */
187
  public function sections( $sections ) {
188
  $sections['comments'] = array(
189
- 'title' => __( 'Comments Integration', 'zerospam' ),
190
  );
191
 
192
  return $sections;
@@ -200,21 +200,21 @@ class Comments {
200
  */
201
  public function settings( $settings, $options ) {
202
  $settings['verify_comments'] = array(
203
- 'title' => __( 'Protect Comments', 'zerospam' ),
204
  'section' => 'comments',
205
  'type' => 'checkbox',
206
  'options' => array(
207
- 'enabled' => __( 'Monitor comments for malicious or automated spambots.', 'zerospam' ),
208
  ),
209
  'value' => ! empty( $options['verify_comments'] ) ? $options['verify_comments'] : false,
210
  'recommended' => 'enabled',
211
  );
212
 
213
- $message = __( 'Your IP has been flagged as spam/malicious.', 'zerospam' );
214
 
215
  $settings['comment_spam_message'] = array(
216
- 'title' => __( 'Spam/Malicious Message', 'zerospam' ),
217
- 'desc' => __( 'When comment protection is enabled, the message displayed to the user when a comment has been detected as spam/malicious.', 'zerospam' ),
218
  'section' => 'comments',
219
  'type' => 'text',
220
  'field_class' => 'large-text',
@@ -224,15 +224,15 @@ class Comments {
224
  );
225
 
226
  $settings['log_blocked_comments'] = array(
227
- 'title' => __( 'Log Blocked Comments', 'zerospam' ),
228
  'section' => 'comments',
229
  'type' => 'checkbox',
230
  'desc' => wp_kses(
231
- __( 'Enables logging blocked comments. <strong>Recommended for enhanced protection.</strong>', 'zerospam' ),
232
  array( 'strong' => array() )
233
  ),
234
  'options' => array(
235
- 'enabled' => __( 'Enabled', 'zerospam' ),
236
  ),
237
  'value' => ! empty( $options['log_blocked_comments'] ) ? $options['log_blocked_comments'] : false,
238
  'recommended' => 'enabled',
47
  * @param array $types Array of available detection types.
48
  */
49
  public function types( $types ) {
50
+ $types['comment'] = __( 'Comment', 'zero-spam' );
51
 
52
  return $types;
53
  }
186
  */
187
  public function sections( $sections ) {
188
  $sections['comments'] = array(
189
+ 'title' => __( 'Comments Integration', 'zero-spam' ),
190
  );
191
 
192
  return $sections;
200
  */
201
  public function settings( $settings, $options ) {
202
  $settings['verify_comments'] = array(
203
+ 'title' => __( 'Protect Comments', 'zero-spam' ),
204
  'section' => 'comments',
205
  'type' => 'checkbox',
206
  'options' => array(
207
+ 'enabled' => __( 'Monitor comments for malicious or automated spambots.', 'zero-spam' ),
208
  ),
209
  'value' => ! empty( $options['verify_comments'] ) ? $options['verify_comments'] : false,
210
  'recommended' => 'enabled',
211
  );
212
 
213
+ $message = __( 'Your IP has been flagged as spam/malicious.', 'zero-spam' );
214
 
215
  $settings['comment_spam_message'] = array(
216
+ 'title' => __( 'Spam/Malicious Message', 'zero-spam' ),
217
+ 'desc' => __( 'When comment protection is enabled, the message displayed to the user when a comment has been detected as spam/malicious.', 'zero-spam' ),
218
  'section' => 'comments',
219
  'type' => 'text',
220
  'field_class' => 'large-text',
224
  );
225
 
226
  $settings['log_blocked_comments'] = array(
227
+ 'title' => __( 'Log Blocked Comments', 'zero-spam' ),
228
  'section' => 'comments',
229
  'type' => 'checkbox',
230
  'desc' => wp_kses(
231
+ __( 'Enables logging blocked comments. <strong>Recommended for enhanced protection.</strong>', 'zero-spam' ),
232
  array( 'strong' => array() )
233
  ),
234
  'options' => array(
235
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
236
  ),
237
  'value' => ! empty( $options['log_blocked_comments'] ) ? $options['log_blocked_comments'] : false,
238
  'recommended' => 'enabled',
modules/contactform7/class-contactform7.php CHANGED
@@ -129,7 +129,7 @@ class ContactForm7 {
129
  * @param array $types Array of available detection types.
130
  */
131
  public function types( $types ) {
132
- $types['contactform7'] = __( 'Contact Form 7', 'zerospam' );
133
 
134
  return $types;
135
  }
@@ -141,7 +141,7 @@ class ContactForm7 {
141
  */
142
  public function sections( $sections ) {
143
  $sections['contactform7'] = array(
144
- 'title' => __( 'Contact Form 7 Integration', 'zerospam' ),
145
  );
146
 
147
  return $sections;
@@ -155,21 +155,21 @@ class ContactForm7 {
155
  */
156
  public function settings( $settings, $options ) {
157
  $settings['verify_contactform7'] = array(
158
- 'title' => __( 'Protect CF7 Submissions', 'zerospam' ),
159
  'section' => 'contactform7',
160
  'type' => 'checkbox',
161
  'options' => array(
162
- 'enabled' => __( 'Monitor CF7 submissions for malicious or automated spambots.', 'zerospam' ),
163
  ),
164
  'value' => ! empty( $options['verify_contactform7'] ) ? $options['verify_contactform7'] : false,
165
  'recommended' => 'enabled',
166
  );
167
 
168
- $message = __( 'Your IP has been flagged as spam/malicious.', 'zerospam' );
169
 
170
  $settings['contactform7_spam_message'] = array(
171
- 'title' => __( 'Spam/Malicious Message', 'zerospam' ),
172
- 'desc' => __( 'When CF7 protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zerospam' ),
173
  'section' => 'contactform7',
174
  'type' => 'text',
175
  'field_class' => 'large-text',
@@ -179,15 +179,15 @@ class ContactForm7 {
179
  );
180
 
181
  $settings['log_blocked_contactform7'] = array(
182
- 'title' => __( 'Log Blocked CF7 Submissions', 'zerospam' ),
183
  'section' => 'contactform7',
184
  'type' => 'checkbox',
185
  'desc' => wp_kses(
186
- __( 'Enables logging blocked CF7 submissions. <strong>Recommended for enhanced protection.</strong>', 'zerospam' ),
187
  array( 'strong' => array() )
188
  ),
189
  'options' => array(
190
- 'enabled' => __( 'Enabled', 'zerospam' ),
191
  ),
192
  'value' => ! empty( $options['log_blocked_contactform7'] ) ? $options['log_blocked_contactform7'] : false,
193
  'recommended' => 'enabled',
129
  * @param array $types Array of available detection types.
130
  */
131
  public function types( $types ) {
132
+ $types['contactform7'] = __( 'Contact Form 7', 'zero-spam' );
133
 
134
  return $types;
135
  }
141
  */
142
  public function sections( $sections ) {
143
  $sections['contactform7'] = array(
144
+ 'title' => __( 'Contact Form 7 Integration', 'zero-spam' ),
145
  );
146
 
147
  return $sections;
155
  */
156
  public function settings( $settings, $options ) {
157
  $settings['verify_contactform7'] = array(
158
+ 'title' => __( 'Protect CF7 Submissions', 'zero-spam' ),
159
  'section' => 'contactform7',
160
  'type' => 'checkbox',
161
  'options' => array(
162
+ 'enabled' => __( 'Monitor CF7 submissions for malicious or automated spambots.', 'zero-spam' ),
163
  ),
164
  'value' => ! empty( $options['verify_contactform7'] ) ? $options['verify_contactform7'] : false,
165
  'recommended' => 'enabled',
166
  );
167
 
168
+ $message = __( 'Your IP has been flagged as spam/malicious.', 'zero-spam' );
169
 
170
  $settings['contactform7_spam_message'] = array(
171
+ 'title' => __( 'Spam/Malicious Message', 'zero-spam' ),
172
+ 'desc' => __( 'When CF7 protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zero-spam' ),
173
  'section' => 'contactform7',
174
  'type' => 'text',
175
  'field_class' => 'large-text',
179
  );
180
 
181
  $settings['log_blocked_contactform7'] = array(
182
+ 'title' => __( 'Log Blocked CF7 Submissions', 'zero-spam' ),
183
  'section' => 'contactform7',
184
  'type' => 'checkbox',
185
  'desc' => wp_kses(
186
+ __( 'Enables logging blocked CF7 submissions. <strong>Recommended for enhanced protection.</strong>', 'zero-spam' ),
187
  array( 'strong' => array() )
188
  ),
189
  'options' => array(
190
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
191
  ),
192
  'value' => ! empty( $options['log_blocked_contactform7'] ) ? $options['log_blocked_contactform7'] : false,
193
  'recommended' => 'enabled',
modules/davidwalsh/class-davidwalsh.php CHANGED
@@ -101,7 +101,7 @@ class DavidWalsh {
101
  * @param array $types Array of failed types.
102
  */
103
  public function failed_types( $types ) {
104
- $types['david_walsh'] = __( 'David Walsh', 'zerospam' );
105
 
106
  return $types;
107
  }
@@ -113,7 +113,7 @@ class DavidWalsh {
113
  */
114
  public function sections( $sections ) {
115
  $sections['davidwalsh'] = array(
116
- 'title' => __( 'David Walsh Detection Settings', 'zerospam' ),
117
  );
118
 
119
  return $sections;
@@ -127,11 +127,11 @@ class DavidWalsh {
127
  */
128
  public function settings( $settings, $options ) {
129
  $settings['davidwalsh'] = array(
130
- 'title' => __( 'David Walsh Technique', 'zerospam' ),
131
  'desc' => sprintf(
132
  wp_kses(
133
  /* translators: %s: url */
134
- __( 'Enables the <a href="%s" target="_blank" rel="noreferrer noopener">David Walsh technique</a>. <strong>Requires JavaScript be enabled.</strong>', 'zerospam' ),
135
  array(
136
  'a' => array(
137
  'target' => array(),
@@ -146,18 +146,18 @@ class DavidWalsh {
146
  'section' => 'davidwalsh',
147
  'type' => 'checkbox',
148
  'options' => array(
149
- 'enabled' => __( 'Enabled', 'zerospam' ),
150
  ),
151
  'value' => ! empty( $options['davidwalsh'] ) ? $options['davidwalsh'] : false,
152
  'recommended' => 'enabled',
153
  );
154
 
155
  $settings['davidwalsh_form_selectors'] = array(
156
- 'title' => __( 'Custom Form Selectors', 'zerospam' ),
157
  'desc' => sprintf(
158
  wp_kses(
159
  /* translators: %s: url */
160
- __( 'Comma-seperated list of custom form selectors that should use the <a href="%s" target="_blank" rel="noreferrer noopener">David Walsh technique</a>.', 'zerospam' ),
161
  array(
162
  'a' => array(
163
  'target' => array(),
101
  * @param array $types Array of failed types.
102
  */
103
  public function failed_types( $types ) {
104
+ $types['david_walsh'] = __( 'David Walsh', 'zero-spam' );
105
 
106
  return $types;
107
  }
113
  */
114
  public function sections( $sections ) {
115
  $sections['davidwalsh'] = array(
116
+ 'title' => __( 'David Walsh Detection Settings', 'zero-spam' ),
117
  );
118
 
119
  return $sections;
127
  */
128
  public function settings( $settings, $options ) {
129
  $settings['davidwalsh'] = array(
130
+ 'title' => __( 'David Walsh Technique', 'zero-spam' ),
131
  'desc' => sprintf(
132
  wp_kses(
133
  /* translators: %s: url */
134
+ __( 'Enables the <a href="%s" target="_blank" rel="noreferrer noopener">David Walsh technique</a>. <strong>Requires JavaScript be enabled.</strong>', 'zero-spam' ),
135
  array(
136
  'a' => array(
137
  'target' => array(),
146
  'section' => 'davidwalsh',
147
  'type' => 'checkbox',
148
  'options' => array(
149
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
150
  ),
151
  'value' => ! empty( $options['davidwalsh'] ) ? $options['davidwalsh'] : false,
152
  'recommended' => 'enabled',
153
  );
154
 
155
  $settings['davidwalsh_form_selectors'] = array(
156
+ 'title' => __( 'Custom Form Selectors', 'zero-spam' ),
157
  'desc' => sprintf(
158
  wp_kses(
159
  /* translators: %s: url */
160
+ __( 'Comma-seperated list of custom form selectors that should use the <a href="%s" target="_blank" rel="noreferrer noopener">David Walsh technique</a>.', 'zero-spam' ),
161
  array(
162
  'a' => array(
163
  'target' => array(),
modules/fluentforms/class-fluentforms.php CHANGED
@@ -195,7 +195,7 @@ class FluentForms {
195
  * @param array $types Array of available detection types.
196
  */
197
  public function types( $types ) {
198
- $types['fluent_form'] = __( 'Fluent Form', 'zerospam' );
199
 
200
  return $types;
201
  }
@@ -207,7 +207,7 @@ class FluentForms {
207
  */
208
  public function sections( $sections ) {
209
  $sections['fluentforms'] = array(
210
- 'title' => __( 'Fluent Forms Integration', 'zerospam' ),
211
  );
212
 
213
  return $sections;
@@ -221,21 +221,21 @@ class FluentForms {
221
  */
222
  public function settings( $settings, $options ) {
223
  $settings['verify_fluentforms'] = array(
224
- 'title' => __( 'Protect Fluent Form Submissions', 'zerospam' ),
225
  'section' => 'fluentforms',
226
  'type' => 'checkbox',
227
  'options' => array(
228
- 'enabled' => __( 'Monitor Fluent Form submissions for malicious or automated spambots.', 'zerospam' ),
229
  ),
230
  'value' => ! empty( $options['verify_fluentforms'] ) ? $options['verify_fluentforms'] : false,
231
  'recommended' => 'enabled',
232
  );
233
 
234
- $message = __( 'Your IP has been flagged as spam/malicious.', 'zerospam' );
235
 
236
  $settings['fluentforms_spam_message'] = array(
237
- 'title' => __( 'Spam/Malicious Message', 'zerospam' ),
238
- 'desc' => __( 'When Fluent Form protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zerospam' ),
239
  'section' => 'fluentforms',
240
  'type' => 'text',
241
  'field_class' => 'large-text',
@@ -245,15 +245,15 @@ class FluentForms {
245
  );
246
 
247
  $settings['log_blocked_fluentforms'] = array(
248
- 'title' => __( 'Log Blocked Fluent Form Submissions', 'zerospam' ),
249
  'section' => 'fluentforms',
250
  'type' => 'checkbox',
251
  'desc' => wp_kses(
252
- __( 'Enables logging blocked Fluent Form submissions. <strong>Recommended for enhanced protection.</strong>', 'zerospam' ),
253
  array( 'strong' => array() )
254
  ),
255
  'options' => array(
256
- 'enabled' => __( 'Enabled', 'zerospam' ),
257
  ),
258
  'value' => ! empty( $options['log_blocked_fluentforms'] ) ? $options['log_blocked_fluentforms'] : false,
259
  'recommended' => 'enabled',
195
  * @param array $types Array of available detection types.
196
  */
197
  public function types( $types ) {
198
+ $types['fluent_form'] = __( 'Fluent Form', 'zero-spam' );
199
 
200
  return $types;
201
  }
207
  */
208
  public function sections( $sections ) {
209
  $sections['fluentforms'] = array(
210
+ 'title' => __( 'Fluent Forms Integration', 'zero-spam' ),
211
  );
212
 
213
  return $sections;
221
  */
222
  public function settings( $settings, $options ) {
223
  $settings['verify_fluentforms'] = array(
224
+ 'title' => __( 'Protect Fluent Form Submissions', 'zero-spam' ),
225
  'section' => 'fluentforms',
226
  'type' => 'checkbox',
227
  'options' => array(
228
+ 'enabled' => __( 'Monitor Fluent Form submissions for malicious or automated spambots.', 'zero-spam' ),
229
  ),
230
  'value' => ! empty( $options['verify_fluentforms'] ) ? $options['verify_fluentforms'] : false,
231
  'recommended' => 'enabled',
232
  );
233
 
234
+ $message = __( 'Your IP has been flagged as spam/malicious.', 'zero-spam' );
235
 
236
  $settings['fluentforms_spam_message'] = array(
237
+ 'title' => __( 'Spam/Malicious Message', 'zero-spam' ),
238
+ 'desc' => __( 'When Fluent Form protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zero-spam' ),
239
  'section' => 'fluentforms',
240
  'type' => 'text',
241
  'field_class' => 'large-text',
245
  );
246
 
247
  $settings['log_blocked_fluentforms'] = array(
248
+ 'title' => __( 'Log Blocked Fluent Form Submissions', 'zero-spam' ),
249
  'section' => 'fluentforms',
250
  'type' => 'checkbox',
251
  'desc' => wp_kses(
252
+ __( 'Enables logging blocked Fluent Form submissions. <strong>Recommended for enhanced protection.</strong>', 'zero-spam' ),
253
  array( 'strong' => array() )
254
  ),
255
  'options' => array(
256
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
257
  ),
258
  'value' => ! empty( $options['log_blocked_fluentforms'] ) ? $options['log_blocked_fluentforms'] : false,
259
  'recommended' => 'enabled',
modules/formidable/class-formidable.php CHANGED
@@ -44,7 +44,7 @@ class Formidable {
44
  * @param array $types Array of available detection types.
45
  */
46
  public function types( $types ) {
47
- $types['formidable'] = __( 'Formidable', 'zerospam' );
48
 
49
  return $types;
50
  }
@@ -56,7 +56,7 @@ class Formidable {
56
  */
57
  public function sections( $sections ) {
58
  $sections['formidable'] = array(
59
- 'title' => __( 'Formidable Integration', 'zerospam' ),
60
  );
61
 
62
  return $sections;
@@ -70,21 +70,21 @@ class Formidable {
70
  */
71
  public function settings( $settings, $options ) {
72
  $settings['verify_formidable'] = array(
73
- 'title' => __( 'Protect Formidable Submissions', 'zerospam' ),
74
  'section' => 'formidable',
75
  'type' => 'checkbox',
76
  'options' => array(
77
- 'enabled' => __( 'Monitor Formidable submissions for malicious or automated spambots.', 'zerospam' ),
78
  ),
79
  'value' => ! empty( $options['verify_formidable'] ) ? $options['verify_formidable'] : false,
80
  'recommended' => 'enabled',
81
  );
82
 
83
- $message = __( 'Your IP has been flagged as spam/malicious.', 'zerospam' );
84
 
85
  $settings['formidable_spam_message'] = array(
86
- 'title' => __( 'Spam/Malicious Message', 'zerospam' ),
87
- 'desc' => __( 'When Formidable protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zerospam' ),
88
  'section' => 'formidable',
89
  'type' => 'text',
90
  'field_class' => 'large-text',
@@ -94,15 +94,15 @@ class Formidable {
94
  );
95
 
96
  $settings['log_blocked_formidable'] = array(
97
- 'title' => __( 'Log Blocked Formidable Submissions', 'zerospam' ),
98
  'section' => 'formidable',
99
  'type' => 'checkbox',
100
  'desc' => wp_kses(
101
- __( 'Enables logging blocked Formidable submissions. <strong>Recommended for enhanced protection.</strong>', 'zerospam' ),
102
  array( 'strong' => array() )
103
  ),
104
  'options' => array(
105
- 'enabled' => __( 'Enabled', 'zerospam' ),
106
  ),
107
  'value' => ! empty( $options['log_blocked_formidable'] ) ? $options['log_blocked_formidable'] : false,
108
  'recommended' => 'enabled',
44
  * @param array $types Array of available detection types.
45
  */
46
  public function types( $types ) {
47
+ $types['formidable'] = __( 'Formidable', 'zero-spam' );
48
 
49
  return $types;
50
  }
56
  */
57
  public function sections( $sections ) {
58
  $sections['formidable'] = array(
59
+ 'title' => __( 'Formidable Integration', 'zero-spam' ),
60
  );
61
 
62
  return $sections;
70
  */
71
  public function settings( $settings, $options ) {
72
  $settings['verify_formidable'] = array(
73
+ 'title' => __( 'Protect Formidable Submissions', 'zero-spam' ),
74
  'section' => 'formidable',
75
  'type' => 'checkbox',
76
  'options' => array(
77
+ 'enabled' => __( 'Monitor Formidable submissions for malicious or automated spambots.', 'zero-spam' ),
78
  ),
79
  'value' => ! empty( $options['verify_formidable'] ) ? $options['verify_formidable'] : false,
80
  'recommended' => 'enabled',
81
  );
82
 
83
+ $message = __( 'Your IP has been flagged as spam/malicious.', 'zero-spam' );
84
 
85
  $settings['formidable_spam_message'] = array(
86
+ 'title' => __( 'Spam/Malicious Message', 'zero-spam' ),
87
+ 'desc' => __( 'When Formidable protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zero-spam' ),
88
  'section' => 'formidable',
89
  'type' => 'text',
90
  'field_class' => 'large-text',
94
  );
95
 
96
  $settings['log_blocked_formidable'] = array(
97
+ 'title' => __( 'Log Blocked Formidable Submissions', 'zero-spam' ),
98
  'section' => 'formidable',
99
  'type' => 'checkbox',
100
  'desc' => wp_kses(
101
+ __( 'Enables logging blocked Formidable submissions. <strong>Recommended for enhanced protection.</strong>', 'zero-spam' ),
102
  array( 'strong' => array() )
103
  ),
104
  'options' => array(
105
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
106
  ),
107
  'value' => ! empty( $options['log_blocked_formidable'] ) ? $options['log_blocked_formidable'] : false,
108
  'recommended' => 'enabled',
modules/give/class-give.php CHANGED
@@ -119,7 +119,7 @@ class Give {
119
  * @param array $types Array of available detection types.
120
  */
121
  public function types( $types ) {
122
- $types['givewp'] = __( 'GiveWP', 'zerospam' );
123
 
124
  return $types;
125
  }
@@ -131,7 +131,7 @@ class Give {
131
  */
132
  public function sections( $sections ) {
133
  $sections['givewp'] = array(
134
- 'title' => __( 'GiveWP Integration', 'zerospam' ),
135
  );
136
 
137
  return $sections;
@@ -148,7 +148,7 @@ class Give {
148
  'title' => sprintf(
149
  wp_kses(
150
  /* translators: %s: url */
151
- __( 'Protect <a href="%s" target="_blank" rel="noreferrer noopener">GiveWP</a> Submissions', 'zerospam' ),
152
  array(
153
  'a' => array(
154
  'href' => array(),
@@ -163,17 +163,17 @@ class Give {
163
  'section' => 'givewp',
164
  'type' => 'checkbox',
165
  'options' => array(
166
- 'enabled' => __( 'Monitor GiveWP submissions for malicious or automated spambots.', 'zerospam' ),
167
  ),
168
  'value' => ! empty( $options['verify_givewp'] ) ? $options['verify_givewp'] : false,
169
  'recommended' => 'enabled',
170
  );
171
 
172
- $message = __( 'We\'re sorry, but we\'re unable to process the transaction. Your IP has been flagged as possible spam.', 'zerospam' );
173
 
174
  $settings['givewp_spam_message'] = array(
175
- 'title' => __( 'Spam/Malicious Message', 'zerospam' ),
176
- 'desc' => __( 'When GiveWP protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zerospam' ),
177
  'section' => 'givewp',
178
  'type' => 'text',
179
  'field_class' => 'large-text',
@@ -183,15 +183,15 @@ class Give {
183
  );
184
 
185
  $settings['log_blocked_givewp'] = array(
186
- 'title' => __( 'Log Blocked GiveWP Submissions', 'zerospam' ),
187
  'section' => 'givewp',
188
  'type' => 'checkbox',
189
  'desc' => wp_kses(
190
- __( 'Enables logging blocked GiveWP submissions. <strong>Recommended for enhanced protection.</strong>', 'zerospam' ),
191
  array( 'strong' => array() )
192
  ),
193
  'options' => array(
194
- 'enabled' => __( 'Enabled', 'zerospam' ),
195
  ),
196
  'value' => ! empty( $options['log_blocked_givewp'] ) ? $options['log_blocked_givewp'] : false,
197
  'recommended' => 'enabled',
119
  * @param array $types Array of available detection types.
120
  */
121
  public function types( $types ) {
122
+ $types['givewp'] = __( 'GiveWP', 'zero-spam' );
123
 
124
  return $types;
125
  }
131
  */
132
  public function sections( $sections ) {
133
  $sections['givewp'] = array(
134
+ 'title' => __( 'GiveWP Integration', 'zero-spam' ),
135
  );
136
 
137
  return $sections;
148
  'title' => sprintf(
149
  wp_kses(
150
  /* translators: %s: url */
151
+ __( 'Protect <a href="%s" target="_blank" rel="noreferrer noopener">GiveWP</a> Submissions', 'zero-spam' ),
152
  array(
153
  'a' => array(
154
  'href' => array(),
163
  'section' => 'givewp',
164
  'type' => 'checkbox',
165
  'options' => array(
166
+ 'enabled' => __( 'Monitor GiveWP submissions for malicious or automated spambots.', 'zero-spam' ),
167
  ),
168
  'value' => ! empty( $options['verify_givewp'] ) ? $options['verify_givewp'] : false,
169
  'recommended' => 'enabled',
170
  );
171
 
172
+ $message = __( 'We\'re sorry, but we\'re unable to process the transaction. Your IP has been flagged as possible spam.', 'zero-spam' );
173
 
174
  $settings['givewp_spam_message'] = array(
175
+ 'title' => __( 'Spam/Malicious Message', 'zero-spam' ),
176
+ 'desc' => __( 'When GiveWP protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zero-spam' ),
177
  'section' => 'givewp',
178
  'type' => 'text',
179
  'field_class' => 'large-text',
183
  );
184
 
185
  $settings['log_blocked_givewp'] = array(
186
+ 'title' => __( 'Log Blocked GiveWP Submissions', 'zero-spam' ),
187
  'section' => 'givewp',
188
  'type' => 'checkbox',
189
  'desc' => wp_kses(
190
+ __( 'Enables logging blocked GiveWP submissions. <strong>Recommended for enhanced protection.</strong>', 'zero-spam' ),
191
  array( 'strong' => array() )
192
  ),
193
  'options' => array(
194
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
195
  ),
196
  'value' => ! empty( $options['log_blocked_givewp'] ) ? $options['log_blocked_givewp'] : false,
197
  'recommended' => 'enabled',
modules/login/class-login.php CHANGED
@@ -130,7 +130,7 @@ class Login {
130
  * @param array $types Array of available detection types.
131
  */
132
  public function types( $types ) {
133
- $types['login'] = __( 'Login Attempt', 'zerospam' );
134
 
135
  return $types;
136
  }
@@ -142,7 +142,7 @@ class Login {
142
  */
143
  public function sections( $sections ) {
144
  $sections['login'] = array(
145
- 'title' => __( 'User Login Integration', 'zerospam' ),
146
  );
147
 
148
  return $sections;
@@ -156,21 +156,21 @@ class Login {
156
  */
157
  public function settings( $settings, $options ) {
158
  $settings['verify_login'] = array(
159
- 'title' => __( 'Protect Login Attempts', 'zerospam' ),
160
  'section' => 'login',
161
  'type' => 'checkbox',
162
  'options' => array(
163
- 'enabled' => __( 'Monitor login attempts for malicious or automated spambots.', 'zerospam' ),
164
  ),
165
  'value' => ! empty( $options['verify_login'] ) ? $options['verify_login'] : false,
166
  'recommended' => 'enabled',
167
  );
168
 
169
- $message = __( 'Your IP has been flagged as spam/malicious.', 'zerospam' );
170
 
171
  $settings['login_spam_message'] = array(
172
- 'title' => __( 'Spam/Malicious Message', 'zerospam' ),
173
- 'desc' => __( 'When login protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zerospam' ),
174
  'section' => 'login',
175
  'type' => 'text',
176
  'field_class' => 'large-text',
@@ -180,15 +180,15 @@ class Login {
180
  );
181
 
182
  $settings['log_blocked_logins'] = array(
183
- 'title' => __( 'Log Blocked Login Attempts', 'zerospam' ),
184
  'section' => 'login',
185
  'type' => 'checkbox',
186
  'desc' => wp_kses(
187
- __( 'Enables logging blocked login attempts. <strong>Recommended for enhanced protection.</strong>', 'zerospam' ),
188
  array( 'strong' => array() )
189
  ),
190
  'options' => array(
191
- 'enabled' => __( 'Enabled', 'zerospam' ),
192
  ),
193
  'value' => ! empty( $options['log_blocked_logins'] ) ? $options['log_blocked_logins'] : false,
194
  'recommended' => 'enabled',
130
  * @param array $types Array of available detection types.
131
  */
132
  public function types( $types ) {
133
+ $types['login'] = __( 'Login Attempt', 'zero-spam' );
134
 
135
  return $types;
136
  }
142
  */
143
  public function sections( $sections ) {
144
  $sections['login'] = array(
145
+ 'title' => __( 'User Login Integration', 'zero-spam' ),
146
  );
147
 
148
  return $sections;
156
  */
157
  public function settings( $settings, $options ) {
158
  $settings['verify_login'] = array(
159
+ 'title' => __( 'Protect Login Attempts', 'zero-spam' ),
160
  'section' => 'login',
161
  'type' => 'checkbox',
162
  'options' => array(
163
+ 'enabled' => __( 'Monitor login attempts for malicious or automated spambots.', 'zero-spam' ),
164
  ),
165
  'value' => ! empty( $options['verify_login'] ) ? $options['verify_login'] : false,
166
  'recommended' => 'enabled',
167
  );
168
 
169
+ $message = __( 'Your IP has been flagged as spam/malicious.', 'zero-spam' );
170
 
171
  $settings['login_spam_message'] = array(
172
+ 'title' => __( 'Spam/Malicious Message', 'zero-spam' ),
173
+ 'desc' => __( 'When login protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zero-spam' ),
174
  'section' => 'login',
175
  'type' => 'text',
176
  'field_class' => 'large-text',
180
  );
181
 
182
  $settings['log_blocked_logins'] = array(
183
+ 'title' => __( 'Log Blocked Login Attempts', 'zero-spam' ),
184
  'section' => 'login',
185
  'type' => 'checkbox',
186
  'desc' => wp_kses(
187
+ __( 'Enables logging blocked login attempts. <strong>Recommended for enhanced protection.</strong>', 'zero-spam' ),
188
  array( 'strong' => array() )
189
  ),
190
  'options' => array(
191
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
192
  ),
193
  'value' => ! empty( $options['log_blocked_logins'] ) ? $options['log_blocked_logins'] : false,
194
  'recommended' => 'enabled',
modules/mailchimpforwp/class-mailchimpforwp.php CHANGED
@@ -155,7 +155,7 @@ class MailchimpForWP {
155
  * @param array $types Array of available detection types.
156
  */
157
  public function types( $types ) {
158
- $types['mailchimp4wp'] = __( 'Mailchimp for WordPress', 'zerospam' );
159
 
160
  return $types;
161
  }
@@ -167,7 +167,7 @@ class MailchimpForWP {
167
  */
168
  public function sections( $sections ) {
169
  $sections['mailchimp4wp'] = array(
170
- 'title' => __( 'Mailchimp for WordPress Integration', 'zerospam' ),
171
  );
172
 
173
  return $sections;
@@ -181,21 +181,21 @@ class MailchimpForWP {
181
  */
182
  public function settings( $settings, $options ) {
183
  $settings['verify_mailchimp4wp'] = array(
184
- 'title' => __( 'Protect Forms', 'zerospam' ),
185
  'section' => 'mailchimp4wp',
186
  'type' => 'checkbox',
187
  'options' => array(
188
- 'enabled' => __( 'Monitor Mailchimp form submissions for malicious or automated spambots.', 'zerospam' ),
189
  ),
190
  'value' => ! empty( $options['verify_mailchimp4wp'] ) ? $options['verify_mailchimp4wp'] : false,
191
  'recommended' => 'enabled',
192
  );
193
 
194
- $message = __( 'Your IP has been flagged as spam/malicious.', 'zerospam' );
195
 
196
  $settings['mailchimp4wp_spam_message'] = array(
197
- 'title' => __( 'Mailchimp Spam/Malicious Message', 'zerospam' ),
198
- 'desc' => __( 'When Mailchimp form protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zerospam' ),
199
  'section' => 'mailchimp4wp',
200
  'type' => 'text',
201
  'field_class' => 'large-text',
@@ -205,15 +205,15 @@ class MailchimpForWP {
205
  );
206
 
207
  $settings['log_blocked_mailchimp4wp'] = array(
208
- 'title' => __( 'Log Blocked Registrations', 'zerospam' ),
209
  'section' => 'mailchimp4wp',
210
  'type' => 'checkbox',
211
  'desc' => wp_kses(
212
- __( 'Enables logging blocked Mailchimp form submissions. <strong>Recommended for enhanced protection.</strong>', 'zerospam' ),
213
  array( 'strong' => array() )
214
  ),
215
  'options' => array(
216
- 'enabled' => __( 'Enabled', 'zerospam' ),
217
  ),
218
  'value' => ! empty( $options['log_blocked_mailchimp4wp'] ) ? $options['log_blocked_mailchimp4wp'] : false,
219
  'recommended' => 'enabled',
155
  * @param array $types Array of available detection types.
156
  */
157
  public function types( $types ) {
158
+ $types['mailchimp4wp'] = __( 'Mailchimp for WordPress', 'zero-spam' );
159
 
160
  return $types;
161
  }
167
  */
168
  public function sections( $sections ) {
169
  $sections['mailchimp4wp'] = array(
170
+ 'title' => __( 'Mailchimp for WordPress Integration', 'zero-spam' ),
171
  );
172
 
173
  return $sections;
181
  */
182
  public function settings( $settings, $options ) {
183
  $settings['verify_mailchimp4wp'] = array(
184
+ 'title' => __( 'Protect Forms', 'zero-spam' ),
185
  'section' => 'mailchimp4wp',
186
  'type' => 'checkbox',
187
  'options' => array(
188
+ 'enabled' => __( 'Monitor Mailchimp form submissions for malicious or automated spambots.', 'zero-spam' ),
189
  ),
190
  'value' => ! empty( $options['verify_mailchimp4wp'] ) ? $options['verify_mailchimp4wp'] : false,
191
  'recommended' => 'enabled',
192
  );
193
 
194
+ $message = __( 'Your IP has been flagged as spam/malicious.', 'zero-spam' );
195
 
196
  $settings['mailchimp4wp_spam_message'] = array(
197
+ 'title' => __( 'Mailchimp Spam/Malicious Message', 'zero-spam' ),
198
+ 'desc' => __( 'When Mailchimp form protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zero-spam' ),
199
  'section' => 'mailchimp4wp',
200
  'type' => 'text',
201
  'field_class' => 'large-text',
205
  );
206
 
207
  $settings['log_blocked_mailchimp4wp'] = array(
208
+ 'title' => __( 'Log Blocked Registrations', 'zero-spam' ),
209
  'section' => 'mailchimp4wp',
210
  'type' => 'checkbox',
211
  'desc' => wp_kses(
212
+ __( 'Enables logging blocked Mailchimp form submissions. <strong>Recommended for enhanced protection.</strong>', 'zero-spam' ),
213
  array( 'strong' => array() )
214
  ),
215
  'options' => array(
216
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
217
  ),
218
  'value' => ! empty( $options['log_blocked_mailchimp4wp'] ) ? $options['log_blocked_mailchimp4wp'] : false,
219
  'recommended' => 'enabled',
modules/memberpress/class-memberpress.php CHANGED
@@ -222,8 +222,8 @@ class MemberPress {
222
  * @param array $types Array of available detection types.
223
  */
224
  public function types( $types ) {
225
- $types['memberpress_registration'] = __( 'MemberPress Registration', 'zerospam' );
226
- $types['memberpress_login'] = __( 'MemberPress Login', 'zerospam' );
227
 
228
  return $types;
229
  }
@@ -235,7 +235,7 @@ class MemberPress {
235
  */
236
  public function sections( $sections ) {
237
  $sections['memberpress'] = array(
238
- 'title' => __( 'MemberPress Integration', 'zerospam' ),
239
  );
240
 
241
  return $sections;
@@ -248,7 +248,7 @@ class MemberPress {
248
  * @param array $options Array of saved database options.
249
  */
250
  public function settings( $settings, $options ) {
251
- $default_spam_message = __( 'Your IP has been flagged as spam/malicious.', 'zerospam' );
252
 
253
  // Registration protection.
254
  $settings['memberpress_registration_info'] = array(
@@ -256,7 +256,7 @@ class MemberPress {
256
  'type' => 'html',
257
  'html' => sprintf(
258
  wp_kses(
259
- __( '<h3 style="margin: 0">Registration Protection</h3>', 'zerospam' ),
260
  array(
261
  'h3' => array(
262
  'style' => array(),
@@ -267,19 +267,19 @@ class MemberPress {
267
  );
268
 
269
  $settings['verify_memberpress_registration'] = array(
270
- 'title' => __( 'Protect Registration Forms', 'zerospam' ),
271
  'section' => 'memberpress',
272
  'type' => 'checkbox',
273
  'options' => array(
274
- 'enabled' => __( 'Monitor MemberPress registrations for malicious or automated spambots.', 'zerospam' ),
275
  ),
276
  'value' => ! empty( $options['verify_memberpress_registration'] ) ? $options['verify_memberpress_registration'] : false,
277
  'recommended' => 'enabled',
278
  );
279
 
280
  $settings['memberpress_regsitration_spam_message'] = array(
281
- 'title' => __( 'Registration Spam/Malicious Message', 'zerospam' ),
282
- 'desc' => __( 'When registration protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zerospam' ),
283
  'section' => 'memberpress',
284
  'type' => 'text',
285
  'field_class' => 'large-text',
@@ -289,15 +289,15 @@ class MemberPress {
289
  );
290
 
291
  $settings['log_blocked_memberpress_registrations'] = array(
292
- 'title' => __( 'Log Blocked Registrations', 'zerospam' ),
293
  'section' => 'memberpress',
294
  'type' => 'checkbox',
295
  'desc' => wp_kses(
296
- __( 'Enables logging blocked registration attempts. <strong>Recommended for enhanced protection.</strong>', 'zerospam' ),
297
  array( 'strong' => array() )
298
  ),
299
  'options' => array(
300
- 'enabled' => __( 'Enabled', 'zerospam' ),
301
  ),
302
  'value' => ! empty( $options['log_blocked_memberpress_registrations'] ) ? $options['log_blocked_memberpress_registrations'] : false,
303
  'recommended' => 'enabled',
@@ -309,7 +309,7 @@ class MemberPress {
309
  'type' => 'html',
310
  'html' => sprintf(
311
  wp_kses(
312
- __( '<h3 style="margin-bottom: 0">User Login Protection</h3>', 'zerospam' ),
313
  array(
314
  'h3' => array(
315
  'style' => array(),
@@ -320,19 +320,19 @@ class MemberPress {
320
  );
321
 
322
  $settings['verify_memberpress_login'] = array(
323
- 'title' => __( 'Protect Login Forms', 'zerospam' ),
324
  'section' => 'memberpress',
325
  'type' => 'checkbox',
326
  'options' => array(
327
- 'enabled' => __( 'Monitor MemberPress logins for malicious or automated spambots.', 'zerospam' ),
328
  ),
329
  'value' => ! empty( $options['verify_memberpress_login'] ) ? $options['verify_memberpress_login'] : false,
330
  'recommended' => 'enabled',
331
  );
332
 
333
  $settings['memberpress_login_spam_message'] = array(
334
- 'title' => __( 'Login Spam/Malicious Message', 'zerospam' ),
335
- 'desc' => __( 'When login protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zerospam' ),
336
  'section' => 'memberpress',
337
  'type' => 'text',
338
  'field_class' => 'large-text',
@@ -342,15 +342,15 @@ class MemberPress {
342
  );
343
 
344
  $settings['log_blocked_memberpress_logins'] = array(
345
- 'title' => __( 'Log Blocked Logins', 'zerospam' ),
346
  'section' => 'memberpress',
347
  'type' => 'checkbox',
348
  'desc' => wp_kses(
349
- __( 'Enables logging blocked login attempts. <strong>Recommended for enhanced protection.</strong>', 'zerospam' ),
350
  array( 'strong' => array() )
351
  ),
352
  'options' => array(
353
- 'enabled' => __( 'Enabled', 'zerospam' ),
354
  ),
355
  'value' => ! empty( $options['log_blocked_memberpress_logins'] ) ? $options['log_blocked_memberpress_logins'] : false,
356
  'recommended' => 'enabled',
222
  * @param array $types Array of available detection types.
223
  */
224
  public function types( $types ) {
225
+ $types['memberpress_registration'] = __( 'MemberPress Registration', 'zero-spam' );
226
+ $types['memberpress_login'] = __( 'MemberPress Login', 'zero-spam' );
227
 
228
  return $types;
229
  }
235
  */
236
  public function sections( $sections ) {
237
  $sections['memberpress'] = array(
238
+ 'title' => __( 'MemberPress Integration', 'zero-spam' ),
239
  );
240
 
241
  return $sections;
248
  * @param array $options Array of saved database options.
249
  */
250
  public function settings( $settings, $options ) {
251
+ $default_spam_message = __( 'Your IP has been flagged as spam/malicious.', 'zero-spam' );
252
 
253
  // Registration protection.
254
  $settings['memberpress_registration_info'] = array(
256
  'type' => 'html',
257
  'html' => sprintf(
258
  wp_kses(
259
+ __( '<h3 style="margin: 0">Registration Protection</h3>', 'zero-spam' ),
260
  array(
261
  'h3' => array(
262
  'style' => array(),
267
  );
268
 
269
  $settings['verify_memberpress_registration'] = array(
270
+ 'title' => __( 'Protect Registration Forms', 'zero-spam' ),
271
  'section' => 'memberpress',
272
  'type' => 'checkbox',
273
  'options' => array(
274
+ 'enabled' => __( 'Monitor MemberPress registrations for malicious or automated spambots.', 'zero-spam' ),
275
  ),
276
  'value' => ! empty( $options['verify_memberpress_registration'] ) ? $options['verify_memberpress_registration'] : false,
277
  'recommended' => 'enabled',
278
  );
279
 
280
  $settings['memberpress_regsitration_spam_message'] = array(
281
+ 'title' => __( 'Registration Spam/Malicious Message', 'zero-spam' ),
282
+ 'desc' => __( 'When registration protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zero-spam' ),
283
  'section' => 'memberpress',
284
  'type' => 'text',
285
  'field_class' => 'large-text',
289
  );
290
 
291
  $settings['log_blocked_memberpress_registrations'] = array(
292
+ 'title' => __( 'Log Blocked Registrations', 'zero-spam' ),
293
  'section' => 'memberpress',
294
  'type' => 'checkbox',
295
  'desc' => wp_kses(
296
+ __( 'Enables logging blocked registration attempts. <strong>Recommended for enhanced protection.</strong>', 'zero-spam' ),
297
  array( 'strong' => array() )
298
  ),
299
  'options' => array(
300
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
301
  ),
302
  'value' => ! empty( $options['log_blocked_memberpress_registrations'] ) ? $options['log_blocked_memberpress_registrations'] : false,
303
  'recommended' => 'enabled',
309
  'type' => 'html',
310
  'html' => sprintf(
311
  wp_kses(
312
+ __( '<h3 style="margin-bottom: 0">User Login Protection</h3>', 'zero-spam' ),
313
  array(
314
  'h3' => array(
315
  'style' => array(),
320
  );
321
 
322
  $settings['verify_memberpress_login'] = array(
323
+ 'title' => __( 'Protect Login Forms', 'zero-spam' ),
324
  'section' => 'memberpress',
325
  'type' => 'checkbox',
326
  'options' => array(
327
+ 'enabled' => __( 'Monitor MemberPress logins for malicious or automated spambots.', 'zero-spam' ),
328
  ),
329
  'value' => ! empty( $options['verify_memberpress_login'] ) ? $options['verify_memberpress_login'] : false,
330
  'recommended' => 'enabled',
331
  );
332
 
333
  $settings['memberpress_login_spam_message'] = array(
334
+ 'title' => __( 'Login Spam/Malicious Message', 'zero-spam' ),
335
+ 'desc' => __( 'When login protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zero-spam' ),
336
  'section' => 'memberpress',
337
  'type' => 'text',
338
  'field_class' => 'large-text',
342
  );
343
 
344
  $settings['log_blocked_memberpress_logins'] = array(
345
+ 'title' => __( 'Log Blocked Logins', 'zero-spam' ),
346
  'section' => 'memberpress',
347
  'type' => 'checkbox',
348
  'desc' => wp_kses(
349
+ __( 'Enables logging blocked login attempts. <strong>Recommended for enhanced protection.</strong>', 'zero-spam' ),
350
  array( 'strong' => array() )
351
  ),
352
  'options' => array(
353
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
354
  ),
355
  'value' => ! empty( $options['log_blocked_memberpress_logins'] ) ? $options['log_blocked_memberpress_logins'] : false,
356
  'recommended' => 'enabled',
modules/registration/class-registration.php CHANGED
@@ -45,7 +45,7 @@ class Registration {
45
  * @param array $types Array of available detection types.
46
  */
47
  public function types( $types ) {
48
- $types['registration'] = __( 'Registration', 'zerospam' );
49
 
50
  return $types;
51
  }
@@ -146,7 +146,7 @@ class Registration {
146
  */
147
  public function sections( $sections ) {
148
  $sections['registration'] = array(
149
- 'title' => __( 'Registration Integration', 'zerospam' ),
150
  );
151
 
152
  return $sections;
@@ -160,21 +160,21 @@ class Registration {
160
  */
161
  public function settings( $settings, $options ) {
162
  $settings['verify_registrations'] = array(
163
- 'title' => __( 'Protect Registrations', 'zerospam' ),
164
  'section' => 'registration',
165
  'type' => 'checkbox',
166
  'options' => array(
167
- 'enabled' => __( 'Monitor registrations for malicious or automated spambots.', 'zerospam' ),
168
  ),
169
  'value' => ! empty( $options['verify_registrations'] ) ? $options['verify_registrations'] : false,
170
  'recommended' => 'enabled',
171
  );
172
 
173
- $message = __( 'Your IP has been flagged as spam/malicious.', 'zerospam' );
174
 
175
  $settings['registration_spam_message'] = array(
176
- 'title' => __( 'Spam/Malicious Message', 'zerospam' ),
177
- 'desc' => __( 'When registration protection is enabled, the message displayed to the user when a registration has been detected as spam/malicious.', 'zerospam' ),
178
  'section' => 'registration',
179
  'type' => 'text',
180
  'field_class' => 'large-text',
@@ -184,15 +184,15 @@ class Registration {
184
  );
185
 
186
  $settings['log_blocked_registrations'] = array(
187
- 'title' => __( 'Log Blocked Registrations', 'zerospam' ),
188
  'section' => 'registration',
189
  'type' => 'checkbox',
190
  'desc' => wp_kses(
191
- __( 'Enables logging blocked registrations. <strong>Recommended for enhanced protection.</strong>', 'zerospam' ),
192
  array( 'strong' => array() )
193
  ),
194
  'options' => array(
195
- 'enabled' => __( 'Enabled', 'zerospam' ),
196
  ),
197
  'value' => ! empty( $options['log_blocked_registrations'] ) ? $options['log_blocked_registrations'] : false,
198
  'recommended' => 'enabled',
45
  * @param array $types Array of available detection types.
46
  */
47
  public function types( $types ) {
48
+ $types['registration'] = __( 'Registration', 'zero-spam' );
49
 
50
  return $types;
51
  }
146
  */
147
  public function sections( $sections ) {
148
  $sections['registration'] = array(
149
+ 'title' => __( 'Registration Integration', 'zero-spam' ),
150
  );
151
 
152
  return $sections;
160
  */
161
  public function settings( $settings, $options ) {
162
  $settings['verify_registrations'] = array(
163
+ 'title' => __( 'Protect Registrations', 'zero-spam' ),
164
  'section' => 'registration',
165
  'type' => 'checkbox',
166
  'options' => array(
167
+ 'enabled' => __( 'Monitor registrations for malicious or automated spambots.', 'zero-spam' ),
168
  ),
169
  'value' => ! empty( $options['verify_registrations'] ) ? $options['verify_registrations'] : false,
170
  'recommended' => 'enabled',
171
  );
172
 
173
+ $message = __( 'Your IP has been flagged as spam/malicious.', 'zero-spam' );
174
 
175
  $settings['registration_spam_message'] = array(
176
+ 'title' => __( 'Spam/Malicious Message', 'zero-spam' ),
177
+ 'desc' => __( 'When registration protection is enabled, the message displayed to the user when a registration has been detected as spam/malicious.', 'zero-spam' ),
178
  'section' => 'registration',
179
  'type' => 'text',
180
  'field_class' => 'large-text',
184
  );
185
 
186
  $settings['log_blocked_registrations'] = array(
187
+ 'title' => __( 'Log Blocked Registrations', 'zero-spam' ),
188
  'section' => 'registration',
189
  'type' => 'checkbox',
190
  'desc' => wp_kses(
191
+ __( 'Enables logging blocked registrations. <strong>Recommended for enhanced protection.</strong>', 'zero-spam' ),
192
  array( 'strong' => array() )
193
  ),
194
  'options' => array(
195
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
196
  ),
197
  'value' => ! empty( $options['log_blocked_registrations'] ) ? $options['log_blocked_registrations'] : false,
198
  'recommended' => 'enabled',
modules/wpforms/class-wpforms.php CHANGED
@@ -121,7 +121,7 @@ class WPForms {
121
  * @param array $types Array of available detection types.
122
  */
123
  public function types( $types ) {
124
- $types['wpforms'] = __( 'WPForms', 'zerospam' );
125
 
126
  return $types;
127
  }
@@ -140,7 +140,7 @@ class WPForms {
140
  */
141
  public function sections( $sections ) {
142
  $sections['wpforms'] = array(
143
- 'title' => __( 'WPForms Integration', 'zerospam' ),
144
  );
145
 
146
  return $sections;
@@ -154,21 +154,21 @@ class WPForms {
154
  */
155
  public function settings( $settings, $options ) {
156
  $settings['verify_wpforms'] = array(
157
- 'title' => __( 'Protect WPForms Submissions', 'zerospam' ),
158
  'section' => 'wpforms',
159
  'type' => 'checkbox',
160
  'options' => array(
161
- 'enabled' => __( 'Monitor WPForms submissions for malicious or automated spambots.', 'zerospam' ),
162
  ),
163
  'value' => ! empty( $options['verify_wpforms'] ) ? $options['verify_wpforms'] : false,
164
  'recommended' => 'enabled',
165
  );
166
 
167
- $message = __( 'Your IP has been flagged as spam/malicious.', 'zerospam' );
168
 
169
  $settings['wpforms_spam_message'] = array(
170
- 'title' => __( 'WPForms Spam/Malicious Message', 'zerospam' ),
171
- 'desc' => __( 'When WPForms protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zerospam' ),
172
  'section' => 'wpforms',
173
  'type' => 'text',
174
  'field_class' => 'large-text',
@@ -178,15 +178,15 @@ class WPForms {
178
  );
179
 
180
  $settings['log_blocked_wpforms'] = array(
181
- 'title' => __( 'Log Blocked WPForms Submissions', 'zerospam' ),
182
  'section' => 'wpforms',
183
  'type' => 'checkbox',
184
  'desc' => wp_kses(
185
- __( 'Enables logging blocked WPForms submissions. <strong>Recommended for enhanced protection.</strong>', 'zerospam' ),
186
  array( 'strong' => array() )
187
  ),
188
  'options' => array(
189
- 'enabled' => __( 'Enabled', 'zerospam' ),
190
  ),
191
  'value' => ! empty( $options['log_blocked_wpforms'] ) ? $options['log_blocked_wpforms'] : false,
192
  'recommended' => 'enabled',
121
  * @param array $types Array of available detection types.
122
  */
123
  public function types( $types ) {
124
+ $types['wpforms'] = __( 'WPForms', 'zero-spam' );
125
 
126
  return $types;
127
  }
140
  */
141
  public function sections( $sections ) {
142
  $sections['wpforms'] = array(
143
+ 'title' => __( 'WPForms Integration', 'zero-spam' ),
144
  );
145
 
146
  return $sections;
154
  */
155
  public function settings( $settings, $options ) {
156
  $settings['verify_wpforms'] = array(
157
+ 'title' => __( 'Protect WPForms Submissions', 'zero-spam' ),
158
  'section' => 'wpforms',
159
  'type' => 'checkbox',
160
  'options' => array(
161
+ 'enabled' => __( 'Monitor WPForms submissions for malicious or automated spambots.', 'zero-spam' ),
162
  ),
163
  'value' => ! empty( $options['verify_wpforms'] ) ? $options['verify_wpforms'] : false,
164
  'recommended' => 'enabled',
165
  );
166
 
167
+ $message = __( 'Your IP has been flagged as spam/malicious.', 'zero-spam' );
168
 
169
  $settings['wpforms_spam_message'] = array(
170
+ 'title' => __( 'WPForms Spam/Malicious Message', 'zero-spam' ),
171
+ 'desc' => __( 'When WPForms protection is enabled, the message displayed to the user when a submission has been detected as spam/malicious.', 'zero-spam' ),
172
  'section' => 'wpforms',
173
  'type' => 'text',
174
  'field_class' => 'large-text',
178
  );
179
 
180
  $settings['log_blocked_wpforms'] = array(
181
+ 'title' => __( 'Log Blocked WPForms Submissions', 'zero-spam' ),
182
  'section' => 'wpforms',
183
  'type' => 'checkbox',
184
  'desc' => wp_kses(
185
+ __( 'Enables logging blocked WPForms submissions. <strong>Recommended for enhanced protection.</strong>', 'zero-spam' ),
186
  array( 'strong' => array() )
187
  ),
188
  'options' => array(
189
+ 'enabled' => __( 'Enabled', 'zero-spam' ),
190
  ),
191
  'value' => ! empty( $options['log_blocked_wpforms'] ) ? $options['log_blocked_wpforms'] : false,
192
  'recommended' => 'enabled',
readme.txt CHANGED
@@ -1,11 +1,11 @@
1
- === WordPress Zero Spam ===
2
  Contributors: bmarshall511
3
  Tags: protection, firewall, security, spam, spam blocker
4
  Donate link: https://www.zerospam.org/subscribe/
5
  Requires at least: 5.2
6
  Tested up to: 5.9
7
  Requires PHP: 7.3
8
- Stable tag: 5.2.11
9
  License: GNU GPLv3
10
  License URI: https://choosealicense.com/licenses/gpl-3.0/
11
 
@@ -13,13 +13,13 @@ No captcha needed, behind the scenes protection against spam & malicious attacks
13
 
14
  == Description ==
15
 
16
- Quit forcing people to answer questions or confusing captchas to prove they're not spam. Stop malicious users before they ever have a chance to infiltrate your site &mdash; **introducing WordPress Zero Spam**.
17
 
18
- [WordPress Zero Spam](https://www.highfivery.com/projects/zero-spam/?utm_source=wordpress.org&utm_medium=plugin&utm_campaign=wordpress_zero_spam) uses AI in combination with proven spam detection techniques and databases of known malicious IPs from around the world to detect and block unwanted visitors.
19
 
20
  **Just install, activate, configure, and enjoy a spam-free site!**
21
 
22
- = WordPress Zero Spam features =
23
 
24
  * No captcha, spam isn't a users' problem
25
  * No moderation queues, spam isn't a administrators' problem
@@ -31,7 +31,7 @@ Quit forcing people to answer questions or confusing captchas to prove they're n
31
  * Block known disposable &amp; malicious email domains using [disposable](https://github.com/disposable)
32
  * Multiple detection techniques including [David Walsh's solution](https://davidwalsh.name/wordpress-comment-spam)
33
 
34
- = WordPress Zero Spam also protects =
35
 
36
  * WordPress core comments, user registrations &amp; login attempts
37
  * [GiveWP](https://givewp.com/ref/1118/) donation submissions
@@ -43,11 +43,11 @@ Quit forcing people to answer questions or confusing captchas to prove they're n
43
  * [Mailchimp for WordPress](https://wordpress.org/plugins/mailchimp-for-wp/) submissions
44
  * and can be easily integrated into any existing theme or plugin
45
 
46
- WordPress Zero Spam is great at blocking spam &mdash; as a site owner there's more you can do to [stop WordPress spam](https://www.benmarshall.me/stop-wordpress-spam/) in its tracks.
47
 
48
- = WordPress Zero Spam needs your support =
49
 
50
- **WordPress Zero Spam is free & always will be.** Please consider making a [donation](https://www.benmarshall.me/donate/?utm_source=wordpress.org&utm_medium=plugin&utm_campaign=wordpress_zero_spam) to help encourage plugin's continued development.
51
 
52
  * Like our [Facebook Page](https://www.facebook.com/zerospamorg/)
53
  * Follow us on [Twitter](https://www.facebook.com/zerospamorg)
@@ -63,23 +63,23 @@ For more information & developer documentation, see the [plugin’s website](htt
63
 
64
  == Frequently Asked Questions ==
65
 
66
- = Does WordPress Zero Spam block user IPs? =
67
 
68
- *Not by itself.* WordPress Zero Spam does not block IP addresses by itself. Visitors that are getting blocked have either been manually blocked by the site admin or appear in one of the IP blacklist like [Stop Forum Spam](https://www.stopforumspam.com/), [Project Honeypot](https://www.projecthoneypot.org/), or the [Zero Spam IP database](https://www.zerospam.org).
69
 
70
  If a legitimate user is getting blocked, check the Log (Admin > Dashboard > Zero Spam > Log) to get further details why they were blocked. You can adjust how strict the 3rd-party blacklist checks are or disable those if you find that your users are prone to being flagged as spam/malicious.
71
 
72
- = Does WordPress Zero Spam check Jetpack comments? =
73
 
74
- **No.** WordPress Zero Spam is unable to integrate Jetpack. For more information, see [https://wordpress.org/support/topic/incompatible-with-jetpack-comments](https://wordpress.org/support/topic/incompatible-with-jetpack-comments).
75
 
76
- = How do I boost performance of WordPress Zero Spam? =
77
 
78
  **Enabled caching.** Caching is highly recommended and will prevent repeated calls to third-party API and access checks on each page visit.
79
 
80
  You can also adjust the cache and API timeout settings in admin depending on your server and specific needs.
81
 
82
- = What WordPress Zero Spam WP-CLI commands are available? =
83
 
84
  * `wp zerospam autoconfigure` &mdash; Auto-configures with recommended settings.
85
  * `wp zerospam settings` &mdash; Displays all plugin settings.
@@ -95,14 +95,18 @@ If hosting with Pantheon, see their [known issues page](https://pantheon.io/docs
95
 
96
  == Screenshots ==
97
 
98
- 1. WordPress Zero Spam dashboard
99
- 2. WordPress Zero Spam detections log
100
- 3. WordPress Zero Spam blocked IPs
101
- 4. WordPress Zero Spam blacklisted IPs
102
- 5. WordPress Zero Spam settings
103
 
104
  == Changelog ==
105
 
 
 
 
 
106
  = v5.2.11
107
 
108
  * fix(security): fixes the missing orderby parameter sanitization in the admin dashboard
@@ -238,7 +242,7 @@ If hosting with Pantheon, see their [known issues page](https://pantheon.io/docs
238
 
239
  = v5.0.12 =
240
 
241
- * Fixed issue with WPForms AJAX forms not getting validated by WordPress Zero Spam [#238](https://github.com/bmarshall511/wordpress-zero-spam/issues/238)
242
  * David Walsh detection technique applied to WPForms & CF7
243
  * Miscellaneous admin UI improvements
244
  * Added ability to disable syncing WP's Disallowed Comment Keys
1
+ === Zero Spam for WordPress ===
2
  Contributors: bmarshall511
3
  Tags: protection, firewall, security, spam, spam blocker
4
  Donate link: https://www.zerospam.org/subscribe/
5
  Requires at least: 5.2
6
  Tested up to: 5.9
7
  Requires PHP: 7.3
8
+ Stable tag: 5.2.12
9
  License: GNU GPLv3
10
  License URI: https://choosealicense.com/licenses/gpl-3.0/
11
 
13
 
14
  == Description ==
15
 
16
+ Quit forcing people to answer questions or confusing captchas to prove they're not spam. Stop malicious users before they ever have a chance to infiltrate your site &mdash; **introducing Zero Spam for WordPress**.
17
 
18
+ [Zero Spam for WordPress](https://www.highfivery.com/projects/zero-spam/?utm_source=wordpress.org&utm_medium=plugin&utm_campaign=wordpress_zero_spam) uses AI in combination with proven spam detection techniques and databases of known malicious IPs from around the world to detect and block unwanted visitors.
19
 
20
  **Just install, activate, configure, and enjoy a spam-free site!**
21
 
22
+ = Zero Spam for WordPress features =
23
 
24
  * No captcha, spam isn't a users' problem
25
  * No moderation queues, spam isn't a administrators' problem
31
  * Block known disposable &amp; malicious email domains using [disposable](https://github.com/disposable)
32
  * Multiple detection techniques including [David Walsh's solution](https://davidwalsh.name/wordpress-comment-spam)
33
 
34
+ = Zero Spam for WordPress also protects =
35
 
36
  * WordPress core comments, user registrations &amp; login attempts
37
  * [GiveWP](https://givewp.com/ref/1118/) donation submissions
43
  * [Mailchimp for WordPress](https://wordpress.org/plugins/mailchimp-for-wp/) submissions
44
  * and can be easily integrated into any existing theme or plugin
45
 
46
+ Zero Spam for WordPress is great at blocking spam &mdash; as a site owner there's more you can do to [stop WordPress spam](https://www.benmarshall.me/stop-wordpress-spam/) in its tracks.
47
 
48
+ = Zero Spam for WordPress needs your support =
49
 
50
+ **Zero Spam for WordPress is free & always will be.** Please consider making a [donation](https://www.benmarshall.me/donate/?utm_source=wordpress.org&utm_medium=plugin&utm_campaign=wordpress_zero_spam) to help encourage plugin's continued development.
51
 
52
  * Like our [Facebook Page](https://www.facebook.com/zerospamorg/)
53
  * Follow us on [Twitter](https://www.facebook.com/zerospamorg)
63
 
64
  == Frequently Asked Questions ==
65
 
66
+ = Does Zero Spam for WordPress block user IPs? =
67
 
68
+ *Not by itself.* Zero Spam for WordPress does not block IP addresses by itself. Visitors that are getting blocked have either been manually blocked by the site admin or appear in one of the IP blacklist like [Stop Forum Spam](https://www.stopforumspam.com/), [Project Honeypot](https://www.projecthoneypot.org/), or the [Zero Spam IP database](https://www.zerospam.org).
69
 
70
  If a legitimate user is getting blocked, check the Log (Admin > Dashboard > Zero Spam > Log) to get further details why they were blocked. You can adjust how strict the 3rd-party blacklist checks are or disable those if you find that your users are prone to being flagged as spam/malicious.
71
 
72
+ = Does Zero Spam for WordPress check Jetpack comments? =
73
 
74
+ **No.** Zero Spam for WordPress is unable to integrate Jetpack. For more information, see [https://wordpress.org/support/topic/incompatible-with-jetpack-comments](https://wordpress.org/support/topic/incompatible-with-jetpack-comments).
75
 
76
+ = How do I boost performance of Zero Spam for WordPress? =
77
 
78
  **Enabled caching.** Caching is highly recommended and will prevent repeated calls to third-party API and access checks on each page visit.
79
 
80
  You can also adjust the cache and API timeout settings in admin depending on your server and specific needs.
81
 
82
+ = What Zero Spam for WordPress WP-CLI commands are available? =
83
 
84
  * `wp zerospam autoconfigure` &mdash; Auto-configures with recommended settings.
85
  * `wp zerospam settings` &mdash; Displays all plugin settings.
95
 
96
  == Screenshots ==
97
 
98
+ 1. Zero Spam for WordPress dashboard
99
+ 2. Zero Spam for WordPress detections log
100
+ 3. Zero Spam for WordPress blocked IPs
101
+ 4. Zero Spam for WordPress blacklisted IPs
102
+ 5. Zero Spam for WordPress settings
103
 
104
  == Changelog ==
105
 
106
+ = v5.2.12 =
107
+
108
+ * refactor(wordpress coding standards): misc updates to conform to wordpress coding standards
109
+
110
  = v5.2.11
111
 
112
  * fix(security): fixes the missing orderby parameter sanitization in the admin dashboard
242
 
243
  = v5.0.12 =
244
 
245
+ * Fixed issue with WPForms AJAX forms not getting validated by Zero Spam for WordPress [#238](https://github.com/bmarshall511/wordpress-zero-spam/issues/238)
246
  * David Walsh detection technique applied to WPForms & CF7
247
  * Miscellaneous admin UI improvements
248
  * Added ability to disable syncing WP's Disallowed Comment Keys
wordpress-zero-spam.php CHANGED
@@ -1,24 +1,24 @@
1
  <?php
2
  /**
3
- * WordPress Zero Spam Plugin
4
  *
5
- * @package WordPressZeroSpam
6
  * @subpackage WordPress
7
  * @since 5.0.0
8
  * @author Highfivery LLC
9
- * @copyright 2021 Highfivery LLC
10
  * @license GPL-2.0-or-later
11
  *
12
  * @wordpress-plugin
13
- * Plugin Name: WordPress Zero Spam
14
  * Plugin URI: https://www.highfivery.com/projects/zero-spam/
15
- * Description: Tired of all the worthless and bloated WordPress anti-spam & security plugins? WordPress Zero Spam makes blocking spam &amp; malicious activity a cinch. <strong>Just install, activate, configure, and say goodbye to spam.</strong>
16
- * Version: 5.2.11
17
  * Requires at least: 5.2
18
  * Requires PHP: 7.3
19
  * Author: Highfivery LLC
20
  * Author URI: https://www.highfivery.com/
21
- * Text Domain: zerospam
22
  * Domain Path: /languages
23
  * License: GPL v2 or later
24
  * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
@@ -31,7 +31,7 @@ defined( 'ABSPATH' ) || die();
31
  define( 'ZEROSPAM', __FILE__ );
32
  define( 'ZEROSPAM_PATH', plugin_dir_path( ZEROSPAM ) );
33
  define( 'ZEROSPAM_PLUGIN_BASE', plugin_basename( ZEROSPAM ) );
34
- define( 'ZEROSPAM_VERSION', '5.2.11' );
35
 
36
  if ( defined( 'ZEROSPAM_DEVELOPMENT_URL' ) ) {
37
  define( 'ZEROSPAM_URL', ZEROSPAM_DEVELOPMENT_URL );
@@ -53,7 +53,7 @@ if ( ! version_compare( PHP_VERSION, '7.3', '>=' ) ) {
53
  * Load plugin textdomain
54
  */
55
  function zerospam_load_plugin_textdomain() {
56
- load_plugin_textdomain( 'zerospam' );
57
  }
58
 
59
  /**
@@ -63,8 +63,8 @@ function zerospam_fail_php_version() {
63
  $message = sprintf(
64
  /* translators: %s: replaced with the PHP version number */
65
  esc_html__(
66
- 'WordPress Zero Spam requires PHP version %s+, plugin is currently NOT RUNNING.',
67
- 'zerospam'
68
  ),
69
  '7.3'
70
  );
@@ -83,7 +83,7 @@ function zerospam_fail_wp_version() {
83
  $message = sprintf(
84
  /* translators: %s: replaced with the WordPress version number */
85
  esc_html__(
86
- 'WordPress Zero Spam requires WordPress version %s+. Because you are using an earlier version, the plugin is currently NOT RUNNING.',
87
  'zerospam'
88
  ),
89
  '5'
1
  <?php
2
  /**
3
+ * Zero Spam for WordPress Plugin
4
  *
5
+ * @package ZeroSpam
6
  * @subpackage WordPress
7
  * @since 5.0.0
8
  * @author Highfivery LLC
9
+ * @copyright 2022 Highfivery LLC
10
  * @license GPL-2.0-or-later
11
  *
12
  * @wordpress-plugin
13
+ * Plugin Name: Zero Spam for WordPress
14
  * Plugin URI: https://www.highfivery.com/projects/zero-spam/
15
+ * Description: Tired of all the ineffective WordPress anti-spam & security plugins? Zero Spam for WordPress makes blocking spam &amp; malicious activity a cinch. <strong>Just activate, configure, and say goodbye to spam.</strong>
16
+ * Version: 5.2.12
17
  * Requires at least: 5.2
18
  * Requires PHP: 7.3
19
  * Author: Highfivery LLC
20
  * Author URI: https://www.highfivery.com/
21
+ * Text Domain: zero-spam
22
  * Domain Path: /languages
23
  * License: GPL v2 or later
24
  * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
31
  define( 'ZEROSPAM', __FILE__ );
32
  define( 'ZEROSPAM_PATH', plugin_dir_path( ZEROSPAM ) );
33
  define( 'ZEROSPAM_PLUGIN_BASE', plugin_basename( ZEROSPAM ) );
34
+ define( 'ZEROSPAM_VERSION', '5.2.12' );
35
 
36
  if ( defined( 'ZEROSPAM_DEVELOPMENT_URL' ) ) {
37
  define( 'ZEROSPAM_URL', ZEROSPAM_DEVELOPMENT_URL );
53
  * Load plugin textdomain
54
  */
55
  function zerospam_load_plugin_textdomain() {
56
+ load_plugin_textdomain( 'zero-spam' );
57
  }
58
 
59
  /**
63
  $message = sprintf(
64
  /* translators: %s: replaced with the PHP version number */
65
  esc_html__(
66
+ 'Zero Spam for WordPress requires PHP version %s+, plugin is currently NOT RUNNING.',
67
+ 'zero-spam'
68
  ),
69
  '7.3'
70
  );
83
  $message = sprintf(
84
  /* translators: %s: replaced with the WordPress version number */
85
  esc_html__(
86
+ 'Zero Spam for WordPress requires WordPress version %s+. Because you are using an earlier version, the plugin is currently NOT RUNNING.',
87
  'zerospam'
88
  ),
89
  '5'