diff --git a/404.html b/404.html index bf4d1fb1..15b36b72 100644 --- a/404.html +++ b/404.html @@ -1,12 +1,14 @@ 404 Page not found -
Page Not Found

404

The page you are looking for is not there yet.

\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/application.29ad74523cc80fab32a2f75bc2d8ad70b1d090924005fb70f44571d75de5968e.js b/application.b68a12dc7717f07656966ceb9e6873af3b28ec93f7e6dcb8b6b9ebeedf46a561.js similarity index 99% rename from application.29ad74523cc80fab32a2f75bc2d8ad70b1d090924005fb70f44571d75de5968e.js rename to application.b68a12dc7717f07656966ceb9e6873af3b28ec93f7e6dcb8b6b9ebeedf46a561.js index 09fd9ac8..dcc1dd7e 100644 --- a/application.29ad74523cc80fab32a2f75bc2d8ad70b1d090924005fb70f44571d75de5968e.js +++ b/application.b68a12dc7717f07656966ceb9e6873af3b28ec93f7e6dcb8b6b9ebeedf46a561.js @@ -1843,7 +1843,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function ee(){throw new TypeError(`Invalid attempt to destructure non-iterable instance. In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var Ce=function(){},ce={},G={},de=null,xe={mark:Ce,measure:Ce};try{typeof window<"u"&&(ce=window),typeof document<"u"&&(G=document),typeof MutationObserver<"u"&&(de=MutationObserver),typeof performance<"u"&&(xe=performance)}catch{}var ie=ce.navigator||{},ke=ie.userAgent,He=ke===void 0?"":ke,me=ce,Ve=G,se=de,ut=xe,ve=!!me.document,Ge=!!Ve.documentElement&&!!Ve.head&&typeof Ve.addEventListener=="function"&&typeof Ve.createElement=="function",bt=~He.indexOf("MSIE")||~He.indexOf("Trident/"),Ct,Rt,Gt,Mt,Te,Nn="___FONT_AWESOME___",wn=16,jt="fa",cr="svg-inline--fa",Kt="data-fa-i2svg",un="data-fa-pseudo-element",ct="data-fa-pseudo-element-pending",yt="data-prefix",tt="data-icon",st="fontawesome-i2svg",Ut="async",lt=["HTML","HEAD","STYLE","SCRIPT"],m1=function(){try{return!0}catch{return!1}}(),Je="classic",Gr="sharp",yn=[Je,Gr];function wr(at){return new Proxy(at,{get:function(Nt,Jt){return Jt in Nt?Nt[Jt]:Nt[Je]}})}var j1=wr((Ct={},b(Ct,Je,{fa:"solid",fas:"solid","fa-solid":"solid",far:"regular","fa-regular":"regular",fal:"light","fa-light":"light",fat:"thin","fa-thin":"thin",fad:"duotone","fa-duotone":"duotone",fab:"brands","fa-brands":"brands",fak:"kit",fakd:"kit","fa-kit":"kit","fa-kit-duotone":"kit"}),b(Ct,Gr,{fa:"solid",fass:"solid","fa-solid":"solid",fasr:"regular","fa-regular":"regular",fasl:"light","fa-light":"light",fast:"thin","fa-thin":"thin"}),Ct)),C1=wr((Rt={},b(Rt,Je,{solid:"fas",regular:"far",light:"fal",thin:"fat",duotone:"fad",brands:"fab",kit:"fak"}),b(Rt,Gr,{solid:"fass",regular:"fasr",light:"fasl",thin:"fast"}),Rt)),k1=wr((Gt={},b(Gt,Je,{fab:"fa-brands",fad:"fa-duotone",fak:"fa-kit",fal:"fa-light",far:"fa-regular",fas:"fa-solid",fat:"fa-thin"}),b(Gt,Gr,{fass:"fa-solid",fasr:"fa-regular",fasl:"fa-light",fast:"fa-thin"}),Gt)),Kn=wr((Mt={},b(Mt,Je,{"fa-brands":"fab","fa-duotone":"fad","fa-kit":"fak","fa-light":"fal","fa-regular":"far","fa-solid":"fas","fa-thin":"fat"}),b(Mt,Gr,{"fa-solid":"fass","fa-regular":"fasr","fa-light":"fasl","fa-thin":"fast"}),Mt)),Mn=/fa(s|r|l|t|d|b|k|ss|sr|sl|st)?[\-\ ]/,qn="fa-layers-text",w1=/Font ?Awesome ?([56 ]*)(Solid|Regular|Light|Thin|Duotone|Brands|Free|Pro|Sharp|Kit)?.*/i,O1=wr((Te={},b(Te,Je,{900:"fas",400:"far",normal:"far",300:"fal",100:"fat"}),b(Te,Gr,{900:"fass",400:"fasr",300:"fasl",100:"fast"}),Te)),ar=[1,2,3,4,5,6,7,8,9,10],fr=ar.concat([11,12,13,14,15,16,17,18,19,20]),pi=["class","data-prefix","data-icon","data-fa-transform","data-fa-mask"],Ui={GROUP:"duotone-group",SWAP_OPACITY:"swap-opacity",PRIMARY:"primary",SECONDARY:"secondary"},b2=new Set;Object.keys(C1[Je]).map(b2.add.bind(b2)),Object.keys(C1[Gr]).map(b2.add.bind(b2));var $t=[].concat(yn,L(b2),["2xs","xs","sm","lg","xl","2xl","beat","border","fade","beat-fade","bounce","flip-both","flip-horizontal","flip-vertical","flip","fw","inverse","layers-counter","layers-text","layers","li","pull-left","pull-right","pulse","rotate-180","rotate-270","rotate-90","rotate-by","shake","spin-pulse","spin-reverse","spin","stack-1x","stack-2x","stack","ul",Ui.GROUP,Ui.SWAP_OPACITY,Ui.PRIMARY,Ui.SECONDARY]).concat(ar.map(function(at){return"".concat(at,"x")})).concat(fr.map(function(at){return"w-".concat(at)})),Qe=me.FontAwesomeConfig||{};function Ye(at){var wt=Ve.querySelector("script["+at+"]");if(wt)return wt.getAttribute(at)}function et(at){return at===""?!0:at==="false"?!1:at==="true"?!0:at}if(Ve&&typeof Ve.querySelector=="function"){var Xe=[["data-family-prefix","familyPrefix"],["data-css-prefix","cssPrefix"],["data-family-default","familyDefault"],["data-style-default","styleDefault"],["data-replacement-class","replacementClass"],["data-auto-replace-svg","autoReplaceSvg"],["data-auto-add-css","autoAddCss"],["data-auto-a11y","autoA11y"],["data-search-pseudo-elements","searchPseudoElements"],["data-observe-mutations","observeMutations"],["data-mutate-approach","mutateApproach"],["data-keep-original-source","keepOriginalSource"],["data-measure-performance","measurePerformance"],["data-show-missing-icons","showMissingIcons"]];Xe.forEach(function(at){var wt=A(at,2),Nt=wt[0],Jt=wt[1],je=et(Ye(Nt));je!=null&&(Qe[Jt]=je)})}var Pt={styleDefault:"solid",familyDefault:"classic",cssPrefix:jt,replacementClass:cr,autoReplaceSvg:!0,autoAddCss:!0,autoA11y:!0,searchPseudoElements:!1,observeMutations:!0,mutateApproach:"async",keepOriginalSource:!0,measurePerformance:!1,showMissingIcons:!0};Qe.familyPrefix&&(Qe.cssPrefix=Qe.familyPrefix);var Yt=a(a({},Pt),Qe);Yt.autoReplaceSvg||(Yt.observeMutations=!1);var Dt={};Object.keys(Pt).forEach(function(at){Object.defineProperty(Dt,at,{enumerable:!0,set:function(Nt){Yt[at]=Nt,F1.forEach(function(Jt){return Jt(Dt)})},get:function(){return Yt[at]}})}),Object.defineProperty(Dt,"familyPrefix",{enumerable:!0,set:function(wt){Yt.cssPrefix=wt,F1.forEach(function(Nt){return Nt(Dt)})},get:function(){return Yt.cssPrefix}}),me.FontAwesomeConfig=Dt;var F1=[];function En(at){return F1.push(at),function(){F1.splice(F1.indexOf(at),1)}}var Ee=wn,ot={size:16,x:0,y:0,rotate:0,flipX:!1,flipY:!1};function an(at){try{for(var wt=arguments.length,Nt=new Array(wt>1?wt-1:0),Jt=1;Jt-1;je--){var Et=Nt[je],It=(Et.tagName||"").toUpperCase();["STYLE","LINK"].indexOf(It)>-1&&(Jt=Et)}return Ve.head.insertBefore(wt,Jt),at}}var jn="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";function $n(){for(var at=12,wt="";at-- >0;)wt+=jn[Math.random()*62|0];return wt}function _1(at){for(var wt=[],Nt=(at||[]).length>>>0;Nt--;)wt[Nt]=at[Nt];return wt}function J1(at){return at.classList?_1(at.classList):(at.getAttribute("class")||"").split(" ").filter(function(wt){return wt})}function hr(at){return"".concat(at).replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")}function o2(at){return Object.keys(at||{}).reduce(function(wt,Nt){return wt+"".concat(Nt,'="').concat(hr(at[Nt]),'" ')},"").trim()}function r2(at){return Object.keys(at||{}).reduce(function(wt,Nt){return wt+"".concat(Nt,": ").concat(at[Nt].trim(),";")},"")}function hi(at){return at.size!==ot.size||at.x!==ot.x||at.y!==ot.y||at.rotate!==ot.rotate||at.flipX||at.flipY}function di(at){var wt=at.transform,Nt=at.containerWidth,Jt=at.iconWidth,je={transform:"translate(".concat(Nt/2," 256)")},Et="translate(".concat(wt.x*32,", ").concat(wt.y*32,") "),It="scale(".concat(wt.size/16*(wt.flipX?-1:1),", ").concat(wt.size/16*(wt.flipY?-1:1),") "),sn="rotate(".concat(wt.rotate," 0 0)"),Ln={transform:"".concat(Et," ").concat(It," ").concat(sn)},V1={transform:"translate(".concat(Jt/2*-1," -256)")};return{outer:je,inner:Ln,path:V1}}function Qi(at){var wt=at.transform,Nt=at.width,Jt=Nt===void 0?wn:Nt,je=at.height,Et=je===void 0?wn:je,It=at.startCentered,sn=It===void 0?!1:It,Ln="";return sn&&bt?Ln+="translate(".concat(wt.x/Ee-Jt/2,"em, ").concat(wt.y/Ee-Et/2,"em) "):sn?Ln+="translate(calc(-50% + ".concat(wt.x/Ee,"em), calc(-50% + ").concat(wt.y/Ee,"em)) "):Ln+="translate(".concat(wt.x/Ee,"em, ").concat(wt.y/Ee,"em) "),Ln+="scale(".concat(wt.size/Ee*(wt.flipX?-1:1),", ").concat(wt.size/Ee*(wt.flipY?-1:1),") "),Ln+="rotate(".concat(wt.rotate,"deg) "),Ln}var F2=':host,:root{--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Solid";--fa-font-regular:normal 400 1em/1 "Font Awesome 6 Regular";--fa-font-light:normal 300 1em/1 "Font Awesome 6 Light";--fa-font-thin:normal 100 1em/1 "Font Awesome 6 Thin";--fa-font-duotone:normal 900 1em/1 "Font Awesome 6 Duotone";--fa-font-sharp-solid:normal 900 1em/1 "Font Awesome 6 Sharp";--fa-font-sharp-regular:normal 400 1em/1 "Font Awesome 6 Sharp";--fa-font-sharp-light:normal 300 1em/1 "Font Awesome 6 Sharp";--fa-font-sharp-thin:normal 100 1em/1 "Font Awesome 6 Sharp";--fa-font-brands:normal 400 1em/1 "Font Awesome 6 Brands"}svg:not(:host).svg-inline--fa,svg:not(:root).svg-inline--fa{overflow:visible;box-sizing:content-box}.svg-inline--fa{display:var(--fa-display,inline-block);height:1em;overflow:visible;vertical-align:-.125em}.svg-inline--fa.fa-2xs{vertical-align:.1em}.svg-inline--fa.fa-xs{vertical-align:0}.svg-inline--fa.fa-sm{vertical-align:-.0714285705em}.svg-inline--fa.fa-lg{vertical-align:-.2em}.svg-inline--fa.fa-xl{vertical-align:-.25em}.svg-inline--fa.fa-2xl{vertical-align:-.3125em}.svg-inline--fa.fa-pull-left{margin-right:var(--fa-pull-margin,.3em);width:auto}.svg-inline--fa.fa-pull-right{margin-left:var(--fa-pull-margin,.3em);width:auto}.svg-inline--fa.fa-li{width:var(--fa-li-width,2em);top:.25em}.svg-inline--fa.fa-fw{width:var(--fa-fw-width,1.25em)}.fa-layers svg.svg-inline--fa{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.fa-layers-counter,.fa-layers-text{display:inline-block;position:absolute;text-align:center}.fa-layers{display:inline-block;height:1em;position:relative;text-align:center;vertical-align:-.125em;width:1em}.fa-layers svg.svg-inline--fa{-webkit-transform-origin:center center;transform-origin:center center}.fa-layers-text{left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);-webkit-transform-origin:center center;transform-origin:center center}.fa-layers-counter{background-color:var(--fa-counter-background-color,#ff253a);border-radius:var(--fa-counter-border-radius,1em);box-sizing:border-box;color:var(--fa-inverse,#fff);line-height:var(--fa-counter-line-height,1);max-width:var(--fa-counter-max-width,5em);min-width:var(--fa-counter-min-width,1.5em);overflow:hidden;padding:var(--fa-counter-padding,.25em .5em);right:var(--fa-right,0);text-overflow:ellipsis;top:var(--fa-top,0);-webkit-transform:scale(var(--fa-counter-scale,.25));transform:scale(var(--fa-counter-scale,.25));-webkit-transform-origin:top right;transform-origin:top right}.fa-layers-bottom-right{bottom:var(--fa-bottom,0);right:var(--fa-right,0);top:auto;-webkit-transform:scale(var(--fa-layers-scale,.25));transform:scale(var(--fa-layers-scale,.25));-webkit-transform-origin:bottom right;transform-origin:bottom right}.fa-layers-bottom-left{bottom:var(--fa-bottom,0);left:var(--fa-left,0);right:auto;top:auto;-webkit-transform:scale(var(--fa-layers-scale,.25));transform:scale(var(--fa-layers-scale,.25));-webkit-transform-origin:bottom left;transform-origin:bottom left}.fa-layers-top-right{top:var(--fa-top,0);right:var(--fa-right,0);-webkit-transform:scale(var(--fa-layers-scale,.25));transform:scale(var(--fa-layers-scale,.25));-webkit-transform-origin:top right;transform-origin:top right}.fa-layers-top-left{left:var(--fa-left,0);right:auto;top:var(--fa-top,0);-webkit-transform:scale(var(--fa-layers-scale,.25));transform:scale(var(--fa-layers-scale,.25));-webkit-transform-origin:top left;transform-origin:top left}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-2xs{font-size:.625em;line-height:.1em;vertical-align:.225em}.fa-xs{font-size:.75em;line-height:.0833333337em;vertical-align:.125em}.fa-sm{font-size:.875em;line-height:.0714285718em;vertical-align:.0535714295em}.fa-lg{font-size:1.25em;line-height:.05em;vertical-align:-.075em}.fa-xl{font-size:1.5em;line-height:.0416666682em;vertical-align:-.125em}.fa-2xl{font-size:2em;line-height:.03125em;vertical-align:-.1875em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:var(--fa-li-margin,2.5em);padding-left:0}.fa-ul>li{position:relative}.fa-li{left:calc(var(--fa-li-width,2em) * -1);position:absolute;text-align:center;width:var(--fa-li-width,2em);line-height:inherit}.fa-border{border-color:var(--fa-border-color,#eee);border-radius:var(--fa-border-radius,.1em);border-style:var(--fa-border-style,solid);border-width:var(--fa-border-width,.08em);padding:var(--fa-border-padding,.2em .25em .15em)}.fa-pull-left{float:left;margin-right:var(--fa-pull-margin,.3em)}.fa-pull-right{float:right;margin-left:var(--fa-pull-margin,.3em)}.fa-beat{-webkit-animation-name:fa-beat;animation-name:fa-beat;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-bounce{-webkit-animation-name:fa-bounce;animation-name:fa-bounce;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1))}.fa-fade{-webkit-animation-name:fa-fade;animation-name:fa-fade;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-beat-fade{-webkit-animation-name:fa-beat-fade;animation-name:fa-beat-fade;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-flip{-webkit-animation-name:fa-flip;animation-name:fa-flip;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-shake{-webkit-animation-name:fa-shake;animation-name:fa-shake;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,linear);animation-timing-function:var(--fa-animation-timing,linear)}.fa-spin{-webkit-animation-name:fa-spin;animation-name:fa-spin;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,2s);animation-duration:var(--fa-animation-duration,2s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,linear);animation-timing-function:var(--fa-animation-timing,linear)}.fa-spin-reverse{--fa-animation-direction:reverse}.fa-pulse,.fa-spin-pulse{-webkit-animation-name:fa-spin;animation-name:fa-spin;-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,steps(8));animation-timing-function:var(--fa-animation-timing,steps(8))}@media (prefers-reduced-motion:reduce){.fa-beat,.fa-beat-fade,.fa-bounce,.fa-fade,.fa-flip,.fa-pulse,.fa-shake,.fa-spin,.fa-spin-pulse{-webkit-animation-delay:-1ms;animation-delay:-1ms;-webkit-animation-duration:1ms;animation-duration:1ms;-webkit-animation-iteration-count:1;animation-iteration-count:1;-webkit-transition-delay:0s;transition-delay:0s;-webkit-transition-duration:0s;transition-duration:0s}}@-webkit-keyframes fa-beat{0%,90%{-webkit-transform:scale(1);transform:scale(1)}45%{-webkit-transform:scale(var(--fa-beat-scale,1.25));transform:scale(var(--fa-beat-scale,1.25))}}@keyframes fa-beat{0%,90%{-webkit-transform:scale(1);transform:scale(1)}45%{-webkit-transform:scale(var(--fa-beat-scale,1.25));transform:scale(var(--fa-beat-scale,1.25))}}@-webkit-keyframes fa-bounce{0%{-webkit-transform:scale(1,1) translateY(0);transform:scale(1,1) translateY(0)}10%{-webkit-transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0);transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{-webkit-transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em));transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{-webkit-transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0);transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{-webkit-transform:scale(1,1) translateY(var(--fa-bounce-rebound,-.125em));transform:scale(1,1) translateY(var(--fa-bounce-rebound,-.125em))}64%{-webkit-transform:scale(1,1) translateY(0);transform:scale(1,1) translateY(0)}100%{-webkit-transform:scale(1,1) translateY(0);transform:scale(1,1) translateY(0)}}@keyframes fa-bounce{0%{-webkit-transform:scale(1,1) translateY(0);transform:scale(1,1) translateY(0)}10%{-webkit-transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0);transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{-webkit-transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em));transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{-webkit-transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0);transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{-webkit-transform:scale(1,1) translateY(var(--fa-bounce-rebound,-.125em));transform:scale(1,1) translateY(var(--fa-bounce-rebound,-.125em))}64%{-webkit-transform:scale(1,1) translateY(0);transform:scale(1,1) translateY(0)}100%{-webkit-transform:scale(1,1) translateY(0);transform:scale(1,1) translateY(0)}}@-webkit-keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@-webkit-keyframes fa-beat-fade{0%,100%{opacity:var(--fa-beat-fade-opacity,.4);-webkit-transform:scale(1);transform:scale(1)}50%{opacity:1;-webkit-transform:scale(var(--fa-beat-fade-scale,1.125));transform:scale(var(--fa-beat-fade-scale,1.125))}}@keyframes fa-beat-fade{0%,100%{opacity:var(--fa-beat-fade-opacity,.4);-webkit-transform:scale(1);transform:scale(1)}50%{opacity:1;-webkit-transform:scale(var(--fa-beat-fade-scale,1.125));transform:scale(var(--fa-beat-fade-scale,1.125))}}@-webkit-keyframes fa-flip{50%{-webkit-transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg));transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@keyframes fa-flip{50%{-webkit-transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg));transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@-webkit-keyframes fa-shake{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}4%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}24%,8%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}12%,28%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}20%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}32%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}36%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}100%,40%{-webkit-transform:rotate(0);transform:rotate(0)}}@keyframes fa-shake{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}4%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}24%,8%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}12%,28%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}20%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}32%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}36%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}100%,40%{-webkit-transform:rotate(0);transform:rotate(0)}}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.fa-rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-webkit-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-webkit-transform:scale(1,-1);transform:scale(1,-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1,-1);transform:scale(-1,-1)}.fa-rotate-by{-webkit-transform:rotate(var(--fa-rotate-angle,none));transform:rotate(var(--fa-rotate-angle,none))}.fa-stack{display:inline-block;vertical-align:middle;height:2em;position:relative;width:2.5em}.fa-stack-1x,.fa-stack-2x{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0;z-index:var(--fa-stack-z-index,auto)}.svg-inline--fa.fa-stack-1x{height:1em;width:1.25em}.svg-inline--fa.fa-stack-2x{height:2em;width:2.5em}.fa-inverse{color:var(--fa-inverse,#fff)}.fa-sr-only,.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.fa-sr-only-focusable:not(:focus),.sr-only-focusable:not(:focus){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.svg-inline--fa .fa-primary{fill:var(--fa-primary-color,currentColor);opacity:var(--fa-primary-opacity,1)}.svg-inline--fa .fa-secondary{fill:var(--fa-secondary-color,currentColor);opacity:var(--fa-secondary-opacity,.4)}.svg-inline--fa.fa-swap-opacity .fa-primary{opacity:var(--fa-secondary-opacity,.4)}.svg-inline--fa.fa-swap-opacity .fa-secondary{opacity:var(--fa-primary-opacity,1)}.svg-inline--fa mask .fa-primary,.svg-inline--fa mask .fa-secondary{fill:#000}.fa-duotone.fa-inverse,.fad.fa-inverse{color:var(--fa-inverse,#fff)}';function i2(){var at=jt,wt=cr,Nt=Dt.cssPrefix,Jt=Dt.replacementClass,je=F2;if(Nt!==at||Jt!==wt){var Et=new RegExp("\\.".concat(at,"\\-"),"g"),It=new RegExp("\\--".concat(at,"\\-"),"g"),sn=new RegExp("\\.".concat(wt),"g");je=je.replace(Et,".".concat(Nt,"-")).replace(It,"--".concat(Nt,"-")).replace(sn,".".concat(Jt))}return je}var Vs=!1;function bs(){Dt.autoAddCss&&!Vs&&(kn(i2()),Vs=!0)}var Ea={mixout:function(){return{dom:{css:i2,insertCss:bs}}},hooks:function(){return{beforeDOMElementCreation:function(){bs()},beforeI2svg:function(){bs()}}}},v2=me||{};v2[Nn]||(v2[Nn]={}),v2[Nn].styles||(v2[Nn].styles={}),v2[Nn].hooks||(v2[Nn].hooks={}),v2[Nn].shims||(v2[Nn].shims=[]);var ua=v2[Nn],W2=[],ec=function at(){Ve.removeEventListener("DOMContentLoaded",at),wa=1,W2.map(function(wt){return wt()})},wa=!1;Ge&&(wa=(Ve.documentElement.doScroll?/^loaded|^c/:/^loaded|^i|^c/).test(Ve.readyState),wa||Ve.addEventListener("DOMContentLoaded",ec));function Fc(at){Ge&&(wa?setTimeout(at,0):W2.push(at))}function zo(at){var wt=at.tag,Nt=at.attributes,Jt=Nt===void 0?{}:Nt,je=at.children,Et=je===void 0?[]:je;return typeof at=="string"?hr(at):"<".concat(wt," ").concat(o2(Jt),">").concat(Et.map(zo).join(""),"")}function Oc(at,wt,Nt){if(at&&at[wt]&&at[wt][Nt])return{prefix:wt,iconName:Nt,icon:at[wt][Nt]}}var U3=function(wt,Nt){return function(Jt,je,Et,It){return wt.call(Nt,Jt,je,Et,It)}},tc=function(wt,Nt,Jt,je){var Et=Object.keys(wt),It=Et.length,sn=je!==void 0?U3(Nt,je):Nt,Ln,V1,Y1;for(Jt===void 0?(Ln=1,Y1=wt[Et[0]]):(Ln=0,Y1=Jt);Ln=55296&&je<=56319&&Nt=55296&&Jt<=56319&&Nt>wt+1&&(je=at.charCodeAt(wt+1),je>=56320&&je<=57343)?(Jt-55296)*1024+je-56320+65536:Jt}function Zc(at){return Object.keys(at).reduce(function(wt,Nt){var Jt=at[Nt],je=!!Jt.icon;return je?wt[Jt.iconName]=Jt.icon:wt[Nt]=Jt,wt},{})}function ne(at,wt){var Nt=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},Jt=Nt.skipHooks,je=Jt===void 0?!1:Jt,Et=Zc(wt);typeof ua.hooks.addPack=="function"&&!je?ua.hooks.addPack(at,Zc(wt)):ua.styles[at]=a(a({},ua.styles[at]||{}),Et),at==="fas"&&ne("fa",wt)}var Oe=[f(/path d="((?:(?!")[\s\S])+)".*path d="((?:(?!")[\s\S])+)"/,{d1:1,d2:2}),f(/path class="((?:(?!")[\s\S])+)".*d="((?:(?!")[\s\S])+)".*path class="((?:(?!")[\s\S])+)".*d="((?:(?!")[\s\S])+)"/,{cls1:1,d1:2,cls2:3,d2:4}),f(/path class="((?:(?!")[\s\S])+)".*d="((?:(?!")[\s\S])+)"/,{cls1:1,d1:2})],fe,De,vt,Ne=ua.styles,gn=ua.shims,gt=(fe={},b(fe,Je,Object.values(k1[Je])),b(fe,Gr,Object.values(k1[Gr])),fe),v1=null,br={},Ri={},m2={},Zr={},Gi={},ba=(De={},b(De,Je,Object.keys(j1[Je])),b(De,Gr,Object.keys(j1[Gr])),De);function pa(at){return~$t.indexOf(at)}function Ma(at,wt){var Nt=wt.split("-"),Jt=Nt[0],je=Nt.slice(1).join("-");return Jt===at&&je!==""&&!pa(je)?je:null}var k2=function(){var wt=function(Et){return tc(Ne,function(It,sn,Ln){return It[Ln]=tc(sn,Et,{}),It},{})};br=wt(function(je,Et,It){if(Et[3]&&(je[Et[3]]=It),Et[2]){var sn=Et[2].filter(function(Ln){return typeof Ln=="number"});sn.forEach(function(Ln){je[Ln.toString(16)]=It})}return je}),Ri=wt(function(je,Et,It){if(je[It]=It,Et[2]){var sn=Et[2].filter(function(Ln){return typeof Ln=="string"});sn.forEach(function(Ln){je[Ln]=It})}return je}),Gi=wt(function(je,Et,It){var sn=Et[2];return je[It]=It,sn.forEach(function(Ln){je[Ln]=It}),je});var Nt="far"in Ne||Dt.autoFetchSvg,Jt=tc(gn,function(je,Et){var It=Et[0],sn=Et[1],Ln=Et[2];return sn==="far"&&!Nt&&(sn="fas"),typeof It=="string"&&(je.names[It]={prefix:sn,iconName:Ln}),typeof It=="number"&&(je.unicodes[It.toString(16)]={prefix:sn,iconName:Ln}),je},{names:{},unicodes:{}});m2=Jt.names,Zr=Jt.unicodes,v1=Ga(Dt.styleDefault,{family:Dt.familyDefault})};En(function(at){v1=Ga(at.styleDefault,{family:Dt.familyDefault})}),k2();function as(at,wt){return(br[at]||{})[wt]}function Ai(at,wt){return(Ri[at]||{})[wt]}function P2(at,wt){return(Gi[at]||{})[wt]}function Aa(at){return m2[at]||{prefix:null,iconName:null}}function xs(at){var wt=Zr[at],Nt=as("fas",at);return wt||(Nt?{prefix:"fas",iconName:Nt}:null)||{prefix:null,iconName:null}}function Ua(){return v1}var es=function(){return{prefix:null,iconName:null,rest:[]}};function Ga(at){var wt=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},Nt=wt.family,Jt=Nt===void 0?Je:Nt,je=j1[Jt][at],Et=C1[Jt][at]||C1[Jt][je],It=at in ua.styles?at:null;return Et||It||null}var ja=(vt={},b(vt,Je,Object.keys(k1[Je])),b(vt,Gr,Object.keys(k1[Gr])),vt);function il(at){var wt,Nt=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},Jt=Nt.skipLookups,je=Jt===void 0?!1:Jt,Et=(wt={},b(wt,Je,"".concat(Dt.cssPrefix,"-").concat(Je)),b(wt,Gr,"".concat(Dt.cssPrefix,"-").concat(Gr)),wt),It=null,sn=Je;(at.includes(Et[Je])||at.some(function(V1){return ja[Je].includes(V1)}))&&(sn=Je),(at.includes(Et[Gr])||at.some(function(V1){return ja[Gr].includes(V1)}))&&(sn=Gr);var Ln=at.reduce(function(V1,Y1){var Lr=Ma(Dt.cssPrefix,Y1);if(Ne[Y1]?(Y1=gt[sn].includes(Y1)?Kn[sn][Y1]:Y1,It=Y1,V1.prefix=Y1):ba[sn].indexOf(Y1)>-1?(It=Y1,V1.prefix=Ga(Y1,{family:sn})):Lr?V1.iconName=Lr:Y1!==Dt.replacementClass&&Y1!==Et[Je]&&Y1!==Et[Gr]&&V1.rest.push(Y1),!je&&V1.prefix&&V1.iconName){var Vr=It==="fa"?Aa(V1.iconName):{},S2=P2(V1.prefix,V1.iconName);Vr.prefix&&(It=null),V1.iconName=Vr.iconName||S2||V1.iconName,V1.prefix=Vr.prefix||V1.prefix,V1.prefix==="far"&&!Ne.far&&Ne.fas&&!Dt.autoFetchSvg&&(V1.prefix="fas")}return V1},es());return(at.includes("fa-brands")||at.includes("fab"))&&(Ln.prefix="fab"),(at.includes("fa-duotone")||at.includes("fad"))&&(Ln.prefix="fad"),!Ln.prefix&&sn===Gr&&(Ne.fass||Dt.autoFetchSvg)&&(Ln.prefix="fass",Ln.iconName=P2(Ln.prefix,Ln.iconName)||Ln.iconName),(Ln.prefix==="fa"||It==="fa")&&(Ln.prefix=Ua()||"fas"),Ln}var R0=function(){function at(){h(this,at),this.definitions={}}return _(at,[{key:"add",value:function(){for(var Nt=this,Jt=arguments.length,je=new Array(Jt),Et=0;Et0&&Y1.forEach(function(Lr){typeof Lr=="string"&&(Nt[sn][Lr]=V1)}),Nt[sn][Ln]=V1}),Nt}}]),at}(),o0=[],Sl={},x4={},O8=Object.keys(x4);function Gc(at,wt){var Nt=wt.mixoutsTo;return o0=at,Sl={},Object.keys(x4).forEach(function(Jt){O8.indexOf(Jt)===-1&&delete x4[Jt]}),o0.forEach(function(Jt){var je=Jt.mixout?Jt.mixout():{};if(Object.keys(je).forEach(function(It){typeof je[It]=="function"&&(Nt[It]=je[It]),o(je[It])==="object"&&Object.keys(je[It]).forEach(function(sn){Nt[It]||(Nt[It]={}),Nt[It][sn]=je[It][sn]})}),Jt.hooks){var Et=Jt.hooks();Object.keys(Et).forEach(function(It){Sl[It]||(Sl[It]=[]),Sl[It].push(Et[It])})}Jt.provides&&Jt.provides(x4)}),Nt}function f3(at,wt){for(var Nt=arguments.length,Jt=new Array(Nt>2?Nt-2:0),je=2;je1?wt-1:0),Jt=1;Jt0&&arguments[0]!==void 0?arguments[0]:{};return Ge?(Ql("beforeI2svg",wt),h3("pseudoElements2svg",wt),h3("i2svg",wt)):Promise.reject("Operation requires a DOM of some kind.")},watch:function(){var wt=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},Nt=wt.autoReplaceSvgRoot;Dt.autoReplaceSvg===!1&&(Dt.autoReplaceSvg=!0),Dt.observeMutations=!0,Fc(function(){al({autoReplaceSvgRoot:Nt}),Ql("watch",wt)})}},N8={icon:function(wt){if(wt===null)return null;if(o(wt)==="object"&&wt.prefix&&wt.iconName)return{prefix:wt.prefix,iconName:P2(wt.prefix,wt.iconName)||wt.iconName};if(Array.isArray(wt)&&wt.length===2){var Nt=wt[1].indexOf("fa-")===0?wt[1].slice(3):wt[1],Jt=Ga(wt[0]);return{prefix:Jt,iconName:P2(Jt,Nt)||Nt}}if(typeof wt=="string"&&(wt.indexOf("".concat(Dt.cssPrefix,"-"))>-1||wt.match(Mn))){var je=il(wt.split(" "),{skipLookups:!0});return{prefix:je.prefix||Ua(),iconName:P2(je.prefix,je.iconName)||je.iconName}}if(typeof wt=="string"){var Et=Ua();return{prefix:Et,iconName:P2(Et,wt)||wt}}}},Zl={noAuto:Ef,config:Dt,dom:c6,parse:N8,library:o6,findIconDefinition:C0,toHtml:zo},al=function(){var wt=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},Nt=wt.autoReplaceSvgRoot,Jt=Nt===void 0?Ve:Nt;(Object.keys(ua.styles).length>0||Dt.autoFetchSvg)&&Ge&&Dt.autoReplaceSvg&&Zl.dom.i2svg({node:Jt})};function $5(at){ve&&(me.FontAwesome||(me.FontAwesome=Zl),Fc(function(){al(),Ql("bootstrap")})),ua.hooks=a(a({},ua.hooks),{},{addPack:function(Nt,Jt){ua.styles[Nt]=a(a({},ua.styles[Nt]||{}),Jt),k2(),al()},addPacks:function(Nt){Nt.forEach(function(Jt){var je=A(Jt,2),Et=je[0],It=je[1];ua.styles[Et]=a(a({},ua.styles[Et]||{}),It)}),k2(),al()},addShims:function(Nt){var Jt;(Jt=ua.shims).push.apply(Jt,L(Nt)),k2(),al()}})}function vu(at,wt){return Object.defineProperty(at,"abstract",{get:wt}),Object.defineProperty(at,"html",{get:function(){return at.abstract.map(function(Jt){return zo(Jt)})}}),Object.defineProperty(at,"node",{get:function(){if(Ge){var Jt=Ve.createElement("div");return Jt.innerHTML=at.html,Jt.children}}}),at}function c5(at){var wt=at.children,Nt=at.main,Jt=at.mask,je=at.attributes,Et=at.styles,It=at.transform;if(hi(It)&&Nt.found&&!Jt.found){var sn=Nt.width,Ln=Nt.height,V1={x:sn/Ln/2,y:.5};je.style=r2(a(a({},Et),{},{"transform-origin":"".concat(V1.x+It.x/16,"em ").concat(V1.y+It.y/16,"em")}))}return[{tag:"svg",attributes:je,children:wt}]}function hd(at){var wt=at.prefix,Nt=at.iconName,Jt=at.children,je=at.attributes,Et=at.symbol,It=Et===!0?"".concat(wt,"-").concat(Dt.cssPrefix,"-").concat(Nt):Et;return[{tag:"svg",attributes:{style:"display: none;"},children:[{tag:"symbol",attributes:a(a({},je),{},{id:It}),children:Jt}]}]}function E2(at){var wt=at.icons,Nt=wt.main,Jt=wt.mask,je=at.prefix,Et=at.iconName,It=at.transform,sn=at.symbol,Ln=at.title,V1=at.maskId,Y1=at.titleId,Lr=at.extra,Vr=at.watchable,S2=Vr===void 0?!1:Vr,C2=Jt.found?Jt:Nt,H2=C2.width,oa=C2.height,O2=je==="fak",ts=[Dt.replacementClass,Et?"".concat(Dt.cssPrefix,"-").concat(Et):""].filter(function(xf){return Lr.classes.indexOf(xf)===-1}).filter(function(xf){return xf!==""||!!xf}).concat(Lr.classes).join(" "),Ao={children:[],attributes:a(a({},Lr.attributes),{},{"data-prefix":je,"data-icon":Et,class:ts,role:Lr.attributes.role||"img",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 ".concat(H2," ").concat(oa)})},Yc=O2&&!~Lr.classes.indexOf("fa-fw")?{width:"".concat(H2/oa*16*.0625,"em")}:{};S2&&(Ao.attributes[Kt]=""),Ln&&(Ao.children.push({tag:"title",attributes:{id:Ao.attributes["aria-labelledby"]||"title-".concat(Y1||$n())},children:[Ln]}),delete Ao.attributes.title);var Jc=a(a({},Ao),{},{prefix:je,iconName:Et,main:Nt,mask:Jt,maskId:V1,transform:It,symbol:sn,styles:a(a({},Yc),Lr.styles)}),cl=Jt.found&&Nt.found?h3("generateAbstractMask",Jc)||{children:[],attributes:{}}:h3("generateAbstractIcon",Jc)||{children:[],attributes:{}},k3=cl.children,j3=cl.attributes;return Jc.children=k3,Jc.attributes=j3,sn?hd(Jc):c5(Jc)}function f1(at){var wt=at.content,Nt=at.width,Jt=at.height,je=at.transform,Et=at.title,It=at.extra,sn=at.watchable,Ln=sn===void 0?!1:sn,V1=a(a(a({},It.attributes),Et?{title:Et}:{}),{},{class:It.classes.join(" ")});Ln&&(V1[Kt]="");var Y1=a({},It.styles);hi(je)&&(Y1.transform=Qi({transform:je,startCentered:!0,width:Nt,height:Jt}),Y1["-webkit-transform"]=Y1.transform);var Lr=r2(Y1);Lr.length>0&&(V1.style=Lr);var Vr=[];return Vr.push({tag:"span",attributes:V1,children:[wt]}),Et&&Vr.push({tag:"span",attributes:{class:"sr-only"},children:[Et]}),Vr}function ni(at){var wt=at.content,Nt=at.title,Jt=at.extra,je=a(a(a({},Jt.attributes),Nt?{title:Nt}:{}),{},{class:Jt.classes.join(" ")}),Et=r2(Jt.styles);Et.length>0&&(je.style=Et);var It=[];return It.push({tag:"span",attributes:je,children:[wt]}),Nt&&It.push({tag:"span",attributes:{class:"sr-only"},children:[Nt]}),It}var Ki=ua.styles;function Ls(at){var wt=at[0],Nt=at[1],Jt=at.slice(4),je=A(Jt,1),Et=je[0],It=null;return Array.isArray(Et)?It={tag:"g",attributes:{class:"".concat(Dt.cssPrefix,"-").concat(Ui.GROUP)},children:[{tag:"path",attributes:{class:"".concat(Dt.cssPrefix,"-").concat(Ui.SECONDARY),fill:"currentColor",d:Et[0]}},{tag:"path",attributes:{class:"".concat(Dt.cssPrefix,"-").concat(Ui.PRIMARY),fill:"currentColor",d:Et[1]}}]}:It={tag:"path",attributes:{fill:"currentColor",d:Et}},{found:!0,width:wt,height:Nt,icon:It}}var D0={found:!1,width:512,height:512};function Mo(at,wt){!m1&&!Dt.showMissingIcons&&at&&console.error('Icon with name "'.concat(at,'" and prefix "').concat(wt,'" is missing.'))}function z0(at,wt){var Nt=wt;return wt==="fa"&&Dt.styleDefault!==null&&(wt=Ua()),new Promise(function(Jt,je){var Et={found:!1,width:512,height:512,icon:h3("missingIconAbstract")||{}};if(Nt==="fa"){var It=Aa(at)||{};at=It.iconName||at,wt=It.prefix||wt}if(at&&wt&&Ki[wt]&&Ki[wt][at]){var sn=Ki[wt][at];return Jt(Ls(sn))}Mo(at,wt),Jt(a(a({},D0),{},{icon:Dt.showMissingIcons&&at?h3("missingIconAbstract")||{}:{}}))})}var I8=function(){},c0=Dt.measurePerformance&&ut&&ut.mark&&ut.measure?ut:{mark:I8,measure:I8},j='FA "6.5.1"',te=function(wt){return c0.mark("".concat(j," ").concat(wt," begins")),function(){return be(wt)}},be=function(wt){c0.mark("".concat(j," ").concat(wt," ends")),c0.measure("".concat(j," ").concat(wt),"".concat(j," ").concat(wt," begins"),"".concat(j," ").concat(wt," ends"))},Ie={begin:te,end:be},nt=function(){};function rt(at){var wt=at.getAttribute?at.getAttribute(Kt):null;return typeof wt=="string"}function _t(at){var wt=at.getAttribute?at.getAttribute(yt):null,Nt=at.getAttribute?at.getAttribute(tt):null;return wt&&Nt}function xn(at){return at&&at.classList&&at.classList.contains&&at.classList.contains(Dt.replacementClass)}function _n(){if(Dt.autoReplaceSvg===!0)return Jr.replace;var at=Jr[Dt.autoReplaceSvg];return at||Jr.replace}function l1(at){return Ve.createElementNS("http://www.w3.org/2000/svg",at)}function sr(at){return Ve.createElement(at)}function Tr(at){var wt=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},Nt=wt.ceFn,Jt=Nt===void 0?at.tag==="svg"?l1:sr:Nt;if(typeof at=="string")return Ve.createTextNode(at);var je=Jt(at.tag);Object.keys(at.attributes||[]).forEach(function(It){je.setAttribute(It,at.attributes[It])});var Et=at.children||[];return Et.forEach(function(It){je.appendChild(Tr(It,{ceFn:Jt}))}),je}function N1(at){var wt=" ".concat(at.outerHTML," ");return wt="".concat(wt,"Font Awesome fontawesome.com "),wt}var Jr={replace:function(wt){var Nt=wt[0];if(Nt.parentNode)if(wt[1].forEach(function(je){Nt.parentNode.insertBefore(Tr(je),Nt)}),Nt.getAttribute(Kt)===null&&Dt.keepOriginalSource){var Jt=Ve.createComment(N1(Nt));Nt.parentNode.replaceChild(Jt,Nt)}else Nt.remove()},nest:function(wt){var Nt=wt[0],Jt=wt[1];if(~J1(Nt).indexOf(Dt.replacementClass))return Jr.replace(wt);var je=new RegExp("".concat(Dt.cssPrefix,"-.*"));if(delete Jt[0].attributes.id,Jt[0].attributes.class){var Et=Jt[0].attributes.class.split(" ").reduce(function(sn,Ln){return Ln===Dt.replacementClass||Ln.match(je)?sn.toSvg.push(Ln):sn.toNode.push(Ln),sn},{toNode:[],toSvg:[]});Jt[0].attributes.class=Et.toSvg.join(" "),Et.toNode.length===0?Nt.removeAttribute("class"):Nt.setAttribute("class",Et.toNode.join(" "))}var It=Jt.map(function(sn){return zo(sn)}).join(` `);Nt.setAttribute(Kt,""),Nt.innerHTML=It}};function ma(at){at()}function qs(at,wt){var Nt=typeof wt=="function"?wt:nt;if(at.length===0)Nt();else{var Jt=ma;Dt.mutateApproach===Ut&&(Jt=me.requestAnimationFrame||ma),Jt(function(){var je=_n(),Et=Ie.begin("mutate");at.map(je),Et(),Nt()})}}var La=!1;function jc(){La=!0}function P0(){La=!1}var Yo=null;function sl(at){if(se&&Dt.observeMutations){var wt=at.treeCallback,Nt=wt===void 0?nt:wt,Jt=at.nodeCallback,je=Jt===void 0?nt:Jt,Et=at.pseudoElementsCallback,It=Et===void 0?nt:Et,sn=at.observeMutationsRoot,Ln=sn===void 0?Ve:sn;Yo=new se(function(V1){if(!La){var Y1=Ua();_1(V1).forEach(function(Lr){if(Lr.type==="childList"&&Lr.addedNodes.length>0&&!rt(Lr.addedNodes[0])&&(Dt.searchPseudoElements&&It(Lr.target),Nt(Lr.target)),Lr.type==="attributes"&&Lr.target.parentNode&&Dt.searchPseudoElements&&It(Lr.target.parentNode),Lr.type==="attributes"&&rt(Lr.target)&&~pi.indexOf(Lr.attributeName))if(Lr.attributeName==="class"&&_t(Lr.target)){var Vr=il(J1(Lr.target)),S2=Vr.prefix,C2=Vr.iconName;Lr.target.setAttribute(yt,S2||Y1),C2&&Lr.target.setAttribute(tt,C2)}else xn(Lr.target)&&je(Lr.target)})}}),Ge&&Yo.observe(Ln,{childList:!0,attributes:!0,characterData:!0,subtree:!0})}}function Xs(){Yo&&Yo.disconnect()}function F6(at){var wt=at.getAttribute("style"),Nt=[];return wt&&(Nt=wt.split(";").reduce(function(Jt,je){var Et=je.split(":"),It=Et[0],sn=Et.slice(1);return It&&sn.length>0&&(Jt[It]=sn.join(":").trim()),Jt},{})),Nt}function Ia(at){var wt=at.getAttribute("data-prefix"),Nt=at.getAttribute("data-icon"),Jt=at.innerText!==void 0?at.innerText.trim():"",je=il(J1(at));return je.prefix||(je.prefix=Ua()),wt&&Nt&&(je.prefix=wt,je.iconName=Nt),je.iconName&&je.prefix||(je.prefix&&Jt.length>0&&(je.iconName=Ai(je.prefix,at.innerText)||as(je.prefix,Uc(at.innerText))),!je.iconName&&Dt.autoFetchSvg&&at.firstChild&&at.firstChild.nodeType===Node.TEXT_NODE&&(je.iconName=at.firstChild.data)),je}function l0(at){var wt=_1(at.attributes).reduce(function(je,Et){return je.name!=="class"&&je.name!=="style"&&(je[Et.name]=Et.value),je},{}),Nt=at.getAttribute("title"),Jt=at.getAttribute("data-fa-title-id");return Dt.autoA11y&&(Nt?wt["aria-labelledby"]="".concat(Dt.replacementClass,"-title-").concat(Jt||$n()):(wt["aria-hidden"]="true",wt.focusable="false")),wt}function R8(){return{iconName:null,title:null,titleId:null,prefix:null,transform:ot,symbol:!1,mask:{iconName:null,prefix:null,rest:[]},maskId:null,extra:{classes:[],styles:{},attributes:{}}}}function dd(at){var wt=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{styleParser:!0},Nt=Ia(at),Jt=Nt.iconName,je=Nt.prefix,Et=Nt.rest,It=l0(at),sn=f3("parseNodeAttributes",{},at),Ln=wt.styleParser?F6(at):[];return a({iconName:Jt,title:at.getAttribute("title"),titleId:at.getAttribute("data-fa-title-id"),prefix:je,transform:ot,mask:{iconName:null,prefix:null,rest:[]},maskId:null,symbol:!1,extra:{classes:Et,styles:Ln,attributes:It}},sn)}var Cl=ua.styles;function wf(at){var wt=Dt.autoReplaceSvg==="nest"?dd(at,{styleParser:!1}):dd(at);return~wt.extra.classes.indexOf(qn)?h3("generateLayersText",at,wt):h3("generateSvgReplacementMutation",at,wt)}var q0=new Set;yn.map(function(at){q0.add("fa-".concat(at))}),Object.keys(j1[Je]).map(q0.add.bind(q0)),Object.keys(j1[Gr]).map(q0.add.bind(q0)),q0=L(q0);function l6(at){var wt=arguments.length>1&&arguments[1]!==void 0?arguments[1]:null;if(!Ge)return Promise.resolve();var Nt=Ve.documentElement.classList,Jt=function(Lr){return Nt.add("".concat(st,"-").concat(Lr))},je=function(Lr){return Nt.remove("".concat(st,"-").concat(Lr))},Et=Dt.autoFetchSvg?q0:yn.map(function(Y1){return"fa-".concat(Y1)}).concat(Object.keys(Cl));Et.includes("fa")||Et.push("fa");var It=[".".concat(qn,":not([").concat(Kt,"])")].concat(Et.map(function(Y1){return".".concat(Y1,":not([").concat(Kt,"])")})).join(", ");if(It.length===0)return Promise.resolve();var sn=[];try{sn=_1(at.querySelectorAll(It))}catch{}if(sn.length>0)Jt("pending"),je("complete");else return Promise.resolve();var Ln=Ie.begin("onTree"),V1=sn.reduce(function(Y1,Lr){try{var Vr=wf(Lr);Vr&&Y1.push(Vr)}catch(S2){m1||S2.name==="MissingIcon"&&console.error(S2)}return Y1},[]);return new Promise(function(Y1,Lr){Promise.all(V1).then(function(Vr){qs(Vr,function(){Jt("active"),Jt("complete"),je("pending"),typeof wt=="function"&&wt(),Ln(),Y1()})}).catch(function(Vr){Ln(),Lr(Vr)})})}function l5(at){var wt=arguments.length>1&&arguments[1]!==void 0?arguments[1]:null;wf(at).then(function(Nt){Nt&&qs([Nt],wt)})}function Jl(at){return function(wt){var Nt=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},Jt=(wt||{}).icon?wt:C0(wt||{}),je=Nt.mask;return je&&(je=(je||{}).icon?je:C0(je||{})),at(Jt,a(a({},Nt),{},{mask:je}))}}var W5=function(wt){var Nt=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},Jt=Nt.transform,je=Jt===void 0?ot:Jt,Et=Nt.symbol,It=Et===void 0?!1:Et,sn=Nt.mask,Ln=sn===void 0?null:sn,V1=Nt.maskId,Y1=V1===void 0?null:V1,Lr=Nt.title,Vr=Lr===void 0?null:Lr,S2=Nt.titleId,C2=S2===void 0?null:S2,H2=Nt.classes,oa=H2===void 0?[]:H2,O2=Nt.attributes,ts=O2===void 0?{}:O2,Ao=Nt.styles,Yc=Ao===void 0?{}:Ao;if(wt){var Jc=wt.prefix,cl=wt.iconName,k3=wt.icon;return vu(a({type:"icon"},wt),function(){return Ql("beforeDOMElementCreation",{iconDefinition:wt,params:Nt}),Dt.autoA11y&&(Vr?ts["aria-labelledby"]="".concat(Dt.replacementClass,"-title-").concat(C2||$n()):(ts["aria-hidden"]="true",ts.focusable="false")),E2({icons:{main:Ls(k3),mask:Ln?Ls(Ln.icon):{found:!1,width:null,height:null,icon:{}}},prefix:Jc,iconName:cl,transform:a(a({},ot),je),symbol:It,title:Vr,maskId:Y1,titleId:C2,extra:{attributes:ts,styles:Yc,classes:oa}})})}},bu={mixout:function(){return{icon:Jl(W5)}},hooks:function(){return{mutationObserverCallbacks:function(Nt){return Nt.treeCallback=l6,Nt.nodeCallback=l5,Nt}}},provides:function(wt){wt.i2svg=function(Nt){var Jt=Nt.node,je=Jt===void 0?Ve:Jt,Et=Nt.callback,It=Et===void 0?function(){}:Et;return l6(je,It)},wt.generateSvgReplacementMutation=function(Nt,Jt){var je=Jt.iconName,Et=Jt.title,It=Jt.titleId,sn=Jt.prefix,Ln=Jt.transform,V1=Jt.symbol,Y1=Jt.mask,Lr=Jt.maskId,Vr=Jt.extra;return new Promise(function(S2,C2){Promise.all([z0(je,sn),Y1.iconName?z0(Y1.iconName,Y1.prefix):Promise.resolve({found:!1,width:512,height:512,icon:{}})]).then(function(H2){var oa=A(H2,2),O2=oa[0],ts=oa[1];S2([Nt,E2({icons:{main:O2,mask:ts},prefix:sn,iconName:je,transform:Ln,symbol:V1,maskId:Lr,title:Et,titleId:It,extra:Vr,watchable:!0})])}).catch(C2)})},wt.generateAbstractIcon=function(Nt){var Jt=Nt.children,je=Nt.attributes,Et=Nt.main,It=Nt.transform,sn=Nt.styles,Ln=r2(sn);Ln.length>0&&(je.style=Ln);var V1;return hi(It)&&(V1=h3("generateAbstractTransformGrouping",{main:Et,transform:It,containerWidth:Et.width,iconWidth:Et.width})),Jt.push(V1||Et.icon),{children:Jt,attributes:je}}}},ol={mixout:function(){return{layer:function(Nt){var Jt=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},je=Jt.classes,Et=je===void 0?[]:je;return vu({type:"layer"},function(){Ql("beforeDOMElementCreation",{assembler:Nt,params:Jt});var It=[];return Nt(function(sn){Array.isArray(sn)?sn.map(function(Ln){It=It.concat(Ln.abstract)}):It=It.concat(sn.abstract)}),[{tag:"span",attributes:{class:["".concat(Dt.cssPrefix,"-layers")].concat(L(Et)).join(" ")},children:It}]})}}}},Pm={mixout:function(){return{counter:function(Nt){var Jt=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},je=Jt.title,Et=je===void 0?null:je,It=Jt.classes,sn=It===void 0?[]:It,Ln=Jt.attributes,V1=Ln===void 0?{}:Ln,Y1=Jt.styles,Lr=Y1===void 0?{}:Y1;return vu({type:"counter",content:Nt},function(){return Ql("beforeDOMElementCreation",{content:Nt,params:Jt}),ni({content:Nt.toString(),title:Et,extra:{attributes:V1,styles:Lr,classes:["".concat(Dt.cssPrefix,"-layers-counter")].concat(L(sn))}})})}}}},pd={mixout:function(){return{text:function(Nt){var Jt=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},je=Jt.transform,Et=je===void 0?ot:je,It=Jt.title,sn=It===void 0?null:It,Ln=Jt.classes,V1=Ln===void 0?[]:Ln,Y1=Jt.attributes,Lr=Y1===void 0?{}:Y1,Vr=Jt.styles,S2=Vr===void 0?{}:Vr;return vu({type:"text",content:Nt},function(){return Ql("beforeDOMElementCreation",{content:Nt,params:Jt}),f1({content:Nt,transform:a(a({},ot),Et),title:sn,extra:{attributes:Lr,styles:S2,classes:["".concat(Dt.cssPrefix,"-layers-text")].concat(L(V1))}})})}}},provides:function(wt){wt.generateLayersText=function(Nt,Jt){var je=Jt.title,Et=Jt.transform,It=Jt.extra,sn=null,Ln=null;if(bt){var V1=parseInt(getComputedStyle(Nt).fontSize,10),Y1=Nt.getBoundingClientRect();sn=Y1.width/V1,Ln=Y1.height/V1}return Dt.autoA11y&&!je&&(It.attributes["aria-hidden"]="true"),Promise.resolve([Nt,f1({content:Nt.innerHTML,width:sn,height:Ln,transform:Et,title:je,extra:It,watchable:!0})])}}},U6=new RegExp('"',"ug"),qo=[1105920,1112319];function N7(at){var wt=at.replace(U6,""),Nt=s0(wt,0),Jt=Nt>=qo[0]&&Nt<=qo[1],je=wt.length===2?wt[0]===wt[1]:!1;return{value:Uc(je?wt[0]:wt),isSecondary:Jt||je}}function u6(at,wt){var Nt="".concat(ct).concat(wt.replace(":","-"));return new Promise(function(Jt,je){if(at.getAttribute(Nt)!==null)return Jt();var Et=_1(at.children),It=Et.filter(function(k3){return k3.getAttribute(un)===wt})[0],sn=me.getComputedStyle(at,wt),Ln=sn.getPropertyValue("font-family").match(w1),V1=sn.getPropertyValue("font-weight"),Y1=sn.getPropertyValue("content");if(It&&!Ln)return at.removeChild(It),Jt();if(Ln&&Y1!=="none"&&Y1!==""){var Lr=sn.getPropertyValue("content"),Vr=~["Sharp"].indexOf(Ln[2])?Gr:Je,S2=~["Solid","Regular","Light","Thin","Duotone","Brands","Kit"].indexOf(Ln[2])?C1[Vr][Ln[2].toLowerCase()]:O1[Vr][V1],C2=N7(Lr),H2=C2.value,oa=C2.isSecondary,O2=Ln[0].startsWith("FontAwesome"),ts=as(S2,H2),Ao=ts;if(O2){var Yc=xs(H2);Yc.iconName&&Yc.prefix&&(ts=Yc.iconName,S2=Yc.prefix)}if(ts&&!oa&&(!It||It.getAttribute(yt)!==S2||It.getAttribute(tt)!==Ao)){at.setAttribute(Nt,Ao),It&&at.removeChild(It);var Jc=R8(),cl=Jc.extra;cl.attributes[un]=wt,z0(ts,S2).then(function(k3){var j3=E2(a(a({},Jc),{},{icons:{main:k3,mask:es()},prefix:S2,iconName:Ao,extra:cl,watchable:!0})),xf=Ve.createElementNS("http://www.w3.org/2000/svg","svg");wt==="::before"?at.insertBefore(xf,at.firstChild):at.appendChild(xf),xf.outerHTML=j3.map(function(kS){return zo(kS)}).join(` -`),at.removeAttribute(Nt),Jt()}).catch(je)}else Jt()}else Jt()})}function Sf(at){return Promise.all([u6(at,"::before"),u6(at,"::after")])}function L3(at){return at.parentNode!==document.head&&!~lt.indexOf(at.tagName.toUpperCase())&&!at.getAttribute(un)&&(!at.parentNode||at.parentNode.tagName!=="svg")}function e4(at){if(Ge)return new Promise(function(wt,Nt){var Jt=_1(at.querySelectorAll("*")).filter(L3).map(Sf),je=Ie.begin("searchPseudoElements");jc(),Promise.all(Jt).then(function(){je(),P0(),wt()}).catch(function(){je(),P0(),Nt()})})}var Cf={hooks:function(){return{mutationObserverCallbacks:function(Nt){return Nt.pseudoElementsCallback=e4,Nt}}},provides:function(wt){wt.pseudoElements2svg=function(Nt){var Jt=Nt.node,je=Jt===void 0?Ve:Jt;Dt.searchPseudoElements&&e4(je)}}},M4=!1,Tf={mixout:function(){return{dom:{unwatch:function(){jc(),M4=!0}}}},hooks:function(){return{bootstrap:function(){sl(f3("mutationObserverCallbacks",{}))},noAuto:function(){Xs()},watch:function(Nt){var Jt=Nt.observeMutationsRoot;M4?P0():sl(f3("mutationObserverCallbacks",{observeMutationsRoot:Jt}))}}}},u5=function(wt){var Nt={size:16,x:0,y:0,flipX:!1,flipY:!1,rotate:0};return wt.toLowerCase().split(" ").reduce(function(Jt,je){var Et=je.toLowerCase().split("-"),It=Et[0],sn=Et.slice(1).join("-");if(It&&sn==="h")return Jt.flipX=!0,Jt;if(It&&sn==="v")return Jt.flipY=!0,Jt;if(sn=parseFloat(sn),isNaN(sn))return Jt;switch(It){case"grow":Jt.size=Jt.size+sn;break;case"shrink":Jt.size=Jt.size-sn;break;case"left":Jt.x=Jt.x-sn;break;case"right":Jt.x=Jt.x+sn;break;case"up":Jt.y=Jt.y-sn;break;case"down":Jt.y=Jt.y+sn;break;case"rotate":Jt.rotate=Jt.rotate+sn;break}return Jt},Nt)},f6={mixout:function(){return{parse:{transform:function(Nt){return u5(Nt)}}}},hooks:function(){return{parseNodeAttributes:function(Nt,Jt){var je=Jt.getAttribute("data-fa-transform");return je&&(Nt.transform=u5(je)),Nt}}},provides:function(wt){wt.generateAbstractTransformGrouping=function(Nt){var Jt=Nt.main,je=Nt.transform,Et=Nt.containerWidth,It=Nt.iconWidth,sn={transform:"translate(".concat(Et/2," 256)")},Ln="translate(".concat(je.x*32,", ").concat(je.y*32,") "),V1="scale(".concat(je.size/16*(je.flipX?-1:1),", ").concat(je.size/16*(je.flipY?-1:1),") "),Y1="rotate(".concat(je.rotate," 0 0)"),Lr={transform:"".concat(Ln," ").concat(V1," ").concat(Y1)},Vr={transform:"translate(".concat(It/2*-1," -256)")},S2={outer:sn,inner:Lr,path:Vr};return{tag:"g",attributes:a({},S2.outer),children:[{tag:"g",attributes:a({},S2.inner),children:[{tag:Jt.icon.tag,children:Jt.icon.children,attributes:a(a({},Jt.icon.attributes),S2.path)}]}]}}}},A4={x:0,y:0,width:"100%",height:"100%"};function D8(at){var wt=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return at.attributes&&(at.attributes.fill||wt)&&(at.attributes.fill="black"),at}function G6(at){return at.tag==="g"?at.children:[at]}var z8={hooks:function(){return{parseNodeAttributes:function(Nt,Jt){var je=Jt.getAttribute("data-fa-mask"),Et=je?il(je.split(" ").map(function(It){return It.trim()})):es();return Et.prefix||(Et.prefix=Ua()),Nt.mask=Et,Nt.maskId=Jt.getAttribute("data-fa-mask-id"),Nt}}},provides:function(wt){wt.generateAbstractMask=function(Nt){var Jt=Nt.children,je=Nt.attributes,Et=Nt.main,It=Nt.mask,sn=Nt.maskId,Ln=Nt.transform,V1=Et.width,Y1=Et.icon,Lr=It.width,Vr=It.icon,S2=di({transform:Ln,containerWidth:Lr,iconWidth:V1}),C2={tag:"rect",attributes:a(a({},A4),{},{fill:"white"})},H2=Y1.children?{children:Y1.children.map(D8)}:{},oa={tag:"g",attributes:a({},S2.inner),children:[D8(a({tag:Y1.tag,attributes:a(a({},Y1.attributes),S2.path)},H2))]},O2={tag:"g",attributes:a({},S2.outer),children:[oa]},ts="mask-".concat(sn||$n()),Ao="clip-".concat(sn||$n()),Yc={tag:"mask",attributes:a(a({},A4),{},{id:ts,maskUnits:"userSpaceOnUse",maskContentUnits:"userSpaceOnUse"}),children:[C2,O2]},Jc={tag:"defs",children:[{tag:"clipPath",attributes:{id:Ao},children:G6(Vr)},Yc]};return Jt.push(Jc,{tag:"rect",attributes:a({fill:"currentColor","clip-path":"url(#".concat(Ao,")"),mask:"url(#".concat(ts,")")},A4)}),{children:Jt,attributes:je}}}},Zv={provides:function(wt){var Nt=!1;me.matchMedia&&(Nt=me.matchMedia("(prefers-reduced-motion: reduce)").matches),wt.missingIconAbstract=function(){var Jt=[],je={fill:"currentColor"},Et={attributeType:"XML",repeatCount:"indefinite",dur:"2s"};Jt.push({tag:"path",attributes:a(a({},je),{},{d:"M156.5,447.7l-12.6,29.5c-18.7-9.5-35.9-21.2-51.5-34.9l22.7-22.7C127.6,430.5,141.5,440,156.5,447.7z M40.6,272H8.5 c1.4,21.2,5.4,41.7,11.7,61.1L50,321.2C45.1,305.5,41.8,289,40.6,272z M40.6,240c1.4-18.8,5.2-37,11.1-54.1l-29.5-12.6 C14.7,194.3,10,216.7,8.5,240H40.6z M64.3,156.5c7.8-14.9,17.2-28.8,28.1-41.5L69.7,92.3c-13.7,15.6-25.5,32.8-34.9,51.5 L64.3,156.5z M397,419.6c-13.9,12-29.4,22.3-46.1,30.4l11.9,29.8c20.7-9.9,39.8-22.6,56.9-37.6L397,419.6z M115,92.4 c13.9-12,29.4-22.3,46.1-30.4l-11.9-29.8c-20.7,9.9-39.8,22.6-56.8,37.6L115,92.4z M447.7,355.5c-7.8,14.9-17.2,28.8-28.1,41.5 l22.7,22.7c13.7-15.6,25.5-32.9,34.9-51.5L447.7,355.5z M471.4,272c-1.4,18.8-5.2,37-11.1,54.1l29.5,12.6 c7.5-21.1,12.2-43.5,13.6-66.8H471.4z M321.2,462c-15.7,5-32.2,8.2-49.2,9.4v32.1c21.2-1.4,41.7-5.4,61.1-11.7L321.2,462z M240,471.4c-18.8-1.4-37-5.2-54.1-11.1l-12.6,29.5c21.1,7.5,43.5,12.2,66.8,13.6V471.4z M462,190.8c5,15.7,8.2,32.2,9.4,49.2h32.1 c-1.4-21.2-5.4-41.7-11.7-61.1L462,190.8z M92.4,397c-12-13.9-22.3-29.4-30.4-46.1l-29.8,11.9c9.9,20.7,22.6,39.8,37.6,56.9 L92.4,397z M272,40.6c18.8,1.4,36.9,5.2,54.1,11.1l12.6-29.5C317.7,14.7,295.3,10,272,8.5V40.6z M190.8,50 c15.7-5,32.2-8.2,49.2-9.4V8.5c-21.2,1.4-41.7,5.4-61.1,11.7L190.8,50z M442.3,92.3L419.6,115c12,13.9,22.3,29.4,30.5,46.1 l29.8-11.9C470,128.5,457.3,109.4,442.3,92.3z M397,92.4l22.7-22.7c-15.6-13.7-32.8-25.5-51.5-34.9l-12.6,29.5 C370.4,72.1,384.4,81.5,397,92.4z"})});var It=a(a({},Et),{},{attributeName:"opacity"}),sn={tag:"circle",attributes:a(a({},je),{},{cx:"256",cy:"364",r:"28"}),children:[]};return Nt||sn.children.push({tag:"animate",attributes:a(a({},Et),{},{attributeName:"r",values:"28;14;28;28;14;28;"})},{tag:"animate",attributes:a(a({},It),{},{values:"1;0;1;1;0;1;"})}),Jt.push(sn),Jt.push({tag:"path",attributes:a(a({},je),{},{opacity:"1",d:"M263.7,312h-16c-6.6,0-12-5.4-12-12c0-71,77.4-63.9,77.4-107.8c0-20-17.8-40.2-57.4-40.2c-29.1,0-44.3,9.6-59.2,28.7 c-3.9,5-11.1,6-16.2,2.4l-13.1-9.2c-5.6-3.9-6.9-11.8-2.6-17.2c21.2-27.2,46.4-44.7,91.2-44.7c52.3,0,97.4,29.8,97.4,80.2 c0,67.6-77.4,63.5-77.4,107.8C275.7,306.6,270.3,312,263.7,312z"}),children:Nt?[]:[{tag:"animate",attributes:a(a({},It),{},{values:"1;0;0;0;0;1;"})}]}),Nt||Jt.push({tag:"path",attributes:a(a({},je),{},{opacity:"0",d:"M232.5,134.5l7,168c0.3,6.4,5.6,11.5,12,11.5h9c6.4,0,11.7-5.1,12-11.5l7-168c0.3-6.8-5.2-12.5-12-12.5h-23 C237.7,122,232.2,127.7,232.5,134.5z"}),children:[{tag:"animate",attributes:a(a({},It),{},{values:"0;0;1;1;0;0;"})}]}),{tag:"g",attributes:{class:"missing"},children:Jt}}}},P8={hooks:function(){return{parseNodeAttributes:function(Nt,Jt){var je=Jt.getAttribute("data-fa-symbol"),Et=je===null?!1:je===""?!0:je;return Nt.symbol=Et,Nt}}}},G3=[Ea,bu,ol,Pm,pd,Cf,Tf,f6,z8,Zv,P8];Gc(G3,{mixoutsTo:Zl}),an($5)})();var F$t=Ks(mvt());eV();H();le.env.FEATURE_VIDEOPLAYER==="1"&&Promise.resolve().then(()=>Ks(Evt()));le.env.FEATURE_TOC==="1"&&Promise.resolve().then(()=>(Svt(),xvn));le.env.FEATURE_DARKMODE==="1"&&Promise.resolve().then(()=>Ks(Tvt()));le.env.FEATURE_FLOWCHART==="1"&&Promise.resolve().then(()=>Ks(HPt()));le.env.FEATURE_SYNTAXHIGHLIGHT==="1"&&Promise.resolve().then(()=>Ks(VYt()));le.env.FEATURE_MATH==="1"&&Promise.resolve().then(()=>Ks(g$t()));le.env.FEATURE_EMBEDPDF==="1"&&Promise.resolve().then(()=>(v$t(),dJn));H();H();var b$t=()=>{let r=document.getElementById("top-navbar"),a=document.getElementById("navbar-toggler"),o=document.getElementById("navbar-theme-icon-svg");if(window.scrollY>40){r?.classList.remove("transparent-navbar"),r?.classList.add("shadow"),a?.classList.remove("navbar-dark"),a?.classList.add("navbar-light"),o?.classList.remove("svg-inverted");let f=document.getElementById("main-logo");if(f){let h=f.getAttribute("src");document.getElementById("logo")?.setAttribute("src",h)}}else{r?.classList.remove("shadow"),r?.classList.add("transparent-navbar"),a?.classList.remove("navbar-light"),a?.classList.add("navbar-dark"),o?.classList.add("svg-inverted");let f=document.getElementById("inverted-logo");if(f){let h=f.getAttribute("src");document.getElementById("logo")?.setAttribute("src",h)}}};document.addEventListener("DOMContentLoaded",function(){document.getElementById("top-navbar")?.classList.contains("homepage")&&(document.addEventListener("scroll",b$t),b$t());let a=document.getElementsByClassName("navbar-collapse");Array.from(a).forEach(function(o){o.addEventListener("click",function(f){f.target.tagName==="A"&&o.classList.add("collapse")})})});H();kNe();function pJn(){let r=document.getElementById("sidebar-section");if(r!=null){if(r.classList.contains("expanded"))r.classList.remove("expanded");else{let a=document.getElementById("toc-section");a!=null&&a.classList.contains("hide")&&a.classList.remove("hide"),r.classList.add("expanded");let{isMobile:o}=NN();o&&r.classList.contains("expanded")&&(document.body.scrollTop=0,document.documentElement.scrollTop=0,document.getElementById("hero-area")!=null&&document.getElementById("hero-area").classList.toggle("hide"))}document.getElementById("content-section")!=null&&document.getElementById("content-section").classList.toggle("hide")}}window.addEventListener("DOMContentLoaded",()=>{let r=document.getElementById("sidebar-toggler");r&&r.addEventListener("click",pJn)});H();function mJn(r){let a=r.parentNode.getElementsByClassName("course");if(a==null)return;for(let f of a)(f.classList.contains("hidden-course")||f.classList.contains("toggled-hidden-course"))&&(f.classList.toggle("hidden-course"),f.classList.add("toggled-hidden-course"));let o=r.parentNode.getElementsByClassName("show-more-btn");for(let f of o)f.classList.toggle("hidden")}window.addEventListener("DOMContentLoaded",()=>{Array.from(document.getElementsByClassName("btn")).filter(a=>a!=null&&(a.id==="show-more-btn"||a.id==="show-less-btn")).forEach(a=>a.addEventListener("click",({target:o})=>mJn(o)))});H();eV();function gJn(r,a,o){let f=document.createElement("div");f.classList.add("col-lg-6","m-0","p-0"),f.appendChild(a[o].cloneNode(!0)),f.children[0].classList.add("img-type-1"),r.appendChild(f),o++;let h=document.createElement("div");h.classList.add("col-lg-3","m-0","p-0"),h.appendChild(a[o].cloneNode(!0)),h.children[0].classList.add("img-type-1"),r.appendChild(h),o++;let v=document.createElement("div");v.classList.add("col-lg-3","m-0","p-0"),v.appendChild(a[o].cloneNode(!0)),v.children[0].classList.add("img-type-2"),o++,v.appendChild(a[o].cloneNode(!0)),v.children[1].classList.add("img-type-2"),r.appendChild(v),o++}function vJn(r,a,o){let f=document.createElement("div");f.classList.add("col-lg-3","m-0","p-0"),f.appendChild(a[o].cloneNode(!0)),f.children[0].classList.add("img-type-2"),o++,f.appendChild(a[o].cloneNode(!0)),f.children[1].classList.add("img-type-2"),r.appendChild(f),o++;let h=document.createElement("div");h.classList.add("col-lg-3","m-0","p-0"),h.appendChild(a[o].cloneNode(!0)),h.children[0].classList.add("img-type-1"),r.appendChild(h),o++;let v=document.createElement("div");v.classList.add("col-lg-6","m-0","p-0"),v.appendChild(a[o].cloneNode(!0)),v.children[0].classList.add("img-type-1"),r.appendChild(v),o++}function bJn(r,a,o){console.log(o);let f=document.createElement("div");f.classList.add("col-lg-6","col-md-6","m-0","p-0"),f.appendChild(a[o].cloneNode(!0)),f.children[0].classList.add("img-type-1"),r.appendChild(f),o++;let h=document.createElement("div");h.classList.add("col-lg-3","col-md-3","m-0","p-0"),h.appendChild(a[o].cloneNode(!0)),h.children[0].classList.add("img-type-1"),r.appendChild(h),o++;let v=document.createElement("div");v.classList.add("col-lg-3","col-md-3","m-0","p-0"),v.appendChild(a[o].cloneNode(!0)),v.children[0].classList.add("img-type-1"),r.appendChild(v),o++}function _Jn(r,a,o){let f=document.createElement("div");f.classList.add("col-lg-3","col-md-3","m-0","p-0"),f.appendChild(a[o].cloneNode(!0)),f.children[0].classList.add("img-type-1"),r.appendChild(f),o++;let h=document.createElement("div");h.classList.add("col-lg-3","col-md-3","m-0","p-0"),h.appendChild(a[o].cloneNode(!0)),h.children[0].classList.add("img-type-1"),r.appendChild(h),o++;let v=document.createElement("div");v.classList.add("col-lg-6","col-md-3","m-0","p-0"),v.appendChild(a[o].cloneNode(!0)),v.children[0].classList.add("img-type-1"),r.appendChild(v),o++}function _$t(r,a,o){let f=document.createElement("div");f.classList.add("col-6","m-0","p-0"),f.appendChild(a[o].cloneNode(!0)),f.children[0].classList.add("img-type-1"),r.appendChild(f),o++;let h=document.createElement("div");h.classList.add("col-6","m-0","p-0"),h.appendChild(a[o].cloneNode(!0)),h.children[0].classList.add("img-type-1"),r.appendChild(h),o++}function JVe(r,a,o){let f=document.createElement("div");f.classList.add("col-12","m-0","p-0"),f.appendChild(a[o].cloneNode(!0)),f.children[0].classList.add("img-type-1"),r.appendChild(f),o++}function yJn(){let{isLaptop:r,isTablet:a}=NN(),o=document.getElementById("gallery");if(o==null)return;o.innerHTML="";let f=document.getElementById("achievements-holder").children,h=f.length,v=0,_=1;for(;vdocument.addEventListener(r,yJn));H();var y$t=Ks(tBe());eV();document.addEventListener("DOMContentLoaded",()=>{let r=document.getElementById("project-card-holder");r!=null&&r.children.length!==0&&new y$t.default(".filtr-projects",{layout:"sameWidth",controlsSelector:".project-filtr-control"})});i6e("github-buttons","https://buttons.github.io/buttons.js");H();var E$t=Ks(tBe());document.addEventListener("DOMContentLoaded",()=>{let r=document.getElementById("publication-card-holder");r!=null&&r.children.length!==0&&new E$t.default(".filtr-publications",{layout:"sameWidth",gridItemsSelector:".pub-filtr-item",controlsSelector:".pub-filtr-control"})});H();H();var x$t=Ks(T$t());document.addEventListener("DOMContentLoaded",function(){function r(h){let v=document.getElementsByClassName("note-card-holder")[0],_=parseInt(window.getComputedStyle(v).getPropertyValue("grid-auto-rows")),b=parseInt(window.getComputedStyle(v).getPropertyValue("grid-row-gap")),S=Math.ceil((h.querySelector(".item").getBoundingClientRect().height+b)/(_+b));h.style.gridRowEnd="span "+S}function a(){let h=document.getElementsByClassName("note-card");for(let v=0;v`Invalid value for key ${r}`,AJn=r=>`Pattern length exceeds max of ${r}.`,LJn=r=>`Missing ${r} property in key`,kJn=r=>`Property 'weight' in key '${r}' must be a positive integer`,M$t=Object.prototype.hasOwnProperty,rBe=class{constructor(a){this._keys=[],this._keyMap={};let o=0;a.forEach(f=>{let h=D$t(f);o+=h.weight,this._keys.push(h),this._keyMap[h.id]=h,o+=h.weight}),this._keys.forEach(f=>{f.weight/=o})}get(a){return this._keyMap[a]}keys(){return this._keys}toJSON(){return JSON.stringify(this._keys)}};function D$t(r){let a=null,o=null,f=null,h=1,v=null;if(Ty(r)||AS(r))f=r,a=A$t(r),o=iBe(r);else{if(!M$t.call(r,"name"))throw new Error(LJn("name"));let _=r.name;if(f=_,M$t.call(r,"weight")&&(h=r.weight,h<=0))throw new Error(kJn(_));a=A$t(_),o=iBe(_),v=r.getFn}return{path:a,id:o,weight:h,src:f,getFn:v}}function A$t(r){return AS(r)?r:r.split(".")}function iBe(r){return AS(r)?r.join("."):r}function OJn(r,a){let o=[],f=!1,h=(v,_,b)=>{if(I9(v))if(!_[b])o.push(v);else{let S=_[b],T=v[S];if(!I9(T))return;if(b===_.length-1&&(Ty(T)||N$t(T)||CJn(T)))o.push(SJn(T));else if(AS(T)){f=!0;for(let A=0,L=T.length;Ar.score===a.score?r.idx{this._keysMap[o.id]=f})}create(){this.isCreated||!this.docs.length||(this.isCreated=!0,Ty(this.docs[0])?this.docs.forEach((a,o)=>{this._addString(a,o)}):this.docs.forEach((a,o)=>{this._addObject(a,o)}),this.norm.clear())}add(a){let o=this.size();Ty(a)?this._addString(a,o):this._addObject(a,o)}removeAt(a){this.records.splice(a,1);for(let o=a,f=this.size();o{let _=h.getFn?h.getFn(a):this.getFn(a,h.path);if(I9(_)){if(AS(_)){let b=[],S=[{nestedArrIndex:-1,value:_}];for(;S.length;){let{nestedArrIndex:T,value:A}=S.pop();if(I9(A))if(Ty(A)&&!nBe(A)){let L={v:A,i:T,n:this.norm.get(A)};b.push(L)}else AS(A)&&A.forEach((L,O)=>{S.push({nestedArrIndex:O,value:L})})}f.$[v]=b}else if(Ty(_)&&!nBe(_)){let b={v:_,n:this.norm.get(_)};f.$[v]=b}}}),this.records.push(f)}toJSON(){return{keys:this.keys,records:this.records}}};function z$t(r,a,{getFn:o=io.getFn,fieldNormWeight:f=io.fieldNormWeight}={}){let h=new iJ({getFn:o,fieldNormWeight:f});return h.setKeys(r.map(D$t)),h.setSources(a),h.create(),h}function HJn(r,{getFn:a=io.getFn,fieldNormWeight:o=io.fieldNormWeight}={}){let{keys:f,records:h}=r,v=new iJ({getFn:a,fieldNormWeight:o});return v.setKeys(f),v.setIndexRecords(h),v}function Wfe(r,{errors:a=0,currentLocation:o=0,expectedLocation:f=0,distance:h=io.distance,ignoreLocation:v=io.ignoreLocation}={}){let _=a/r.length;if(v)return _;let b=Math.abs(f-o);return h?_+b/h:b?1:_}function VJn(r=[],a=io.minMatchCharLength){let o=[],f=-1,h=-1,v=0;for(let _=r.length;v<_;v+=1){let b=r[v];b&&f===-1?f=v:!b&&f!==-1&&(h=v-1,h-f+1>=a&&o.push([f,h]),f=-1)}return r[v-1]&&v-f>=a&&o.push([f,v-1]),o}var PI=32;function BJn(r,a,o,{location:f=io.location,distance:h=io.distance,threshold:v=io.threshold,findAllMatches:_=io.findAllMatches,minMatchCharLength:b=io.minMatchCharLength,includeMatches:S=io.includeMatches,ignoreLocation:T=io.ignoreLocation}={}){if(a.length>PI)throw new Error(AJn(PI));let A=a.length,L=r.length,O=Math.max(0,Math.min(f,L)),D=v,U=O,W=b>1||S,Q=W?Array(L):[],J;for(;(J=r.indexOf(a,U))>-1;){let de=Wfe(a,{currentLocation:J,expectedLocation:O,distance:h,ignoreLocation:T});if(D=Math.min(de,D),U=J+A,W){let xe=0;for(;xe=ke;se-=1){let ut=se-1,ve=o[r.charAt(ut)];if(W&&(Q[ut]=+!!ve),me[se]=(me[se+1]<<1|1)&ve,de&&(me[se]|=(Z[se+1]|Z[se])<<1|1|Z[se+1]),me[se]&ce&&(ee=Wfe(a,{errors:de,currentLocation:ut,expectedLocation:O,distance:h,ignoreLocation:T}),ee<=D)){if(D=ee,U=ut,U<=O)break;ke=Math.max(1,2*O-U)}}if(Wfe(a,{errors:de+1,currentLocation:O,expectedLocation:O,distance:h,ignoreLocation:T})>D)break;Z=me}let G={isMatch:U>=0,score:Math.max(.001,ee)};if(W){let de=VJn(Q,b);de.length?S&&(G.indices=de):G.isMatch=!1}return G}function FJn(r){let a={};for(let o=0,f=r.length;o{this.chunks.push({pattern:O,alphabet:FJn(O),startIndex:D})},L=this.pattern.length;if(L>PI){let O=0,D=L%PI,U=L-D;for(;O{let{isMatch:J,score:Z,indices:ee}=BJn(a,U,W,{location:h+Q,distance:v,threshold:_,findAllMatches:b,minMatchCharLength:S,includeMatches:f,ignoreLocation:T});J&&(O=!0),L+=Z,J&&ee&&(A=[...A,...ee])});let D={isMatch:O,score:O?L/this.chunks.length:1};return O&&f&&(D.indices=A),D}},xy=class{constructor(a){this.pattern=a}static isMultiMatch(a){return L$t(a,this.multiRegex)}static isSingleMatch(a){return L$t(a,this.singleRegex)}search(){}};function L$t(r,a){let o=r.match(a);return o?o[1]:null}var aBe=class extends xy{constructor(a){super(a)}static get type(){return"exact"}static get multiRegex(){return/^="(.*)"$/}static get singleRegex(){return/^=(.*)$/}search(a){let o=a===this.pattern;return{isMatch:o,score:o?0:1,indices:[0,this.pattern.length-1]}}},sBe=class extends xy{constructor(a){super(a)}static get type(){return"inverse-exact"}static get multiRegex(){return/^!"(.*)"$/}static get singleRegex(){return/^!(.*)$/}search(a){let f=a.indexOf(this.pattern)===-1;return{isMatch:f,score:f?0:1,indices:[0,a.length-1]}}},oBe=class extends xy{constructor(a){super(a)}static get type(){return"prefix-exact"}static get multiRegex(){return/^\^"(.*)"$/}static get singleRegex(){return/^\^(.*)$/}search(a){let o=a.startsWith(this.pattern);return{isMatch:o,score:o?0:1,indices:[0,this.pattern.length-1]}}},cBe=class extends xy{constructor(a){super(a)}static get type(){return"inverse-prefix-exact"}static get multiRegex(){return/^!\^"(.*)"$/}static get singleRegex(){return/^!\^(.*)$/}search(a){let o=!a.startsWith(this.pattern);return{isMatch:o,score:o?0:1,indices:[0,a.length-1]}}},lBe=class extends xy{constructor(a){super(a)}static get type(){return"suffix-exact"}static get multiRegex(){return/^"(.*)"\$$/}static get singleRegex(){return/^(.*)\$$/}search(a){let o=a.endsWith(this.pattern);return{isMatch:o,score:o?0:1,indices:[a.length-this.pattern.length,a.length-1]}}},uBe=class extends xy{constructor(a){super(a)}static get type(){return"inverse-suffix-exact"}static get multiRegex(){return/^!"(.*)"\$$/}static get singleRegex(){return/^!(.*)\$$/}search(a){let o=!a.endsWith(this.pattern);return{isMatch:o,score:o?0:1,indices:[0,a.length-1]}}},Xfe=class extends xy{constructor(a,{location:o=io.location,threshold:f=io.threshold,distance:h=io.distance,includeMatches:v=io.includeMatches,findAllMatches:_=io.findAllMatches,minMatchCharLength:b=io.minMatchCharLength,isCaseSensitive:S=io.isCaseSensitive,ignoreLocation:T=io.ignoreLocation}={}){super(a),this._bitapSearch=new Kfe(a,{location:o,threshold:f,distance:h,includeMatches:v,findAllMatches:_,minMatchCharLength:b,isCaseSensitive:S,ignoreLocation:T})}static get type(){return"fuzzy"}static get multiRegex(){return/^"(.*)"$/}static get singleRegex(){return/^(.*)$/}search(a){return this._bitapSearch.searchIn(a)}},Qfe=class extends xy{constructor(a){super(a)}static get type(){return"include"}static get multiRegex(){return/^'"(.*)"$/}static get singleRegex(){return/^'(.*)$/}search(a){let o=0,f,h=[],v=this.pattern.length;for(;(f=a.indexOf(this.pattern,o))>-1;)o=f+v,h.push([f,o-1]);let _=!!h.length;return{isMatch:_,score:_?0:1,indices:h}}},fBe=[aBe,Qfe,oBe,cBe,uBe,lBe,sBe,Xfe],k$t=fBe.length,UJn=/ +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,GJn="|";function jJn(r,a={}){return r.split(GJn).map(o=>{let f=o.trim().split(UJn).filter(v=>v&&!!v.trim()),h=[];for(let v=0,_=f.length;v<_;v+=1){let b=f[v],S=!1,T=-1;for(;!S&&++T!!(r[Zfe.AND]||r[Zfe.OR]),$Jn=r=>!!r[mBe.PATH],WJn=r=>!AS(r)&&I$t(r)&&!gBe(r),O$t=r=>({[Zfe.AND]:Object.keys(r).map(a=>({[a]:r[a]}))});function P$t(r,a,{auto:o=!0}={}){let f=h=>{let v=Object.keys(h),_=$Jn(h);if(!_&&v.length>1&&!gBe(h))return f(O$t(h));if(WJn(h)){let S=_?h[mBe.PATH]:v[0],T=_?h[mBe.PATTERN]:h[S];if(!Ty(T))throw new Error(MJn(S));let A={keyId:iBe(S),pattern:T};return o&&(A.searcher=pBe(T,a)),A}let b={children:[],operator:v[0]};return v.forEach(S=>{let T=h[S];AS(T)&&T.forEach(A=>{b.children.push(f(A))})}),b};return gBe(r)||(r=O$t(r)),f(r)}function KJn(r,{ignoreFieldNorm:a=io.ignoreFieldNorm}){r.forEach(o=>{let f=1;o.matches.forEach(({key:h,norm:v,score:_})=>{let b=h?h.weight:null;f*=Math.pow(_===0&&b?Number.EPSILON:_,(b||1)*(a?1:v))}),o.score=f})}function XJn(r,a){let o=r.matches;a.matches=[],I9(o)&&o.forEach(f=>{if(!I9(f.indices)||!f.indices.length)return;let{indices:h,value:v}=f,_={indices:h,value:v};f.key&&(_.key=f.key.src),f.idx>-1&&(_.refIndex=f.idx),a.matches.push(_)})}function QJn(r,a){a.score=r.score}function ZJn(r,a,{includeMatches:o=io.includeMatches,includeScore:f=io.includeScore}={}){let h=[];return o&&h.push(XJn),f&&h.push(QJn),r.map(v=>{let{idx:_}=v,b={item:a[_],refIndex:_};return h.length&&h.forEach(S=>{S(v,b)}),b})}var LS=class{constructor(a,o={},f){this.options={...io,...o},this.options.useExtendedSearch,this._keyStore=new rBe(this.options.keys),this.setCollection(a,f)}setCollection(a,o){if(this._docs=a,o&&!(o instanceof iJ))throw new Error(xJn);this._myIndex=o||z$t(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}add(a){I9(a)&&(this._docs.push(a),this._myIndex.add(a))}remove(a=()=>!1){let o=[];for(let f=0,h=this._docs.length;f-1&&(S=S.slice(0,o)),ZJn(S,this._docs,{includeMatches:f,includeScore:h})}_searchStringList(a){let o=pBe(a,this.options),{records:f}=this._myIndex,h=[];return f.forEach(({v,i:_,n:b})=>{if(!I9(v))return;let{isMatch:S,score:T,indices:A}=o.searchIn(v);S&&h.push({item:v,idx:_,matches:[{score:T,value:v,norm:b,indices:A}]})}),h}_searchLogical(a){let o=P$t(a,this.options),f=(b,S,T)=>{if(!b.children){let{keyId:L,searcher:O}=b,D=this._findMatches({key:this._keyStore.get(L),value:this._myIndex.getValueForItemAtKeyId(S,L),searcher:O});return D&&D.length?[{idx:T,item:S,matches:D}]:[]}let A=[];for(let L=0,O=b.children.length;L{if(I9(b)){let T=f(o,b,S);T.length&&(v[S]||(v[S]={idx:S,item:b,matches:[]},_.push(v[S])),T.forEach(({matches:A})=>{v[S].matches.push(...A)}))}}),_}_searchObjectList(a){let o=pBe(a,this.options),{keys:f,records:h}=this._myIndex,v=[];return h.forEach(({$:_,i:b})=>{if(!I9(_))return;let S=[];f.forEach((T,A)=>{S.push(...this._findMatches({key:T,value:_[A],searcher:o}))}),S.length&&v.push({idx:b,item:_,matches:S})}),v}_findMatches({key:a,value:o,searcher:f}){if(!I9(o))return[];let h=[];if(AS(o))o.forEach(({v,i:_,n:b})=>{if(!I9(v))return;let{isMatch:S,score:T,indices:A}=f.searchIn(v);S&&h.push({score:T,key:a,value:v,idx:_,norm:b,indices:A})});else{let{v,n:_}=o,{isMatch:b,score:S,indices:T}=f.searchIn(v);b&&h.push({score:S,key:a,value:v,norm:_,indices:T})}return h}};LS.version="6.6.2";LS.createIndex=z$t;LS.parseIndex=HJn;LS.config=io;LS.parseQuery=P$t;qJn(hBe);var V$t=Ks(H$t());window.addEventListener("DOMContentLoaded",()=>{let a={shouldSort:!0,includeMatches:!0,threshold:0,tokenize:!0,location:0,distance:100,maxPatternLength:32,minMatchCharLength:1,keys:[{name:"title",weight:.8},{name:"hero",weight:.7},{name:"summary",weight:.6},{name:"date",weight:.5},{name:"contents",weight:.5},{name:"tags",weight:.3},{name:"categories",weight:.3}]},o=v("keyword");if(o)document.getElementById("search-box").value=o,f(o);else{let b=document.createElement("p");b.textContent="Please enter a word or phrase above",document.getElementById("search-results")?.append(b)}function f(b){let S=window.location.href.split("/search/")[0]+"/index.json";fetch(S).then(T=>T.json()).then(function(T){let A=T,O=new LS(A,a).search(b);if(document.getElementById("search-box").value=b,O.length>0)h(O);else{let D=document.createElement("p");D.textContent="No matches found",document.getElementById("search-results")?.append(D)}})}function h(b){b.forEach(function(S,T){let A=S.item.contents,L="",O=[];a.tokenize?O.push(o):S.matches.forEach(function(Q){if(Q.key==="tags"||Q.key==="categories")O.push(Q.value);else if(Q.key==="contents"){let J=Q.indices[0][0]-60>0?Q.indices[0][0]-60:0,Z=Q.indices[0][1]+60{function r(h){h.innerHTML=`${h.innerHTML}`}let a=document.getElementById("post-content");if(a!=null){let h=["h1","h2","h3","h4","h5","h6"];for(let v=0;v300?f.classList.add("show"):f.classList.remove("show")}),f.addEventListener("click",function(h){h.preventDefault(),window.scrollTo({top:0,behavior:"smooth"})}))});H();H();var JJn=({strings:r=["Put your strings here...","and Enjoy!"],typeSpeed:a=100,backSpeed:o=50,backDelay:f=500,startDelay:h=500,cursorChar:v="|",placeholder:_=!1,showCursor:b=!0,disableBackTyping:S=!1,onFinished:T=function(){},loop:A=!0})=>({strings:r,typeSpeed:a,backSpeed:o,cursorChar:v,backDelay:f,placeholder:_,startDelay:h,showCursor:b,loop:A,disableBackTyping:S,onFinished:T}),B$t=(r,a)=>{let o=0,f,h,v=(O,D)=>{o===f&&D.loop&&(o=0),setTimeout(()=>{_(O[o],D)},D.startDelay)},_=(O,D)=>{let U=0,W=O.length,Q=setInterval(()=>{if(D.placeholder?r.placeholder+=O[U]:r.textContent+=O[U],++U===W)return b(Q,D)},D.typeSpeed)},b=(O,D)=>{if(clearInterval(O),D.disableBackTyping&&o===f-1||!D.loop&&o===f-1)return D.onFinished();setTimeout(()=>S(D),D.backDelay)},S=O=>{let D=O.placeholder?r.placeholder:r.textContent,U=D.length,W=setInterval(()=>{if(O.placeholder?r.placeholder=r.placeholder.substr(0,--U):r.textContent=D.substr(0,--U),U===0)return T(W,O)},O.backSpeed)},T=(O,D)=>{clearInterval(O),++o,v(h,D)},A=(O,D)=>{let U=document.createElement("span");U.classList.add("ityped-cursor"),U.textContent="|",U.textContent=D.cursorChar,O.insertAdjacentElement("afterend",U)};return(O=>{let D=JJn(O||{}),U=D.strings;h=U,f=U.length,typeof r=="string"&&(r=document.querySelector(r)),D.showCursor&&A(r,D),v(U,D)})(a)};document.addEventListener("DOMContentLoaded",()=>{let r=document.getElementById("typing-carousel-data")?.children;if(r==null||r.length===0)return;let a=Array.from(r).map(o=>o.textContent);B$t("#ityped",{strings:a,startDelay:200,loop:!0})});F$t.default.replace();})(); +`),at.removeAttribute(Nt),Jt()}).catch(je)}else Jt()}else Jt()})}function Sf(at){return Promise.all([u6(at,"::before"),u6(at,"::after")])}function L3(at){return at.parentNode!==document.head&&!~lt.indexOf(at.tagName.toUpperCase())&&!at.getAttribute(un)&&(!at.parentNode||at.parentNode.tagName!=="svg")}function e4(at){if(Ge)return new Promise(function(wt,Nt){var Jt=_1(at.querySelectorAll("*")).filter(L3).map(Sf),je=Ie.begin("searchPseudoElements");jc(),Promise.all(Jt).then(function(){je(),P0(),wt()}).catch(function(){je(),P0(),Nt()})})}var Cf={hooks:function(){return{mutationObserverCallbacks:function(Nt){return Nt.pseudoElementsCallback=e4,Nt}}},provides:function(wt){wt.pseudoElements2svg=function(Nt){var Jt=Nt.node,je=Jt===void 0?Ve:Jt;Dt.searchPseudoElements&&e4(je)}}},M4=!1,Tf={mixout:function(){return{dom:{unwatch:function(){jc(),M4=!0}}}},hooks:function(){return{bootstrap:function(){sl(f3("mutationObserverCallbacks",{}))},noAuto:function(){Xs()},watch:function(Nt){var Jt=Nt.observeMutationsRoot;M4?P0():sl(f3("mutationObserverCallbacks",{observeMutationsRoot:Jt}))}}}},u5=function(wt){var Nt={size:16,x:0,y:0,flipX:!1,flipY:!1,rotate:0};return wt.toLowerCase().split(" ").reduce(function(Jt,je){var Et=je.toLowerCase().split("-"),It=Et[0],sn=Et.slice(1).join("-");if(It&&sn==="h")return Jt.flipX=!0,Jt;if(It&&sn==="v")return Jt.flipY=!0,Jt;if(sn=parseFloat(sn),isNaN(sn))return Jt;switch(It){case"grow":Jt.size=Jt.size+sn;break;case"shrink":Jt.size=Jt.size-sn;break;case"left":Jt.x=Jt.x-sn;break;case"right":Jt.x=Jt.x+sn;break;case"up":Jt.y=Jt.y-sn;break;case"down":Jt.y=Jt.y+sn;break;case"rotate":Jt.rotate=Jt.rotate+sn;break}return Jt},Nt)},f6={mixout:function(){return{parse:{transform:function(Nt){return u5(Nt)}}}},hooks:function(){return{parseNodeAttributes:function(Nt,Jt){var je=Jt.getAttribute("data-fa-transform");return je&&(Nt.transform=u5(je)),Nt}}},provides:function(wt){wt.generateAbstractTransformGrouping=function(Nt){var Jt=Nt.main,je=Nt.transform,Et=Nt.containerWidth,It=Nt.iconWidth,sn={transform:"translate(".concat(Et/2," 256)")},Ln="translate(".concat(je.x*32,", ").concat(je.y*32,") "),V1="scale(".concat(je.size/16*(je.flipX?-1:1),", ").concat(je.size/16*(je.flipY?-1:1),") "),Y1="rotate(".concat(je.rotate," 0 0)"),Lr={transform:"".concat(Ln," ").concat(V1," ").concat(Y1)},Vr={transform:"translate(".concat(It/2*-1," -256)")},S2={outer:sn,inner:Lr,path:Vr};return{tag:"g",attributes:a({},S2.outer),children:[{tag:"g",attributes:a({},S2.inner),children:[{tag:Jt.icon.tag,children:Jt.icon.children,attributes:a(a({},Jt.icon.attributes),S2.path)}]}]}}}},A4={x:0,y:0,width:"100%",height:"100%"};function D8(at){var wt=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return at.attributes&&(at.attributes.fill||wt)&&(at.attributes.fill="black"),at}function G6(at){return at.tag==="g"?at.children:[at]}var z8={hooks:function(){return{parseNodeAttributes:function(Nt,Jt){var je=Jt.getAttribute("data-fa-mask"),Et=je?il(je.split(" ").map(function(It){return It.trim()})):es();return Et.prefix||(Et.prefix=Ua()),Nt.mask=Et,Nt.maskId=Jt.getAttribute("data-fa-mask-id"),Nt}}},provides:function(wt){wt.generateAbstractMask=function(Nt){var Jt=Nt.children,je=Nt.attributes,Et=Nt.main,It=Nt.mask,sn=Nt.maskId,Ln=Nt.transform,V1=Et.width,Y1=Et.icon,Lr=It.width,Vr=It.icon,S2=di({transform:Ln,containerWidth:Lr,iconWidth:V1}),C2={tag:"rect",attributes:a(a({},A4),{},{fill:"white"})},H2=Y1.children?{children:Y1.children.map(D8)}:{},oa={tag:"g",attributes:a({},S2.inner),children:[D8(a({tag:Y1.tag,attributes:a(a({},Y1.attributes),S2.path)},H2))]},O2={tag:"g",attributes:a({},S2.outer),children:[oa]},ts="mask-".concat(sn||$n()),Ao="clip-".concat(sn||$n()),Yc={tag:"mask",attributes:a(a({},A4),{},{id:ts,maskUnits:"userSpaceOnUse",maskContentUnits:"userSpaceOnUse"}),children:[C2,O2]},Jc={tag:"defs",children:[{tag:"clipPath",attributes:{id:Ao},children:G6(Vr)},Yc]};return Jt.push(Jc,{tag:"rect",attributes:a({fill:"currentColor","clip-path":"url(#".concat(Ao,")"),mask:"url(#".concat(ts,")")},A4)}),{children:Jt,attributes:je}}}},Zv={provides:function(wt){var Nt=!1;me.matchMedia&&(Nt=me.matchMedia("(prefers-reduced-motion: reduce)").matches),wt.missingIconAbstract=function(){var Jt=[],je={fill:"currentColor"},Et={attributeType:"XML",repeatCount:"indefinite",dur:"2s"};Jt.push({tag:"path",attributes:a(a({},je),{},{d:"M156.5,447.7l-12.6,29.5c-18.7-9.5-35.9-21.2-51.5-34.9l22.7-22.7C127.6,430.5,141.5,440,156.5,447.7z M40.6,272H8.5 c1.4,21.2,5.4,41.7,11.7,61.1L50,321.2C45.1,305.5,41.8,289,40.6,272z M40.6,240c1.4-18.8,5.2-37,11.1-54.1l-29.5-12.6 C14.7,194.3,10,216.7,8.5,240H40.6z M64.3,156.5c7.8-14.9,17.2-28.8,28.1-41.5L69.7,92.3c-13.7,15.6-25.5,32.8-34.9,51.5 L64.3,156.5z M397,419.6c-13.9,12-29.4,22.3-46.1,30.4l11.9,29.8c20.7-9.9,39.8-22.6,56.9-37.6L397,419.6z M115,92.4 c13.9-12,29.4-22.3,46.1-30.4l-11.9-29.8c-20.7,9.9-39.8,22.6-56.8,37.6L115,92.4z M447.7,355.5c-7.8,14.9-17.2,28.8-28.1,41.5 l22.7,22.7c13.7-15.6,25.5-32.9,34.9-51.5L447.7,355.5z M471.4,272c-1.4,18.8-5.2,37-11.1,54.1l29.5,12.6 c7.5-21.1,12.2-43.5,13.6-66.8H471.4z M321.2,462c-15.7,5-32.2,8.2-49.2,9.4v32.1c21.2-1.4,41.7-5.4,61.1-11.7L321.2,462z M240,471.4c-18.8-1.4-37-5.2-54.1-11.1l-12.6,29.5c21.1,7.5,43.5,12.2,66.8,13.6V471.4z M462,190.8c5,15.7,8.2,32.2,9.4,49.2h32.1 c-1.4-21.2-5.4-41.7-11.7-61.1L462,190.8z M92.4,397c-12-13.9-22.3-29.4-30.4-46.1l-29.8,11.9c9.9,20.7,22.6,39.8,37.6,56.9 L92.4,397z M272,40.6c18.8,1.4,36.9,5.2,54.1,11.1l12.6-29.5C317.7,14.7,295.3,10,272,8.5V40.6z M190.8,50 c15.7-5,32.2-8.2,49.2-9.4V8.5c-21.2,1.4-41.7,5.4-61.1,11.7L190.8,50z M442.3,92.3L419.6,115c12,13.9,22.3,29.4,30.5,46.1 l29.8-11.9C470,128.5,457.3,109.4,442.3,92.3z M397,92.4l22.7-22.7c-15.6-13.7-32.8-25.5-51.5-34.9l-12.6,29.5 C370.4,72.1,384.4,81.5,397,92.4z"})});var It=a(a({},Et),{},{attributeName:"opacity"}),sn={tag:"circle",attributes:a(a({},je),{},{cx:"256",cy:"364",r:"28"}),children:[]};return Nt||sn.children.push({tag:"animate",attributes:a(a({},Et),{},{attributeName:"r",values:"28;14;28;28;14;28;"})},{tag:"animate",attributes:a(a({},It),{},{values:"1;0;1;1;0;1;"})}),Jt.push(sn),Jt.push({tag:"path",attributes:a(a({},je),{},{opacity:"1",d:"M263.7,312h-16c-6.6,0-12-5.4-12-12c0-71,77.4-63.9,77.4-107.8c0-20-17.8-40.2-57.4-40.2c-29.1,0-44.3,9.6-59.2,28.7 c-3.9,5-11.1,6-16.2,2.4l-13.1-9.2c-5.6-3.9-6.9-11.8-2.6-17.2c21.2-27.2,46.4-44.7,91.2-44.7c52.3,0,97.4,29.8,97.4,80.2 c0,67.6-77.4,63.5-77.4,107.8C275.7,306.6,270.3,312,263.7,312z"}),children:Nt?[]:[{tag:"animate",attributes:a(a({},It),{},{values:"1;0;0;0;0;1;"})}]}),Nt||Jt.push({tag:"path",attributes:a(a({},je),{},{opacity:"0",d:"M232.5,134.5l7,168c0.3,6.4,5.6,11.5,12,11.5h9c6.4,0,11.7-5.1,12-11.5l7-168c0.3-6.8-5.2-12.5-12-12.5h-23 C237.7,122,232.2,127.7,232.5,134.5z"}),children:[{tag:"animate",attributes:a(a({},It),{},{values:"0;0;1;1;0;0;"})}]}),{tag:"g",attributes:{class:"missing"},children:Jt}}}},P8={hooks:function(){return{parseNodeAttributes:function(Nt,Jt){var je=Jt.getAttribute("data-fa-symbol"),Et=je===null?!1:je===""?!0:je;return Nt.symbol=Et,Nt}}}},G3=[Ea,bu,ol,Pm,pd,Cf,Tf,f6,z8,Zv,P8];Gc(G3,{mixoutsTo:Zl}),an($5)})();var F$t=Ks(mvt());eV();H();le.env.FEATURE_VIDEOPLAYER==="1"&&Promise.resolve().then(()=>Ks(Evt()));Promise.resolve().then(()=>Svt());Promise.resolve().then(()=>Ks(Tvt()));le.env.FEATURE_FLOWCHART==="1"&&Promise.resolve().then(()=>Ks(HPt()));le.env.FEATURE_SYNTAXHIGHLIGHT==="1"&&Promise.resolve().then(()=>Ks(VYt()));le.env.FEATURE_MATH==="1"&&Promise.resolve().then(()=>Ks(g$t()));le.env.FEATURE_EMBEDPDF==="1"&&Promise.resolve().then(()=>(v$t(),dJn));H();H();var b$t=()=>{let r=document.getElementById("top-navbar"),a=document.getElementById("navbar-toggler"),o=document.getElementById("navbar-theme-icon-svg");if(window.scrollY>40){r?.classList.remove("transparent-navbar"),r?.classList.add("shadow"),a?.classList.remove("navbar-dark"),a?.classList.add("navbar-light"),o?.classList.remove("svg-inverted");let f=document.getElementById("main-logo");if(f){let h=f.getAttribute("src");document.getElementById("logo")?.setAttribute("src",h)}}else{r?.classList.remove("shadow"),r?.classList.add("transparent-navbar"),a?.classList.remove("navbar-light"),a?.classList.add("navbar-dark"),o?.classList.add("svg-inverted");let f=document.getElementById("inverted-logo");if(f){let h=f.getAttribute("src");document.getElementById("logo")?.setAttribute("src",h)}}};document.addEventListener("DOMContentLoaded",function(){document.getElementById("top-navbar")?.classList.contains("homepage")&&(document.addEventListener("scroll",b$t),b$t());let a=document.getElementsByClassName("navbar-collapse");Array.from(a).forEach(function(o){o.addEventListener("click",function(f){f.target.tagName==="A"&&o.classList.add("collapse")})})});H();kNe();function pJn(){let r=document.getElementById("sidebar-section");if(r!=null){if(r.classList.contains("expanded"))r.classList.remove("expanded");else{let a=document.getElementById("toc-section");a!=null&&a.classList.contains("hide")&&a.classList.remove("hide"),r.classList.add("expanded");let{isMobile:o}=NN();o&&r.classList.contains("expanded")&&(document.body.scrollTop=0,document.documentElement.scrollTop=0,document.getElementById("hero-area")!=null&&document.getElementById("hero-area").classList.toggle("hide"))}document.getElementById("content-section")!=null&&document.getElementById("content-section").classList.toggle("hide")}}window.addEventListener("DOMContentLoaded",()=>{let r=document.getElementById("sidebar-toggler");r&&r.addEventListener("click",pJn)});H();function mJn(r){let a=r.parentNode.getElementsByClassName("course");if(a==null)return;for(let f of a)(f.classList.contains("hidden-course")||f.classList.contains("toggled-hidden-course"))&&(f.classList.toggle("hidden-course"),f.classList.add("toggled-hidden-course"));let o=r.parentNode.getElementsByClassName("show-more-btn");for(let f of o)f.classList.toggle("hidden")}window.addEventListener("DOMContentLoaded",()=>{Array.from(document.getElementsByClassName("btn")).filter(a=>a!=null&&(a.id==="show-more-btn"||a.id==="show-less-btn")).forEach(a=>a.addEventListener("click",({target:o})=>mJn(o)))});H();eV();function gJn(r,a,o){let f=document.createElement("div");f.classList.add("col-lg-6","m-0","p-0"),f.appendChild(a[o].cloneNode(!0)),f.children[0].classList.add("img-type-1"),r.appendChild(f),o++;let h=document.createElement("div");h.classList.add("col-lg-3","m-0","p-0"),h.appendChild(a[o].cloneNode(!0)),h.children[0].classList.add("img-type-1"),r.appendChild(h),o++;let v=document.createElement("div");v.classList.add("col-lg-3","m-0","p-0"),v.appendChild(a[o].cloneNode(!0)),v.children[0].classList.add("img-type-2"),o++,v.appendChild(a[o].cloneNode(!0)),v.children[1].classList.add("img-type-2"),r.appendChild(v),o++}function vJn(r,a,o){let f=document.createElement("div");f.classList.add("col-lg-3","m-0","p-0"),f.appendChild(a[o].cloneNode(!0)),f.children[0].classList.add("img-type-2"),o++,f.appendChild(a[o].cloneNode(!0)),f.children[1].classList.add("img-type-2"),r.appendChild(f),o++;let h=document.createElement("div");h.classList.add("col-lg-3","m-0","p-0"),h.appendChild(a[o].cloneNode(!0)),h.children[0].classList.add("img-type-1"),r.appendChild(h),o++;let v=document.createElement("div");v.classList.add("col-lg-6","m-0","p-0"),v.appendChild(a[o].cloneNode(!0)),v.children[0].classList.add("img-type-1"),r.appendChild(v),o++}function bJn(r,a,o){console.log(o);let f=document.createElement("div");f.classList.add("col-lg-6","col-md-6","m-0","p-0"),f.appendChild(a[o].cloneNode(!0)),f.children[0].classList.add("img-type-1"),r.appendChild(f),o++;let h=document.createElement("div");h.classList.add("col-lg-3","col-md-3","m-0","p-0"),h.appendChild(a[o].cloneNode(!0)),h.children[0].classList.add("img-type-1"),r.appendChild(h),o++;let v=document.createElement("div");v.classList.add("col-lg-3","col-md-3","m-0","p-0"),v.appendChild(a[o].cloneNode(!0)),v.children[0].classList.add("img-type-1"),r.appendChild(v),o++}function _Jn(r,a,o){let f=document.createElement("div");f.classList.add("col-lg-3","col-md-3","m-0","p-0"),f.appendChild(a[o].cloneNode(!0)),f.children[0].classList.add("img-type-1"),r.appendChild(f),o++;let h=document.createElement("div");h.classList.add("col-lg-3","col-md-3","m-0","p-0"),h.appendChild(a[o].cloneNode(!0)),h.children[0].classList.add("img-type-1"),r.appendChild(h),o++;let v=document.createElement("div");v.classList.add("col-lg-6","col-md-3","m-0","p-0"),v.appendChild(a[o].cloneNode(!0)),v.children[0].classList.add("img-type-1"),r.appendChild(v),o++}function _$t(r,a,o){let f=document.createElement("div");f.classList.add("col-6","m-0","p-0"),f.appendChild(a[o].cloneNode(!0)),f.children[0].classList.add("img-type-1"),r.appendChild(f),o++;let h=document.createElement("div");h.classList.add("col-6","m-0","p-0"),h.appendChild(a[o].cloneNode(!0)),h.children[0].classList.add("img-type-1"),r.appendChild(h),o++}function JVe(r,a,o){let f=document.createElement("div");f.classList.add("col-12","m-0","p-0"),f.appendChild(a[o].cloneNode(!0)),f.children[0].classList.add("img-type-1"),r.appendChild(f),o++}function yJn(){let{isLaptop:r,isTablet:a}=NN(),o=document.getElementById("gallery");if(o==null)return;o.innerHTML="";let f=document.getElementById("achievements-holder").children,h=f.length,v=0,_=1;for(;vdocument.addEventListener(r,yJn));H();var y$t=Ks(tBe());eV();document.addEventListener("DOMContentLoaded",()=>{let r=document.getElementById("project-card-holder");r!=null&&r.children.length!==0&&new y$t.default(".filtr-projects",{layout:"sameWidth",controlsSelector:".project-filtr-control"})});i6e("github-buttons","https://buttons.github.io/buttons.js");H();var E$t=Ks(tBe());document.addEventListener("DOMContentLoaded",()=>{let r=document.getElementById("publication-card-holder");r!=null&&r.children.length!==0&&new E$t.default(".filtr-publications",{layout:"sameWidth",gridItemsSelector:".pub-filtr-item",controlsSelector:".pub-filtr-control"})});H();H();var x$t=Ks(T$t());document.addEventListener("DOMContentLoaded",function(){function r(h){let v=document.getElementsByClassName("note-card-holder")[0],_=parseInt(window.getComputedStyle(v).getPropertyValue("grid-auto-rows")),b=parseInt(window.getComputedStyle(v).getPropertyValue("grid-row-gap")),S=Math.ceil((h.querySelector(".item").getBoundingClientRect().height+b)/(_+b));h.style.gridRowEnd="span "+S}function a(){let h=document.getElementsByClassName("note-card");for(let v=0;v`Invalid value for key ${r}`,AJn=r=>`Pattern length exceeds max of ${r}.`,LJn=r=>`Missing ${r} property in key`,kJn=r=>`Property 'weight' in key '${r}' must be a positive integer`,M$t=Object.prototype.hasOwnProperty,rBe=class{constructor(a){this._keys=[],this._keyMap={};let o=0;a.forEach(f=>{let h=D$t(f);o+=h.weight,this._keys.push(h),this._keyMap[h.id]=h,o+=h.weight}),this._keys.forEach(f=>{f.weight/=o})}get(a){return this._keyMap[a]}keys(){return this._keys}toJSON(){return JSON.stringify(this._keys)}};function D$t(r){let a=null,o=null,f=null,h=1,v=null;if(Ty(r)||AS(r))f=r,a=A$t(r),o=iBe(r);else{if(!M$t.call(r,"name"))throw new Error(LJn("name"));let _=r.name;if(f=_,M$t.call(r,"weight")&&(h=r.weight,h<=0))throw new Error(kJn(_));a=A$t(_),o=iBe(_),v=r.getFn}return{path:a,id:o,weight:h,src:f,getFn:v}}function A$t(r){return AS(r)?r:r.split(".")}function iBe(r){return AS(r)?r.join("."):r}function OJn(r,a){let o=[],f=!1,h=(v,_,b)=>{if(I9(v))if(!_[b])o.push(v);else{let S=_[b],T=v[S];if(!I9(T))return;if(b===_.length-1&&(Ty(T)||N$t(T)||CJn(T)))o.push(SJn(T));else if(AS(T)){f=!0;for(let A=0,L=T.length;Ar.score===a.score?r.idx{this._keysMap[o.id]=f})}create(){this.isCreated||!this.docs.length||(this.isCreated=!0,Ty(this.docs[0])?this.docs.forEach((a,o)=>{this._addString(a,o)}):this.docs.forEach((a,o)=>{this._addObject(a,o)}),this.norm.clear())}add(a){let o=this.size();Ty(a)?this._addString(a,o):this._addObject(a,o)}removeAt(a){this.records.splice(a,1);for(let o=a,f=this.size();o{let _=h.getFn?h.getFn(a):this.getFn(a,h.path);if(I9(_)){if(AS(_)){let b=[],S=[{nestedArrIndex:-1,value:_}];for(;S.length;){let{nestedArrIndex:T,value:A}=S.pop();if(I9(A))if(Ty(A)&&!nBe(A)){let L={v:A,i:T,n:this.norm.get(A)};b.push(L)}else AS(A)&&A.forEach((L,O)=>{S.push({nestedArrIndex:O,value:L})})}f.$[v]=b}else if(Ty(_)&&!nBe(_)){let b={v:_,n:this.norm.get(_)};f.$[v]=b}}}),this.records.push(f)}toJSON(){return{keys:this.keys,records:this.records}}};function z$t(r,a,{getFn:o=io.getFn,fieldNormWeight:f=io.fieldNormWeight}={}){let h=new iJ({getFn:o,fieldNormWeight:f});return h.setKeys(r.map(D$t)),h.setSources(a),h.create(),h}function HJn(r,{getFn:a=io.getFn,fieldNormWeight:o=io.fieldNormWeight}={}){let{keys:f,records:h}=r,v=new iJ({getFn:a,fieldNormWeight:o});return v.setKeys(f),v.setIndexRecords(h),v}function Wfe(r,{errors:a=0,currentLocation:o=0,expectedLocation:f=0,distance:h=io.distance,ignoreLocation:v=io.ignoreLocation}={}){let _=a/r.length;if(v)return _;let b=Math.abs(f-o);return h?_+b/h:b?1:_}function VJn(r=[],a=io.minMatchCharLength){let o=[],f=-1,h=-1,v=0;for(let _=r.length;v<_;v+=1){let b=r[v];b&&f===-1?f=v:!b&&f!==-1&&(h=v-1,h-f+1>=a&&o.push([f,h]),f=-1)}return r[v-1]&&v-f>=a&&o.push([f,v-1]),o}var PI=32;function BJn(r,a,o,{location:f=io.location,distance:h=io.distance,threshold:v=io.threshold,findAllMatches:_=io.findAllMatches,minMatchCharLength:b=io.minMatchCharLength,includeMatches:S=io.includeMatches,ignoreLocation:T=io.ignoreLocation}={}){if(a.length>PI)throw new Error(AJn(PI));let A=a.length,L=r.length,O=Math.max(0,Math.min(f,L)),D=v,U=O,W=b>1||S,Q=W?Array(L):[],J;for(;(J=r.indexOf(a,U))>-1;){let de=Wfe(a,{currentLocation:J,expectedLocation:O,distance:h,ignoreLocation:T});if(D=Math.min(de,D),U=J+A,W){let xe=0;for(;xe=ke;se-=1){let ut=se-1,ve=o[r.charAt(ut)];if(W&&(Q[ut]=+!!ve),me[se]=(me[se+1]<<1|1)&ve,de&&(me[se]|=(Z[se+1]|Z[se])<<1|1|Z[se+1]),me[se]&ce&&(ee=Wfe(a,{errors:de,currentLocation:ut,expectedLocation:O,distance:h,ignoreLocation:T}),ee<=D)){if(D=ee,U=ut,U<=O)break;ke=Math.max(1,2*O-U)}}if(Wfe(a,{errors:de+1,currentLocation:O,expectedLocation:O,distance:h,ignoreLocation:T})>D)break;Z=me}let G={isMatch:U>=0,score:Math.max(.001,ee)};if(W){let de=VJn(Q,b);de.length?S&&(G.indices=de):G.isMatch=!1}return G}function FJn(r){let a={};for(let o=0,f=r.length;o{this.chunks.push({pattern:O,alphabet:FJn(O),startIndex:D})},L=this.pattern.length;if(L>PI){let O=0,D=L%PI,U=L-D;for(;O{let{isMatch:J,score:Z,indices:ee}=BJn(a,U,W,{location:h+Q,distance:v,threshold:_,findAllMatches:b,minMatchCharLength:S,includeMatches:f,ignoreLocation:T});J&&(O=!0),L+=Z,J&&ee&&(A=[...A,...ee])});let D={isMatch:O,score:O?L/this.chunks.length:1};return O&&f&&(D.indices=A),D}},xy=class{constructor(a){this.pattern=a}static isMultiMatch(a){return L$t(a,this.multiRegex)}static isSingleMatch(a){return L$t(a,this.singleRegex)}search(){}};function L$t(r,a){let o=r.match(a);return o?o[1]:null}var aBe=class extends xy{constructor(a){super(a)}static get type(){return"exact"}static get multiRegex(){return/^="(.*)"$/}static get singleRegex(){return/^=(.*)$/}search(a){let o=a===this.pattern;return{isMatch:o,score:o?0:1,indices:[0,this.pattern.length-1]}}},sBe=class extends xy{constructor(a){super(a)}static get type(){return"inverse-exact"}static get multiRegex(){return/^!"(.*)"$/}static get singleRegex(){return/^!(.*)$/}search(a){let f=a.indexOf(this.pattern)===-1;return{isMatch:f,score:f?0:1,indices:[0,a.length-1]}}},oBe=class extends xy{constructor(a){super(a)}static get type(){return"prefix-exact"}static get multiRegex(){return/^\^"(.*)"$/}static get singleRegex(){return/^\^(.*)$/}search(a){let o=a.startsWith(this.pattern);return{isMatch:o,score:o?0:1,indices:[0,this.pattern.length-1]}}},cBe=class extends xy{constructor(a){super(a)}static get type(){return"inverse-prefix-exact"}static get multiRegex(){return/^!\^"(.*)"$/}static get singleRegex(){return/^!\^(.*)$/}search(a){let o=!a.startsWith(this.pattern);return{isMatch:o,score:o?0:1,indices:[0,a.length-1]}}},lBe=class extends xy{constructor(a){super(a)}static get type(){return"suffix-exact"}static get multiRegex(){return/^"(.*)"\$$/}static get singleRegex(){return/^(.*)\$$/}search(a){let o=a.endsWith(this.pattern);return{isMatch:o,score:o?0:1,indices:[a.length-this.pattern.length,a.length-1]}}},uBe=class extends xy{constructor(a){super(a)}static get type(){return"inverse-suffix-exact"}static get multiRegex(){return/^!"(.*)"\$$/}static get singleRegex(){return/^!(.*)\$$/}search(a){let o=!a.endsWith(this.pattern);return{isMatch:o,score:o?0:1,indices:[0,a.length-1]}}},Xfe=class extends xy{constructor(a,{location:o=io.location,threshold:f=io.threshold,distance:h=io.distance,includeMatches:v=io.includeMatches,findAllMatches:_=io.findAllMatches,minMatchCharLength:b=io.minMatchCharLength,isCaseSensitive:S=io.isCaseSensitive,ignoreLocation:T=io.ignoreLocation}={}){super(a),this._bitapSearch=new Kfe(a,{location:o,threshold:f,distance:h,includeMatches:v,findAllMatches:_,minMatchCharLength:b,isCaseSensitive:S,ignoreLocation:T})}static get type(){return"fuzzy"}static get multiRegex(){return/^"(.*)"$/}static get singleRegex(){return/^(.*)$/}search(a){return this._bitapSearch.searchIn(a)}},Qfe=class extends xy{constructor(a){super(a)}static get type(){return"include"}static get multiRegex(){return/^'"(.*)"$/}static get singleRegex(){return/^'(.*)$/}search(a){let o=0,f,h=[],v=this.pattern.length;for(;(f=a.indexOf(this.pattern,o))>-1;)o=f+v,h.push([f,o-1]);let _=!!h.length;return{isMatch:_,score:_?0:1,indices:h}}},fBe=[aBe,Qfe,oBe,cBe,uBe,lBe,sBe,Xfe],k$t=fBe.length,UJn=/ +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,GJn="|";function jJn(r,a={}){return r.split(GJn).map(o=>{let f=o.trim().split(UJn).filter(v=>v&&!!v.trim()),h=[];for(let v=0,_=f.length;v<_;v+=1){let b=f[v],S=!1,T=-1;for(;!S&&++T!!(r[Zfe.AND]||r[Zfe.OR]),$Jn=r=>!!r[mBe.PATH],WJn=r=>!AS(r)&&I$t(r)&&!gBe(r),O$t=r=>({[Zfe.AND]:Object.keys(r).map(a=>({[a]:r[a]}))});function P$t(r,a,{auto:o=!0}={}){let f=h=>{let v=Object.keys(h),_=$Jn(h);if(!_&&v.length>1&&!gBe(h))return f(O$t(h));if(WJn(h)){let S=_?h[mBe.PATH]:v[0],T=_?h[mBe.PATTERN]:h[S];if(!Ty(T))throw new Error(MJn(S));let A={keyId:iBe(S),pattern:T};return o&&(A.searcher=pBe(T,a)),A}let b={children:[],operator:v[0]};return v.forEach(S=>{let T=h[S];AS(T)&&T.forEach(A=>{b.children.push(f(A))})}),b};return gBe(r)||(r=O$t(r)),f(r)}function KJn(r,{ignoreFieldNorm:a=io.ignoreFieldNorm}){r.forEach(o=>{let f=1;o.matches.forEach(({key:h,norm:v,score:_})=>{let b=h?h.weight:null;f*=Math.pow(_===0&&b?Number.EPSILON:_,(b||1)*(a?1:v))}),o.score=f})}function XJn(r,a){let o=r.matches;a.matches=[],I9(o)&&o.forEach(f=>{if(!I9(f.indices)||!f.indices.length)return;let{indices:h,value:v}=f,_={indices:h,value:v};f.key&&(_.key=f.key.src),f.idx>-1&&(_.refIndex=f.idx),a.matches.push(_)})}function QJn(r,a){a.score=r.score}function ZJn(r,a,{includeMatches:o=io.includeMatches,includeScore:f=io.includeScore}={}){let h=[];return o&&h.push(XJn),f&&h.push(QJn),r.map(v=>{let{idx:_}=v,b={item:a[_],refIndex:_};return h.length&&h.forEach(S=>{S(v,b)}),b})}var LS=class{constructor(a,o={},f){this.options={...io,...o},this.options.useExtendedSearch,this._keyStore=new rBe(this.options.keys),this.setCollection(a,f)}setCollection(a,o){if(this._docs=a,o&&!(o instanceof iJ))throw new Error(xJn);this._myIndex=o||z$t(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}add(a){I9(a)&&(this._docs.push(a),this._myIndex.add(a))}remove(a=()=>!1){let o=[];for(let f=0,h=this._docs.length;f-1&&(S=S.slice(0,o)),ZJn(S,this._docs,{includeMatches:f,includeScore:h})}_searchStringList(a){let o=pBe(a,this.options),{records:f}=this._myIndex,h=[];return f.forEach(({v,i:_,n:b})=>{if(!I9(v))return;let{isMatch:S,score:T,indices:A}=o.searchIn(v);S&&h.push({item:v,idx:_,matches:[{score:T,value:v,norm:b,indices:A}]})}),h}_searchLogical(a){let o=P$t(a,this.options),f=(b,S,T)=>{if(!b.children){let{keyId:L,searcher:O}=b,D=this._findMatches({key:this._keyStore.get(L),value:this._myIndex.getValueForItemAtKeyId(S,L),searcher:O});return D&&D.length?[{idx:T,item:S,matches:D}]:[]}let A=[];for(let L=0,O=b.children.length;L{if(I9(b)){let T=f(o,b,S);T.length&&(v[S]||(v[S]={idx:S,item:b,matches:[]},_.push(v[S])),T.forEach(({matches:A})=>{v[S].matches.push(...A)}))}}),_}_searchObjectList(a){let o=pBe(a,this.options),{keys:f,records:h}=this._myIndex,v=[];return h.forEach(({$:_,i:b})=>{if(!I9(_))return;let S=[];f.forEach((T,A)=>{S.push(...this._findMatches({key:T,value:_[A],searcher:o}))}),S.length&&v.push({idx:b,item:_,matches:S})}),v}_findMatches({key:a,value:o,searcher:f}){if(!I9(o))return[];let h=[];if(AS(o))o.forEach(({v,i:_,n:b})=>{if(!I9(v))return;let{isMatch:S,score:T,indices:A}=f.searchIn(v);S&&h.push({score:T,key:a,value:v,idx:_,norm:b,indices:A})});else{let{v,n:_}=o,{isMatch:b,score:S,indices:T}=f.searchIn(v);b&&h.push({score:S,key:a,value:v,norm:_,indices:T})}return h}};LS.version="6.6.2";LS.createIndex=z$t;LS.parseIndex=HJn;LS.config=io;LS.parseQuery=P$t;qJn(hBe);var V$t=Ks(H$t());window.addEventListener("DOMContentLoaded",()=>{let a={shouldSort:!0,includeMatches:!0,threshold:0,tokenize:!0,location:0,distance:100,maxPatternLength:32,minMatchCharLength:1,keys:[{name:"title",weight:.8},{name:"hero",weight:.7},{name:"summary",weight:.6},{name:"date",weight:.5},{name:"contents",weight:.5},{name:"tags",weight:.3},{name:"categories",weight:.3}]},o=v("keyword");if(o)document.getElementById("search-box").value=o,f(o);else{let b=document.createElement("p");b.textContent="Please enter a word or phrase above",document.getElementById("search-results")?.append(b)}function f(b){let S=window.location.href.split("/search/")[0]+"/index.json";fetch(S).then(T=>T.json()).then(function(T){let A=T,O=new LS(A,a).search(b);if(document.getElementById("search-box").value=b,O.length>0)h(O);else{let D=document.createElement("p");D.textContent="No matches found",document.getElementById("search-results")?.append(D)}})}function h(b){b.forEach(function(S,T){let A=S.item.contents,L="",O=[];a.tokenize?O.push(o):S.matches.forEach(function(Q){if(Q.key==="tags"||Q.key==="categories")O.push(Q.value);else if(Q.key==="contents"){let J=Q.indices[0][0]-60>0?Q.indices[0][0]-60:0,Z=Q.indices[0][1]+60{function r(h){h.innerHTML=`${h.innerHTML}`}let a=document.getElementById("post-content");if(a!=null){let h=["h1","h2","h3","h4","h5","h6"];for(let v=0;v300?f.classList.add("show"):f.classList.remove("show")}),f.addEventListener("click",function(h){h.preventDefault(),window.scrollTo({top:0,behavior:"smooth"})}))});H();H();var JJn=({strings:r=["Put your strings here...","and Enjoy!"],typeSpeed:a=100,backSpeed:o=50,backDelay:f=500,startDelay:h=500,cursorChar:v="|",placeholder:_=!1,showCursor:b=!0,disableBackTyping:S=!1,onFinished:T=function(){},loop:A=!0})=>({strings:r,typeSpeed:a,backSpeed:o,cursorChar:v,backDelay:f,placeholder:_,startDelay:h,showCursor:b,loop:A,disableBackTyping:S,onFinished:T}),B$t=(r,a)=>{let o=0,f,h,v=(O,D)=>{o===f&&D.loop&&(o=0),setTimeout(()=>{_(O[o],D)},D.startDelay)},_=(O,D)=>{let U=0,W=O.length,Q=setInterval(()=>{if(D.placeholder?r.placeholder+=O[U]:r.textContent+=O[U],++U===W)return b(Q,D)},D.typeSpeed)},b=(O,D)=>{if(clearInterval(O),D.disableBackTyping&&o===f-1||!D.loop&&o===f-1)return D.onFinished();setTimeout(()=>S(D),D.backDelay)},S=O=>{let D=O.placeholder?r.placeholder:r.textContent,U=D.length,W=setInterval(()=>{if(O.placeholder?r.placeholder=r.placeholder.substr(0,--U):r.textContent=D.substr(0,--U),U===0)return T(W,O)},O.backSpeed)},T=(O,D)=>{clearInterval(O),++o,v(h,D)},A=(O,D)=>{let U=document.createElement("span");U.classList.add("ityped-cursor"),U.textContent="|",U.textContent=D.cursorChar,O.insertAdjacentElement("afterend",U)};return(O=>{let D=JJn(O||{}),U=D.strings;h=U,f=U.length,typeof r=="string"&&(r=document.querySelector(r)),D.showCursor&&A(r,D),v(U,D)})(a)};document.addEventListener("DOMContentLoaded",()=>{let r=document.getElementById("typing-carousel-data")?.children;if(r==null||r.length===0)return;let a=Array.from(r).map(o=>o.textContent);B$t("#ityped",{strings:a,startDelay:200,loop:!0})});F$t.default.replace();})(); /*! Bundled license information: popper.js/dist/umd/popper.js: diff --git a/categories/aws/index.html b/categories/aws/index.html index eaf75654..4bd95bc3 100644 --- a/categories/aws/index.html +++ b/categories/aws/index.html @@ -1,12 +1,14 @@ AWS -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/categories/basic/index.html b/categories/basic/index.html index 39825051..598d4499 100644 --- a/categories/basic/index.html +++ b/categories/basic/index.html @@ -1,12 +1,14 @@ Basic -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/categories/computer-science/index.html b/categories/computer-science/index.html index da52429c..3b176ac5 100644 --- a/categories/computer-science/index.html +++ b/categories/computer-science/index.html @@ -1,12 +1,14 @@ computer-science -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/categories/ddd/index.html b/categories/ddd/index.html index 545e5621..a42b916f 100644 --- a/categories/ddd/index.html +++ b/categories/ddd/index.html @@ -1,12 +1,14 @@ ddd -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/categories/development/index.html b/categories/development/index.html index 7e39a2ee..fc2428a7 100644 --- a/categories/development/index.html +++ b/categories/development/index.html @@ -1,12 +1,14 @@ Development -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/categories/dynamodb/index.html b/categories/dynamodb/index.html index e9a9db7a..35780555 100644 --- a/categories/dynamodb/index.html +++ b/categories/dynamodb/index.html @@ -1,12 +1,14 @@ DynamoDB -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/categories/go/index.html b/categories/go/index.html index 7c7eb623..4f70750c 100644 --- a/categories/go/index.html +++ b/categories/go/index.html @@ -1,12 +1,14 @@ Go -
Hero Image
netパッケージで非推奨のTemporaryメソッドの扱いについて

はじめに こちらはKyash Advent Calendar 2022 の 13 日目の記事です。 今年の 11 月に Kyash に入社しました!サーバサイドチームのueharaです👋 今回はnet/httpパッケージの非推奨メソッドであるTemporary()について、社のメンバーから知見を共有してもらったのでその話をします。 @@ -49,4 +51,4 @@ package main import ( "fmt" "time" "github.com/uh-zz/traning/algorithm/shuffle" ) func main() { // ランダムな要素 n 個のスライス取得 input := shuffle.RandomIntList(n) inputLength := len(input) // マージソート MergeSort(&input, 0, inputLength) } // MergeSort マージソート func MergeSort(input \*[]int, left, right int) { // 要素数1つの場合は抜ける if right-left == 1 { return } // 配列を2つに分けるインデックス middle := left + (right-left)/2 // 配列左側 MergeSort(input, left, middle) // 配列右側 MergeSort(input, middle, right) var buffer []int // 左側と右側をバッファにためる(右側反転) for index := left; index < middle; index++ { buffer = append(buffer, (*input)[index]) } for index := right - 1; index >= middle; index-- { buffer = append(buffer, (*input)[index]) } // マージする scopeLeft := 0 scopeRight := len(buffer) - 1 for index := left; index < right; index++ { if buffer[scopeLeft] <= buffer[scopeRight] { // 左側採用 (*input)[index] = buffer[scopeLeft] scopeLeft++ } else { // 右側採用 (*input)[index] = buffer[scopeRight] scopeRight-- } } } これ考えたのぶっ飛んでるなあと思って Wikipedia 見てたら、考案者がフォン・ノイマンでやっぱりぶっ飛んでた(凄すぎ)

\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/categories/index.html b/categories/index.html index a23dce4b..6897d0bb 100644 --- a/categories/index.html +++ b/categories/index.html @@ -1,12 +1,14 @@ Categories -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/categories/oauth/index.html b/categories/oauth/index.html index 9c831766..199f3bdc 100644 --- a/categories/oauth/index.html +++ b/categories/oauth/index.html @@ -1,12 +1,14 @@ oauth -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/categories/oss/index.html b/categories/oss/index.html index 23079343..a45bda7c 100644 --- a/categories/oss/index.html +++ b/categories/oss/index.html @@ -1,12 +1,14 @@ oss -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/categories/poem/index.html b/categories/poem/index.html index 9aa770fd..987d5f69 100644 --- a/categories/poem/index.html +++ b/categories/poem/index.html @@ -1,12 +1,14 @@ poem -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/categories/security/index.html b/categories/security/index.html index fa22ec4a..54c0823b 100644 --- a/categories/security/index.html +++ b/categories/security/index.html @@ -1,12 +1,14 @@ security -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/categories/system-design/index.html b/categories/system-design/index.html index 9afa4263..e5b3e2a5 100644 --- a/categories/system-design/index.html +++ b/categories/system-design/index.html @@ -1,12 +1,14 @@ system-design -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/en/about/index.html b/en/about/index.html index f7756b10..cb04d4b4 100644 --- a/en/about/index.html +++ b/en/about/index.html @@ -1,13 +1,15 @@ -
Author Image

Monday, January 1, 1



\ No newline at end of file diff --git a/en/index.html b/en/index.html index e2017430..e63912eb 100644 --- a/en/index.html +++ b/en/index.html @@ -1,13 +1,15 @@ Ens -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/index.html b/index.html index bf0eff43..3621f0ea 100644 --- a/index.html +++ b/index.html @@ -1,9 +1,11 @@ small land -
Author Image

uh-zz

Reo Uehara

Software Engineer at Kyash Inc.

I am a software engineer with 6 years of working experience. Also, I am working and studying computer science as a student.

AWS Certified Solutions Architect - Associate

Experiences

1
Software Engineer
Kyash Inc.

Nov 2022 - Present, @@ -80,4 +82,4 @@ package main func readFile(path string) chan string { // ファイルを読み込み、その結果を返すFutureを返す promise := make(chan string) // readFile とは別のゴルーチンでファイルを読み出す go func() { content, err := os.

\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/notes/index.html b/notes/index.html index 43aa0ec5..cd8af1bc 100644 --- a/notes/index.html +++ b/notes/index.html @@ -1,12 +1,14 @@ Notes -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/notes/page/2/index.html b/notes/page/2/index.html index baa4360e..c3aa6f40 100644 --- a/notes/page/2/index.html +++ b/notes/page/2/index.html @@ -1,12 +1,14 @@ Notes -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/posts/category/aws/2020/06/dynamo-only-sortkey-without-partionkey/index.html b/posts/category/aws/2020/06/dynamo-only-sortkey-without-partionkey/index.html index 7751015a..7315820a 100644 --- a/posts/category/aws/2020/06/dynamo-only-sortkey-without-partionkey/index.html +++ b/posts/category/aws/2020/06/dynamo-only-sortkey-without-partionkey/index.html @@ -13,15 +13,17 @@ これの設計2を参考にしました。 全データ共通のダミー列を用意して、以下の GSI を作成します。 パーティションキーはダミー列 ソートキーに日付 これで同じ日付範囲の複数データを引っ張ってくることが可能になります。 -確かに美しいと言えないかもしれませんが、機転の効いた方法だと思いました。">
Author Image

Friday, June 5, 2020

DynamoDB のソートキーだけで絞り込みたいとき

はじめに

Dynamo のテーブルに GSI(グローバルセカンダリインデックス)を貼ってハッシュキー+ソートキーでクエリするパターンが通常の使い方かと思います。

ではソートキーを日付にしていた場合、同じ日付範囲のデータを一括で取得できる方法はありますでしょうか?

公式ドキュメントにはその辺の Tips なかったのですが、同僚から以下の記事を教えてもらいました。

DynamoDB の設計力をあげたい

これの設計2を参考にしました。

全データ共通のダミー列を用意して、以下の GSI を作成します。

  • パーティションキーはダミー列
  • ソートキーに日付

これで同じ日付範囲の複数データを引っ張ってくることが可能になります。

確かに美しいと言えないかもしれませんが、機転の効いた方法だと思いました。



\ No newline at end of file diff --git a/posts/category/aws/index.html b/posts/category/aws/index.html index 500e5b27..7c3bbc3f 100644 --- a/posts/category/aws/index.html +++ b/posts/category/aws/index.html @@ -1,12 +1,14 @@ AWS -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/posts/category/computer-science/2020/09/process-management/index.html b/posts/category/computer-science/2020/09/process-management/index.html index e3c00abd..2e400b50 100644 --- a/posts/category/computer-science/2020/09/process-management/index.html +++ b/posts/category/computer-science/2020/09/process-management/index.html @@ -43,15 +43,17 @@ Github でも fork がありますが、意味合いは同じです。既存のリポジトリを複製します。複製したリポジトリは自由に更新できますが、fork した元のリポジトリに対しては更新はできません。 プロセスの fork は元からあるプロセスを親プロセス、複製されたプロセスを子プロセスと呼びます。 子プロセスの fork 実行時の戻り値は 0 です。 -(戻り値 0 は正常終了のステータスコード)そして親プロセスの fork 実行時の戻り値は子プロセスのプロセス ID です。">
Author Image

Sunday, July 5, 2020

プロセス管理

はじめに

バックエンドエンジニアのロードマップに沿ってエンジニアとしての自己肯定感を養うシリーズです。

プロセスとは

プロセスという概念は Linux において、ファイルシステム、ストリームに並んで重要な構成要素の1つです。

プログラマが作成したソースコードはファイルに保存されます。そしてファイルの保存先はハードディスクです。

プログラムの実行時、プログラムはハードディスクからメモリへと読み込まれます。

CPU はメモリに読み込まれたプログラムを順次処理していきます。このとき、メモリに読み込まれて CPU に処理されているプログラムをプロセスといいます。

1つのプロセスを処理できるのは1つの CPU のみです。

そのため、同じプロセスしか一度に実行できなくなるといったことを避けるために、CPU はプロセスごとに処理時間を決めて次々に切り替えます。

普段使っている PC やスマホは Youtube や Line や Twitter など、複数アプリを同時に起動して使用しています。

あれは CPU が処理時間を決めて順に処理しているために実現されています。

OS のコアであるカーネルはプロセスの優先順位を考慮して、各プロセスに処理時間を割り当てます。

(この機能をスケジューラ、またはディスパッチャといいます。)

アドレス空間

プロセス1つに対して、CPU とメモリがそれぞれ1つ必要です。CPU は前述の通り、処理時間を割り当てるのに対し、メモリはプロセスごとにアドレス空間を割り当てます。

メモリにプログラムを書き込む際にはアドレスが必要です。

しかしプロセスには 0 番地から始まるメモリが必要なため、1つのプロセスしか使えなくなってしまいます。

そこでプロセスから見えるアドレス(論理アドレス)と実際のアドレス(物理アドレス)を分けてしまいます。

こうすることで、カーネルと CPU によって論理アドレス → 物理アドレスと変換された実際のアドレスに対して書き込むことができます。

1つのプロセスの論理アドレス、物理アドレスを全体としてアドレス空間といいます。

アドレス空間はプロセスごとに割り当てられるので他のプロセスにアクセスできなくなります。

プロセス API

fork(2)

自分のプロセスを複製して新しいプロセスを作ります。

Github でも fork がありますが、意味合いは同じです。既存のリポジトリを複製します。複製したリポジトリは自由に更新できますが、fork した元のリポジトリに対しては更新はできません。

プロセスの fork は元からあるプロセスを親プロセス、複製されたプロセスを子プロセスと呼びます。

子プロセスの fork 実行時の戻り値は 0 です。

(戻り値 0 は正常終了のステータスコード)そして親プロセスの fork 実行時の戻り値は子プロセスのプロセス ID です。

シェルでもps auxコマンドを使用して確認できます。

exec

プロセスを新しいプログラムで上書きします。fork したプロセスで即座に exec することで新しいプログラムを時刻したことになります。

wait(2)

fork したプロセスの終了を待ちます。

以上で、プロセスのライフサイクルは fork で子プロセスを生成し、exec で実行して wait によって、親プロセス側で終了判定するといった流れになります。

pipe(2)

シェルではパイプ「|」を使って複数のコマンドをつなぐことができます。

言い換えると、パイプはプロセスからプロセスにつながったストリームのことです。(ストリームはバイトの流れ道のイメージ)

pipe を実行すると、1つのプロセスでは、自身の書き込み用から読み込み用のファイルディスクリプタへ一方向のストリームが生成されます。

また、プロセスを fork するとストリームも複製されます。

そこで pipe を実行した後に、fork し親プロセスの読み込み側、子プロセスの書き込み側を close すると、

親プロセスの書き込み側 → 子プロセスの読み込み側への1つのストリームが生成されます。

これがシェルのパイプの原理です。

デーモンプロセス

http サーバや mysql サーバ、いわゆる常駐プロセスと呼ばれるものです。

ps auxコマンドを実行した際、TTY の項目が?になっているプロセスで、制御端末を持たないプロセスのことを言います。

サーバのようにずっと動作し続けるプロセスは、実行したユーザを持たないことで停止されることがなくなります。

(プロセスは、起動したユーザがログアウトするとプロセスも停止してしまうからです。)

余談

プロセスについての情報がなかなか探せない中、本棚に眠っていた良書を思い出して引っ張り出した甲斐がありました。

日々の業務でも触れていますが、 汎用的な知識は重要だと痛切に感じます。

備考

ふつうの Linux プログラミング 第 2 版 Linux の仕組みから学べる gcc プログラミングの王道

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/category/computer-science/2020/10/memory-management/index.html b/posts/category/computer-science/2020/10/memory-management/index.html index ced82f19..8a7bdc3f 100644 --- a/posts/category/computer-science/2020/10/memory-management/index.html +++ b/posts/category/computer-science/2020/10/memory-management/index.html @@ -55,16 +55,18 @@ brk(2) malloc や realloc が割り当てるためのメモリを探してくるものです。 物理アドレスが割り当てられていないページに物理アドレスを対応づけます。 余談 メモリはエラーでもかなりお世話になる部分なので、次回以降、実際のエラーやプログラミング言語(Go か Java)に絡めた記事を書きたいです。 -備考 ふつうの Linux プログラミング 第 2 版 Linux の仕組みから学べる gcc プログラミングの王道">
Author Image

Monday, October 5, 2020

メモリ管理

はじめに

バックエンドエンジニアのロードマップに沿ってエンジニアとしての自己肯定感を養うシリーズです。

仮想メモリ

プロセス管理でもあったように、メモリはアドレス空間ごとにプロセスを管理します。

アドレス空間は 4KB/8KB 単位のページに分割して管理されています。

ページはそれぞれ論理アドレス、物理アドレスを対応づける単位でもあります。

論理アドレスと物理アドレスは常に紐づけられているわけではなく、そのページが必要になった時点で割り当てることも可能です。

そのため、論理アドレスを実際の物理アドレスの容量より大きく確保することができます。

(実際に使えるメモリの量よりも大きなメモリを想定できるということです。)

仮装メモリとして使う仕組みには次の3つが挙げられます。

ページング

仮想メモリといえばこれ、という風に教えられるものの筆頭かと思います。

ハードディスクを物理メモリの代わりに使うといったものです。

物理メモリが不足すると、OS のコアであるカーネルは使われていないページをハードディスクに移して論理アドレスを解放します。

そしてプロセスがハードディスクに移されたページにアクセスしようとすると、カーネルがプロセスを停止し、ハードディスクのページを再度物理メモリに読み込み、論理アドレスを対応づけます。

また、プロセス全体を単位にする場合はスワッピングと呼ばれます。

メモリマップトファイル

ファイルをメモリとしてアクセスすることができるものです。

アクセスがあった瞬間に、カーネルがファイルをメモリに読み込みます。プロセスがメモリを使い終わると、論理アドレスと物理アドレスを解放して、メモリの内容をファイルに保存します。

共有メモリ

1つの物理アドレスを、複数のプロセスの論理アドレスに対応づけるものです。 アドレス空間をまたぐと危険では?!という見方もありますが、複数プロセスで処理できるため、巨大な画像データを編集するときには都合が良いみたいです。

※Go では共有メモリを使わずに Message Passing を使っています。

メモリ管理 API

malloc(3)

メモリをヒープ領域に割り当てます。プログラム実行時に決まるサイズのメモリはヒープ領域から確保します。

ヒープは「何かを積み重ねた山」のことで、その名の通り、プログラムを実行してから決定する量だけメモリを確保しておく領域なので納得です。

malloc で確保したメモリはfreeで解放しなければいけません。

calloc(3)

メモリをヒープ領域に割り当てます。malloc と異なる点は、割り当てたメモリをゼロクリアすることです。

こちらも malloc 同様、確保したメモリはfreeで解放しなければいけません。

realloc(3)

malloc で割り当てたメモリのサイズを拡大、縮小します。こちらも確保したメモリはfreeで解放しなければいけません。

free

割り当てたメモリを開放します。いったん開放したアドレスにはアクセスしてはいけません。

メモリの開放漏れを防ぐために、malloc で確保したメモリは常に free で開放されるべきです。

brk(2)

malloc や realloc が割り当てるためのメモリを探してくるものです。

物理アドレスが割り当てられていないページに物理アドレスを対応づけます。

余談

メモリはエラーでもかなりお世話になる部分なので、次回以降、実際のエラーやプログラミング言語(Go か Java)に絡めた記事を書きたいです。

備考

ふつうの Linux プログラミング 第 2 版 Linux の仕組みから学べる gcc プログラミングの王道

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/category/computer-science/2020/11/thread-and-concurrency/index.html b/posts/category/computer-science/2020/11/thread-and-concurrency/index.html index 56fc909b..322b7645 100644 --- a/posts/category/computer-science/2020/11/thread-and-concurrency/index.html +++ b/posts/category/computer-science/2020/11/thread-and-concurrency/index.html @@ -49,14 +49,16 @@ 以下のような実装です。 こちらを参考にさせていただきました。 (ほぼコメントつけただけですが) -package main import ( "fmt" "time" ) // 使い回し用のワーカー func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Println("worker", id, "started job", j) time.Sleep(time.Second) // 1秒待ち(重い処理を想定) fmt.Println("worker", id, "finished job", j) results <- j * 2 } } func main() { // タスクの数 const numJobs = 5 // こなさなければいけないタスク jobs := make(chan int, numJobs) // タスクの成果物 results := make(chan int, numJobs) for w := 1; w <= 3; w++ { // 使い回し用のワーカーだけ生成しておく(この状態ではまだタスクをもらってないのでブロック) go worker(w, jobs, results) } // タスク数だけjobsに渡す for j := 1; j <= numJobs; j++ { // チャネルへの書き込みを契機にワーカー起動 jobs <- j } // タスク数だけ格納されたらチャネルを閉じる close(jobs) for a := 1; a <= numJobs; a++ { <-results } } // 結果 worker 3 started job 1 worker 1 started job 2 worker 2 started job 3 worker 3 finished job 1 worker 3 started job 4 worker 1 finished job 2 worker 1 started job 5 worker 2 finished job 3 worker 1 finished job 5 worker 3 finished job 4 実行するとわかりますが、順番がごっちゃになって処理されているのがわかります。">
Author Image

Monday, October 5, 2020

スレッドと並行処理

はじめに

バックエンドエンジニアのロードマップに沿ってエンジニアとしての自己肯定感を養うシリーズです。

スレッド

プロセスが最低1つは持っている実行単位のことです。

こんな言い方をするのは、プロセスが複数のスレッドを管理できるからです。

実行単位という視点でプロセスとの違いは、「アドレス空間」を共有できるという点です。

尾を引くようにプロセス管理の話に繋がりますが、プロセスにはそれぞれ1つのアドレス空間が割り当てられます。

そして別のプロセスからアドレス空間へのアクセスは原則できません。(これを可能にするために共有メモリという方法を使います)

それに対して、スレッドは1つのプロセスの実行単位を分けたものですから、同じアドレス空間を共有できるというわけです。

そういうわけで、スレッドとプロセスをそれぞれ複数起動する場合は、スレッドの方がアドレス空間を1つで済ませることができるため省コストになります。

では、複数のスレッドを起動してやることは?というと並行処理です。

並行処理

これもすでに出てきている話ではあります。プロセス管理の記事で出した複数アプリを同時に起動させるという部分です。

「同時に」というのは私たちユーザがそう解釈しているだけで、アプリはカーネルが割り当てた非常に短い処理時間ごとに切り替えているのでしたよね。これが並行処理です。

スレッドでも同じように短い処理時間ごとに切り替えて「同時に」処理させることができます。

並列処理との違い

私自身、再三調べては納得 → 忘れるを繰り返していましたが、プロセス管理(3 度目)をまとめることでやっと理解できたと思います。

並行処理では処理時間ごとに切り替えると言いましたが、並列処理では CPU 1つは言わず2つで処理してしまえばいいじゃないという考え方です。

図で見ると非常にわかりやすいのですが、並行処理だとパン食べてチーズ食べてハム食べてレタス食べて、、を繰り返して食べ切る作戦なのに対して、並列処理はミックスサンドとして食べ切るようなイメージです。

そんなの絶対ミックスサンドとして処理したら無限じゃんと思われますが、並列処理にも上限があるようです。

アムダールの法則といって複数のプロセッサ(CPU のことですね)を使って並列化による高速化を行う場合、そのプログラムの中で逐次的に実行される処理部分(並列)の時間によって、高速化が制限されるというものです。

出典:wikipedia「アムダールの法則」より引用

まあ、上限があるといっても高速するのに変わりはないわけです。

今回はその中でも比較的面白い実装を見つけたのでそれを紹介します。

ワーカープール

スレッドプールとも呼ばれるものです。並行処理でたくさんのスレッドを起動して、、というのももちろん可能ですが、それには代償が伴います。

ワーカープールはそのようにいくつもスレッドを起動させるのではなく、すでに起動したスレッドを使い回そうの精神で実装される並行処理です。

以下のような実装です。

こちらを参考にさせていただきました。

(ほぼコメントつけただけですが)

package main
 
 import (
@@ -121,6 +123,6 @@
 worker 1 finished job 5
 worker 3 finished job 4
 

実行するとわかりますが、順番がごっちゃになって処理されているのがわかります。

これにより、ワーカーというスレッドごとに並行処理されているという動作を確認することができました。

余談

他にも面白そうな実装をいくつか見つけましたが、ただ羅列するだけでは萎えると思ったので気が向いたら別で紹介したいと思います。

なにげに goroutine を使用していますが、goroutine の中身の処理内容(work stealing アルゴリズム)も面白いので、後々まとめたいと思ってます。

備考

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/category/computer-science/index.html b/posts/category/computer-science/index.html index 9032251d..9a39402a 100644 --- a/posts/category/computer-science/index.html +++ b/posts/category/computer-science/index.html @@ -1,12 +1,14 @@ Computer Science -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/posts/category/development/2020/08/agile-software-development/index.html b/posts/category/development/2020/08/agile-software-development/index.html index 86e59bdb..75e98610 100644 --- a/posts/category/development/2020/08/agile-software-development/index.html +++ b/posts/category/development/2020/08/agile-software-development/index.html @@ -39,15 +39,17 @@ そのイテレーション(スプリント)でリリースする機能も複数人が関わっていたり、メンバー間での連携が必要な機能だったり。。 極めつけは1つのアプリの全機能を全メンバーが把握しているのがヨシとされるので、知らない機能は教えたり教わったりしないといけないからです。(これは私のチームだけなのかは知りませんが) まとめ 、、とすごく大変そうに見えますが(実際に大変ですが)、スクラムならではの団体戦みのある開発でまあうまく回せるんではないでしょうかというのが感想です。 -備考 表紙イラスト:Loose Drawing">
Author Image

Friday, June 5, 2020

アジャイル開発

はじめに

バックエンドエンジニアのロードマップに沿ってエンジニアとしての自己肯定感を養うシリーズです。

アジャイル開発

「アジャイル開発」っていうとなんかカッコいいしモダンっぽいというイメージをおそらく持っている人もいるでしょう。(私を含めて)

逆に「ウォーターフォール開発」はなんか古臭いし、どこぞの金融系ぷ r、、おっと誰か来たみたいなのでこの辺で。

とまあ、もてはやされたアジャイル開発ですが、フタを開けてみれば「要件定義 → 設計 → 実装 → テスト」の全工程を1つの単位として反復するという手法なのです。

反復する期間はチームやプロジェクトによってまちまちですが、1 週間〜4 週間ほどです。

ってことはですよ、V 字モデルのウォーターフォールを短いスパンで回してるだけ?、、それウォーターフォールじゃねぇか!!

、、というヤジも分からなくはありませんが、ちゃんとメリットがあります。

メリット

1. スピーディー(早い)

だってそうですよね。ウォーターフォールでは全工程を段階的に進めていくのでリリースまでに時間がかかってしまいます。

対してアジャイルでは前工程を1つのサイクルとして反復するのでリリースまでの期間が短く済みます。

2. やすい(安い ×)

しかもアジャイルは、開発サイクルが短い分、仕様変更や追加機能の対応がしやすいというのもあります。

ウォーターフォールだと、段階的に進めるので、1つの仕様変更があった場合、工程を戻すことになり、、おぉ、、考えただけでも恐ろしいですね。

3. ユーザーファースト(うまい?)

これも納得ですね。

リリースが早い分、クライアント(ユーザー)に効率よく素早く提供できる → クライアント喜ぶ → 褒められる → 嬉しい=うまい?

(これは数合わせです)

アジャイル開発の手法

手法は以下の3つです。

  • スクラム
  • エクストリームプログラミング
  • ユーザ機能駆動開発

この中で私が経験したのは、スクラムのみです。(2020/07 時点)

どのサイトでも言われている通り、この開発手法ではメンバーとのコミュニケーションが非常に重要です。

そのイテレーション(スプリント)でリリースする機能も複数人が関わっていたり、メンバー間での連携が必要な機能だったり。。

極めつけは1つのアプリの全機能を全メンバーが把握しているのがヨシとされるので、知らない機能は教えたり教わったりしないといけないからです。(これは私のチームだけなのかは知りませんが)

まとめ

、、とすごく大変そうに見えますが(実際に大変ですが)、スクラムならではの団体戦みのある開発でまあうまく回せるんではないでしょうかというのが感想です。

備考

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/category/development/2021/03/pragmatic-programmer/index.html b/posts/category/development/2021/03/pragmatic-programmer/index.html index d04e9232..2c1a5743 100644 --- a/posts/category/development/2021/03/pragmatic-programmer/index.html +++ b/posts/category/development/2021/03/pragmatic-programmer/index.html @@ -67,14 +67,16 @@ 1つのメソッドであまりにも多くのことをやろうとすると、 連結されている全ての車両に影響が及ぶように、メソッドと属性が影響を受ける 例)割引料金を算出するメソッドの中で、これらの操作を行う。 顧客の注文履歴を参照する 注文履歴から特定の注文オブジェクトを取得する 注文オブジェクトの総額を返す 総額から割引した値をオブジェクトにセットする 次のような考え方がある -照会せずに依頼する TDA(Tell, Don’t Ask)">
Author Image

Friday, March 5, 2021

達人プログラマーとは

はじめに

エンジニアとしてコードを書くようになって、もうすぐ2年というタイミングに差し掛かりました

心境の変化としては、がむしゃらに毎日のタスクを通して「動く」コードを書くことから、メンテナンスしやすいコードを意識することが多くなりました

「達人プログラマー」は、プログラマとして次のステップを踏み出そうというときにベストな一冊となっています

達人の哲学

ソフトウェアのエントロピーの話は心当たりがありすぎた

エントロピー とは、物理学の用語で「ある系における無秩序の度合い」のことで、 時間が経つたびにエントロピーは増大していく

ソフトウェアも同様に、時間が経つたびに無秩序になっていく

これを 割れ窓理論 というメカニズムで説明していたのもわかりやすかった

窓が1枚割れているのを長期間放置しておくと、それをメンテナンスする気力もなくなるマインドが 植え付けられて、最終的には建物全体が破壊されていく

ソフトウェアではこれを、悪い設計、誤った意思決定、質の悪いコードに見立てることができて、 @@ -93,6 +95,6 @@ 日々実施するアクティビティである。

テストとはバグを見つけることではない

テストの利点は、テストについて考え、テストを記述しているときにあり、 テストを実行しているときではない

→ テストを契約と見做せば重要度とモチベーションの変化になるのではないか

象を一頭食べるにはどうすれば良いか

→ 一口ずつ食べる ←大事!!

明確な目的地を心に描けてなかった場合、どのような方法論であっても 堂々巡りになってしまう可能性がある。 ←

プロジェクトを始める前に

ひとりぼっちでコーディングに取り組んではいけない

達人のプロジェクト

猫の群れを飼い慣らすことに匹敵するほど、優秀なプログラマーをまとめるのは難しい

50 人はチームとは言わずに「群れ」といった方がしっくりくる

事を成し遂げるにはまずスケジュールする

カーゴカルト的な手法は、開発においてもテストやツールにおいても危険

ユーザーが必要としたタイミングで調達すること

早めにテスト、何度もテスト、自動でテスト

まとめ

このタイミングで1周できたのは幸運でした。

折に触れてて再読したいと思います。

備考

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/category/development/index.html b/posts/category/development/index.html index c925058e..951c041d 100644 --- a/posts/category/development/index.html +++ b/posts/category/development/index.html @@ -1,12 +1,14 @@ Development -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/posts/category/go/2020/07/compare-sort-aligorithm/index.html b/posts/category/go/2020/07/compare-sort-aligorithm/index.html index ca786a86..279ecc93 100644 --- a/posts/category/go/2020/07/compare-sort-aligorithm/index.html +++ b/posts/category/go/2020/07/compare-sort-aligorithm/index.html @@ -9,14 +9,16 @@ 出典:wikipedia「マージソート」より引用 最悪の計算量が O(n log n) であるから少なくとも O(n^2)よりは速いんだろうなという印象(雑すぎるか) 以下「ソートを極める! 〜 なぜソートを学ぶのか 〜」を元に実装してみた(なるべくソースを見ないで実装を試みたがマージする箇所は折れた、、) -package main import ( "fmt" "time" "github.com/uh-zz/traning/algorithm/shuffle" ) func main() { // ランダムな要素 n 個のスライス取得 input := shuffle.RandomIntList(n) inputLength := len(input) // マージソート MergeSort(&input, 0, inputLength) } // MergeSort マージソート func MergeSort(input \*[]int, left, right int) { // 要素数1つの場合は抜ける if right-left == 1 { return } // 配列を2つに分けるインデックス middle := left + (right-left)/2 // 配列左側 MergeSort(input, left, middle) // 配列右側 MergeSort(input, middle, right) var buffer []int // 左側と右側をバッファにためる(右側反転) for index := left; index < middle; index++ { buffer = append(buffer, (*input)[index]) } for index := right - 1; index >= middle; index-- { buffer = append(buffer, (*input)[index]) } // マージする scopeLeft := 0 scopeRight := len(buffer) - 1 for index := left; index < right; index++ { if buffer[scopeLeft] <= buffer[scopeRight] { // 左側採用 (*input)[index] = buffer[scopeLeft] scopeLeft++ } else { // 右側採用 (*input)[index] = buffer[scopeRight] scopeRight-- } } } これ考えたのぶっ飛んでるなあと思って Wikipedia 見てたら、考案者がフォン・ノイマンでやっぱりぶっ飛んでた(凄すぎ)">
Author Image

Sunday, July 5, 2020

ソートアルゴリズムをGoで実装してみた

はじめに

バックエンドエンジニアのロードマップに沿ってエンジニアとしての自己肯定感を養うシリーズです。

マージソート

マージソートは、ソートのアルゴリズムで、既に整列してある複数個の列を 1 個の列にマージする際に、小さいものから先に新しい列に並べれば、新しい列も整列されている、というボトムアップの分割統治法による。大きい列を多数の列に分割し、そのそれぞれをマージする作業は並列化できる。

出典:wikipedia「マージソート」より引用

最悪の計算量が O(n log n) であるから少なくとも O(n^2)よりは速いんだろうなという印象(雑すぎるか)

以下「ソートを極める! 〜 なぜソートを学ぶのか 〜」を元に実装してみた(なるべくソースを見ないで実装を試みたがマージする箇所は折れた、、)

package main
 
 import (
@@ -115,6 +117,6 @@
 
 }
 

こっちは実装もしやすく理解するのも難しくないという印象。最終的にはどちらもソートするというのにこの差は、、と思ってしまう。

速度比較

今回はソートアルゴリズムの実装がメインだったけど、2つあるなら比較するまでがアウトプットだろうなと感じたので比較します。

マシンスペック

  • OS: macOS Catalina
  • プロセッサ: 1.6 GHz(Core i5)
  • メモリ: 16 GB

実施方法

要素数 n 個のスライスのソート時間を比較する。要素はそれぞれランダムになっている。

結果

要素数(n)マージソート(O(n log n)(sec)挿入ソート(O(n^2)(sec)
1,0000.0003570.000277
10,0000.0050020.024778
100,0000.0367051.524296
1,000,0000.341336-

※挿入ソート(1,000,000)は 1 分以上かかったので省略

要素が倍になるほどマージソートの速さがわかりますね。

このページのソースは GitHub にもあります。

ソートアルゴリズムの比較

余談

アルゴリズムを1ヶ月で把握しようとしてましたがソートアルゴリズムの雰囲気を掴むだけでそれくらい時間かかりました、、

1つずつ精進ですね。。



\ No newline at end of file diff --git a/posts/category/go/2020/07/spherical-trigonometry/index.html b/posts/category/go/2020/07/spherical-trigonometry/index.html index 52e9067c..206ef1a7 100644 --- a/posts/category/go/2020/07/spherical-trigonometry/index.html +++ b/posts/category/go/2020/07/spherical-trigonometry/index.html @@ -19,14 +19,16 @@ 球面三角法の余弦定理を利用して実際に距離を算出する方法は球面三角法の余弦定理がわかりやすいです。 実装 実装したソースコードは Github でも確認できます。 球面三角法を利用した2点間の距離計算 -package main import "math" // Coordinate 緯度経度 type Coordinate struct { Longitude float64 Latitude float64 } // EarthRadius 赤道半径 const EarthRadius = 6378140 // DistanceOnTheEarth 地球上の 2 点間の距離を出す(球面三角法) func DistanceOnTheEarth(from, to Coordinate) float64 { fromLadLon := from.Longitude * math.Pi / 180 fromLadLat := from.Latitude * math.Pi / 180 toLadLon := to.">
Author Image

Monday, July 6, 2020

球面三角法による2点間の距離計算をGoで実装してみた

はじめに

バックエンドエンジニアのロードマップに沿ってエンジニアとしての自己肯定感を養うシリーズです。

地球上の2点間の距離計算ってアプリだと Google Map API を使えば完了!だと思いますが、どう計算してるかって気になりますよね?

今回は球面三角法を利用した地球上の2点間の距離計算を Go で実装します。(調べたらフツーにあるんですが)

球面三角法とは

その名の通り、三角関数を利用して球面上の辺や角の大きさを導出するものです。平面と球面とでの違いは辺の大きさが 球面では中心角によって表されることにあります。

よって、球面三角法を使用して算出した弧の長さ(中心角)と赤道の半径を乗算すると距離が求まります。

球面三角法の証明については、球面三角形の定理を参考にしました!

(“高校生に向けて"とある通り、非常にわかりやすかったです)

球面三角法の余弦定理を利用して実際に距離を算出する方法は球面三角法の余弦定理がわかりやすいです。

実装

実装したソースコードは Github でも確認できます。

球面三角法を利用した2点間の距離計算

package main
 
@@ -59,6 +61,6 @@
 
 }
 

動かしてみる

それでは実装した Go の関数を呼び出す簡単なアプリを動かしていきます。

※今回使用するアプリも Github 上の同じディレクトリにあるのでビルドすると使用できます。

アプリの挙動としては、

  1. 2 点間の緯度経度情報を取得する(取得するために外部 APIを利用します)
  2. 1 で取得した2点の緯度経度情報を今回実装した距離計算の関数へ渡して算出する

比較するためにこちらのサイトを利用します。

結果

場所比較サイト今回のアプリ
西東京市 ~ 大阪市都島区383.344422383.3444215569602
札幌市厚別区 ~ 沖縄市2,231.3182342231.3182342761

※地球上の半径 r は 6378.140km にしています。

。。。同じになってしまいました。。比較とはなんだったんだろう

まあよく捉えると、比較サイトのような便利計算サイトと同等?のものが作れたということでしょうか。

余談

久しぶりに証明を見たり計算を手で追っていく作業をしたので懐かしい気持ちになりました。

普段の業務でそこまで計算式を使わない分、こう自発的に調べて実装するのも楽しいと思いました。



\ No newline at end of file diff --git a/posts/category/go/2022/12/kyash-advent-calendar/index.html b/posts/category/go/2022/12/kyash-advent-calendar/index.html index 4321257a..1f37efba 100644 --- a/posts/category/go/2022/12/kyash-advent-calendar/index.html +++ b/posts/category/go/2022/12/kyash-advent-calendar/index.html @@ -8,7 +8,7 @@ サッと概要を話すと、Temporary()はnet.Errorインターフェースに定義されているメソッドで、一時的なエラーかどうか判定するために用意されています。 ただし、「一時的」というのがうまく定義されていないとの理由で、こちらのメソッドは Go1.18 で非推奨になりました。 net.Error.Temporary has been deprecated. https://tip.golang.org/doc/go1.18 Temporary()が非推奨になった経緯 前提として、net.Errorインターフェースは、以下のように定義されています ※ソースは Go 1.19 です -// An Error represents a network error. type Error interface { error Timeout() bool // Is the error a timeout? // Deprecated: Temporary errors are not well-defined. // Most "temporary" errors are timeouts, and the few exceptions are surprising.">
Author Image

Tuesday, December 13, 2022

netパッケージで非推奨のTemporaryメソッドの扱いについて

はじめに

こちらはKyash Advent Calendar 2022 の 13 日目の記事です。

今年の 11 月に Kyash に入社しました!サーバサイドチームのueharaです👋

今回はnet/httpパッケージの非推奨メソッドであるTemporary()について、社のメンバーから知見を共有してもらったのでその話をします。

net/http パッケージの 非推奨メソッド Temporary() について

Temporary()については、フューチャー社の記事にわかりやすくまとめられています。

https://future-architect.github.io/articles/20220203a/

上記の記事を踏まえて、ここでは非推奨になった経緯と対応について言及しようと思います。

サッと概要を話すと、Temporary()net.Errorインターフェースに定義されているメソッドで、一時的なエラーかどうか判定するために用意されています。 ただし、「一時的」というのがうまく定義されていないとの理由で、こちらのメソッドは Go1.18 で非推奨になりました。

net.Error.Temporary has been deprecated. https://tip.golang.org/doc/go1.18

Temporary()が非推奨になった経緯

前提として、net.Errorインターフェースは、以下のように定義されています @@ -77,6 +79,6 @@ fmt.Println(ne.Error()) }

さいごに

Temporary()で判定したいようなケースはなるべくさけて代替のエラーを見つけるのがよさそうですね

学びとしては、非推奨になったきっかけの issue を読んでみて、標準パッケージを読むことに対する抵抗が少しなくなったような気がしたことです💦



\ No newline at end of file diff --git a/posts/category/go/2022/12/qiita-advent-calender/index.html b/posts/category/go/2022/12/qiita-advent-calender/index.html index a96357af..5287d184 100644 --- a/posts/category/go/2022/12/qiita-advent-calender/index.html +++ b/posts/category/go/2022/12/qiita-advent-calender/index.html @@ -11,7 +11,7 @@ flowchart LR 呼び出し元 --> Futureメソッド -- 実行できるようになるまで待つ --> 処理するメソッド 呼び出し元と処理するメソッドの間に Future メソッドを挟むことで、Future メソッドがプロキシ的に働き、非同期的に処理するメソッドを実行できるようになっています。 Go だとこんなかんじにかけるらしい 以下の記事で Future/Promiseという説明書されています https://ascii.jp/elem/000/001/486/1486902/ -package main func readFile(path string) chan string { // ファイルを読み込み、その結果を返すFutureを返す promise := make(chan string) // readFile とは別のゴルーチンでファイルを読み出す go func() { content, err := os.">
Author Image

Saturday, December 10, 2022

Futureパターンが使われているOSSを見てみた

はじめに

@uh-zzです!

この記事は、Go Advent Calendar 2022の 10 日目の記事になります!

今年は、個人的に色々なことに挑戦した年だったなあと振り返るとともに、去年のアドベントカレンダーからもう1年経つのか〜という気持ちです

この記事では、Go における Future パターンをご紹介できればと思います

Future パターンとは

あるメソッドを呼び出すとします。 もしもオブジェクトが、そのメソッドを実行できる状態なら、実行します。 でも、実行できない状態なら、将来実行できる状態になるまで待つようにしたいとします。 その時に使えるのがこの Future パターンです。 future は「未来」という意味です

もう少し正確にお話しましょう。 単にあるクラスに 「実行できる状態になるまで待つ」 という機能を入れるわけではありません。 すでに存在しているクラスに一皮かぶせて、 「実行できる状態になるまで待てるような機能を追加する」 というのが Future パターンです。

出典: 結城浩, Future パターン, デザインパターン紹介

上記の参考記事内では、Java をつかったマルチスレッドプログラミングで Future パターンが実装されています。

引用箇所の説明がほぼすべてですが、イメージ図で補足するとこんな感じになります

flowchart LR
    呼び出し元 --> Futureメソッド -- 実行できるようになるまで待つ --> 処理するメソッド
 

呼び出し元と処理するメソッドの間に Future メソッドを挟むことで、Future メソッドがプロキシ的に働き、非同期的に処理するメソッドを実行できるようになっています。

Go だとこんなかんじにかけるらしい

以下の記事で Future/Promiseという説明書されています

https://ascii.jp/elem/000/001/486/1486902/

package main
@@ -92,6 +94,6 @@
 

※記事内にあるコードに、コメントを追記させていただきました。🙏

Java で実現していた Future メソッドとは違い、Go ではチャネルをつかって実行待ちを表現できるようです。 main 関数だけ見ると、呼び出し側では同期的に見えますが、内部でチャネルによる非同期処理が行われています。

実際に使われているところを深ぼってみた

https://github.com/hashicorp/raft

Error()の実装はここ https://github.com/hashicorp/raft/blob/6b4e32088e0bda22ea219fc89b0ee47f420e2b0b/future.go#L168

raft の apply だけを深堀りしてみるのもいいかもしれない

おわりに

Future パターンを取り上げてみましたが、蓋を開けてみるとチャネルを使った並行プログラミングでよく目にするような処理に、”名前がついてたんだ〜!”と思う方もいるでしょう(私のことです)

パターンを知る → 使っている OSS を見にいく流れは体験としていいなと思ったので、来年も引き続きやっていきます👋



\ No newline at end of file diff --git a/posts/category/go/index.html b/posts/category/go/index.html index fcab5b1f..a9a64b80 100644 --- a/posts/category/go/index.html +++ b/posts/category/go/index.html @@ -1,12 +1,14 @@ Go -
Hero Image
netパッケージで非推奨のTemporaryメソッドの扱いについて

はじめに こちらはKyash Advent Calendar 2022 の 13 日目の記事です。 今年の 11 月に Kyash に入社しました!サーバサイドチームのueharaです👋 今回はnet/httpパッケージの非推奨メソッドであるTemporary()について、社のメンバーから知見を共有してもらったのでその話をします。 @@ -49,4 +51,4 @@ package main import ( "fmt" "time" "github.com/uh-zz/traning/algorithm/shuffle" ) func main() { // ランダムな要素 n 個のスライス取得 input := shuffle.RandomIntList(n) inputLength := len(input) // マージソート MergeSort(&input, 0, inputLength) } // MergeSort マージソート func MergeSort(input \*[]int, left, right int) { // 要素数1つの場合は抜ける if right-left == 1 { return } // 配列を2つに分けるインデックス middle := left + (right-left)/2 // 配列左側 MergeSort(input, left, middle) // 配列右側 MergeSort(input, middle, right) var buffer []int // 左側と右側をバッファにためる(右側反転) for index := left; index < middle; index++ { buffer = append(buffer, (*input)[index]) } for index := right - 1; index >= middle; index-- { buffer = append(buffer, (*input)[index]) } // マージする scopeLeft := 0 scopeRight := len(buffer) - 1 for index := left; index < right; index++ { if buffer[scopeLeft] <= buffer[scopeRight] { // 左側採用 (*input)[index] = buffer[scopeLeft] scopeLeft++ } else { // 右側採用 (*input)[index] = buffer[scopeRight] scopeRight-- } } } これ考えたのぶっ飛んでるなあと思って Wikipedia 見てたら、考案者がフォン・ノイマンでやっぱりぶっ飛んでた(凄すぎ)

\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/posts/category/index.html b/posts/category/index.html index 90b9fc9e..14f6dbc7 100644 --- a/posts/category/index.html +++ b/posts/category/index.html @@ -1,12 +1,14 @@ Top Category -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/posts/category/inputs/2022/07/index.html b/posts/category/inputs/2022/07/index.html index 94ecbe51..b5010bbc 100644 --- a/posts/category/inputs/2022/07/index.html +++ b/posts/category/inputs/2022/07/index.html @@ -33,15 +33,17 @@ Domain-Driven Design Simplified. まだよんでない 読んだ本 自分に気づく心理学-加藤 諦三(著) -Lean と DevOps の科学[Accelerate] テクノロジーの戦略的活用が組織変革を加速する (impress top gear)-Nicole Forsgren Ph.D. (著), Jez Humble (著), Gene Kim (著), 武舎広幸 (翻訳), 武舎るみ (翻訳)">
Author Image

Tuesday, July 5, 2022

2022年07月に読んだ記事とか本とか

はじめに

読んだ記事とか本のリンクを張っておきます

読んだ記事

アーキテクトに求められるマインドとは / mindset for an architect

「少なくとも、最悪ではないアーキテクチャを狙う」

自分の中で新しい視点だった(常に選択肢の中で(世間的に)最善とされているものがいいという思考をしてる)

「変更が容易であれば、最初から望ましいアーキテクチャを正確に設計しなければならないという、プレッシャーも少なくなる」

Re: スクラム開発チームと業務委託エンジニアの相性が最悪だと思っている

Spring で快適な DB 疎通ユニットテストライフを送りたい

yaml、json、または csv などのファイルでテスト用データの事前投入や結果比較を容易にしてくれます

Database RIder はテストメソッド単位で使用するデータファイルを指定できる

友達に教えてもらった。テストデータをコードと別で、テスト前後の比較も簡単にしてくれるのはすごい。

「“楽しくないけどお金のためにやる人”はやはり伸びない」まつもとゆきひろ氏が説く“プログラマーに向いている人”

「ノーコードによって仕事が奪われるイメージはない」まつもとゆきひろ × 高橋直大 × 楠正憲が語る、これからのプログラマーの仕事

Amazon DynamoDB: A Scalable, Predictably Performant, and Fully Managed NoSQL Database Service

まだよんでない

Domain-Driven Design Simplified.

まだよんでない

読んだ本

自分に気づく心理学-加藤 諦三(著)

Lean と DevOps の科学[Accelerate] テクノロジーの戦略的活用が組織変革を加速する (impress top gear)-Nicole Forsgren Ph.D. (著), Jez Humble (著), Gene Kim (著), 武舎広幸 (翻訳), 武舎るみ (翻訳)

JABEE 対応 技術者倫理入門-小出 泰士(著)

やさしく学べる基礎物理-基礎物理教育研究会(編集)

星の王子さま-サン=テグジュペリ(著)



\ No newline at end of file diff --git a/posts/category/inputs/index.html b/posts/category/inputs/index.html index 444091ed..cdefb18d 100644 --- a/posts/category/inputs/index.html +++ b/posts/category/inputs/index.html @@ -1,12 +1,14 @@ Inputs -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/posts/category/look-back-on/2021/index.html b/posts/category/look-back-on/2021/index.html index be7cc8da..d561db6b 100644 --- a/posts/category/look-back-on/2021/index.html +++ b/posts/category/look-back-on/2021/index.html @@ -1,13 +1,15 @@ 2021年の振り返り -
Author Image

Friday, December 31, 2021

2021年の振り返り

はじめに

今年のふりかえりをするために個人ブログを数ヶ月ぶりに更新しています。

しばらくぶりに拙ブログを見ていて、ぜんぜんメンテしてなかったや。。の反省を強く感じたので来年はアウトプットをもっともっと増やします!

2021/01

とくに話すトピックはありませんでした。

読んでた本

2021/02

とくに話すトピックはありませんでした。

読んでた本

2021/03

このころから年内に引っ越しを考えはじめました。

部屋に不満はありませんでしたが、ぼんやりと中央線沿い(=東京の西側)がかっこいいというイメージをもっていたので一人でちょくちょく出向いていました。

主に、杉並区エリア(中野/高円寺/阿佐ヶ谷/荻窪)を中心にまわっていました。

特に、荻窪にある杉並アニメーションミュージアムは、展示も楽しく見れますが、ミュージアムが入っている杉並会館の雰囲気が抜群にいいのでおすすめです。

2021/04

転職しました。社会人4年目にして3社目になります。

前職と同じくサーバーサイドのポジションです。

前職では、コロナ以降フルリモートでしたが、転職後は週3出社になりました。

出社になってからは、ランチをメンバーと取るようになり、コミュニケーションが増えたのがメリットに感じました。

仕事に関して前職では主に、Java/Go/Node.js での開発を2年ほどしていましたが、転職直後は Ruby on Rails での開発がメインになりました。

はじめての Ruby と Rails ということもあり、メンバーにはだいぶお世話になりながらも、プライベートではおすすめの参考書をかたっぱしから読む生活をしていました。

読んでた本

2021/05

緊急事態宣言の期間に入り、ほぼフルリモートになりました。

この頃のコミットを見てみると、主に Rails プロジェクトでのバグフィックスや、小さな機能追加をしていました。

(レビューでいろいろ教えてくれたメンバーには感謝です 💦)

コードレビューに関して前職ではほぼ対面レビューだったのに対して、転職してからは Github 上でのレビューに切り替わったことで、レビュアー以外のメンバーにも非同期的にチェックしてもらえたのがすごくよかったです。

2021/06

コミットを見てみると、この頃に担当したタスクにだいぶ時間を割いていました。

というのも、タスクを進める上で発生した海外担当者とのメールであくせくしていた思い出があります。

慣れない英語メールのやり取りが長引いてしまったものの、説明するのに必要なドメイン知識の理解がだいぶ進んだので、トレードオフだったのかなあと後になって感じています。

読んでた本

2021/07

この月から、「プログラミング言語 Go」オンライン読書会に参加するようになりました。

月に 1 度の読書会ですが、毎回新しい発見があって楽しいです。

プライベートではそろそろ引っ越しをしようと suumo を見ていて、何件かピックアップして不動産に行きました。

ピックアップした物件ではなかったものの、ちょうどその日に空いた物件を一番乗りで見に行くことになり、初日で即決しました。

当初の予定通り、中央線沿いに決まったのでこの頃は浮かれていました。

2021/08

社外のオンライン LTに参加したりしました。

2021/09

この頃のコミットを見ると、社内での Go プロジェクトへのコミットが少しずつ増えてきました。

プライベートでは、一人散歩でよく歩いてました。

よかったコース

読んだ本

2021/10

この頃、ようやく緊急事態宣言が解除されました。

開発合宿があり、LTなどしました。

プライベートでは、hacktoberfestに参加したりしました。

初参加かつ、OSS も初めてではありましたが、コミットできそうなリポジトリに5つプルリクエストを出しました。

T シャツ獲得!の要件を満たしたので現在、発送待ちです。(届いたらツイートします)

2021/11

Go Conference 2021 Autumnにボランティアスタッフで参加させていただきました。

パートナースタッフに、社のロゴや twitter アカウントを載せてもらえたのは感無量でした。

(運営の方ありがとうございます!)

来年は、もっともっと関わっていくぞ〜の気持ちになりました。

読んだ本

2021/12

Go に対する機運が社内でも高まってきました。(有志で勉強会を開くようになりました。)

また、個人的にGo アドベントカレンダーにも初参加してみました。

読んだ本

まとめ

今年は、転職&引っ越しと、いろいろ変化の多い年でした。

あと、少しずつ社外のイベント/コミュニティにも参加できるようになってきました。

来年は、アウトプットを増やして、社と私の認知度を上げていくのを目標にします。

(コミュニティ活動も積極的に参加していくぞ〜!!)

備考

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/category/look-back-on/2022/05/31/go-to-the-teikyo-university/index.html b/posts/category/look-back-on/2022/05/31/go-to-the-teikyo-university/index.html index fe431e82..720b35c6 100644 --- a/posts/category/look-back-on/2022/05/31/go-to-the-teikyo-university/index.html +++ b/posts/category/look-back-on/2022/05/31/go-to-the-teikyo-university/index.html @@ -1,13 +1,15 @@ 【通信教育課程】帝京大学理工学部情報科学科に編入学しました -
Author Image

Tuesday, May 31, 2022

【通信教育課程】帝京大学理工学部情報科学科に編入学しました

はじめに

表題の通り、今年の 4 月から帝京大学理工学部情報科学科の通信教育課程に 2 年次編入しました。

そもそもの経緯と入るまでの話、入って 1 ヶ月経過した後の所感をまとめておきたいと思います。

きっかけ

大学進学について

通信制大学へ進学したいと思ったのは今年に入ってからではなく、ここ 2 年くらい検討していました。

当初は理工系ではなく、社会学/哲学に興味があり、その方面の勉強がしたいと漠然と考えていました。

ただ 2 年の間、大学への入学を躊躇してたのは以下の理由がありました。

  • 通信制大学の卒業が難しい、また卒業率が低いといった情報を見て腰が重かった
  • 働きながら時間が取れない、平日のフルタイムかつ出社している場合、早朝か、仕事から帰ってきて勉強時間を確保する必要が出てくるので、リモートできないと厳しい
  • とりあえず入門書を買って積んでおけば自分で勉強できるし、進学しなくてもいいのでは?と諦めムードを出していた

以上の理由から悩んでは忘れるを一人繰り返しては日々を過ごしていました。

キャリアについて考えるようになった

そんな中、昨年末に以下の記事を拝見しました。

生涯現役のソフトウェアエンジニアでありたい。IC(Individual Contributor)のキャリアパスがあると自覚するまで 10 年の軌跡

IC(Individual Contributor)というキャリアがあるのかというのと、記事中の主張から自分のキャリアについて振り返る様になりました。

これまでのキャリアは前述のようにかなり行きあたりばったりでしたが、その中にも不動となる主軸が 2 つありました。(中略)

1 つは「毎日楽しく開発したい」ということ。(中略)

もう 1 つの軸は「選択肢を常に複数確保する」ことです。(中略)

この「毎日楽しく開発したい」は、私がエンジニアになりたいと思った動機「楽しく(刺激的に)生きたい」に通じるものがあり、IC というキャリアないしはテクニカルスキルをあげることで自分の幸福につながるのかという気づきがありました。

遠回りのような近道のような、どちらとも言えないですが、自分で出した答えの1つが大学進学、それもコンピュータに関する学位を取得するということでした。

ここについては自分の中で消化しきれていない部分もあるので、別の記事で改めて振り返ることにします。

帝京大学に決めたのはそこまで時間がかからなかった

フルタイムで働きながらコンピュータに関する学位が取得できる通信制大学は、調べた限りだと選択肢は限られました。

また、同じくエンジニアとして働きながら勉強されている方のブログが大変参考になりました。

@gkzvoice さんには twitter でブログに関して質問させていただき、またアドバイスまでいただいたので感謝です。

入るまでの手続きなど

詳細な手続きは募集要項にあるので、ここでは所感を述べるだけにします。

  • 調査書、成績表の発行を、所属していた専門学校に依頼する必要があるので、余裕を持って出願する
  • 志望理由を記載する必要があるので、動機と抱負は棚卸ししてたほうがスムーズかも

2 年次編入について

今回 2 年次編入で出願することができました。

というのも、情報系専門学校の 2 年制を卒業しているので、編入の要件を満たしていたからというのが理由です。

要件を満たしていれば、専門学校での授業内容がまとめられたシラバス?を願書と一緒に提出した後、大学にて専門学校の授業内容から、関連する大学側での科目が履修済みとして、認定されます。

今回は認定された科目が上限数に達していたので、晴れて編入することができたのでした。

そして入学しました

出願から約 2 ヶ月後、晴れて入学式を迎えることができました。

日本武道館で約 1 時間のコンパクトな式が執り行なわれ、あれよあれよと駅に流れ着き帰宅しました。

社会人なので、午後からはお仕事しました

1 ヶ月が経過して

学生という自覚を少し感じるようになりました。

ここ数日はレポート期限と授業の多さにやられていてどこか上の空でした。(まだ試験が残っているのでしばらくはこの状態が続きそう)

今回、履修登録した科目と進捗状況についても別の記事でまとめます。

まとめ

通学してないこともあり、社会人大学生になった自覚は正直実感しにくいというのが所感です。

ただ勉強する習慣ができつつあることや、レポートを通してドキュメンテーションの大切さを日々感じるようにはなりました。

今後はブログを通して、進捗や所感をアウトプットしていければなとぼんやり考えています。

本業と学業、どちらも進捗出していくぞ〜

備考

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/category/look-back-on/2022/09/04/preview-courses-at-teikyo-univ/index.html b/posts/category/look-back-on/2022/09/04/preview-courses-at-teikyo-univ/index.html index ab298720..45d64519 100644 --- a/posts/category/look-back-on/2022/09/04/preview-courses-at-teikyo-univ/index.html +++ b/posts/category/look-back-on/2022/09/04/preview-courses-at-teikyo-univ/index.html @@ -1,13 +1,15 @@ 履修科目一覧をNotionでつくりました -
Author Image

Sunday, September 4, 2022

履修科目一覧をNotionでつくりました

ご連絡

4 月から通信大学での学習を始めて、もう少しで半年になります。

節目というか、ちょっと時間ができたので、私が履修している科目一覧を Notion で管理しようと思い立ち、さくっと作ってみました。

科目一覧 - Notion

これから同じように学習される方の参考になれば幸いです。(私も諸先輩方のブログを見て、参考になったので恩返しできれば!)

近況

元気にやっています👋

備考

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/category/look-back-on/2022/12/31/index.html b/posts/category/look-back-on/2022/12/31/index.html index 797d50fe..3729c641 100644 --- a/posts/category/look-back-on/2022/12/31/index.html +++ b/posts/category/look-back-on/2022/12/31/index.html @@ -1,16 +1,18 @@ 2022年の振り返り -
Author Image

Saturday, December 31, 2022

2022年の振り返り

はじめに

1年経つのは早いですね。

今年のサマリーとしては、通信大学へ入学したことと転職したこと、です。

去年はこのブログの投稿を増やしていくと意気込んでいましたが実績は、、意気込みは大事なので来年も意気込んでいきます💪

振り返りについては需要の有無に関わらず書いていきたいと思ってる所存です。

バックナンバー

2022/01

とくに話すトピックはありませんでした。

新年一発目こそなにかあれよ!と自分でツッコミを入れたくなったので、意識的に1月にイベントつくっていきます

2022/02

コロナの感染拡大がまた出てきたころで、予定されていた開発合宿がオンラインでの開催になりました

初のオンライン合宿開催!開発合宿についてご紹介!

Gatherはこのとき初めて使いましたが、会議室に入ると強制的にビデオ通話になったりホワイトボードを共有したりと Google Meet や Zoom のような使い方ができるのに加え、マップを自分たちでつくったりゴーカートができたりと、息抜き要素があったのが推しポイントです。

このとき気に入って、合宿のあともオンボーディングを Gather でやってたりもしたなぁと思い返したり😌

2022/03

とくに話すことはありませんでした。

2022/04

ふらっと Kyash のイベントを見にいきました。

Kyash TechTalk #2 - Serverside のシステム構成とアーキテクチャ

このとき、Kyash のサーバ構成を知れたのもそうですが、苦労話や課題に思っていることを対外的に発信しているのを見て、技術力求められそうだなというのと、中の人楽しそうに話してるなと思ったのを覚えています。

このイベントのあと、メールでカジュアル面談のお誘いをもらったので、転職活動はしてなかったけど、興味本位でセッティングしてもらったのが今年の転職につながりました。

またプライベートな話題としては、通信大学に入学しました

【通信教育課程】帝京大学理工学部情報科学科に編入学しました

入ってから8ヶ月目で思うことは、年間 12 科目の単位を働きながら取るのは絶対ムリ!ではないかもしれませんが、ギリギリを攻めている感覚と怠惰な休日の時間を取りづらくなるということです。 これは勉強するリズムがついていいじゃないかという反面、興味が薄い科目に関して場当たり的な勉強をしてしまいがちなのと、休日を授業やレポートで埋めると休みが休みでなくなってしまう悲しみを少なからず感じるということです。

この振り返りは、来年 2 月の区切りのいいところで改めて記事にしようと思います。

2022/05

ジムに行き始めました。きっかけはリモートワークをしていて一日座ってる時間が長いと寝つきが悪かったりするので、体を動かしてぐっすり眠りたい、と思ったからです 。

今も継続して週に 2 回くらいは走りに行ってます。

走るマシン(トレッドミル)しか活用できてないので、来年はほかのトレーニングにも手を出したいです。

2022/06

とくに話すことはありませんでした。

2022/07

通信大学の初めての単位習得試験があり、物理的な会場での受験でした。

内心なにかしら交流があるかも😌、とそわそわしていましたが、杞憂に終わりました。

2022/08

昨年から月 1 で参加していた『プログラミング言語 Go』オンライン読書会が一区切りつきました。

初めて参加した社外勉強会がこの読書会だったので、個人的に印象深く、毎回新しい知見を得る場として楽しませていただきました。

今は柴田先生が主催するべつの読書会に参加していますが、相変わらず聞き専になってしまっているので、恥ずかしがらずに質問していくのを来年の抱負にしようと思います笑

2022/09

今年は通信大学に入ったのを言い訳に、技術書以外の本を買ったり読んだりする機会が少なかったんですが、その中でも社会学のテキストが個人的に面白かったので、マイベストブックにノミネートしました。

社会学 新版 (New Liberal Arts Selection)

これまでぼんやり社会学を勉強したいなと思ってたところでこの本を強制的に読むことになり、ざっと主要なトピックを俯瞰することができました。

個人的に、「文化と再生産」の話が好きです。

2022/10

今年もしれっと hacktoberfest に参加していました。

以下の記事で紹介されているように、スパムが大量生産される問題を含みつつ、OSS 活動ををタイポ修正やちょっとしたバグフィックスから始められる、始めるモチベーションに使っています。(自分のプルリクがそうなっているかもしれないという思いもありつつ、健全な活動をしていると自分に言い聞かせています)

「プログラムの修正を送ると T シャツがもらえる」キャンペーンが開発者に迷惑がられる理由とは?

、とまあ今年も達成できたので、また特典が届いたたらツイートします。

あとは、サウナ遠征(一人)で名古屋に行きました。 このときのスケジュールがスムーズすぎて、また来年遠征の予定を立て始めています笑

※ツイート忘れてますが、ウェルビー栄デビューもこの遠征で達成しました

2022/11

Kyash に入社しました👍

全体の感想としてカジュアル面談で話を聞いてから、選考に進み、オファーをいただくまでがすごく速かった気がします笑

※このとき並行で数社選考を進めていたんですが、どのチームも魅力的だったとここで断っておきます

その中でも、オンラインイベントで楽しそうに話してたのが忘れられず決断をしたのでした

※転職エピソードについてはもっと語ることあるだろと自分にツッコミを入れつつ別途どこかで振り返ります。

2022/12

Kyash に入って、初めて社のアドベントカレンダーに参加しました

【Go】net/http パッケージで非推奨の Temporary の扱いについて

あとは、Go アドベントカレンダーに今年も細々と投稿しました

【Go/並行処理】Future パターンってなにか調べてみた!

あとは、nilerrに影響を受けてnilpointerなるものを書いて静的解析ツールを作る実績も解除しました。

作ったのはいいものの使い道なくね?と我に返ってしまい告知はしませんでしたが、ここで供養させていただこうと思います笑

まとめ

なにかアウトプットをたくさんしたという感じではないものの、人生してるなあという振り返りでした。

来年の抱負は引き続きアウトプット増やすようにパブリックなコミットを意識しつつ、言い訳せずに積んでる本を消化します笑

あとは、コミュニティに入れるように気持ち前のめりになって日々を過ごそうと思います。

備考

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/category/look-back-on/index.html b/posts/category/look-back-on/index.html index bf0f9b5e..ad95b4ad 100644 --- a/posts/category/look-back-on/index.html +++ b/posts/category/look-back-on/index.html @@ -1,12 +1,14 @@ 振り返り -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/posts/category/oss/2020/08/semantic-versioning/index.html b/posts/category/oss/2020/08/semantic-versioning/index.html index b0d6a946..697bc651 100644 --- a/posts/category/oss/2020/08/semantic-versioning/index.html +++ b/posts/category/oss/2020/08/semantic-versioning/index.html @@ -15,16 +15,18 @@ ちょっと踏み込むと プレリリースバージョンには、パッチ番号の後ろにハイフンで区切って識別子をつけることができます。 (例:1.1.0-alpha / 1.1.0-beta / 1.1.0-rc) ※ちなみに識別子のrcは「release candidate」の略でベータ版よりもさらに製品版に近い品質のバージョンにつけるそうです。(略を初めて知りました。) あと npm の packagge.json でもモジュールをセマンティックバージョンで管理してます。(~や^が付与されているのをよく見ると思います。) これについては上、真ん中、下で覚えるバージョニング範囲指定がわかりやすかったので共有しておきます。 余談 たかがバージョニング、されどバージョニングといった感じでした。知ってて損はないですよね。 -備考 表紙イラスト:Loose Drawing">
Author Image

Wednesday, August 5, 2020

Semantic Versioning

はじめに

バックエンドエンジニアのロードマップに沿ってエンジニアとしての自己肯定感を養うシリーズです。

セマンティックバージョニング?

アプリに振るバージョン番号をSemVerというルールに従って付与しましょうというものです。

確かにバージョン番号に意味を持たせることで、ユーザからもアプリのバージョン番号が上がればバグ修正なのか機能追加なのかわかりますし、プログラムからも互換性を考慮して処理を分けることができるのでよいですね。

これだけ覚えておけば OK

バージョン番号の形式は、メジャー.マイナー.パッチです。(例:1.0.0)

メジャー

  • 後方互換性がない変更があった時にはこの番号を上げなければいけません(MUST)
  • この番号を上げた際には、マイナー/パッチの番号は 0 にリセットしなければいけません(MUST)
  • この番号が「0」の場合は初期開発用として扱います。リリースの段階でこの番号を「1」に上げます。

マイナー

  • 後方互換性を保ちつつ、機能追加のある時にはこの番号を上げなければいけません(MUST)
  • この番号を上げた際には、パッチの番号は 0 にリセットしなければいけません(MUST)

パッチ

  • 後方互換性を保ちつつ、バグ修正のある時にはこの番号を上げなければいけません(MUST)

※バグ修正とは間違った振る舞いを修正する内部の変更のことをいいます。

ちょっと踏み込むと

  • プレリリースバージョンには、パッチ番号の後ろにハイフンで区切って識別子をつけることができます。

(例:1.1.0-alpha / 1.1.0-beta / 1.1.0-rc) ※ちなみに識別子のrcは「release candidate」の略でベータ版よりもさらに製品版に近い品質のバージョンにつけるそうです。(略を初めて知りました。)

  • あと npm の packagge.json でもモジュールをセマンティックバージョンで管理してます。(~^が付与されているのをよく見ると思います。)

これについては上、真ん中、下で覚えるバージョニング範囲指定がわかりやすかったので共有しておきます。

余談

たかがバージョニング、されどバージョニングといった感じでした。知ってて損はないですよね。

備考

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/category/oss/index.html b/posts/category/oss/index.html index f5496632..cfc71adb 100644 --- a/posts/category/oss/index.html +++ b/posts/category/oss/index.html @@ -1,12 +1,14 @@ OSS -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/posts/category/page/2/index.html b/posts/category/page/2/index.html index ac8714bb..0d6b60ed 100644 --- a/posts/category/page/2/index.html +++ b/posts/category/page/2/index.html @@ -1,12 +1,14 @@ Top Category -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/posts/category/security/2021/01/oauth/index.html b/posts/category/security/2021/01/oauth/index.html index 03eef016..4a4e124a 100644 --- a/posts/category/security/2021/01/oauth/index.html +++ b/posts/category/security/2021/01/oauth/index.html @@ -35,16 +35,18 @@ OAuth 1.0 のほうが OAuth 2.0 より安全なの?でも言われている通り、2.0 はクライアントアプリケーションの幅が広がった分、秘密鍵の隠蔽が難しくなるみたいです。。 隠蔽できるかの違いはありますが、セキュリティレベルは両者それほど変わらないみたいです。 (2.0 は経路を TLS 化していることで、1.0 よりも提示するパラメータが少なくなっているという事実はあるそうな) -まとめ 実装のことを考えてこれからも 2.0 を使っていきましょうという締めです。">
Author Image

Tuesday, January 5, 2021

OAuth について

はじめに

バックエンドエンジニアのロードマップに沿ってエンジニアとしての自己肯定感を養うシリーズです。

OAuth とは

ひとまず、一番分かりやすい OAuth の説明で大体の感覚がつかめますのでオススメです。

こちらでもざっくり説明させてもらうと、OAuth は複数のアプリを連携させるための仕組みです。

例えば、ブログの記事を更新した瞬間に、ブログから更新情報をツイートしたかったりする場合に使われます。

ただ、そのままツイートできるわけではなくて、ブログアプリがツイートする許可(認可)をしてあげる必要があります。

そして許可されたアプリは許可証(アクセストークン)を持っていることで、Twitter を使ってツイートできるという仕組みです。

メリット

OAuth を使うことで、上の例であげたブログアプリは、Twitter のユーザ名とパスワードを知らなくてもツイートできるという点です。

巷のアプリはこれを使うことで、Google アカウントや Twitter など SNS アカウントを持っているだけでユーザ登録できちゃいます。最初の煩わしい登録の手間が省けて良いです。

OAuth1.0

OAuth の初期バージョンです。他に 1.0a という名前のバージョンもありますが、Twitter では 1.0a を使うことができるみたいです。 (後述の 2.0 も同様に使用可)

特徴としては、認証と署名を用いて実現される仕様でありますが、実装が複雑で使用する言語が限られてしまうというデメリット?があるみたいです。(堅牢ではあると思いますが)

また、1.0 は Web アプリのみ対応しているので、デスクトップ/モバイルアプリは蚊帳の外とこれまた制限されるみたいです。

(Twitter は Web アプリ以外でも使える xAuth という OAuth 拡張を開発したりしてたみたいです)

さらに悲しいことに、1.0 の仕様は次の 2.0 の策定を持って廃止されたみたいです。

OAuth2.0

後継です。複雑と言われていた署名(とトークン交換)をバッサリ省いています。

これによって実装しやすいものになりましたがセキュリティが気になるところです。

OAuth 1.0 のほうが OAuth 2.0 より安全なの?でも言われている通り、2.0 はクライアントアプリケーションの幅が広がった分、秘密鍵の隠蔽が難しくなるみたいです。。

隠蔽できるかの違いはありますが、セキュリティレベルは両者それほど変わらないみたいです。

(2.0 は経路を TLS 化していることで、1.0 よりも提示するパラメータが少なくなっているという事実はあるそうな)

まとめ

実装のことを考えてこれからも 2.0 を使っていきましょうという締めです。

(Twitter 以外のほとんどのアプリが 2.0 を採用していることもあり、、)

この辺の仕様がやはり読んだだけではイメージしづらいところがありますので、簡単に実装してみて実務で使えるようになりたいですという感想です。

備考

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/category/security/index.html b/posts/category/security/index.html index b831dba0..191b4061 100644 --- a/posts/category/security/index.html +++ b/posts/category/security/index.html @@ -1,12 +1,14 @@ Security -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/posts/category/system-design/2020/12/principles-of-the-systems-architecture/part1/index.html b/posts/category/system-design/2020/12/principles-of-the-systems-architecture/part1/index.html index d2ad35b7..cc6ca2a7 100644 --- a/posts/category/system-design/2020/12/principles-of-the-systems-architecture/part1/index.html +++ b/posts/category/system-design/2020/12/principles-of-the-systems-architecture/part1/index.html @@ -13,14 +13,16 @@ 範囲の広い汎用的な型を使うのではなく、業務に合わせた値で制限するというものです。 値オブジェクトクラスはこんなかんじ class Quantity { static final int MIN = 1; static final int MAX = 100; int value; Quantity(int value) { if (value < MIN) { throw new IllegalArgumentException("不正" + MIN + "未満"); } if (value > MAX) { throw new IllegalArgumentException("不正" + MAX + "超"); } this.value = value; } } そして参照はこんなかんじ -Quantity quantity = new Quantity(50); こうすることで Quantity 型は値の制限(0~100)付きの実装ができるので安全です。">
Author Image

Saturday, December 5, 2020

システム設計-part1-

はじめに

バックエンドエンジニアのロードマップに沿ってエンジニアとしての自己肯定感を養うシリーズです。

現場で役立つシステム設計の原則を元に記事を作成しています。

設計パターン

値オブジェクト(Value Object)

Java で変数を扱うとき、int や String などで型定義しがちな初心者丸出しの実装をしていた私ですが、値オブジェクトを知ったとき眼からウロコでした。

値オブジェクトとは、汎用的な型(int や String)で型を定義するのではなく、専用の型(クラスやインターフェース)を定義します。

範囲の広い汎用的な型を使うのではなく、業務に合わせた値で制限するというものです。

値オブジェクトクラスはこんなかんじ

class Quantity {
 
     static final int MIN = 1;
@@ -70,6 +72,6 @@
   }
 }
 

意地で不変なオブジェクトを返すようにします。そうすることで変更による副作用の起きにくいプログラムを作ることに繋がります。

まとめ

  • 値オブジェクトもコレクションオブジェクトもどちらも「不変であれ」ということです。同じインスタンスを使い回そうとすればするほど、変更によるバグが出る可能性が高くなります。
  • データとロジックは1つのクラスに閉じこめましょう。ロジックをまとめておくことで、使う側はメソッドを呼ぶだけで済むし、変更する場合はそのクラスだけを対象にすればよいわけです。人類の英知ですね。

備考

現場で役立つシステム設計の原則

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/category/system-design/2020/12/principles-of-the-systems-architecture/part2/index.html b/posts/category/system-design/2020/12/principles-of-the-systems-architecture/part2/index.html index 3dbb348e..1f19427c 100644 --- a/posts/category/system-design/2020/12/principles-of-the-systems-architecture/part2/index.html +++ b/posts/category/system-design/2020/12/principles-of-the-systems-architecture/part2/index.html @@ -13,14 +13,16 @@ Yen fee() { Yen result; if (isChild()) { result = chidFee(); } else if (isSenior()) { result = seniorFee(); } else { result = adultFee(); } return result; } さっきのコードからローカル変数を抜いて結果をすぐにreturnするようにした(例 2) Yen fee() { if (isChild()) { return chidFee(); } else if (isSenior()) { return seniorFee(); } else { return adultFee(); } } このように、値が決まるとすぐにreturnするやり方を早期リターンと言います。 ガード節 上記の例 2 からelseを抜いた(例 3) -Yen fee() { if (isChild()) return chidFee(); if (isSenior()) return seniorFee(); return adultFee(); } elseを抜いた早期リターンをガード節と言います。非常にコンパクトですね。">
Author Image

Saturday, December 5, 2020

システム設計-part2-

はじめに

バックエンドエンジニアのロードマップに沿ってエンジニアとしての自己肯定感を養うシリーズです。

現場で役立つシステム設計の原則を元に記事を作成しています。

設計パターン

早期リターン

複雑になりがちな場合分けのロジックの見通しをよくしようというものです。

ありがちなif-elseをつなげた(例 1)

Yen fee() {
   Yen result;
 
@@ -121,6 +123,6 @@
   return feeType.yen();
 }
 

enumクラスのvalueOf()メソッドはMapget()メソッドと同様に、if 文を使うことなく料金区分ごとのオブジェクトを取得できます。

このような振る舞いを持った列挙型(enum)を区分オブジェクトと言います。

まとめ

前回同様、コードをスッキリさせる手法を見てきました。インターフェースを使うことで抽象的なメソッドを作ったり、列挙型を使って if 文をなるべく減らせることはコードの保守性、拡張性を高めてくれますね。

備考

現場で役立つシステム設計の原則

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/category/system-design/2020/12/principles-of-the-systems-architecture/part3/index.html b/posts/category/system-design/2020/12/principles-of-the-systems-architecture/part3/index.html index 80569151..dbf9b7e3 100644 --- a/posts/category/system-design/2020/12/principles-of-the-systems-architecture/part3/index.html +++ b/posts/category/system-design/2020/12/principles-of-the-systems-architecture/part3/index.html @@ -41,14 +41,16 @@ まとめ 時すでに遅しと言いますか、現場での反省点をつらつら振り返ってベストプラクティスを学んでいるという感じです。 次回に活かそうというモチベーションは上がるのでいい復習方法だと感じます。 備考 現場で役立つシステム設計の原則 -表紙イラスト:Loose Drawing">
Author Image

Saturday, December 5, 2020

システム設計-part3-

はじめに

バックエンドエンジニアのロードマップに沿ってエンジニアとしての自己肯定感を養うシリーズです。

現場で役立つシステム設計の原則を元に記事を作成しています。

業務ロジック

メソッドをロジックの置き場所にする

現場で役立つシステム設計の原則では、“従来"という表現をされていますが、手続き型と呼ばれている設計ではデータクラスと機能クラスに分けて表現します。

その名の通りデータクラスはデータを格納して、機能クラスはデータクラスのデータを判断、加工、計算するといった使い方です。

この手続き型の問題は、拡張するときの変更箇所の特定に時間がかかるということです。

なぜかというと、データクラスが参照できるクラスであれば、アーキテクチャのどのレイヤーにでもロジックが書けてしまうからです。

便利のようには見えますが、先に言った変更箇所の特定に時間がかかるこの方法は最善ではありません。

解決としては、Java 本来のクラスの使い方を踏襲することです。

データとロジックを 1 つのクラスに閉じてしまおうという考え方です。

class PersonName {
   private String firstName;
 
@@ -59,6 +61,6 @@
   }
 }
 

データであるfirstNamelastName、そしてロジック(メソッド)のfullName()が同じクラス内にあります。

こうするとクラス内でデータを扱うことができて変更もこのクラス内で閉じることができます。

また、メソッドはクラス内のインスタンス変数(firstNamelastName)を使って何らかの処理を行う用途で作成します。

クラスが肥大化したら小さく分ける

これもやってしまいがちですが、改修を繰り返していくうちに、クラスが大きくなっていきます。

大きくなったクラスは手続き型同様に変更箇所の特定に時間がかかります。

それを防ぐために、大きくなってしまったクラスを次のルールで細分化します。

  • インスタンス変数とメソッドを対応付ける
  • メソッドが全てのインスタンス変数を使うようになる

細分化したクラスはそれぞれ独立性が高くなるので、別のクラスで使う時にも再利用ができるようになります。

こうした関連の強いデータとロジックをまとめたクラスを凝集度が高いと言います。

凝集度が高いクラスは、変更箇所もそのクラスに閉じることになるので、疎結合になり他への影響が少なくて済みます。

まとめ

時すでに遅しと言いますか、現場での反省点をつらつら振り返ってベストプラクティスを学んでいるという感じです。

次回に活かそうというモチベーションは上がるのでいい復習方法だと感じます。

備考

現場で役立つシステム設計の原則

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/category/system-design/index.html b/posts/category/system-design/index.html index fa1de89e..ea193cf9 100644 --- a/posts/category/system-design/index.html +++ b/posts/category/system-design/index.html @@ -1,12 +1,14 @@ System Design -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/posts/index.html b/posts/index.html index 4acbe8ba..1756452c 100644 --- a/posts/index.html +++ b/posts/index.html @@ -1,12 +1,14 @@ Posts -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/posts/introduction/index.html b/posts/introduction/index.html index 8ccec893..72a62d3e 100644 --- a/posts/introduction/index.html +++ b/posts/introduction/index.html @@ -1,13 +1,15 @@ Introduction -
Author Image

Thursday, May 5, 2022

Introduction

はじめまして!

このページでは、いくつか自己紹介をしたいと思います。

内容に関しては追って更新しますので、しばらくお待ちくださいませ。

※「待てないよ!早く知りたい!」という意見がありましたら、お気軽に Twitter にてご連絡ください。

備考

表紙イラスト:Loose Drawing



\ No newline at end of file diff --git a/posts/page/2/index.html b/posts/page/2/index.html index d68451b4..32f00b13 100644 --- a/posts/page/2/index.html +++ b/posts/page/2/index.html @@ -1,12 +1,14 @@ Posts -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/search/index.html b/search/index.html index 61ce7bd1..3a7382c2 100644 --- a/search/index.html +++ b/search/index.html @@ -1,12 +1,14 @@ Searches -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/tags/aws/index.html b/tags/aws/index.html index 72904b1a..2c1d604f 100644 --- a/tags/aws/index.html +++ b/tags/aws/index.html @@ -1,12 +1,14 @@ AWS -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/tags/basic/index.html b/tags/basic/index.html index 013fcca2..e2dbc495 100644 --- a/tags/basic/index.html +++ b/tags/basic/index.html @@ -1,12 +1,14 @@ Basic -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/tags/computer-science/index.html b/tags/computer-science/index.html index 6b651141..e28e8af8 100644 --- a/tags/computer-science/index.html +++ b/tags/computer-science/index.html @@ -1,12 +1,14 @@ computer-science -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/tags/ddd/index.html b/tags/ddd/index.html index a6197ba6..a3c4b969 100644 --- a/tags/ddd/index.html +++ b/tags/ddd/index.html @@ -1,12 +1,14 @@ ddd -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/tags/development/index.html b/tags/development/index.html index 8a691f27..deafc047 100644 --- a/tags/development/index.html +++ b/tags/development/index.html @@ -1,12 +1,14 @@ Development -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/tags/dynamodb/index.html b/tags/dynamodb/index.html index aa0df331..4528da66 100644 --- a/tags/dynamodb/index.html +++ b/tags/dynamodb/index.html @@ -1,12 +1,14 @@ DynamoDB -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/tags/go/index.html b/tags/go/index.html index 1504cd5e..c9228a14 100644 --- a/tags/go/index.html +++ b/tags/go/index.html @@ -1,12 +1,14 @@ Go -
Hero Image
netパッケージで非推奨のTemporaryメソッドの扱いについて

はじめに こちらはKyash Advent Calendar 2022 の 13 日目の記事です。 今年の 11 月に Kyash に入社しました!サーバサイドチームのueharaです👋 今回はnet/httpパッケージの非推奨メソッドであるTemporary()について、社のメンバーから知見を共有してもらったのでその話をします。 @@ -49,4 +51,4 @@ package main import ( "fmt" "time" "github.com/uh-zz/traning/algorithm/shuffle" ) func main() { // ランダムな要素 n 個のスライス取得 input := shuffle.RandomIntList(n) inputLength := len(input) // マージソート MergeSort(&input, 0, inputLength) } // MergeSort マージソート func MergeSort(input \*[]int, left, right int) { // 要素数1つの場合は抜ける if right-left == 1 { return } // 配列を2つに分けるインデックス middle := left + (right-left)/2 // 配列左側 MergeSort(input, left, middle) // 配列右側 MergeSort(input, middle, right) var buffer []int // 左側と右側をバッファにためる(右側反転) for index := left; index < middle; index++ { buffer = append(buffer, (*input)[index]) } for index := right - 1; index >= middle; index-- { buffer = append(buffer, (*input)[index]) } // マージする scopeLeft := 0 scopeRight := len(buffer) - 1 for index := left; index < right; index++ { if buffer[scopeLeft] <= buffer[scopeRight] { // 左側採用 (*input)[index] = buffer[scopeLeft] scopeLeft++ } else { // 右側採用 (*input)[index] = buffer[scopeRight] scopeRight-- } } } これ考えたのぶっ飛んでるなあと思って Wikipedia 見てたら、考案者がフォン・ノイマンでやっぱりぶっ飛んでた(凄すぎ)

\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/tags/index.html b/tags/index.html index 4fcc3783..61224d7e 100644 --- a/tags/index.html +++ b/tags/index.html @@ -1,12 +1,14 @@ Tags -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/tags/oauth/index.html b/tags/oauth/index.html index cbe05aa0..a7983593 100644 --- a/tags/oauth/index.html +++ b/tags/oauth/index.html @@ -1,12 +1,14 @@ oauth -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/tags/oss/index.html b/tags/oss/index.html index f1b64dd4..ef3729a2 100644 --- a/tags/oss/index.html +++ b/tags/oss/index.html @@ -1,12 +1,14 @@ oss -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/tags/poem/index.html b/tags/poem/index.html index 9616ffc2..8ec29977 100644 --- a/tags/poem/index.html +++ b/tags/poem/index.html @@ -1,12 +1,14 @@ poem -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/tags/security/index.html b/tags/security/index.html index 68c28f03..cef0b96f 100644 --- a/tags/security/index.html +++ b/tags/security/index.html @@ -1,12 +1,14 @@ security -
\ No newline at end of file +Hugo Logo \ No newline at end of file diff --git a/tags/system-design/index.html b/tags/system-design/index.html index 7698b4be..7bda2172 100644 --- a/tags/system-design/index.html +++ b/tags/system-design/index.html @@ -1,12 +1,14 @@ system-design -
\ No newline at end of file +Hugo Logo \ No newline at end of file