diff --git a/404.html b/404.html new file mode 100644 index 0000000..7907128 --- /dev/null +++ b/404.html @@ -0,0 +1 @@ +IASC Book
\ No newline at end of file diff --git a/css/app.eff21fb5.css b/css/app.eff21fb5.css new file mode 100644 index 0000000..ac0f0fe --- /dev/null +++ b/css/app.eff21fb5.css @@ -0,0 +1 @@ +@import url(https://fonts.googleapis.com/css?family=Noto+Sans:400,700);@import url(https://fonts.googleapis.com/css?family=Sanchez:400italic,400);@import url(https://fonts.googleapis.com/css?family=Roboto:100);@media only screen and (max-width:767px){.footer[data-v-b2ede83e]{font-size:.8rem!important}.year[data-v-b2ede83e]{width:30%}.fork-me[data-v-b2ede83e]{width:70%}}.footer[data-v-b2ede83e]{height:2em;bottom:0;color:#aaa;background-color:#333;font-size:.9rem}.github-icon[data-v-b2ede83e]{height:15px;display:inline-block;margin-top:-5px}.app{padding:70px}#app{padding-left:300px;transition:.3s ease}#app.collapsed,#app.onmobile{padding-left:50px}.container{max-width:900px}.sidebar-overlay{position:fixed;width:100%;height:100%;top:0;left:0;background-color:#000;opacity:.5;z-index:900}.bm-menu{background:#6b7a8f;color:#fff}.bm-menu .components{padding:20px 0;border-bottom:1px solid #6b7a8f}.bm-menu ul p{color:#fff;padding:10px}.bm-menu ul li a{padding:10px;font-size:1.1em;display:block}.bm-menu ul li a:hover{color:#7187a7;background:#fff}.bm-menu ul li.active>a,a[aria-expanded=true]{color:#fff;background:#7187a7}.sidebar.v-sidebar-menu .vsm-arrow[data-v-46613048]:after{content:"";font-family:FontAwesome}.sidebar.v-sidebar-menu .collapse-btn[data-v-46613048]:after{content:"";font-family:FontAwesome}body{font-family:Poppins,sans-serif;background:#fafafa}.container{max-width:1140px}p{font-family:Poppins,sans-serif;font-size:1.1em;font-weight:300;line-height:1.7em;color:#999}h1:hover .header-anchor,h2:hover .header-anchor,h3:hover .header-anchor,h4:hover .header-anchor,h5:hover .header-anchor,h6:hover .header-anchor{opacity:1}.header-anchor{opacity:0}a,a:focus,a:hover{color:inherit;text-decoration:none;transition:all .3s}.line{width:100%;height:1px;border-bottom:1px dashed #ddd;margin:40px 0}.title{text-align:center}.wrapper{display:flex;width:100%;align-items:stretch;overflow:hidden;min-height:650px}a[data-toggle=collapse]{position:relative}.dropdown-toggle:after{display:block;position:absolute;top:50%;right:20px;transform:translateY(-50%)}ul ul a{font-size:.9em;padding-left:30px;background:#6b7a8f}.content{width:100%;padding:20px;min-height:100vh;transition:all .3s}.inner-content{margin-bottom:50px;padding-top:25px;color:#333}.inner-content,.inner-content p{font-family:Open Sans,Helvetica Neue,Helvetica,Arial,sans-serif;font-size:20px}.inner-content p{color:#404040}.inner-content a{color:#f7882f}.inner-content a:hover{color:#6b7a8f}.titulo-heading{margin-bottom:15px}.header{padding-left:0;padding-right:0}.center{display:block;margin-left:auto;margin-right:auto;width:100%;max-width:700px}.iasc-image{max-width:600px;margin-top:25px;margin-bottom:25px}.right-flex{display:flex;justify-content:flex-end}.highlight pre code *{white-space:nowrap}.highlight pre{overflow-x:auto}.highlight pre code{white-space:pre}.highlight .hll,.highlight pre,pre{background-color:#f8f8f8;border:1px solid #ccc;padding:6px 10px;border-radius:3px}.highlight .c{color:#998;font-style:italic}.highlight .err{color:#a61717;background-color:#e3d2d2}.highlight .k,.highlight .o{font-weight:700}.highlight .cm{color:#998;font-style:italic}.highlight .cp{color:#999;font-weight:700}.highlight .c1{color:#998;font-style:italic}.highlight .cs{color:#999;font-weight:700;font-style:italic}.highlight .gd{color:#000;background-color:#fdd}.highlight .gd .x{color:#000;background-color:#faa}.highlight .ge{font-style:italic}.highlight .gr{color:#a00}.highlight .gh{color:#999}.highlight .gi{color:#000;background-color:#dfd}.highlight .gi .x{color:#000;background-color:#afa}.highlight .go{color:#888}.highlight .gp{color:#555}.highlight .gs,.highlight .gu{font-weight:700}.highlight .gu{color:purple}.highlight .gt{color:#a00}.highlight .kc,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kt{font-weight:700}.highlight .kt{color:#458}.highlight .m{color:#099}.highlight .s{color:#d14}.highlight .n{color:#333}.highlight .na{color:teal}.highlight .nb{color:#0086b3}.highlight .nc{color:#458;font-weight:700}.highlight .no{color:teal}.highlight .ni{color:purple}.highlight .ne,.highlight .nf{color:#900;font-weight:700}.highlight .nn{color:#555}.highlight .nt{color:navy}.highlight .nv{color:teal}.highlight .ow{font-weight:700}.highlight .w{color:#bbb}.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo{color:#099}.highlight .s2,.highlight .sb,.highlight .sc,.highlight .sd,.highlight .se,.highlight .sh,.highlight .si,.highlight .sx{color:#d14}.highlight .sr{color:#009926}.highlight .s1{color:#d14}.highlight .ss{color:#990073}.highlight .bp{color:#999}.highlight .vc,.highlight .vg,.highlight .vi{color:teal}.highlight .il{color:#099}.highlight .gc{color:#999;background-color:#eaf2f5}blockquote{display:block;position:relative;padding-left:1em;border-left:.2em solid #4d91b3;font-family:Roboto,serif;-webkit-margin-before:1em;margin-block-start:1em;-webkit-margin-after:1em;margin-block-end:1em;-webkit-margin-start:40px;margin-inline-start:40px;-webkit-margin-end:40px;margin-inline-end:40px}blockquote>p{color:#4d91b3!important;font-size:20px;line-height:1.5em;font-weight:100}blockquote>p:after,blockquote>p:before{content:"\201C";font-family:Sanchez;color:#4d91b3}blockquote>p:after{content:"\201D"}cite{display:block;border-width:2px 0;border-style:solid;border-color:#eee;padding:1.5em 0 .5em;margin:1.5em 0;position:relative}cite:before{content:"\201C";position:absolute;top:0;left:50%;transform:translate(-50%,-50%);background:#fff;width:3rem;height:2rem;font:6em/1.08em PT Sans,sans-serif;color:#666;text-align:center}cite:after{content:"\2013 \2003" attr(cite);display:block;text-align:right;font-size:.875em;color:#e74c3c} \ No newline at end of file diff --git a/css/chunk-06ecdd3c.66cbce88.css b/css/chunk-06ecdd3c.66cbce88.css new file mode 100644 index 0000000..96e5c43 --- /dev/null +++ b/css/chunk-06ecdd3c.66cbce88.css @@ -0,0 +1 @@ +.container-background[data-v-501637a8]{background-image:url(../img/home-bg.a6ad161f.jpg);min-height:150px}.titulo[data-v-501637a8]{padding-top:10px;padding-bottom:10px;padding-left:40px;font-family:Open Sans,Helvetica Neue,Helvetica,Arial,sans-serif;color:#fafafa;text-shadow:2px 2px 5px rgba(0,0,0,.5)}.warning{background-color:#ff8;padding:20px;border-radius:6px;margin-bottom:20px;margin-top:20px}.navbar{padding:15px 10px;background:#fff;border:none;border-radius:0;margin-bottom:2px;box-shadow:1px 1px 3px rgba(0,0,0,.1)}.navbar-btn{box-shadow:none;border:none}.navbar-button,.navbar-button:hover{background:#f7882f;color:#fff}.scroll-touch[data-v-488267d0]{-webkit-overflow-scrolling:touch} \ No newline at end of file diff --git a/css/chunk-687c6fec.332edc58.css b/css/chunk-687c6fec.332edc58.css new file mode 100644 index 0000000..7e22c68 --- /dev/null +++ b/css/chunk-687c6fec.332edc58.css @@ -0,0 +1 @@ +@import url(https://fonts.googleapis.com/css?family=Nunito+Sans);.error[data-v-6e5db9d2]{min-height:800px}[data-v-6e5db9d2]:root{--blue:#0e0620;--white:#fff;--orange:#f05800}button[data-v-6e5db9d2]{font-family:Nunito Sans}ul[data-v-6e5db9d2]{list-style-type:none;-webkit-padding-start:35px;padding-inline-start:35px}svg[data-v-6e5db9d2]{width:100%}h1[data-v-6e5db9d2]{font-size:7.5em;margin:15px 0;font-weight:700}h2[data-v-6e5db9d2]{font-weight:700}.btn[data-v-6e5db9d2]{z-index:1;overflow:hidden;background:transparent;position:relative;padding:8px 50px;border-radius:30px;cursor:pointer;font-size:1em;letter-spacing:2px;transition:.2s ease;font-weight:700;margin:5px 0}.btn.orange[data-v-6e5db9d2]{border:4px solid var(--orange);color:var(--blue)}.btn.orange[data-v-6e5db9d2]:before{content:"";position:absolute;left:0;top:0;width:0;height:100%;background:var(--orange);z-index:-1;transition:.2s ease}.btn.orange[data-v-6e5db9d2]:hover{color:var(--white);background:var(--orange);transition:.2s ease}.btn.orange[data-v-6e5db9d2]:hover:before{width:100%}@media screen and (max-width:768px){body[data-v-6e5db9d2]{display:block}.container[data-v-6e5db9d2]{margin-top:70px;margin-bottom:70px}} \ No newline at end of file diff --git a/css/chunk-930b4194.16b7d4ed.css b/css/chunk-930b4194.16b7d4ed.css new file mode 100644 index 0000000..f14ecc4 --- /dev/null +++ b/css/chunk-930b4194.16b7d4ed.css @@ -0,0 +1 @@ +.wrap-banner[data-v-7af6ec48]{position:relative;align-items:center;display:flex;height:100%;justify-content:center;min-height:300px}.main-title[data-v-7af6ec48]{color:#fff;z-index:999}.main-title h2[data-v-7af6ec48]{font-size:5rem;font-family:Teko,sans-serif;text-shadow:5px 5px #000;text-transform:uppercase;margin:0}.main-title p.subtitle[data-v-7af6ec48]{color:#fff;font-size:1rem;font-family:Teko,sans-serif;text-shadow:1px 1px #000;padding-left:5px;margin:0}.titulo-heading[data-v-7af6ec48]{margin-bottom:15px}.particle-js[data-v-7af6ec48]{background-image:url(../img/iasc-home.9ad3dd15.jpg);background-size:cover;position:absolute;top:0;left:0;width:100%;height:100%}.navbar{padding:15px 10px;background:#fff;border:none;border-radius:0;margin-bottom:2px;box-shadow:1px 1px 3px rgba(0,0,0,.1)}.navbar-btn{box-shadow:none;border:none}.navbar-button,.navbar-button:hover{background:#f7882f;color:#fff} \ No newline at end of file diff --git a/css/chunk-vendors.8c96c656.css b/css/chunk-vendors.8c96c656.css new file mode 100644 index 0000000..bdd770c --- /dev/null +++ b/css/chunk-vendors.8c96c656.css @@ -0,0 +1,10 @@ +/*! + * Bootstrap v4.6.0 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors + * Copyright 2011-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,:after,:before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,Liberation Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{font-style:normal;line-height:inherit}address,dl,ol,ul{margin-bottom:1rem}dl,ol,ul{margin-top:0}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{border-style:none}img,svg{vertical-align:middle}svg{overflow:hidden}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem}.display-1,.display-2{font-weight:300;line-height:1.2}.display-2{font-size:5.5rem}.display-3{font-size:4.5rem}.display-3,.display-4{font-weight:300;line-height:1.2}.display-4{font-size:3.5rem}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-inline,.list-unstyled{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer:before{content:"\2014\00A0"}.img-fluid,.img-thumbnail{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:flex;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col-auto,.col-lg,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-auto,.col-md,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-md-auto,.col-sm,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-1>*{flex:0 0 100%;max-width:100%}.row-cols-2>*{flex:0 0 50%;max-width:50%}.row-cols-3>*{flex:0 0 33.333333%;max-width:33.333333%}.row-cols-4>*{flex:0 0 25%;max-width:25%}.row-cols-5>*{flex:0 0 20%;max-width:20%}.row-cols-6>*{flex:0 0 16.666667%;max-width:16.666667%}.col-auto{flex:0 0 auto;width:auto;max-width:100%}.col-1{flex:0 0 8.333333%;max-width:8.333333%}.col-2{flex:0 0 16.666667%;max-width:16.666667%}.col-3{flex:0 0 25%;max-width:25%}.col-4{flex:0 0 33.333333%;max-width:33.333333%}.col-5{flex:0 0 41.666667%;max-width:41.666667%}.col-6{flex:0 0 50%;max-width:50%}.col-7{flex:0 0 58.333333%;max-width:58.333333%}.col-8{flex:0 0 66.666667%;max-width:66.666667%}.col-9{flex:0 0 75%;max-width:75%}.col-10{flex:0 0 83.333333%;max-width:83.333333%}.col-11{flex:0 0 91.666667%;max-width:91.666667%}.col-12{flex:0 0 100%;max-width:100%}.order-first{order:-1}.order-last{order:13}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-sm-1>*{flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{flex:0 0 33.333333%;max-width:33.333333%}.row-cols-sm-4>*{flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{flex:0 0 16.666667%;max-width:16.666667%}.col-sm-auto{flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{flex:0 0 25%;max-width:25%}.col-sm-4{flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{flex:0 0 50%;max-width:50%}.col-sm-7{flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{flex:0 0 75%;max-width:75%}.col-sm-10{flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{flex:0 0 100%;max-width:100%}.order-sm-first{order:-1}.order-sm-last{order:13}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-md-1>*{flex:0 0 100%;max-width:100%}.row-cols-md-2>*{flex:0 0 50%;max-width:50%}.row-cols-md-3>*{flex:0 0 33.333333%;max-width:33.333333%}.row-cols-md-4>*{flex:0 0 25%;max-width:25%}.row-cols-md-5>*{flex:0 0 20%;max-width:20%}.row-cols-md-6>*{flex:0 0 16.666667%;max-width:16.666667%}.col-md-auto{flex:0 0 auto;width:auto;max-width:100%}.col-md-1{flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{flex:0 0 25%;max-width:25%}.col-md-4{flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{flex:0 0 50%;max-width:50%}.col-md-7{flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{flex:0 0 75%;max-width:75%}.col-md-10{flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{flex:0 0 100%;max-width:100%}.order-md-first{order:-1}.order-md-last{order:13}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-lg-1>*{flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{flex:0 0 33.333333%;max-width:33.333333%}.row-cols-lg-4>*{flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{flex:0 0 16.666667%;max-width:16.666667%}.col-lg-auto{flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{flex:0 0 25%;max-width:25%}.col-lg-4{flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{flex:0 0 50%;max-width:50%}.col-lg-7{flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{flex:0 0 75%;max-width:75%}.col-lg-10{flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{flex:0 0 100%;max-width:100%}.order-lg-first{order:-1}.order-lg-last{order:13}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-xl-1>*{flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{flex:0 0 33.333333%;max-width:33.333333%}.row-cols-xl-4>*{flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{flex:0 0 16.666667%;max-width:16.666667%}.col-xl-auto{flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{flex:0 0 25%;max-width:25%}.col-xl-4{flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{flex:0 0 50%;max-width:50%}.col-xl-7{flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{flex:0 0 75%;max-width:75%}.col-xl-10{flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{flex:0 0 100%;max-width:100%}.order-xl-first{order:-1}.order-xl-last{order:13}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered,.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover,.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover,.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover,.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover,.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover,.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover,.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover,.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th,.table-hover .table-active:hover,.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:hsla(0,0%,100%,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:hsla(0,0%,100%,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size],textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:flex;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:inline-flex;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.form-row>.col>.valid-tooltip,.form-row>[class*=col-]>.valid-tooltip{left:5px}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label:before,.was-validated .custom-control-input:valid~.custom-control-label:before{border-color:#28a745}.custom-control-input.is-valid:checked~.custom-control-label:before,.was-validated .custom-control-input:valid:checked~.custom-control-label:before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label:before,.was-validated .custom-control-input:valid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label:before,.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.form-row>.col>.invalid-tooltip,.form-row>[class*=col-]>.invalid-tooltip{left:5px}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3E%3C/svg%3E") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label:before,.was-validated .custom-control-input:invalid~.custom-control-label:before{border-color:#dc3545}.custom-control-input.is-invalid:checked~.custom-control-label:before,.was-validated .custom-control-input:invalid:checked~.custom-control-label:before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label:before,.was-validated .custom-control-input:invalid:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label:before,.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label:before,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:flex;flex-flow:row wrap;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{justify-content:center}.form-inline .form-group,.form-inline label{display:flex;align-items:center;margin-bottom:0}.form-inline .form-group{flex:0 0 auto;flex-flow:row wrap}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:flex;align-items:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{align-items:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary.focus,.btn-primary:focus,.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary.focus,.btn-secondary:focus,.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success.focus,.btn-success:focus,.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info.focus,.btn-info:focus,.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning.focus,.btn-warning:focus,.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger.focus,.btn-danger:focus,.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light.focus,.btn-light:focus,.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark.focus,.btn-dark:focus,.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3}.btn-link.focus,.btn-link:focus,.btn-link:hover{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty:after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-toggle:after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";display:none}.dropleft .dropdown-toggle:before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty:after{margin-left:0}.dropleft .dropdown-toggle:before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#e9ecef}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#adb5bd;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;flex:1 1 auto}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split:after,.dropright .dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after{margin-left:0}.dropleft .dropdown-toggle-split:before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio],.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;flex:1 1 auto;width:1%;min-width:0;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:flex;align-items:center}.input-group>.custom-file:not(:first-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label:after,.input-group.has-validation>.custom-select:nth-last-child(n+3),.input-group.has-validation>.form-control:nth-last-child(n+3),.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label:after,.input-group:not(.has-validation)>.custom-select:not(:last-child),.input-group:not(.has-validation)>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-append,.input-group-prepend{display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.btn,.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.input-group-text,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;z-index:1;display:block;min-height:1.5rem;padding-left:1.5rem;-webkit-print-color-adjust:exact;color-adjust:exact}.custom-control-inline{display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label:before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label:before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label:before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label:before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label:before,.custom-control-input[disabled]~.custom-control-label:before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label:before{pointer-events:none;background-color:#fff;border:1px solid #adb5bd}.custom-control-label:after,.custom-control-label:before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:""}.custom-control-label:after{background:50%/50% 50% no-repeat}.custom-checkbox .custom-control-label:before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label:before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label:before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label:before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label:after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label:after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label:after{background-color:#fff;transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label:before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center/8px 10px no-repeat;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{display:inline-block;margin-bottom:0}.custom-file,.custom-file-input{position:relative;width:100%;height:calc(1.5em + .75rem + 2px)}.custom-file-input{z-index:2;margin:0;overflow:hidden;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label:after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]:after{content:attr(data-browse)}.custom-file-label{left:0;z-index:1;height:calc(1.5em + .75rem + 2px);overflow:hidden;font-weight:400;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label,.custom-file-label:after{position:absolute;top:0;right:0;padding:.375rem .75rem;line-height:1.5;color:#495057}.custom-file-label:after{bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower,.custom-range::-ms-fill-upper{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label:before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label:before,.custom-file-label,.custom-select{transition:none}}.nav{display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{margin-bottom:-1px;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;padding:.5rem 1rem}.navbar,.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:50%/100% 100% no-repeat}.navbar-nav-scroll{max-height:75vh;overflow-y:auto}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{flex-wrap:nowrap}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{flex-wrap:nowrap}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{flex-wrap:nowrap}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{flex-wrap:nowrap}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{flex-wrap:nowrap}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand,.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand,.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:hsla(0,0%,100%,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:hsla(0,0%,100%,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:hsla(0,0%,100%,.5);border-color:hsla(0,0%,100%,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:hsla(0,0%,100%,.5)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:flex;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem}.card-subtitle,.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-bottom:-.75rem;border-bottom:0}.card-header-pills,.card-header-tabs{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem;border-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom,.card-img-top{flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{display:flex;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-moz-column-count:3;column-count:3;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:flex;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item:before{float:left;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover:before{text-decoration:underline;text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;z-index:2;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{0%{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{0%{background-position:1rem 0}to{background-position:0 0}}.progress{height:1rem;line-height:0;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress,.progress-bar{display:flex;overflow:hidden}.progress-bar{flex-direction:column;justify-content:center;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:flex;align-items:flex-start}.media-body{flex:1}.list-group{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0}a.close.disabled{pointer-events:none}.toast{flex-basis:350px;max-width:350px;font-size:.875rem;background-color:hsla(0,0%,100%,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:flex;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:hsla(0,0%,100%,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translateY(-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered:before{display:block;height:calc(100vh - 1rem);height:-webkit-min-content;height:-moz-min-content;height:min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{flex-direction:column;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable:before{content:none}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:flex;align-items:flex-start;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;padding:1rem}.modal-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered:before{height:calc(100vh - 3.5rem);height:-webkit-min-content;height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,Liberation Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow:before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow:before,.bs-tooltip-top .arrow:before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow:before,.bs-tooltip-right .arrow:before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.bs-tooltip-bottom .arrow:before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow:before,.bs-tooltip-left .arrow:before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{top:0;left:0;z-index:1060;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,Liberation Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover,.popover .arrow{position:absolute;display:block}.popover .arrow{width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow:after,.popover .arrow:before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow:before,.bs-popover-top>.arrow:before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow:after,.bs-popover-top>.arrow:after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow:before,.bs-popover-right>.arrow:before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow:after,.bs-popover-right>.arrow:after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow:before,.bs-popover-bottom>.arrow:before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow:after,.bs-popover-bottom>.arrow:after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header:before,.bs-popover-bottom .popover-header:before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow:before,.bs-popover-left>.arrow:before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow:after,.bs-popover-left>.arrow:after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner:after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:50%/100% 100% no-repeat}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8'%3E%3Cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:flex;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{transform:rotate(1turn)}}@keyframes spinner-border{to{transform:rotate(1turn)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:spinner-border .75s linear infinite;animation:spinner-border .75s linear infinite}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner-grow .75s linear infinite;animation:spinner-grow .75s linear infinite}.spinner-grow-sm{width:1rem;height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{-webkit-animation-duration:1.5s;animation-duration:1.5s}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important}.rounded-right,.rounded-top{border-top-right-radius:.25rem!important}.rounded-bottom,.rounded-right{border-bottom-right-radius:.25rem!important}.rounded-bottom,.rounded-left{border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix:after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive:before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9:before{padding-top:42.857143%}.embed-responsive-16by9:before{padding-top:56.25%}.embed-responsive-4by3:before{padding-top:75%}.embed-responsive-1by1:before{padding-top:100%}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-fill{flex:1 1 auto!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}@media (min-width:576px){.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}}@media (min-width:768px){.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;-ms-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:sticky!important}.fixed-top{top:0}.fixed-bottom,.fixed-top{position:fixed;right:0;left:0;z-index:1030}.fixed-bottom{bottom:0}@supports (position:sticky){.sticky-top{position:sticky;top:0;z-index:1020}}.sr-only{white-space:nowrap}.sr-only-focusable:active,.sr-only-focusable:focus{white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link:after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:transparent}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:hsla(0,0%,100%,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-break:break-word!important;word-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,:after,:before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]:after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}.container,body{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}}.hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#d14}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#009926}.hljs-bullet,.hljs-symbol{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.v-sidebar-menu{position:fixed;top:0;left:0;bottom:0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;z-index:999;width:100%;text-align:left;-webkit-transition:max-width .3s ease;transition:max-width .3s ease}.v-sidebar-menu,.v-sidebar-menu *{-webkit-box-sizing:border-box;box-sizing:border-box}.v-sidebar-menu .vsm--scroll-wrapper{height:100%;overflow-y:auto;overflow-x:hidden}.v-sidebar-menu .vsm--dropdown>.vsm--list{padding:5px}.v-sidebar-menu .vsm--item{position:relative;display:block;width:100%;white-space:nowrap}.v-sidebar-menu .vsm--link{cursor:pointer;position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:16px;font-weight:400;padding:10px;line-height:30px;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:20;-webkit-transition:all .3s ease;transition:all .3s ease}.v-sidebar-menu .vsm--link_active,.v-sidebar-menu .vsm--link_exact-active{font-weight:600}.v-sidebar-menu .vsm--link_disabled{opacity:.4;pointer-events:none}.v-sidebar-menu .vsm--link_level-1 .vsm--icon{height:30px;line-height:30px;width:30px;-ms-flex-negative:0;flex-shrink:0;text-align:center;border-radius:3px}.v-sidebar-menu .vsm--icon{display:inline-block;margin-right:10px}.v-sidebar-menu .vsm--title{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.v-sidebar-menu .vsm--arrow{width:30px;text-align:center;font-style:normal;font-weight:900;-webkit-transition:-webkit-transform .3s ease;transition:-webkit-transform .3s ease;transition:transform .3s ease;transition:transform .3s ease,-webkit-transform .3s ease}.v-sidebar-menu .vsm--arrow:after{content:"\f105";font-family:Font Awesome\ 5 Free}.v-sidebar-menu .vsm--arrow_open{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.v-sidebar-menu .vsm--arrow_slot:after{display:none}.v-sidebar-menu .vsm--header{font-size:14px;font-weight:600;padding:10px;white-space:nowrap;text-transform:uppercase}.v-sidebar-menu .vsm--badge_default{padding:0 6px;font-size:12px;border-radius:3px;height:20px;line-height:20px;font-weight:600;text-transform:uppercase}.v-sidebar-menu .vsm--toggle-btn{display:block;text-align:center;font-style:normal;font-weight:900;height:50px;cursor:pointer;border:none;width:100%}.v-sidebar-menu .vsm--toggle-btn:after{content:"\f337";font-family:Font Awesome\ 5 Free}.v-sidebar-menu .vsm--toggle-btn_slot:after{display:none}.v-sidebar-menu.vsm_collapsed .vsm--link_level-1.vsm--link_hover,.v-sidebar-menu.vsm_collapsed .vsm--link_level-1:hover{background-color:transparent!important}.v-sidebar-menu.vsm_rtl{right:0;left:inherit;text-align:right;direction:rtl}.v-sidebar-menu.vsm_rtl .vsm--icon{margin-left:10px;margin-right:0}.v-sidebar-menu.vsm_relative{position:relative;height:100%}.v-sidebar-menu .expand-enter-active,.v-sidebar-menu .expand-leave-active{-webkit-transition:height .3s ease;transition:height .3s ease;overflow:hidden}.v-sidebar-menu .expand-enter,.v-sidebar-menu .expand-leave-to{height:0!important}.v-sidebar-menu .slide-animation-enter-active,.v-sidebar-menu .slide-animation-leave-active{-webkit-transition:width .3s ease;transition:width .3s ease}.v-sidebar-menu .slide-animation-enter,.v-sidebar-menu .slide-animation-leave-to{width:0!important}.v-sidebar-menu .fade-animation-enter-active,.v-sidebar-menu .fade-animation-leave-active{-webkit-transition:opacity .3s ease,visibility .3s ease;transition:opacity .3s ease,visibility .3s ease}.v-sidebar-menu .fade-animation-enter,.v-sidebar-menu .fade-animation-leave-to{opacity:0!important;visibility:hidden!important}.v-sidebar-menu .vsm--mobile-item>.vsm--item{padding:0!important;margin:0!important}.v-sidebar-menu .vsm--mobile-item>.vsm--item>.vsm--link{margin:0!important;background-color:transparent!important;line-height:30px!important}.v-sidebar-menu{background-color:#2a2a2e}.v-sidebar-menu .vsm--link{color:#fff}.v-sidebar-menu .vsm--link_level-1.vsm--link_active,.v-sidebar-menu .vsm--link_level-1.vsm--link_exact-active{-webkit-box-shadow:3px 0 0 0 #4285f4 inset;box-shadow:inset 3px 0 0 0 #4285f4}.v-sidebar-menu .vsm--link_level-1 .vsm--icon{background-color:#1e1e21}.v-sidebar-menu .vsm--link:hover,.v-sidebar-menu .vsm--link_hover{background-color:rgba(30,30,33,.5)}.v-sidebar-menu .vsm--link_mobile-item,.v-sidebar-menu .vsm--link_mobile-item.vsm--link_hover,.v-sidebar-menu .vsm--link_mobile-item:hover{color:#fff}.v-sidebar-menu.vsm_collapsed .vsm--link_level-1.vsm--link_hover .vsm--icon,.v-sidebar-menu.vsm_collapsed .vsm--link_level-1:hover .vsm--icon{color:#fff;background-color:#4285f4}.v-sidebar-menu .vsm--dropdown .vsm--list{background-color:#36363b}.v-sidebar-menu .vsm--mobile-bg{background-color:#4285f4}.v-sidebar-menu.vsm_expanded .vsm--item_open .vsm--link_level-1{color:#fff;background-color:#4285f4}.v-sidebar-menu.vsm_expanded .vsm--item_open .vsm--link_level-1 .vsm--icon{background-color:#4285f4}.v-sidebar-menu.vsm_rtl .vsm--link_level-1.vsm--link_active,.v-sidebar-menu.vsm_rtl .vsm--link_level-1.vsm--link_exact-active{-webkit-box-shadow:-3px 0 0 0 #4285f4 inset;box-shadow:inset -3px 0 0 0 #4285f4}.v-sidebar-menu .vsm--header{color:hsla(0,0%,100%,.7)}.v-sidebar-menu .vsm--badge_default,.v-sidebar-menu .vsm--toggle-btn{color:#fff;background-color:#1e1e21}.v-sidebar-menu.vsm_white-theme{background-color:#fff}.v-sidebar-menu.vsm_white-theme .vsm--link{color:#262626}.v-sidebar-menu.vsm_white-theme .vsm--link_level-1.vsm--link_active,.v-sidebar-menu.vsm_white-theme .vsm--link_level-1.vsm--link_exact-active{-webkit-box-shadow:3px 0 0 0 #4285f4 inset;box-shadow:inset 3px 0 0 0 #4285f4}.v-sidebar-menu.vsm_white-theme .vsm--link_level-1.vsm--link_active .vsm--icon,.v-sidebar-menu.vsm_white-theme .vsm--link_level-1.vsm--link_exact-active .vsm--icon{color:#fff;background-color:#262626}.v-sidebar-menu.vsm_white-theme .vsm--link_level-1 .vsm--icon{background-color:#bbc5d6}.v-sidebar-menu.vsm_white-theme .vsm--link:hover,.v-sidebar-menu.vsm_white-theme .vsm--link_hover{background-color:hsla(0,0%,94.9%,.5)}.v-sidebar-menu.vsm_white-theme .vsm--link_mobile-item,.v-sidebar-menu.vsm_white-theme .vsm--link_mobile-item.vsm--link_hover,.v-sidebar-menu.vsm_white-theme .vsm--link_mobile-item:hover{color:#fff}.v-sidebar-menu.vsm_white-theme.vsm_collapsed .vsm--link_level-1.vsm--link_hover .vsm--icon,.v-sidebar-menu.vsm_white-theme.vsm_collapsed .vsm--link_level-1:hover .vsm--icon{color:#fff;background-color:#4285f4}.v-sidebar-menu.vsm_white-theme .vsm--dropdown .vsm--list{background-color:#e3e3e3}.v-sidebar-menu.vsm_white-theme .vsm--mobile-bg{background-color:#4285f4}.v-sidebar-menu.vsm_white-theme.vsm_expanded .vsm--item_open .vsm--link_level-1{color:#fff;background-color:#4285f4}.v-sidebar-menu.vsm_white-theme.vsm_expanded .vsm--item_open .vsm--link_level-1 .vsm--icon{background-color:#4285f4}.v-sidebar-menu.vsm_white-theme.vsm_rtl .vsm--link_level-1.vsm--link_active,.v-sidebar-menu.vsm_white-theme.vsm_rtl .vsm--link_level-1.vsm--link_exact-active{-webkit-box-shadow:-3px 0 0 0 #4285f4 inset;box-shadow:inset -3px 0 0 0 #4285f4}.v-sidebar-menu.vsm_white-theme .vsm--header{color:rgba(38,38,38,.7)}.v-sidebar-menu.vsm_white-theme .vsm--badge_default,.v-sidebar-menu.vsm_white-theme .vsm--toggle-btn{color:#262626;background-color:#f2f2f2} +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:FontAwesome;src:url(../fonts/fontawesome-webfont.674f50d2.eot);src:url(../fonts/fontawesome-webfont.674f50d2.eot?#iefix&v=4.7.0) format("embedded-opentype"),url(../fonts/fontawesome-webfont.af7ae505.woff2) format("woff2"),url(../fonts/fontawesome-webfont.fee66e71.woff) format("woff"),url(../fonts/fontawesome-webfont.b06871f2.ttf) format("truetype"),url(../img/fontawesome-webfont.912ec66d.svg#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857em;text-align:center}.fa-ul{padding-left:0;margin-left:2.1428571429em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.1428571429em;width:2.1428571429em;top:.1428571429em;text-align:center}.fa-li.fa-lg{left:-1.8571428571em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{transform:rotate(0deg)}to{transform:rotate(359deg)}}@keyframes fa-spin{0%{transform:rotate(0deg)}to{transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before{content:""}.fa-check-circle:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before{content:""}.fa-arrow-circle-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} \ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..5584a3f Binary files /dev/null and b/favicon.ico differ diff --git a/fonts/fontawesome-webfont.674f50d2.eot b/fonts/fontawesome-webfont.674f50d2.eot new file mode 100644 index 0000000..e9f60ca Binary files /dev/null and b/fonts/fontawesome-webfont.674f50d2.eot differ diff --git a/fonts/fontawesome-webfont.af7ae505.woff2 b/fonts/fontawesome-webfont.af7ae505.woff2 new file mode 100644 index 0000000..4d13fc6 Binary files /dev/null and b/fonts/fontawesome-webfont.af7ae505.woff2 differ diff --git a/fonts/fontawesome-webfont.b06871f2.ttf b/fonts/fontawesome-webfont.b06871f2.ttf new file mode 100644 index 0000000..35acda2 Binary files /dev/null and b/fonts/fontawesome-webfont.b06871f2.ttf differ diff --git a/fonts/fontawesome-webfont.fee66e71.woff b/fonts/fontawesome-webfont.fee66e71.woff new file mode 100644 index 0000000..400014a Binary files /dev/null and b/fonts/fontawesome-webfont.fee66e71.woff differ diff --git a/img/0.a5ade99c.png b/img/0.a5ade99c.png new file mode 100644 index 0000000..680f9d2 Binary files /dev/null and b/img/0.a5ade99c.png differ diff --git a/img/1.1097a9e9.png b/img/1.1097a9e9.png new file mode 100644 index 0000000..5929862 Binary files /dev/null and b/img/1.1097a9e9.png differ diff --git a/img/1.1ca539fd.png b/img/1.1ca539fd.png new file mode 100644 index 0000000..35ecce9 Binary files /dev/null and b/img/1.1ca539fd.png differ diff --git a/img/2.3c408fb8.png b/img/2.3c408fb8.png new file mode 100644 index 0000000..fe82acc Binary files /dev/null and b/img/2.3c408fb8.png differ diff --git a/img/3.ae7e51dc.png b/img/3.ae7e51dc.png new file mode 100644 index 0000000..7e21a40 Binary files /dev/null and b/img/3.ae7e51dc.png differ diff --git a/img/actors.12e50190.png b/img/actors.12e50190.png new file mode 100644 index 0000000..5231b03 Binary files /dev/null and b/img/actors.12e50190.png differ diff --git a/img/auto_homero.801407e0.png b/img/auto_homero.801407e0.png new file mode 100644 index 0000000..1f1c814 Binary files /dev/null and b/img/auto_homero.801407e0.png differ diff --git a/img/basic-event-loop.8b8923fb.png b/img/basic-event-loop.8b8923fb.png new file mode 100644 index 0000000..c508d9c Binary files /dev/null and b/img/basic-event-loop.8b8923fb.png differ diff --git a/img/child-processes.bc85fc35.svg b/img/child-processes.bc85fc35.svg new file mode 100644 index 0000000..5a17276 --- /dev/null +++ b/img/child-processes.bc85fc35.svg @@ -0,0 +1,963 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/img/complete-event-loop.b59ad9a8.png b/img/complete-event-loop.b59ad9a8.png new file mode 100644 index 0000000..834d2bd Binary files /dev/null and b/img/complete-event-loop.b59ad9a8.png differ diff --git a/img/compose.41295c5b.png b/img/compose.41295c5b.png new file mode 100644 index 0000000..7eb7bf4 Binary files /dev/null and b/img/compose.41295c5b.png differ diff --git a/img/contenedores_diagrama.858e4572.png b/img/contenedores_diagrama.858e4572.png new file mode 100644 index 0000000..bf0a361 Binary files /dev/null and b/img/contenedores_diagrama.858e4572.png differ diff --git a/img/control_plane.96aa0ab2.png b/img/control_plane.96aa0ab2.png new file mode 100644 index 0000000..0d704fd Binary files /dev/null and b/img/control_plane.96aa0ab2.png differ diff --git a/img/docker.16d69f9e.png b/img/docker.16d69f9e.png new file mode 100644 index 0000000..1b6031e Binary files /dev/null and b/img/docker.16d69f9e.png differ diff --git a/img/docker_intro.1a2ca7e8.png b/img/docker_intro.1a2ca7e8.png new file mode 100644 index 0000000..15db11d Binary files /dev/null and b/img/docker_intro.1a2ca7e8.png differ diff --git a/img/fiber_status.9c3f958e.png b/img/fiber_status.9c3f958e.png new file mode 100644 index 0000000..20c88de Binary files /dev/null and b/img/fiber_status.9c3f958e.png differ diff --git a/img/fiversvsthreads.04634cfb.png b/img/fiversvsthreads.04634cfb.png new file mode 100644 index 0000000..4a6b16e Binary files /dev/null and b/img/fiversvsthreads.04634cfb.png differ diff --git a/img/fontawesome-webfont.912ec66d.svg b/img/fontawesome-webfont.912ec66d.svg new file mode 100644 index 0000000..855c845 --- /dev/null +++ b/img/fontawesome-webfont.912ec66d.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/img/github_logo.ec3a60c8.png b/img/github_logo.ec3a60c8.png new file mode 100644 index 0000000..9490ffc Binary files /dev/null and b/img/github_logo.ec3a60c8.png differ diff --git a/img/guilds_0.c4d25035.png b/img/guilds_0.c4d25035.png new file mode 100644 index 0000000..c21ab5a Binary files /dev/null and b/img/guilds_0.c4d25035.png differ diff --git a/img/guilds_1.8b5d1a6a.png b/img/guilds_1.8b5d1a6a.png new file mode 100644 index 0000000..ae9f887 Binary files /dev/null and b/img/guilds_1.8b5d1a6a.png differ diff --git a/img/guilds_2.3132ef15.png b/img/guilds_2.3132ef15.png new file mode 100644 index 0000000..e1e912c Binary files /dev/null and b/img/guilds_2.3132ef15.png differ diff --git a/img/guilds_3.07dd8c32.png b/img/guilds_3.07dd8c32.png new file mode 100644 index 0000000..a89736e Binary files /dev/null and b/img/guilds_3.07dd8c32.png differ diff --git a/img/guilds_4.c4345142.png b/img/guilds_4.c4345142.png new file mode 100644 index 0000000..af34cba Binary files /dev/null and b/img/guilds_4.c4345142.png differ diff --git a/img/guilds_5.d4b578a0.png b/img/guilds_5.d4b578a0.png new file mode 100644 index 0000000..1bfb1b5 Binary files /dev/null and b/img/guilds_5.d4b578a0.png differ diff --git a/img/guilds_6.bdc76127.png b/img/guilds_6.bdc76127.png new file mode 100644 index 0000000..64945ed Binary files /dev/null and b/img/guilds_6.bdc76127.png differ diff --git a/img/guilds_7.33caabec.png b/img/guilds_7.33caabec.png new file mode 100644 index 0000000..2f66a1b Binary files /dev/null and b/img/guilds_7.33caabec.png differ diff --git a/img/guilds_8.dc175235.png b/img/guilds_8.dc175235.png new file mode 100644 index 0000000..5f45c47 Binary files /dev/null and b/img/guilds_8.dc175235.png differ diff --git a/img/home-bg.a6ad161f.jpg b/img/home-bg.a6ad161f.jpg new file mode 100644 index 0000000..85d02c8 Binary files /dev/null and b/img/home-bg.a6ad161f.jpg differ diff --git a/img/homer-grill.b73187de.gif b/img/homer-grill.b73187de.gif new file mode 100644 index 0000000..b61f72f Binary files /dev/null and b/img/homer-grill.b73187de.gif differ diff --git a/img/homero-movil.8fe1d20e.jpg b/img/homero-movil.8fe1d20e.jpg new file mode 100644 index 0000000..a26d2c6 Binary files /dev/null and b/img/homero-movil.8fe1d20e.jpg differ diff --git a/img/iasc-home.9ad3dd15.jpg b/img/iasc-home.9ad3dd15.jpg new file mode 100644 index 0000000..c312de8 Binary files /dev/null and b/img/iasc-home.9ad3dd15.jpg differ diff --git a/img/iasc-home.jpg b/img/iasc-home.jpg new file mode 100644 index 0000000..c312de8 Binary files /dev/null and b/img/iasc-home.jpg differ diff --git a/img/image1.d0c1cc9e.png b/img/image1.d0c1cc9e.png new file mode 100644 index 0000000..5420334 Binary files /dev/null and b/img/image1.d0c1cc9e.png differ diff --git a/img/image10.4683f863.png b/img/image10.4683f863.png new file mode 100644 index 0000000..55f324c Binary files /dev/null and b/img/image10.4683f863.png differ diff --git a/img/image11.a37c77f8.jpg b/img/image11.a37c77f8.jpg new file mode 100644 index 0000000..b1c2c03 Binary files /dev/null and b/img/image11.a37c77f8.jpg differ diff --git a/img/image12.f374f4f9.png b/img/image12.f374f4f9.png new file mode 100644 index 0000000..8b98be5 Binary files /dev/null and b/img/image12.f374f4f9.png differ diff --git a/img/image13.aa9b12a8.png b/img/image13.aa9b12a8.png new file mode 100644 index 0000000..717838a Binary files /dev/null and b/img/image13.aa9b12a8.png differ diff --git a/img/image14.3e72e131.png b/img/image14.3e72e131.png new file mode 100644 index 0000000..478256b Binary files /dev/null and b/img/image14.3e72e131.png differ diff --git a/img/image2.5a8685e5.png b/img/image2.5a8685e5.png new file mode 100644 index 0000000..d0ff26d Binary files /dev/null and b/img/image2.5a8685e5.png differ diff --git a/img/image4.132661ac.png b/img/image4.132661ac.png new file mode 100644 index 0000000..fac61ac Binary files /dev/null and b/img/image4.132661ac.png differ diff --git a/img/image5.db96ab35.png b/img/image5.db96ab35.png new file mode 100644 index 0000000..cda4c11 Binary files /dev/null and b/img/image5.db96ab35.png differ diff --git a/img/image7.bcf1a28f.png b/img/image7.bcf1a28f.png new file mode 100644 index 0000000..945a945 Binary files /dev/null and b/img/image7.bcf1a28f.png differ diff --git a/img/image8.fd1bffb3.png b/img/image8.fd1bffb3.png new file mode 100644 index 0000000..70dcf0c Binary files /dev/null and b/img/image8.fd1bffb3.png differ diff --git a/img/image9.44cb6ec8.png b/img/image9.44cb6ec8.png new file mode 100644 index 0000000..293b20d Binary files /dev/null and b/img/image9.44cb6ec8.png differ diff --git a/img/in_rod_we_trust.61a8e21b.png b/img/in_rod_we_trust.61a8e21b.png new file mode 100644 index 0000000..8edb05a Binary files /dev/null and b/img/in_rod_we_trust.61a8e21b.png differ diff --git a/img/monolito.fb888a05.jpg b/img/monolito.fb888a05.jpg new file mode 100644 index 0000000..cffd720 Binary files /dev/null and b/img/monolito.fb888a05.jpg differ diff --git a/img/node-system.391f5210.png b/img/node-system.391f5210.png new file mode 100644 index 0000000..bf3ff72 Binary files /dev/null and b/img/node-system.391f5210.png differ diff --git a/img/pisa_tower.37378781.jpeg b/img/pisa_tower.37378781.jpeg new file mode 100644 index 0000000..a4f7e00 Binary files /dev/null and b/img/pisa_tower.37378781.jpeg differ diff --git a/img/principio-kiss.6dc64b42.jpg b/img/principio-kiss.6dc64b42.jpg new file mode 100644 index 0000000..21220a4 Binary files /dev/null and b/img/principio-kiss.6dc64b42.jpg differ diff --git a/img/puma-general-arch.4d403982.png b/img/puma-general-arch.4d403982.png new file mode 100644 index 0000000..89e26bd Binary files /dev/null and b/img/puma-general-arch.4d403982.png differ diff --git a/img/secret.4995711d.jpg b/img/secret.4995711d.jpg new file mode 100644 index 0000000..166ee4d Binary files /dev/null and b/img/secret.4995711d.jpg differ diff --git a/img/service-mesh-generic-topology_social.74defb07.png b/img/service-mesh-generic-topology_social.74defb07.png new file mode 100644 index 0000000..24b70bc Binary files /dev/null and b/img/service-mesh-generic-topology_social.74defb07.png differ diff --git a/img/service-mesh.c04f75ea.png b/img/service-mesh.c04f75ea.png new file mode 100644 index 0000000..6ea4acc Binary files /dev/null and b/img/service-mesh.c04f75ea.png differ diff --git a/img/swarm.71963495.png b/img/swarm.71963495.png new file mode 100644 index 0000000..5b8a3dd Binary files /dev/null and b/img/swarm.71963495.png differ diff --git a/img/v8.826badb9.png b/img/v8.826badb9.png new file mode 100644 index 0000000..910a416 Binary files /dev/null and b/img/v8.826badb9.png differ diff --git a/img/virtualizacion_diagrama.40320551.png b/img/virtualizacion_diagrama.40320551.png new file mode 100644 index 0000000..3f53521 Binary files /dev/null and b/img/virtualizacion_diagrama.40320551.png differ diff --git a/img/xruby-gil-jvm.4771a258.png b/img/xruby-gil-jvm.4771a258.png new file mode 100644 index 0000000..31ddc02 Binary files /dev/null and b/img/xruby-gil-jvm.4771a258.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..7907128 --- /dev/null +++ b/index.html @@ -0,0 +1 @@ +IASC Book
\ No newline at end of file diff --git a/js/app.fca0c0d8.js b/js/app.fca0c0d8.js new file mode 100644 index 0000000..835296f --- /dev/null +++ b/js/app.fca0c0d8.js @@ -0,0 +1,2 @@ +(function(e){function t(t){for(var c,o,i=t[0],u=t[1],d=t[2],s=0,l=[];s\n
\n
\n
\n \n \n \n \n \n \n \n
\n
\n
\n
\n\n\n\n\n","import mod from \"-!../node_modules/cache-loader/dist/cjs.js??ref--12-0!../node_modules/thread-loader/dist/cjs.js!../node_modules/babel-loader/lib/index.js!../node_modules/cache-loader/dist/cjs.js??ref--0-0!../node_modules/vue-loader/lib/index.js??vue-loader-options!./IASCBook.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../node_modules/cache-loader/dist/cjs.js??ref--12-0!../node_modules/thread-loader/dist/cjs.js!../node_modules/babel-loader/lib/index.js!../node_modules/cache-loader/dist/cjs.js??ref--0-0!../node_modules/vue-loader/lib/index.js??vue-loader-options!./IASCBook.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./IASCBook.vue?vue&type=template&id=46613048&scoped=true&\"\nimport script from \"./IASCBook.vue?vue&type=script&lang=js&\"\nexport * from \"./IASCBook.vue?vue&type=script&lang=js&\"\nimport style0 from \"./IASCBook.vue?vue&type=style&index=0&lang=css&\"\nimport style1 from \"./IASCBook.vue?vue&type=style&index=1&id=46613048&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"46613048\",\n null\n \n)\n\nexport default component.exports","import Vue from \"vue\";\nimport VueRouter from \"vue-router\";\nimport { publicPath } from '@/../vue.config'\nimport ContentPages from '@/static/pages.json'\n\nVue.use(VueRouter);\n\nconst pagesRoutes = () => {\n return ContentPages.map(section => (\n {\n path: `/${section.path}`,\n component: () => import(`@/content/${section.page}.md`),\n meta: {\n title: section.title,\n extra: section.extra,\n need_detail: section.need_detail,\n description: section.description\n }\n }\n ))\n}\n\nconst routes = [\n {\n path: '/',\n name: 'Home',\n component: () => import('@/content/main.md'),\n meta: {\n layout: 'AppLayoutHome'\n }\n },\n ...pagesRoutes(),\n {\n path: '/stm',\n component: () => import('@/views/STM.vue'),\n meta: {\n title: 'STM',\n description: 'Memoria Transaccional'\n },\n },\n {\n path: '/efecto_lado_haskell',\n component: () => import('@/views/EfectoLadoHaskell.vue'),\n meta: {\n title: 'Efectos de Lado en Haskell',\n description: 'Una intro a memoria transaccional en Haskell'\n },\n },\n {\n path:\"*\",\n component: () => import('../views/errors/NotFound.vue'),\n meta: {\n layout: 'AppLayoutError'\n }\n }\n];\n\nconst router = new VueRouter({\n mode: 'history',\n base: publicPath,\n routes,\n scrollBehavior (to, _from, savedPosition) {\n if (to.hash) {\n return { selector: to.hash }\n } else if (savedPosition) {\n return savedPosition;\n } else {\n return { x: 0, y: 0 }\n }\n }\n});\n\nexport default router;\n","import \"core-js/stable\";\nimport 'mutationobserver-shim'\nimport Vue from 'vue'\nimport './plugins/bootstrap-vue'\nimport './plugins/vue-particles'\nimport './plugins/highlightjs-vue'\n\nimport IASCBook from './IASCBook.vue'\nimport router from \"./router\";\nimport './assets/styles/style.css';\nimport './assets/styles/syntax.css';\nimport './assets/styles/blockquote.css';\nimport 'vue-sidebar-menu/dist/vue-sidebar-menu.css'\nimport \"font-awesome/scss/font-awesome.scss\";\n\nVue.config.productionTip = false\n\nnew Vue({\n router,\n render: h => h(IASCBook),\n}).$mount('#app')\n","const uslug = require('uslug')\nconst uslugify = s => uslug(s)\n\nmodule.exports = {\n publicPath: process.env.NODE_ENV === 'production'\n ? '/iasc-book'\n : '/',\n chainWebpack(config){\n config.module.rule('md')\n .test(/\\.md/)\n .use('vue-loader')\n .loader('vue-loader')\n .end()\n .use('vue-markdown-loader')\n .loader('vue-markdown-loader/lib/markdown-compiler')\n .options({\n raw: true,\n use: [\n /* markdown-it plugin */\n [require('markdown-it-anchor'), {\n level: 1,\n // slugify: string => string,\n permalink: true,\n // renderPermalink: (slug, opts, state, permalink) => {},\n permalinkClass: 'header-anchor',\n permalinkSymbol: '¶',\n permalinkBefore: false,\n slugify: uslugify\n }],\n [require('markdown-it-footnote'), {}],\n [require('markdown-it-abbr'), {}],\n [require('markdown-it-container'), 'warning', {}]\n ]\n })\n }\n}","export * from \"-!../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../node_modules/cache-loader/dist/cjs.js??ref--0-0!../node_modules/vue-loader/lib/index.js??vue-loader-options!./IASCBook.vue?vue&type=style&index=0&lang=css&\"","module.exports = __webpack_public_path__ + \"img/github_logo.ec3a60c8.png\";","export * from \"-!../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../node_modules/cache-loader/dist/cjs.js??ref--0-0!../node_modules/vue-loader/lib/index.js??vue-loader-options!./IASCBook.vue?vue&type=style&index=1&id=46613048&lang=scss&scoped=true&\"","var map = {\n\t\"./AppLayout.vue\": [\n\t\t\"dead\"\n\t],\n\t\"./AppLayoutDefault.vue\": [\n\t\t\"266e\",\n\t\t\"chunk-2d0b2d29\"\n\t],\n\t\"./AppLayoutEntry.vue\": [\n\t\t\"e1a9\",\n\t\t\"chunk-06ecdd3c\"\n\t],\n\t\"./AppLayoutError.vue\": [\n\t\t\"9f69\",\n\t\t\"chunk-2d0f0fc6\"\n\t],\n\t\"./AppLayoutHome.vue\": [\n\t\t\"34f5\",\n\t\t\"chunk-930b4194\"\n\t]\n};\nfunction webpackAsyncContext(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\treturn Promise.resolve().then(function() {\n\t\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\t\te.code = 'MODULE_NOT_FOUND';\n\t\t\tthrow e;\n\t\t});\n\t}\n\n\tvar ids = map[req], id = ids[0];\n\treturn Promise.all(ids.slice(1).map(__webpack_require__.e)).then(function() {\n\t\treturn __webpack_require__(id);\n\t});\n}\nwebpackAsyncContext.keys = function webpackAsyncContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackAsyncContext.id = \"a449\";\nmodule.exports = webpackAsyncContext;","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c(_vm.layout,{tag:\"component\"},[_vm._t(\"default\")],2)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AppLayout.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AppLayout.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./AppLayout.vue?vue&type=template&id=205386ea&\"\nimport script from \"./AppLayout.vue?vue&type=script&lang=js&\"\nexport * from \"./AppLayout.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","var map = {\n\t\"./actores_intro.md\": [\n\t\t\"4d14\",\n\t\t\"chunk-9b0b6b6c\"\n\t],\n\t\"./cap.md\": [\n\t\t\"e4a4\",\n\t\t\"chunk-5855597c\"\n\t],\n\t\"./concurrencia_paralelismo.md\": [\n\t\t\"ab49\",\n\t\t\"chunk-2d212f5c\"\n\t],\n\t\"./contenedores.md\": [\n\t\t\"e07e\",\n\t\t\"chunk-fef08b62\"\n\t],\n\t\"./coroutines.md\": [\n\t\t\"021b\",\n\t\t\"chunk-2d0a34c9\"\n\t],\n\t\"./cps.md\": [\n\t\t\"f62b\",\n\t\t\"chunk-2d22cff6\"\n\t],\n\t\"./distribucion.md\": [\n\t\t\"dc28\",\n\t\t\"chunk-134a5bcf\"\n\t],\n\t\"./distribucion_elixir.md\": [\n\t\t\"d2be\",\n\t\t\"chunk-2d21de07\"\n\t],\n\t\"./estructuras_funcionales.md\": [\n\t\t\"2d25\",\n\t\t\"chunk-2d0bd92b\"\n\t],\n\t\"./event_loop.md\": [\n\t\t\"c3c4\",\n\t\t\"chunk-33c3e200\"\n\t],\n\t\"./fibers.md\": [\n\t\t\"52f8\",\n\t\t\"chunk-36154627\"\n\t],\n\t\"./guild.md\": [\n\t\t\"f723\",\n\t\t\"chunk-7095c905\"\n\t],\n\t\"./interleaving.md\": [\n\t\t\"7b02\",\n\t\t\"chunk-49b1d262\"\n\t],\n\t\"./introduccion.md\": [\n\t\t\"6b41\",\n\t\t\"chunk-349b0eea\"\n\t],\n\t\"./main.md\": [\n\t\t\"7949\",\n\t\t\"chunk-4c048be9\"\n\t],\n\t\"./mitos.md\": [\n\t\t\"4198\",\n\t\t\"chunk-2d0c0352\"\n\t],\n\t\"./otp.md\": [\n\t\t\"0f18\",\n\t\t\"chunk-2d0af7d3\"\n\t],\n\t\"./promises.md\": [\n\t\t\"b771\",\n\t\t\"chunk-2d2102a5\"\n\t],\n\t\"./service_mesh.md\": [\n\t\t\"d3c5\",\n\t\t\"chunk-4fe8e0d3\"\n\t]\n};\nfunction webpackAsyncContext(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\treturn Promise.resolve().then(function() {\n\t\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\t\te.code = 'MODULE_NOT_FOUND';\n\t\t\tthrow e;\n\t\t});\n\t}\n\n\tvar ids = map[req], id = ids[0];\n\treturn __webpack_require__.e(ids[1]).then(function() {\n\t\treturn __webpack_require__(id);\n\t});\n}\nwebpackAsyncContext.keys = function webpackAsyncContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackAsyncContext.id = \"e383\";\nmodule.exports = webpackAsyncContext;"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-06ecdd3c.08cef7ca.js b/js/chunk-06ecdd3c.08cef7ca.js new file mode 100644 index 0000000..7d226af --- /dev/null +++ b/js/chunk-06ecdd3c.08cef7ca.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-06ecdd3c"],{"21ea":function(t,e,a){"use strict";a("e7b8")},2640:function(t,e,a){},"5dfc":function(t,e,a){"use strict";a("cba0")},"7a59":function(t,e,a){"use strict";a("2640")},a298:function(t,e,a){"use strict";a("c56b")},c56b:function(t,e,a){},cba0:function(t,e,a){},d178:function(t,e,a){"use strict";var n=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("nav",{staticClass:"navbar navbar-expand-lg navbar-light"},[t._m(0),a("div",{staticClass:"collapse navbar-collapse",attrs:{id:"navbarNav"}},[a("ul",{staticClass:"navbar-nav ml-auto"},[a("li",{staticClass:"nav-item active"},[a("router-link",{staticClass:"nav-link",attrs:{to:"/"}},[t._v("Home "),a("span",{staticClass:"sr-only"},[t._v("(current)")])])],1),t._m(1)])])])},i=[function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("button",{staticClass:"navbar-toggler",attrs:{type:"button","data-toggle":"collapse","data-target":"#navbarNav","aria-controls":"navbarNav","aria-expanded":"false","aria-label":"Toggle navigation"}},[a("span",{staticClass:"navbar-toggler-icon"})])},function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("li",{staticClass:"nav-item"},[a("a",{staticClass:"nav-link navbar-button",attrs:{href:"http://arquitecturas-concurrentes.github.io/"}},[t._v("IASC")])])}],s=(a("5dfc"),a("2877")),r={},o=Object(s["a"])(r,n,i,!1,null,null,null);e["a"]=o.exports},e1a9:function(t,e,a){"use strict";a.r(e);var n=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"scroll-touch"},[a("Navbar"),a("Entry",{attrs:{title:t.entry.title,description:t.entry.description,extra:t.entry.extra,need_detail:t.entry.need_detail}}),t._t("default")],2)},i=[],s=(a("a4d3"),a("e01a"),function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"wrapper"},[a("div",{staticClass:"container header"},[a("div",{staticClass:"titulo-heading"},[a("div",{staticClass:"container-background"},[a("div",{staticClass:"titulo"},[a("h3",{staticClass:"Title"},[t._v(" "+t._s(this.title)+" ")]),a("br"),a("h4",[t._v(" "+t._s(this.description)+" ")])])])]),this.need_detail?a("div",[a("NeedMoreDetail")],1):t._e(),this.extra?a("div",[a("AdditionalContent")],1):t._e(),a("div",{staticClass:"container"},[a("div",{staticClass:"inner-content col-sm-8 col-md-10"},[a("router-view")],1)])])])}),r=[],o=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"alert alert-warning",attrs:{role:"alert"}},[t._v(" Nota: La siguiente seccion necesita mas detalles y citas para que sea considerado como una seccion estable. Se esperan posibles cambios a lo largo del tiempo. ")])},l=[],c={name:"NeedMoreDetail",mounted:function(){}},u=c,d=a("2877"),v=Object(d["a"])(u,o,l,!1,null,null,null),f=v.exports,p=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"alert alert-info",attrs:{role:"alert"}},[t._v(" La siguiente seccion contiene contenido considerado como complementario y no obligatorio para la materia de IASC. ")])},h=[],m={name:"AdditionalContent",mounted:function(){}},b=m,_=Object(d["a"])(b,p,h,!1,null,null,null),C=_.exports,g={name:"Entry",components:{NeedMoreDetail:f,AdditionalContent:C},mounted:function(){this.scrollToAnchor()},updated:function(){this.scrollToAnchor()},methods:{scrollToAnchor:function(){var t=this;this.$nextTick((function(){if(t.$route.hash){var e=t.$route.hash,a=document.querySelector(e);a&&window.scrollTo(0,a.offsetTop)}}))}},props:{title:String,description:String,need_detail:Boolean,extra:Boolean}},y=g,x=(a("21ea"),a("a298"),Object(d["a"])(y,s,r,!1,null,"501637a8",null)),$=x.exports,w=a("d178"),E={name:"AppLayoutEntry",components:{Entry:$,Navbar:w["a"]},data:function(){return{entry:{title:this.$route.meta.title,need_detail:this.$route.meta.need_detail,extra:this.$route.meta.extra,description:this.$route.meta.description}}}},A=E,N=(a("7a59"),Object(d["a"])(A,n,i,!1,null,"488267d0",null));e["default"]=N.exports},e7b8:function(t,e,a){}}]); +//# sourceMappingURL=chunk-06ecdd3c.08cef7ca.js.map \ No newline at end of file diff --git a/js/chunk-06ecdd3c.08cef7ca.js.map b/js/chunk-06ecdd3c.08cef7ca.js.map new file mode 100644 index 0000000..209e02a --- /dev/null +++ b/js/chunk-06ecdd3c.08cef7ca.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/components/Entry.vue?5318","webpack:///./src/components/Navbar.vue?1166","webpack:///./src/layouts/AppLayoutEntry.vue?6a6b","webpack:///./src/components/Entry.vue?2cf4","webpack:///./src/components/Navbar.vue?a63b","webpack:///./src/components/Navbar.vue","webpack:///./src/layouts/AppLayoutEntry.vue?9ccb","webpack:///./src/components/Entry.vue?53a9","webpack:///./src/components/NeedMoreDetail.vue?aae9","webpack:///src/components/NeedMoreDetail.vue","webpack:///./src/components/NeedMoreDetail.vue?3c80","webpack:///./src/components/NeedMoreDetail.vue","webpack:///./src/components/AdditionalContent.vue?44bb","webpack:///src/components/AdditionalContent.vue","webpack:///./src/components/AdditionalContent.vue?a998","webpack:///./src/components/AdditionalContent.vue","webpack:///src/components/Entry.vue","webpack:///./src/components/Entry.vue?f007","webpack:///./src/components/Entry.vue","webpack:///src/layouts/AppLayoutEntry.vue","webpack:///./src/layouts/AppLayoutEntry.vue?770e","webpack:///./src/layouts/AppLayoutEntry.vue"],"names":["render","_vm","this","_h","$createElement","_c","_self","staticClass","_m","attrs","_v","staticRenderFns","script","component","entry","title","description","extra","need_detail","_t","_s","_e","name","mounted","components","NeedMoreDetail","AdditionalContent","scrollToAnchor","updated","methods","props","String","Boolean","Entry","Navbar","data","$route","meta"],"mappings":"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","file":"js/chunk-06ecdd3c.08cef7ca.js","sourcesContent":["export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Entry.vue?vue&type=style&index=0&id=501637a8&scoped=true&lang=css&\"","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Navbar.vue?vue&type=style&index=0&lang=css&\"","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AppLayoutEntry.vue?vue&type=style&index=0&id=488267d0&scoped=true&lang=css&\"","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Entry.vue?vue&type=style&index=1&lang=css&\"","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('nav',{staticClass:\"navbar navbar-expand-lg navbar-light\"},[_vm._m(0),_c('div',{staticClass:\"collapse navbar-collapse\",attrs:{\"id\":\"navbarNav\"}},[_c('ul',{staticClass:\"navbar-nav ml-auto\"},[_c('li',{staticClass:\"nav-item active\"},[_c('router-link',{staticClass:\"nav-link\",attrs:{\"to\":\"/\"}},[_vm._v(\"Home \"),_c('span',{staticClass:\"sr-only\"},[_vm._v(\"(current)\")])])],1),_vm._m(1)])])])}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('button',{staticClass:\"navbar-toggler\",attrs:{\"type\":\"button\",\"data-toggle\":\"collapse\",\"data-target\":\"#navbarNav\",\"aria-controls\":\"navbarNav\",\"aria-expanded\":\"false\",\"aria-label\":\"Toggle navigation\"}},[_c('span',{staticClass:\"navbar-toggler-icon\"})])},function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('li',{staticClass:\"nav-item\"},[_c('a',{staticClass:\"nav-link navbar-button\",attrs:{\"href\":\"http://arquitecturas-concurrentes.github.io/\"}},[_vm._v(\"IASC\")])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./Navbar.vue?vue&type=template&id=7f0398a6&\"\nvar script = {}\nimport style0 from \"./Navbar.vue?vue&type=style&index=0&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"scroll-touch\"},[_c('Navbar'),_c('Entry',{attrs:{\"title\":_vm.entry.title,\"description\":_vm.entry.description,\"extra\":_vm.entry.extra,\"need_detail\":_vm.entry.need_detail}}),_vm._t(\"default\")],2)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"wrapper\"},[_c('div',{staticClass:\"container header\"},[_c('div',{staticClass:\"titulo-heading\"},[_c('div',{staticClass:\"container-background\"},[_c('div',{staticClass:\"titulo\"},[_c('h3',{staticClass:\"Title\"},[_vm._v(\" \"+_vm._s(this.title)+\" \")]),_c('br'),_c('h4',[_vm._v(\" \"+_vm._s(this.description)+\" \")])])])]),(this.need_detail)?_c('div',[_c('NeedMoreDetail')],1):_vm._e(),(this.extra)?_c('div',[_c('AdditionalContent')],1):_vm._e(),_c('div',{staticClass:\"container\"},[_c('div',{staticClass:\"inner-content col-sm-8 col-md-10\"},[_c('router-view')],1)])])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"alert alert-warning\",attrs:{\"role\":\"alert\"}},[_vm._v(\" Nota: La siguiente seccion necesita mas detalles y citas para que sea considerado como una seccion estable. Se esperan posibles cambios a lo largo del tiempo. \")])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./NeedMoreDetail.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./NeedMoreDetail.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./NeedMoreDetail.vue?vue&type=template&id=deee2dea&\"\nimport script from \"./NeedMoreDetail.vue?vue&type=script&lang=js&\"\nexport * from \"./NeedMoreDetail.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"alert alert-info\",attrs:{\"role\":\"alert\"}},[_vm._v(\" La siguiente seccion contiene contenido considerado como complementario y no obligatorio para la materia de IASC. \")])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AdditionalContent.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AdditionalContent.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./AdditionalContent.vue?vue&type=template&id=63ba3426&\"\nimport script from \"./AdditionalContent.vue?vue&type=script&lang=js&\"\nexport * from \"./AdditionalContent.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","\n\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Entry.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Entry.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./Entry.vue?vue&type=template&id=501637a8&scoped=true&\"\nimport script from \"./Entry.vue?vue&type=script&lang=js&\"\nexport * from \"./Entry.vue?vue&type=script&lang=js&\"\nimport style0 from \"./Entry.vue?vue&type=style&index=0&id=501637a8&scoped=true&lang=css&\"\nimport style1 from \"./Entry.vue?vue&type=style&index=1&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"501637a8\",\n null\n \n)\n\nexport default component.exports","\n\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AppLayoutEntry.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AppLayoutEntry.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./AppLayoutEntry.vue?vue&type=template&id=488267d0&scoped=true&\"\nimport script from \"./AppLayoutEntry.vue?vue&type=script&lang=js&\"\nexport * from \"./AppLayoutEntry.vue?vue&type=script&lang=js&\"\nimport style0 from \"./AppLayoutEntry.vue?vue&type=style&index=0&id=488267d0&scoped=true&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"488267d0\",\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-134a5bcf.40d7cefa.js b/js/chunk-134a5bcf.40d7cefa.js new file mode 100644 index 0000000..6378b5a --- /dev/null +++ b/js/chunk-134a5bcf.40d7cefa.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-134a5bcf"],{"0db9":function(e,a){e.exports="data:image/png;base64,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"},2936:function(e,a,o){e.exports=o.p+"img/image8.fd1bffb3.png"},"2cb2":function(e,a,o){e.exports=o.p+"img/image10.4683f863.png"},"2ed8":function(e,a,o){e.exports=o.p+"img/image4.132661ac.png"},"335d":function(e,a,o){e.exports=o.p+"img/image13.aa9b12a8.png"},"4cf6":function(e,a,o){e.exports=o.p+"img/image7.bcf1a28f.png"},"76f5":function(e,a,o){e.exports=o.p+"img/image2.5a8685e5.png"},da9c:function(e,a,o){e.exports=o.p+"img/image9.44cb6ec8.png"},db3b:function(e,a,o){e.exports=o.p+"img/image12.f374f4f9.png"},dc28:function(e,a,o){"use strict";o.r(a);var s=function(){var e=this,a=e.$createElement;e._self._c;return e._m(0)},n=[function(){var e=this,a=e.$createElement,s=e._self._c||a;return s("section",[s("h1",{attrs:{id:"distribución"}},[e._v("Distribución "),s("a",{staticClass:"header-anchor",attrs:{href:"#distribución"}},[e._v("¶")])]),s("h2",{attrs:{id:"introduccion"}},[e._v("Introduccion "),s("a",{staticClass:"header-anchor",attrs:{href:"#introduccion"}},[e._v("¶")])]),s("p",[e._v("Antes de hablar de distribución, es a veces ideal tratar de explicarlo de cómo se llega a ella. En general cuando se plantea la arquitectura de una aplicación, en cuanto a la arquitectura, en donde queda afuera lo que es el diseño e implementación del mismo, en general se plantea o se despliega por primera vez como un monolito, es decir, solo implementar todo nuestro sistema en un solo servidor. Ya sea un prototipo, o una versión temprana (beta) de nuestra aplicación, en general se plantea el monolito como arquitectura inicial, por costos y tiempo en el que se despliega la aplicación, y también porque no tenemos problemas que nos puede causar un sistema distribuido.")]),s("img",{staticClass:"center",staticStyle:{width:"500px"},attrs:{src:o("76f5")}}),s("p",[e._v("Esta es una imagen de una arquitectura monolitica tradicional, con una aplicacion y una base SQL, que en general esta desplegada en un solo servidor. Algunos problemas que puede generar esta arquitectura es la siguiente:")]),s("ul",[s("li",[e._v("Incremento de la complejidad de la aplicacion, a medida que pasa el tiempo y la misma empieza a tener gran cantidad de componentes o va creciendo los requerimientos del sistema")]),s("li",[e._v("Cuando empieza a ser usado cada vez por más usuarios, esto hace que aumente la carga y que un solo servidor pueda no ser suficiente o incluso generar problemas con la carga que generan estos usuarios")])]),s("p",[e._v("Ante el aumento de la carga de usuarios, tráfico y mayor interacción entre la aplicación y la base de datos, esto genera una carga mayor en el único servidor que tenemos, por lo cual deberemos escalar. Hay dos tipos de escala:")]),s("h3",{attrs:{id:"escala-vertical-scale-up"}},[e._v("Escala Vertical (Scale Up) "),s("a",{staticClass:"header-anchor",attrs:{href:"#escala-vertical-scale-up"}},[e._v("¶")])]),s("img",{staticClass:"center",attrs:{src:o("0db9")}}),s("p",[e._v("Esta manera de escalar, también conocido como escalar para arriba o verticalmente (?) (scale up), es incrementando los recursos de un servidor o un nodo, o sea aumentar CPU, memoria, disco, etc. Lo que nos permite este tipo de escala es que no necesitamos realizar cambios o desarrollo adicional en nuestro sistema, solo habrá un tiempo en el que nuestro sistema no estará disponible hasta una vez que hayan sido implementado estos cambios. El problema de escalar verticalmente es que el costo empieza a ser exponencial en un momento, por lo que en un momento se puede hacer muy costoso un nodo único muy grande en donde cada vez las mejoras van a ser menores en cuanto a recursos. También hay un momento en el que, si utilizamos servidores tradicionales y no mainframes, exista una limitación en cuanto a la tecnología, en general por limitaciones en cuanto a la CPUs")]),s("h3",{attrs:{id:"escala-horizontal"}},[e._v("Escala Horizontal "),s("a",{staticClass:"header-anchor",attrs:{href:"#escala-horizontal"}},[e._v("¶")])]),s("img",{staticClass:"center",attrs:{src:o("db3b")}}),s("p",[e._v("La otra manera de escalar, es horizontalmente también (Scale Out) es cuando en vez de incrementar los recursos, se agregan nuevos servidores con los mismos recursos. Lo bueno de poder escalar horizontalmente es que la aplicación no deja de estar disponible al escalar de esta manera. El costo con esta metodología es mucho más económica por este medio, que escalando verticalmente, otro aspecto interesante es que es más tolerante a fallos, ya que más copias de la aplicación están corriendo al mismo tiempo. Las grandes desventajas son que la arquitectura se complica, junto con el aumento del ancho de banda entre los distintos componentes que puede llegar a tener nuestro sistema una vez que hagamos scale out.")]),s("p",[e._v("Con respecto a nuestra aplicación monolítica, podemos bien o replicar toda la aplicación con su bbdd, y que no tengan relación alguna cada una de las maquinas (imagen izquierda), o bien podemos solo replicar en cada uno de los servidores la aplicación y luego tener en otra instancia nuestra bbdd (imagen derecha).")]),s("img",{staticClass:"center",attrs:{src:o("4cf6")}}),s("p",[e._v("La motivación para la arquitectura de la imagen de la izquierda puede ser que se quiera distribuir por países el sistema, o sea, que en cada país que exista esta aplicación se dirija a un servidor que contiene todo su estado. La otra manera de escalar horizontalmente nuestro monolito nos permite que no tengamos tres bases de datos distintas, y que incluso el sistema pueda ser visto aun por el usuario como uno solo, o sea generalmente mediante alguna diferencia de endpoints, pero… como manejar la carga de manera que no se sobrecargue un solo servidor y los otros no? Con un load balancer…")]),s("img",{staticClass:"center",attrs:{src:o("335d")}}),s("p",[e._v("Un load balancer nos va a permitir usar alguna estrategia por la cual la carga sea distribuida de manera equitativa. Esto puede ser por un algoritmo simple, tal como puede ser un round robin, o puede tener algún feedback de los nodos o servidores, que pueden dar al load balancer un poco más de información sobre a dónde redirigir el tráfico.")]),s("p",[e._v("Pero esta es la única manera de escalar?? La respuesta es no.")]),s("p",[e._v("Se puede escalar horizontalmente de varias maneras, existe un libro que es el de “Art of Scalability” de Michael Fisher que nos propone un interesante modelo de cubo de como escalar.")]),s("img",{staticClass:"center",attrs:{src:o("da9c")}}),s("p",[e._v("En esta representación el punto de origen concuerda con el sistema monolítico en una sola instancia, y la arista de arriba a la derecha del cubo, nos representa la máxima escalabilidad de la aplicación. Y como el cubo es en tres dimensiones, eso nos dice que no solo hay una manera de escalar nuestra aplicación sino que hay varias que incluso podríamos llegar a combinar, ahora veremos cada una de las dimensiones")]),s("h3",{attrs:{id:"eje-x-clonacion"}},[e._v("Eje X - Clonacion "),s("a",{staticClass:"header-anchor",attrs:{href:"#eje-x-clonacion"}},[e._v("¶")])]),s("p",[e._v("Esta manera de escalar, es la que vimos al final de la sección anterior, es cuando tenemos varias réplicas de nuestra aplicación monolítica y que pueden o bien acceder a una bbdd. Otros temas a mencionar que no se hayan hecho antes es el tema de que al existir varias copias de nuestro sistema, tendremos que de alguna manera garantizar que los datos se mantengan consistentes, ya que varias copias van a estar accediendo a los mismos datos, por lo que tendremos que bien o implementar un sistema de lockeo de los datos o usar algo que nos garantice esto, que bien puede ser la base de datos. Este esquema no nos resuelve aún el problema de una aplicación de alta complejidad, o sea.. Que aun nuestro código va a estar aun organizado como una aplicación monolítica, esto puede no ser una desventaja si no tenemos un basecode demasiado grande pero si lo fuese, por temas de complejidad o incluso de uso de servicios de terceros, tal vez sea un problema a nivel de desarrollo o mantenimiento.")]),s("h3",{attrs:{id:"eje-y-descomposición-funcional"}},[e._v("Eje Y - Descomposición Funcional "),s("a",{staticClass:"header-anchor",attrs:{href:"#eje-y-descomposición-funcional"}},[e._v("¶")])]),s("p",[e._v("En vez de tener varias instancias o nodos del mismo sistema, cada uno conteniendo todo el código del sistema, en este eje se va a descomponer nuestra aplicación entre los distintos nodos, esto es lo que se conoce generalmente como microservicios, y cada uno de estos va a ser responsable de una función.")]),s("img",{staticClass:"center",attrs:{src:o("2936")}}),s("p",[e._v("Y como podemos descomponer a nuestra aplicación?")]),s("ul",[s("li",[s("p",[e._v("Podemos descomponer por medio de la función técnica de lo que hace ya sea un endpoint, o una funcionalidad, por ejemplo, se puede descomponer una aplicación en servicios de capacidad (capability-services) como login, usuarios, productos, etc. Abajo hay un pequeño ejemplo de un servicio de discusión, estilo reddit.")])]),s("li",[s("p",[e._v("Otra manera de descomponer es dividir por dominios a la aplicación, o sea por los recursos pero como un todo, y no por las funcionalidades, o sea si tenemos una aplicación de venta, podemos dividir la aplicación en: servicio al cliente, ventas, catalogo para el usuario. Esta división es más bien por entidades (Entity-Services)")])])]),s("p",[e._v("También pueden combinarse esta división o usarse otro tipo de división del sistema, el esquema no es estricto en este sentido, por lo que nos da la libertad de escalar nuestra aplicación o más bien de dividirla de acuerdo a nuestro dominio. No hay ya necesidad de clonar toda la aplicación de esta manera. El problema es que esto genera otras desventajas y son que ahora nuestros microservicios además de trabajar con la bbdd a veces tendrán que coordinarse los unos a los otros mediante mensajes o requests incluso, también puede haber un incremento en el uso del ancho de banda.")]),s("h3",{attrs:{id:"eje-z-shardingdata-partitioning"}},[e._v("Eje Z - Sharding/Data Partitioning "),s("a",{staticClass:"header-anchor",attrs:{href:"#eje-z-shardingdata-partitioning"}},[e._v("¶")])]),s("p",[e._v("Hasta ahora vimos cómo dividir nuestro sistema pero a nivel de organización de la lógica de nuestros componentes, puede existir el caso en el que si estamos persistiendo los datos de nuestro sistema, el mismo aún tenga una sola base de datos o a lo sumo este replicada en otras bases, pero que en suma estas réplicas son solo una copia de todo el estado de la base de datos principal, por lo que en ese esquema solo una base de datos admite escrituras y todas puedan ser leídas. Dependiendo del tipo de réplica, la misma puede ser hecha ni bien se escriben los valores o a veces pueden tenerse escrituras que no garantice que una vez que se escribió el valor en la base de datos, el mismo esté replicado en las otras bases, esto se llama replicación asincrónica. Pueden ver mas de esto en el siguiente (link)[https://www.cybertec-postgresql.com/en/services/postgresql-replication/synchronous-synchronous-replication/]")]),s("p",[e._v("Pero aún tenemos el estado, a lo sumo replicado, tal como lo teníamos con los servidores al escalarlo mediante clonación (eje x), y solo podemos tener una escritura a la vez, esto puede ser un cuello de botella si existen muchas escrituras sobre la base de datos. El esquema de este eje z, es el de dividir la base de datos o el estado en subsets, por lo que podemos dividir el estado bajo un criterio determinado, por ejemplo si tenemos un estado que son los productos, bien podemos dividir los mismos por rango de letras como el siguiente ejemplo.")]),s("img",{staticClass:"center",attrs:{src:o("2ed8")}}),s("p",[e._v("Y como tenemos ahora el estado particionado, vamos a tener que tener algo que nos pueda despachar al nodo correcto los pedidos de lectura o escritura, que puede ser un load balancer, o bien que los nodos de estado o persistencia se puedan hablar entre ellos para devolver o persistir el estado, esto último es en el caso en el que no se tenga una base de datos relacional o tan solo se pueda implementar un shardeo de este tipo. Lo interesante de este esquema es que no tenemos más de un nodo de datos que pueda aceptar escrituras, aunque solo habrá una escritura por subset.")]),s("h2",{attrs:{id:"combinación-de-ejes"}},[e._v("Combinación de Ejes "),s("a",{staticClass:"header-anchor",attrs:{href:"#combinación-de-ejes"}},[e._v("¶")])]),s("p",[e._v("Como el modelo de escala es tridimensional, se puede incluso combinar para que nuestra arquitectura sea más robusta, por ejemplo, podemos tener un esquema de microservicios en el que además cada servicio, como el de login, puede esta clonado y tener más de un servicio de login disponible y el mismo esté tan solo distribuido por un segundo nivel de load balancer que redirige los request con un criterio, que nos da un esquema así? Como dijimos antes, mayor robustez, si bien escalar por microservicios divide la carga, aun todos los usuarios en gran medida, deberán loguearse, y ademas al separar los servicios, aun seguimos teniendo un solo punto de fallo, por lo que para que el servicio esté disponible si el servidor de login se cae, es el de escalar después este microservicio por medio de clonar el mismo en varios servidores idénticos con este microservicios.")]),s("img",{staticClass:"center",attrs:{src:o("f5a1")}}),s("h3",{attrs:{id:"sesiones"}},[e._v("Sesiones "),s("a",{staticClass:"header-anchor",attrs:{href:"#sesiones"}},[e._v("¶")])]),s("p",[e._v("Otro tema que no hablamos antes es sobre las sesiones en nuestra aplicación ahora distribuida, en el primer caso que es el de replicar la aplicación, si tenemos varios nodos con toda nuestra aplicación y un load balancer, puede ocurrir que un usuario se loguee en un nodo y luego en otro request, pueda ser redirigido a otro nodo donde no se tiene registro de su login, como se resuelve esto? O bien teniendo un lugar, como una base de datos aparte donde se registren las sesiones o bien se puede optar por un esquema de sticky sessions")]),s("img",{staticClass:"center",attrs:{src:o("2cb2")}}),s("p",[e._v("ELs sticky sessions permiten mediante una cookie, saber contra qué servidor se autenticaron, además de otra información de la sesión, el load balancer sabe a qué nodo redirigir los requests de un usuario en particular sobre un modelo de cloning o en el que nuestra aplicación esta solo replicada, en otros tipo de arquitecturas como microservicios, puede ser que no sea necesario a menos que exista solo nodo de login de usuarios.")]),s("h3",{attrs:{id:"heartbeat-y-gossip"}},[e._v("Heartbeat y gossip "),s("a",{staticClass:"header-anchor",attrs:{href:"#heartbeat-y-gossip"}},[e._v("¶")])]),s("p",[e._v("A veces es necesario saber si un nodo o servicio esta disponible y que sepamos que no este caido, a veces si es solo un servicio que estamos exponiendo podemos tan solo tener un healthcheck, que es solo un endpoint de nuestro sistema (algo mas de detalle en "),s("a",{attrs:{href:"https://microservices.io/patterns/observability/health-check-api.html"}},[e._v("https://microservices.io/patterns/observability/health-check-api.html")]),e._v(", puede ser incluso implementado si no estamos en un esquema de microservicios) para confirmar si nuestro servicio esta disponible y puede admitir nuevos pedidos, pero esto es en general a nivel de HHTP, por lo que si un nodo nuestro se cae podriamos no llegar a poder responder un request hecho a nuestro endpoint. Entonces cómo podemos detectar fallas en nodos de nuestro sistema si no es solo mediante un chequeo de healthcheck o un mecanismo similar? Podemos hacerlo mediante conexiones de tcp en las que se pase un token o un bit o un valor que se van a ir pasando entre los nodos, y de esta manera cuando un nodo deje de pasar ese valor después de un tiempo prolongado, muy superior al tiempo entre emisión de este valor, se puede tomar al nodo como caido. Esto se lo conoce como heartbeat, y es útil para conocer si se cayeron los nodos sin depender de un healthcheck, ya que pudo existir una caída del nodo y que no sea un problema lógico o de algún componente o servicio externo. Lo recomendable es que la información de heartbeat este en una vía o conexión distinta a lo que se usaría para intercambiar información entre nodos o servidores. Otra manera un poco mas bien ordenada o distribuida, de cómo notificar a otros servidores y no hacer múltiples conexiones entre nodos, para usar heartbeat, es el de usar un protocolo de gossip. Esto permite que se intercambie más información entre servidores, y que no sea solo un simple valor o bit, por ejemplo, puede ser información tal como por ejemplo: “se cayó el nodo de login x”, o “volvió a estar disponible el nodo que contiene la base de datos”. Se puede encontrar un poco más de información en el siguiente "),s("a",{attrs:{href:"https://github.com/gossiperl/gossiperl/wiki/gossip-in-computer-science"}},[e._v("link")])]),s("p",[e._v("Videos que nos parecieron interesantes")]),s("p",[s("a",{attrs:{href:"https://www.youtube.com/watch?v=PE4gwstWhmc"}},[e._v("How We've Scaled Dropbox")])]),s("p",[s("a",{attrs:{href:"https://www.youtube.com/watch?v=Y6Ev8GIlbxc"}},[e._v("Distributed Systems in One Lesson by Tim Berglund")])])])}],i=o("2877"),r={},t=Object(i["a"])(r,s,n,!1,null,null,null);a["default"]=t.exports},f5a1:function(e,a,o){e.exports=o.p+"img/image5.db96ab35.png"}}]); +//# sourceMappingURL=chunk-134a5bcf.40d7cefa.js.map \ No newline at end of file diff --git a/js/chunk-134a5bcf.40d7cefa.js.map b/js/chunk-134a5bcf.40d7cefa.js.map new file mode 100644 index 0000000..b5f01c9 --- /dev/null +++ b/js/chunk-134a5bcf.40d7cefa.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/images/distribucion/image6.png","webpack:///./src/images/distribucion/image8.png","webpack:///./src/images/distribucion/image10.png","webpack:///./src/images/distribucion/image4.png","webpack:///./src/images/distribucion/image13.png","webpack:///./src/images/distribucion/image7.png","webpack:///./src/images/distribucion/image2.png","webpack:///./src/images/distribucion/image9.png","webpack:///./src/images/distribucion/image12.png","webpack:///./src/content/distribucion.md?31c1","webpack:///./src/content/distribucion.md","webpack:///./src/images/distribucion/image5.png"],"names":["module","exports","render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","staticStyle","script","component"],"mappings":"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","file":"js/chunk-134a5bcf.40d7cefa.js","sourcesContent":["module.exports = \"data:image/png;base64,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\"","module.exports = __webpack_public_path__ + \"img/image8.fd1bffb3.png\";","module.exports = __webpack_public_path__ + \"img/image10.4683f863.png\";","module.exports = __webpack_public_path__ + \"img/image4.132661ac.png\";","module.exports = __webpack_public_path__ + \"img/image13.aa9b12a8.png\";","module.exports = __webpack_public_path__ + \"img/image7.bcf1a28f.png\";","module.exports = __webpack_public_path__ + \"img/image2.5a8685e5.png\";","module.exports = __webpack_public_path__ + \"img/image9.44cb6ec8.png\";","module.exports = __webpack_public_path__ + \"img/image12.f374f4f9.png\";","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h1',{attrs:{\"id\":\"distribución\"}},[_vm._v(\"Distribución \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#distribución\"}},[_vm._v(\"¶\")])]),_c('h2',{attrs:{\"id\":\"introduccion\"}},[_vm._v(\"Introduccion \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#introduccion\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Antes de hablar de distribución, es a veces ideal tratar de explicarlo de cómo se llega a ella. En general cuando se plantea la arquitectura de una aplicación, en cuanto a la arquitectura, en donde queda afuera lo que es el diseño e implementación del mismo, en general se plantea o se despliega por primera vez como un monolito, es decir, solo implementar todo nuestro sistema en un solo servidor. Ya sea un prototipo, o una versión temprana (beta) de nuestra aplicación, en general se plantea el monolito como arquitectura inicial, por costos y tiempo en el que se despliega la aplicación, y también porque no tenemos problemas que nos puede causar un sistema distribuido.\")]),_c('img',{staticClass:\"center\",staticStyle:{\"width\":\"500px\"},attrs:{\"src\":require(\"@/images/distribucion/image2.png\")}}),_c('p',[_vm._v(\"Esta es una imagen de una arquitectura monolitica tradicional, con una aplicacion y una base SQL, que en general esta desplegada en un solo servidor. Algunos problemas que puede generar esta arquitectura es la siguiente:\")]),_c('ul',[_c('li',[_vm._v(\"Incremento de la complejidad de la aplicacion, a medida que pasa el tiempo y la misma empieza a tener gran cantidad de componentes o va creciendo los requerimientos del sistema\")]),_c('li',[_vm._v(\"Cuando empieza a ser usado cada vez por más usuarios, esto hace que aumente la carga y que un solo servidor pueda no ser suficiente o incluso generar problemas con la carga que generan estos usuarios\")])]),_c('p',[_vm._v(\"Ante el aumento de la carga de usuarios, tráfico y mayor interacción entre la aplicación y la base de datos, esto genera una carga mayor en el único servidor que tenemos, por lo cual deberemos escalar. Hay dos tipos de escala:\")]),_c('h3',{attrs:{\"id\":\"escala-vertical-scale-up\"}},[_vm._v(\"Escala Vertical (Scale Up) \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#escala-vertical-scale-up\"}},[_vm._v(\"¶\")])]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/distribucion/image6.png\")}}),_c('p',[_vm._v(\"Esta manera de escalar, también conocido como escalar para arriba o verticalmente (?) (scale up), es incrementando los recursos de un servidor o un nodo, o sea aumentar CPU, memoria, disco, etc. Lo que nos permite este tipo de escala es que no necesitamos realizar cambios o desarrollo adicional en nuestro sistema, solo habrá un tiempo en el que nuestro sistema no estará disponible hasta una vez que hayan sido implementado estos cambios. El problema de escalar verticalmente es que el costo empieza a ser exponencial en un momento, por lo que en un momento se puede hacer muy costoso un nodo único muy grande en donde cada vez las mejoras van a ser menores en cuanto a recursos. También hay un momento en el que, si utilizamos servidores tradicionales y no mainframes, exista una limitación en cuanto a la tecnología, en general por limitaciones en cuanto a la CPUs\")]),_c('h3',{attrs:{\"id\":\"escala-horizontal\"}},[_vm._v(\"Escala Horizontal \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#escala-horizontal\"}},[_vm._v(\"¶\")])]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/distribucion/image12.png\")}}),_c('p',[_vm._v(\"La otra manera de escalar, es horizontalmente también (Scale Out) es cuando en vez de incrementar los recursos, se agregan nuevos servidores con los mismos recursos. Lo bueno de poder escalar horizontalmente es que la aplicación no deja de estar disponible al escalar de esta manera. El costo con esta metodología es mucho más económica por este medio, que escalando verticalmente, otro aspecto interesante es que es más tolerante a fallos, ya que más copias de la aplicación están corriendo al mismo tiempo. Las grandes desventajas son que la arquitectura se complica, junto con el aumento del ancho de banda entre los distintos componentes que puede llegar a tener nuestro sistema una vez que hagamos scale out.\")]),_c('p',[_vm._v(\"Con respecto a nuestra aplicación monolítica, podemos bien o replicar toda la aplicación con su bbdd, y que no tengan relación alguna cada una de las maquinas (imagen izquierda), o bien podemos solo replicar en cada uno de los servidores la aplicación y luego tener en otra instancia nuestra bbdd (imagen derecha).\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/distribucion/image7.png\")}}),_c('p',[_vm._v(\"La motivación para la arquitectura de la imagen de la izquierda puede ser que se quiera distribuir por países el sistema, o sea, que en cada país que exista esta aplicación se dirija a un servidor que contiene todo su estado. La otra manera de escalar horizontalmente nuestro monolito nos permite que no tengamos tres bases de datos distintas, y que incluso el sistema pueda ser visto aun por el usuario como uno solo, o sea generalmente mediante alguna diferencia de endpoints, pero… como manejar la carga de manera que no se sobrecargue un solo servidor y los otros no? Con un load balancer…\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/distribucion/image13.png\")}}),_c('p',[_vm._v(\"Un load balancer nos va a permitir usar alguna estrategia por la cual la carga sea distribuida de manera equitativa. Esto puede ser por un algoritmo simple, tal como puede ser un round robin, o puede tener algún feedback de los nodos o servidores, que pueden dar al load balancer un poco más de información sobre a dónde redirigir el tráfico.\")]),_c('p',[_vm._v(\"Pero esta es la única manera de escalar?? La respuesta es no.\")]),_c('p',[_vm._v(\"Se puede escalar horizontalmente de varias maneras, existe un libro que es el de “Art of Scalability” de Michael Fisher que nos propone un interesante modelo de cubo de como escalar.\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/distribucion/image9.png\")}}),_c('p',[_vm._v(\"En esta representación el punto de origen concuerda con el sistema monolítico en una sola instancia, y la arista de arriba a la derecha del cubo, nos representa la máxima escalabilidad de la aplicación. Y como el cubo es en tres dimensiones, eso nos dice que no solo hay una manera de escalar nuestra aplicación sino que hay varias que incluso podríamos llegar a combinar, ahora veremos cada una de las dimensiones\")]),_c('h3',{attrs:{\"id\":\"eje-x-clonacion\"}},[_vm._v(\"Eje X - Clonacion \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#eje-x-clonacion\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Esta manera de escalar, es la que vimos al final de la sección anterior, es cuando tenemos varias réplicas de nuestra aplicación monolítica y que pueden o bien acceder a una bbdd. Otros temas a mencionar que no se hayan hecho antes es el tema de que al existir varias copias de nuestro sistema, tendremos que de alguna manera garantizar que los datos se mantengan consistentes, ya que varias copias van a estar accediendo a los mismos datos, por lo que tendremos que bien o implementar un sistema de lockeo de los datos o usar algo que nos garantice esto, que bien puede ser la base de datos. Este esquema no nos resuelve aún el problema de una aplicación de alta complejidad, o sea.. Que aun nuestro código va a estar aun organizado como una aplicación monolítica, esto puede no ser una desventaja si no tenemos un basecode demasiado grande pero si lo fuese, por temas de complejidad o incluso de uso de servicios de terceros, tal vez sea un problema a nivel de desarrollo o mantenimiento.\")]),_c('h3',{attrs:{\"id\":\"eje-y-descomposición-funcional\"}},[_vm._v(\"Eje Y - Descomposición Funcional \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#eje-y-descomposición-funcional\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"En vez de tener varias instancias o nodos del mismo sistema, cada uno conteniendo todo el código del sistema, en este eje se va a descomponer nuestra aplicación entre los distintos nodos, esto es lo que se conoce generalmente como microservicios, y cada uno de estos va a ser responsable de una función.\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/distribucion/image8.png\")}}),_c('p',[_vm._v(\"Y como podemos descomponer a nuestra aplicación?\")]),_c('ul',[_c('li',[_c('p',[_vm._v(\"Podemos descomponer por medio de la función técnica de lo que hace ya sea un endpoint, o una funcionalidad, por ejemplo, se puede descomponer una aplicación en servicios de capacidad (capability-services) como login, usuarios, productos, etc. Abajo hay un pequeño ejemplo de un servicio de discusión, estilo reddit.\")])]),_c('li',[_c('p',[_vm._v(\"Otra manera de descomponer es dividir por dominios a la aplicación, o sea por los recursos pero como un todo, y no por las funcionalidades, o sea si tenemos una aplicación de venta, podemos dividir la aplicación en: servicio al cliente, ventas, catalogo para el usuario. Esta división es más bien por entidades (Entity-Services)\")])])]),_c('p',[_vm._v(\"También pueden combinarse esta división o usarse otro tipo de división del sistema, el esquema no es estricto en este sentido, por lo que nos da la libertad de escalar nuestra aplicación o más bien de dividirla de acuerdo a nuestro dominio. No hay ya necesidad de clonar toda la aplicación de esta manera. El problema es que esto genera otras desventajas y son que ahora nuestros microservicios además de trabajar con la bbdd a veces tendrán que coordinarse los unos a los otros mediante mensajes o requests incluso, también puede haber un incremento en el uso del ancho de banda.\")]),_c('h3',{attrs:{\"id\":\"eje-z-shardingdata-partitioning\"}},[_vm._v(\"Eje Z - Sharding/Data Partitioning \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#eje-z-shardingdata-partitioning\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Hasta ahora vimos cómo dividir nuestro sistema pero a nivel de organización de la lógica de nuestros componentes, puede existir el caso en el que si estamos persistiendo los datos de nuestro sistema, el mismo aún tenga una sola base de datos o a lo sumo este replicada en otras bases, pero que en suma estas réplicas son solo una copia de todo el estado de la base de datos principal, por lo que en ese esquema solo una base de datos admite escrituras y todas puedan ser leídas. Dependiendo del tipo de réplica, la misma puede ser hecha ni bien se escriben los valores o a veces pueden tenerse escrituras que no garantice que una vez que se escribió el valor en la base de datos, el mismo esté replicado en las otras bases, esto se llama replicación asincrónica. Pueden ver mas de esto en el siguiente (link)[https://www.cybertec-postgresql.com/en/services/postgresql-replication/synchronous-synchronous-replication/]\")]),_c('p',[_vm._v(\"Pero aún tenemos el estado, a lo sumo replicado, tal como lo teníamos con los servidores al escalarlo mediante clonación (eje x), y solo podemos tener una escritura a la vez, esto puede ser un cuello de botella si existen muchas escrituras sobre la base de datos. El esquema de este eje z, es el de dividir la base de datos o el estado en subsets, por lo que podemos dividir el estado bajo un criterio determinado, por ejemplo si tenemos un estado que son los productos, bien podemos dividir los mismos por rango de letras como el siguiente ejemplo.\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/distribucion/image4.png\")}}),_c('p',[_vm._v(\"Y como tenemos ahora el estado particionado, vamos a tener que tener algo que nos pueda despachar al nodo correcto los pedidos de lectura o escritura, que puede ser un load balancer, o bien que los nodos de estado o persistencia se puedan hablar entre ellos para devolver o persistir el estado, esto último es en el caso en el que no se tenga una base de datos relacional o tan solo se pueda implementar un shardeo de este tipo. Lo interesante de este esquema es que no tenemos más de un nodo de datos que pueda aceptar escrituras, aunque solo habrá una escritura por subset.\")]),_c('h2',{attrs:{\"id\":\"combinación-de-ejes\"}},[_vm._v(\"Combinación de Ejes \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#combinación-de-ejes\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Como el modelo de escala es tridimensional, se puede incluso combinar para que nuestra arquitectura sea más robusta, por ejemplo, podemos tener un esquema de microservicios en el que además cada servicio, como el de login, puede esta clonado y tener más de un servicio de login disponible y el mismo esté tan solo distribuido por un segundo nivel de load balancer que redirige los request con un criterio, que nos da un esquema así? Como dijimos antes, mayor robustez, si bien escalar por microservicios divide la carga, aun todos los usuarios en gran medida, deberán loguearse, y ademas al separar los servicios, aun seguimos teniendo un solo punto de fallo, por lo que para que el servicio esté disponible si el servidor de login se cae, es el de escalar después este microservicio por medio de clonar el mismo en varios servidores idénticos con este microservicios.\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/distribucion/image5.png\")}}),_c('h3',{attrs:{\"id\":\"sesiones\"}},[_vm._v(\"Sesiones \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#sesiones\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Otro tema que no hablamos antes es sobre las sesiones en nuestra aplicación ahora distribuida, en el primer caso que es el de replicar la aplicación, si tenemos varios nodos con toda nuestra aplicación y un load balancer, puede ocurrir que un usuario se loguee en un nodo y luego en otro request, pueda ser redirigido a otro nodo donde no se tiene registro de su login, como se resuelve esto? O bien teniendo un lugar, como una base de datos aparte donde se registren las sesiones o bien se puede optar por un esquema de sticky sessions\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/distribucion/image10.png\")}}),_c('p',[_vm._v(\"ELs sticky sessions permiten mediante una cookie, saber contra qué servidor se autenticaron, además de otra información de la sesión, el load balancer sabe a qué nodo redirigir los requests de un usuario en particular sobre un modelo de cloning o en el que nuestra aplicación esta solo replicada, en otros tipo de arquitecturas como microservicios, puede ser que no sea necesario a menos que exista solo nodo de login de usuarios.\")]),_c('h3',{attrs:{\"id\":\"heartbeat-y-gossip\"}},[_vm._v(\"Heartbeat y gossip \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#heartbeat-y-gossip\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"A veces es necesario saber si un nodo o servicio esta disponible y que sepamos que no este caido, a veces si es solo un servicio que estamos exponiendo podemos tan solo tener un healthcheck, que es solo un endpoint de nuestro sistema (algo mas de detalle en \"),_c('a',{attrs:{\"href\":\"https://microservices.io/patterns/observability/health-check-api.html\"}},[_vm._v(\"https://microservices.io/patterns/observability/health-check-api.html\")]),_vm._v(\", puede ser incluso implementado si no estamos en un esquema de microservicios) para confirmar si nuestro servicio esta disponible y puede admitir nuevos pedidos, pero esto es en general a nivel de HHTP, por lo que si un nodo nuestro se cae podriamos no llegar a poder responder un request hecho a nuestro endpoint. Entonces cómo podemos detectar fallas en nodos de nuestro sistema si no es solo mediante un chequeo de healthcheck o un mecanismo similar? Podemos hacerlo mediante conexiones de tcp en las que se pase un token o un bit o un valor que se van a ir pasando entre los nodos, y de esta manera cuando un nodo deje de pasar ese valor después de un tiempo prolongado, muy superior al tiempo entre emisión de este valor, se puede tomar al nodo como caido. Esto se lo conoce como heartbeat, y es útil para conocer si se cayeron los nodos sin depender de un healthcheck, ya que pudo existir una caída del nodo y que no sea un problema lógico o de algún componente o servicio externo. Lo recomendable es que la información de heartbeat este en una vía o conexión distinta a lo que se usaría para intercambiar información entre nodos o servidores. Otra manera un poco mas bien ordenada o distribuida, de cómo notificar a otros servidores y no hacer múltiples conexiones entre nodos, para usar heartbeat, es el de usar un protocolo de gossip. Esto permite que se intercambie más información entre servidores, y que no sea solo un simple valor o bit, por ejemplo, puede ser información tal como por ejemplo: “se cayó el nodo de login x”, o “volvió a estar disponible el nodo que contiene la base de datos”. Se puede encontrar un poco más de información en el siguiente \"),_c('a',{attrs:{\"href\":\"https://github.com/gossiperl/gossiperl/wiki/gossip-in-computer-science\"}},[_vm._v(\"link\")])]),_c('p',[_vm._v(\"Videos que nos parecieron interesantes\")]),_c('p',[_c('a',{attrs:{\"href\":\"https://www.youtube.com/watch?v=PE4gwstWhmc\"}},[_vm._v(\"How We've Scaled Dropbox\")])]),_c('p',[_c('a',{attrs:{\"href\":\"https://www.youtube.com/watch?v=Y6Ev8GIlbxc\"}},[_vm._v(\"Distributed Systems in One Lesson by Tim Berglund\")])])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./distribucion.md?vue&type=template&id=be777878&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","module.exports = __webpack_public_path__ + \"img/image5.db96ab35.png\";"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-2d0a34c9.b72d6dd3.js b/js/chunk-2d0a34c9.b72d6dd3.js new file mode 100644 index 0000000..0fe114d --- /dev/null +++ b/js/chunk-2d0a34c9.b72d6dd3.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0a34c9"],{"021b":function(e,s,a){"use strict";a.r(s);var r=function(){var e=this,s=e.$createElement;e._self._c;return e._m(0)},n=[function(){var e=this,s=e.$createElement,a=e._self._c||s;return a("section",[a("h2",{attrs:{id:"anteriormente-en-arquitecturas-concurrentes"}},[e._v("Anteriormente... en Arquitecturas Concurrentes "),a("a",{staticClass:"header-anchor",attrs:{href:"#anteriormente-en-arquitecturas-concurrentes"}},[e._v("¶")])]),a("p",[e._v("Hasta ahora trabajamos sobre un modelo de concurrencia basado en un "),a("em",[e._v("event loop")]),e._v(". En este esquema, cada evento se procesa completamente antes de pasar a la ejecución del próximo, y todo esto ocurre en un único thread.")]),a("p",[e._v("Una ventaja que esto implica es que cuando una función se está ejecutando, tenemos la seguridad de que no va a ser interrumpida por el planificador hasta que termine, lo cual evita los problemas de concurrencia tradicionales que habíamos visto al usar "),a("em",[e._v("threads")]),e._v(" y "),a("em",[e._v("locks")]),e._v(". Y esto lo logramos gracias a que el event loop le provee un "),a("em",[e._v("orden")]),e._v(" a la ejecución concurrente; la serializa.")]),a("p",[e._v("Las corrutinas nos permiten lograr algo similar, sin utilizar (necesariamente) un event loop.")]),a("h2",{attrs:{id:"caso-practico"}},[e._v("Caso practico "),a("a",{staticClass:"header-anchor",attrs:{href:"#caso-practico"}},[e._v("¶")])]),a("p",[e._v('En el desarrollo de software muchas veces solemos enfatizar en lograr que los algoritmos sean más eficientes, es decir que completen los cálculos lo más rápido posible. Pero muchos sistemas dedican su tiempo a "no hacer cálculos", sino que mantienen abiertas muchas conexiones que son lentas. Estos programas presentan un desafío muy diferente: atender una gran cantidad de eventos de red de manera eficiente. Un enfoque actual de este problema es la E/S asíncrona o "asincrónica".')]),a("p",[e._v("Tomemos el ejemplo de un crawler (rastreador web) sencillo. El crawler es una aplicación asíncrona que espera muchas respuestas, pero realiza pocos cálculos. Cuantas más páginas pueda extraer a la vez, va a poder terminar antes.")]),a("h2",{attrs:{id:"el-enfoque-tradicional"}},[e._v("El enfoque tradicional "),a("a",{staticClass:"header-anchor",attrs:{href:"#el-enfoque-tradicional"}},[e._v("¶")])]),a("p",[e._v("¿Cómo hacemos que el crawler sea concurrente? Tradicionalmente, crearíamos un grupo hilos. Cada uno se encargaría de descargar una página a la vez a través de un socket. Por ejemplo, para descargar una página de bla.com:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("import")]),e._v(" sys\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("import")]),e._v(" requests\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("import")]),e._v(" threading\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("from")]),e._v(" bs4 "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("import")]),e._v(" BeautifulSoup\n\n"),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("get_urls_from_root")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(root_url)")]),e._v(":")]),e._v("\n soup = BeautifulSoup(reqs.text, "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'html.parser'")]),e._v(")\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("return")]),e._v(" soup.find_all("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'a'")]),e._v("):\n\n"),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("fetch")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(url)")]),e._v(":")]),e._v("\n r = requests.get(url)\n parse_response(r.content) "),a("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("#Content of the response, in bytes")]),e._v("\n\n"),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("parse_response")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(response)")]),e._v(":")]),e._v("\n hace_su_magia(response)\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("if")]),e._v(" __name__ == "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'__main__'")]),e._v(":\n root_url = sys.argv["),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v("]\n urls = [link.get("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'href'")]),e._v(") "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("for")]),e._v(" link "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("in")]),e._v(" get_urls_from_root(root_url)]\n\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("for")]),e._v(" url "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("in")]),e._v(" urls:\n t = threading.Thread(target=fetch, args=(i,))\n t.start()\n")])]),a("p",[e._v("Este es un ejemplo simple que hace lo mencionado anteriormente. Analicemos con más detalle lo que esta realmente haciendo la función "),a("strong",[e._v("fetch")]),e._v(", escribámosla de vuelta sin usar la libreria requests.")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("fetch")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(url)")]),e._v(":")]),e._v("\n sock = socket.socket()\n sock.connect(("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'bla.com'")]),e._v(", "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("80")]),e._v("))\n request = "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'GET {} HTTP/1.0\\r\\nHost: bla.com\\r\\n\\r\\n'")]),e._v(".format(url)\n sock.send(request.encode("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'ascii'")]),e._v("))\n response = "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("b''")]),e._v("\n chunk = sock.recv("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("4096")]),e._v(")\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("while")]),e._v(" chunk:\n response += chunk\n chunk = sock.recv("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("4096")]),e._v(")\n\n parse_response(response)\n")])]),a("blockquote",[a("p",[e._v("Nota: De esa forma la manipulación de sockets, el connect y el recv estan de forma explicita y nos obliga a hablar de estas cosas que vimos en algún pasado lejano programando en C y leyendo la guia Beej :P")])]),a("h3",{attrs:{id:"entendiendo-el-problema"}},[e._v("Entendiendo el problema "),a("a",{staticClass:"header-anchor",attrs:{href:"#entendiendo-el-problema"}},[e._v("¶")])]),a("p",[e._v("Si se crea un hilo por cada request (solicitud), a medida que aumente el número de requests simultáneas, aumenta la posibilidad de quedarse sin memoria antes de que se agoten los sockets. Podemos evitar la necesidad de subprocesos (hilos), mediante el uso de E/S asincrónica.")]),a("p",[e._v("Por defecto, las operaciones con sockets son bloqueantes, cuando el hilo llama a un método como connect o recv, se detiene hasta que la operación se completa. En consecuencia, para descargar muchas páginas a la vez, necesitamos muchos hilos. Una aplicación sofisticada amortiza el costo de la creación de hilos al mantener los inactivos en un grupo o pool y luego revisarlos para reutilizarlos para tareas posteriores; se suele hacer lo mismo con los sockets en un grupo de conexiones.")]),a("p",[e._v("Sin embargo, los hilos son costosos y los sistemas operativos imponen una variedad de límites estrictos en la cantidad que se puede tener. Un hilo de Python ocupa alrededor de 50k de memoria y el inicio de decenas de miles de hilos puede provocar fallas. Si escalamos hasta decenas de miles de operaciones simultáneas en sockets concurrentes, nos quedamos sin hilos antes de quedarnos sin sockets. La sobrecarga por hilos o los límites del sistema en subprocesos son el cuello de botella.")]),a("p",[e._v("Dan Kegel en su artículo "),a("a",{attrs:{href:"http://www.kegel.com/c10k.html"}},[e._v("The C10K problem")]),a("sup",{staticClass:"footnote-ref"},[a("a",{attrs:{href:"#fn1",id:"fnref1"}},[e._v("[1]")])]),e._v(", describe las limitaciones de utilizar multiples hilos para resolver problemas de concurrencia de E/S.")]),a("p",[e._v('Kegel utilizo el término "C10K" en 1999. Diez mil conexiones no suenan ahora como lo sonaban antes, pero el problema ha cambiado sólo en tamaño, no en especie. En aquel entonces, usar un hilo por conexión para C10K no era práctico. Ahora el límite es en órdenes de magnitud más elevado. De hecho, nuestro crawler de juguete funcionaría bien con hilos. Sin embargo, para aplicaciones a gran escala, con cientos de miles de conexiones, el límite permanece; hay un límite más allá del cual la mayoría de los sistemas aún pueden crear sockets, pero se han quedado sin hilos. ¿Cómo podemos superar esto?')]),a("h2",{attrs:{id:"async"}},[e._v("Async "),a("a",{staticClass:"header-anchor",attrs:{href:"#async"}},[e._v("¶")])]),a("p",[e._v("Los frameworks de E/S asincrónicos realizan operaciones simultáneas en un solo hilo utilizando sockets no bloqueantes. En nuestro crawler asíncrono, configuramos el socket no bloqueante antes de comenzar a conectarnos al servidor:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[e._v("sock = socket.socket()\nsock.setblocking("),a("span",{pre:!0,attrs:{class:"hljs-literal"}},[e._v("False")]),e._v(")\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("try")]),e._v(":\n sock.connect(("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'bla.com'")]),e._v(", "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("80")]),e._v("))\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("except")]),e._v(" BlockingIOError:\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("pass")]),e._v("\n")])]),a("p",[e._v("Un socket no bloqueante genera una excepción al realizar el "),a("em",[e._v("connect")]),e._v(", incluso cuando funciona normalmente. Esta excepción replica el comportamiento irritante de la función C subyacente, que establece "),a("em",[e._v("errno")]),e._v(" en "),a("em",[e._v("EINPROGRESS")]),e._v(" para indicarle que ha comenzado.")]),a("p",[e._v("Ahora nuestro crawler necesita una forma de saber cuándo se establece la conexión, para poder enviar la solicitud HTTP. Simplemente podríamos seguir intentándolo en un loop. Este método no puede esperar eventos de manera eficiente en múltiples sockets. En la antigüedad, la solución de BSD Unix a este problema era select, una función de C que espera a que ocurra un evento en un socket sin bloqueo o en un pequeño vector de ellos. Hoy en día, la demanda de aplicaciones con un gran número de conexiones ha llevado a reemplazos como poll, luego kqueue en BSD y epoll en Linux. Estas API son similares a las de select, pero funcionan bien con un gran número de conexiones.")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("from")]),e._v(" selectors "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("import")]),e._v(" DefaultSelector, EVENT_WRITE\n\nselector = DefaultSelector()\n\nsock = socket.socket()\nsock.setblocking("),a("span",{pre:!0,attrs:{class:"hljs-literal"}},[e._v("False")]),e._v(")\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("try")]),e._v(":\n sock.connect(("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'bla.com'")]),e._v(", "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("80")]),e._v("))\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("except")]),e._v(" BlockingIOError:\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("pass")]),e._v("\n\n"),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("connected")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(":")]),e._v("\n selector.unregister(sock.fileno())\n print("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'connected!'")]),e._v(")\n\nselector.register(sock.fileno(), EVENT_WRITE, connected)\n")])]),a("p",[e._v("Procesamos las notificaciones de E/S a medida que el selector las recibe, en un loop:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("loop")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(":")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("while")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-literal"}},[e._v("True")]),e._v(":\n events = selector.select()\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("for")]),e._v(" event_key, event_mask "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("in")]),e._v(" events:\n callback = event_key.data\n callback()\n")])]),a("p",[e._v('Aquí hemos logrado tener "concurrencia", pero no "paralelismo". Es decir, construimos un pequeño sistema que superpone E/S. Es capaz de iniciar nuevas operaciones mientras otras están "en vuelo". No utiliza varios núcleos para ejecutar cálculos en paralelo. Este sistema está diseñado para problemas I/O-bound, no con CPU-bound.')]),a("p",[a("strong",[e._v("La iteración final en nuestro ejemplo seria refactorizar esto para que use corrutinas, pero antes necesitamos ver rápidamente lo que son para entender en que nos van a ayudar.")])]),a("blockquote",[a("p",[e._v("Nota al margen: las corrutinas no son nada nuevo. C++, Smalltalk, Erlang y muchos más (¡hasta PHP!) las tienen desde hace mucho. Pero recientemente han conseguido cierta notoriedad en la industria por su uso en lenguajes como Go, Kotlin y Python.")])]),a("p",[e._v("Para entender como funcionan, primero veamos "),a("strong",[e._v("iteradores")]),e._v(" y "),a("strong",[e._v("generadores")]),e._v("...")]),a("img",{staticClass:"center",attrs:{src:"https://www.salesoptimize.com/wp-content/uploads/2016/11/76e3344703e128bed674b84014fa01ab.jpg"}}),a("h2",{attrs:{id:"iteradores-y-generadores"}},[e._v("Iteradores y generadores "),a("a",{staticClass:"header-anchor",attrs:{href:"#iteradores-y-generadores"}},[e._v("¶")])]),a("p",[e._v("Un "),a("strong",[e._v("generador")]),e._v(" es un tipo especial de subrutina, pensando en teoría de conjuntos, podemos decir que el conjunto generador es un subconjunto de corrutina.")]),a("blockquote",[a("p",[e._v("Esta bien, pero entonces.. ¿qué es un generador?")])]),a("p",[e._v("También podemos decir que un "),a("strong",[e._v("generador")]),e._v(" es una función que produce una secuencia de resultados, en lugar de un único valor.")]),a("p",[e._v("Un "),a("strong",[e._v("iterador")]),e._v(" es un objeto que permite al programador recorrer un contenedor (colección de elementos) por ejemplo una lista. Una manera de implementar iteradores es utilizar un "),a("strong",[e._v("generador")]),e._v(", que como comentamos antes, puede producir valores para quien lo llama varias veces (en lugar de devolver sólo uno).")]),a("p",[e._v('Cuando invocamos a una función generadora se crea un "objeto generador" que permanece en un estado pausado, no se ejecuta automáticamente.')]),a("p",[e._v("Veámoslo con un ejemplo:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("cuenta_regresiva")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(numero)")]),e._v(":")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("while")]),e._v(" numero > "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v(":\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("yield")]),e._v(" numero\n numero -= "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v("\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("for")]),e._v(" numero "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("in")]),e._v(" cuenta_regresiva("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("5")]),e._v("):\n print(numero)\n")])]),a("blockquote",[a("p",[e._v("El resultado de ejecutar el script es: 5 4 3 2 1")])]),a("p",[e._v('Acá podemos ver a el generador en su estado pausado, por esta propiedad los solemos usar en un for, y si es aplicable en un for, se deduce que el estado pausado es un objeto iterable. Llamando a next se ejecutan todas las lineas hasta volver al "segundo" yield')]),a("blockquote",[a("p",[e._v("x = cuenta_regresiva(5) x next(x) 4")])]),a("p",[e._v("A continuación se puede ver un ejemplo de un generador que devuelve los números de Fibonacci:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("fibonacci")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(":")]),e._v("\n a, b = "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v(", "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("while")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-literal"}},[e._v("True")]),e._v(":\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("yield")]),e._v(" a\n a, b = b, a+b\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("for")]),e._v(" numero "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("in")]),e._v(" fibonacci(): "),a("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("# Utilización de generador como iterador")]),e._v("\n print(numero)\n")])]),a("h3",{attrs:{id:"corrutinas-basadas-en-generadores"}},[e._v("Corrutinas basadas en generadores "),a("a",{staticClass:"header-anchor",attrs:{href:"#corrutinas-basadas-en-generadores"}},[e._v("¶")])]),a("p",[e._v("Es posible implementar corrutinas basadas en generadores, de hecho, hasta Python 2.5 las corrutinas estaban hechas de esta forma, con la ayuda de una rutina de despachador de nivel superior (un trampolín, esencialmente) que pasa el control explícitamente a los generadores secundarios.")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("coro")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(":")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("#yield usado de esta forma creamos una corrutina que hace más que generar valores, si no que también consume")]),e._v("\n hello = "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("yield")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v('"Soy una corrutina"')]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("yield")]),e._v(" hello\n\nc = coro()\nprint(next(c))\nprint(c.send("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v('", basada en generadores"')]),e._v("))\n")])]),a("h2",{attrs:{id:"qué-es-una-corrutina"}},[e._v("¿Qué es una corrutina? "),a("a",{staticClass:"header-anchor",attrs:{href:"#qué-es-una-corrutina"}},[e._v("¶")])]),a("p",[e._v("Una corrutina es similar a una subrutina tradicional (piensen en las funciones/procedimientos que vieron en Algoritmos), pero con la diferencia de que, mientras que la salida de una subrutina pone fin a su ejecución, una corrutina puede además "),a("strong",[e._v("suspenderse")]),e._v(", cediendo el control a otra hasta que se le indique que debe "),a("strong",[e._v("retomar")]),e._v(" su ejecución.")]),a("p",[e._v("Para entender mejor a qué nos referimos con esto, veamos un ejemplo en Python, uno de los lenguajes que cuenta con soporte para corrutinas.")]),a("h4",{attrs:{id:"sin-corrutinas"}},[e._v("Sin corrutinas "),a("a",{staticClass:"header-anchor",attrs:{href:"#sin-corrutinas"}},[e._v("¶")])]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("import")]),e._v(" time\n\n"),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("io")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(":")]),e._v("\n time.sleep("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(")\n print("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'1'")]),e._v(")\n time.sleep("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(")\n print("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'2'")]),e._v(")\n time.sleep("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(")\n print("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'3'")]),e._v(")\n\n"),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("main")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(tareas)")]),e._v(":")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("for")]),e._v(" tarea "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("in")]),e._v(" tareas:\n io()\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("if")]),e._v(" __name__ == "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'__main__'")]),e._v(":\n tiempo = time.perf_counter()\n main(range("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("3")]),e._v("))\n tiempo2 = time.perf_counter() - tiempo\n print("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("f'Tiempo total: "),a("span",{pre:!0,attrs:{class:"hljs-subst"}},[e._v("{tiempo2:"),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0.2")]),e._v("f}")]),e._v(" segundos'")]),e._v(")\n")])]),a("p",[e._v("Este código imprime:")]),a("blockquote",[a("p",[e._v("1 2 3 1 2 3 1 2 3 Tiempo total: 9.01 segundos")])]),a("p",[e._v("Podemos ver que cada ciclo de IOs de cada tarea se ejecuta y termina una atrás de la otra. ¿Qué pasa si agregamos corrutinas?")]),a("h4",{attrs:{id:"con-corrutinas"}},[e._v("Con corrutinas "),a("a",{staticClass:"header-anchor",attrs:{href:"#con-corrutinas"}},[e._v("¶")])]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("import")]),e._v(" time\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("import")]),e._v(" asyncio\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("async")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("io")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(":")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("#Hay un async adelante del def, asi que soy una corrutina :D")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("await")]),e._v(" asyncio.sleep("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(")\n print("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(")\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("await")]),e._v(" asyncio.sleep("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(")\n print("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("2")]),e._v(")\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("await")]),e._v(" asyncio.sleep("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(")\n print("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("3")]),e._v(")\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("async")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("main")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(":")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("await")]),e._v(" asyncio.gather(io(), io(), io())\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("if")]),e._v(" __name__ == "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'__main__'")]),e._v(":\n tiempo = time.perf_counter()\n asyncio.run(main())\n tiempo2 = time.perf_counter() - tiempo\n print("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("f'Tiempo total: "),a("span",{pre:!0,attrs:{class:"hljs-subst"}},[e._v("{tiempo2:"),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0.2")]),e._v("f}")]),e._v(" segundos'")]),e._v(")\n")])]),a("blockquote",[a("p",[e._v("1 1 1 2 2 2 3 3 3 Tiempo total: 3.00 segundos")])]),a("p",[e._v("La diferencia en los tiempos es notable. También observamos que el orden de ejecución fue distinto en este caso.")]),a("h2",{attrs:{id:"cómo-funcionan"}},[e._v("¿Cómo funcionan? "),a("a",{staticClass:"header-anchor",attrs:{href:"#cómo-funcionan"}},[e._v("¶")])]),a("p",[e._v("Cuando usamos corrutinas, no hay intervención del SO. Hay un sólo proceso, un sólo thread. Entonces... ¿qué es lo que esta pasando?")]),a("p",[e._v('Lo que ocurre es que las corrutinas liberan la CPU cuando están en "tiempo de espera" ('),a("code",{pre:!0},[e._v("await")]),e._v("), permitiendo que otras puedan usar la CPU.")]),a("p",[e._v("Podemos decir que es como una simultánea de ajedrez, en donde una persona juega contra dos o más. Hace un movimiento y no se queda esperando la respuesta del oponente en ese tablero, sino que pasa al siguiente y realiza un movimiento ahí. De esa forma, trata las partidas (tareas) de forma concurrente, lo que resulta en que se terminen en menos tiempo.")]),a("img",{staticClass:"center",attrs:{src:"https://i.ytimg.com/vi/Hp6827K1pFE/hqdefault.jpg"}}),a("p",[e._v("Seguro están pensando:")]),a("blockquote",[a("p",[e._v("Un momento... esto se parece a un thread")])]),a("p",[e._v("Lo que nos lleva a nuestra próxima sección...")]),a("h2",{attrs:{id:"corrutinas-vs-threads"}},[e._v("Corrutinas vs Threads "),a("a",{staticClass:"header-anchor",attrs:{href:"#corrutinas-vs-threads"}},[e._v("¶")])]),a("p",[e._v("La diferencia fundamental entre corrutinas y threads se da en la forma en la que se lleva a cabo la multitarea.")]),a("p",[e._v("Los threads, como ya vimos, manejan un esquema de "),a("strong",[e._v("multitarea apropiativa")]),e._v(" (en inglés, "),a("em",[e._v("preemptive multitasking")]),e._v("), donde el planificador es el encargado de asignar intervalos de uso de CPU a los threads que se están ejecutando, desalojándolos cuando este termina.")]),a("p",[e._v("Las corrutinas, en contraposición, permiten tener "),a("strong",[e._v("multitarea cooperativa")]),e._v(" ("),a("em",[e._v("cooperative/non-preemptive multitasking")]),e._v("). Esto significa que el cambio de contexto no es controlado por el planificador, sino que cada corrutina es la encargada de ceder el control cuando está inactiva o bloqueda.")]),a("p",[e._v('Otra diferencia, presente al menos en la visión "tradicional" de corrutinas, es que '),a("strong",[e._v("las corrutinas proveen concurrencia pero no paralelismo")]),e._v(". De esta forma, evitan problemas de concurrencia, ya que corren en un "),a("strong",[e._v("único contexto de ejecución")]),e._v(", y además "),a("strong",[e._v("controlan cuándo se suspenden")]),e._v(" (en vez de que el planificador las interrumpa en puntos arbitrarios).")]),a("blockquote",[a("p",[e._v("Las corrutinas ocupan menos memoria que los hilos (3k por corrutina vs 50k por hilo).")])]),a("p",[e._v("Una ventaja más que las corrutinas tienen sobre los hilos es que su funcionamiento no involucra llamadas al sistema bloqueantes para su creación ni para el cambio de contexto, ya que todo se maneja al nivel de la aplicación.")]),a("p",[e._v("Interesante comparación de cuando usar corrutinas y cuando usar threads en Kotlin."),a("sup",{staticClass:"footnote-ref"},[a("a",{attrs:{href:"#fn2",id:"fnref2"}},[e._v("[2]")])])]),a("h2",{attrs:{id:"cómo-se-declaran-y-ejecutan-en-python"}},[e._v("¿Cómo se declaran y ejecutan en Python? "),a("a",{staticClass:"header-anchor",attrs:{href:"#cómo-se-declaran-y-ejecutan-en-python"}},[e._v("¶")])]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("import")]),e._v(" asyncio\n\n"),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("print_loco")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(algo)")]),e._v(":")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("return")]),e._v(" print(algo,"),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'loco'")]),e._v(")\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("async")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("print_re_loco")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(algo)")]),e._v(":")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("return")]),e._v(" print(algo,"),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'loco'")]),e._v(")\n")])]),a("blockquote",[a("p",[e._v("print_loco")])]),a("blockquote",[a("p",[e._v("")])]),a("blockquote",[a("p",[e._v("print_re_loco")])]),a("blockquote",[a("p",[e._v("")])]),a("p",[e._v("Las dos funciones lucen similares, la diferencia vamos a notar cuando las usamos:")]),a("blockquote",[a("p",[e._v("print_loco('bla')")])]),a("blockquote",[a("p",[e._v("bla loco")])]),a("p",[e._v("Nada fuera de lo esperado.")]),a("blockquote",[a("p",[e._v("print_re_loco('algo')")])]),a("blockquote",[a("p",[e._v("")])]),a("p",[e._v('Nos retorna un objeto "corrutina" que por defecto no se va a planificar. Entonces, ¿cómo hago que se ejecute? Bueno, hay tres formas distintas para hacer eso.')]),a("p",[a("strong",[e._v("1-")]),e._v(" Usando la función "),a("code",{pre:!0},[e._v("run")]),e._v(" del módulo "),a("code",{pre:!0},[e._v("asyncio")]),a("sup",{staticClass:"footnote-ref"},[a("a",{attrs:{href:"#fn3",id:"fnref3"}},[e._v("[3]")])])]),a("blockquote",[a("p",[e._v("coro = print_re_loco('algo')")])]),a("blockquote",[a("p",[e._v("asyncio.run(coro)")])]),a("blockquote",[a("p",[e._v("algo loco")])]),a("p",[a("strong",[e._v("2-")]),e._v(" Usando "),a("code",{pre:!0},[e._v("await")]),e._v(" en una corrutina")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("import")]),e._v(" asyncio\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("async")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("say_after")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(delay, what)")]),e._v(":")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("await")]),e._v(" asyncio.sleep(delay)\n print(what)\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("async")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("main")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(":")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("await")]),e._v(" say_after("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(", "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'hello'")]),e._v(")\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("await")]),e._v(" say_after("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("2")]),e._v(", "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'world'")]),e._v(")\n")])]),a("blockquote",[a("p",[e._v("asyncio.run(main())")])]),a("blockquote",[a("p",[e._v("hello")])]),a("blockquote",[a("p",[e._v("world")])]),a("p",[a("em",[e._v("Nota: acá usamos "),a("code",{pre:!0},[e._v("run")]),e._v(" para ejecutar la corrutina "),a("code",{pre:!0},[e._v("main")]),e._v(" y "),a("code",{pre:!0},[e._v("await")]),e._v(" para ejecutar las corrutinas "),a("code",{pre:!0},[e._v("say_after")]),e._v(".")])]),a("p",[a("strong",[e._v("3-")]),e._v(" Con la función "),a("code",{pre:!0},[e._v("create_task")]),e._v(" de "),a("code",{pre:!0},[e._v("asyncio")]),e._v(", que ejecuta corrutinas concurrentemente "),a("em",[e._v("wrappeándolas")]),e._v(" en "),a("code",{pre:!0},[e._v("Tasks")]),e._v(", usando por detrás un "),a("strong",[e._v("event loop")]),e._v(" para planificarlas.")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("import")]),e._v(" asyncio\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("async")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("main")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(":")]),e._v("\n task1 = asyncio.create_task(say_after("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(", "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'hello'")]),e._v("))\n task2 = asyncio.create_task(say_after("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("2")]),e._v(", "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'world'")]),e._v("))\n\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("await")]),e._v(" task1\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("await")]),e._v(" task2\n")])]),a("p",[a("em",[e._v("Nota: "),a("code",{pre:!0},[e._v("create_task")]),e._v(" envía la corrutina al event loop, permitiendo que corra en segundo plano. "),a("code",{pre:!0},[e._v("gather")]),e._v(" hace algo muy parecido, pero podemos decir que es conveniente usarlo cuando nos interesa hacer algo con el resultado de las corrutinas.")])]),a("h2",{attrs:{id:"qué-pasa-si-ejecuto-código-bloqueante-dentro-de-una-corrutina"}},[e._v("¿Qué pasa si ejecuto código bloqueante dentro de una corrutina? "),a("a",{staticClass:"header-anchor",attrs:{href:"#qué-pasa-si-ejecuto-código-bloqueante-dentro-de-una-corrutina"}},[e._v("¶")])]),a("p",[e._v("Si observaron con detalle se habrán dado cuenta de que cuando se usa sleep para suspender a la corrutina, se esta usando "),a("code",{pre:!0},[e._v("asyncio.sleep")]),e._v(" en lugar de "),a("code",{pre:!0},[e._v("time.sleep")]),e._v(". Esto es porque el segundo es bloqueante. Entonces como ya dedujeron, las operaciones bloqueantes bloquean todo el thread del sistema operativo subyacente.")]),a("p",[e._v("Pero hay formas de evitarlo :D!, lo que se hace es que correr estas tareas "),a("strong",[e._v("bloqueantes")]),e._v(" y otras que vamos a llamar "),a("strong",[e._v("CPU-bound-intensive")]),e._v(", sea conveniente ejecutarlas en otro thread. Concretamente en "),a("strong",[e._v("Python")]),e._v(" usando "),a("code",{pre:!0},[e._v("loop.run_in_executor()")]),e._v(" "),a("a",{attrs:{href:"https://docs.python.org/3/library/asyncio-dev.html#running-blocking-code"}},[e._v("Running Blocking Code")])]),a("p",[a("em",[e._v("Nota: también es posible setear un timeout para que cuando se cumpla, se corte su ejecución "),a("a",{attrs:{href:"https://docs.python.org/3/library/asyncio-task.html#timeouts"}},[e._v("ver timeouts")]),e._v(" .")])]),a("h2",{attrs:{id:"corrutinas-vs-generadores"}},[e._v("Corrutinas vs Generadores "),a("a",{staticClass:"header-anchor",attrs:{href:"#corrutinas-vs-generadores"}},[e._v("¶")])]),a("p",[e._v("Si bien ambos pueden ceder múltiples veces, suspender su ejecución y permitir el reingreso en múltiples puntos de entrada, difieren en que las corrutinas tienen la capacidad para controlar dónde continúa la ejecución inmediatamente después de ceder, mientras que los generadores no pueden, estos transfieren el control de nuevo al generador que lo llamo. Es decir, dado que los generadores se utilizan principalmente para simplificar la escritura de iteradores, la declaración de rendimiento en un generador no especifica una rutina para saltar, sino que devuelve un valor a una rutina principal. "),a("a",{attrs:{href:"https://docs.python.org/3/reference/expressions.html#yieldexpr"}},[e._v("Explicación de yield y comparación con corrutinas")])]),a("p",[a("strong",[e._v("Bien, entonces ahora somos capaces de retomar el ejemplo y refactorizar lo necesario para implementarlo con corrutinas :D")])]),a("h2",{attrs:{id:"con-corrutinas-basadas-en-generadores"}},[e._v("Con corrutinas basadas en generadores "),a("a",{staticClass:"header-anchor",attrs:{href:"#con-corrutinas-basadas-en-generadores"}},[e._v("¶")])]),a("p",[e._v("Es posible escribir código asincrónico que combine la eficiencia de los callbacks con el buen aspecto clásico de la programación multiproceso/hilo.")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("fetch")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(self, url)")]),e._v(":")]),e._v("\n response = "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("yield")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("from")]),e._v(" self.session.get(url)\n body = "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("yield")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("from")]),e._v(" response.read()\n")])]),a("p",[e._v("Ahora, fetch es una función generadora, en lugar de una normal. Creamos un "),a("a",{attrs:{href:"https://docs.python.org/es/3/library/asyncio-future.html#future-object"}},[e._v("future")]),e._v(" pendiente, luego lo cedemos para pausar la búsqueda hasta que el socket esté listo. La función interna on_connected resuelve el future.")]),a("blockquote",[a("p",[e._v("Nota: Un future representa un resultado eventual de una operación asincrónica.")])]),a("p",[e._v('Pero cuando el future se resuelva, ¿qué reanuda el generador? Necesitamos un controlador de rutina. Llamémoslo "tarea":')]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-class"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("class")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("Task")]),e._v(":")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("__init__")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(self, coro)")]),e._v(":")]),e._v("\n self.coro = coro\n f = Future()\n f.set_result("),a("span",{pre:!0,attrs:{class:"hljs-literal"}},[e._v("None")]),e._v(")\n self.step(f)\n\n "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("step")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(self, future)")]),e._v(":")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("try")]),e._v(":\n next_future = self.coro.send(future.result)\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("except")]),e._v(" StopIteration:\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("return")]),e._v("\n\n next_future.add_done_callback(self.step)\n\nfetcher = Fetcher("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'/333/'")]),e._v(")\nTask(fetcher.fetch())\n\nloop()\n")])]),a("p",[e._v('Task inicia el generador "fetch" enviando None. Luego, fetch se ejecuta hasta que produce (yield) un future, que la tarea captura como siguiente future. Cuando el socket está conectado, el event loop ejecuta el callback on_connected, que resuelve el future, que llama a step, que reanuda fetch.')]),a("h2",{attrs:{id:"con-corrutinas-1"}},[e._v("Con corrutinas "),a("a",{staticClass:"header-anchor",attrs:{href:"#con-corrutinas-1"}},[e._v("¶")])]),a("p",[e._v("Modificando el codigo de las corrutinas basadas en generadores usando async/await, quedaría algo como:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-python"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("import")]),e._v(" sys\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("import")]),e._v(" asyncio\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("from")]),e._v(" bs4 "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("import")]),e._v(" BeautifulSoup\n\n"),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("get_urls_from_root")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(root_url)")]),e._v(":")]),e._v("\n soup = BeautifulSoup(reqs.text, "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'html.parser'")]),e._v(")\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("return")]),e._v(" soup.find_all("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'a'")]),e._v("):\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("async")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("fetch")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(url)")]),e._v(":")]),e._v("\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("await")]),e._v(" r = get_non_block(url)\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("await")]),e._v(" parse_response(r.content) "),a("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("#Content of the response, in bytes")]),e._v("\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("async")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("parse_response")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(response)")]),e._v(":")]),e._v("\n hace_su_magia(response)\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("async")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("main")]),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(":")]),e._v("\n root_url = sys.argv["),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v("]\n urls = [link.get("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'href'")]),e._v(") "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("for")]),e._v(" link "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("in")]),e._v(" get_urls_from_root(root_url)]\n\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("for")]),e._v(" url "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("in")]),e._v(" urls:\n task = asyncio.create_task(fetch(url))\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("await")]),e._v(" task\n\nasyncio.run(main())\n")])]),a("p",[e._v('Quedaria implementada la solución con corrutinas "nativas" de Python.')]),a("h2",{attrs:{id:"links-interesantes"}},[e._v("Links interesantes "),a("a",{staticClass:"header-anchor",attrs:{href:"#links-interesantes"}},[e._v("¶")])]),a("p",[a("a",{attrs:{href:"https://docs.python.org/3.8/library/asyncio-task.html"}},[e._v("Corrutinas en Python")])]),a("p",[a("a",{attrs:{href:"https://www.tornadoweb.org/en/stable/"}},[e._v("Framework de Python que levanta un server asincronico con corrutinas planificandolas con un event loop")])]),a("p",[a("a",{attrs:{href:"http://www.golangpatterns.info/concurrency/coroutines"}},[e._v("Corrutinas en Go")])]),a("p",[a("a",{attrs:{href:"https://tour.golang.org/concurrency/1"}},[e._v("Para jugar con Goroutines")])]),a("p",[a("a",{attrs:{href:"https://kotlinlang.org/docs/reference/coroutines/basics.html"}},[e._v("Corrutinas en Kotlin")])]),a("p",[a("a",{attrs:{href:"https://kotlinlang.org/docs/tutorials/coroutines/async-programming.html"}},[e._v("Comparación de técnicas programación asincrónica (threading, callbacks, Promises, corrutinas)")]),e._v(". Claramente enfocado para resaltar las ventajas de las corrutinas en Kotlin, pero de todos modos interesante para repasar las técnicas que vimos hasta ahora.")]),a("hr",{staticClass:"footnotes-sep"}),a("section",{staticClass:"footnotes"},[a("ol",{staticClass:"footnotes-list"},[a("li",{staticClass:"footnote-item",attrs:{id:"fn1"}},[a("p",[a("a",{attrs:{href:"http://www.kegel.com/c10k.html"}},[e._v("Kegel, Dan. 1999. The C10K problem")]),e._v(" "),a("a",{staticClass:"footnote-backref",attrs:{href:"#fnref1"}},[e._v("↩︎")])])]),a("li",{staticClass:"footnote-item",attrs:{id:"fn2"}},[a("p",[a("a",{attrs:{href:"https://www.baeldung.com/kotlin-threads-coroutines"}},[e._v("Baeldung. 2021. Threads vs Coroutines in Kotlin")]),e._v(" "),a("a",{staticClass:"footnote-backref",attrs:{href:"#fnref2"}},[e._v("↩︎")])])]),a("li",{staticClass:"footnote-item",attrs:{id:"fn3"}},[a("p",[a("a",{attrs:{href:"https://docs.python.org/3.8/library/asyncio-task.html"}},[e._v("Python Docs. Coroutines and Tasks")]),e._v(" "),a("a",{staticClass:"footnote-backref",attrs:{href:"#fnref3"}},[e._v("↩︎")])])])])])])}],t=a("2877"),o={},l=Object(t["a"])(o,r,n,!1,null,null,null);s["default"]=l.exports}}]); +//# sourceMappingURL=chunk-2d0a34c9.b72d6dd3.js.map \ No newline at end of file diff --git a/js/chunk-2d0a34c9.b72d6dd3.js.map b/js/chunk-2d0a34c9.b72d6dd3.js.map new file mode 100644 index 0000000..31fd3fb --- /dev/null +++ b/js/chunk-2d0a34c9.b72d6dd3.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/content/coroutines.md?8cba","webpack:///./src/content/coroutines.md"],"names":["render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","pre","script","component"],"mappings":"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","file":"js/chunk-2d0a34c9.b72d6dd3.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h2',{attrs:{\"id\":\"anteriormente-en-arquitecturas-concurrentes\"}},[_vm._v(\"Anteriormente... en Arquitecturas Concurrentes \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#anteriormente-en-arquitecturas-concurrentes\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Hasta ahora trabajamos sobre un modelo de concurrencia basado en un \"),_c('em',[_vm._v(\"event loop\")]),_vm._v(\". En este esquema, cada evento se procesa completamente antes de pasar a la ejecución del próximo, y todo esto ocurre en un único thread.\")]),_c('p',[_vm._v(\"Una ventaja que esto implica es que cuando una función se está ejecutando, tenemos la seguridad de que no va a ser interrumpida por el planificador hasta que termine, lo cual evita los problemas de concurrencia tradicionales que habíamos visto al usar \"),_c('em',[_vm._v(\"threads\")]),_vm._v(\" y \"),_c('em',[_vm._v(\"locks\")]),_vm._v(\". Y esto lo logramos gracias a que el event loop le provee un \"),_c('em',[_vm._v(\"orden\")]),_vm._v(\" a la ejecución concurrente; la serializa.\")]),_c('p',[_vm._v(\"Las corrutinas nos permiten lograr algo similar, sin utilizar (necesariamente) un event loop.\")]),_c('h2',{attrs:{\"id\":\"caso-practico\"}},[_vm._v(\"Caso practico \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#caso-practico\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"En el desarrollo de software muchas veces solemos enfatizar en lograr que los algoritmos sean más eficientes, es decir que completen los cálculos lo más rápido posible. Pero muchos sistemas dedican su tiempo a \\\"no hacer cálculos\\\", sino que mantienen abiertas muchas conexiones que son lentas. Estos programas presentan un desafío muy diferente: atender una gran cantidad de eventos de red de manera eficiente. Un enfoque actual de este problema es la E/S asíncrona o \\\"asincrónica\\\".\")]),_c('p',[_vm._v(\"Tomemos el ejemplo de un crawler (rastreador web) sencillo. El crawler es una aplicación asíncrona que espera muchas respuestas, pero realiza pocos cálculos. Cuantas más páginas pueda extraer a la vez, va a poder terminar antes.\")]),_c('h2',{attrs:{\"id\":\"el-enfoque-tradicional\"}},[_vm._v(\"El enfoque tradicional \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#el-enfoque-tradicional\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"¿Cómo hacemos que el crawler sea concurrente? Tradicionalmente, crearíamos un grupo hilos. Cada uno se encargaría de descargar una página a la vez a través de un socket. Por ejemplo, para descargar una página de bla.com:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"import\")]),_vm._v(\" sys\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"import\")]),_vm._v(\" requests\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"import\")]),_vm._v(\" threading\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"from\")]),_vm._v(\" bs4 \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"import\")]),_vm._v(\" BeautifulSoup\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"get_urls_from_root\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(root_url)\")]),_vm._v(\":\")]),_vm._v(\"\\n soup = BeautifulSoup(reqs.text, \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'html.parser'\")]),_vm._v(\")\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"return\")]),_vm._v(\" soup.find_all(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'a'\")]),_vm._v(\"):\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"fetch\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(url)\")]),_vm._v(\":\")]),_vm._v(\"\\n r = requests.get(url)\\n parse_response(r.content) \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"#Content of the response, in bytes\")]),_vm._v(\"\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"parse_response\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(response)\")]),_vm._v(\":\")]),_vm._v(\"\\n hace_su_magia(response)\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"if\")]),_vm._v(\" __name__ == \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'__main__'\")]),_vm._v(\":\\n root_url = sys.argv[\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\"]\\n urls = [link.get(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'href'\")]),_vm._v(\") \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"for\")]),_vm._v(\" link \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"in\")]),_vm._v(\" get_urls_from_root(root_url)]\\n\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"for\")]),_vm._v(\" url \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"in\")]),_vm._v(\" urls:\\n t = threading.Thread(target=fetch, args=(i,))\\n t.start()\\n\")])]),_c('p',[_vm._v(\"Este es un ejemplo simple que hace lo mencionado anteriormente. Analicemos con más detalle lo que esta realmente haciendo la función \"),_c('strong',[_vm._v(\"fetch\")]),_vm._v(\", escribámosla de vuelta sin usar la libreria requests.\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"fetch\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(url)\")]),_vm._v(\":\")]),_vm._v(\"\\n sock = socket.socket()\\n sock.connect((\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'bla.com'\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"80\")]),_vm._v(\"))\\n request = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'GET {} HTTP/1.0\\\\r\\\\nHost: bla.com\\\\r\\\\n\\\\r\\\\n'\")]),_vm._v(\".format(url)\\n sock.send(request.encode(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'ascii'\")]),_vm._v(\"))\\n response = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"b''\")]),_vm._v(\"\\n chunk = sock.recv(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"4096\")]),_vm._v(\")\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"while\")]),_vm._v(\" chunk:\\n response += chunk\\n chunk = sock.recv(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"4096\")]),_vm._v(\")\\n\\n parse_response(response)\\n\")])]),_c('blockquote',[_c('p',[_vm._v(\"Nota: De esa forma la manipulación de sockets, el connect y el recv estan de forma explicita y nos obliga a hablar de estas cosas que vimos en algún pasado lejano programando en C y leyendo la guia Beej :P\")])]),_c('h3',{attrs:{\"id\":\"entendiendo-el-problema\"}},[_vm._v(\"Entendiendo el problema \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#entendiendo-el-problema\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Si se crea un hilo por cada request (solicitud), a medida que aumente el número de requests simultáneas, aumenta la posibilidad de quedarse sin memoria antes de que se agoten los sockets. Podemos evitar la necesidad de subprocesos (hilos), mediante el uso de E/S asincrónica.\")]),_c('p',[_vm._v(\"Por defecto, las operaciones con sockets son bloqueantes, cuando el hilo llama a un método como connect o recv, se detiene hasta que la operación se completa. En consecuencia, para descargar muchas páginas a la vez, necesitamos muchos hilos. Una aplicación sofisticada amortiza el costo de la creación de hilos al mantener los inactivos en un grupo o pool y luego revisarlos para reutilizarlos para tareas posteriores; se suele hacer lo mismo con los sockets en un grupo de conexiones.\")]),_c('p',[_vm._v(\"Sin embargo, los hilos son costosos y los sistemas operativos imponen una variedad de límites estrictos en la cantidad que se puede tener. Un hilo de Python ocupa alrededor de 50k de memoria y el inicio de decenas de miles de hilos puede provocar fallas. Si escalamos hasta decenas de miles de operaciones simultáneas en sockets concurrentes, nos quedamos sin hilos antes de quedarnos sin sockets. La sobrecarga por hilos o los límites del sistema en subprocesos son el cuello de botella.\")]),_c('p',[_vm._v(\"Dan Kegel en su artículo \"),_c('a',{attrs:{\"href\":\"http://www.kegel.com/c10k.html\"}},[_vm._v(\"The C10K problem\")]),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn1\",\"id\":\"fnref1\"}},[_vm._v(\"[1]\")])]),_vm._v(\", describe las limitaciones de utilizar multiples hilos para resolver problemas de concurrencia de E/S.\")]),_c('p',[_vm._v(\"Kegel utilizo el término \\\"C10K\\\" en 1999. Diez mil conexiones no suenan ahora como lo sonaban antes, pero el problema ha cambiado sólo en tamaño, no en especie. En aquel entonces, usar un hilo por conexión para C10K no era práctico. Ahora el límite es en órdenes de magnitud más elevado. De hecho, nuestro crawler de juguete funcionaría bien con hilos. Sin embargo, para aplicaciones a gran escala, con cientos de miles de conexiones, el límite permanece; hay un límite más allá del cual la mayoría de los sistemas aún pueden crear sockets, pero se han quedado sin hilos. ¿Cómo podemos superar esto?\")]),_c('h2',{attrs:{\"id\":\"async\"}},[_vm._v(\"Async \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#async\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Los frameworks de E/S asincrónicos realizan operaciones simultáneas en un solo hilo utilizando sockets no bloqueantes. En nuestro crawler asíncrono, configuramos el socket no bloqueante antes de comenzar a conectarnos al servidor:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_vm._v(\"sock = socket.socket()\\nsock.setblocking(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-literal\"}},[_vm._v(\"False\")]),_vm._v(\")\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"try\")]),_vm._v(\":\\n sock.connect((\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'bla.com'\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"80\")]),_vm._v(\"))\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"except\")]),_vm._v(\" BlockingIOError:\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"pass\")]),_vm._v(\"\\n\")])]),_c('p',[_vm._v(\"Un socket no bloqueante genera una excepción al realizar el \"),_c('em',[_vm._v(\"connect\")]),_vm._v(\", incluso cuando funciona normalmente. Esta excepción replica el comportamiento irritante de la función C subyacente, que establece \"),_c('em',[_vm._v(\"errno\")]),_vm._v(\" en \"),_c('em',[_vm._v(\"EINPROGRESS\")]),_vm._v(\" para indicarle que ha comenzado.\")]),_c('p',[_vm._v(\"Ahora nuestro crawler necesita una forma de saber cuándo se establece la conexión, para poder enviar la solicitud HTTP. Simplemente podríamos seguir intentándolo en un loop. Este método no puede esperar eventos de manera eficiente en múltiples sockets. En la antigüedad, la solución de BSD Unix a este problema era select, una función de C que espera a que ocurra un evento en un socket sin bloqueo o en un pequeño vector de ellos. Hoy en día, la demanda de aplicaciones con un gran número de conexiones ha llevado a reemplazos como poll, luego kqueue en BSD y epoll en Linux. Estas API son similares a las de select, pero funcionan bien con un gran número de conexiones.\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"from\")]),_vm._v(\" selectors \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"import\")]),_vm._v(\" DefaultSelector, EVENT_WRITE\\n\\nselector = DefaultSelector()\\n\\nsock = socket.socket()\\nsock.setblocking(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-literal\"}},[_vm._v(\"False\")]),_vm._v(\")\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"try\")]),_vm._v(\":\\n sock.connect((\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'bla.com'\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"80\")]),_vm._v(\"))\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"except\")]),_vm._v(\" BlockingIOError:\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"pass\")]),_vm._v(\"\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"connected\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\":\")]),_vm._v(\"\\n selector.unregister(sock.fileno())\\n print(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'connected!'\")]),_vm._v(\")\\n\\nselector.register(sock.fileno(), EVENT_WRITE, connected)\\n\")])]),_c('p',[_vm._v(\"Procesamos las notificaciones de E/S a medida que el selector las recibe, en un loop:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"loop\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\":\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"while\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-literal\"}},[_vm._v(\"True\")]),_vm._v(\":\\n events = selector.select()\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"for\")]),_vm._v(\" event_key, event_mask \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"in\")]),_vm._v(\" events:\\n callback = event_key.data\\n callback()\\n\")])]),_c('p',[_vm._v(\"Aquí hemos logrado tener \\\"concurrencia\\\", pero no \\\"paralelismo\\\". Es decir, construimos un pequeño sistema que superpone E/S. Es capaz de iniciar nuevas operaciones mientras otras están \\\"en vuelo\\\". No utiliza varios núcleos para ejecutar cálculos en paralelo. Este sistema está diseñado para problemas I/O-bound, no con CPU-bound.\")]),_c('p',[_c('strong',[_vm._v(\"La iteración final en nuestro ejemplo seria refactorizar esto para que use corrutinas, pero antes necesitamos ver rápidamente lo que son para entender en que nos van a ayudar.\")])]),_c('blockquote',[_c('p',[_vm._v(\"Nota al margen: las corrutinas no son nada nuevo. C++, Smalltalk, Erlang y muchos más (¡hasta PHP!) las tienen desde hace mucho. Pero recientemente han conseguido cierta notoriedad en la industria por su uso en lenguajes como Go, Kotlin y Python.\")])]),_c('p',[_vm._v(\"Para entender como funcionan, primero veamos \"),_c('strong',[_vm._v(\"iteradores\")]),_vm._v(\" y \"),_c('strong',[_vm._v(\"generadores\")]),_vm._v(\"...\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":\"https://www.salesoptimize.com/wp-content/uploads/2016/11/76e3344703e128bed674b84014fa01ab.jpg\"}}),_c('h2',{attrs:{\"id\":\"iteradores-y-generadores\"}},[_vm._v(\"Iteradores y generadores \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#iteradores-y-generadores\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Un \"),_c('strong',[_vm._v(\"generador\")]),_vm._v(\" es un tipo especial de subrutina, pensando en teoría de conjuntos, podemos decir que el conjunto generador es un subconjunto de corrutina.\")]),_c('blockquote',[_c('p',[_vm._v(\"Esta bien, pero entonces.. ¿qué es un generador?\")])]),_c('p',[_vm._v(\"También podemos decir que un \"),_c('strong',[_vm._v(\"generador\")]),_vm._v(\" es una función que produce una secuencia de resultados, en lugar de un único valor.\")]),_c('p',[_vm._v(\"Un \"),_c('strong',[_vm._v(\"iterador\")]),_vm._v(\" es un objeto que permite al programador recorrer un contenedor (colección de elementos) por ejemplo una lista. Una manera de implementar iteradores es utilizar un \"),_c('strong',[_vm._v(\"generador\")]),_vm._v(\", que como comentamos antes, puede producir valores para quien lo llama varias veces (en lugar de devolver sólo uno).\")]),_c('p',[_vm._v(\"Cuando invocamos a una función generadora se crea un \\\"objeto generador\\\" que permanece en un estado pausado, no se ejecuta automáticamente.\")]),_c('p',[_vm._v(\"Veámoslo con un ejemplo:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"cuenta_regresiva\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(numero)\")]),_vm._v(\":\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"while\")]),_vm._v(\" numero > \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\":\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"yield\")]),_vm._v(\" numero\\n numero -= \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\"\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"for\")]),_vm._v(\" numero \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"in\")]),_vm._v(\" cuenta_regresiva(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"5\")]),_vm._v(\"):\\n print(numero)\\n\")])]),_c('blockquote',[_c('p',[_vm._v(\"El resultado de ejecutar el script es: 5 4 3 2 1\")])]),_c('p',[_vm._v(\"Acá podemos ver a el generador en su estado pausado, por esta propiedad los solemos usar en un for, y si es aplicable en un for, se deduce que el estado pausado es un objeto iterable. Llamando a next se ejecutan todas las lineas hasta volver al \\\"segundo\\\" yield\")]),_c('blockquote',[_c('p',[_vm._v(\"x = cuenta_regresiva(5) x next(x) 4\")])]),_c('p',[_vm._v(\"A continuación se puede ver un ejemplo de un generador que devuelve los números de Fibonacci:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"fibonacci\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\":\")]),_vm._v(\"\\n a, b = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"while\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-literal\"}},[_vm._v(\"True\")]),_vm._v(\":\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"yield\")]),_vm._v(\" a\\n a, b = b, a+b\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"for\")]),_vm._v(\" numero \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"in\")]),_vm._v(\" fibonacci(): \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"# Utilización de generador como iterador\")]),_vm._v(\"\\n print(numero)\\n\")])]),_c('h3',{attrs:{\"id\":\"corrutinas-basadas-en-generadores\"}},[_vm._v(\"Corrutinas basadas en generadores \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#corrutinas-basadas-en-generadores\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Es posible implementar corrutinas basadas en generadores, de hecho, hasta Python 2.5 las corrutinas estaban hechas de esta forma, con la ayuda de una rutina de despachador de nivel superior (un trampolín, esencialmente) que pasa el control explícitamente a los generadores secundarios.\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"coro\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\":\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"#yield usado de esta forma creamos una corrutina que hace más que generar valores, si no que también consume\")]),_vm._v(\"\\n hello = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"yield\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"\\\"Soy una corrutina\\\"\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"yield\")]),_vm._v(\" hello\\n\\nc = coro()\\nprint(next(c))\\nprint(c.send(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"\\\", basada en generadores\\\"\")]),_vm._v(\"))\\n\")])]),_c('h2',{attrs:{\"id\":\"qué-es-una-corrutina\"}},[_vm._v(\"¿Qué es una corrutina? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#qué-es-una-corrutina\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Una corrutina es similar a una subrutina tradicional (piensen en las funciones/procedimientos que vieron en Algoritmos), pero con la diferencia de que, mientras que la salida de una subrutina pone fin a su ejecución, una corrutina puede además \"),_c('strong',[_vm._v(\"suspenderse\")]),_vm._v(\", cediendo el control a otra hasta que se le indique que debe \"),_c('strong',[_vm._v(\"retomar\")]),_vm._v(\" su ejecución.\")]),_c('p',[_vm._v(\"Para entender mejor a qué nos referimos con esto, veamos un ejemplo en Python, uno de los lenguajes que cuenta con soporte para corrutinas.\")]),_c('h4',{attrs:{\"id\":\"sin-corrutinas\"}},[_vm._v(\"Sin corrutinas \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#sin-corrutinas\"}},[_vm._v(\"¶\")])]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"import\")]),_vm._v(\" time\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"io\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\":\")]),_vm._v(\"\\n time.sleep(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\")\\n print(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'1'\")]),_vm._v(\")\\n time.sleep(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\")\\n print(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'2'\")]),_vm._v(\")\\n time.sleep(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\")\\n print(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'3'\")]),_vm._v(\")\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"main\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(tareas)\")]),_vm._v(\":\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"for\")]),_vm._v(\" tarea \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"in\")]),_vm._v(\" tareas:\\n io()\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"if\")]),_vm._v(\" __name__ == \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'__main__'\")]),_vm._v(\":\\n tiempo = time.perf_counter()\\n main(range(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"3\")]),_vm._v(\"))\\n tiempo2 = time.perf_counter() - tiempo\\n print(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"f'Tiempo total: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-subst\"}},[_vm._v(\"{tiempo2:\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0.2\")]),_vm._v(\"f}\")]),_vm._v(\" segundos'\")]),_vm._v(\")\\n\")])]),_c('p',[_vm._v(\"Este código imprime:\")]),_c('blockquote',[_c('p',[_vm._v(\"1 2 3 1 2 3 1 2 3 Tiempo total: 9.01 segundos\")])]),_c('p',[_vm._v(\"Podemos ver que cada ciclo de IOs de cada tarea se ejecuta y termina una atrás de la otra. ¿Qué pasa si agregamos corrutinas?\")]),_c('h4',{attrs:{\"id\":\"con-corrutinas\"}},[_vm._v(\"Con corrutinas \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#con-corrutinas\"}},[_vm._v(\"¶\")])]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"import\")]),_vm._v(\" time\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"import\")]),_vm._v(\" asyncio\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"async\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"io\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\":\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"#Hay un async adelante del def, asi que soy una corrutina :D\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"await\")]),_vm._v(\" asyncio.sleep(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\")\\n print(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\")\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"await\")]),_vm._v(\" asyncio.sleep(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\")\\n print(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"2\")]),_vm._v(\")\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"await\")]),_vm._v(\" asyncio.sleep(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\")\\n print(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"3\")]),_vm._v(\")\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"async\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"main\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\":\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"await\")]),_vm._v(\" asyncio.gather(io(), io(), io())\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"if\")]),_vm._v(\" __name__ == \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'__main__'\")]),_vm._v(\":\\n tiempo = time.perf_counter()\\n asyncio.run(main())\\n tiempo2 = time.perf_counter() - tiempo\\n print(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"f'Tiempo total: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-subst\"}},[_vm._v(\"{tiempo2:\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0.2\")]),_vm._v(\"f}\")]),_vm._v(\" segundos'\")]),_vm._v(\")\\n\")])]),_c('blockquote',[_c('p',[_vm._v(\"1 1 1 2 2 2 3 3 3 Tiempo total: 3.00 segundos\")])]),_c('p',[_vm._v(\"La diferencia en los tiempos es notable. También observamos que el orden de ejecución fue distinto en este caso.\")]),_c('h2',{attrs:{\"id\":\"cómo-funcionan\"}},[_vm._v(\"¿Cómo funcionan? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#cómo-funcionan\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Cuando usamos corrutinas, no hay intervención del SO. Hay un sólo proceso, un sólo thread. Entonces... ¿qué es lo que esta pasando?\")]),_c('p',[_vm._v(\"Lo que ocurre es que las corrutinas liberan la CPU cuando están en \\\"tiempo de espera\\\" (\"),_c('code',{pre:true},[_vm._v(\"await\")]),_vm._v(\"), permitiendo que otras puedan usar la CPU.\")]),_c('p',[_vm._v(\"Podemos decir que es como una simultánea de ajedrez, en donde una persona juega contra dos o más. Hace un movimiento y no se queda esperando la respuesta del oponente en ese tablero, sino que pasa al siguiente y realiza un movimiento ahí. De esa forma, trata las partidas (tareas) de forma concurrente, lo que resulta en que se terminen en menos tiempo.\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":\"https://i.ytimg.com/vi/Hp6827K1pFE/hqdefault.jpg\"}}),_c('p',[_vm._v(\"Seguro están pensando:\")]),_c('blockquote',[_c('p',[_vm._v(\"Un momento... esto se parece a un thread\")])]),_c('p',[_vm._v(\"Lo que nos lleva a nuestra próxima sección...\")]),_c('h2',{attrs:{\"id\":\"corrutinas-vs-threads\"}},[_vm._v(\"Corrutinas vs Threads \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#corrutinas-vs-threads\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"La diferencia fundamental entre corrutinas y threads se da en la forma en la que se lleva a cabo la multitarea.\")]),_c('p',[_vm._v(\"Los threads, como ya vimos, manejan un esquema de \"),_c('strong',[_vm._v(\"multitarea apropiativa\")]),_vm._v(\" (en inglés, \"),_c('em',[_vm._v(\"preemptive multitasking\")]),_vm._v(\"), donde el planificador es el encargado de asignar intervalos de uso de CPU a los threads que se están ejecutando, desalojándolos cuando este termina.\")]),_c('p',[_vm._v(\"Las corrutinas, en contraposición, permiten tener \"),_c('strong',[_vm._v(\"multitarea cooperativa\")]),_vm._v(\" (\"),_c('em',[_vm._v(\"cooperative/non-preemptive multitasking\")]),_vm._v(\"). Esto significa que el cambio de contexto no es controlado por el planificador, sino que cada corrutina es la encargada de ceder el control cuando está inactiva o bloqueda.\")]),_c('p',[_vm._v(\"Otra diferencia, presente al menos en la visión \\\"tradicional\\\" de corrutinas, es que \"),_c('strong',[_vm._v(\"las corrutinas proveen concurrencia pero no paralelismo\")]),_vm._v(\". De esta forma, evitan problemas de concurrencia, ya que corren en un \"),_c('strong',[_vm._v(\"único contexto de ejecución\")]),_vm._v(\", y además \"),_c('strong',[_vm._v(\"controlan cuándo se suspenden\")]),_vm._v(\" (en vez de que el planificador las interrumpa en puntos arbitrarios).\")]),_c('blockquote',[_c('p',[_vm._v(\"Las corrutinas ocupan menos memoria que los hilos (3k por corrutina vs 50k por hilo).\")])]),_c('p',[_vm._v(\"Una ventaja más que las corrutinas tienen sobre los hilos es que su funcionamiento no involucra llamadas al sistema bloqueantes para su creación ni para el cambio de contexto, ya que todo se maneja al nivel de la aplicación.\")]),_c('p',[_vm._v(\"Interesante comparación de cuando usar corrutinas y cuando usar threads en Kotlin.\"),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn2\",\"id\":\"fnref2\"}},[_vm._v(\"[2]\")])])]),_c('h2',{attrs:{\"id\":\"cómo-se-declaran-y-ejecutan-en-python\"}},[_vm._v(\"¿Cómo se declaran y ejecutan en Python? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#cómo-se-declaran-y-ejecutan-en-python\"}},[_vm._v(\"¶\")])]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"import\")]),_vm._v(\" asyncio\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"print_loco\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(algo)\")]),_vm._v(\":\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"return\")]),_vm._v(\" print(algo,\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'loco'\")]),_vm._v(\")\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"async\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"print_re_loco\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(algo)\")]),_vm._v(\":\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"return\")]),_vm._v(\" print(algo,\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'loco'\")]),_vm._v(\")\\n\")])]),_c('blockquote',[_c('p',[_vm._v(\"print_loco\")])]),_c('blockquote',[_c('p',[_vm._v(\"\")])]),_c('blockquote',[_c('p',[_vm._v(\"print_re_loco\")])]),_c('blockquote',[_c('p',[_vm._v(\"\")])]),_c('p',[_vm._v(\"Las dos funciones lucen similares, la diferencia vamos a notar cuando las usamos:\")]),_c('blockquote',[_c('p',[_vm._v(\"print_loco('bla')\")])]),_c('blockquote',[_c('p',[_vm._v(\"bla loco\")])]),_c('p',[_vm._v(\"Nada fuera de lo esperado.\")]),_c('blockquote',[_c('p',[_vm._v(\"print_re_loco('algo')\")])]),_c('blockquote',[_c('p',[_vm._v(\"\")])]),_c('p',[_vm._v(\"Nos retorna un objeto \\\"corrutina\\\" que por defecto no se va a planificar. Entonces, ¿cómo hago que se ejecute? Bueno, hay tres formas distintas para hacer eso.\")]),_c('p',[_c('strong',[_vm._v(\"1-\")]),_vm._v(\" Usando la función \"),_c('code',{pre:true},[_vm._v(\"run\")]),_vm._v(\" del módulo \"),_c('code',{pre:true},[_vm._v(\"asyncio\")]),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn3\",\"id\":\"fnref3\"}},[_vm._v(\"[3]\")])])]),_c('blockquote',[_c('p',[_vm._v(\"coro = print_re_loco('algo')\")])]),_c('blockquote',[_c('p',[_vm._v(\"asyncio.run(coro)\")])]),_c('blockquote',[_c('p',[_vm._v(\"algo loco\")])]),_c('p',[_c('strong',[_vm._v(\"2-\")]),_vm._v(\" Usando \"),_c('code',{pre:true},[_vm._v(\"await\")]),_vm._v(\" en una corrutina\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"import\")]),_vm._v(\" asyncio\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"async\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"say_after\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(delay, what)\")]),_vm._v(\":\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"await\")]),_vm._v(\" asyncio.sleep(delay)\\n print(what)\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"async\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"main\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\":\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"await\")]),_vm._v(\" say_after(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'hello'\")]),_vm._v(\")\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"await\")]),_vm._v(\" say_after(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"2\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'world'\")]),_vm._v(\")\\n\")])]),_c('blockquote',[_c('p',[_vm._v(\"asyncio.run(main())\")])]),_c('blockquote',[_c('p',[_vm._v(\"hello\")])]),_c('blockquote',[_c('p',[_vm._v(\"world\")])]),_c('p',[_c('em',[_vm._v(\"Nota: acá usamos \"),_c('code',{pre:true},[_vm._v(\"run\")]),_vm._v(\" para ejecutar la corrutina \"),_c('code',{pre:true},[_vm._v(\"main\")]),_vm._v(\" y \"),_c('code',{pre:true},[_vm._v(\"await\")]),_vm._v(\" para ejecutar las corrutinas \"),_c('code',{pre:true},[_vm._v(\"say_after\")]),_vm._v(\".\")])]),_c('p',[_c('strong',[_vm._v(\"3-\")]),_vm._v(\" Con la función \"),_c('code',{pre:true},[_vm._v(\"create_task\")]),_vm._v(\" de \"),_c('code',{pre:true},[_vm._v(\"asyncio\")]),_vm._v(\", que ejecuta corrutinas concurrentemente \"),_c('em',[_vm._v(\"wrappeándolas\")]),_vm._v(\" en \"),_c('code',{pre:true},[_vm._v(\"Tasks\")]),_vm._v(\", usando por detrás un \"),_c('strong',[_vm._v(\"event loop\")]),_vm._v(\" para planificarlas.\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"import\")]),_vm._v(\" asyncio\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"async\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"main\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\":\")]),_vm._v(\"\\n task1 = asyncio.create_task(say_after(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'hello'\")]),_vm._v(\"))\\n task2 = asyncio.create_task(say_after(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"2\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'world'\")]),_vm._v(\"))\\n\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"await\")]),_vm._v(\" task1\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"await\")]),_vm._v(\" task2\\n\")])]),_c('p',[_c('em',[_vm._v(\"Nota: \"),_c('code',{pre:true},[_vm._v(\"create_task\")]),_vm._v(\" envía la corrutina al event loop, permitiendo que corra en segundo plano. \"),_c('code',{pre:true},[_vm._v(\"gather\")]),_vm._v(\" hace algo muy parecido, pero podemos decir que es conveniente usarlo cuando nos interesa hacer algo con el resultado de las corrutinas.\")])]),_c('h2',{attrs:{\"id\":\"qué-pasa-si-ejecuto-código-bloqueante-dentro-de-una-corrutina\"}},[_vm._v(\"¿Qué pasa si ejecuto código bloqueante dentro de una corrutina? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#qué-pasa-si-ejecuto-código-bloqueante-dentro-de-una-corrutina\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Si observaron con detalle se habrán dado cuenta de que cuando se usa sleep para suspender a la corrutina, se esta usando \"),_c('code',{pre:true},[_vm._v(\"asyncio.sleep\")]),_vm._v(\" en lugar de \"),_c('code',{pre:true},[_vm._v(\"time.sleep\")]),_vm._v(\". Esto es porque el segundo es bloqueante. Entonces como ya dedujeron, las operaciones bloqueantes bloquean todo el thread del sistema operativo subyacente.\")]),_c('p',[_vm._v(\"Pero hay formas de evitarlo :D!, lo que se hace es que correr estas tareas \"),_c('strong',[_vm._v(\"bloqueantes\")]),_vm._v(\" y otras que vamos a llamar \"),_c('strong',[_vm._v(\"CPU-bound-intensive\")]),_vm._v(\", sea conveniente ejecutarlas en otro thread. Concretamente en \"),_c('strong',[_vm._v(\"Python\")]),_vm._v(\" usando \"),_c('code',{pre:true},[_vm._v(\"loop.run_in_executor()\")]),_vm._v(\" \"),_c('a',{attrs:{\"href\":\"https://docs.python.org/3/library/asyncio-dev.html#running-blocking-code\"}},[_vm._v(\"Running Blocking Code\")])]),_c('p',[_c('em',[_vm._v(\"Nota: también es posible setear un timeout para que cuando se cumpla, se corte su ejecución \"),_c('a',{attrs:{\"href\":\"https://docs.python.org/3/library/asyncio-task.html#timeouts\"}},[_vm._v(\"ver timeouts\")]),_vm._v(\" .\")])]),_c('h2',{attrs:{\"id\":\"corrutinas-vs-generadores\"}},[_vm._v(\"Corrutinas vs Generadores \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#corrutinas-vs-generadores\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Si bien ambos pueden ceder múltiples veces, suspender su ejecución y permitir el reingreso en múltiples puntos de entrada, difieren en que las corrutinas tienen la capacidad para controlar dónde continúa la ejecución inmediatamente después de ceder, mientras que los generadores no pueden, estos transfieren el control de nuevo al generador que lo llamo. Es decir, dado que los generadores se utilizan principalmente para simplificar la escritura de iteradores, la declaración de rendimiento en un generador no especifica una rutina para saltar, sino que devuelve un valor a una rutina principal. \"),_c('a',{attrs:{\"href\":\"https://docs.python.org/3/reference/expressions.html#yieldexpr\"}},[_vm._v(\"Explicación de yield y comparación con corrutinas\")])]),_c('p',[_c('strong',[_vm._v(\"Bien, entonces ahora somos capaces de retomar el ejemplo y refactorizar lo necesario para implementarlo con corrutinas :D\")])]),_c('h2',{attrs:{\"id\":\"con-corrutinas-basadas-en-generadores\"}},[_vm._v(\"Con corrutinas basadas en generadores \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#con-corrutinas-basadas-en-generadores\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Es posible escribir código asincrónico que combine la eficiencia de los callbacks con el buen aspecto clásico de la programación multiproceso/hilo.\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"fetch\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(self, url)\")]),_vm._v(\":\")]),_vm._v(\"\\n response = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"yield\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"from\")]),_vm._v(\" self.session.get(url)\\n body = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"yield\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"from\")]),_vm._v(\" response.read()\\n\")])]),_c('p',[_vm._v(\"Ahora, fetch es una función generadora, en lugar de una normal. Creamos un \"),_c('a',{attrs:{\"href\":\"https://docs.python.org/es/3/library/asyncio-future.html#future-object\"}},[_vm._v(\"future\")]),_vm._v(\" pendiente, luego lo cedemos para pausar la búsqueda hasta que el socket esté listo. La función interna on_connected resuelve el future.\")]),_c('blockquote',[_c('p',[_vm._v(\"Nota: Un future representa un resultado eventual de una operación asincrónica.\")])]),_c('p',[_vm._v(\"Pero cuando el future se resuelva, ¿qué reanuda el generador? Necesitamos un controlador de rutina. Llamémoslo \\\"tarea\\\":\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-class\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"class\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"Task\")]),_vm._v(\":\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"__init__\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(self, coro)\")]),_vm._v(\":\")]),_vm._v(\"\\n self.coro = coro\\n f = Future()\\n f.set_result(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-literal\"}},[_vm._v(\"None\")]),_vm._v(\")\\n self.step(f)\\n\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"step\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(self, future)\")]),_vm._v(\":\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"try\")]),_vm._v(\":\\n next_future = self.coro.send(future.result)\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"except\")]),_vm._v(\" StopIteration:\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"return\")]),_vm._v(\"\\n\\n next_future.add_done_callback(self.step)\\n\\nfetcher = Fetcher(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'/333/'\")]),_vm._v(\")\\nTask(fetcher.fetch())\\n\\nloop()\\n\")])]),_c('p',[_vm._v(\"Task inicia el generador \\\"fetch\\\" enviando None. Luego, fetch se ejecuta hasta que produce (yield) un future, que la tarea captura como siguiente future. Cuando el socket está conectado, el event loop ejecuta el callback on_connected, que resuelve el future, que llama a step, que reanuda fetch.\")]),_c('h2',{attrs:{\"id\":\"con-corrutinas-1\"}},[_vm._v(\"Con corrutinas \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#con-corrutinas-1\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Modificando el codigo de las corrutinas basadas en generadores usando async/await, quedaría algo como:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-python\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"import\")]),_vm._v(\" sys\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"import\")]),_vm._v(\" asyncio\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"from\")]),_vm._v(\" bs4 \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"import\")]),_vm._v(\" BeautifulSoup\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"get_urls_from_root\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(root_url)\")]),_vm._v(\":\")]),_vm._v(\"\\n soup = BeautifulSoup(reqs.text, \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'html.parser'\")]),_vm._v(\")\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"return\")]),_vm._v(\" soup.find_all(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'a'\")]),_vm._v(\"):\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"async\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"fetch\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(url)\")]),_vm._v(\":\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"await\")]),_vm._v(\" r = get_non_block(url)\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"await\")]),_vm._v(\" parse_response(r.content) \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"#Content of the response, in bytes\")]),_vm._v(\"\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"async\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"parse_response\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(response)\")]),_vm._v(\":\")]),_vm._v(\"\\n hace_su_magia(response)\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"async\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"main\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\":\")]),_vm._v(\"\\n root_url = sys.argv[\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\"]\\n urls = [link.get(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'href'\")]),_vm._v(\") \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"for\")]),_vm._v(\" link \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"in\")]),_vm._v(\" get_urls_from_root(root_url)]\\n\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"for\")]),_vm._v(\" url \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"in\")]),_vm._v(\" urls:\\n task = asyncio.create_task(fetch(url))\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"await\")]),_vm._v(\" task\\n\\nasyncio.run(main())\\n\")])]),_c('p',[_vm._v(\"Quedaria implementada la solución con corrutinas \\\"nativas\\\" de Python.\")]),_c('h2',{attrs:{\"id\":\"links-interesantes\"}},[_vm._v(\"Links interesantes \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#links-interesantes\"}},[_vm._v(\"¶\")])]),_c('p',[_c('a',{attrs:{\"href\":\"https://docs.python.org/3.8/library/asyncio-task.html\"}},[_vm._v(\"Corrutinas en Python\")])]),_c('p',[_c('a',{attrs:{\"href\":\"https://www.tornadoweb.org/en/stable/\"}},[_vm._v(\"Framework de Python que levanta un server asincronico con corrutinas planificandolas con un event loop\")])]),_c('p',[_c('a',{attrs:{\"href\":\"http://www.golangpatterns.info/concurrency/coroutines\"}},[_vm._v(\"Corrutinas en Go\")])]),_c('p',[_c('a',{attrs:{\"href\":\"https://tour.golang.org/concurrency/1\"}},[_vm._v(\"Para jugar con Goroutines\")])]),_c('p',[_c('a',{attrs:{\"href\":\"https://kotlinlang.org/docs/reference/coroutines/basics.html\"}},[_vm._v(\"Corrutinas en Kotlin\")])]),_c('p',[_c('a',{attrs:{\"href\":\"https://kotlinlang.org/docs/tutorials/coroutines/async-programming.html\"}},[_vm._v(\"Comparación de técnicas programación asincrónica (threading, callbacks, Promises, corrutinas)\")]),_vm._v(\". Claramente enfocado para resaltar las ventajas de las corrutinas en Kotlin, pero de todos modos interesante para repasar las técnicas que vimos hasta ahora.\")]),_c('hr',{staticClass:\"footnotes-sep\"}),_c('section',{staticClass:\"footnotes\"},[_c('ol',{staticClass:\"footnotes-list\"},[_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn1\"}},[_c('p',[_c('a',{attrs:{\"href\":\"http://www.kegel.com/c10k.html\"}},[_vm._v(\"Kegel, Dan. 1999. The C10K problem\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref1\"}},[_vm._v(\"↩︎\")])])]),_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn2\"}},[_c('p',[_c('a',{attrs:{\"href\":\"https://www.baeldung.com/kotlin-threads-coroutines\"}},[_vm._v(\"Baeldung. 2021. Threads vs Coroutines in Kotlin\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref2\"}},[_vm._v(\"↩︎\")])])]),_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn3\"}},[_c('p',[_c('a',{attrs:{\"href\":\"https://docs.python.org/3.8/library/asyncio-task.html\"}},[_vm._v(\"Python Docs. Coroutines and Tasks\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref3\"}},[_vm._v(\"↩︎\")])])])])])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./coroutines.md?vue&type=template&id=192b2df6&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-2d0a4a1b.07a60c29.js b/js/chunk-2d0a4a1b.07a60c29.js new file mode 100644 index 0000000..9bc75ec --- /dev/null +++ b/js/chunk-2d0a4a1b.07a60c29.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0a4a1b"],{"06ed":function(e,t,n){"use strict";n.r(t);var a=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("RemoteMarkdown",{attrs:{url:e.url}})},r=[],s=n("9454"),u={name:"EfectoLadoHaskell",components:{RemoteMarkdown:s["a"]},data:function(){return{url:"https://raw.githubusercontent.com/arquitecturas-concurrentes/iasc-stm-haskell-2019/master/00_side_effects/README.md"}}},c=u,o=n("2877"),l=Object(o["a"])(c,a,r,!1,null,null,null);t["default"]=l.exports}}]); +//# sourceMappingURL=chunk-2d0a4a1b.07a60c29.js.map \ No newline at end of file diff --git a/js/chunk-2d0a4a1b.07a60c29.js.map b/js/chunk-2d0a4a1b.07a60c29.js.map new file mode 100644 index 0000000..97d8cc7 --- /dev/null +++ b/js/chunk-2d0a4a1b.07a60c29.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/views/EfectoLadoHaskell.vue?2e82","webpack:///src/views/EfectoLadoHaskell.vue","webpack:///./src/views/EfectoLadoHaskell.vue?ec2e","webpack:///./src/views/EfectoLadoHaskell.vue"],"names":["render","_vm","this","_h","$createElement","_c","_self","attrs","url","staticRenderFns","component"],"mappings":"yHAAA,IAAIA,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,iBAAiB,CAACE,MAAM,CAAC,IAAMN,EAAIO,QAClIC,EAAkB,G,YCKtB,GACE,KAAF,oBACE,WAAF,CACI,eAAJ,QAEE,KALF,WAMI,MAAO,CACLD,IAAK,yHCbgV,I,YCOvVE,EAAY,eACd,EACAV,EACAS,GACA,EACA,KACA,KACA,MAIa,aAAAC,E","file":"js/chunk-2d0a4a1b.07a60c29.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('RemoteMarkdown',{attrs:{\"url\":_vm.url}})}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./EfectoLadoHaskell.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./EfectoLadoHaskell.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./EfectoLadoHaskell.vue?vue&type=template&id=58b646f1&\"\nimport script from \"./EfectoLadoHaskell.vue?vue&type=script&lang=js&\"\nexport * from \"./EfectoLadoHaskell.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-2d0af7d3.c7489446.js b/js/chunk-2d0af7d3.c7489446.js new file mode 100644 index 0000000..132a445 --- /dev/null +++ b/js/chunk-2d0af7d3.c7489446.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0af7d3"],{"0f18":function(e,s,a){"use strict";a.r(s);var o=function(){var e=this,s=e.$createElement;e._self._c;return e._m(0)},r=[function(){var e=this,s=e.$createElement,a=e._self._c||s;return a("section",[a("h2",{attrs:{id:"modulos-de-otp"}},[e._v("Modulos de OTP "),a("a",{staticClass:"header-anchor",attrs:{href:"#modulos-de-otp"}},[e._v("¶")])]),a("p",[e._v("Existen algunos módulos que fuimos viendo, en mayor o menor medida, o que merecen ser mencionados son:")]),a("ul",[a("li",[e._v("GenServer")]),a("li",[e._v("Application")]),a("li",[e._v("Registry")]),a("li",[e._v("Agent")]),a("li",[e._v("Supervisor")]),a("li",[e._v("Genserver ("),a("a",{attrs:{href:"https://hexdocs.pm/elixir/GenServer.html"}},[e._v("Genserver Hexdocs")]),e._v(")")])]),a("p",[e._v("Para una descripcion un poco mas amena de lo que es un Genserver y de lo que hace, junto con ejemplos bastante claros, se puede ver en "),a("a",{attrs:{href:"https://elixir-lang.org/getting-started/mix-otp/genserver.html"}},[e._v("hexdocs un poco mas de las especificaciones y temas puntuales de genserver")])]),a("p",[e._v("Un servidor OTP es un módulo que nos permite modelar un servidor o un cliente en una comunicación de cliente-servidor, y nos va a poder ayudar a que nuestro proceso pueda recibir tanto llamadas sincronicas como asincrónicas por medio de la convención de OTP. En su nivel más básico, un GenServer es un proceso único que ejecuta un bucle que maneja un mensaje por iteración y que siempre devuelve un estado que es el en el que queda el proceso, y también ayuda a modelar, mediante una convención, las distintas respuestas al cliente. También tiene las funciones que nos permiten hacer las llamadas a un servidor Genserver, las llamadas son:")]),a("ul",[a("li",[e._v("Call: Para realizar llamadas sincrónicas a otro proceso Genserver, que requieren una respuesta del servidor, por medio de un handle_call ("),a("a",{attrs:{href:"https://hexdocs.pm/elixir/GenServer.html#call/3"}},[e._v("Hexdocs")]),e._v(")")]),a("li",[e._v("Cast: Para realizar llamadas asincronicas a otro proceso Genserver, que no necesariamente require una respuesta del servidor, por medio de un handle_cast ("),a("a",{attrs:{href:"https://hexdocs.pm/elixir/GenServer.html#cast/2"}},[e._v("Hexdocs")]),e._v(")")])]),a("p",[e._v("Tenemos tipos de mensajes, tanto asincrónicos como sincronicos, los tipos de mensajes que podemos utilizar son para manejar las llamadas:")]),a("ul",[a("li",[e._v("Handle_call: Si bien todos los procesos de Elixir el envio de mensajes son asincrónicos, podemos siempre modelar una llamada asincrónica como sincrónica, mediante una espera activa, esperando una respuesta, handle_call nos permite que un proceso Genserver pueda exponer un callback que requiere una respuesta del cliente, por lo que una vez que se procesa este callback, se debe retornar una respuesta o un :reply que está conformado por la tupla {:reply, response, state}. Podemos ver todas la opciones de lo que puede retornar un handle_call ("),a("a",{attrs:{href:"https://hexdocs.pm/elixir/GenServer.html#c:handle_call/3"}},[e._v("Hexdocs")]),e._v(")")]),a("li",[e._v("Handle_cast: Permite manejar mensajes asincronicos mediate llamadas cast, y que pueden devolver un resultado o no necesariamente. ("),a("a",{attrs:{href:"https://hexdocs.pm/elixir/GenServer.html#c:handle_cast/2"}},[e._v("Hexdocs")]),e._v(")")]),a("li",[e._v("Handle_info: Permite manejar cualquier otro tipo de mensajes ("),a("a",{attrs:{href:"https://hexdocs.pm/elixir/GenServer.html#c:handle_info/2"}},[e._v("Hexdocs")]),e._v("))")])]),a("h2",{attrs:{id:"application-hexdocs"}},[e._v("Application ("),a("a",{attrs:{href:"https://hexdocs.pm/elixir/Application.html"}},[e._v("Hexdocs")]),e._v(") "),a("a",{staticClass:"header-anchor",attrs:{href:"#application-hexdocs"}},[e._v("¶")])]),a("p",[e._v("Este modulo permite modelar procesos que sirvan como un punto de entrada a nuestra aplicacion, sea para inicializar una aplicacion Erlang o de OTP, se puede ver un poco mas de detalle de este modulo en "),a("a",{attrs:{href:"https://elixir-lang.org/getting-started/mix-otp/supervisor-and-application.html#understanding-applications"}},[e._v("hexdocs")])]),a("p",[e._v("Registry ("),a("a",{attrs:{href:"https://hexdocs.pm/elixir/Registry.html"}},[e._v("Hexdocs")]),e._v(")")]),a("p",[e._v("Son un módulo de OTP que nos permite modelar procesos que nos permiten almacenar valores clave/valor de manera descentralizada. Suelen ser usados para algunas cosas como:")]),a("ul",[a("li",[e._v("Dispatching")]),a("li",[e._v("Registro de claves clave/valor")]),a("li",[e._v("Registro de claves pub/sub")])]),a("p",[e._v("Después hay una manera de tener un sotre pero a lo largo de la instancia llamado ETS ("),a("a",{attrs:{href:"https://elixir-lang.org/getting-started/mix-otp/ets.html"}},[e._v("Hexdocs")]),e._v(")")]),a("p",[e._v("Si se quiere tener un proceso que guarde un estado que no sea necesariamente algo del estilo clave/valor, podemos optar por otro tipo de módulo llamado Agent")]),a("h2",{attrs:{id:"agent-hexdocs"}},[e._v("Agent ("),a("a",{attrs:{href:"https://hexdocs.pm/elixir/Agent.html"}},[e._v("Hexdocs")]),e._v(") "),a("a",{staticClass:"header-anchor",attrs:{href:"#agent-hexdocs"}},[e._v("¶")])]),a("p",[e._v("El agent es un módulo que nos permite modelar un proceso que permita almacenar un estado, y en general se usa solo para este propósito, obviamente este almacenamiento, tanto los Agent como los Registry, es solo en memoria y no se persiste en disco. Pueden ver el link en el titulo para mayor información, algo interesante para ver es la sección de cómo supervisar un Agent ("),a("a",{attrs:{href:"https://hexdocs.pm/elixir/Agent.html#module-how-to-supervise"}},[e._v("https://hexdocs.pm/elixir/Agent.html#module-how-to-supervise")]),e._v(").")]),a("h2",{attrs:{id:"supervisores-hexdocs"}},[e._v("Supervisores ("),a("a",{attrs:{href:"https://hexdocs.pm/elixir/Supervisor.html"}},[e._v("Hexdocs")]),e._v(") "),a("a",{staticClass:"header-anchor",attrs:{href:"#supervisores-hexdocs"}},[e._v("¶")])]),a("p",[e._v("Un supervisor es un proceso que supervisa otros procesos, a los que nos referimos como procesos secundarios. Los supervisores se utilizan para construir una estructura de proceso jerárquica denominada árbol de supervisión. Los árboles de supervisión proporcionan tolerancia a fallos y resumen cómo se inician y se cierran nuestras aplicaciones. Por lo que podemos reiniciar una lista de procesos por medio de un supervisor en caso de que alguno de esos procesos se caiga, sea por un error o no..")]),a("p",[e._v("Se tiene que tener varias cosas en cuentas sobre un esquema de supervisión...")]),a("p",[e._v("La especificación de los hijos o procesos que serán especificados")]),a("p",[a("a",{attrs:{href:"https://hexdocs.pm/elixir/Supervisor.html#module-child-specification"}},[e._v("Documentacion de la especificacion")])]),a("p",[e._v("Dos de los argumentos de las especificaciones del child spec son:")]),a("p",[e._v("el valor de "),a("a",{attrs:{href:"https://hexdocs.pm/elixir/Supervisor.html#module-shutdown-values-shutdown"}},[e._v("shutdown")]),e._v(", que es la estrategia de cómo se debería cerrar o matar el proceso, cuando falla o se cae.")]),a("p",[e._v("Y más importante es la del "),a("a",{attrs:{href:"https://hexdocs.pm/elixir/Supervisor.html#module-restart-values-restart"}},[e._v("valor de reinicio de un proceso supervisado")])]),a("h3",{attrs:{id:"como-se-define-un-supervisor"}},[e._v("Como se define un Supervisor? "),a("a",{staticClass:"header-anchor",attrs:{href:"#como-se-define-un-supervisor"}},[e._v("¶")])]),a("p",[e._v("Mediante un modulo generalmente ("),a("a",{attrs:{href:"https://hexdocs.pm/elixir/Supervisor.html#module-restart-values-restart"}},[e._v("Hexdocs")]),e._v(")")]),a("p",[e._v("Ahora el supervisor recibe además de un child_spec una "),a("a",{attrs:{href:"https://hexdocs.pm/elixir/Supervisor.html#module-start_link-2-init-2-and-strategies"}},[e._v("estrategia de supervisión")]),e._v(", que será la acción que tomará un supervisor cuando se caen los procesos supervisados.")]),a("p",[e._v("En el child spec siempre vamos no solo a poder supervisar procesos que son hojas, o sea procesos que van a tener lógica de un sistema, o de nuestra aplicación, o pueden ser otros nodos que pueden ser no terminales, o sea, supervisores, por lo que podemos armar un árbol de supervisión de esta manera.")]),a("p",[e._v("Hay otras estrategias deprecadas, tales como las :simple_one_for_one, que hoy fueron reemplazadas por otro tipo de supervisores, esto es porque los Supervisor son para modelar procesos que son supervisores estáticos, o sea que una vez inicializado no se pueden agregar procesos supervisados, por lo que al ser estático, si se quieren hacer cambios, se debe cambiar el childspec, levantar de nuevo la aplicación y volver a inicializar el supervisor.")]),a("p",[e._v("El otro tipo de supervisores que hoy existe en Elixir y que nos permite inicializar dinámicamente procesos supervisados son los Supervisores dinámicos")]),a("p",[e._v("Esta es la documentación de los hexdocs con algunos puntos bien puntuales sobre los detalles de los "),a("a",{attrs:{href:"https://hexdocs.pm/elixir/DynamicSupervisor.html#content"}},[e._v("supervisores dinamicos")]),e._v(" Esta es la documentación un poco más "),a("a",{attrs:{href:"https://elixir-lang.org/getting-started/mix-otp/dynamic-supervisor.html"}},[e._v("descriptiva de los supervisores dinamicos")])]),a("p",[e._v("Recuerden bien que un supervisor no restaura ni guarda el estado del actor supervisado, una vez que muere, si este es reiniciado, vuelve a ser inicializado con el estado inicial, y si tenía un estado distinto antes de su muerte, este se pierde definitivamente, por lo que a veces es bueno tal vez o bien persistirlo o si es algo importante tenerlo en otro actor como puede ser un Agent.")]),a("p",[e._v("Otros recursos, tal vez un poco desactualizados:")]),a("p",[a("a",{attrs:{href:"https://docs.google.com/document/d/1r_E6Hj4F-38dy5tDbxfTBW2XaU8sSRaf9qtC-VuLDIw/edit#heading=h.40vnggga84mq"}},[e._v("Manejo de Errores e Introducción a la supervisión")])])])}],n=a("2877"),i={},t=Object(n["a"])(i,o,r,!1,null,null,null);s["default"]=t.exports}}]); +//# sourceMappingURL=chunk-2d0af7d3.c7489446.js.map \ No newline at end of file diff --git a/js/chunk-2d0af7d3.c7489446.js.map b/js/chunk-2d0af7d3.c7489446.js.map new file mode 100644 index 0000000..437f5c9 --- /dev/null +++ b/js/chunk-2d0af7d3.c7489446.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/content/otp.md?4519","webpack:///./src/content/otp.md"],"names":["render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","script","component"],"mappings":"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","file":"js/chunk-2d0af7d3.c7489446.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h2',{attrs:{\"id\":\"modulos-de-otp\"}},[_vm._v(\"Modulos de OTP \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#modulos-de-otp\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Existen algunos módulos que fuimos viendo, en mayor o menor medida, o que merecen ser mencionados son:\")]),_c('ul',[_c('li',[_vm._v(\"GenServer\")]),_c('li',[_vm._v(\"Application\")]),_c('li',[_vm._v(\"Registry\")]),_c('li',[_vm._v(\"Agent\")]),_c('li',[_vm._v(\"Supervisor\")]),_c('li',[_vm._v(\"Genserver (\"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/GenServer.html\"}},[_vm._v(\"Genserver Hexdocs\")]),_vm._v(\")\")])]),_c('p',[_vm._v(\"Para una descripcion un poco mas amena de lo que es un Genserver y de lo que hace, junto con ejemplos bastante claros, se puede ver en \"),_c('a',{attrs:{\"href\":\"https://elixir-lang.org/getting-started/mix-otp/genserver.html\"}},[_vm._v(\"hexdocs un poco mas de las especificaciones y temas puntuales de genserver\")])]),_c('p',[_vm._v(\"Un servidor OTP es un módulo que nos permite modelar un servidor o un cliente en una comunicación de cliente-servidor, y nos va a poder ayudar a que nuestro proceso pueda recibir tanto llamadas sincronicas como asincrónicas por medio de la convención de OTP. En su nivel más básico, un GenServer es un proceso único que ejecuta un bucle que maneja un mensaje por iteración y que siempre devuelve un estado que es el en el que queda el proceso, y también ayuda a modelar, mediante una convención, las distintas respuestas al cliente. También tiene las funciones que nos permiten hacer las llamadas a un servidor Genserver, las llamadas son:\")]),_c('ul',[_c('li',[_vm._v(\"Call: Para realizar llamadas sincrónicas a otro proceso Genserver, que requieren una respuesta del servidor, por medio de un handle_call (\"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/GenServer.html#call/3\"}},[_vm._v(\"Hexdocs\")]),_vm._v(\")\")]),_c('li',[_vm._v(\"Cast: Para realizar llamadas asincronicas a otro proceso Genserver, que no necesariamente require una respuesta del servidor, por medio de un handle_cast (\"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/GenServer.html#cast/2\"}},[_vm._v(\"Hexdocs\")]),_vm._v(\")\")])]),_c('p',[_vm._v(\"Tenemos tipos de mensajes, tanto asincrónicos como sincronicos, los tipos de mensajes que podemos utilizar son para manejar las llamadas:\")]),_c('ul',[_c('li',[_vm._v(\"Handle_call: Si bien todos los procesos de Elixir el envio de mensajes son asincrónicos, podemos siempre modelar una llamada asincrónica como sincrónica, mediante una espera activa, esperando una respuesta, handle_call nos permite que un proceso Genserver pueda exponer un callback que requiere una respuesta del cliente, por lo que una vez que se procesa este callback, se debe retornar una respuesta o un :reply que está conformado por la tupla {:reply, response, state}. Podemos ver todas la opciones de lo que puede retornar un handle_call (\"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/GenServer.html#c:handle_call/3\"}},[_vm._v(\"Hexdocs\")]),_vm._v(\")\")]),_c('li',[_vm._v(\"Handle_cast: Permite manejar mensajes asincronicos mediate llamadas cast, y que pueden devolver un resultado o no necesariamente. (\"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/GenServer.html#c:handle_cast/2\"}},[_vm._v(\"Hexdocs\")]),_vm._v(\")\")]),_c('li',[_vm._v(\"Handle_info: Permite manejar cualquier otro tipo de mensajes (\"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/GenServer.html#c:handle_info/2\"}},[_vm._v(\"Hexdocs\")]),_vm._v(\"))\")])]),_c('h2',{attrs:{\"id\":\"application-hexdocs\"}},[_vm._v(\"Application (\"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/Application.html\"}},[_vm._v(\"Hexdocs\")]),_vm._v(\") \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#application-hexdocs\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Este modulo permite modelar procesos que sirvan como un punto de entrada a nuestra aplicacion, sea para inicializar una aplicacion Erlang o de OTP, se puede ver un poco mas de detalle de este modulo en \"),_c('a',{attrs:{\"href\":\"https://elixir-lang.org/getting-started/mix-otp/supervisor-and-application.html#understanding-applications\"}},[_vm._v(\"hexdocs\")])]),_c('p',[_vm._v(\"Registry (\"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/Registry.html\"}},[_vm._v(\"Hexdocs\")]),_vm._v(\")\")]),_c('p',[_vm._v(\"Son un módulo de OTP que nos permite modelar procesos que nos permiten almacenar valores clave/valor de manera descentralizada. Suelen ser usados para algunas cosas como:\")]),_c('ul',[_c('li',[_vm._v(\"Dispatching\")]),_c('li',[_vm._v(\"Registro de claves clave/valor\")]),_c('li',[_vm._v(\"Registro de claves pub/sub\")])]),_c('p',[_vm._v(\"Después hay una manera de tener un sotre pero a lo largo de la instancia llamado ETS (\"),_c('a',{attrs:{\"href\":\"https://elixir-lang.org/getting-started/mix-otp/ets.html\"}},[_vm._v(\"Hexdocs\")]),_vm._v(\")\")]),_c('p',[_vm._v(\"Si se quiere tener un proceso que guarde un estado que no sea necesariamente algo del estilo clave/valor, podemos optar por otro tipo de módulo llamado Agent\")]),_c('h2',{attrs:{\"id\":\"agent-hexdocs\"}},[_vm._v(\"Agent (\"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/Agent.html\"}},[_vm._v(\"Hexdocs\")]),_vm._v(\") \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#agent-hexdocs\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"El agent es un módulo que nos permite modelar un proceso que permita almacenar un estado, y en general se usa solo para este propósito, obviamente este almacenamiento, tanto los Agent como los Registry, es solo en memoria y no se persiste en disco. Pueden ver el link en el titulo para mayor información, algo interesante para ver es la sección de cómo supervisar un Agent (\"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/Agent.html#module-how-to-supervise\"}},[_vm._v(\"https://hexdocs.pm/elixir/Agent.html#module-how-to-supervise\")]),_vm._v(\").\")]),_c('h2',{attrs:{\"id\":\"supervisores-hexdocs\"}},[_vm._v(\"Supervisores (\"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/Supervisor.html\"}},[_vm._v(\"Hexdocs\")]),_vm._v(\") \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#supervisores-hexdocs\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Un supervisor es un proceso que supervisa otros procesos, a los que nos referimos como procesos secundarios. Los supervisores se utilizan para construir una estructura de proceso jerárquica denominada árbol de supervisión. Los árboles de supervisión proporcionan tolerancia a fallos y resumen cómo se inician y se cierran nuestras aplicaciones. Por lo que podemos reiniciar una lista de procesos por medio de un supervisor en caso de que alguno de esos procesos se caiga, sea por un error o no..\")]),_c('p',[_vm._v(\"Se tiene que tener varias cosas en cuentas sobre un esquema de supervisión...\")]),_c('p',[_vm._v(\"La especificación de los hijos o procesos que serán especificados\")]),_c('p',[_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/Supervisor.html#module-child-specification\"}},[_vm._v(\"Documentacion de la especificacion\")])]),_c('p',[_vm._v(\"Dos de los argumentos de las especificaciones del child spec son:\")]),_c('p',[_vm._v(\"el valor de \"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/Supervisor.html#module-shutdown-values-shutdown\"}},[_vm._v(\"shutdown\")]),_vm._v(\", que es la estrategia de cómo se debería cerrar o matar el proceso, cuando falla o se cae.\")]),_c('p',[_vm._v(\"Y más importante es la del \"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/Supervisor.html#module-restart-values-restart\"}},[_vm._v(\"valor de reinicio de un proceso supervisado\")])]),_c('h3',{attrs:{\"id\":\"como-se-define-un-supervisor\"}},[_vm._v(\"Como se define un Supervisor? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#como-se-define-un-supervisor\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Mediante un modulo generalmente (\"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/Supervisor.html#module-restart-values-restart\"}},[_vm._v(\"Hexdocs\")]),_vm._v(\")\")]),_c('p',[_vm._v(\"Ahora el supervisor recibe además de un child_spec una \"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/Supervisor.html#module-start_link-2-init-2-and-strategies\"}},[_vm._v(\"estrategia de supervisión\")]),_vm._v(\", que será la acción que tomará un supervisor cuando se caen los procesos supervisados.\")]),_c('p',[_vm._v(\"En el child spec siempre vamos no solo a poder supervisar procesos que son hojas, o sea procesos que van a tener lógica de un sistema, o de nuestra aplicación, o pueden ser otros nodos que pueden ser no terminales, o sea, supervisores, por lo que podemos armar un árbol de supervisión de esta manera.\")]),_c('p',[_vm._v(\"Hay otras estrategias deprecadas, tales como las :simple_one_for_one, que hoy fueron reemplazadas por otro tipo de supervisores, esto es porque los Supervisor son para modelar procesos que son supervisores estáticos, o sea que una vez inicializado no se pueden agregar procesos supervisados, por lo que al ser estático, si se quieren hacer cambios, se debe cambiar el childspec, levantar de nuevo la aplicación y volver a inicializar el supervisor.\")]),_c('p',[_vm._v(\"El otro tipo de supervisores que hoy existe en Elixir y que nos permite inicializar dinámicamente procesos supervisados son los Supervisores dinámicos\")]),_c('p',[_vm._v(\"Esta es la documentación de los hexdocs con algunos puntos bien puntuales sobre los detalles de los \"),_c('a',{attrs:{\"href\":\"https://hexdocs.pm/elixir/DynamicSupervisor.html#content\"}},[_vm._v(\"supervisores dinamicos\")]),_vm._v(\" Esta es la documentación un poco más \"),_c('a',{attrs:{\"href\":\"https://elixir-lang.org/getting-started/mix-otp/dynamic-supervisor.html\"}},[_vm._v(\"descriptiva de los supervisores dinamicos\")])]),_c('p',[_vm._v(\"Recuerden bien que un supervisor no restaura ni guarda el estado del actor supervisado, una vez que muere, si este es reiniciado, vuelve a ser inicializado con el estado inicial, y si tenía un estado distinto antes de su muerte, este se pierde definitivamente, por lo que a veces es bueno tal vez o bien persistirlo o si es algo importante tenerlo en otro actor como puede ser un Agent.\")]),_c('p',[_vm._v(\"Otros recursos, tal vez un poco desactualizados:\")]),_c('p',[_c('a',{attrs:{\"href\":\"https://docs.google.com/document/d/1r_E6Hj4F-38dy5tDbxfTBW2XaU8sSRaf9qtC-VuLDIw/edit#heading=h.40vnggga84mq\"}},[_vm._v(\"Manejo de Errores e Introducción a la supervisión\")])])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./otp.md?vue&type=template&id=1a50383c&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-2d0b2d29.5982e5a9.js b/js/chunk-2d0b2d29.5982e5a9.js new file mode 100644 index 0000000..75c8ff7 --- /dev/null +++ b/js/chunk-2d0b2d29.5982e5a9.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0b2d29"],{"266e":function(e,n,t){"use strict";t.r(n);var u=function(){var e=this,n=e.$createElement,t=e._self._c||n;return t("div",[e._t("default")],2)},l=[],c=t("2877"),a={},r=Object(c["a"])(a,u,l,!1,null,null,null);n["default"]=r.exports}}]); +//# sourceMappingURL=chunk-2d0b2d29.5982e5a9.js.map \ No newline at end of file diff --git a/js/chunk-2d0b2d29.5982e5a9.js.map b/js/chunk-2d0b2d29.5982e5a9.js.map new file mode 100644 index 0000000..5face9b --- /dev/null +++ b/js/chunk-2d0b2d29.5982e5a9.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/layouts/AppLayoutDefault.vue?ce0b","webpack:///./src/layouts/AppLayoutDefault.vue"],"names":["render","_vm","this","_h","$createElement","_c","_self","_t","staticRenderFns","script","component"],"mappings":"yHAAA,IAAIA,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACJ,EAAIM,GAAG,YAAY,IACzHC,EAAkB,G,YCAlBC,EAAS,GAKTC,EAAY,eACdD,EACAT,EACAQ,GACA,EACA,KACA,KACA,MAIa,aAAAE,E","file":"js/chunk-2d0b2d29.5982e5a9.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_vm._t(\"default\")],2)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./AppLayoutDefault.vue?vue&type=template&id=8107ea64&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-2d0bd92b.10106dec.js b/js/chunk-2d0bd92b.10106dec.js new file mode 100644 index 0000000..f261db7 --- /dev/null +++ b/js/chunk-2d0bd92b.10106dec.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0bd92b"],{"2d25":function(e,a,s){"use strict";s.r(a);var r=function(){var e=this,a=e.$createElement;e._self._c;return e._m(0)},n=[function(){var e=this,a=e.$createElement,s=e._self._c||a;return s("section",[s("h2",{attrs:{id:"paradigma-funcional-qué-es-eso"}},[e._v("¿Paradigma Funcional? ¿Qué es eso? "),s("a",{staticClass:"header-anchor",attrs:{href:"#paradigma-funcional-qué-es-eso"}},[e._v("¶")])]),s("p",[e._v("Es irónico que aunque el paradigma funcional es muy anterior al paradigma de objetos, lo que le ha dado la posibilidad de construir sólidas bases, es difícil dar una definición del mismo. Por ejemplo, la definición más obvia reza que funcional es un paradigma en el que las soluciones a los problemas se estructuran en términos de aplicación de funciones y, si bien es correcta, hay tantos elementos fundamentales que se desprenden de ésta y que no son evidentes que resulta de poca utilidad.")]),s("p",[e._v("Quizás sea más útil pensarlo a partir de las características más frecuentemente evocadas cuando se piensa en éste:")]),s("ul",[s("li",[e._v("Pureza: las funciones, al igual que en matemática, no presentan efectos colaterales, sino que tan sólo reciben, operan y devuelven valores")]),s("li",[e._v("Evaluación diferida: ciertas partes del código no se evaluarán salvo que sea necesario")]),s("li",[e._v("Funciones de primer orden: las funciones son valores, y por tanto pueden ser pasadas por parámetro")]),s("li",[e._v("Pattern matching: los valores pueden ser descompuestos estructuralmente, en un proceso inverso a la construcción: la deconstrucción. Y además podemos usar a esta herramienta como mecanismo de control de flujo: según encaje un valor con un patrón u otro, podremos tomar acciones diferentes.")]),s("li",[e._v("Expresiones lambda: Es posible escribir valores de función de forma literal, sin asignarle un nombre.")]),s("li",[e._v("Inmutabilidad: las variables son meras etiquetas, que una vez unificadas contra un valor, no pueden ser cambiadas.")])]),s("p",[e._v("Sin embargo, ¿son las anteriores ideas propias del paradigma funcional? Miremos más en detalle:")]),s("ul",[s("li",[e._v("No todos los lenguajes funcionales son realmente puros. LISP y sus derivados, por ejemplo, no lo son normalmente: permiten hacer input-ouput (IO) imperativo, modificar variables, etc.")]),s("li",[e._v("No todos los lenguajes funcionales presentan evaluación diferida. Para ser justos, ni siquiera Haskell: éste ofrece evaluación no-estricta, lo cual es ligeramente diferente.")])]),s("p",[e._v("Por un lado muchos lenguajes (funcionales o no) presentan algún tipo de operación de deconstrucción: Ruby, ECMAScript6, Clojure, etc, que es la base para implementar pattern-matching. Y por otro lado, la idea de Pattern matching no figura en Cálculo Lambda, la base teórica de funcional.")]),s("p",[e._v("Virtualmente todos los lenguajes modernos presentan lambdas, closures o bloques de código, que permiten cosificar una porción de código.")]),s("p",[e._v("Si nada de lo que parece tan propio de funcional es realmente exclusivo del mismo, entonces, volvemos a la pregunta: ¿qué es eso? Simple: es la forma particular en que combinamos estas herramientas, razonando declarativamente en términos de valores y transformaciones sobre los mismos. Nuevamente, el todo es más que la suma de las partes.")]),s("p",[e._v("Durante las próximas clases vamos a estar viendo por qué el paradigma funcional puede ser una herramienta muy útil a la hora de trabajar con concurrencia y paralelismo. En particular, vamos a estar trabajando con Haskell, uno de los exponentes más notables de este paradigma. Pero antes, vamos a necesitar aprender (o repasar) algunos conceptos que nos van a ser de utilidad más adelante.")]),s("h2",{attrs:{id:"sobre-pureza-en-funcional"}},[e._v("Sobre pureza en funcional "),s("a",{staticClass:"header-anchor",attrs:{href:"#sobre-pureza-en-funcional"}},[e._v("¶")])]),s("p",[e._v("Haskell es un lenguaje puro; toda operación es similar a una función matemática, donde el resultado de dicha función depende únicamente de sus argumentos. Tanto es así, que hasta los efectos están modelados como valores de tipo IO, que representa un efecto, el cual puede ser operado como cualquier otro valor: podemos pasar efectos por parámetros, colocarlos en listas, ordenarlos, etc. De hecho, un programa ejecutable es una función que devuelve un valor de tipo IO. El runtime de Haskell ejecuta el efecto representado por este valor, produciendo así los efectos en el mundo real deseados. Moraleja: un programa Haskell no tiene efectos, pero es capaz de devolver un valor que los representa, pudiendo así hacer todo lo que un programa imperativo podría hacer, y más.")]),s("h2",{attrs:{id:"simplicidad"}},[e._v("Simplicidad "),s("a",{staticClass:"header-anchor",attrs:{href:"#simplicidad"}},[e._v("¶")])]),s("p",[e._v("La sintaxis e ideas fundamentales de Haskell son realmente simples, y el resto de las ideas más complejas se construyen normalmente sobre las más simples.")]),s("p",[s("strong",[e._v("TODO: Completar o eliminar sección.")])]),s("h2",{attrs:{id:"tipos-en-haskell"}},[e._v("Tipos en Haskell "),s("a",{staticClass:"header-anchor",attrs:{href:"#tipos-en-haskell"}},[e._v("¶")])]),s("p",[e._v("A diferencia de otros lenguajes, como Ruby o Smalltalk, Haskell tiene un sistema de tipos estático. Esto significa que el tipo de cada expresión es conocido en tiempo de compilación.")]),s("p",[e._v("Ilustrémoslo con un ejemplo: si tenemos una función que suma dos números, y le pasamos un string que se sume a un int, en un lenguaje dinámico solo fallaría en tiempo de ejecución, mientras que en un lenguaje con un sistema de tipos estático, no compilaría. Esto permite que puedan capturarse errores en tiempo de compilación en vez de que tengan que aparecer en ejecución.")]),s("p",[e._v("En Haskell todo tiene un tipo, y a diferencia de otros lenguajes similares como Java, Haskell tiene además inferencia de tipos. Si escribimos un número, no tenemos que decirle a Haskell que es un número, sino que puede inferirlo solo. El tipo de un valor se puede conocer por medio del comando "),s("code",{pre:!0},[e._v(":t")]),e._v(":")]),s("pre",{pre:!0},[s("code",{pre:!0,attrs:{"v-pre":"",class:"language-haskell"}},[s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Prelude")]),e._v("> :t 'a'\n'a' :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Char")]),e._v("\n"),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Prelude")]),e._v("> :t "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("True")]),e._v("\n"),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("True")]),e._v(" :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Bool")]),e._v("\n")])]),s("p",[e._v("Como vemos en el GhCI, cuando ejecutamos el comando "),s("code",{pre:!0},[e._v(":t")]),e._v(" junto con un valor, nos dice de qué tipo es. "),s("code",{pre:!0},[e._v("x :: T")]),e._v(' puede leerse como "x es del tipo T".')]),s("p",[e._v("Con expresiones más complejas podemos ver algo como lo siguiente:")]),s("pre",{pre:!0},[s("code",{pre:!0,attrs:{"v-pre":"",class:"language-haskell"}},[s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Prelude")]),e._v("> :t "),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("4")]),e._v(" + "),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("3")]),e._v("\n"),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("4")]),e._v(" + "),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("3")]),e._v(" :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Num")]),e._v(" a => a\n")])]),s("p",[e._v("Simple, todas las expresiones generan un valor con un tipo asociado.")]),s("p",[e._v("Las funciones son otra cosa que también necesita una declaración de tipos, y es una buena práctica que ayuda al sistema de inferencia de tipos, y es recomendado a menos que se necesite crear funciones muy chicas. Empecemos con un ejemplo bien simple:")]),s("pre",{pre:!0},[s("code",{pre:!0,attrs:{"v-pre":"",class:"language-haskell"}},[s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Prelude")]),e._v("> "),s("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("let")]),e._v(" succ a = a + "),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v("\n"),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Prelude")]),e._v("> :t succ\n"),s("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("succ")]),e._v(" :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Num")]),e._v(" a => a -> a \n")])]),s("p",[e._v("Esto se vería así en un código que no sea ghci")]),s("pre",{pre:!0},[s("code",{pre:!0,attrs:{"v-pre":"",class:"language-haskell"}},[s("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("succ")]),e._v(" :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Int")]),e._v(" -> "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Int")]),e._v("\n"),s("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("succ")]),e._v(" a = a + "),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v("\n")])]),s("p",[e._v("Veamos un poco más en detalle otro prototipo de función, por ej. "),s("code",{pre:!0},[e._v("head")]),e._v(" y "),s("code",{pre:!0},[e._v("tail")])]),s("pre",{pre:!0},[s("code",{pre:!0,attrs:{"v-pre":"",class:"language-haskell"}},[s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Prelude")]),e._v("> :t head\n"),s("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("head")]),e._v(" :: [a] -> a\n\n"),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Prelude")]),e._v("> :t tail\n"),s("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("tail")]),e._v(" :: [a] -> [a]\n")])]),s("p",[e._v("Este ejemplo es bien conocido por tomar el primer elemento de una lista, head. Pero veamos la declaración de tipos, head toma un parámetro, que es del tipo lista de a. Pero a no es un tipo... ¿qué es entonces? En este caso es un tipo genérico. Puede ser un "),s("code",{pre:!0},[e._v("Int")]),e._v(", "),s("code",{pre:!0},[e._v("String")]),e._v(", etc., pero el tipo va a ser consistente; es decir, si tenemos una función que va de "),s("code",{pre:!0},[e._v("[a] -> a")]),e._v(", entonces si a es un "),s("code",{pre:!0},[e._v("Int")]),e._v(", la función va a tomar una lista de "),s("code",{pre:!0},[e._v("Int")]),e._v(", y devolver un "),s("code",{pre:!0},[e._v("Int")]),e._v(". Esto es porque la función es polimórfica y puede tomar cualquier lista de un tipo, y devolver el primer elemento, sin importar de qué tipo es la lista.")]),s("p",[e._v("Nuestra función "),s("code",{pre:!0},[e._v("succ")]),e._v(", en cambio, solo toma un "),s("code",{pre:!0},[e._v("Int")]),e._v(" y devuelve otro "),s("code",{pre:!0},[e._v("Int")]),e._v(". Si le pasamos algo de tipo "),s("code",{pre:!0},[e._v("String")]),e._v(", fallaría en tiempo de compilación.")]),s("p",[e._v("En el ejemplo de "),s("code",{pre:!0},[e._v("head")]),e._v(", en la declaración de tipos, a es llamado type variable.")]),s("p",[e._v("Tomemos otro ejemplo, "),s("code",{pre:!0},[e._v("fst")])]),s("pre",{pre:!0},[s("code",{pre:!0,attrs:{"v-pre":"",class:"language-haskell"}},[s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Prelude")]),e._v("> :t fst\n"),s("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("fst")]),e._v(" :: (a, b) -> a\n")])]),s("p",[e._v("En este caso se puede ver cómo la función toma una tupla y devuelve el primer elemento, y tenemos dos type variables, a y b, que si bien son diferentes, no significa que sean de tipos distintos. También podemos ver que el primer elemento y lo que devuelve la función son del mismo tipo, tal como ocurre con "),s("code",{pre:!0},[e._v("head")]),e._v(".")]),s("h2",{attrs:{id:"typeclases"}},[e._v("Typeclases "),s("a",{staticClass:"header-anchor",attrs:{href:"#typeclases"}},[e._v("¶")])]),s("p",[e._v("Una Typeclass es como una especie de interfaz que define un comportamiento. Si un tipo es parte de una typeclass, el tipo soporta e implementa el comportamiento que describe dicha typeclass. Haciendo una comparación con el paradigma de objetos, podríamos decir que las typeclases son como las interfaces de Java, pero implementando el comportamiento, no solo definiendo su contrato.")]),s("p",[e._v("Veamos la operación suma de "),s("code",{pre:!0},[e._v("succ")])]),s("pre",{pre:!0},[s("code",{pre:!0,attrs:{"v-pre":"",class:"language-haskell"}},[s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Prelude")]),e._v("> :t (+)\n(+) :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Num")]),e._v(" a => a -> a -> a\n")])]),s("p",[e._v("Antes que nada vemos que ahora está el símbolo "),s("code",{pre:!0},[e._v("=>")]),e._v(". La lectura hacia la derecha es como las funciones que vimos hasta ahora: la función toma dos elementos de tipo a y devuelve otro de tipo a. A la izquierda del "),s("code",{pre:!0},[e._v("=>")]),e._v(" se indica que el tipo de los dos valores y el retorno deben ser miembros de la clase "),s("code",{pre:!0},[e._v("Num")]),e._v(". Esto último se conoce como "),s("strong",[e._v("class constraint")]),e._v(".")]),s("p",[e._v("Veamos otro ejemplo")]),s("pre",{pre:!0},[s("code",{pre:!0,attrs:{"v-pre":"",class:"language-haskell"}},[s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Prelude")]),e._v("> :t (<=)\n(<=) :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Ord")]),e._v(" a => a -> a -> "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Bool")]),e._v("\n")])]),s("p",[s("code",{pre:!0},[e._v("Ord")]),e._v(" es otra typeclass, que define la interfaz para ordenamiento (<, >, <= y >=, entre otras), por lo que cualquier tipo que requiera ordenamiento de dos o más elementos, debe ser un miembro de "),s("code",{pre:!0},[e._v("Ord")]),e._v(".")]),s("p",[e._v("Volviendo a la suma, vimos que "),s("code",{pre:!0},[e._v("Num")]),e._v(" es un typeclass numérico, y permite que un tipo actúe como número, por ej:")]),s("pre",{pre:!0},[s("code",{pre:!0,attrs:{"v-pre":"",class:"language-haskell"}},[s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Prelude")]),e._v("> :t "),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("42")]),e._v("\n"),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("42")]),e._v(" :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Num")]),e._v(" a => a\n")])]),s("p",[e._v("Por lo que los números pueden actuar como constantes polimórficas, por lo que podemos definir un 42 numérico, flotante o doble, pero hay operaciones que si bien son parte del typeclass, su contrato debe ser cumplido, por ej. si sumamos un doble con un interfaces")]),s("pre",{pre:!0},[s("code",{pre:!0,attrs:{"v-pre":"",class:"language-haskell"}},[s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Prelude")]),e._v("> ("),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("42")]),e._v(" :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Integer")]),e._v(") + ("),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("2")]),e._v(" :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Double")]),e._v(")\n\n:"),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("25")]),e._v(":"),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("20")]),e._v(":\n "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Couldn't")]),e._v(" match expected "),s("span",{pre:!0,attrs:{class:"hljs-class"}},[s("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("type")]),e._v(" ‘"),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Integer")]),e._v("’ with actual "),s("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("type")]),e._v(" ‘"),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Double")]),e._v("’")]),e._v("\n "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("In")]),e._v(" the second argument "),s("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("of")]),e._v(" ‘(+)’, namely ‘("),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("2")]),e._v(" :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Double")]),e._v(")’\n "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("In")]),e._v(" the expression: ("),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("42")]),e._v(" :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Integer")]),e._v(") + ("),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("2")]),e._v(" :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Double")]),e._v(")\n "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("In")]),e._v(" an equation for ‘it’: it = ("),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("42")]),e._v(" :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Integer")]),e._v(") + ("),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("2")]),e._v(" :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Double")]),e._v(")\n"),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Prelude")]),e._v("> ("),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("42")]),e._v(" :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Integer")]),e._v(") + ("),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("2")]),e._v(" :: "),s("span",{pre:!0,attrs:{class:"hljs-type"}},[e._v("Integer")]),e._v(")\n"),s("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("44")]),e._v("\n")])]),s("h2",{attrs:{id:"dualidad-en-estructuras-de-tipos"}},[e._v("Dualidad en estructuras de tipos "),s("a",{staticClass:"header-anchor",attrs:{href:"#dualidad-en-estructuras-de-tipos"}},[e._v("¶")])]),s("p",[e._v("Cada una de ellas presenta una dualidad, pudiendo ser pensada tanto como una estructura de datos, como una estructura de control. Dicho de otra forma, a las estructuras funcionales podemos verlas tanto como contenedores (cajas que almacenan valores) como computaciones (operaciones que al ejecutarlas producen valores).")])])}],o=s("2877"),t={},l=Object(o["a"])(t,r,n,!1,null,null,null);a["default"]=l.exports}}]); +//# sourceMappingURL=chunk-2d0bd92b.10106dec.js.map \ No newline at end of file diff --git a/js/chunk-2d0bd92b.10106dec.js.map b/js/chunk-2d0bd92b.10106dec.js.map new file mode 100644 index 0000000..f93b4ab --- /dev/null +++ b/js/chunk-2d0bd92b.10106dec.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/content/estructuras_funcionales.md?9b26","webpack:///./src/content/estructuras_funcionales.md"],"names":["render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","pre","script","component"],"mappings":"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","file":"js/chunk-2d0bd92b.10106dec.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h2',{attrs:{\"id\":\"paradigma-funcional-qué-es-eso\"}},[_vm._v(\"¿Paradigma Funcional? ¿Qué es eso? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#paradigma-funcional-qué-es-eso\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Es irónico que aunque el paradigma funcional es muy anterior al paradigma de objetos, lo que le ha dado la posibilidad de construir sólidas bases, es difícil dar una definición del mismo. Por ejemplo, la definición más obvia reza que funcional es un paradigma en el que las soluciones a los problemas se estructuran en términos de aplicación de funciones y, si bien es correcta, hay tantos elementos fundamentales que se desprenden de ésta y que no son evidentes que resulta de poca utilidad.\")]),_c('p',[_vm._v(\"Quizás sea más útil pensarlo a partir de las características más frecuentemente evocadas cuando se piensa en éste:\")]),_c('ul',[_c('li',[_vm._v(\"Pureza: las funciones, al igual que en matemática, no presentan efectos colaterales, sino que tan sólo reciben, operan y devuelven valores\")]),_c('li',[_vm._v(\"Evaluación diferida: ciertas partes del código no se evaluarán salvo que sea necesario\")]),_c('li',[_vm._v(\"Funciones de primer orden: las funciones son valores, y por tanto pueden ser pasadas por parámetro\")]),_c('li',[_vm._v(\"Pattern matching: los valores pueden ser descompuestos estructuralmente, en un proceso inverso a la construcción: la deconstrucción. Y además podemos usar a esta herramienta como mecanismo de control de flujo: según encaje un valor con un patrón u otro, podremos tomar acciones diferentes.\")]),_c('li',[_vm._v(\"Expresiones lambda: Es posible escribir valores de función de forma literal, sin asignarle un nombre.\")]),_c('li',[_vm._v(\"Inmutabilidad: las variables son meras etiquetas, que una vez unificadas contra un valor, no pueden ser cambiadas.\")])]),_c('p',[_vm._v(\"Sin embargo, ¿son las anteriores ideas propias del paradigma funcional? Miremos más en detalle:\")]),_c('ul',[_c('li',[_vm._v(\"No todos los lenguajes funcionales son realmente puros. LISP y sus derivados, por ejemplo, no lo son normalmente: permiten hacer input-ouput (IO) imperativo, modificar variables, etc.\")]),_c('li',[_vm._v(\"No todos los lenguajes funcionales presentan evaluación diferida. Para ser justos, ni siquiera Haskell: éste ofrece evaluación no-estricta, lo cual es ligeramente diferente.\")])]),_c('p',[_vm._v(\"Por un lado muchos lenguajes (funcionales o no) presentan algún tipo de operación de deconstrucción: Ruby, ECMAScript6, Clojure, etc, que es la base para implementar pattern-matching. Y por otro lado, la idea de Pattern matching no figura en Cálculo Lambda, la base teórica de funcional.\")]),_c('p',[_vm._v(\"Virtualmente todos los lenguajes modernos presentan lambdas, closures o bloques de código, que permiten cosificar una porción de código.\")]),_c('p',[_vm._v(\"Si nada de lo que parece tan propio de funcional es realmente exclusivo del mismo, entonces, volvemos a la pregunta: ¿qué es eso? Simple: es la forma particular en que combinamos estas herramientas, razonando declarativamente en términos de valores y transformaciones sobre los mismos. Nuevamente, el todo es más que la suma de las partes.\")]),_c('p',[_vm._v(\"Durante las próximas clases vamos a estar viendo por qué el paradigma funcional puede ser una herramienta muy útil a la hora de trabajar con concurrencia y paralelismo. En particular, vamos a estar trabajando con Haskell, uno de los exponentes más notables de este paradigma. Pero antes, vamos a necesitar aprender (o repasar) algunos conceptos que nos van a ser de utilidad más adelante.\")]),_c('h2',{attrs:{\"id\":\"sobre-pureza-en-funcional\"}},[_vm._v(\"Sobre pureza en funcional \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#sobre-pureza-en-funcional\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Haskell es un lenguaje puro; toda operación es similar a una función matemática, donde el resultado de dicha función depende únicamente de sus argumentos. Tanto es así, que hasta los efectos están modelados como valores de tipo IO, que representa un efecto, el cual puede ser operado como cualquier otro valor: podemos pasar efectos por parámetros, colocarlos en listas, ordenarlos, etc. De hecho, un programa ejecutable es una función que devuelve un valor de tipo IO. El runtime de Haskell ejecuta el efecto representado por este valor, produciendo así los efectos en el mundo real deseados. Moraleja: un programa Haskell no tiene efectos, pero es capaz de devolver un valor que los representa, pudiendo así hacer todo lo que un programa imperativo podría hacer, y más.\")]),_c('h2',{attrs:{\"id\":\"simplicidad\"}},[_vm._v(\"Simplicidad \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#simplicidad\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"La sintaxis e ideas fundamentales de Haskell son realmente simples, y el resto de las ideas más complejas se construyen normalmente sobre las más simples.\")]),_c('p',[_c('strong',[_vm._v(\"TODO: Completar o eliminar sección.\")])]),_c('h2',{attrs:{\"id\":\"tipos-en-haskell\"}},[_vm._v(\"Tipos en Haskell \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#tipos-en-haskell\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"A diferencia de otros lenguajes, como Ruby o Smalltalk, Haskell tiene un sistema de tipos estático. Esto significa que el tipo de cada expresión es conocido en tiempo de compilación.\")]),_c('p',[_vm._v(\"Ilustrémoslo con un ejemplo: si tenemos una función que suma dos números, y le pasamos un string que se sume a un int, en un lenguaje dinámico solo fallaría en tiempo de ejecución, mientras que en un lenguaje con un sistema de tipos estático, no compilaría. Esto permite que puedan capturarse errores en tiempo de compilación en vez de que tengan que aparecer en ejecución.\")]),_c('p',[_vm._v(\"En Haskell todo tiene un tipo, y a diferencia de otros lenguajes similares como Java, Haskell tiene además inferencia de tipos. Si escribimos un número, no tenemos que decirle a Haskell que es un número, sino que puede inferirlo solo. El tipo de un valor se puede conocer por medio del comando \"),_c('code',{pre:true},[_vm._v(\":t\")]),_vm._v(\":\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-haskell\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Prelude\")]),_vm._v(\"> :t 'a'\\n'a' :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Char\")]),_vm._v(\"\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Prelude\")]),_vm._v(\"> :t \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"True\")]),_vm._v(\"\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"True\")]),_vm._v(\" :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Bool\")]),_vm._v(\"\\n\")])]),_c('p',[_vm._v(\"Como vemos en el GhCI, cuando ejecutamos el comando \"),_c('code',{pre:true},[_vm._v(\":t\")]),_vm._v(\" junto con un valor, nos dice de qué tipo es. \"),_c('code',{pre:true},[_vm._v(\"x :: T\")]),_vm._v(\" puede leerse como \\\"x es del tipo T\\\".\")]),_c('p',[_vm._v(\"Con expresiones más complejas podemos ver algo como lo siguiente:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-haskell\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Prelude\")]),_vm._v(\"> :t \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"4\")]),_vm._v(\" + \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"3\")]),_vm._v(\"\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"4\")]),_vm._v(\" + \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"3\")]),_vm._v(\" :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Num\")]),_vm._v(\" a => a\\n\")])]),_c('p',[_vm._v(\"Simple, todas las expresiones generan un valor con un tipo asociado.\")]),_c('p',[_vm._v(\"Las funciones son otra cosa que también necesita una declaración de tipos, y es una buena práctica que ayuda al sistema de inferencia de tipos, y es recomendado a menos que se necesite crear funciones muy chicas. Empecemos con un ejemplo bien simple:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-haskell\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Prelude\")]),_vm._v(\"> \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"let\")]),_vm._v(\" succ a = a + \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\"\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Prelude\")]),_vm._v(\"> :t succ\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"succ\")]),_vm._v(\" :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Num\")]),_vm._v(\" a => a -> a \\n\")])]),_c('p',[_vm._v(\"Esto se vería así en un código que no sea ghci\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-haskell\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"succ\")]),_vm._v(\" :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Int\")]),_vm._v(\" -> \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Int\")]),_vm._v(\"\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"succ\")]),_vm._v(\" a = a + \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\"\\n\")])]),_c('p',[_vm._v(\"Veamos un poco más en detalle otro prototipo de función, por ej. \"),_c('code',{pre:true},[_vm._v(\"head\")]),_vm._v(\" y \"),_c('code',{pre:true},[_vm._v(\"tail\")])]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-haskell\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Prelude\")]),_vm._v(\"> :t head\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"head\")]),_vm._v(\" :: [a] -> a\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Prelude\")]),_vm._v(\"> :t tail\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"tail\")]),_vm._v(\" :: [a] -> [a]\\n\")])]),_c('p',[_vm._v(\"Este ejemplo es bien conocido por tomar el primer elemento de una lista, head. Pero veamos la declaración de tipos, head toma un parámetro, que es del tipo lista de a. Pero a no es un tipo... ¿qué es entonces? En este caso es un tipo genérico. Puede ser un \"),_c('code',{pre:true},[_vm._v(\"Int\")]),_vm._v(\", \"),_c('code',{pre:true},[_vm._v(\"String\")]),_vm._v(\", etc., pero el tipo va a ser consistente; es decir, si tenemos una función que va de \"),_c('code',{pre:true},[_vm._v(\"[a] -> a\")]),_vm._v(\", entonces si a es un \"),_c('code',{pre:true},[_vm._v(\"Int\")]),_vm._v(\", la función va a tomar una lista de \"),_c('code',{pre:true},[_vm._v(\"Int\")]),_vm._v(\", y devolver un \"),_c('code',{pre:true},[_vm._v(\"Int\")]),_vm._v(\". Esto es porque la función es polimórfica y puede tomar cualquier lista de un tipo, y devolver el primer elemento, sin importar de qué tipo es la lista.\")]),_c('p',[_vm._v(\"Nuestra función \"),_c('code',{pre:true},[_vm._v(\"succ\")]),_vm._v(\", en cambio, solo toma un \"),_c('code',{pre:true},[_vm._v(\"Int\")]),_vm._v(\" y devuelve otro \"),_c('code',{pre:true},[_vm._v(\"Int\")]),_vm._v(\". Si le pasamos algo de tipo \"),_c('code',{pre:true},[_vm._v(\"String\")]),_vm._v(\", fallaría en tiempo de compilación.\")]),_c('p',[_vm._v(\"En el ejemplo de \"),_c('code',{pre:true},[_vm._v(\"head\")]),_vm._v(\", en la declaración de tipos, a es llamado type variable.\")]),_c('p',[_vm._v(\"Tomemos otro ejemplo, \"),_c('code',{pre:true},[_vm._v(\"fst\")])]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-haskell\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Prelude\")]),_vm._v(\"> :t fst\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"fst\")]),_vm._v(\" :: (a, b) -> a\\n\")])]),_c('p',[_vm._v(\"En este caso se puede ver cómo la función toma una tupla y devuelve el primer elemento, y tenemos dos type variables, a y b, que si bien son diferentes, no significa que sean de tipos distintos. También podemos ver que el primer elemento y lo que devuelve la función son del mismo tipo, tal como ocurre con \"),_c('code',{pre:true},[_vm._v(\"head\")]),_vm._v(\".\")]),_c('h2',{attrs:{\"id\":\"typeclases\"}},[_vm._v(\"Typeclases \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#typeclases\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Una Typeclass es como una especie de interfaz que define un comportamiento. Si un tipo es parte de una typeclass, el tipo soporta e implementa el comportamiento que describe dicha typeclass. Haciendo una comparación con el paradigma de objetos, podríamos decir que las typeclases son como las interfaces de Java, pero implementando el comportamiento, no solo definiendo su contrato.\")]),_c('p',[_vm._v(\"Veamos la operación suma de \"),_c('code',{pre:true},[_vm._v(\"succ\")])]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-haskell\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Prelude\")]),_vm._v(\"> :t (+)\\n(+) :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Num\")]),_vm._v(\" a => a -> a -> a\\n\")])]),_c('p',[_vm._v(\"Antes que nada vemos que ahora está el símbolo \"),_c('code',{pre:true},[_vm._v(\"=>\")]),_vm._v(\". La lectura hacia la derecha es como las funciones que vimos hasta ahora: la función toma dos elementos de tipo a y devuelve otro de tipo a. A la izquierda del \"),_c('code',{pre:true},[_vm._v(\"=>\")]),_vm._v(\" se indica que el tipo de los dos valores y el retorno deben ser miembros de la clase \"),_c('code',{pre:true},[_vm._v(\"Num\")]),_vm._v(\". Esto último se conoce como \"),_c('strong',[_vm._v(\"class constraint\")]),_vm._v(\".\")]),_c('p',[_vm._v(\"Veamos otro ejemplo\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-haskell\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Prelude\")]),_vm._v(\"> :t (<=)\\n(<=) :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Ord\")]),_vm._v(\" a => a -> a -> \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Bool\")]),_vm._v(\"\\n\")])]),_c('p',[_c('code',{pre:true},[_vm._v(\"Ord\")]),_vm._v(\" es otra typeclass, que define la interfaz para ordenamiento (<, >, <= y >=, entre otras), por lo que cualquier tipo que requiera ordenamiento de dos o más elementos, debe ser un miembro de \"),_c('code',{pre:true},[_vm._v(\"Ord\")]),_vm._v(\".\")]),_c('p',[_vm._v(\"Volviendo a la suma, vimos que \"),_c('code',{pre:true},[_vm._v(\"Num\")]),_vm._v(\" es un typeclass numérico, y permite que un tipo actúe como número, por ej:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-haskell\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Prelude\")]),_vm._v(\"> :t \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"42\")]),_vm._v(\"\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"42\")]),_vm._v(\" :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Num\")]),_vm._v(\" a => a\\n\")])]),_c('p',[_vm._v(\"Por lo que los números pueden actuar como constantes polimórficas, por lo que podemos definir un 42 numérico, flotante o doble, pero hay operaciones que si bien son parte del typeclass, su contrato debe ser cumplido, por ej. si sumamos un doble con un interfaces\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-haskell\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Prelude\")]),_vm._v(\"> (\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"42\")]),_vm._v(\" :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Integer\")]),_vm._v(\") + (\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"2\")]),_vm._v(\" :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Double\")]),_vm._v(\")\\n\\n:\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"25\")]),_vm._v(\":\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"20\")]),_vm._v(\":\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Couldn't\")]),_vm._v(\" match expected \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-class\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"type\")]),_vm._v(\" ‘\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Integer\")]),_vm._v(\"’ with actual \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"type\")]),_vm._v(\" ‘\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Double\")]),_vm._v(\"’\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"In\")]),_vm._v(\" the second argument \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"of\")]),_vm._v(\" ‘(+)’, namely ‘(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"2\")]),_vm._v(\" :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Double\")]),_vm._v(\")’\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"In\")]),_vm._v(\" the expression: (\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"42\")]),_vm._v(\" :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Integer\")]),_vm._v(\") + (\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"2\")]),_vm._v(\" :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Double\")]),_vm._v(\")\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"In\")]),_vm._v(\" an equation for ‘it’: it = (\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"42\")]),_vm._v(\" :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Integer\")]),_vm._v(\") + (\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"2\")]),_vm._v(\" :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Double\")]),_vm._v(\")\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Prelude\")]),_vm._v(\"> (\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"42\")]),_vm._v(\" :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Integer\")]),_vm._v(\") + (\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"2\")]),_vm._v(\" :: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-type\"}},[_vm._v(\"Integer\")]),_vm._v(\")\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"44\")]),_vm._v(\"\\n\")])]),_c('h2',{attrs:{\"id\":\"dualidad-en-estructuras-de-tipos\"}},[_vm._v(\"Dualidad en estructuras de tipos \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#dualidad-en-estructuras-de-tipos\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Cada una de ellas presenta una dualidad, pudiendo ser pensada tanto como una estructura de datos, como una estructura de control. Dicho de otra forma, a las estructuras funcionales podemos verlas tanto como contenedores (cajas que almacenan valores) como computaciones (operaciones que al ejecutarlas producen valores).\")])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./estructuras_funcionales.md?vue&type=template&id=8c85f1ae&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-2d0c0352.17d5a176.js b/js/chunk-2d0c0352.17d5a176.js new file mode 100644 index 0000000..804ff21 --- /dev/null +++ b/js/chunk-2d0c0352.17d5a176.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0c0352"],{4198:function(e,a,o){"use strict";o.r(a);var n=function(){var e=this,a=e.$createElement;e._self._c;return e._m(0)},s=[function(){var e=this,a=e.$createElement,o=e._self._c||a;return o("section",[o("h2",{attrs:{id:"bonus-mitos-de-la-distribución"}},[e._v("Bonus: Mitos de la distribución "),o("a",{staticClass:"header-anchor",attrs:{href:"#bonus-mitos-de-la-distribución"}},[e._v("¶")])]),o("p",[e._v("Durante muchos tiempo, existieron 8 leyes o enunciados principales que son falacias y que son difíciles de manejar y la gente de erlang tomó algunas decisiones cuando se diseñó el lenguaje en sí.")]),o("ul",[o("li",[o("p",[e._v("La red es confiable: Esta es la primera falacia que hay en la computación distribuida, pueden existir fallos de red bastante más frecuente de lo que uno cree, más acá que en otros lados incluso por muchas razones (cortes de luz, falla de hardware, cable roto, etc). Entonces ya de por si no es verdadero que uno puede interconectar dos nodos en una red y siempre esperar que uno desde un nodo se puede conectar y hablar normalmente con otro nodo. Erlang en si no tiene un mecanismo especial para eso, lo mejor que nos provee es que haya una comunicación asincrónica en la que se manden mensajes asincrónicamente y después de un timeout se reintente o falle, entonces si un nodo se cae, lo manejaremos como si fuese un fallo local.")])]),o("li",[o("p",[e._v("No hay latencia: Esta es otra falacia ya que de por sí a menos que estén todos los nodos en una sola máquina, siempre existe la conocida latencia de red, e incluso si los nodos estuviesen localmente existe una pequeña latencia. Erlang de la manera en la que es, teniendo nodos como procesos aislados e independientes, mensajes asincrónicos, timeouts, monitores, nos permite ir manejando y viendo cómo ir tratando de manejar la latencia entre los distintos nodos e ir ajustando esto dependiendo de la red.")])]),o("li",[o("p",[e._v("El ancho de banda es infinito: Si bien el ancho de banda es mucho mayor que hace unos años, no hay que ir pasando exceso de información o gran cantidad de información entre dos nodos, siempre hay que tener en consideración que una comunicación entre dos nodos pasa en general mediante una conexión de TCP y solo una. Entonces todos los mensajes que mandemos pasarán por un solo canal entre dos nodos, entonces pasar un mensaje muy grande puede generar un bloqueo para otros mensajes consecuentes en este canal y crear un cuello de botella. Además Erlang/Elixir tienen un mecanismo para saber que los nodos están aún vivos que se lo conoce como heartbeat, y funciona de manera en el que los nodos conectados mandan mensajes cortos entre sí para avisar que aún están vivos y levantados y pueden hablar entre sí llamados beats. Estos mensajes se pasan por el mismo canal que los mensajes comunes entonces bloquear el canal con un mensaje muy grande puede generar que se bloquee el mensaje de beat y luego de pasado un tiempo que se rompa el vínculo entre los nodos.")])]),o("li",[o("p",[e._v("La red es segura. Acá no hay mucho que explicar, sabemos que la red es bastante insegura hoy por hoy. En general las aplicaciones se arman en clusters en una red local, y en general hacerlo en nodos en diferentes lugares físicos no está recomendado, de tener que hacerlo, debería implementar algún mecanismo que no viene por default en Erlang/Elixir, mediante ssl, o implementar el protocolo de comunicación entre los nodos. Hay algunos links que después pasaremos de esto.")])]),o("li",[o("p",[e._v("La Topología no cambia. Uno puede diseñar una aplicación distribuida en una LAN o intranet con una cantidad de máquinas con IP fija y una red pre-establecida, pero la realidad es que.. el hardware cambia con el tiempo, se hacen migraciones de red, o se cambia como era la topología de la LAN o inranet. Entonces sucede que no se puede hardcodear la ip de las máquinas al interconectarlas, para eso, Erlang identifica mendiante username a los nodos, hay un mecanismo que no veremos pero que existe llamado cookies que permite que se pueda identificar a un nodo con un username, no hay que confundirlo con las cookies de http pero son algo similares, aunque nunca deben considerarse un mecanismo de seguridad.")])]),o("li",[o("p",[e._v("Solo hay un administrador. Esto se cae muy rápido en los caso que tengamos una gran cantidad de servidores o incluso cuando nuestro sistema empieza a escalar, como vimos para volver a levantar procesos en Erlang es dentro de todo bastante simple aunque debe hacerse por medio de un administrador o persona si el nodo se cae definitivamente.")])]),o("li",[o("p",[e._v("El costo de transporte es cero. Lease esto como costo de transporte de datos de un nodo a otro en términos de tiempos y/o dinero. Serializar los datos no es gratis o rápido a veces, y la red posee una latencia también como mencionamos que acarrea un costo. En cuanto a costo monetario, siempre hay costo de mantenimiento de la red, servicio de ISP, hardware, personal.")])]),o("li",[o("p",[e._v("La red es homogenea. Esto último se refiere a que siempre usamos los mismos formatos para operar todo junto. Esto se refiere a que siempre se usa un mismo estándar y no siempre es así, se usan distintos lenguajes y estándares (XML, JSON, no no vamos a compararlos aca), pero en Erlang se tiene en cuenta que siempre nos vamos a comunicar y hablar con nodos y nuestro sistema está en el mismo lenguaje y que hablan el mismo protocolo. Entonces volvemos a un concepto como duck typing, en la que si tenemos un nodo que está implementado en otro lenguaje pero usa el mismo protocolo que erlang, entonces podrá hablar con otros nodos, un caso es cnode. Otra manera de intercambiar información es mediante BERT-RPC, cualquier otro sistema que use esta implementación podrá pasar información a un nodo erlang/elixir.")])])])])}],r=o("2877"),i={},t=Object(r["a"])(i,n,s,!1,null,null,null);a["default"]=t.exports}}]); +//# sourceMappingURL=chunk-2d0c0352.17d5a176.js.map \ No newline at end of file diff --git a/js/chunk-2d0c0352.17d5a176.js.map b/js/chunk-2d0c0352.17d5a176.js.map new file mode 100644 index 0000000..43ad855 --- /dev/null +++ b/js/chunk-2d0c0352.17d5a176.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/content/mitos.md?cbaa","webpack:///./src/content/mitos.md"],"names":["render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","script","component"],"mappings":"uHAAA,IAAIA,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAsBH,EAAII,MAAMC,GAAO,OAAOL,EAAIM,GAAG,IACnGC,EAAkB,CAAC,WAAa,IAAIP,EAAIC,KAASC,EAAGF,EAAIG,eAAmBE,EAAGL,EAAII,MAAMC,IAAIH,EAAG,OAAOG,EAAG,UAAU,CAACA,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,mCAAmC,CAACR,EAAIS,GAAG,oCAAoCJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,oCAAoC,CAACR,EAAIS,GAAG,SAASJ,EAAG,IAAI,CAACL,EAAIS,GAAG,yMAAyMJ,EAAG,KAAK,CAACA,EAAG,KAAK,CAACA,EAAG,IAAI,CAACL,EAAIS,GAAG,kuBAAkuBJ,EAAG,KAAK,CAACA,EAAG,IAAI,CAACL,EAAIS,GAAG,ggBAAggBJ,EAAG,KAAK,CAACA,EAAG,IAAI,CAACL,EAAIS,GAAG,8iCAA8iCJ,EAAG,KAAK,CAACA,EAAG,IAAI,CAACL,EAAIS,GAAG,ieAAieJ,EAAG,KAAK,CAACA,EAAG,IAAI,CAACL,EAAIS,GAAG,2sBAA2sBJ,EAAG,KAAK,CAACA,EAAG,IAAI,CAACL,EAAIS,GAAG,4VAA4VJ,EAAG,KAAK,CAACA,EAAG,IAAI,CAACL,EAAIS,GAAG,wXAAwXJ,EAAG,KAAK,CAACA,EAAG,IAAI,CAACL,EAAIS,GAAG,wzB,YCAh3JE,EAAS,GAKTC,EAAY,eACdD,EACAZ,EACAQ,GACA,EACA,KACA,KACA,MAIa,aAAAK,E","file":"js/chunk-2d0c0352.17d5a176.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h2',{attrs:{\"id\":\"bonus-mitos-de-la-distribución\"}},[_vm._v(\"Bonus: Mitos de la distribución \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#bonus-mitos-de-la-distribución\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Durante muchos tiempo, existieron 8 leyes o enunciados principales que son falacias y que son difíciles de manejar y la gente de erlang tomó algunas decisiones cuando se diseñó el lenguaje en sí.\")]),_c('ul',[_c('li',[_c('p',[_vm._v(\"La red es confiable: Esta es la primera falacia que hay en la computación distribuida, pueden existir fallos de red bastante más frecuente de lo que uno cree, más acá que en otros lados incluso por muchas razones (cortes de luz, falla de hardware, cable roto, etc). Entonces ya de por si no es verdadero que uno puede interconectar dos nodos en una red y siempre esperar que uno desde un nodo se puede conectar y hablar normalmente con otro nodo. Erlang en si no tiene un mecanismo especial para eso, lo mejor que nos provee es que haya una comunicación asincrónica en la que se manden mensajes asincrónicamente y después de un timeout se reintente o falle, entonces si un nodo se cae, lo manejaremos como si fuese un fallo local.\")])]),_c('li',[_c('p',[_vm._v(\"No hay latencia: Esta es otra falacia ya que de por sí a menos que estén todos los nodos en una sola máquina, siempre existe la conocida latencia de red, e incluso si los nodos estuviesen localmente existe una pequeña latencia. Erlang de la manera en la que es, teniendo nodos como procesos aislados e independientes, mensajes asincrónicos, timeouts, monitores, nos permite ir manejando y viendo cómo ir tratando de manejar la latencia entre los distintos nodos e ir ajustando esto dependiendo de la red.\")])]),_c('li',[_c('p',[_vm._v(\"El ancho de banda es infinito: Si bien el ancho de banda es mucho mayor que hace unos años, no hay que ir pasando exceso de información o gran cantidad de información entre dos nodos, siempre hay que tener en consideración que una comunicación entre dos nodos pasa en general mediante una conexión de TCP y solo una. Entonces todos los mensajes que mandemos pasarán por un solo canal entre dos nodos, entonces pasar un mensaje muy grande puede generar un bloqueo para otros mensajes consecuentes en este canal y crear un cuello de botella. Además Erlang/Elixir tienen un mecanismo para saber que los nodos están aún vivos que se lo conoce como heartbeat, y funciona de manera en el que los nodos conectados mandan mensajes cortos entre sí para avisar que aún están vivos y levantados y pueden hablar entre sí llamados beats. Estos mensajes se pasan por el mismo canal que los mensajes comunes entonces bloquear el canal con un mensaje muy grande puede generar que se bloquee el mensaje de beat y luego de pasado un tiempo que se rompa el vínculo entre los nodos.\")])]),_c('li',[_c('p',[_vm._v(\"La red es segura. Acá no hay mucho que explicar, sabemos que la red es bastante insegura hoy por hoy. En general las aplicaciones se arman en clusters en una red local, y en general hacerlo en nodos en diferentes lugares físicos no está recomendado, de tener que hacerlo, debería implementar algún mecanismo que no viene por default en Erlang/Elixir, mediante ssl, o implementar el protocolo de comunicación entre los nodos. Hay algunos links que después pasaremos de esto.\")])]),_c('li',[_c('p',[_vm._v(\"La Topología no cambia. Uno puede diseñar una aplicación distribuida en una LAN o intranet con una cantidad de máquinas con IP fija y una red pre-establecida, pero la realidad es que.. el hardware cambia con el tiempo, se hacen migraciones de red, o se cambia como era la topología de la LAN o inranet. Entonces sucede que no se puede hardcodear la ip de las máquinas al interconectarlas, para eso, Erlang identifica mendiante username a los nodos, hay un mecanismo que no veremos pero que existe llamado cookies que permite que se pueda identificar a un nodo con un username, no hay que confundirlo con las cookies de http pero son algo similares, aunque nunca deben considerarse un mecanismo de seguridad.\")])]),_c('li',[_c('p',[_vm._v(\"Solo hay un administrador. Esto se cae muy rápido en los caso que tengamos una gran cantidad de servidores o incluso cuando nuestro sistema empieza a escalar, como vimos para volver a levantar procesos en Erlang es dentro de todo bastante simple aunque debe hacerse por medio de un administrador o persona si el nodo se cae definitivamente.\")])]),_c('li',[_c('p',[_vm._v(\"El costo de transporte es cero. Lease esto como costo de transporte de datos de un nodo a otro en términos de tiempos y/o dinero. Serializar los datos no es gratis o rápido a veces, y la red posee una latencia también como mencionamos que acarrea un costo. En cuanto a costo monetario, siempre hay costo de mantenimiento de la red, servicio de ISP, hardware, personal.\")])]),_c('li',[_c('p',[_vm._v(\"La red es homogenea. Esto último se refiere a que siempre usamos los mismos formatos para operar todo junto. Esto se refiere a que siempre se usa un mismo estándar y no siempre es así, se usan distintos lenguajes y estándares (XML, JSON, no no vamos a compararlos aca), pero en Erlang se tiene en cuenta que siempre nos vamos a comunicar y hablar con nodos y nuestro sistema está en el mismo lenguaje y que hablan el mismo protocolo. Entonces volvemos a un concepto como duck typing, en la que si tenemos un nodo que está implementado en otro lenguaje pero usa el mismo protocolo que erlang, entonces podrá hablar con otros nodos, un caso es cnode. Otra manera de intercambiar información es mediante BERT-RPC, cualquier otro sistema que use esta implementación podrá pasar información a un nodo erlang/elixir.\")])])])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./mitos.md?vue&type=template&id=29ed7f28&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-2d0f0fc6.433c258f.js b/js/chunk-2d0f0fc6.433c258f.js new file mode 100644 index 0000000..ab9c7d9 --- /dev/null +++ b/js/chunk-2d0f0fc6.433c258f.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0f0fc6"],{"9f69":function(n,t,e){"use strict";e.r(t);var c=function(){var n=this,t=n.$createElement,e=n._self._c||t;return e("div",[e("div",{staticClass:"container"},[e("div",{staticClass:"inner-content col-sm-8 col-md-10"},[e("router-view")],1)])])},o=[],s={name:"AppLayoutError",components:{}},r=s,a=e("2877"),i=Object(a["a"])(r,c,o,!1,null,"07264d80",null);t["default"]=i.exports}}]); +//# sourceMappingURL=chunk-2d0f0fc6.433c258f.js.map \ No newline at end of file diff --git a/js/chunk-2d0f0fc6.433c258f.js.map b/js/chunk-2d0f0fc6.433c258f.js.map new file mode 100644 index 0000000..32e5e83 --- /dev/null +++ b/js/chunk-2d0f0fc6.433c258f.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/layouts/AppLayoutError.vue?bf12","webpack:///src/layouts/AppLayoutError.vue","webpack:///./src/layouts/AppLayoutError.vue?44da","webpack:///./src/layouts/AppLayoutError.vue"],"names":["render","_vm","this","_h","$createElement","_c","_self","staticClass","staticRenderFns","name","components","component"],"mappings":"yHAAA,IAAIA,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACA,EAAG,MAAM,CAACE,YAAY,aAAa,CAACF,EAAG,MAAM,CAACE,YAAY,oCAAoC,CAACF,EAAG,gBAAgB,QACxNG,EAAkB,GCUtB,GACEC,KAAM,iBACNC,WAAY,ICb0U,I,YCOpVC,EAAY,eACd,EACAX,EACAQ,GACA,EACA,KACA,WACA,MAIa,aAAAG,E","file":"js/chunk-2d0f0fc6.433c258f.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('div',{staticClass:\"container\"},[_c('div',{staticClass:\"inner-content col-sm-8 col-md-10\"},[_c('router-view')],1)])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AppLayoutError.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AppLayoutError.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./AppLayoutError.vue?vue&type=template&id=07264d80&scoped=true&\"\nimport script from \"./AppLayoutError.vue?vue&type=script&lang=js&\"\nexport * from \"./AppLayoutError.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"07264d80\",\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-2d2102a5.978b3591.js b/js/chunk-2d2102a5.978b3591.js new file mode 100644 index 0000000..f573467 --- /dev/null +++ b/js/chunk-2d2102a5.978b3591.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d2102a5"],{b771:function(e,s,a){"use strict";a.r(s);var r=function(){var e=this,s=e.$createElement;e._self._c;return e._m(0)},n=[function(){var e=this,s=e.$createElement,a=e._self._c||s;return a("section",[a("h2",{attrs:{id:"introduccion"}},[e._v("Introduccion "),a("a",{staticClass:"header-anchor",attrs:{href:"#introduccion"}},[e._v("¶")])]),a("p",[e._v("En "),a("a",{attrs:{href:"https://arquitecturas-concurrentes.github.io/iasc-book/cps/"}},[e._v("capítulos anteriores")]),e._v(" vimos una posible forma de estructurar nuestros programas, utilizando CPS. Esta técnica, a diferencia de call-and-return y memoria compartida, nos permite implementar, de forma fácil:")]),a("ul",[a("li",[e._v("computaciones con un único resultado")]),a("li",[e._v("computaciones que pueden fallar")]),a("li",[e._v("computaciones no determinísticas")]),a("li",[e._v("excepciones")]),a("li",[e._v("asincronismo")])]),a("p",[e._v("Bueno, quizás no tan fácilmente. Vimos que si no tenemos cuidado y no delegamos "),a("em",[e._v("apropiadamente")]),e._v(", es muy posible que caigamos en el callback-hell: continuaciones anidadas dentro de continuaciones. Para ser justos, esto no es un problema de CPS propiamente dicho sino de la subutilización de una de las herramientas más poderosas del paradigma funcional: el orden superior.")]),a("p",[e._v("De todas formas, lo admitimos, para el programador inexperto en estos territorios, razonar sobre abstracciones que combinan funciones, como "),a("em",[e._v("compose")]),e._v("’s o "),a("em",[e._v("pipeline")]),e._v("’s no es simple: las funciones no son valores obvios.")]),a("p",[e._v("A su vez, la secuenciación de continuaciones es un problema aún mayor cuando estamos trabajando con operaciones que pueden fallar, ya que la cantidad de flujos de ejecución posibles aumenta, haciendo que sea muy fácil perder algún potencial error.")]),a("p",[e._v("Pero si "),a("strong",[e._v("secuenciar")]),e._v(" operaciones no es trivial, trabajar con operaciones "),a("strong",[e._v("concurrentes")]),e._v(" es todavía más difícil. Por ejemplo, si tenemos un cliente HTTP que usa continuaciones, y queremos agrupar en una lista las respuestas de varios requests, no nos queda otra opción que alejarnos del enfoque más "),a("em",[e._v("purista")]),e._v(" de CPS e introducir estado mutable que va a ser modificado por las distintas continuaciones:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("const")]),e._v(" pokemonIniciales = [];\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("const")]),e._v(" pokemonObtenido = "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(" =>")]),e._v(" {\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("if")]),e._v("(pokemonIniciales.length < "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("3")]),e._v(") {\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("return")]),e._v(";\n }\n elegirInicial(pokemonIniciales);\n};\nrequest("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'https://pokeapi.co/api/v2/pokemon/1'")]),e._v(", (response) => {\n pokemonIniciales.push(response.body());\n pokemonObtenido();\n});\nrequest("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'https://pokeapi.co/api/v2/pokemon/4'")]),e._v(", (response) => {\n pokemonIniciales.push(response.body());\n pokemonObtenido();\n});\nrequest("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'https://pokeapi.co/api/v2/pokemon/7'")]),e._v(", (response) => {\n pokemonIniciales.push(response.body());\n pokemonObtenido();\n});\n")])]),a("p",[e._v("Motivada por estas problemáticas surge otra forma de estructurar programas concurrentes: las promesas ("),a("em",[e._v("futures")]),e._v(" o "),a("em",[e._v("promises")]),e._v(", en inglés). Se trata de una técnica que de nueva no tiene nada (data de fines de los ‘70), pero que se ha popularizado y gracias a implementaciones en lenguajes como Scala o JavaScript.")]),a("p",[e._v("Veamos qué tienen para ofrecernos.")]),a("h2",{attrs:{id:"reificando-los-resultados-de-nuestras-operaciones"}},[e._v("Reificando los resultados de nuestras operaciones "),a("a",{staticClass:"header-anchor",attrs:{href:"#reificando-los-resultados-de-nuestras-operaciones"}},[e._v("¶")])]),a("p",[e._v("Para empezar, volvamos a nuestro clásico ejemplo: la función "),a("code",{pre:!0},[e._v("successor")]),e._v(", en su variante CPS:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("successor")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("x, callback")]),e._v(") ")]),e._v("{\n callback(x + "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(");\n}\n")])]),a("p",[e._v("Que podemos usar de la siguiente forma:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[e._v("successor("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("4")]),e._v(", (resultado) => "),a("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("console")]),e._v(".log(resultado));\n")])]),a("p",[e._v("Para pasar de nuestro mundo de continuaciones al de "),a("em",[e._v("promesas")]),e._v(", vamos a hacer lo siguente:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("successor")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("x")]),e._v(") ")]),e._v("{\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("return")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("new")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("Promise")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("resolve")]),e._v(") =>")]),e._v(" {\n resolve(x+"),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(");\n });\n}\n")])]),a("p",[e._v("¿Qué cambió? Ahora nuestra función "),a("code",{pre:!0},[e._v("successor")]),e._v(" retorna un valor, pero éste no es el valor del resultado que buscamos, sino que tenemos que interactuar con una "),a("code",{pre:!0},[e._v("Promise")]),e._v(" para obtenerlo.")]),a("p",[e._v("La forma de hacerlo va a ser a través de uno de los mensajes que entienden las promesas: "),a("code",{pre:!0},[e._v("then")]),e._v(", que nos permite encadenar operaciones que se van a llevar a cabo una vez que el resultado de la promesa esté disponible.")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[e._v("successor("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("4")]),e._v(").then("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("resultado")]),e._v(") =>")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("console")]),e._v(".log(resultado));\n")])]),a("blockquote",[a("p",[e._v('"Una vez que el resultado de la promesa esté disponible" dijiste?')])]),a("p",[e._v("Claro, porque las promesas se usan en general para representar el resultado de operaciones asincrónicas:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[e._v("promesaConTimeout = "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("new")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("Promise")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("resolve")]),e._v(") =>")]),e._v(" {\n setTimeout("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(" =>")]),e._v(" resolve("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v('"Vengo del pasado"')]),e._v("), "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("5")]),e._v("_000);\n});\npromesaConTimeout.then("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("mensaje")]),e._v(") =>")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("console")]),e._v(".log(mensaje));\n")])]),a("p",[e._v("Si inspeccionamos esa promesa en el momento en que la creamos, vamos a ver que se encuentra en estado "),a("strong",[e._v("pendiente")]),e._v(", ya que todavía no se ha completado. Sin embargo, si esperamos 5 segundos, veremos el mensaje en la consola, y al inspeccionar la promesa veremos que se encuentra "),a("strong",[e._v("resuelta")]),e._v(".")]),a("p",[e._v("Vemos entonces que las promesas son objetos con estado, y que éste puede variar con el tiempo, pasando de estar pendiente a resuelta.")]),a("h2",{attrs:{id:"manejando-los-errores"}},[e._v("Manejando los errores "),a("a",{staticClass:"header-anchor",attrs:{href:"#manejando-los-errores"}},[e._v("¶")])]),a("p",[e._v("Las promesas nos permiten no solo representar resultados exitosos, sino también casos de error:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("inverse")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("x")]),e._v(") ")]),e._v("{\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("return")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("new")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("Promise")]),e._v(" ("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("resolve, reject")]),e._v(") =>")]),e._v(" {\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("if")]),e._v(" (x === "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v(") {\n reject("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v('"No existe la inversa de 0"')]),e._v(")\n } "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("else")]),e._v(" {\n resolve("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(" / x);\n }\n });\n}\n")])]),a("p",[e._v("Si invocamos esta función con "),a("code",{pre:!0},[e._v("0")]),e._v(" como parámetro, vemos que la promesa resultante está "),a("strong",[e._v("rechazada")]),e._v(", y que tiene valor de error.")]),a("p",[e._v("Esto nos permite manejar "),a("em",[e._v("excepciones")]),e._v(", usando otro mensaje que entienden las promesas, "),a("code",{pre:!0},[e._v("catch")]),e._v(":")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("printInverse")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("x")]),e._v(") ")]),e._v("{\n inverse(x).then("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("result")]),e._v(" =>")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("console")]),e._v(".log(result))\n .catch("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("error")]),e._v(" =>")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("console")]),e._v(".error(error));\n}\n")])]),a("p",[e._v('Algo destacable del manejo de excepciones, es que las excepciones "cascadean" hasta el primer '),a("code",{pre:!0},[e._v("catch")]),e._v(" que puede manejarlas. Esto constituye una diferencia respecto a CPS, donde siempre tenemos que pasar los callback de error explícitamente.")]),a("p",[e._v("Otra diferencia entre CPS y promesas que podemos observar es que las promesas siempre se resuelven o se rechazan. No nos permiten no tener un resultado ("),a("em",[e._v("fallar")]),e._v("), ni tampoco tener múltiples resultados ("),a("em",[e._v("no determinismo")]),e._v(").")]),a("h2",{attrs:{id:"encadenando-promesas"}},[e._v("Encadenando promesas "),a("a",{staticClass:"header-anchor",attrs:{href:"#encadenando-promesas"}},[e._v("¶")])]),a("p",[e._v("Como ya vimos, podemos usar "),a("code",{pre:!0},[e._v("then")]),e._v(" para agregar un callback que se ejecutará cuando la promesa se resuelva. Lo interesante es que "),a("code",{pre:!0},[e._v("then")]),e._v(" nos devuelve "),a("strong",[e._v("una nueva promesa")]),e._v(", por lo que podemos seguir encadenando operaciones:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[e._v("promesaConTimeout\n .then("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("mensaje")]),e._v(") =>")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'¡'")]),e._v(" + mensaje + "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'!'")]),e._v(")\n .then("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("mensajeConEnfasis")]),e._v(") =>")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("console")]),e._v(".log(mensajeConEnfasis));\n")])]),a("p",[e._v("Además, si la función que le pasamos al "),a("code",{pre:!0},[e._v("then")]),e._v(" devuelve una promesa, nos garantiza que dicha promesa se va a resolver antes que la que devuelve el "),a("code",{pre:!0},[e._v("then")]),e._v(" mismo. Esto evita tener un "),a("em",[e._v("promise-hell")]),e._v(" (patente pendiente) de promesas anidadas.")]),a("p",[e._v("Veamos un ejemplo de esto último. Si usamos la función "),a("code",{pre:!0},[e._v("fetch")]),e._v(" que existe en el browser para hacer requests HTTP, obtenemos una promesa que eventualmente se resolverá con la respuesta al request. Ahora bien, si queremos parsear esa respuesta como JSON, vamos a tener que enviar el mensaje "),a("code",{pre:!0},[e._v("json()")]),e._v(" a la respuesta, que también nos devuelve una promesa. Usando "),a("code",{pre:!0},[e._v("then")]),e._v(" podemos secuenciar estas operaciones asincrónicas, de forma tal que, al final, sólo tengamos una promesa con el objeto parseado:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[e._v("fetch("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'https://pokeapi.co/api/v2/pokemon/1'")]),e._v(")\n .then("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("response")]),e._v(" =>")]),e._v(" response.json())\n .then("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("pokemon")]),e._v(" =>")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("console")]),e._v(".log("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("`Encontre a: "),a("span",{pre:!0,attrs:{class:"hljs-subst"}},[e._v("${pokemon.name}")]),e._v("`")]),e._v("));\n")])]),a("h2",{attrs:{id:"otras-formas-de-componer-promesas"}},[e._v("Otras formas de componer promesas "),a("a",{staticClass:"header-anchor",attrs:{href:"#otras-formas-de-componer-promesas"}},[e._v("¶")])]),a("p",[e._v('Además de componer operaciones asincrónicas "en serie", muchas veces queremos hacerlo "en paralelo" (o, siendo más precisos, concurrentemente). Al principio vimos que hacer esto con callbacks nos llevaba por un camino bastante oscuro.')]),a("p",[e._v("¿Cómo se logra lo mismo usando promesas?")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("const")]),e._v(" fetchJSON = "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("requestUrl")]),e._v(") =>")]),e._v(" fetch(requestUrl).then("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("response")]),e._v(" =>")]),e._v(" response.json());\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("const")]),e._v(" respuestas = ["),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(", "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("4")]),e._v(", "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("7")]),e._v("].map("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("nroPokedex")]),e._v(" =>")]),e._v(" fetchJSON("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'https://pokeapi.co/api/v2/pokemon/'")]),e._v(" + nroPokedex));\n"),a("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("Promise")]),e._v(".all(respuestas)\n .then("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("iniciales")]),e._v(" =>")]),e._v(" elegirInicial(iniciales));\n")])]),a("p",[e._v("Con "),a("code",{pre:!0},[e._v("Promise.all")]),e._v(" podemos agregar los resultados de múltiples promesas, para después operar todos los resultados de forma conjunta, y de una forma mucho más declarativa que cuando usábamos CPS.")]),a("p",[a("code",{pre:!0},[e._v("Promise.all")]),e._v(" no es la única forma que tenemos de combinar promesas. Durante la cursada vamos a ver otras, aunque si tienen curiosidad, pueden buscar "),a("code",{pre:!0},[e._v("Promise.race()")]),e._v(", "),a("code",{pre:!0},[e._v("Promise.any()")]),e._v(" y "),a("code",{pre:!0},[e._v("Promise.allSettled()")]),e._v(".")]),a("h2",{attrs:{id:"volviendo-la-vista-atrás"}},[e._v("Volviendo la vista atrás "),a("a",{staticClass:"header-anchor",attrs:{href:"#volviendo-la-vista-atrás"}},[e._v("¶")])]),a("p",[e._v("Después de haber hecho un recorrido por las funcionalidades principales que nos ofrecen las promesas, cabe preguntarnos: ¿qué cambió con el uso de promesas, respecto al uso de CPS?")]),a("p",[e._v('Primero que nada, es importante entender que no estamos agregando nada "mágico", ni ningún concepto de manejo de concurrencia novedoso. Las promesas se paran sobre el uso de continuaciones de toda la vida, sólo que agregando una capa de abstracción por encima que, por un lado, facilita ciertas cosas, pero que también impide otras.')]),a("p",[e._v("La diferencia fundamental está en quién tiene el control de "),a("em",[e._v("la próxima acción a ejecutar")]),e._v(". Con CPS, una vez que pasábamos un callback por parámetro a una función, perdíamos todo control sobre el flujo de ejecución, que pasaba a ser responsabilidad de esa función. Con las promesas, seguimos teniendo una referencia del lado del invocador, y esto puede ser de gran ayuda al momento de agregar nuevas operaciones que dependen de la primera que hicimos.")]),a("p",[e._v("Acá entran las distintas formas de componer promesas que vimos, que son posibles justamente gracias a haber reificado el resultado de la ejecución.")]),a("p",[e._v("Ahora bien, las promesas no vienen a reemplazar el uso de callbacks, o al menos no en su totalidad. Como vimos, hay categorías enteras de situaciones (falla, no determinismo) que no se pueden manejar mediante el uso promesas. Esto en una primer momento podría parecer una desventaja, pero la realidad es que, al enfocarse en un escenario concreto en particular (el manejo de operaciones asincrónicas que producen un sólo resultado), las promesas pueden ofrecer una interfaz a la vez sencilla y poderosa para ese caso de uso.")]),a("p",[e._v("De hecho, enfoques como la "),a("strong",[e._v("programación reactiva")]),e._v(" extienden los principios de las promesas (y agregan unos cuantos otros), permitiendo manejar tanto casos de falla como no determinismo. Pero al hacerlo también terminan con una interfaz mucho más compleja que la de las promesas.")]),a("h2",{attrs:{id:"recursos-recomendados"}},[e._v("Recursos recomendados "),a("a",{staticClass:"header-anchor",attrs:{href:"#recursos-recomendados"}},[e._v("¶")])]),a("ul",[a("li",[a("a",{attrs:{href:"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises"}},[e._v("Guía sobre uso de Promesas")])]),a("li",[a("a",{attrs:{href:"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"}},[e._v("Documentación más en detalle sobre su interfaz")])]),a("li",[a("a",{attrs:{href:"https://gist.github.com/staltz/868e7e9bc2a7b8c1f754"}},[e._v("Bonus - Introducción a Programación Reactiva")])])])])}],o=a("2877"),t={},p=Object(o["a"])(t,r,n,!1,null,null,null);s["default"]=p.exports}}]); +//# sourceMappingURL=chunk-2d2102a5.978b3591.js.map \ No newline at end of file diff --git a/js/chunk-2d2102a5.978b3591.js.map b/js/chunk-2d2102a5.978b3591.js.map new file mode 100644 index 0000000..99ffce9 --- /dev/null +++ b/js/chunk-2d2102a5.978b3591.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/content/promises.md?3535","webpack:///./src/content/promises.md"],"names":["render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","pre","script","component"],"mappings":"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","file":"js/chunk-2d2102a5.978b3591.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h2',{attrs:{\"id\":\"introduccion\"}},[_vm._v(\"Introduccion \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#introduccion\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"En \"),_c('a',{attrs:{\"href\":\"https://arquitecturas-concurrentes.github.io/iasc-book/cps/\"}},[_vm._v(\"capítulos anteriores\")]),_vm._v(\" vimos una posible forma de estructurar nuestros programas, utilizando CPS. Esta técnica, a diferencia de call-and-return y memoria compartida, nos permite implementar, de forma fácil:\")]),_c('ul',[_c('li',[_vm._v(\"computaciones con un único resultado\")]),_c('li',[_vm._v(\"computaciones que pueden fallar\")]),_c('li',[_vm._v(\"computaciones no determinísticas\")]),_c('li',[_vm._v(\"excepciones\")]),_c('li',[_vm._v(\"asincronismo\")])]),_c('p',[_vm._v(\"Bueno, quizás no tan fácilmente. Vimos que si no tenemos cuidado y no delegamos \"),_c('em',[_vm._v(\"apropiadamente\")]),_vm._v(\", es muy posible que caigamos en el callback-hell: continuaciones anidadas dentro de continuaciones. Para ser justos, esto no es un problema de CPS propiamente dicho sino de la subutilización de una de las herramientas más poderosas del paradigma funcional: el orden superior.\")]),_c('p',[_vm._v(\"De todas formas, lo admitimos, para el programador inexperto en estos territorios, razonar sobre abstracciones que combinan funciones, como \"),_c('em',[_vm._v(\"compose\")]),_vm._v(\"’s o \"),_c('em',[_vm._v(\"pipeline\")]),_vm._v(\"’s no es simple: las funciones no son valores obvios.\")]),_c('p',[_vm._v(\"A su vez, la secuenciación de continuaciones es un problema aún mayor cuando estamos trabajando con operaciones que pueden fallar, ya que la cantidad de flujos de ejecución posibles aumenta, haciendo que sea muy fácil perder algún potencial error.\")]),_c('p',[_vm._v(\"Pero si \"),_c('strong',[_vm._v(\"secuenciar\")]),_vm._v(\" operaciones no es trivial, trabajar con operaciones \"),_c('strong',[_vm._v(\"concurrentes\")]),_vm._v(\" es todavía más difícil. Por ejemplo, si tenemos un cliente HTTP que usa continuaciones, y queremos agrupar en una lista las respuestas de varios requests, no nos queda otra opción que alejarnos del enfoque más \"),_c('em',[_vm._v(\"purista\")]),_vm._v(\" de CPS e introducir estado mutable que va a ser modificado por las distintas continuaciones:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"const\")]),_vm._v(\" pokemonIniciales = [];\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"const\")]),_vm._v(\" pokemonObtenido = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\" =>\")]),_vm._v(\" {\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"if\")]),_vm._v(\"(pokemonIniciales.length < \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"3\")]),_vm._v(\") {\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"return\")]),_vm._v(\";\\n }\\n elegirInicial(pokemonIniciales);\\n};\\nrequest(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'https://pokeapi.co/api/v2/pokemon/1'\")]),_vm._v(\", (response) => {\\n pokemonIniciales.push(response.body());\\n pokemonObtenido();\\n});\\nrequest(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'https://pokeapi.co/api/v2/pokemon/4'\")]),_vm._v(\", (response) => {\\n pokemonIniciales.push(response.body());\\n pokemonObtenido();\\n});\\nrequest(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'https://pokeapi.co/api/v2/pokemon/7'\")]),_vm._v(\", (response) => {\\n pokemonIniciales.push(response.body());\\n pokemonObtenido();\\n});\\n\")])]),_c('p',[_vm._v(\"Motivada por estas problemáticas surge otra forma de estructurar programas concurrentes: las promesas (\"),_c('em',[_vm._v(\"futures\")]),_vm._v(\" o \"),_c('em',[_vm._v(\"promises\")]),_vm._v(\", en inglés). Se trata de una técnica que de nueva no tiene nada (data de fines de los ‘70), pero que se ha popularizado y gracias a implementaciones en lenguajes como Scala o JavaScript.\")]),_c('p',[_vm._v(\"Veamos qué tienen para ofrecernos.\")]),_c('h2',{attrs:{\"id\":\"reificando-los-resultados-de-nuestras-operaciones\"}},[_vm._v(\"Reificando los resultados de nuestras operaciones \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#reificando-los-resultados-de-nuestras-operaciones\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Para empezar, volvamos a nuestro clásico ejemplo: la función \"),_c('code',{pre:true},[_vm._v(\"successor\")]),_vm._v(\", en su variante CPS:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"successor\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"x, callback\")]),_vm._v(\") \")]),_vm._v(\"{\\n callback(x + \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\");\\n}\\n\")])]),_c('p',[_vm._v(\"Que podemos usar de la siguiente forma:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_vm._v(\"successor(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"4\")]),_vm._v(\", (resultado) => \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"console\")]),_vm._v(\".log(resultado));\\n\")])]),_c('p',[_vm._v(\"Para pasar de nuestro mundo de continuaciones al de \"),_c('em',[_vm._v(\"promesas\")]),_vm._v(\", vamos a hacer lo siguente:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"successor\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"x\")]),_vm._v(\") \")]),_vm._v(\"{\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"return\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"new\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"Promise\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"resolve\")]),_vm._v(\") =>\")]),_vm._v(\" {\\n resolve(x+\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\");\\n });\\n}\\n\")])]),_c('p',[_vm._v(\"¿Qué cambió? Ahora nuestra función \"),_c('code',{pre:true},[_vm._v(\"successor\")]),_vm._v(\" retorna un valor, pero éste no es el valor del resultado que buscamos, sino que tenemos que interactuar con una \"),_c('code',{pre:true},[_vm._v(\"Promise\")]),_vm._v(\" para obtenerlo.\")]),_c('p',[_vm._v(\"La forma de hacerlo va a ser a través de uno de los mensajes que entienden las promesas: \"),_c('code',{pre:true},[_vm._v(\"then\")]),_vm._v(\", que nos permite encadenar operaciones que se van a llevar a cabo una vez que el resultado de la promesa esté disponible.\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_vm._v(\"successor(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"4\")]),_vm._v(\").then(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"resultado\")]),_vm._v(\") =>\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"console\")]),_vm._v(\".log(resultado));\\n\")])]),_c('blockquote',[_c('p',[_vm._v(\"\\\"Una vez que el resultado de la promesa esté disponible\\\" dijiste?\")])]),_c('p',[_vm._v(\"Claro, porque las promesas se usan en general para representar el resultado de operaciones asincrónicas:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_vm._v(\"promesaConTimeout = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"new\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"Promise\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"resolve\")]),_vm._v(\") =>\")]),_vm._v(\" {\\n setTimeout(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\" =>\")]),_vm._v(\" resolve(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"\\\"Vengo del pasado\\\"\")]),_vm._v(\"), \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"5\")]),_vm._v(\"_000);\\n});\\npromesaConTimeout.then(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"mensaje\")]),_vm._v(\") =>\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"console\")]),_vm._v(\".log(mensaje));\\n\")])]),_c('p',[_vm._v(\"Si inspeccionamos esa promesa en el momento en que la creamos, vamos a ver que se encuentra en estado \"),_c('strong',[_vm._v(\"pendiente\")]),_vm._v(\", ya que todavía no se ha completado. Sin embargo, si esperamos 5 segundos, veremos el mensaje en la consola, y al inspeccionar la promesa veremos que se encuentra \"),_c('strong',[_vm._v(\"resuelta\")]),_vm._v(\".\")]),_c('p',[_vm._v(\"Vemos entonces que las promesas son objetos con estado, y que éste puede variar con el tiempo, pasando de estar pendiente a resuelta.\")]),_c('h2',{attrs:{\"id\":\"manejando-los-errores\"}},[_vm._v(\"Manejando los errores \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#manejando-los-errores\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Las promesas nos permiten no solo representar resultados exitosos, sino también casos de error:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"inverse\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"x\")]),_vm._v(\") \")]),_vm._v(\"{\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"return\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"new\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"Promise\")]),_vm._v(\" (\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"resolve, reject\")]),_vm._v(\") =>\")]),_vm._v(\" {\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"if\")]),_vm._v(\" (x === \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\") {\\n reject(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"\\\"No existe la inversa de 0\\\"\")]),_vm._v(\")\\n } \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"else\")]),_vm._v(\" {\\n resolve(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\" / x);\\n }\\n });\\n}\\n\")])]),_c('p',[_vm._v(\"Si invocamos esta función con \"),_c('code',{pre:true},[_vm._v(\"0\")]),_vm._v(\" como parámetro, vemos que la promesa resultante está \"),_c('strong',[_vm._v(\"rechazada\")]),_vm._v(\", y que tiene valor de error.\")]),_c('p',[_vm._v(\"Esto nos permite manejar \"),_c('em',[_vm._v(\"excepciones\")]),_vm._v(\", usando otro mensaje que entienden las promesas, \"),_c('code',{pre:true},[_vm._v(\"catch\")]),_vm._v(\":\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"printInverse\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"x\")]),_vm._v(\") \")]),_vm._v(\"{\\n inverse(x).then(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"result\")]),_vm._v(\" =>\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"console\")]),_vm._v(\".log(result))\\n .catch(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"error\")]),_vm._v(\" =>\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"console\")]),_vm._v(\".error(error));\\n}\\n\")])]),_c('p',[_vm._v(\"Algo destacable del manejo de excepciones, es que las excepciones \\\"cascadean\\\" hasta el primer \"),_c('code',{pre:true},[_vm._v(\"catch\")]),_vm._v(\" que puede manejarlas. Esto constituye una diferencia respecto a CPS, donde siempre tenemos que pasar los callback de error explícitamente.\")]),_c('p',[_vm._v(\"Otra diferencia entre CPS y promesas que podemos observar es que las promesas siempre se resuelven o se rechazan. No nos permiten no tener un resultado (\"),_c('em',[_vm._v(\"fallar\")]),_vm._v(\"), ni tampoco tener múltiples resultados (\"),_c('em',[_vm._v(\"no determinismo\")]),_vm._v(\").\")]),_c('h2',{attrs:{\"id\":\"encadenando-promesas\"}},[_vm._v(\"Encadenando promesas \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#encadenando-promesas\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Como ya vimos, podemos usar \"),_c('code',{pre:true},[_vm._v(\"then\")]),_vm._v(\" para agregar un callback que se ejecutará cuando la promesa se resuelva. Lo interesante es que \"),_c('code',{pre:true},[_vm._v(\"then\")]),_vm._v(\" nos devuelve \"),_c('strong',[_vm._v(\"una nueva promesa\")]),_vm._v(\", por lo que podemos seguir encadenando operaciones:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_vm._v(\"promesaConTimeout\\n .then(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"mensaje\")]),_vm._v(\") =>\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'¡'\")]),_vm._v(\" + mensaje + \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'!'\")]),_vm._v(\")\\n .then(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"mensajeConEnfasis\")]),_vm._v(\") =>\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"console\")]),_vm._v(\".log(mensajeConEnfasis));\\n\")])]),_c('p',[_vm._v(\"Además, si la función que le pasamos al \"),_c('code',{pre:true},[_vm._v(\"then\")]),_vm._v(\" devuelve una promesa, nos garantiza que dicha promesa se va a resolver antes que la que devuelve el \"),_c('code',{pre:true},[_vm._v(\"then\")]),_vm._v(\" mismo. Esto evita tener un \"),_c('em',[_vm._v(\"promise-hell\")]),_vm._v(\" (patente pendiente) de promesas anidadas.\")]),_c('p',[_vm._v(\"Veamos un ejemplo de esto último. Si usamos la función \"),_c('code',{pre:true},[_vm._v(\"fetch\")]),_vm._v(\" que existe en el browser para hacer requests HTTP, obtenemos una promesa que eventualmente se resolverá con la respuesta al request. Ahora bien, si queremos parsear esa respuesta como JSON, vamos a tener que enviar el mensaje \"),_c('code',{pre:true},[_vm._v(\"json()\")]),_vm._v(\" a la respuesta, que también nos devuelve una promesa. Usando \"),_c('code',{pre:true},[_vm._v(\"then\")]),_vm._v(\" podemos secuenciar estas operaciones asincrónicas, de forma tal que, al final, sólo tengamos una promesa con el objeto parseado:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_vm._v(\"fetch(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'https://pokeapi.co/api/v2/pokemon/1'\")]),_vm._v(\")\\n .then(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"response\")]),_vm._v(\" =>\")]),_vm._v(\" response.json())\\n .then(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"pokemon\")]),_vm._v(\" =>\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"console\")]),_vm._v(\".log(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"`Encontre a: \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-subst\"}},[_vm._v(\"${pokemon.name}\")]),_vm._v(\"`\")]),_vm._v(\"));\\n\")])]),_c('h2',{attrs:{\"id\":\"otras-formas-de-componer-promesas\"}},[_vm._v(\"Otras formas de componer promesas \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#otras-formas-de-componer-promesas\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Además de componer operaciones asincrónicas \\\"en serie\\\", muchas veces queremos hacerlo \\\"en paralelo\\\" (o, siendo más precisos, concurrentemente). Al principio vimos que hacer esto con callbacks nos llevaba por un camino bastante oscuro.\")]),_c('p',[_vm._v(\"¿Cómo se logra lo mismo usando promesas?\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"const\")]),_vm._v(\" fetchJSON = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"requestUrl\")]),_vm._v(\") =>\")]),_vm._v(\" fetch(requestUrl).then(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"response\")]),_vm._v(\" =>\")]),_vm._v(\" response.json());\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"const\")]),_vm._v(\" respuestas = [\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"4\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"7\")]),_vm._v(\"].map(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"nroPokedex\")]),_vm._v(\" =>\")]),_vm._v(\" fetchJSON(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'https://pokeapi.co/api/v2/pokemon/'\")]),_vm._v(\" + nroPokedex));\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"Promise\")]),_vm._v(\".all(respuestas)\\n .then(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"iniciales\")]),_vm._v(\" =>\")]),_vm._v(\" elegirInicial(iniciales));\\n\")])]),_c('p',[_vm._v(\"Con \"),_c('code',{pre:true},[_vm._v(\"Promise.all\")]),_vm._v(\" podemos agregar los resultados de múltiples promesas, para después operar todos los resultados de forma conjunta, y de una forma mucho más declarativa que cuando usábamos CPS.\")]),_c('p',[_c('code',{pre:true},[_vm._v(\"Promise.all\")]),_vm._v(\" no es la única forma que tenemos de combinar promesas. Durante la cursada vamos a ver otras, aunque si tienen curiosidad, pueden buscar \"),_c('code',{pre:true},[_vm._v(\"Promise.race()\")]),_vm._v(\", \"),_c('code',{pre:true},[_vm._v(\"Promise.any()\")]),_vm._v(\" y \"),_c('code',{pre:true},[_vm._v(\"Promise.allSettled()\")]),_vm._v(\".\")]),_c('h2',{attrs:{\"id\":\"volviendo-la-vista-atrás\"}},[_vm._v(\"Volviendo la vista atrás \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#volviendo-la-vista-atrás\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Después de haber hecho un recorrido por las funcionalidades principales que nos ofrecen las promesas, cabe preguntarnos: ¿qué cambió con el uso de promesas, respecto al uso de CPS?\")]),_c('p',[_vm._v(\"Primero que nada, es importante entender que no estamos agregando nada \\\"mágico\\\", ni ningún concepto de manejo de concurrencia novedoso. Las promesas se paran sobre el uso de continuaciones de toda la vida, sólo que agregando una capa de abstracción por encima que, por un lado, facilita ciertas cosas, pero que también impide otras.\")]),_c('p',[_vm._v(\"La diferencia fundamental está en quién tiene el control de \"),_c('em',[_vm._v(\"la próxima acción a ejecutar\")]),_vm._v(\". Con CPS, una vez que pasábamos un callback por parámetro a una función, perdíamos todo control sobre el flujo de ejecución, que pasaba a ser responsabilidad de esa función. Con las promesas, seguimos teniendo una referencia del lado del invocador, y esto puede ser de gran ayuda al momento de agregar nuevas operaciones que dependen de la primera que hicimos.\")]),_c('p',[_vm._v(\"Acá entran las distintas formas de componer promesas que vimos, que son posibles justamente gracias a haber reificado el resultado de la ejecución.\")]),_c('p',[_vm._v(\"Ahora bien, las promesas no vienen a reemplazar el uso de callbacks, o al menos no en su totalidad. Como vimos, hay categorías enteras de situaciones (falla, no determinismo) que no se pueden manejar mediante el uso promesas. Esto en una primer momento podría parecer una desventaja, pero la realidad es que, al enfocarse en un escenario concreto en particular (el manejo de operaciones asincrónicas que producen un sólo resultado), las promesas pueden ofrecer una interfaz a la vez sencilla y poderosa para ese caso de uso.\")]),_c('p',[_vm._v(\"De hecho, enfoques como la \"),_c('strong',[_vm._v(\"programación reactiva\")]),_vm._v(\" extienden los principios de las promesas (y agregan unos cuantos otros), permitiendo manejar tanto casos de falla como no determinismo. Pero al hacerlo también terminan con una interfaz mucho más compleja que la de las promesas.\")]),_c('h2',{attrs:{\"id\":\"recursos-recomendados\"}},[_vm._v(\"Recursos recomendados \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#recursos-recomendados\"}},[_vm._v(\"¶\")])]),_c('ul',[_c('li',[_c('a',{attrs:{\"href\":\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises\"}},[_vm._v(\"Guía sobre uso de Promesas\")])]),_c('li',[_c('a',{attrs:{\"href\":\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\"}},[_vm._v(\"Documentación más en detalle sobre su interfaz\")])]),_c('li',[_c('a',{attrs:{\"href\":\"https://gist.github.com/staltz/868e7e9bc2a7b8c1f754\"}},[_vm._v(\"Bonus - Introducción a Programación Reactiva\")])])])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./promises.md?vue&type=template&id=3c33c690&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-2d212f5c.78f8895b.js b/js/chunk-2d212f5c.78f8895b.js new file mode 100644 index 0000000..1a5bf54 --- /dev/null +++ b/js/chunk-2d212f5c.78f8895b.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d212f5c"],{ab49:function(e,a,o){"use strict";o.r(a);var s=function(){var e=this,a=e.$createElement;e._self._c;return e._m(0)},r=[function(){var e=this,a=e.$createElement,o=e._self._c||a;return o("section",[o("h3",{attrs:{id:"introduccion"}},[e._v("Introduccion "),o("a",{staticClass:"header-anchor",attrs:{href:"#introduccion"}},[e._v("¶")])]),o("p",[o("a",{attrs:{href:"https://arquitecturas-concurrentes.github.io/iasc-book/introduccion/"}},[e._v("Ya presentada la noción de arquitectura")]),e._v(", nos queda introducir el otro gran tópico que nos incumbe: la concurrencia, concepto diferente pero relacionado (y a veces confundido) con el de paralelismo. No vamos a entrar en definiciones de libro, pero es importante que repasemos qué significa cada uno.")]),o("h3",{attrs:{id:"paralelismo"}},[e._v("Paralelismo "),o("a",{staticClass:"header-anchor",attrs:{href:"#paralelismo"}},[e._v("¶")])]),o("p",[e._v("El "),o("strong",[e._v("paralelismo")]),e._v(" es la ejecución simultánea de dos o más operaciones. Se trata de una propiedad que permite a los programas ejecutarse más rápido, y requiere un soporte "),o("strong",[e._v("físico")]),e._v(": ya sean múltiples procesadores, núcleos o computadoras, tenemos múltiples computaciones ejecutándose al mismo tiempo, con mínima o nula comunicación entre ellas. Es una cuestión no funcional, normalmente no percibida cualitativamente por el usuario.")]),o("p",[e._v("Por ejemplo, tanto si procesamos un archivo de log para filtrar palabras en una sola computadora, o a través de un clúster "),o("a",{attrs:{href:"https://hadoop.apache.org/"}},[e._v("Hadoop")]),e._v(" con decenas de computadoras, el resultado final será el mismo.")]),o("p",[e._v("El paralelismo existe en múltiples niveles:")]),o("ul",[o("li",[o("p",[o("strong",[e._v("Paralelismo a nivel de bit")]),e._v(": ¿Por qué las computadoras de 64 bits son más rápidas que las de 16 bits? Si un equipo de 16 bits quiere realizar una suma de dos números de 32 bits, debe realizar una serie de operaciones de 16 bits, pero una computadora de 64 bits, puede realizar y soportar las mismas operaciones que las de 32, 16 y 8 bits, ya que utilizan los registros de acuerdo a su longitud.")])]),o("li",[o("p",[o("strong",[e._v("Paralelismo a nivel de instrucción")]),e._v(': Los procesadores, mediante técnicas como pipelining, ejecución fuera de orden y ejecución especulativa, permiten ejecutar varias operaciones en simultáneo. Este tipo de optimización queda encapsulada a este nivel, es decir, funciona "por atrás" sin que el usuario lo sepa. De hecho, gran parte de la complejidad de estos mecanismos está en procurar que todos los resultados se vean como si la ejecución hubiese sido secuencial.')]),o("p",[e._v("En los últimos años no se han encontrado nuevas maneras para incrementar la velocidad de un procesador de un solo núcleo. Por eso, la industria migró al mundo de los múltiples núcleos. Con esto, emergen los problemas de que las instrucciones no se manejan secuencialmente.")])]),o("li",[o("p",[o("strong",[e._v("Paralelismo a nivel de datos")]),e._v(": conocido como SIMD (“single instruction, multiple data”), esta arquitectura es capaz de llevar a cabo la misma operación sobre una gran cantidad de datos en paralelo. Este tipo de ejecución no es útil para todos los problemas, pero sí para varias áreas, como el procesamiento de imágenes (especialmente en videojuegos), y el entrenamiento de modelos de deep learning. Por esta razón, las GPUs (unidades gráficas de procesamiento) se han desarrollado como procesadores de datos paralelos especiales.")])]),o("li",[o("p",[o("strong",[e._v("Paralelismo a nivel de tareas")]),e._v(": esto es lo que se conoce como múltiples procesadores. Desde el punto de vista de un programador, el punto más importante de una arquitectura multiprocesador es el modelo de memoria, que puede ser distribuida o compartida. En un multiprocesador con arquitectura de memoria compartida, cada procesador puede acceder a cualquier locación de memoria, y la comunicación inter-procesador es generalmente realizada a través de la memoria. En un esquema de memoria distribuida, cada procesador tiene su propia memoria local, y la comunicación inter-procesador se realiza mediante la red, o un bus de datos (en caso de que estén en una misma máquina física). Debido a que la comunicación inter-procesador es más rápida en memoria, históricamente se tendió a escribir código para arquitecturas de memoria compartida. Sin embargo, cuando se cuenta con una cantidad elevada de procesadores, la memoria compartida se convierte en un cuello de botella, y ahí el modelo que se ajusta mejor es uno basado en un esquema distribuido. La memoria distribuida también es importante y fundamental si se desea implementar sistemas tolerantes a fallos, que utilicen múltiples máquinas para soportar fallos de hardware.")])])]),o("p",[e._v("En esta materia vamos a enfocarnos en el paralelismo a nivel de tareas.")]),o("h3",{attrs:{id:"concurrencia"}},[e._v("Concurrencia "),o("a",{staticClass:"header-anchor",attrs:{href:"#concurrencia"}},[e._v("¶")])]),o("p",[e._v("Decimos que hay "),o("strong",[e._v("concurrencia")]),e._v(" cuando existen simultáneamente múltiples contextos de ejecución. Se trata de una propiedad "),o("strong",[e._v("lógica")]),e._v(" que permite a los programas ser más usables, y que afecta a la funcionalidad del sistema.")]),o("p",[e._v("Por ejemplo, si tenemos un procesador de texto, mientras escribimos, en segundo plano tendremos tareas que validan la ortografía, guardan el documento, lo sincronizan contra una versión remota y descargan actualizaciones. Si estas tareas no se estuvieran ejecutando de forma concurrente, tendríamos que dejar de escribir, guardar el archivo, chequear la ortografía, etc., de forma secuencial, lo cual evidentemente afecta a la usabilidad del sistema. Y esto es independiente de que las tareas se ejecuten en paralelo o no.")]),o("p",[e._v("Como se desprende del ejemplo, cuando estamos ante un diseño concurrente, tendremos en general recursos compartidos (por ejemplo la hoja del editor) y por tanto deberemos comunicar y coordinar de alguna forma estas tareas.")]),o("p",[e._v("La concurrencia es naturalmente una fuente de "),o("strong",[e._v("no determinismo")]),e._v(", dado que el orden de ejecución de los distintos contextos de ejecución puede variar. Este no determinismo puede ser visible externamente (por ejemplo, por el usuario de un programa), o puede estar abstraído de forma que exista la ilusión de una ejecución determinística.")]),o("p",[e._v("Un ejemplo común de no determinismo son las "),o("strong",[e._v("condiciones de carrera")]),e._v(", que ocurren cuando alguno de los órdenes posibles en los que se pueden ejecutar los distintos contextos producen resultados no deseados.")]),o("p",[e._v("Moraleja: si bien podemos tener sistemas concurrentes en los que haya ejecución paralela, concurrencia no implica paralelismo. Y paralelismo no implica concurrencia.")])])}],n=o("2877"),i={},t=Object(n["a"])(i,s,r,!1,null,null,null);a["default"]=t.exports}}]); +//# sourceMappingURL=chunk-2d212f5c.78f8895b.js.map \ No newline at end of file diff --git a/js/chunk-2d212f5c.78f8895b.js.map b/js/chunk-2d212f5c.78f8895b.js.map new file mode 100644 index 0000000..353ff98 --- /dev/null +++ b/js/chunk-2d212f5c.78f8895b.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/content/concurrencia_paralelismo.md?f834","webpack:///./src/content/concurrencia_paralelismo.md"],"names":["render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","script","component"],"mappings":"uHAAA,IAAIA,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAsBH,EAAII,MAAMC,GAAO,OAAOL,EAAIM,GAAG,IACnGC,EAAkB,CAAC,WAAa,IAAIP,EAAIC,KAASC,EAAGF,EAAIG,eAAmBE,EAAGL,EAAII,MAAMC,IAAIH,EAAG,OAAOG,EAAG,UAAU,CAACA,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,iBAAiB,CAACR,EAAIS,GAAG,iBAAiBJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,kBAAkB,CAACR,EAAIS,GAAG,SAASJ,EAAG,IAAI,CAACA,EAAG,IAAI,CAACG,MAAM,CAAC,KAAO,yEAAyE,CAACR,EAAIS,GAAG,6CAA6CT,EAAIS,GAAG,yQAAyQJ,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,gBAAgB,CAACR,EAAIS,GAAG,gBAAgBJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,iBAAiB,CAACR,EAAIS,GAAG,SAASJ,EAAG,IAAI,CAACL,EAAIS,GAAG,OAAOJ,EAAG,SAAS,CAACL,EAAIS,GAAG,iBAAiBT,EAAIS,GAAG,6JAA6JJ,EAAG,SAAS,CAACL,EAAIS,GAAG,YAAYT,EAAIS,GAAG,iQAAiQJ,EAAG,IAAI,CAACL,EAAIS,GAAG,+HAA+HJ,EAAG,IAAI,CAACG,MAAM,CAAC,KAAO,+BAA+B,CAACR,EAAIS,GAAG,YAAYT,EAAIS,GAAG,qEAAqEJ,EAAG,IAAI,CAACL,EAAIS,GAAG,iDAAiDJ,EAAG,KAAK,CAACA,EAAG,KAAK,CAACA,EAAG,IAAI,CAACA,EAAG,SAAS,CAACL,EAAIS,GAAG,gCAAgCT,EAAIS,GAAG,uXAAuXJ,EAAG,KAAK,CAACA,EAAG,IAAI,CAACA,EAAG,SAAS,CAACL,EAAIS,GAAG,wCAAwCT,EAAIS,GAAG,mbAAqbJ,EAAG,IAAI,CAACL,EAAIS,GAAG,wRAAwRJ,EAAG,KAAK,CAACA,EAAG,IAAI,CAACA,EAAG,SAAS,CAACL,EAAIS,GAAG,kCAAkCT,EAAIS,GAAG,4fAA4fJ,EAAG,KAAK,CAACA,EAAG,IAAI,CAACA,EAAG,SAAS,CAACL,EAAIS,GAAG,mCAAmCT,EAAIS,GAAG,srCAAsrCJ,EAAG,IAAI,CAACL,EAAIS,GAAG,6EAA6EJ,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,iBAAiB,CAACR,EAAIS,GAAG,iBAAiBJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,kBAAkB,CAACR,EAAIS,GAAG,SAASJ,EAAG,IAAI,CAACL,EAAIS,GAAG,oBAAoBJ,EAAG,SAAS,CAACL,EAAIS,GAAG,kBAAkBT,EAAIS,GAAG,gGAAgGJ,EAAG,SAAS,CAACL,EAAIS,GAAG,YAAYT,EAAIS,GAAG,gGAAgGJ,EAAG,IAAI,CAACL,EAAIS,GAAG,ghBAAghBJ,EAAG,IAAI,CAACL,EAAIS,GAAG,oOAAoOJ,EAAG,IAAI,CAACL,EAAIS,GAAG,kDAAkDJ,EAAG,SAAS,CAACL,EAAIS,GAAG,qBAAqBT,EAAIS,GAAG,sRAAsRJ,EAAG,IAAI,CAACL,EAAIS,GAAG,gDAAgDJ,EAAG,SAAS,CAACL,EAAIS,GAAG,4BAA4BT,EAAIS,GAAG,gJAAgJJ,EAAG,IAAI,CAACL,EAAIS,GAAG,+K,YCA/sNE,EAAS,GAKTC,EAAY,eACdD,EACAZ,EACAQ,GACA,EACA,KACA,KACA,MAIa,aAAAK,E","file":"js/chunk-2d212f5c.78f8895b.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h3',{attrs:{\"id\":\"introduccion\"}},[_vm._v(\"Introduccion \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#introduccion\"}},[_vm._v(\"¶\")])]),_c('p',[_c('a',{attrs:{\"href\":\"https://arquitecturas-concurrentes.github.io/iasc-book/introduccion/\"}},[_vm._v(\"Ya presentada la noción de arquitectura\")]),_vm._v(\", nos queda introducir el otro gran tópico que nos incumbe: la concurrencia, concepto diferente pero relacionado (y a veces confundido) con el de paralelismo. No vamos a entrar en definiciones de libro, pero es importante que repasemos qué significa cada uno.\")]),_c('h3',{attrs:{\"id\":\"paralelismo\"}},[_vm._v(\"Paralelismo \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#paralelismo\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"El \"),_c('strong',[_vm._v(\"paralelismo\")]),_vm._v(\" es la ejecución simultánea de dos o más operaciones. Se trata de una propiedad que permite a los programas ejecutarse más rápido, y requiere un soporte \"),_c('strong',[_vm._v(\"físico\")]),_vm._v(\": ya sean múltiples procesadores, núcleos o computadoras, tenemos múltiples computaciones ejecutándose al mismo tiempo, con mínima o nula comunicación entre ellas. Es una cuestión no funcional, normalmente no percibida cualitativamente por el usuario.\")]),_c('p',[_vm._v(\"Por ejemplo, tanto si procesamos un archivo de log para filtrar palabras en una sola computadora, o a través de un clúster \"),_c('a',{attrs:{\"href\":\"https://hadoop.apache.org/\"}},[_vm._v(\"Hadoop\")]),_vm._v(\" con decenas de computadoras, el resultado final será el mismo.\")]),_c('p',[_vm._v(\"El paralelismo existe en múltiples niveles:\")]),_c('ul',[_c('li',[_c('p',[_c('strong',[_vm._v(\"Paralelismo a nivel de bit\")]),_vm._v(\": ¿Por qué las computadoras de 64 bits son más rápidas que las de 16 bits? Si un equipo de 16 bits quiere realizar una suma de dos números de 32 bits, debe realizar una serie de operaciones de 16 bits, pero una computadora de 64 bits, puede realizar y soportar las mismas operaciones que las de 32, 16 y 8 bits, ya que utilizan los registros de acuerdo a su longitud.\")])]),_c('li',[_c('p',[_c('strong',[_vm._v(\"Paralelismo a nivel de instrucción\")]),_vm._v(\": Los procesadores, mediante técnicas como pipelining, ejecución fuera de orden y ejecución especulativa, permiten ejecutar varias operaciones en simultáneo. Este tipo de optimización queda encapsulada a este nivel, es decir, funciona \\\"por atrás\\\" sin que el usuario lo sepa. De hecho, gran parte de la complejidad de estos mecanismos está en procurar que todos los resultados se vean como si la ejecución hubiese sido secuencial.\")]),_c('p',[_vm._v(\"En los últimos años no se han encontrado nuevas maneras para incrementar la velocidad de un procesador de un solo núcleo. Por eso, la industria migró al mundo de los múltiples núcleos. Con esto, emergen los problemas de que las instrucciones no se manejan secuencialmente.\")])]),_c('li',[_c('p',[_c('strong',[_vm._v(\"Paralelismo a nivel de datos\")]),_vm._v(\": conocido como SIMD (“single instruction, multiple data”), esta arquitectura es capaz de llevar a cabo la misma operación sobre una gran cantidad de datos en paralelo. Este tipo de ejecución no es útil para todos los problemas, pero sí para varias áreas, como el procesamiento de imágenes (especialmente en videojuegos), y el entrenamiento de modelos de deep learning. Por esta razón, las GPUs (unidades gráficas de procesamiento) se han desarrollado como procesadores de datos paralelos especiales.\")])]),_c('li',[_c('p',[_c('strong',[_vm._v(\"Paralelismo a nivel de tareas\")]),_vm._v(\": esto es lo que se conoce como múltiples procesadores. Desde el punto de vista de un programador, el punto más importante de una arquitectura multiprocesador es el modelo de memoria, que puede ser distribuida o compartida. En un multiprocesador con arquitectura de memoria compartida, cada procesador puede acceder a cualquier locación de memoria, y la comunicación inter-procesador es generalmente realizada a través de la memoria. En un esquema de memoria distribuida, cada procesador tiene su propia memoria local, y la comunicación inter-procesador se realiza mediante la red, o un bus de datos (en caso de que estén en una misma máquina física). Debido a que la comunicación inter-procesador es más rápida en memoria, históricamente se tendió a escribir código para arquitecturas de memoria compartida. Sin embargo, cuando se cuenta con una cantidad elevada de procesadores, la memoria compartida se convierte en un cuello de botella, y ahí el modelo que se ajusta mejor es uno basado en un esquema distribuido. La memoria distribuida también es importante y fundamental si se desea implementar sistemas tolerantes a fallos, que utilicen múltiples máquinas para soportar fallos de hardware.\")])])]),_c('p',[_vm._v(\"En esta materia vamos a enfocarnos en el paralelismo a nivel de tareas.\")]),_c('h3',{attrs:{\"id\":\"concurrencia\"}},[_vm._v(\"Concurrencia \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#concurrencia\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Decimos que hay \"),_c('strong',[_vm._v(\"concurrencia\")]),_vm._v(\" cuando existen simultáneamente múltiples contextos de ejecución. Se trata de una propiedad \"),_c('strong',[_vm._v(\"lógica\")]),_vm._v(\" que permite a los programas ser más usables, y que afecta a la funcionalidad del sistema.\")]),_c('p',[_vm._v(\"Por ejemplo, si tenemos un procesador de texto, mientras escribimos, en segundo plano tendremos tareas que validan la ortografía, guardan el documento, lo sincronizan contra una versión remota y descargan actualizaciones. Si estas tareas no se estuvieran ejecutando de forma concurrente, tendríamos que dejar de escribir, guardar el archivo, chequear la ortografía, etc., de forma secuencial, lo cual evidentemente afecta a la usabilidad del sistema. Y esto es independiente de que las tareas se ejecuten en paralelo o no.\")]),_c('p',[_vm._v(\"Como se desprende del ejemplo, cuando estamos ante un diseño concurrente, tendremos en general recursos compartidos (por ejemplo la hoja del editor) y por tanto deberemos comunicar y coordinar de alguna forma estas tareas.\")]),_c('p',[_vm._v(\"La concurrencia es naturalmente una fuente de \"),_c('strong',[_vm._v(\"no determinismo\")]),_vm._v(\", dado que el orden de ejecución de los distintos contextos de ejecución puede variar. Este no determinismo puede ser visible externamente (por ejemplo, por el usuario de un programa), o puede estar abstraído de forma que exista la ilusión de una ejecución determinística.\")]),_c('p',[_vm._v(\"Un ejemplo común de no determinismo son las \"),_c('strong',[_vm._v(\"condiciones de carrera\")]),_vm._v(\", que ocurren cuando alguno de los órdenes posibles en los que se pueden ejecutar los distintos contextos producen resultados no deseados.\")]),_c('p',[_vm._v(\"Moraleja: si bien podemos tener sistemas concurrentes en los que haya ejecución paralela, concurrencia no implica paralelismo. Y paralelismo no implica concurrencia.\")])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./concurrencia_paralelismo.md?vue&type=template&id=6c5c53c1&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-2d21aecd.a9484b97.js b/js/chunk-2d21aecd.a9484b97.js new file mode 100644 index 0000000..943b645 --- /dev/null +++ b/js/chunk-2d21aecd.a9484b97.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d21aecd"],{be1e:function(e,t,n){"use strict";n.r(t);var r=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("RemoteMarkdown",{attrs:{url:e.url}})},a=[],s=n("9454"),o={name:"STM",components:{RemoteMarkdown:s["a"]},data:function(){return{url:"https://raw.githubusercontent.com/arquitecturas-concurrentes/iasc-stm-haskell-2019/master/01_semaphores_and_philosophers/README.md"}}},u=o,c=n("2877"),l=Object(c["a"])(u,r,a,!1,null,null,null);t["default"]=l.exports}}]); +//# sourceMappingURL=chunk-2d21aecd.a9484b97.js.map \ No newline at end of file diff --git a/js/chunk-2d21aecd.a9484b97.js.map b/js/chunk-2d21aecd.a9484b97.js.map new file mode 100644 index 0000000..856b842 --- /dev/null +++ b/js/chunk-2d21aecd.a9484b97.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/views/STM.vue?4a40","webpack:///src/views/STM.vue","webpack:///./src/views/STM.vue?35a7","webpack:///./src/views/STM.vue"],"names":["render","_vm","this","_h","$createElement","_c","_self","attrs","url","staticRenderFns","component"],"mappings":"uHAAA,IAAIA,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,iBAAiB,CAACE,MAAM,CAAC,IAAMN,EAAIO,QAClIC,EAAkB,G,YCKtB,GACE,KAAF,MACE,WAAF,CACI,eAAJ,QAEE,KALF,WAMI,MAAO,CACLD,IAAK,wICbkU,I,YCOzUE,EAAY,eACd,EACAV,EACAS,GACA,EACA,KACA,KACA,MAIa,aAAAC,E","file":"js/chunk-2d21aecd.a9484b97.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('RemoteMarkdown',{attrs:{\"url\":_vm.url}})}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./STM.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./STM.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./STM.vue?vue&type=template&id=477aebde&\"\nimport script from \"./STM.vue?vue&type=script&lang=js&\"\nexport * from \"./STM.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-2d21de07.24f6f56c.js b/js/chunk-2d21de07.24f6f56c.js new file mode 100644 index 0000000..ca4d506 --- /dev/null +++ b/js/chunk-2d21de07.24f6f56c.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d21de07"],{d2be:function(e,a,o){"use strict";o.r(a);var n=function(){var e=this,a=e.$createElement;e._self._c;return e._m(0)},s=[function(){var e=this,a=e.$createElement,o=e._self._c||a;return o("section",[o("hr"),o("h2",{attrs:{id:"layout-defaulttitle-distribucion-en-elixirdescription-distribuyendo-en-elixir-una-introduccion"}},[e._v('layout: default title: "Distribucion En Elixir" description: "Distribuyendo en Elixir. Una introduccion" '),o("a",{staticClass:"header-anchor",attrs:{href:"#layout-defaulttitle-distribucion-en-elixirdescription-distribuyendo-en-elixir-una-introduccion"}},[e._v("¶")])]),o("h1",{attrs:{id:"distribución-en-elixirerlang-beam"}},[e._v("Distribución en Elixir/Erlang (BEAM) "),o("a",{staticClass:"header-anchor",attrs:{href:"#distribución-en-elixirerlang-beam"}},[e._v("¶")])]),o("p",[e._v("Cuando hablamos de distribución en general, en general estamos solos sin ayuda de algún componente del lenguaje que estamos usando, es decir, estamos solos en la oscuridad sin saber qué es lo que puede suceder. Con erlang/elixir, a pesar de que posee mecanismos como los que vimos, tampoco estamos con mucha más ayuda del lenguaje, o sea seguimos en la oscuridad. Elixir nos da ventajas para tolerancia a fallos y resiliencia pero no mucho más que eso. Cuando se implementó Erlang muchas de las consideraciones que veremos hoy no se tomaron en cuenta por un tema de que la arquitectura en la que fue concebido es distinto a lo que hoy conocemos. Elixir posee algunas cosas base por la cuales podemos utilizar como fundaciones para construir aplicaciones distribuidas, que ya vimos interconectando máquinas virtuales entre si, como serializar datos (van a tener que ver la api para esto), y como saber cuando un nodo se cae (esto lo vemos pronto), pero no sobre soluciones específicas como que pasa cuando un proceso se cae o algo falla inesperadamente en una maquina. O sea OTP nos da muchas herramientas para ir manejando y construyendo estas herramientas pero no existe una en particular para solucionar todos los problemas puntuales de nuestra aplicación Erlang/Elixir, o sea no hay bala de plata.")]),o("p",[e._v("Una instancia de la máquina virtual de erlang, que está lista para comunicarse con otras vm’s las llamaremos nodos. Cuando se inicializa un nodo, se le da un nombre en concreto como vimos con el caso del ping pong y este se conecta a una aplicación llamada Erlang Port Mapper Daemon (EPMD), que ejecuta en cada una de las máquinas que son parte del cluster que estaremos armando, si es el caso que es más de una máquina. EPMD actuará como un name server que permite que los nodos se registren, se contacten con otros nodos y notifiquen cuando hay algún conflicto de nombres.")]),o("p",[e._v("De esta manera ya podemos empezar a conectar uno nodos con otros, y ver como empiezan a haber comunicación entre estos, un primer approach que se puede ver es que si se tiene un nodo A y otro B solo con una conexión y uno de estos se cae, el otro nodo queda aislado.")]),o("p",[e._v("Si B estaba comunicado con C y necesita procesar algo que puede solo hacerlo A y B solo lo hacia delegando a A, esta funcionalidad ya no funciona ya que A esta aislado. Una primera idea es interconectar a todos con todos. Esta idea podría ser interesante, más que nada por una cuestión de tolerancia a fallos, pero sucede que puede ser un problema si la aplicación escala y se necesitan interconectar más nodos. Será dificil de tener cientos y cientos de nodos interconectados en sí más que nada por la cantidad de conexiones que necesitan, también hay que recordar que se necesita un puerto por nodo al que se está conectando. La topología más común a esto es hacerlo en forma de anillo, algo parecido a lo que hay en token ring, pero sin el token.")]),o("p",[e._v("Una vez que se conectaron los nodos, estos son ya independientes, poseen su registro del proceso, sus tablas de ETS y módulos independientes unos de otros. Un nodo cuando se cae no hace que se caigan los nodos asociados. Lo interesante de la conexión entre nodos es que se pueden mandar mensajes de la misma manera en la que se lo hace entre procesos de un mismo nodo. La serialización/deserialización lo hace automáticamente y de manera transparente el nodo. Veremos que las estructuras incluidas los pids funcionan de la misma manera remotamente como localmente, esto significa que puede mandarse mensajes de pids sobre la red y comunicarlos mediante mensajes.")])])}],i=o("2877"),r={},t=Object(i["a"])(r,n,s,!1,null,null,null);a["default"]=t.exports}}]); +//# sourceMappingURL=chunk-2d21de07.24f6f56c.js.map \ No newline at end of file diff --git a/js/chunk-2d21de07.24f6f56c.js.map b/js/chunk-2d21de07.24f6f56c.js.map new file mode 100644 index 0000000..8bc1f58 --- /dev/null +++ b/js/chunk-2d21de07.24f6f56c.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/content/distribucion_elixir.md?0b95","webpack:///./src/content/distribucion_elixir.md"],"names":["render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","script","component"],"mappings":"uHAAA,IAAIA,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAsBH,EAAII,MAAMC,GAAO,OAAOL,EAAIM,GAAG,IACnGC,EAAkB,CAAC,WAAa,IAAIP,EAAIC,KAASC,EAAGF,EAAIG,eAAmBE,EAAGL,EAAII,MAAMC,IAAIH,EAAG,OAAOG,EAAG,UAAU,CAACA,EAAG,MAAMA,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,mGAAmG,CAACR,EAAIS,GAAG,6GAAiHJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,oGAAoG,CAACR,EAAIS,GAAG,SAASJ,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,sCAAsC,CAACR,EAAIS,GAAG,yCAAyCJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,uCAAuC,CAACR,EAAIS,GAAG,SAASJ,EAAG,IAAI,CAACL,EAAIS,GAAG,0xCAA0xCJ,EAAG,IAAI,CAACL,EAAIS,GAAG,okBAAokBJ,EAAG,IAAI,CAACL,EAAIS,GAAG,gRAAgRJ,EAAG,IAAI,CAACL,EAAIS,GAAG,mvBAAmvBJ,EAAG,IAAI,CAACL,EAAIS,GAAG,gqB,YCAvpHE,EAAS,GAKTC,EAAY,eACdD,EACAZ,EACAQ,GACA,EACA,KACA,KACA,MAIa,aAAAK,E","file":"js/chunk-2d21de07.24f6f56c.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('hr'),_c('h2',{attrs:{\"id\":\"layout-defaulttitle-distribucion-en-elixirdescription-distribuyendo-en-elixir-una-introduccion\"}},[_vm._v(\"layout: default title: \\\"Distribucion En Elixir\\\" description: \\\"Distribuyendo en Elixir. Una introduccion\\\" \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#layout-defaulttitle-distribucion-en-elixirdescription-distribuyendo-en-elixir-una-introduccion\"}},[_vm._v(\"¶\")])]),_c('h1',{attrs:{\"id\":\"distribución-en-elixirerlang-beam\"}},[_vm._v(\"Distribución en Elixir/Erlang (BEAM) \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#distribución-en-elixirerlang-beam\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Cuando hablamos de distribución en general, en general estamos solos sin ayuda de algún componente del lenguaje que estamos usando, es decir, estamos solos en la oscuridad sin saber qué es lo que puede suceder. Con erlang/elixir, a pesar de que posee mecanismos como los que vimos, tampoco estamos con mucha más ayuda del lenguaje, o sea seguimos en la oscuridad. Elixir nos da ventajas para tolerancia a fallos y resiliencia pero no mucho más que eso. Cuando se implementó Erlang muchas de las consideraciones que veremos hoy no se tomaron en cuenta por un tema de que la arquitectura en la que fue concebido es distinto a lo que hoy conocemos. Elixir posee algunas cosas base por la cuales podemos utilizar como fundaciones para construir aplicaciones distribuidas, que ya vimos interconectando máquinas virtuales entre si, como serializar datos (van a tener que ver la api para esto), y como saber cuando un nodo se cae (esto lo vemos pronto), pero no sobre soluciones específicas como que pasa cuando un proceso se cae o algo falla inesperadamente en una maquina. O sea OTP nos da muchas herramientas para ir manejando y construyendo estas herramientas pero no existe una en particular para solucionar todos los problemas puntuales de nuestra aplicación Erlang/Elixir, o sea no hay bala de plata.\")]),_c('p',[_vm._v(\"Una instancia de la máquina virtual de erlang, que está lista para comunicarse con otras vm’s las llamaremos nodos. Cuando se inicializa un nodo, se le da un nombre en concreto como vimos con el caso del ping pong y este se conecta a una aplicación llamada Erlang Port Mapper Daemon (EPMD), que ejecuta en cada una de las máquinas que son parte del cluster que estaremos armando, si es el caso que es más de una máquina. EPMD actuará como un name server que permite que los nodos se registren, se contacten con otros nodos y notifiquen cuando hay algún conflicto de nombres.\")]),_c('p',[_vm._v(\"De esta manera ya podemos empezar a conectar uno nodos con otros, y ver como empiezan a haber comunicación entre estos, un primer approach que se puede ver es que si se tiene un nodo A y otro B solo con una conexión y uno de estos se cae, el otro nodo queda aislado.\")]),_c('p',[_vm._v(\"Si B estaba comunicado con C y necesita procesar algo que puede solo hacerlo A y B solo lo hacia delegando a A, esta funcionalidad ya no funciona ya que A esta aislado. Una primera idea es interconectar a todos con todos. Esta idea podría ser interesante, más que nada por una cuestión de tolerancia a fallos, pero sucede que puede ser un problema si la aplicación escala y se necesitan interconectar más nodos. Será dificil de tener cientos y cientos de nodos interconectados en sí más que nada por la cantidad de conexiones que necesitan, también hay que recordar que se necesita un puerto por nodo al que se está conectando. La topología más común a esto es hacerlo en forma de anillo, algo parecido a lo que hay en token ring, pero sin el token.\")]),_c('p',[_vm._v(\"Una vez que se conectaron los nodos, estos son ya independientes, poseen su registro del proceso, sus tablas de ETS y módulos independientes unos de otros. Un nodo cuando se cae no hace que se caigan los nodos asociados. Lo interesante de la conexión entre nodos es que se pueden mandar mensajes de la misma manera en la que se lo hace entre procesos de un mismo nodo. La serialización/deserialización lo hace automáticamente y de manera transparente el nodo. Veremos que las estructuras incluidas los pids funcionan de la misma manera remotamente como localmente, esto significa que puede mandarse mensajes de pids sobre la red y comunicarlos mediante mensajes.\")])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./distribucion_elixir.md?vue&type=template&id=324eee5a&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-2d22cff6.31a88251.js b/js/chunk-2d22cff6.31a88251.js new file mode 100644 index 0000000..1da8efc --- /dev/null +++ b/js/chunk-2d22cff6.31a88251.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d22cff6"],{f62b:function(e,s,a){"use strict";a.r(s);var n=function(){var e=this,s=e.$createElement;e._self._c;return e._m(0)},r=[function(){var e=this,s=e.$createElement,a=e._self._c||s;return a("section",[a("h1",{attrs:{id:"introduccion"}},[e._v("Introduccion "),a("a",{staticClass:"header-anchor",attrs:{href:"#introduccion"}},[e._v("¶")])]),a("p",[e._v("Empecemos de a poco y por algo muy simple: una función que incrementa en una unidad a su argumento, la función succesor.")]),a("blockquote",[a("p",[e._v("Nota: cuando decimos función lo decimos en el sentido estricto de una computación que toma un valor y devuelve otro, sin tener ningún tipo de efecto En JavaScript, su código se ve como el siguiente:")])]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("succesor")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("x")]),e._v(") ")]),e._v("{\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("return")]),e._v(" x + "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(";\n}\n")])]),a("p",[e._v("Usar esta función no tiene mucho misterio:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" i0 = "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v(";\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" i1 = succesor(i0);\n…etc…\n")])]),a("p",[e._v("La función succesor está escrita en lo que se conoce como estilo directo: los resultados de la misma (en este caso, su entrada más uno) se obtienen a partir de su retorno.")]),a("p",[e._v("Hasta acá nada extraño. Hagamos ahora un salto conceptual: otra forma posible de escribir este código, es que el resultado se obtenga a partir de un callback.")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("succesor")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("x, callback")]),e._v(") ")]),e._v("{\n callback(x + "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(");\n}\n")])]),a("p",[e._v("¿Y cómo la usamos?")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" i0 = "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v(";\nsuccesor(i0, (resultado) => {\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" i1 = resultado;\n "),a("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("//...etc...")]),e._v("\n});\n")])]),a("p",[e._v("¡Momento! ¿Qué fue eso? Si bien puede verse un poco perturbador al principio, este código es totalmente equivalente al anterior: cuando se aplica la función succesor, calcula su siguiente, y se lo pasa al callback, que opera con el mismo normalmente.")]),a("blockquote",[a("p",[e._v("Si te estás preguntando hacia dónde vamos y qué tiene todo esto que ver con la concurrencia, ¡danos uno rato! Prometemos que pronto todo tendrá sentido.")])]),a("p",[e._v("A este callback se lo llama continuación. Porque… ¡es lo que que se ejecuta a continuación! O en inglés: continuation. ¿Qué significa esto? Que las funciones que toman continuaciones, no solo ahora saben lo que tienen que hacer, sino también cuándo se ejecutará lo que siga. Por eso decimos que una función escrita de este forma tiene, además de la lógica de negocio, control de flujo (o simplemente llamado control).")]),a("p",[e._v("Peeeero, para que esto sea realmente posible, tenemos que tomar ciertas precauciones, y entender que al trabajar de esta forma, el resultado sólo se puede obtener dentro de la continuación. Por tanto, el siguiente es un code smell:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" i0 = "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v(";\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" i1;\nsuccesor(i0, (resultado) => {\n i1 = resultado;\n});\n"),a("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("//..resto...")]),e._v("\n")])]),a("p",[e._v("Aquí estamos capturando el resultado de successor a través de la continuación, asumiendo que el código se ejecutará inmediatamente y que estará disponible en la línea 6.")]),a("p",[e._v("Pero si es realmente successor quien tiene control sobre cuándo y cómo se ejecuta la continuación, no podemos garantizar esto dado que no sabemos cuándo se va a ejecutar la continuación.")]),a("p",[e._v("¿Esto significa que el código anterior no funciona? No, pero tenemos que entender que estamos rompiendo el modelo de continuación, al no permitir que sea la función successor la que determine cuándo y cómo seguir. Y eso puede ser una fuente de bugs.")]),a("h3",{attrs:{id:"consecuencias"}},[e._v("Consecuencias "),a("a",{staticClass:"header-anchor",attrs:{href:"#consecuencias"}},[e._v("¶")])]),a("p",[e._v("En oposición al estilo directo, caracterizado por la obtención de resultados mediante retornos, surge así el estilo de paso de continuaciones (CPS, por sus siglas en inglés). Es decir, cuando tenemos una función que toma una continuación y efectivamente colocamos todo el código que opera con el resultado dentro de la misma, tenemos una función CPS.")]),a("p",[e._v("El CPS es especial porque es fácil introducirlo, pero imposible salir de él, al menos no sin introducir bugs y potenciales problemas en el sistema.")]),a("p",[e._v("Retomando las ideas de nuestro primer episodio, esto es una propiedad interesante: una vez impuesta la arquitectura, no tenemos opción de escapar de ella, lo que nos resta en flexibilidad, pero nos fuerza a ser consistentes.")]),a("p",[e._v("Ejemplo: si ahora queremos implementar una función que incrementa el doble de un número, usando nuestro successor CPS, estaríamos tentados a escribir esto:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("incrementarDoble")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("i")]),e._v(") ")]),e._v("{\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" i0 = "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("2")]),e._v(" * i;\n succesor(i0, "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("resultado")]),e._v(") ")]),e._v("{\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" i1 = resultado;\n ???\n });\n}\n")])]),a("p",[e._v("Y ahí vemos el problema: incrementarDoble debe retornar i1, ¡pero no puede hacerlo, porque no hay garantías de cuando se va a ejecutar la continuación, ni cuantas veces! Por ello, la única alternativa válida (sin basarse en los detalles de implementación de successor, claro), es convertir a incrementarDoble en CPS también:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("incrementarDoble")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("i, cont")]),e._v(") ")]),e._v("{\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" i0 = "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("2")]),e._v(" * i;\n succesor(i0, cont);\n}\n")])]),a("p",[e._v("Moraleja: una vez que introducimos CPS, su uso sólo puede extenderse.")]),a("blockquote",[a("p",[e._v("Esto no significa que no podamos tener computaciones no CPS. Por ejemplo, la multiplicación podría ser extraída como una función en estilo directo. Desarrollaremos esta idea arquitectural mejor en próximos episodios cuando ataquemos el mundo monádico.")])]),a("h3",{attrs:{id:"para-qué-cps"}},[e._v("¿Para qué CPS? "),a("a",{staticClass:"header-anchor",attrs:{href:"#para-qué-cps"}},[e._v("¶")])]),a("p",[e._v("Resulta bastante evidente que razonar sobre CPS es más complejo que en el estilo directo. Entonces, ¿por qué habríamos de adoptarlo?")]),a("p",[e._v("CPS, al otorgarle a la función no sólo capacidad de cómputo sino de control, permite hacer cosas muy poderosas. En los ejemplos anteriores no lo aprovechamos, porque la computación succesor puede ser modelada con una función con un sólo resultado posible:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[e._v("\n"),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("succesor")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("x, cont")]),e._v(") ")]),e._v("{\n cont(x + "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(");\n}\n")])]),a("p",[e._v("Pero sin embargo, podríamos haber aplicado a la función cont cero (1) o muchas veces (2), podríamos haber recibido múltiples continuaciones y ejecutar alguna de ellas (3), o podríamos haberlas ejecutado en otro momento (4). CPS nos permite, entones, implementar 4 tipos de computaciones: con falla, no determinísticas, con excepciones y asincrónicas.")]),a("blockquote",[a("p",[e._v("Recordar estos tipos de continuaciones, volverán en episodios futuros")])]),a("h3",{attrs:{id:"falla"}},[e._v("Falla "),a("a",{staticClass:"header-anchor",attrs:{href:"#falla"}},[e._v("¶")])]),a("p",[e._v("Con CPS podemos codificar computaciones que pueden no tener resultado (los matemáticos las llaman funciones parciales). Por ejemplo, la división es una función parcial que no tiene un resultado cuando su segundo argumento es cero, por lo que podemos definir una función inversa CPS de la siguiente forma:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("inversa")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("x, cont")]),e._v(") ")]),e._v("{\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("if")]),e._v(" (x !== "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v(") {\n cont("),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v("/x);\n }\n}\n")])]),a("p",[e._v("Si ahora aplicamos a inversa con el valor 2, tendremos como resultado 0.5. Pero si la aplicamos con 0, no tendremos resultado. Esto no es lo mismo que no devolver nada en una función en estilo directo (o devolver null): en una función CPS que puede fallar, si no hay resultado, el programa continuación NO continúa; el flujo de ejecución se detiene.")]),a("h3",{attrs:{id:"no-determinismo"}},[e._v("No determinismo. "),a("a",{staticClass:"header-anchor",attrs:{href:"#no-determinismo"}},[e._v("¶")])]),a("p",[e._v("Hay computaciones que pueden arrojar cero o más resultados, son la generalización de la función: la relación. Por ejemplo, la pregunta ¿quien es hijo de Vito Corleone? (notá el singular) tiene múltiples respuestas: Sonny, Michel, Connie, etc. Esta es la base del paradigma lógico: relaciones que pueden generar ningún resultado, uno, o varios.")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("hijoDeVito")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("cont")]),e._v(") ")]),e._v("{\n cont("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v('"sonny"')]),e._v(");\n cont("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v('"michel"')]),e._v(");\n cont("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v('"connie"')]),e._v(");\n cont("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v('"freddo"')]),e._v(");\n}\n")])]),a("p",[e._v("Se observa fácilmente que logramos las múltiples respuestas mediante la aplicación reiterada de la continuación: el mismo programa está continuando múltiples veces con argumento diferentes.")]),a("p",[e._v("CPS no nos da una restriccion sobre la cantidad de veces a las que se deba llamar la continuacion que recibe. Por lo que vamos a poder aplicar la continuacion 0 o múltiples veces.")]),a("p",[e._v("Tal vez el ejemplo de recien no fue tan convincente.... bueno tenemos el ejemplo mas basico que podemos encontrar en la documentacion de Node.js:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("const")]),e._v(" http = "),a("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("require")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'http'")]),e._v(");\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("const")]),e._v(" hostname = "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'127.0.0.1'")]),e._v(";\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("const")]),e._v(" port = "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("3000")]),e._v(";\n\n"),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("const")]),e._v(" server = http.createServer("),a("span",{pre:!0,attrs:{class:"hljs-function"}},[e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("req, res")]),e._v(") =>")]),e._v(" {\n res.statusCode = "),a("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("200")]),e._v(";\n res.setHeader("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'Content-Type'")]),e._v(", "),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'text/plain'")]),e._v(");\n res.end("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'Hello World'")]),e._v(");\n});\n\nserver.listen(port, hostname, () => {\n "),a("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("console")]),e._v(".log("),a("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("`Server running at http://"),a("span",{pre:!0,attrs:{class:"hljs-subst"}},[e._v("${hostname}")]),e._v(":"),a("span",{pre:!0,attrs:{class:"hljs-subst"}},[e._v("${port}")]),e._v("/`")]),e._v(");\n});\n")])]),a("blockquote",[a("p",[e._v("Shamelessly taken from "),a("a",{attrs:{href:"https://nodejs.org/ca/docs/guides/getting-started-guide/"}},[e._v("here")])])]),a("p",[e._v("Este pequeño ejemplo nos muestra claramente el no determinismo, porque es un servidor que podemos levantar, y nunca vamos a saber cuantos request nos van a llegar al servidor durante el tiempo que este levantado, tal vez recibimos 28392389 requests, tal vez 0.")]),a("h3",{attrs:{id:"excepciones"}},[e._v("Excepciones "),a("a",{staticClass:"header-anchor",attrs:{href:"#excepciones"}},[e._v("¶")])]),a("p",[e._v("Todos conocemos las excepciones. Estas nos dan dos flujos de ejecución: uno de éxito y uno de fracaso, y en ambos hay resultados: el resultado normal del programa o el error en cuestión. Y esto lo podemos lograr pasando dos continaciones: la que contiene el flujo normal, y la que contiene el flujo de error.")]),a("h3",{attrs:{id:"computaciones-asincrónicas"}},[e._v("Computaciones asincrónicas. "),a("a",{staticClass:"header-anchor",attrs:{href:"#computaciones-asincrónicas"}},[e._v("¶")])]),a("p",[e._v("¡Éstas son las que más nos interesan! Operaciones que quizás no se ejecuten inmediatamente, sino en un momento posterior. Más sobre esto, en breve.")]),a("h3",{attrs:{id:"cps-y-callback-hell"}},[e._v("CPS, ¿y Callback Hell? "),a("a",{staticClass:"header-anchor",attrs:{href:"#cps-y-callback-hell"}},[e._v("¶")])]),a("p",[e._v("Un pequeño paréntesis: se suele achacar al uso de CPS la inevitable caída en el callback hell. Por ejemplo:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" cuentaLoca = "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("x, cont")]),e._v(") ")]),e._v("{ \n siguiente(x, "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("y")]),e._v(")")]),e._v("{\n inversa(y, "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("z")]),e._v(")")]),e._v("{\n duplicar(z, cont);\n })\n })\n};\n")])]),a("p",[e._v("Como se observa, algo tan simple en estilo directo como")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[e._v("duplicar(inversa(siguiente(x))) \n")])]),a("p",[e._v("se convierte en una compleja estructura de continuaciones anidadas. ¿Podríamos delegar esto de mejor forma? Si analizamos cómo queda expresada esta computación en estilo directo, podemos ver que duplicar la inversa del siguiente, a fin de cuentas, está describiendo una composición de funciones: al resultado de aplicar una función se le pasa a la entrada la otra. Obviamente, no es la misma composición de funciones que conocemos en estilo directo: es una composición CPS. Y entender esto nos permite definir una función componer, que haga justamente esto:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("componer")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("f, g")]),e._v(") ")]),e._v("{\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("return")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("x, cont")]),e._v(") ")]),e._v("{\n g(x, "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("y")]),e._v(")")]),e._v("{\n f(y, cont);\n })\n }\n }\n")])]),a("p",[e._v("y una vez que tenemos eso podemos ya utilizarla así:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" cuentaLoca = componer(duplicar, componer(inversa, siguiente))\n")])]),a("p",[e._v("Y si le damos una vuelta de tuerca más, podemos observar que estamos ante la estructura de aplicación de un fold, y definir una función pipeline que componga todas las funciones cps")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-function"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("function")]),e._v(" "),a("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("pipeline")]),e._v("("),a("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("fs")]),e._v(") ")]),e._v("{\n "),a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("return")]),e._v(" fs.reduce(componer);\n }\n")])]),a("p",[e._v("Con este pipeline podemos reutilizar el componer aplicandole un fold sobre un array y de esta manera que se puedan componer todas las funciones que tenemos sin caer de nuevo en el Callback Hell:")]),a("pre",{pre:!0},[a("code",{pre:!0,attrs:{"v-pre":"",class:"language-javascript"}},[a("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" cuentaLoca = pipeline([duplicar, inversa, siguiente]);\n")])]),a("p",[e._v("Y así vemos como eliminar el callback hell, aun con CPS, es posible. Moraleja: no es culpa del CPS, es culpa nuestra al no delegar convenientemente.")]),a("h3",{attrs:{id:"conclusiones"}},[e._v("Conclusiones "),a("a",{staticClass:"header-anchor",attrs:{href:"#conclusiones"}},[e._v("¶")])]),a("ul",[a("li",[e._v("CPS nos da gran poder, pero es difícil de manejar adecuadamente")]),a("li",[e._v("CPS nos lleva, si no tenemos cuidado al callback hell. Sin embargo, no es inherente a CPS, sino que es consecuencia de una mala delegación. Es posible resolverlo si se delega apropiadamente y aplicando los conceptos de programación funcional de orden superior y creando combinadores apropiados")]),a("li",[e._v("CPS nos permite implementar computaciones asincrónicas. NodeJS emplea CPS para soportarlas.")]),a("li",[e._v("El uso de CPS en NodeJS: pésimo manejo de errores y ausencia de abstracciones para hacerlo mas tratable. Por eso es que la comunidad centró su atención en otra forma de estructurar programas con influencias funcionales: las promesas (promises).")])])])}],o=a("2877"),t={},c=Object(o["a"])(t,n,r,!1,null,null,null);s["default"]=c.exports}}]); +//# sourceMappingURL=chunk-2d22cff6.31a88251.js.map \ No newline at end of file diff --git a/js/chunk-2d22cff6.31a88251.js.map b/js/chunk-2d22cff6.31a88251.js.map new file mode 100644 index 0000000..5653da1 --- /dev/null +++ b/js/chunk-2d22cff6.31a88251.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/content/cps.md?bd1e","webpack:///./src/content/cps.md"],"names":["render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","pre","script","component"],"mappings":"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","file":"js/chunk-2d22cff6.31a88251.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h1',{attrs:{\"id\":\"introduccion\"}},[_vm._v(\"Introduccion \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#introduccion\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Empecemos de a poco y por algo muy simple: una función que incrementa en una unidad a su argumento, la función succesor.\")]),_c('blockquote',[_c('p',[_vm._v(\"Nota: cuando decimos función lo decimos en el sentido estricto de una computación que toma un valor y devuelve otro, sin tener ningún tipo de efecto En JavaScript, su código se ve como el siguiente:\")])]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"succesor\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"x\")]),_vm._v(\") \")]),_vm._v(\"{\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"return\")]),_vm._v(\" x + \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\";\\n}\\n\")])]),_c('p',[_vm._v(\"Usar esta función no tiene mucho misterio:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" i0 = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\";\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" i1 = succesor(i0);\\n…etc…\\n\")])]),_c('p',[_vm._v(\"La función succesor está escrita en lo que se conoce como estilo directo: los resultados de la misma (en este caso, su entrada más uno) se obtienen a partir de su retorno.\")]),_c('p',[_vm._v(\"Hasta acá nada extraño. Hagamos ahora un salto conceptual: otra forma posible de escribir este código, es que el resultado se obtenga a partir de un callback.\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"succesor\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"x, callback\")]),_vm._v(\") \")]),_vm._v(\"{\\n callback(x + \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\");\\n}\\n\")])]),_c('p',[_vm._v(\"¿Y cómo la usamos?\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" i0 = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\";\\nsuccesor(i0, (resultado) => {\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" i1 = resultado;\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"//...etc...\")]),_vm._v(\"\\n});\\n\")])]),_c('p',[_vm._v(\"¡Momento! ¿Qué fue eso? Si bien puede verse un poco perturbador al principio, este código es totalmente equivalente al anterior: cuando se aplica la función succesor, calcula su siguiente, y se lo pasa al callback, que opera con el mismo normalmente.\")]),_c('blockquote',[_c('p',[_vm._v(\"Si te estás preguntando hacia dónde vamos y qué tiene todo esto que ver con la concurrencia, ¡danos uno rato! Prometemos que pronto todo tendrá sentido.\")])]),_c('p',[_vm._v(\"A este callback se lo llama continuación. Porque… ¡es lo que que se ejecuta a continuación! O en inglés: continuation. ¿Qué significa esto? Que las funciones que toman continuaciones, no solo ahora saben lo que tienen que hacer, sino también cuándo se ejecutará lo que siga. Por eso decimos que una función escrita de este forma tiene, además de la lógica de negocio, control de flujo (o simplemente llamado control).\")]),_c('p',[_vm._v(\"Peeeero, para que esto sea realmente posible, tenemos que tomar ciertas precauciones, y entender que al trabajar de esta forma, el resultado sólo se puede obtener dentro de la continuación. Por tanto, el siguiente es un code smell:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" i0 = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\";\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" i1;\\nsuccesor(i0, (resultado) => {\\n i1 = resultado;\\n});\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"//..resto...\")]),_vm._v(\"\\n\")])]),_c('p',[_vm._v(\"Aquí estamos capturando el resultado de successor a través de la continuación, asumiendo que el código se ejecutará inmediatamente y que estará disponible en la línea 6.\")]),_c('p',[_vm._v(\"Pero si es realmente successor quien tiene control sobre cuándo y cómo se ejecuta la continuación, no podemos garantizar esto dado que no sabemos cuándo se va a ejecutar la continuación.\")]),_c('p',[_vm._v(\"¿Esto significa que el código anterior no funciona? No, pero tenemos que entender que estamos rompiendo el modelo de continuación, al no permitir que sea la función successor la que determine cuándo y cómo seguir. Y eso puede ser una fuente de bugs.\")]),_c('h3',{attrs:{\"id\":\"consecuencias\"}},[_vm._v(\"Consecuencias \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#consecuencias\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"En oposición al estilo directo, caracterizado por la obtención de resultados mediante retornos, surge así el estilo de paso de continuaciones (CPS, por sus siglas en inglés). Es decir, cuando tenemos una función que toma una continuación y efectivamente colocamos todo el código que opera con el resultado dentro de la misma, tenemos una función CPS.\")]),_c('p',[_vm._v(\"El CPS es especial porque es fácil introducirlo, pero imposible salir de él, al menos no sin introducir bugs y potenciales problemas en el sistema.\")]),_c('p',[_vm._v(\"Retomando las ideas de nuestro primer episodio, esto es una propiedad interesante: una vez impuesta la arquitectura, no tenemos opción de escapar de ella, lo que nos resta en flexibilidad, pero nos fuerza a ser consistentes.\")]),_c('p',[_vm._v(\"Ejemplo: si ahora queremos implementar una función que incrementa el doble de un número, usando nuestro successor CPS, estaríamos tentados a escribir esto:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"incrementarDoble\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"i\")]),_vm._v(\") \")]),_vm._v(\"{\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" i0 = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"2\")]),_vm._v(\" * i;\\n succesor(i0, \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"resultado\")]),_vm._v(\") \")]),_vm._v(\"{\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" i1 = resultado;\\n ???\\n });\\n}\\n\")])]),_c('p',[_vm._v(\"Y ahí vemos el problema: incrementarDoble debe retornar i1, ¡pero no puede hacerlo, porque no hay garantías de cuando se va a ejecutar la continuación, ni cuantas veces! Por ello, la única alternativa válida (sin basarse en los detalles de implementación de successor, claro), es convertir a incrementarDoble en CPS también:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"incrementarDoble\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"i, cont\")]),_vm._v(\") \")]),_vm._v(\"{\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" i0 = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"2\")]),_vm._v(\" * i;\\n succesor(i0, cont);\\n}\\n\")])]),_c('p',[_vm._v(\"Moraleja: una vez que introducimos CPS, su uso sólo puede extenderse.\")]),_c('blockquote',[_c('p',[_vm._v(\"Esto no significa que no podamos tener computaciones no CPS. Por ejemplo, la multiplicación podría ser extraída como una función en estilo directo. Desarrollaremos esta idea arquitectural mejor en próximos episodios cuando ataquemos el mundo monádico.\")])]),_c('h3',{attrs:{\"id\":\"para-qué-cps\"}},[_vm._v(\"¿Para qué CPS? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#para-qué-cps\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Resulta bastante evidente que razonar sobre CPS es más complejo que en el estilo directo. Entonces, ¿por qué habríamos de adoptarlo?\")]),_c('p',[_vm._v(\"CPS, al otorgarle a la función no sólo capacidad de cómputo sino de control, permite hacer cosas muy poderosas. En los ejemplos anteriores no lo aprovechamos, porque la computación succesor puede ser modelada con una función con un sólo resultado posible:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_vm._v(\"\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"succesor\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"x, cont\")]),_vm._v(\") \")]),_vm._v(\"{\\n cont(x + \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\");\\n}\\n\")])]),_c('p',[_vm._v(\"Pero sin embargo, podríamos haber aplicado a la función cont cero (1) o muchas veces (2), podríamos haber recibido múltiples continuaciones y ejecutar alguna de ellas (3), o podríamos haberlas ejecutado en otro momento (4). CPS nos permite, entones, implementar 4 tipos de computaciones: con falla, no determinísticas, con excepciones y asincrónicas.\")]),_c('blockquote',[_c('p',[_vm._v(\"Recordar estos tipos de continuaciones, volverán en episodios futuros\")])]),_c('h3',{attrs:{\"id\":\"falla\"}},[_vm._v(\"Falla \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#falla\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Con CPS podemos codificar computaciones que pueden no tener resultado (los matemáticos las llaman funciones parciales). Por ejemplo, la división es una función parcial que no tiene un resultado cuando su segundo argumento es cero, por lo que podemos definir una función inversa CPS de la siguiente forma:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"inversa\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"x, cont\")]),_vm._v(\") \")]),_vm._v(\"{\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"if\")]),_vm._v(\" (x !== \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\") {\\n cont(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\"/x);\\n }\\n}\\n\")])]),_c('p',[_vm._v(\"Si ahora aplicamos a inversa con el valor 2, tendremos como resultado 0.5. Pero si la aplicamos con 0, no tendremos resultado. Esto no es lo mismo que no devolver nada en una función en estilo directo (o devolver null): en una función CPS que puede fallar, si no hay resultado, el programa continuación NO continúa; el flujo de ejecución se detiene.\")]),_c('h3',{attrs:{\"id\":\"no-determinismo\"}},[_vm._v(\"No determinismo. \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#no-determinismo\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Hay computaciones que pueden arrojar cero o más resultados, son la generalización de la función: la relación. Por ejemplo, la pregunta ¿quien es hijo de Vito Corleone? (notá el singular) tiene múltiples respuestas: Sonny, Michel, Connie, etc. Esta es la base del paradigma lógico: relaciones que pueden generar ningún resultado, uno, o varios.\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"hijoDeVito\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"cont\")]),_vm._v(\") \")]),_vm._v(\"{\\n cont(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"\\\"sonny\\\"\")]),_vm._v(\");\\n cont(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"\\\"michel\\\"\")]),_vm._v(\");\\n cont(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"\\\"connie\\\"\")]),_vm._v(\");\\n cont(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"\\\"freddo\\\"\")]),_vm._v(\");\\n}\\n\")])]),_c('p',[_vm._v(\"Se observa fácilmente que logramos las múltiples respuestas mediante la aplicación reiterada de la continuación: el mismo programa está continuando múltiples veces con argumento diferentes.\")]),_c('p',[_vm._v(\"CPS no nos da una restriccion sobre la cantidad de veces a las que se deba llamar la continuacion que recibe. Por lo que vamos a poder aplicar la continuacion 0 o múltiples veces.\")]),_c('p',[_vm._v(\"Tal vez el ejemplo de recien no fue tan convincente.... bueno tenemos el ejemplo mas basico que podemos encontrar en la documentacion de Node.js:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"const\")]),_vm._v(\" http = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"require\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'http'\")]),_vm._v(\");\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"const\")]),_vm._v(\" hostname = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'127.0.0.1'\")]),_vm._v(\";\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"const\")]),_vm._v(\" port = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"3000\")]),_vm._v(\";\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"const\")]),_vm._v(\" server = http.createServer(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"req, res\")]),_vm._v(\") =>\")]),_vm._v(\" {\\n res.statusCode = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"200\")]),_vm._v(\";\\n res.setHeader(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'Content-Type'\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'text/plain'\")]),_vm._v(\");\\n res.end(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'Hello World'\")]),_vm._v(\");\\n});\\n\\nserver.listen(port, hostname, () => {\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"console\")]),_vm._v(\".log(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"`Server running at http://\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-subst\"}},[_vm._v(\"${hostname}\")]),_vm._v(\":\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-subst\"}},[_vm._v(\"${port}\")]),_vm._v(\"/`\")]),_vm._v(\");\\n});\\n\")])]),_c('blockquote',[_c('p',[_vm._v(\"Shamelessly taken from \"),_c('a',{attrs:{\"href\":\"https://nodejs.org/ca/docs/guides/getting-started-guide/\"}},[_vm._v(\"here\")])])]),_c('p',[_vm._v(\"Este pequeño ejemplo nos muestra claramente el no determinismo, porque es un servidor que podemos levantar, y nunca vamos a saber cuantos request nos van a llegar al servidor durante el tiempo que este levantado, tal vez recibimos 28392389 requests, tal vez 0.\")]),_c('h3',{attrs:{\"id\":\"excepciones\"}},[_vm._v(\"Excepciones \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#excepciones\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Todos conocemos las excepciones. Estas nos dan dos flujos de ejecución: uno de éxito y uno de fracaso, y en ambos hay resultados: el resultado normal del programa o el error en cuestión. Y esto lo podemos lograr pasando dos continaciones: la que contiene el flujo normal, y la que contiene el flujo de error.\")]),_c('h3',{attrs:{\"id\":\"computaciones-asincrónicas\"}},[_vm._v(\"Computaciones asincrónicas. \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#computaciones-asincrónicas\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"¡Éstas son las que más nos interesan! Operaciones que quizás no se ejecuten inmediatamente, sino en un momento posterior. Más sobre esto, en breve.\")]),_c('h3',{attrs:{\"id\":\"cps-y-callback-hell\"}},[_vm._v(\"CPS, ¿y Callback Hell? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#cps-y-callback-hell\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Un pequeño paréntesis: se suele achacar al uso de CPS la inevitable caída en el callback hell. Por ejemplo:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" cuentaLoca = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"x, cont\")]),_vm._v(\") \")]),_vm._v(\"{ \\n siguiente(x, \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"y\")]),_vm._v(\")\")]),_vm._v(\"{\\n inversa(y, \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"z\")]),_vm._v(\")\")]),_vm._v(\"{\\n duplicar(z, cont);\\n })\\n })\\n};\\n\")])]),_c('p',[_vm._v(\"Como se observa, algo tan simple en estilo directo como\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_vm._v(\"duplicar(inversa(siguiente(x))) \\n\")])]),_c('p',[_vm._v(\"se convierte en una compleja estructura de continuaciones anidadas. ¿Podríamos delegar esto de mejor forma? Si analizamos cómo queda expresada esta computación en estilo directo, podemos ver que duplicar la inversa del siguiente, a fin de cuentas, está describiendo una composición de funciones: al resultado de aplicar una función se le pasa a la entrada la otra. Obviamente, no es la misma composición de funciones que conocemos en estilo directo: es una composición CPS. Y entender esto nos permite definir una función componer, que haga justamente esto:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"componer\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"f, g\")]),_vm._v(\") \")]),_vm._v(\"{\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"return\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"x, cont\")]),_vm._v(\") \")]),_vm._v(\"{\\n g(x, \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"y\")]),_vm._v(\")\")]),_vm._v(\"{\\n f(y, cont);\\n })\\n }\\n }\\n\")])]),_c('p',[_vm._v(\"y una vez que tenemos eso podemos ya utilizarla así:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" cuentaLoca = componer(duplicar, componer(inversa, siguiente))\\n\")])]),_c('p',[_vm._v(\"Y si le damos una vuelta de tuerca más, podemos observar que estamos ante la estructura de aplicación de un fold, y definir una función pipeline que componga todas las funciones cps\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"function\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"pipeline\")]),_vm._v(\"(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"fs\")]),_vm._v(\") \")]),_vm._v(\"{\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"return\")]),_vm._v(\" fs.reduce(componer);\\n }\\n\")])]),_c('p',[_vm._v(\"Con este pipeline podemos reutilizar el componer aplicandole un fold sobre un array y de esta manera que se puedan componer todas las funciones que tenemos sin caer de nuevo en el Callback Hell:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-javascript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" cuentaLoca = pipeline([duplicar, inversa, siguiente]);\\n\")])]),_c('p',[_vm._v(\"Y así vemos como eliminar el callback hell, aun con CPS, es posible. Moraleja: no es culpa del CPS, es culpa nuestra al no delegar convenientemente.\")]),_c('h3',{attrs:{\"id\":\"conclusiones\"}},[_vm._v(\"Conclusiones \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#conclusiones\"}},[_vm._v(\"¶\")])]),_c('ul',[_c('li',[_vm._v(\"CPS nos da gran poder, pero es difícil de manejar adecuadamente\")]),_c('li',[_vm._v(\"CPS nos lleva, si no tenemos cuidado al callback hell. Sin embargo, no es inherente a CPS, sino que es consecuencia de una mala delegación. Es posible resolverlo si se delega apropiadamente y aplicando los conceptos de programación funcional de orden superior y creando combinadores apropiados\")]),_c('li',[_vm._v(\"CPS nos permite implementar computaciones asincrónicas. NodeJS emplea CPS para soportarlas.\")]),_c('li',[_vm._v(\"El uso de CPS en NodeJS: pésimo manejo de errores y ausencia de abstracciones para hacerlo mas tratable. Por eso es que la comunidad centró su atención en otra forma de estructurar programas con influencias funcionales: las promesas (promises).\")])])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./cps.md?vue&type=template&id=ef5b4632&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-33c3e200.a3963baa.js b/js/chunk-33c3e200.a3963baa.js new file mode 100644 index 0000000..2f74d0e --- /dev/null +++ b/js/chunk-33c3e200.a3963baa.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-33c3e200"],{"377f":function(e,a,s){e.exports=s.p+"img/node-system.391f5210.png"},4976:function(e,a,s){e.exports=s.p+"img/basic-event-loop.8b8923fb.png"},"599b":function(e,a,s){e.exports=s.p+"img/complete-event-loop.b59ad9a8.png"},bc00:function(e,a,s){e.exports=s.p+"img/v8.826badb9.png"},c3c4:function(e,a,s){"use strict";s.r(a);var o=function(){var e=this,a=e.$createElement;e._self._c;return e._m(0)},n=[function(){var e=this,a=e.$createElement,o=e._self._c||a;return o("section",[o("h2",{attrs:{id:"introducción"}},[e._v("Introducción "),o("a",{staticClass:"header-anchor",attrs:{href:"#introducción"}},[e._v("¶")])]),o("p",[e._v("El "),o("strong",[e._v("event loop")]),e._v(" es la forma que usa Node.js para "),o("strong",[e._v("organizar el procesamiento del código")]),e._v(".")]),o("p",[e._v("Para poder profundizar en el event loop debemos entender de forma high level qué es la V8 y qué relación tiene con Node.")]),o("p",[e._v("V8, de forma muy básica, podemos definirlo como uno de los motores de JavaScript que interpreta y ejecuta código Js. Todos los browsers contienen un motor Js: V8 es el creado por Google (Firefox usa el propio llamado SpiderMonkey).")]),o("p",[e._v("V8 de alguna forma permitía una interpretación mucho más rápida de JavaScript de los navegadores, esto gracias a la combinación del uso del intérprete y el compilador.")]),o("p",[e._v("Ryah Dahll, como explica en la presentación de "),o("a",{attrs:{href:"https://www.youtube.com/watch?v=ztspvPYybIY&t=1s"}},[e._v("JsConf")]),e._v(", consigue crear servidores web para las necesidades actuales haciendo que la V8 funcione por fuera del navegador, es decir, en el sistema operativo.")]),o("p",[e._v("Motor V8 de JavaScript:")]),o("ul",[o("li",[e._v("Posee dos componentes principales: "),o("ul",[o("li",[e._v("Heap: Aloca variables, funciones y estructuras.")]),o("li",[e._v("Call Stack: Permite el anidamiento de llamadas.")])])]),o("li",[e._v("Existe un bucle de ejecución")])]),o("img",{staticClass:"center iasc-image",attrs:{src:s("bc00")}}),o("p",[e._v("El bucle que anteriormente nombramos es el EVENT LOOP y es quien nos permite manejar la concurrencia de eventos. ¿Qué es un evento? Pequeñas funcionalidades/funciones que vamos a ejecutar a lo largo del tiempo.")]),o("p",[o("strong",[e._v("Tiene un modelo de concurrencia orientado a EVENTOS.")])]),o("h3",{attrs:{id:"qué-es-node"}},[e._v("¿Qué es Node? "),o("a",{staticClass:"header-anchor",attrs:{href:"#qué-es-node"}},[e._v("¶")])]),o("p",[o("cite",{attrs:{cite:"Node.js Documentation"}},[e._v("As an asynchronous event-driven JavaScript runtime, Node.js is designed to build scalable network applications")])]),o("p",[e._v("Ejemplo en Node de un contador:")]),o("pre",{pre:!0},[o("code",{pre:!0,attrs:{"v-pre":"",class:"language-JavaScript"}},[o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" a = "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v(";\n\n"),o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("for")]),e._v(" ("),o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("let")]),e._v(" i = "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v("; i < "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("10000")]),e._v("; i++) {\n setImmediate("),o("span",{pre:!0,attrs:{class:"hljs-function"}},[o("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(" =>")]),e._v(" a +="),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(");\n}\n"),o("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("console")]),e._v(".log(a);\n")])]),o("p",[o("strong",[e._v("¿Qué hace el código?")]),e._v(" En una primera instancia podemos pensar que en "),o("code",{pre:!0},[e._v("a")]),e._v(" se incrementa uno a uno y luego imprimimos la variable con 10000.")]),o("p",[e._v("¿Qué pensamos que hace el "),o("code",{pre:!0},[e._v("setImmediate")]),e._v("? ¿Lo ejecuta inmediatamente?")]),o("p",[e._v("El "),o("code",{pre:!0},[e._v("immediate")]),e._v(" lo que hace es generar un evento, es decir, se generan eventos que se van ejecutando en el bucle de event loop.")]),o("p",[e._v("Si lo ejecutamos, vamos a notar que imprime 0.")]),o("p",[o("strong",[e._v("¿Qué pasó?")])]),o("p",[e._v("Los eventos, a diferencia de las "),o("code",{pre:!0},[e._v("corutinas")]),e._v(", se planifican automáticamente, tenemos como ventaja el poder delegar esos detalles, ya que el modelo está más implícito.")]),o("p",[o("strong",[e._v("Cada evento es un contexto de ejecución distinto.")]),e._v(" Nuestra pregunta puede ser ¿cuándo se produce un cambio de contexto?")]),o("p",[e._v("En el ejemplo del contador, podemos decir que encolamos 10000 veces ese evento y nos da la sensación que estas son llamadas "),o("em",[e._v("sincrónicas")]),e._v(", pero realmente esto no pasa. Por atrás tenemos un elemento que nos permite de alguna forma multiplexar, hacer que el IO que es sincrónico no lo sea.")]),o("p",[e._v("Las interrupciones una vez que llegan, se ejecutan inmediatamente.")]),o("h3",{attrs:{id:"primer-acercamiento-al-evento-loop-high-level"}},[e._v("Primer acercamiento al evento loop - High level "),o("a",{staticClass:"header-anchor",attrs:{href:"#primer-acercamiento-al-evento-loop-high-level"}},[e._v("¶")])]),o("p",[e._v("Podemos pensar que el event loop es un bucle simple en donde los eventos se van ejecutando hasta que en un momento termina.")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("4976")}}),o("p",[e._v("¿Qué pasa si a nuestro anterior ejemplo agrego un "),o("code",{pre:!0},[e._v("console.log")]),e._v(" dentro de otro "),o("code",{pre:!0},[e._v("setImmediate()")]),e._v("?")]),o("pre",{pre:!0},[o("code",{pre:!0,attrs:{"v-pre":"",class:"language-JavaScript"}},[o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" a = "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v(";\n\n"),o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("for")]),e._v(" ("),o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("let")]),e._v(" i = "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v("; i < "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("10000")]),e._v("; i++) {\n setImmediate("),o("span",{pre:!0,attrs:{class:"hljs-function"}},[o("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(" =>")]),e._v(" a +="),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(");\n}\nsetImmediate("),o("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("console")]),e._v(".log(a));\n")])]),o("p",[e._v("Alternativas:")]),o("ul",[o("li",[e._v("Log con 10000")]),o("li",[e._v("Log con 0")]),o("li",[e._v("Resultados no determinísticos.")])]),o("p",[o("strong",[e._v("Realidad")]),e._v(": Si lo ejecuto me termina dando 10000, aparentemente se encolan y se van ejecutando en el orden correcto.")]),o("p",[e._v("¿Por qué sucede esto?")]),o("p",[e._v("El event loop es una especie de bucle que tiene varias etapas, y tienen algunas ya prefijadas")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("599b")}}),o("p",[e._v("Son pequeñas etapas, y por cada uno de estos ciclos va a procesar eventos de diferentes naturalezas. El orden de estos ciclos es determinístico.")]),o("p",[e._v("A la cajita de Js, podemos interpretarlas como el código de Js principal de nuestra app.")]),o("p",[e._v("Cambiando un poco el ejemplo")]),o("pre",{pre:!0},[o("code",{pre:!0,attrs:{"v-pre":"",class:"language-JavaScript"}},[o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("var")]),e._v(" a = "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v(";\n\n"),o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("for")]),e._v(" ("),o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("let")]),e._v(" i = "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v("; i < "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("10000")]),e._v("; i++) {\n setImmediate("),o("span",{pre:!0,attrs:{class:"hljs-function"}},[o("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v(" =>")]),e._v(" a +="),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(");\n}\nsetTimeout("),o("span",{pre:!0,attrs:{class:"hljs-function"}},[o("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("()")]),e._v("=>")]),e._v(" {\n "),o("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("console")]),e._v(".log("),o("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'Dentro del timeout'")]),e._v(");\n "),o("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("console")]),e._v(".log(a);\n}, "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("3300")]),e._v(");\n\n"),o("span",{pre:!0,attrs:{class:"hljs-built_in"}},[e._v("console")]),e._v(".log(a);\n")])]),o("p",[e._v("Si ejecuto este código me da 0.")]),o("p",[e._v("Esto sucede ya que se lee todo el código, y el resto de los eventos se planifica después.")]),o("p",[e._v("El bucle se ejecuta en un tiempo específico por lo cual se le asigna una cantidad determinada de tiempo a cada una de sus etapas, justamente porque estamos corriendo sobre solo un thread, en consecuencia solo lo podemos planificar en un solo procesador.")]),o("p",[o("strong",[e._v("¿Qué pasa si en alguna de esas cajitas de Js tenemos una ejecución CPU Intensive?")])]),o("p",[e._v("El sistema operativo ve a Node como un solo thread. Tanto lo CPU intensive como elementos sincronicos pueden hacer que todas las fases se demoren y bloqueen. Este thread tiene una política de no desalojo de la ejecución si la misma es de código Js, por más que se asignen pequeñas porciones de tiempo a cada etapa del event loop si tenemos elemento que bloquean la CPU, no nos permite que el schedule pueda correr y dar paso a la nueva etapa.")]),o("p",[o("cite",{attrs:{cite:"What is the event loop"}},[e._v("The event loop is what allows Node.js to perform non-blocking I/O operations — despite the fact that JavaScript is single-threaded — by offloading operations to the system kernel whenever possible")])]),o("h3",{attrs:{id:"componentes-de-nuestro-sistema-nodejs"}},[e._v("Componentes de nuestro sistema Node.js "),o("a",{staticClass:"header-anchor",attrs:{href:"#componentes-de-nuestro-sistema-nodejs"}},[e._v("¶")])]),o("img",{staticClass:"center iasc-image",attrs:{src:s("377f")}}),o("p",[e._v("Podemos observar que tiene una queue de eventos general que el event loop va a ir tratando.")]),o("p",[o("a",{attrs:{href:"https://github.com/libuv/libuv"}},[e._v("libuv")]),e._v(": Es una lib que nos permite wrappear las llamadas bloqueantes en no bloqueantes, esto puede lograrse a través de los llamados worker threads. Estos van a ejecutar estas llamadas y una vez que las terminen de tratar mediante el callback vuelven evento entrando el event queue. Esta lib va a tratar todas las operaciones bloqueantes como pueden ser escuchar un puerto, leer archivos, entre otras operaciones.")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("599b")}}),o("p",[e._v("¿Cómo serian los pasos de nuestro event loop?")]),o("ul",[o("li",[e._v("Escaneo de nuestro código principal (index.js) "),o("ul",[o("li",[e._v("Ejecuta todas las operaciones que se puedan ejecutar inmediatamente.")]),o("li",[e._v("Si en el index detecta eventos (continuaciones, operaciones asincrónicas u operaciones IO) los atiende después, es decir, los encola.")])])]),o("li",[e._v("Terminada la lectura del index, comienza a ciclar por una secuencia bien definida. Atiende timeouts, IO, de red, immediate y eventos de cierre de recursos. "),o("ul",[o("li",[e._v("En esta etapa existen microqueues (Js) donde se fija si existen eventos encolados que están listos para ser procesados, y los ejecuta. (**1)")])])]),o("li",[e._v("Si no tiene más nada que ejecutar, termina el ciclo y la ejecución, caso contrario, arranca nuevamente el ciclo.")])]),o("p",[e._v("(**1) Es una cola de tareas que los worker threads van tomando desde ese punto y cuando está listo ese procesamiento vuelve a encolar en la cola de eventos del event loop.")]),o("p",[o("strong",[e._v("IMPORTANTE")]),e._v(": No debemos bloquear el event loop")]),o("p",[e._v("Si tengo operaciones CPU intensive debemos considerar:")]),o("ul",[o("li",[o("em",[e._v("Partitioning")]),e._v(".")]),o("li",[o("em",[e._v("Offloading")]),e._v(".")]),o("li",[e._v("Uso de funciones de worker threads.")])]),o("p",[e._v("Lo que en nuestro gráfico simplificado nombramos como "),o("em",[e._v("función unicornio")]),e._v(" (este es un nombre inventado por nosotros, no existe tal nomenclatura) permite aprovechar funciones del sistema operativo, es una especie de listener el cual cuando se termina de procesar un elemento o existen nuevos eventos, dicha función puede ser de nexo e informar cuando suceden estas cosas. (libuv y SO).")]),o("h2",{attrs:{id:"resumen-de-event-loop"}},[e._v("Resumen de event loop "),o("a",{staticClass:"header-anchor",attrs:{href:"#resumen-de-event-loop"}},[e._v("¶")])]),o("ul",[o("li",[e._v("Forma de organizar el procesamiento del código en Node.js.")]),o("li",[e._v("Se basa en procesamiento concurrente de código Js con un solo thread, con no-desalojo para código Js.")]),o("li",[e._v("Tiene tres pasos "),o("ul",[o("li",[e._v("Escanea el index, donde ejecuta todo el código que se pueda ejecutar inmediatamente, encolando continuations, IO, etc.")]),o("li",[e._v("Terminado el escaneo, itera en la siguiente secuencia, teniendo microqueues donde revisa si existen eventos preparados para ser ejecutados, y los ejecuta. "),o("ul",[o("li",[e._v("Atiende operaciones asincrónicas, timeouts")]),o("li",[e._v("IO y redes")]),o("li",[e._v("immediate")]),o("li",[e._v("eventos de cierra de recursos")])])]),o("li",[e._v("Si no tiene más que ejecutar, cierra la ejecución, caso contrario, vuelve a retomar el ciclo.")])])]),o("li",[e._v("Tiene 1 hilo, pero n workers que se encargan de ejecutar las tareas pesadas.")])]),o("h3",{attrs:{id:"referencias"}},[e._v("Referencias "),o("a",{staticClass:"header-anchor",attrs:{href:"#referencias"}},[e._v("¶")])]),o("ul",[o("li",[o("a",{attrs:{href:"https://www.youtube.com/watch?v=PNa9OMajw9w"}},[e._v("Morning Keynote- Everything You Need to Know About Node.js Event Loop - Bert Belder, IBM")])]),o("li",[o("a",{attrs:{href:"https://www.youtube.com/watch?v=ztspvPYybIY&t=1s"}},[e._v("Ryan Dahl: Original Node.js presentation - JsConf")])]),o("li",[o("a",{attrs:{href:"https://www.youtube.com/watch?v=_c51fcXRLGw"}},[e._v("Introduction to libuv: What's a Unicorn Velociraptor? - Colin Ihrig, Joyent")])]),o("li",[o("a",{attrs:{href:"https://nodejs.org/en/docs/guides/dont-block-the-event-loop/"}},[e._v("Don't Block the Event Loop (or the Worker Pool)")])]),o("li",[o("a",{attrs:{href:"https://nodejs.dev/learn"}},[e._v("Introduction to Node.js")])]),o("li",[o("a",{attrs:{href:"https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#what-is-the-event-loop"}},[e._v("What is the event loop")])])])])}],t=s("2877"),r={},i=Object(t["a"])(r,o,n,!1,null,null,null);a["default"]=i.exports}}]); +//# sourceMappingURL=chunk-33c3e200.a3963baa.js.map \ No newline at end of file diff --git a/js/chunk-33c3e200.a3963baa.js.map b/js/chunk-33c3e200.a3963baa.js.map new file mode 100644 index 0000000..3de7986 --- /dev/null +++ b/js/chunk-33c3e200.a3963baa.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/images/eventloop/node-system.png","webpack:///./src/images/eventloop/basic-event-loop.png","webpack:///./src/images/eventloop/complete-event-loop.png","webpack:///./src/images/eventloop/v8.png","webpack:///./src/content/event_loop.md?c7b7","webpack:///./src/content/event_loop.md"],"names":["module","exports","render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","pre","script","component"],"mappings":"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","file":"js/chunk-33c3e200.a3963baa.js","sourcesContent":["module.exports = __webpack_public_path__ + \"img/node-system.391f5210.png\";","module.exports = __webpack_public_path__ + \"img/basic-event-loop.8b8923fb.png\";","module.exports = __webpack_public_path__ + \"img/complete-event-loop.b59ad9a8.png\";","module.exports = __webpack_public_path__ + \"img/v8.826badb9.png\";","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h2',{attrs:{\"id\":\"introducción\"}},[_vm._v(\"Introducción \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#introducción\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"El \"),_c('strong',[_vm._v(\"event loop\")]),_vm._v(\" es la forma que usa Node.js para \"),_c('strong',[_vm._v(\"organizar el procesamiento del código\")]),_vm._v(\".\")]),_c('p',[_vm._v(\"Para poder profundizar en el event loop debemos entender de forma high level qué es la V8 y qué relación tiene con Node.\")]),_c('p',[_vm._v(\"V8, de forma muy básica, podemos definirlo como uno de los motores de JavaScript que interpreta y ejecuta código Js. Todos los browsers contienen un motor Js: V8 es el creado por Google (Firefox usa el propio llamado SpiderMonkey).\")]),_c('p',[_vm._v(\"V8 de alguna forma permitía una interpretación mucho más rápida de JavaScript de los navegadores, esto gracias a la combinación del uso del intérprete y el compilador.\")]),_c('p',[_vm._v(\"Ryah Dahll, como explica en la presentación de \"),_c('a',{attrs:{\"href\":\"https://www.youtube.com/watch?v=ztspvPYybIY&t=1s\"}},[_vm._v(\"JsConf\")]),_vm._v(\", consigue crear servidores web para las necesidades actuales haciendo que la V8 funcione por fuera del navegador, es decir, en el sistema operativo.\")]),_c('p',[_vm._v(\"Motor V8 de JavaScript:\")]),_c('ul',[_c('li',[_vm._v(\"Posee dos componentes principales: \"),_c('ul',[_c('li',[_vm._v(\"Heap: Aloca variables, funciones y estructuras.\")]),_c('li',[_vm._v(\"Call Stack: Permite el anidamiento de llamadas.\")])])]),_c('li',[_vm._v(\"Existe un bucle de ejecución\")])]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/eventloop/v8.png\")}}),_c('p',[_vm._v(\"El bucle que anteriormente nombramos es el EVENT LOOP y es quien nos permite manejar la concurrencia de eventos. ¿Qué es un evento? Pequeñas funcionalidades/funciones que vamos a ejecutar a lo largo del tiempo.\")]),_c('p',[_c('strong',[_vm._v(\"Tiene un modelo de concurrencia orientado a EVENTOS.\")])]),_c('h3',{attrs:{\"id\":\"qué-es-node\"}},[_vm._v(\"¿Qué es Node? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#qué-es-node\"}},[_vm._v(\"¶\")])]),_c('p',[_c('cite',{attrs:{\"cite\":\"Node.js Documentation\"}},[_vm._v(\"As an asynchronous event-driven JavaScript runtime, Node.js is designed to build scalable network applications\")])]),_c('p',[_vm._v(\"Ejemplo en Node de un contador:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-JavaScript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" a = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\";\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"for\")]),_vm._v(\" (\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"let\")]),_vm._v(\" i = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\"; i < \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"10000\")]),_vm._v(\"; i++) {\\n setImmediate(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\" =>\")]),_vm._v(\" a +=\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\");\\n}\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"console\")]),_vm._v(\".log(a);\\n\")])]),_c('p',[_c('strong',[_vm._v(\"¿Qué hace el código?\")]),_vm._v(\" En una primera instancia podemos pensar que en \"),_c('code',{pre:true},[_vm._v(\"a\")]),_vm._v(\" se incrementa uno a uno y luego imprimimos la variable con 10000.\")]),_c('p',[_vm._v(\"¿Qué pensamos que hace el \"),_c('code',{pre:true},[_vm._v(\"setImmediate\")]),_vm._v(\"? ¿Lo ejecuta inmediatamente?\")]),_c('p',[_vm._v(\"El \"),_c('code',{pre:true},[_vm._v(\"immediate\")]),_vm._v(\" lo que hace es generar un evento, es decir, se generan eventos que se van ejecutando en el bucle de event loop.\")]),_c('p',[_vm._v(\"Si lo ejecutamos, vamos a notar que imprime 0.\")]),_c('p',[_c('strong',[_vm._v(\"¿Qué pasó?\")])]),_c('p',[_vm._v(\"Los eventos, a diferencia de las \"),_c('code',{pre:true},[_vm._v(\"corutinas\")]),_vm._v(\", se planifican automáticamente, tenemos como ventaja el poder delegar esos detalles, ya que el modelo está más implícito.\")]),_c('p',[_c('strong',[_vm._v(\"Cada evento es un contexto de ejecución distinto.\")]),_vm._v(\" Nuestra pregunta puede ser ¿cuándo se produce un cambio de contexto?\")]),_c('p',[_vm._v(\"En el ejemplo del contador, podemos decir que encolamos 10000 veces ese evento y nos da la sensación que estas son llamadas \"),_c('em',[_vm._v(\"sincrónicas\")]),_vm._v(\", pero realmente esto no pasa. Por atrás tenemos un elemento que nos permite de alguna forma multiplexar, hacer que el IO que es sincrónico no lo sea.\")]),_c('p',[_vm._v(\"Las interrupciones una vez que llegan, se ejecutan inmediatamente.\")]),_c('h3',{attrs:{\"id\":\"primer-acercamiento-al-evento-loop-high-level\"}},[_vm._v(\"Primer acercamiento al evento loop - High level \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#primer-acercamiento-al-evento-loop-high-level\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Podemos pensar que el event loop es un bucle simple en donde los eventos se van ejecutando hasta que en un momento termina.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/eventloop/basic-event-loop.png\")}}),_c('p',[_vm._v(\"¿Qué pasa si a nuestro anterior ejemplo agrego un \"),_c('code',{pre:true},[_vm._v(\"console.log\")]),_vm._v(\" dentro de otro \"),_c('code',{pre:true},[_vm._v(\"setImmediate()\")]),_vm._v(\"?\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-JavaScript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" a = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\";\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"for\")]),_vm._v(\" (\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"let\")]),_vm._v(\" i = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\"; i < \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"10000\")]),_vm._v(\"; i++) {\\n setImmediate(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\" =>\")]),_vm._v(\" a +=\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\");\\n}\\nsetImmediate(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"console\")]),_vm._v(\".log(a));\\n\")])]),_c('p',[_vm._v(\"Alternativas:\")]),_c('ul',[_c('li',[_vm._v(\"Log con 10000\")]),_c('li',[_vm._v(\"Log con 0\")]),_c('li',[_vm._v(\"Resultados no determinísticos.\")])]),_c('p',[_c('strong',[_vm._v(\"Realidad\")]),_vm._v(\": Si lo ejecuto me termina dando 10000, aparentemente se encolan y se van ejecutando en el orden correcto.\")]),_c('p',[_vm._v(\"¿Por qué sucede esto?\")]),_c('p',[_vm._v(\"El event loop es una especie de bucle que tiene varias etapas, y tienen algunas ya prefijadas\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/eventloop/complete-event-loop.png\")}}),_c('p',[_vm._v(\"Son pequeñas etapas, y por cada uno de estos ciclos va a procesar eventos de diferentes naturalezas. El orden de estos ciclos es determinístico.\")]),_c('p',[_vm._v(\"A la cajita de Js, podemos interpretarlas como el código de Js principal de nuestra app.\")]),_c('p',[_vm._v(\"Cambiando un poco el ejemplo\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-JavaScript\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"var\")]),_vm._v(\" a = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\";\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"for\")]),_vm._v(\" (\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"let\")]),_vm._v(\" i = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\"; i < \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"10000\")]),_vm._v(\"; i++) {\\n setImmediate(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\" =>\")]),_vm._v(\" a +=\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\");\\n}\\nsetTimeout(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"()\")]),_vm._v(\"=>\")]),_vm._v(\" {\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"console\")]),_vm._v(\".log(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'Dentro del timeout'\")]),_vm._v(\");\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"console\")]),_vm._v(\".log(a);\\n}, \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"3300\")]),_vm._v(\");\\n\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-built_in\"}},[_vm._v(\"console\")]),_vm._v(\".log(a);\\n\")])]),_c('p',[_vm._v(\"Si ejecuto este código me da 0.\")]),_c('p',[_vm._v(\"Esto sucede ya que se lee todo el código, y el resto de los eventos se planifica después.\")]),_c('p',[_vm._v(\"El bucle se ejecuta en un tiempo específico por lo cual se le asigna una cantidad determinada de tiempo a cada una de sus etapas, justamente porque estamos corriendo sobre solo un thread, en consecuencia solo lo podemos planificar en un solo procesador.\")]),_c('p',[_c('strong',[_vm._v(\"¿Qué pasa si en alguna de esas cajitas de Js tenemos una ejecución CPU Intensive?\")])]),_c('p',[_vm._v(\"El sistema operativo ve a Node como un solo thread. Tanto lo CPU intensive como elementos sincronicos pueden hacer que todas las fases se demoren y bloqueen. Este thread tiene una política de no desalojo de la ejecución si la misma es de código Js, por más que se asignen pequeñas porciones de tiempo a cada etapa del event loop si tenemos elemento que bloquean la CPU, no nos permite que el schedule pueda correr y dar paso a la nueva etapa.\")]),_c('p',[_c('cite',{attrs:{\"cite\":\"What is the event loop\"}},[_vm._v(\"The event loop is what allows Node.js to perform non-blocking I/O operations — despite the fact that JavaScript is single-threaded — by offloading operations to the system kernel whenever possible\")])]),_c('h3',{attrs:{\"id\":\"componentes-de-nuestro-sistema-nodejs\"}},[_vm._v(\"Componentes de nuestro sistema Node.js \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#componentes-de-nuestro-sistema-nodejs\"}},[_vm._v(\"¶\")])]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/eventloop/node-system.png\")}}),_c('p',[_vm._v(\"Podemos observar que tiene una queue de eventos general que el event loop va a ir tratando.\")]),_c('p',[_c('a',{attrs:{\"href\":\"https://github.com/libuv/libuv\"}},[_vm._v(\"libuv\")]),_vm._v(\": Es una lib que nos permite wrappear las llamadas bloqueantes en no bloqueantes, esto puede lograrse a través de los llamados worker threads. Estos van a ejecutar estas llamadas y una vez que las terminen de tratar mediante el callback vuelven evento entrando el event queue. Esta lib va a tratar todas las operaciones bloqueantes como pueden ser escuchar un puerto, leer archivos, entre otras operaciones.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/eventloop/complete-event-loop.png\")}}),_c('p',[_vm._v(\"¿Cómo serian los pasos de nuestro event loop?\")]),_c('ul',[_c('li',[_vm._v(\"Escaneo de nuestro código principal (index.js) \"),_c('ul',[_c('li',[_vm._v(\"Ejecuta todas las operaciones que se puedan ejecutar inmediatamente.\")]),_c('li',[_vm._v(\"Si en el index detecta eventos (continuaciones, operaciones asincrónicas u operaciones IO) los atiende después, es decir, los encola.\")])])]),_c('li',[_vm._v(\"Terminada la lectura del index, comienza a ciclar por una secuencia bien definida. Atiende timeouts, IO, de red, immediate y eventos de cierre de recursos. \"),_c('ul',[_c('li',[_vm._v(\"En esta etapa existen microqueues (Js) donde se fija si existen eventos encolados que están listos para ser procesados, y los ejecuta. (**1)\")])])]),_c('li',[_vm._v(\"Si no tiene más nada que ejecutar, termina el ciclo y la ejecución, caso contrario, arranca nuevamente el ciclo.\")])]),_c('p',[_vm._v(\"(**1) Es una cola de tareas que los worker threads van tomando desde ese punto y cuando está listo ese procesamiento vuelve a encolar en la cola de eventos del event loop.\")]),_c('p',[_c('strong',[_vm._v(\"IMPORTANTE\")]),_vm._v(\": No debemos bloquear el event loop\")]),_c('p',[_vm._v(\"Si tengo operaciones CPU intensive debemos considerar:\")]),_c('ul',[_c('li',[_c('em',[_vm._v(\"Partitioning\")]),_vm._v(\".\")]),_c('li',[_c('em',[_vm._v(\"Offloading\")]),_vm._v(\".\")]),_c('li',[_vm._v(\"Uso de funciones de worker threads.\")])]),_c('p',[_vm._v(\"Lo que en nuestro gráfico simplificado nombramos como \"),_c('em',[_vm._v(\"función unicornio\")]),_vm._v(\" (este es un nombre inventado por nosotros, no existe tal nomenclatura) permite aprovechar funciones del sistema operativo, es una especie de listener el cual cuando se termina de procesar un elemento o existen nuevos eventos, dicha función puede ser de nexo e informar cuando suceden estas cosas. (libuv y SO).\")]),_c('h2',{attrs:{\"id\":\"resumen-de-event-loop\"}},[_vm._v(\"Resumen de event loop \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#resumen-de-event-loop\"}},[_vm._v(\"¶\")])]),_c('ul',[_c('li',[_vm._v(\"Forma de organizar el procesamiento del código en Node.js.\")]),_c('li',[_vm._v(\"Se basa en procesamiento concurrente de código Js con un solo thread, con no-desalojo para código Js.\")]),_c('li',[_vm._v(\"Tiene tres pasos \"),_c('ul',[_c('li',[_vm._v(\"Escanea el index, donde ejecuta todo el código que se pueda ejecutar inmediatamente, encolando continuations, IO, etc.\")]),_c('li',[_vm._v(\"Terminado el escaneo, itera en la siguiente secuencia, teniendo microqueues donde revisa si existen eventos preparados para ser ejecutados, y los ejecuta. \"),_c('ul',[_c('li',[_vm._v(\"Atiende operaciones asincrónicas, timeouts\")]),_c('li',[_vm._v(\"IO y redes\")]),_c('li',[_vm._v(\"immediate\")]),_c('li',[_vm._v(\"eventos de cierra de recursos\")])])]),_c('li',[_vm._v(\"Si no tiene más que ejecutar, cierra la ejecución, caso contrario, vuelve a retomar el ciclo.\")])])]),_c('li',[_vm._v(\"Tiene 1 hilo, pero n workers que se encargan de ejecutar las tareas pesadas.\")])]),_c('h3',{attrs:{\"id\":\"referencias\"}},[_vm._v(\"Referencias \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#referencias\"}},[_vm._v(\"¶\")])]),_c('ul',[_c('li',[_c('a',{attrs:{\"href\":\"https://www.youtube.com/watch?v=PNa9OMajw9w\"}},[_vm._v(\"Morning Keynote- Everything You Need to Know About Node.js Event Loop - Bert Belder, IBM\")])]),_c('li',[_c('a',{attrs:{\"href\":\"https://www.youtube.com/watch?v=ztspvPYybIY&t=1s\"}},[_vm._v(\"Ryan Dahl: Original Node.js presentation - JsConf\")])]),_c('li',[_c('a',{attrs:{\"href\":\"https://www.youtube.com/watch?v=_c51fcXRLGw\"}},[_vm._v(\"Introduction to libuv: What's a Unicorn Velociraptor? - Colin Ihrig, Joyent\")])]),_c('li',[_c('a',{attrs:{\"href\":\"https://nodejs.org/en/docs/guides/dont-block-the-event-loop/\"}},[_vm._v(\"Don't Block the Event Loop (or the Worker Pool)\")])]),_c('li',[_c('a',{attrs:{\"href\":\"https://nodejs.dev/learn\"}},[_vm._v(\"Introduction to Node.js\")])]),_c('li',[_c('a',{attrs:{\"href\":\"https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#what-is-the-event-loop\"}},[_vm._v(\"What is the event loop\")])])])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./event_loop.md?vue&type=template&id=6d85247a&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-349b0eea.fae450fa.js b/js/chunk-349b0eea.fae450fa.js new file mode 100644 index 0000000..f00dd52 --- /dev/null +++ b/js/chunk-349b0eea.fae450fa.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-349b0eea"],{"5fe6":function(e,a,o){e.exports=o.p+"img/monolito.fb888a05.jpg"},6109:function(e,a,o){e.exports=o.p+"img/auto_homero.801407e0.png"},"6b41":function(e,a,o){"use strict";o.r(a);var s=function(){var e=this,a=e.$createElement;e._self._c;return e._m(0)},r=[function(){var e=this,a=e.$createElement,s=e._self._c||a;return s("section",[s("p",[e._v("La materia tiene un objetivo doble: por un lado, conocer tecnologías novedosas de aplicación en la industria de desarrollo de software, y por otro lado, transmitir conocimiento durables, ideas que trasciendan la tecnología, sobre la concurrencia, y la arquitectura de software.")]),s("h2",{attrs:{id:"arquitecturas-concurrentes-qué-es-eso"}},[e._v("¿Arquitecturas Concurrentes? ¿Qué es eso? "),s("a",{staticClass:"header-anchor",attrs:{href:"#arquitecturas-concurrentes-qué-es-eso"}},[e._v("¶")])]),s("p",[e._v("Hace varios años empezamos a armar la materia de Arquitecturas Concurrentes. La razón por la cual empezó esta materia surgía un poco de nuestra frustración de la poca rigurosidad técnica que encontramos en el día a día en nuestros trabajos frente a problemas de arquitecturas, a veces sobrediseñados, a veces bien ideados aunque muy mal bajados en la implementación, o en base a lo que está de moda, sin un sólido fundamento. Por otro lado surge de que la concurrencia nos tiene de hijo: no importa cuanto nos esforcemos, los malignos hilos de ejecución lograrán destruir nuestro programa en modos insospechados. El cuidado parece ser siempre insuficiente: de alguna forma irreproducibles bugs de sincronización nos harían morder el suelo.")]),s("p",[e._v('¿Cuál fue la primera impresión una vez que armamos los contenidos iniciales? Que el diablo está en los detalles: muchas ideas de arquitectura y manejo de concurrencia intuitivamente "suenan bien". Pero recién cuando las bajamos a detalle vemos realmente sus consecuencias.')]),s("p",[e._v("Entonces la materia se trata de dos cosas principales, por un lado dar un estudio bien práctico sobre el manejo de la concurrencia, con distintas herramientas. Y por el otro el de dar nociones de arquitecturas distribuidas.")]),s("p",[e._v("A lo largo de la historia de la materia, la idea fue siempre la de adaptar los contenidos con materiales lo más actualizado posible, y la idea es siempre ir cambiando nuestros temas a lo que consideramos que es abarcar las dos ideas principales antes mencionadas con algunas de las técnologias más actuales.")]),s("h2",{attrs:{id:"sobre-la-arquitectura"}},[e._v("Sobre la Arquitectura "),s("a",{staticClass:"header-anchor",attrs:{href:"#sobre-la-arquitectura"}},[e._v("¶")])]),s("p",[e._v("Primero, algunas palabras sobre la arquitectura de software. He aquí algunas interpretaciones comunes y complementarias del término:")]),s("ul",[s("li",[e._v("Es el diseño lógico de alto nivel: diseñar ya no en términos de componentes como objetos, procedimientos o funciones, sino en términos de módulos, nodos de red, etc.")]),s("li",[e._v("Es el diseño de aquellos aspectos que software que son difíciles de cambiar: tecnologías de base, lenguajes, etc.")]),s("li",[e._v("Es el diseño físico: la selección de los componentes de hardware y el despliegue del software sobre estos componentes.")])]),s("p",[e._v("En general no encontramos muchas desavenencias en torno a esta ideas. Los problemas surgen cuando pensamos en cómo hacer arquitectura.")]),s("h3",{attrs:{id:"haciendo-arquitectura"}},[e._v("Haciendo arquitectura "),s("a",{staticClass:"header-anchor",attrs:{href:"#haciendo-arquitectura"}},[e._v("¶")])]),s("p",[e._v("Para nosotros la construcción de una arquitectura es un proceso:")]),s("ul",[s("li",[s("strong",[e._v("Iterativo")]),e._v(": si bien la arquitectura trata de lidiar con aquellas cosas que son difíciles de cambiar, aún así hay lugar para iterar. Por ejemplo: probablemente cambiar el lenguaje cada 3 iteraciones no sea una opción viable; sin embargo sí lo es empezar con un almacenamiento en archivos o una base embebida SQLite, luego pasar a un motor relacional, luego extraer una parte a una base de datos Mongo, y luego implementar sharding. constructivo: la arquitectura incluye la construcción. Si bien comunicar la arquitectura es una tarea real, la definición de una arquitectura no se limita a generar diagramas de despliegue y listados de tecnologías: hay que meter las manos en el barro. Medir, desplegar, programar, probar, son tareas imprescindibles. Además casi es imposible realizar el diseño de una arquitectura con una metodología en cascada, donde deberíamos ya plantear la arquitectura definitiva en una sola iteración. Veremos más adelante que siempre requieren de cambios")]),s("li",[s("strong",[e._v("verificable")]),e._v(": si la arquitectura no se puede validar de forma rápida, entonces el proceso está fallando. De la misma forma que no deberíamos programar todo el sistema antes de hacer las pruebas, o todas las pruebas antes de poner nuestra primera línea de código productivo, o encarar refactors que duren días, tampoco deberíamos embarcarnos en implementar arquitecturas de las que no podamos tener ningún feedback hasta dentro de varios meses.")]),s("li",[s("strong",[e._v("holístico")]),e._v(": en el desarrollo de una arquitectura los aspectos humanos suelen tener mucho más peso que los técnicos o tecnológicos. Así, cuestiones económicas o financieras (debemos reducir el gasto mensual en servidores en X%), políticas (vamos a usar el contenedor de aplicaciones X porque nuestra empresa tiene un convenio con quien lo comercializa), interpersonales (el gerente de sistemas de nuestro sector está peleado con el área de base de datos, por lo que utilizaremos almacenamiento en la nube), entre otras, son aspectos que impactan en el desarrollo. Debemos construir teniendo en cuenta estas cuestiones, que a veces pueden jugarnos en contra, y otras, a favor nuestro.")]),s("li",[s("strong",[e._v("potenciado por la tecnología")]),e._v(": el conocimiento de la tecnología existente nos ayudará a ahorrarnos el esfuerzo de pensar e implementar ideas ya probadas. Sin embargo, las decisiones arquitectónicas no deberán estar guiadas por la tecnología. No se trata de ir al supermercado, dirigirnos a la góndola de tecnologías, comprar una marca particular de una base de datos, un ESB y soporte comercial. Se trata de entender la problemática, pensar soluciones, y utilizar algún producto si realmente calza con lo que necesitamos. Cuando alguien se presente como Arquitecto Java/.Net/Node/LoQueSea, salí corriendo.")]),s("li",[s("strong",[e._v("enriquecido por la historia")]),e._v(": de forma similar al punto anterior, hay valor en conocer las soluciones que otros sistemas aplicaron, pero eso no significa que debamos hacer algo sólo porque otro lo hizo. Debemos siempre entender y estudiar las particularidades de nuestro problema, y no ser naïve pensando que simplemente podemos copiar el éxito de otro ignorando el proceso de meses o años que lo llevó a donde está. Si Facebook hizo X, capaz tu solución no necesite X… ¡porque no sos Facebook! Un punto a tener en cuenta es siempre el de no sobrediseñar nuestra arquitectura")])]),s("h3",{attrs:{id:"cualidades-arquitectonicas"}},[e._v("Cualidades Arquitectonicas "),s("a",{staticClass:"header-anchor",attrs:{href:"#cualidades-arquitectonicas"}},[e._v("¶")])]),s("p",[e._v("¿Y qué consideramos una buena arquitectura? Cuando podemos desarrollar sin problemas ni complejidades, es decir, libre de duplicaciones y que minimicen la redundancia y el código que solo es burocracia (en la medida de lo posible), llamado también boilerplate, que tengamos buenas abstracciones, que sea fácil de mantener y de probar. Y además, como la característica más importante, que sea "),s("strong",[e._v("simple")]),e._v(".")]),s("h4",{attrs:{id:"la-madre-de-todas-las-cualidades"}},[e._v("La madre de todas las cualidades "),s("a",{staticClass:"header-anchor",attrs:{href:"#la-madre-de-todas-las-cualidades"}},[e._v("¶")])]),s("p",[e._v("Podemos decir que la simplicidad es la madre de todas las cualidades, porque queremos solamente que nuestro sistema deba tener la complejidad mínima necesaria para solucionar una problemática.")]),s("p",[s("cite",{attrs:{cite:"AI"}},[e._v("Everything Should Be Made as Simple as Possible, But Not Simpler")])]),s("p",[e._v("Cuando la simpleza nos permite desarrollar y mantener un sistema sin mayores problemas, sin perder sus abstracciones esenciales ni duplicando código, vamos a poder desarrollar un sistema de manera rápida y el resto de las cualidades serán más fácil de lograr")]),s("img",{staticClass:"center",attrs:{src:o("c8b4")}}),s("h4",{attrs:{id:"cuidado-al-escalar"}},[e._v("Cuidado al escalar "),s("a",{staticClass:"header-anchor",attrs:{href:"#cuidado-al-escalar"}},[e._v("¶")])]),s("p",[e._v("Si bien la escalabilidad es algo importante en una gran cantidad de sistemas, y también es algo que queremos eventualmente cuando crece nuestro sistema en medida de usuarios o de requerimientos. Pero escalar no es algo gratis, es decir, que generalmente nos puede agregar una complejidad al sistema que no teníamos planeado")]),s("p",[s("cite",{attrs:{cite:"Paul Graham"}},[e._v("Do things that don’t scale.")])]),s("p",[e._v("Por eso, siempre es bueno como primera iteración de cualquier arquitectura, la que sea más simple y que soporte la carga de usuarios y recursos que deberíamos soportar a ciencia cierta...")]),s("blockquote",[s("p",[e._v("Pero y si no no sabemos cual será la carga, quizás porque es una aplicación que estamos lanzando por primera vez al mercado?")])]),s("p",[e._v("Bueno, tal vez a muchos les haga algo de ruido que respondamos a que sea lo más simple posible, en este caso una aplicación monolítica implementada con las tecnologías que más rápido les permitan satisfacer sus requerimientos funcionales. Sea Rails o Django, tal vez como primera iteración da lo mismo.")]),s("img",{staticClass:"center",attrs:{src:o("5fe6")}}),s("p",[e._v("Tengan en cuenta que también la decision de la tecnología depende de que equipo de desarrollo tengan, que experiencia tienen el equipo de desarrollo con el que trabajan y si la tecnología les permite desarrollar sin problemas y que tengan las librerías necesarias para cumplir con los requerimientos funcionales.")]),s("blockquote",[s("p",[e._v("Pero.... ¿No soporta miles de transacciones por minuto, no es tolerante a fallos, no puede crecer automáticamente, no puede ser distribuida geográficamente?")])]),s("p",[e._v("No se preocupen, probablemente en una primera iteración no lo necesiten. Además, si están lanzando una aplicación por primera vez al mercado, tal vez quieran empezar con algo chico y ver si la idea más alla de todo les resulta. También tengan en cuenta que si queremos además de resolver un problema, que la aplicación sea tolerante a fallos, pueda ser distribuida geográficamente y que pueda crecer automáticamente, tal vez tome mucho más tiempo, porque no solo es el desarrollo para cumplir con los requerimientos funcionales del trabajo y estos otros requisitos, sino también el de hacer pruebas y que todo funcione. Con lo cual esto puede tomar mucho más tiempo del necesario, para una primera iteración.")]),s("p",[e._v("Puede suceder que aun asi tienen el presupuesto, el tiempo para cumplir con todo esto; puede suceder el peor de los casos, que es que su aplicación una vez que está en el mercado, no lo utilice mucha gente y con lo cual la arquitectura haya quedado sobrediseñada. Esto es un puntapié para dar paso a la próxima sección.")]),s("h3",{attrs:{id:"yagni-you-arent-gonna-need-it"}},[e._v("YAGNI: You aren't gonna need it "),s("a",{staticClass:"header-anchor",attrs:{href:"#yagni-you-arent-gonna-need-it"}},[e._v("¶")])]),s("p",[e._v("Recién cuando estas necesidades surjan, allí podremos construir en base a requerimientos concretos, medibles. Quizás eso signifique distribuir componentes, introducir redundancias, reescribir parte del código, cambiar la forma en que se despliegan las aplicaciones. Lo mismo vale para otras cualidades duras como la tolerancia a fallos, la carga, la seguridad, etc. Son todas cuestiones que deberemos atacar ante demanda y no tratar de sobrediseñar o pensar muy a largo plazo.")]),s("p",[e._v("Según este enfoque, las buenas arquitecturas no se anticipan, no se planifican. Mas bien, emergen: son la consecuencia de decisiones justificadas en los momentos indicados. Y eso nos lleva a una última idea: las buenas arquitecturas son mínimas.")]),s("p",[s("cite",{attrs:{cite:"Dieter Rams"}},[e._v("Good design is as little design as possible.")])]),s("p",[e._v("Esto es un poco que no hay elementos o componentes innecesarios y si apenas percibimos las restricciones que la arquitectura nos propone, entonces el programar dentro de esa arquitectura se vuelve natural y simple, sin preocuparse más que en los requerimientos o fallas de un sistema.")]),s("p",[e._v("Entonces, no siempre empezar con microservicios es la mejor alternativa y no solo por el hype deberíamos adoptar una arquitectura o una tecnología porque esta de moda o porque sí...")]),s("blockquote",[s("p",[e._v("Moraleja: desconfiá de todo aquel arquitecto que, tras brindarle una somera descripción del problema, te proponga una compleja aplicación distribuida en 12 Capas, 3 lenguajes (Go, Scala, JS, porque están de moda) , un Redis, un Oracle, un Memcached, 4 microservicios, 3 tareas batch, 3 niveles de replicación, un despliegue con Puppet, 10 servidores, un BPM y una lata de duraznos (para asegurar la buena digestión). O cualquier combinación que seguro ya te contaron.")])]),s("img",{staticClass:"center",attrs:{src:o("bdd5")}}),s("p",[e._v("Tengan en cuenta que si deciden optar por empezar con una arquitectura más compleja, de ver los costos y los tiempos que eso conlleva, necesitaran más tiempo y más recursos necesariamente, que se traduce en que haya un mayor presupuesto, y si bien llegar a una arquitectura más compleja puede parecer una buena idea para el futuro. Está el problema de que tal vez nunca tengan los usuarios o la carga para aprovechar todas las ventajas de su arquitectura propuesta, y además, al introducir mayor cantidad de componentes que seguro tiene una arquitectura más compleja, esto introduce otros problemas que sean de mantenimiento o de errores, con lo cual puede ser incluso contraproducente si después no pueden solucionar estos en un tiempo que no les afecte al negocio o la idea que propone su sistema.")]),s("img",{staticClass:"center iasc-images",attrs:{src:o("6109")}}),s("p",[e._v("La idea es que su arquitectura no se interponga o complejice el desarrollo de su sistema sea de fallos o nuevos requerimientos, y que ayude a solucionar problemas que son los que están más alla de los requerimientos que tiene que resolver un problema, como la carga de usuarios, información, distribución geográfica, etc.")])])}],n=o("2877"),i={},t=Object(n["a"])(i,s,r,!1,null,null,null);a["default"]=t.exports},bdd5:function(e,a,o){e.exports=o.p+"img/homero-movil.8fe1d20e.jpg"},c8b4:function(e,a,o){e.exports=o.p+"img/principio-kiss.6dc64b42.jpg"}}]); +//# sourceMappingURL=chunk-349b0eea.fae450fa.js.map \ No newline at end of file diff --git a/js/chunk-349b0eea.fae450fa.js.map b/js/chunk-349b0eea.fae450fa.js.map new file mode 100644 index 0000000..f74534c --- /dev/null +++ b/js/chunk-349b0eea.fae450fa.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/images/monolito.jpg","webpack:///./src/images/auto_homero.png","webpack:///./src/content/introduccion.md?5401","webpack:///./src/content/introduccion.md","webpack:///./src/images/homero-movil.jpg","webpack:///./src/images/principio-kiss.jpg"],"names":["module","exports","render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","_v","attrs","staticClass","script","component"],"mappings":"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","file":"js/chunk-349b0eea.fae450fa.js","sourcesContent":["module.exports = __webpack_public_path__ + \"img/monolito.fb888a05.jpg\";","module.exports = __webpack_public_path__ + \"img/auto_homero.801407e0.png\";","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('p',[_vm._v(\"La materia tiene un objetivo doble: por un lado, conocer tecnologías novedosas de aplicación en la industria de desarrollo de software, y por otro lado, transmitir conocimiento durables, ideas que trasciendan la tecnología, sobre la concurrencia, y la arquitectura de software.\")]),_c('h2',{attrs:{\"id\":\"arquitecturas-concurrentes-qué-es-eso\"}},[_vm._v(\"¿Arquitecturas Concurrentes? ¿Qué es eso? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#arquitecturas-concurrentes-qué-es-eso\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Hace varios años empezamos a armar la materia de Arquitecturas Concurrentes. La razón por la cual empezó esta materia surgía un poco de nuestra frustración de la poca rigurosidad técnica que encontramos en el día a día en nuestros trabajos frente a problemas de arquitecturas, a veces sobrediseñados, a veces bien ideados aunque muy mal bajados en la implementación, o en base a lo que está de moda, sin un sólido fundamento. Por otro lado surge de que la concurrencia nos tiene de hijo: no importa cuanto nos esforcemos, los malignos hilos de ejecución lograrán destruir nuestro programa en modos insospechados. El cuidado parece ser siempre insuficiente: de alguna forma irreproducibles bugs de sincronización nos harían morder el suelo.\")]),_c('p',[_vm._v(\"¿Cuál fue la primera impresión una vez que armamos los contenidos iniciales? Que el diablo está en los detalles: muchas ideas de arquitectura y manejo de concurrencia intuitivamente \\\"suenan bien\\\". Pero recién cuando las bajamos a detalle vemos realmente sus consecuencias.\")]),_c('p',[_vm._v(\"Entonces la materia se trata de dos cosas principales, por un lado dar un estudio bien práctico sobre el manejo de la concurrencia, con distintas herramientas. Y por el otro el de dar nociones de arquitecturas distribuidas.\")]),_c('p',[_vm._v(\"A lo largo de la historia de la materia, la idea fue siempre la de adaptar los contenidos con materiales lo más actualizado posible, y la idea es siempre ir cambiando nuestros temas a lo que consideramos que es abarcar las dos ideas principales antes mencionadas con algunas de las técnologias más actuales.\")]),_c('h2',{attrs:{\"id\":\"sobre-la-arquitectura\"}},[_vm._v(\"Sobre la Arquitectura \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#sobre-la-arquitectura\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Primero, algunas palabras sobre la arquitectura de software. He aquí algunas interpretaciones comunes y complementarias del término:\")]),_c('ul',[_c('li',[_vm._v(\"Es el diseño lógico de alto nivel: diseñar ya no en términos de componentes como objetos, procedimientos o funciones, sino en términos de módulos, nodos de red, etc.\")]),_c('li',[_vm._v(\"Es el diseño de aquellos aspectos que software que son difíciles de cambiar: tecnologías de base, lenguajes, etc.\")]),_c('li',[_vm._v(\"Es el diseño físico: la selección de los componentes de hardware y el despliegue del software sobre estos componentes.\")])]),_c('p',[_vm._v(\"En general no encontramos muchas desavenencias en torno a esta ideas. Los problemas surgen cuando pensamos en cómo hacer arquitectura.\")]),_c('h3',{attrs:{\"id\":\"haciendo-arquitectura\"}},[_vm._v(\"Haciendo arquitectura \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#haciendo-arquitectura\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Para nosotros la construcción de una arquitectura es un proceso:\")]),_c('ul',[_c('li',[_c('strong',[_vm._v(\"Iterativo\")]),_vm._v(\": si bien la arquitectura trata de lidiar con aquellas cosas que son difíciles de cambiar, aún así hay lugar para iterar. Por ejemplo: probablemente cambiar el lenguaje cada 3 iteraciones no sea una opción viable; sin embargo sí lo es empezar con un almacenamiento en archivos o una base embebida SQLite, luego pasar a un motor relacional, luego extraer una parte a una base de datos Mongo, y luego implementar sharding. constructivo: la arquitectura incluye la construcción. Si bien comunicar la arquitectura es una tarea real, la definición de una arquitectura no se limita a generar diagramas de despliegue y listados de tecnologías: hay que meter las manos en el barro. Medir, desplegar, programar, probar, son tareas imprescindibles. Además casi es imposible realizar el diseño de una arquitectura con una metodología en cascada, donde deberíamos ya plantear la arquitectura definitiva en una sola iteración. Veremos más adelante que siempre requieren de cambios\")]),_c('li',[_c('strong',[_vm._v(\"verificable\")]),_vm._v(\": si la arquitectura no se puede validar de forma rápida, entonces el proceso está fallando. De la misma forma que no deberíamos programar todo el sistema antes de hacer las pruebas, o todas las pruebas antes de poner nuestra primera línea de código productivo, o encarar refactors que duren días, tampoco deberíamos embarcarnos en implementar arquitecturas de las que no podamos tener ningún feedback hasta dentro de varios meses.\")]),_c('li',[_c('strong',[_vm._v(\"holístico\")]),_vm._v(\": en el desarrollo de una arquitectura los aspectos humanos suelen tener mucho más peso que los técnicos o tecnológicos. Así, cuestiones económicas o financieras (debemos reducir el gasto mensual en servidores en X%), políticas (vamos a usar el contenedor de aplicaciones X porque nuestra empresa tiene un convenio con quien lo comercializa), interpersonales (el gerente de sistemas de nuestro sector está peleado con el área de base de datos, por lo que utilizaremos almacenamiento en la nube), entre otras, son aspectos que impactan en el desarrollo. Debemos construir teniendo en cuenta estas cuestiones, que a veces pueden jugarnos en contra, y otras, a favor nuestro.\")]),_c('li',[_c('strong',[_vm._v(\"potenciado por la tecnología\")]),_vm._v(\": el conocimiento de la tecnología existente nos ayudará a ahorrarnos el esfuerzo de pensar e implementar ideas ya probadas. Sin embargo, las decisiones arquitectónicas no deberán estar guiadas por la tecnología. No se trata de ir al supermercado, dirigirnos a la góndola de tecnologías, comprar una marca particular de una base de datos, un ESB y soporte comercial. Se trata de entender la problemática, pensar soluciones, y utilizar algún producto si realmente calza con lo que necesitamos. Cuando alguien se presente como Arquitecto Java/.Net/Node/LoQueSea, salí corriendo.\")]),_c('li',[_c('strong',[_vm._v(\"enriquecido por la historia\")]),_vm._v(\": de forma similar al punto anterior, hay valor en conocer las soluciones que otros sistemas aplicaron, pero eso no significa que debamos hacer algo sólo porque otro lo hizo. Debemos siempre entender y estudiar las particularidades de nuestro problema, y no ser naïve pensando que simplemente podemos copiar el éxito de otro ignorando el proceso de meses o años que lo llevó a donde está. Si Facebook hizo X, capaz tu solución no necesite X… ¡porque no sos Facebook! Un punto a tener en cuenta es siempre el de no sobrediseñar nuestra arquitectura\")])]),_c('h3',{attrs:{\"id\":\"cualidades-arquitectonicas\"}},[_vm._v(\"Cualidades Arquitectonicas \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#cualidades-arquitectonicas\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"¿Y qué consideramos una buena arquitectura? Cuando podemos desarrollar sin problemas ni complejidades, es decir, libre de duplicaciones y que minimicen la redundancia y el código que solo es burocracia (en la medida de lo posible), llamado también boilerplate, que tengamos buenas abstracciones, que sea fácil de mantener y de probar. Y además, como la característica más importante, que sea \"),_c('strong',[_vm._v(\"simple\")]),_vm._v(\".\")]),_c('h4',{attrs:{\"id\":\"la-madre-de-todas-las-cualidades\"}},[_vm._v(\"La madre de todas las cualidades \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#la-madre-de-todas-las-cualidades\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Podemos decir que la simplicidad es la madre de todas las cualidades, porque queremos solamente que nuestro sistema deba tener la complejidad mínima necesaria para solucionar una problemática.\")]),_c('p',[_c('cite',{attrs:{\"cite\":\"AI\"}},[_vm._v(\"Everything Should Be Made as Simple as Possible, But Not Simpler\")])]),_c('p',[_vm._v(\"Cuando la simpleza nos permite desarrollar y mantener un sistema sin mayores problemas, sin perder sus abstracciones esenciales ni duplicando código, vamos a poder desarrollar un sistema de manera rápida y el resto de las cualidades serán más fácil de lograr\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/principio-kiss.jpg\")}}),_c('h4',{attrs:{\"id\":\"cuidado-al-escalar\"}},[_vm._v(\"Cuidado al escalar \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#cuidado-al-escalar\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Si bien la escalabilidad es algo importante en una gran cantidad de sistemas, y también es algo que queremos eventualmente cuando crece nuestro sistema en medida de usuarios o de requerimientos. Pero escalar no es algo gratis, es decir, que generalmente nos puede agregar una complejidad al sistema que no teníamos planeado\")]),_c('p',[_c('cite',{attrs:{\"cite\":\"Paul Graham\"}},[_vm._v(\"Do things that don’t scale.\")])]),_c('p',[_vm._v(\"Por eso, siempre es bueno como primera iteración de cualquier arquitectura, la que sea más simple y que soporte la carga de usuarios y recursos que deberíamos soportar a ciencia cierta...\")]),_c('blockquote',[_c('p',[_vm._v(\"Pero y si no no sabemos cual será la carga, quizás porque es una aplicación que estamos lanzando por primera vez al mercado?\")])]),_c('p',[_vm._v(\"Bueno, tal vez a muchos les haga algo de ruido que respondamos a que sea lo más simple posible, en este caso una aplicación monolítica implementada con las tecnologías que más rápido les permitan satisfacer sus requerimientos funcionales. Sea Rails o Django, tal vez como primera iteración da lo mismo.\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/monolito.jpg\")}}),_c('p',[_vm._v(\"Tengan en cuenta que también la decision de la tecnología depende de que equipo de desarrollo tengan, que experiencia tienen el equipo de desarrollo con el que trabajan y si la tecnología les permite desarrollar sin problemas y que tengan las librerías necesarias para cumplir con los requerimientos funcionales.\")]),_c('blockquote',[_c('p',[_vm._v(\"Pero.... ¿No soporta miles de transacciones por minuto, no es tolerante a fallos, no puede crecer automáticamente, no puede ser distribuida geográficamente?\")])]),_c('p',[_vm._v(\"No se preocupen, probablemente en una primera iteración no lo necesiten. Además, si están lanzando una aplicación por primera vez al mercado, tal vez quieran empezar con algo chico y ver si la idea más alla de todo les resulta. También tengan en cuenta que si queremos además de resolver un problema, que la aplicación sea tolerante a fallos, pueda ser distribuida geográficamente y que pueda crecer automáticamente, tal vez tome mucho más tiempo, porque no solo es el desarrollo para cumplir con los requerimientos funcionales del trabajo y estos otros requisitos, sino también el de hacer pruebas y que todo funcione. Con lo cual esto puede tomar mucho más tiempo del necesario, para una primera iteración.\")]),_c('p',[_vm._v(\"Puede suceder que aun asi tienen el presupuesto, el tiempo para cumplir con todo esto; puede suceder el peor de los casos, que es que su aplicación una vez que está en el mercado, no lo utilice mucha gente y con lo cual la arquitectura haya quedado sobrediseñada. Esto es un puntapié para dar paso a la próxima sección.\")]),_c('h3',{attrs:{\"id\":\"yagni-you-arent-gonna-need-it\"}},[_vm._v(\"YAGNI: You aren't gonna need it \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#yagni-you-arent-gonna-need-it\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Recién cuando estas necesidades surjan, allí podremos construir en base a requerimientos concretos, medibles. Quizás eso signifique distribuir componentes, introducir redundancias, reescribir parte del código, cambiar la forma en que se despliegan las aplicaciones. Lo mismo vale para otras cualidades duras como la tolerancia a fallos, la carga, la seguridad, etc. Son todas cuestiones que deberemos atacar ante demanda y no tratar de sobrediseñar o pensar muy a largo plazo.\")]),_c('p',[_vm._v(\"Según este enfoque, las buenas arquitecturas no se anticipan, no se planifican. Mas bien, emergen: son la consecuencia de decisiones justificadas en los momentos indicados. Y eso nos lleva a una última idea: las buenas arquitecturas son mínimas.\")]),_c('p',[_c('cite',{attrs:{\"cite\":\"Dieter Rams\"}},[_vm._v(\"Good design is as little design as possible.\")])]),_c('p',[_vm._v(\"Esto es un poco que no hay elementos o componentes innecesarios y si apenas percibimos las restricciones que la arquitectura nos propone, entonces el programar dentro de esa arquitectura se vuelve natural y simple, sin preocuparse más que en los requerimientos o fallas de un sistema.\")]),_c('p',[_vm._v(\"Entonces, no siempre empezar con microservicios es la mejor alternativa y no solo por el hype deberíamos adoptar una arquitectura o una tecnología porque esta de moda o porque sí...\")]),_c('blockquote',[_c('p',[_vm._v(\"Moraleja: desconfiá de todo aquel arquitecto que, tras brindarle una somera descripción del problema, te proponga una compleja aplicación distribuida en 12 Capas, 3 lenguajes (Go, Scala, JS, porque están de moda) , un Redis, un Oracle, un Memcached, 4 microservicios, 3 tareas batch, 3 niveles de replicación, un despliegue con Puppet, 10 servidores, un BPM y una lata de duraznos (para asegurar la buena digestión). O cualquier combinación que seguro ya te contaron.\")])]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/homero-movil.jpg\")}}),_c('p',[_vm._v(\"Tengan en cuenta que si deciden optar por empezar con una arquitectura más compleja, de ver los costos y los tiempos que eso conlleva, necesitaran más tiempo y más recursos necesariamente, que se traduce en que haya un mayor presupuesto, y si bien llegar a una arquitectura más compleja puede parecer una buena idea para el futuro. Está el problema de que tal vez nunca tengan los usuarios o la carga para aprovechar todas las ventajas de su arquitectura propuesta, y además, al introducir mayor cantidad de componentes que seguro tiene una arquitectura más compleja, esto introduce otros problemas que sean de mantenimiento o de errores, con lo cual puede ser incluso contraproducente si después no pueden solucionar estos en un tiempo que no les afecte al negocio o la idea que propone su sistema.\")]),_c('img',{staticClass:\"center iasc-images\",attrs:{\"src\":require(\"@/images/auto_homero.png\")}}),_c('p',[_vm._v(\"La idea es que su arquitectura no se interponga o complejice el desarrollo de su sistema sea de fallos o nuevos requerimientos, y que ayude a solucionar problemas que son los que están más alla de los requerimientos que tiene que resolver un problema, como la carga de usuarios, información, distribución geográfica, etc.\")])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./introduccion.md?vue&type=template&id=5e5a2856&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","module.exports = __webpack_public_path__ + \"img/homero-movil.8fe1d20e.jpg\";","module.exports = __webpack_public_path__ + \"img/principio-kiss.6dc64b42.jpg\";"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-36154627.a6b93af1.js b/js/chunk-36154627.a6b93af1.js new file mode 100644 index 0000000..4265b2c --- /dev/null +++ b/js/chunk-36154627.a6b93af1.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-36154627"],{"0a75":function(e,s,a){e.exports=a.p+"img/secret.4995711d.jpg"},"52f8":function(e,s,a){"use strict";a.r(s);var r=function(){var e=this,s=e.$createElement;e._self._c;return e._m(0)},t=[function(){var e=this,s=e.$createElement,r=e._self._c||s;return r("section",[r("h1",{attrs:{id:"fibers-on-ruby"}},[e._v("Fibers on Ruby "),r("a",{staticClass:"header-anchor",attrs:{href:"#fibers-on-ruby"}},[e._v("¶")])]),r("p",[e._v("Las fibras son estructuras que implementan un mecanismo de concurrencia cooperativa y liviana en Ruby. Básicamente, son un medio para crear bloques de código que se pueden pausar y reanudar, al igual que los hilos. La principal diferencia es que nunca se planifican implicitamente y que la planificación debe realizarla el programador y no la VM.")]),r("p",[e._v("O sea que en el caso de los "),r("code",{pre:!0},[e._v("threads")]),e._v(", el scheduler se encarga de la planificacion y del manejo del ciclo de vida de esta abstracción. En el caso de los "),r("code",{pre:!0},[e._v("fibers")]),e._v(", esta en nuestras manos la planificación, con lo cual en el código vamos a tener que también tener codigo en cuanto a manejo de los fibers que estamos usando, es decir vamos a tener que explícitamente manejar la planificación. Podemos armar algunas abstracciones pero no suele ser una tarea trivial.")]),r("p",[e._v("A diferencia de otros modelos de concurrencia ligeros sin stack, cada "),r("code",{pre:!0},[e._v("fiber")]),e._v(" viene con un stack. Esto permite que el fiber se pause desde llamadas de función anidadas dentro del bloque del "),r("code",{pre:!0},[e._v("Fiber")]),e._v(".")]),r("p",[e._v("Al ser un esquema colaborativo, nos da un mayor control de la ejecución, y es mas, proporcionan un control total al programador sore su ejecucion como mencionamos antes. Veamos un ejemplo de comparacion en cuanto a los tiempos..")]),r("img",{staticClass:"center",attrs:{src:a("812c")}}),r("p",[e._v("Dos threads que se ejecutan, uno se bloquea por 40ms con una llamada de IO, y después toma unos 10ms mas, el procesamiento de estos datos retornados de la llamada. Después hay un segundo thread, que necesita 50ms, de solo tiempo de CPU. El escenario es el mismo tanto con threads, como con fibers y su planificacion cooperativa.")]),r("p",[e._v("Por defecto, MRI usa un "),r("code",{pre:!0},[e._v("fair scheduler")]),e._v(" ("),r("a",{attrs:{href:"https://es.wikipedia.org/wiki/Planificador_Completamente_Justo"}},[e._v("mas aqui")]),e._v("), que significa que cada thread recibe un mismo tiempo para ejecutar, con quantums de 10ms, antes que se suspendan y que el proximo thread se ponga bajo control. Si uno de los threads esta dentro de una llamada bloquante dentro de esos 10ms, se lo debe tomar como tiempo malgastado, es tiempo en el que seguramente todos los threads estan descansando, por estar bloqueados o esperando I/O. Por el otro lado, los Fibers, al ser scheduleados explicitamente por el programador, o sea nosotros, nos da una flexibilidad a la hora de determinar cuando debemos parar la ejecucion de nuestro fiber y cuando retomarlo. Esto trae, como desventaja, que tenemos ahora un codigo mas complejo, pero a su vez nos ayudan, en que en un caso casi ideal, no necesitemos casi el uso de locks.")]),r("blockquote",[r("p",[e._v("Nota: Desde Ruby 3.0, el concepto de los "),r("code",{pre:!0},[e._v("non-blocking fibers")]),e._v(" fue introducido. Todos los fibers ya son por defecto no bloqueantes. Mas sobre esto en la seccion de Ruby 3.")])]),r("h3",{attrs:{id:"diferencias-que-vemos-entre-los-threads-y-fibers"}},[e._v("Diferencias que vemos entre los threads y fibers "),r("a",{staticClass:"header-anchor",attrs:{href:"#diferencias-que-vemos-entre-los-threads-y-fibers"}},[e._v("¶")])]),r("blockquote",[r("p",[e._v("TL;DR..")])]),r("ul",[r("li",[e._v("Los Fibers son ligeros en cuanto a la memoria que consumen y los tiempos del ciclo de vida")]),r("li",[e._v("Tenemos el control de los Fibers, de manera explicita, o sea que tenemos el control absoluto de su ciclo de vida y planificacion.")]),r("li",[e._v("Si bien con los threads tenemos al scheduler que decide cuando un thread se pausa o reanuda, en el caso de los Fibers es variable. O sea, al tener el control nosotros de la planificacion, tenemos que especificar cuando iniciar y parar la ejecucion de un Fiber.")]),r("li",[e._v("Los Fibers, son maneras de escribir bloques de codigo, que pueden ser pausados o resumidos, bastante parecidos a los threads, pero con la diferencia de la planificacion de nuestro lado.")]),r("li",[e._v("Los "),r("code",{pre:!0},[e._v("Threads")]),e._v(" se ejecutan en un segundo plano, especialmente cuando hay una interrupcion. En el caso de los Fibers, se convierten en el programa principal, cuando se ejecutan, hasta que uno los para.")])]),r("h3",{attrs:{id:"uso-y-estados-de-los-fibers"}},[e._v("Uso y estados de los Fibers "),r("a",{staticClass:"header-anchor",attrs:{href:"#uso-y-estados-de-los-fibers"}},[e._v("¶")])]),r("p",[e._v("Para invocar un fiber, basta con hacer algo como lo siguiente")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v("f = Fiber.new { puts "),r("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'blah'")]),e._v(" }\n\nf.resume \nblah\n=> nil\n")])]),r("p",[e._v("Algo interesante para mostrar es que un Fiber no se ejecuta automaticamente, luego de su creacion, sino que necesita que se llame primero a "),r("code",{pre:!0},[e._v("Fiber#resume")]),e._v(" antes. Y seguira en el estado de "),r("code",{pre:!0},[e._v("FIBER_RESUMED")]),e._v(", hasta que se pare su ejecucion o que termine de ejecutar todo el codigo que contiene en su bloque.")]),r("p",[e._v("Como se para un fiber?? por medio de "),r("code",{pre:!0},[e._v("Fiber#yield")]),e._v(". se puede ver este ejemplo en el "),r("a",{attrs:{href:"https://github.com/arquitecturas-concurrentes/ruby-fibers/tree/main/examples/fibers_1.rb"}},[e._v("fiber_1")])]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v("fiber = Fiber.new "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("do")]),e._v("\n puts "),r("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'hola 1'")]),e._v("\n Fiber."),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("yield")]),e._v("\n puts "),r("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'hola 2'")]),e._v("\n"),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n")])]),r("p",[e._v("en el momento que se ejecuta por primera vez "),r("code",{pre:!0},[e._v("fiber.resume")]),e._v(", solo se ejecutara el primer puts, y cuando se llame a yield, el fiber actual se para y pasa su estado a "),r("code",{pre:!0},[e._v("FIBER_SUSPENDED")]),e._v(". Solo una vez que se llame de nuevo a "),r("code",{pre:!0},[e._v("fiber.resume")]),e._v(", se ejecutara el resto del codigo. Una pregunta valida puede ser, que pasa si una vez que corre todo el codigo del bloque que contiene el fiber, se llama de nuevo a "),r("code",{pre:!0},[e._v("fiber.resume")]),e._v("??")]),r("p",[e._v("Es una buena pregunta y es que una vez que termina, pasa su estado a "),r("code",{pre:!0},[e._v("FIBER_TERMINATED")]),e._v(". Con lo cual nos va a dar un error:")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v("["),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("5")]),e._v("] pry(main)> fiber.resume\n"),r("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v("FiberError:")]),e._v(" dead fiber called\nfrom (pry)"),r("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v(":")]),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("9")]),r("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v(":in")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("`resume'\n")])])]),r("p",[e._v("Para siempre chequear este estado tenemos un metodo que es "),r("code",{pre:!0},[e._v("Fiber#alive?")]),e._v(", que nos devuelve un booleano, de si un fiber esta vivo o no. Sobre nuestro ejemplo anterior:")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v("["),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("6")]),e._v("] pry(main)> fiber.alive?\n=> false\n")])]),r("p",[e._v("Un diagrama de transicion de los estados de un Fiber se puede ver a continuacion.")]),r("img",{staticClass:"center",attrs:{src:a("d1ba")}}),r("h4",{attrs:{id:"para-que-sirven-los-fibers"}},[e._v("Para que sirven los fibers? "),r("a",{staticClass:"header-anchor",attrs:{href:"#para-que-sirven-los-fibers"}},[e._v("¶")])]),r("p",[e._v("Este tipo de abstracciones que modelan un contexto de ejecución, no se usan normalmente, sino que es algo que en general se utiliza en una libreria, implementando otras abstracciones sobre y que usen los fibers, para manejar bien los eventos, cuando parar un fiber y reanudarlo, y despues que nuestro codigo de aplicacion use a esta libreria, sin saber los detalles y que no tenga que operar usando fibers directamente.")]),r("p",[e._v("Un ejemplo de esto, puede verse, si implementamos un "),r("code",{pre:!0},[e._v("reactor")]),e._v(", que es un "),r("a",{attrs:{href:"https://en.wikipedia.org/wiki/Reactor_pattern#:~:text=The%20reactor%20design%20pattern%20is,to%20the%20associated%20request%20handlers."}},[e._v("patron de diseno")]),e._v(" que nos va a permitir manejar eventos. Hay muchas manera de implementar un reactor. Vimos hace poco que el "),r("code",{pre:!0},[e._v("event loop")]),e._v(" usa "),r("a",{attrs:{href:"https://man7.org/linux/man-pages/man2/epoll_wait.2.html"}},[e._v("epoll")]),e._v(" para saber de nuevos eventos disponibles, que le llegan a un puerto. Otra manera, aunque no tan efectiva, pero mas sencilla de lograr, puede ser mediante "),r("a",{attrs:{href:"https://man7.org/linux/man-pages/man2/select.2.html"}},[e._v("select")]),e._v(".")]),r("p",[e._v("Con "),r("code",{pre:!0},[e._v("select")]),e._v(", que esta presente en Ruby, mediante un wrapper en "),r("code",{pre:!0},[e._v("IO")]),e._v(", podemos implementar un "),r("code",{pre:!0},[e._v("reactor")]),e._v(" simple. Un ejemplo de la cátedra, que usa una implementación mas completa con "),r("code",{pre:!0},[e._v("timers")]),e._v(" y otras abstracciones se puede ver en este "),r("a",{attrs:{href:"https://github.com/arquitecturas-concurrentes/iasc-event-loop-reactor-ruby"}},[e._v("repositorio")]),e._v(".")]),r("p",[e._v("De una manera mucho mas simple, podemos tener una clase "),r("code",{pre:!0},[e._v("Reactor")]),e._v(", que tenga dos mapas para eventos de escritura o lectura.")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[r("span",{pre:!0,attrs:{class:"hljs-class"}},[r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("class")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("Reactor")])]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-function"}},[r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("initialize")])]),e._v("\n @readable = {}\n @writable = {}\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("#...")]),e._v("\n"),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n")])]),r("p",[e._v("y que tenga un ciclo de corridas en el que se esperan a que los eventos que esten encolados, la parte interesante de este codigo:")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[r("span",{pre:!0,attrs:{class:"hljs-class"}},[r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("class")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("Reactor")])]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-function"}},[r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("initialize")])]),e._v("\n @readable = {}\n @writable = {}\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n\n "),r("span",{pre:!0,attrs:{class:"hljs-function"}},[r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("run")])]),e._v("\n _error_events = [] "),r("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("# unused for now...")]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("while")]),e._v(" @readable.any? "),r("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("||")]),e._v(" @writable.any?\n readable, writable = IO.select(@readable.keys, @writable.keys, _error_events)\n\n readable.each "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("do")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("|io|")]),e._v("\n @readable[io].resume\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n\n writable.each "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("do")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("|io|")]),e._v("\n @writable[io].resume\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n"),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n")])]),r("p",[e._v("esta en la línea del select")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v("readable, writable = IO.select(@readable.keys, @writable.keys, _error_events)\n")])]),r("p",[e._v("donde se esperan a que los eventos que tienen una llamada de IO pendiente terminen.")]),r("p",[e._v("Sobre el Reactor se pueden armar otras abstracicones, tales como un servidor de TCP")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v("server = TCPServer.new("),r("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'localhost'")]),e._v(", port)\nputs "),r("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v('"Listening on 127.0.0.1:'),r("span",{pre:!0,attrs:{class:"hljs-subst"}},[e._v("#{port}")]),e._v('"')]),e._v("\nreactor = Reactor.new\n")])]),r("p",[e._v("y que use en un loop la aceptación de la conexión")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v("loop "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("do")]),e._v("\n client = reactor.wait_readable(server) { server.accept } \n "),r("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("# ....")]),e._v("\n"),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n")])]),r("p",[e._v("despues hay que esperar desde el servidor a que termine el handshake contra el cliente, por lo que eso es otra llamada, y por lo tanto otro evento...")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v("reactor.wait_readable(client) { client.gets })\n")])]),r("p",[e._v("Como unimos estos eventos en el reactor? Mediante alguna abstracción, o contexto de ejecución, que pueda bueno... ejecutarlas. Aquí es donde entran los Fibers..")]),r("p",[e._v("El loop queda entonces, como")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v("loop "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("do")]),e._v("\n client = reactor.wait_readable(server) { server.accept }\n\n Fiber.new "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("do")]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("while")]),e._v(" (_buffer = reactor.wait_readable(client) { client.gets })\n reactor.wait_writable(client)\n client.puts("),r("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v('"Pong!"')]),e._v(")\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n\n client.close\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v(".resume \n"),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n")])]),r("p",[e._v("Despues hay que wrapear el loop en un ctx similar general, que es otro fiber y listo..")]),r("p",[e._v("El reactor toma los bloques de los eventos de io server y client como bloques que se ejecutaran como otros "),r("code",{pre:!0},[e._v("fibers")]),e._v(".")]),r("p",[e._v("El ejemplo esta en este "),r("a",{attrs:{href:"https://github.com/arquitecturas-concurrentes/ruby-fibers/tree/main/examples/socket/tcp_reactor.rb"}},[e._v("archivo")])]),r("h3",{attrs:{id:"fibers-en-ruby-30"}},[e._v("Fibers en Ruby 3.0 "),r("a",{staticClass:"header-anchor",attrs:{href:"#fibers-en-ruby-30"}},[e._v("¶")])]),r("p",[e._v("Entre otras cosas Ruby 3, introduce el concepto de "),r("code",{pre:!0},[e._v("fibers")]),e._v(" no bloqueantes. Ahora cuando hacemos un "),r("code",{pre:!0},[e._v("Fiber.new() do ... end")]),e._v(", se le puede pasar un flag booleano llamado "),r("code",{pre:!0},[e._v("blocking")]),e._v(". Por defecto el valor de este booleano es "),r("code",{pre:!0},[e._v("false")])]),r("p",[e._v("Cuando se le pasa el valor "),r("code",{pre:!0},[e._v("blocking: true")]),e._v(", el "),r("code",{pre:!0},[e._v("Fiber")]),e._v(" se va a comportar como lo hacia en Ruby 2.x.")]),r("p",[e._v("Lo interesante es cuando no se le pasa este flag o el valor es "),r("code",{pre:!0},[e._v("blocking: false")]),e._v(". Esto permite que el Fiber sea "),r("code",{pre:!0},[e._v("no bloqueante")]),e._v(".")]),r("p",[e._v("Los "),r("code",{pre:!0},[e._v("fibers no bloqueantes")]),e._v(", cuando llegan en el codigo que ejecutan, a una zona que es potencialmente bloqueante (sleep, esperar otro proceso, esperar datos de I/O, etc), en vez de congelarse y parar toda la ejecucion del thread, hace un "),r("code",{pre:!0},[e._v("yield")]),e._v(" implicito, y permite que otros fibers tomen el control. Esto si se maneja mendiante un scheduler, permite que se pueda manejar bien a que fiber se le puede dar prioridad")]),r("p",[e._v("Que es el "),r("code",{pre:!0},[e._v("scheduler")]),e._v("?? En realidad la pregunta correcta sería, como nos damos cuenta ahora con un esquema "),r("code",{pre:!0},[e._v("no bloquante")]),e._v(" cuando tenemos una respuesta con la cual nos va a surgir una nueva duda. Cómo podemos seguir con la ejecución de nuestro fiber? Esto surge porque aun tenemos que planificar a los fibers.")]),r("p",[e._v("Para poder saber y manejar cuando tenemos una respuesta, tendremos un "),r("code",{pre:!0},[e._v("scheduler")]),e._v(", y en si es una clase que simula algo similar a un "),r("code",{pre:!0},[e._v("event loop")]),e._v(". Nos va a permitir:")]),r("ul",[r("li",[e._v("Rastrear y saber el estado de los fibers, y en caso que esten realizando alguna operación "),r("code",{pre:!0},[e._v("bloqueante")]),e._v(", cual es.")]),r("li",[e._v("Permitir reanudar la ejecucion de los fibers que hicieron una operación bloqueante, y se les retorno un resultado.")])]),r("p",[e._v("Ruby por default no provee una clase "),r("code",{pre:!0},[e._v("scheduler")]),e._v(", pero si una interfaz que debe cumplir, y se espera que sea implementado por el usuario, siguiendo, como se menciono la interfaz descrita en "),r("a",{attrs:{href:"https://ruby-doc.org/core-3.0.0/Fiber/SchedulerInterface.html"}},[e._v("Fiber::SchedulerInterface")]),e._v(".")]),r("p",[e._v("Entonces para implementar un "),r("code",{pre:!0},[e._v("scheduler")]),e._v(", tenemos que implementar los siguientes metodos:")]),r("ul",[r("li",[e._v("io_wait. Se llama ante eventos del tipo "),r("code",{pre:!0},[e._v("IO#wait, IO#wait_readable, IO#wait_writeable")])]),r("li",[e._v("process_wait. Se llama ante eventos de "),r("code",{pre:!0},[e._v("Kernel#sleep, Mutex#sleep")])]),r("li",[e._v("kernel_sleep. Se llama ante eventos de "),r("code",{pre:!0},[e._v("Process::Status.wait")])]),r("li",[e._v("block. Se llama ante eventos de "),r("code",{pre:!0},[e._v("Thread#join, Mutex")])]),r("li",[e._v("unblock. Se llama cuando se desbloquea un fiber por alguno de los eventos antes mencionados")]),r("li",[e._v("close. Se llama cuando el thread donde corren los fibers recibe una señal de salida")])]),r("p",[e._v("por lo que un esqueleto de un scheduler es algo como")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[r("span",{pre:!0,attrs:{class:"hljs-class"}},[r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("class")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("Scheduler")])]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("# trigger by events: IO#wait, IO#wait_readable, IO#wait_writeable")]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-function"}},[r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("io_wait")]),r("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(io, events, timeout)")])]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n\n "),r("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("# trigger by events: Kernel#sleep, Mutex#sleep")]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-function"}},[r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("kernel_sleep")]),r("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(duration = "),r("span",{pre:!0,attrs:{class:"hljs-literal"}},[e._v("nil")]),e._v(")")])]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n\n "),r("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("# trigger by events: Process::Status.wait")]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-function"}},[r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("process_wait")]),r("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(pid, flags)")])]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n\n "),r("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("# trigger by events: Thread#join, Mutex")]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-function"}},[r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("block")]),r("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(blocker, timeout = "),r("span",{pre:!0,attrs:{class:"hljs-literal"}},[e._v("nil")]),e._v(")")])]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n\n "),r("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("# trigger when a previous block called is unblock")]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-function"}},[r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("unblock")]),r("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(blocker, fiber)")])]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n \n "),r("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("# Called when current thread exits")]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-function"}},[r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("close")])]),e._v("\n "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n"),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n")])]),r("p",[e._v("un ejemplo de un scheduler esta en la parte de "),r("a",{attrs:{href:"https://github.com/arquitecturas-concurrentes/ruby-fibers/tree/main/examples/simple_scheduler.rb"}},[e._v("ejemplos")]),e._v(". Un poco basado en el reactor que implementamos en este "),r("a",{attrs:{href:"https://github.com/arquitecturas-concurrentes/iasc-event-loop-reactor-ruby"}},[e._v("repositorio")]),e._v(". En este repo, en "),r("a",{attrs:{href:"https://github.com/arquitecturas-concurrentes/iasc-event-loop-reactor-ruby/blob/master/src/reactor.rb#L117"}},[e._v("cada ciclo de nuestro reactor implementado")]),e._v(", hace un chequeo de "),r("a",{attrs:{href:"https://github.com/arquitecturas-concurrentes/iasc-event-loop-reactor-ruby/blob/master/src/reactor.rb#L122"}},[e._v("los eventos cada un quantum de tiempo determinado")]),e._v(".")]),r("h5",{attrs:{id:"como-usamos-nuestro-scheduler-una-vez-que-lo-tenemos"}},[e._v("Como usamos nuestro scheduler una vez que lo tenemos? "),r("a",{staticClass:"header-anchor",attrs:{href:"#como-usamos-nuestro-scheduler-una-vez-que-lo-tenemos"}},[e._v("¶")])]),r("p",[e._v("Basta con hacer algo como")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("require")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'my_scheduler'")]),e._v("\n\n\nFiber.set_scheduler(MyScheduler.new)\n")])]),r("p",[e._v("después de eso, podemos seguir usando los fibers, como antes en Ruby 2.x")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[r("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("# now using a non-blocking schema through a SimpleScheduler that does not block the Fibers")]),e._v("\nFiber.new "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("do")]),e._v("\n puts "),r("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'Fiber 1: sleep for 2s'")]),e._v("\n sleep("),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("2")]),e._v(")\n puts "),r("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'Fiber 1: wake up'")]),e._v("\n"),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v(".resume\n\nFiber.new "),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("do")]),e._v("\n puts "),r("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'Fiber 2: sleep for 3s'")]),e._v("\n sleep("),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("3")]),e._v(")\n puts "),r("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'Fiber 2: wake up'")]),e._v("\n"),r("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v(".resume\n")])]),r("h3",{attrs:{id:"que-son-los-fibers-por-atras"}},[e._v("Que son los Fibers por atras?? "),r("a",{staticClass:"header-anchor",attrs:{href:"#que-son-los-fibers-por-atras"}},[e._v("¶")])]),r("p",[e._v("En realidad los Fibers, en su implementación al menos en MRI, son en suma ....")]),r("img",{staticClass:"center",attrs:{src:a("0a75")}}),r("p",[e._v("corutinas, simples corutinas.")]),r("p",[e._v("Incluso las mejoras que se introdujeron en Ruby 2.6, son en base a soluciones en C, que ayudaron a mejorar la performance de "),r("code",{pre:!0},[e._v("yield/resume")]),e._v(", en gran medida, usando "),r("code",{pre:!0},[e._v("libcoro")]),e._v(". Se pueden ver mas detalles de esto "),r("a",{attrs:{href:"https://bugs.ruby-lang.org/issues/14739"}},[e._v("aqui")]),e._v(", y una primera implementacion de esta propuesta se puede ver "),r("a",{attrs:{href:"https://github.com/ioquatix/ruby/commit/4a9c12d94aae1cf3a52ca5f026432cd03e9817bc"}},[e._v("aqui")])]),r("p",[e._v("Un ejemplo de como mejoraron los tiempos en su momento puede verse haciendo un simple benchmark, que "),r("a",{attrs:{href:"https://github.com/arquitecturas-concurrentes/ruby-fibers/tree/main/extras/fibers_benchie.rb"}},[e._v("usamos")]),e._v(" y que comparan una version < 2.6 y una en Ruby 3")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v(" Using /home/ernesto/.rvm/gems/ruby-"),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("2.5")]),e._v("."),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v("\n altair.λ"),r("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v(":~/utn/iasc/fibers-ruby/lib")]),e._v("$ ruby fibers_benchie.rb\n "),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1220634.1484423832")]),e._v("/s\n Using /home/ernesto/.rvm/gems/ruby-"),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("3.0")]),e._v("."),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v("-preview1\n altair.λ"),r("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v(":~/utn/iasc/fibers-ruby/lib")]),e._v("$ ruby fibers_benchie.rb\n "),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("4197152.191945104")]),e._v("/s\n")])]),r("p",[e._v("Esta es una librería de "),r("a",{attrs:{href:"http://software.schmorp.de/pkg/libcoro.html"}},[e._v("corutinas en C")]),e._v(", que tiene la implementacion de lo que seria el "),r("code",{pre:!0},[e._v('"context switch"')]),e._v(" entre fibers, que es la parte que en general se va a a estar ejecutando muy a menudo, en "),r("a",{attrs:{href:"http://cvs.schmorp.de/libcoro/coro.c?revision=1.73&view=markup#l223"}},[e._v("assembler")]),e._v(".")]),r("p",[e._v("Hoy en dia, ya no se delega el mecanismo de las corutinas en "),r("code",{pre:!0},[e._v("libcoro")]),e._v(", y se lo trata nativamente, pero con los mismos conceptos. Incluso concepto de que la parte del cambio de contexto de los "),r("code",{pre:!0},[e._v("fibers")]),e._v(" se hace, dependiendo de la arquitectura, con codigo en assembler. "),r("a",{attrs:{href:"https://github.com/ruby/ruby/blob/0ead818d81c975275238878c81f300dd404e0722/coroutine/x86/Context.S#L16"}},[e._v("Ejemplo de x86 ec")]),e._v(", este context switch se llama desde la implementacion nativa de MRI de fibers en C en esta seccion de la funcion "),r("a",{attrs:{href:"https://github.com/ruby/ruby/blob/3d32c217586a48c709b762865a8abc46f9098455/cont.c#L1376"}},[e._v("fiber_setcontext")])]),r("h2",{attrs:{id:"anexo"}},[e._v("Anexo "),r("a",{staticClass:"header-anchor",attrs:{href:"#anexo"}},[e._v("¶")])]),r("h3",{attrs:{id:"sobre-el-tamaño-del-stack-de-threads-y-fibers"}},[e._v("Sobre el tamaño del stack de Threads y Fibers "),r("a",{staticClass:"header-anchor",attrs:{href:"#sobre-el-tamaño-del-stack-de-threads-y-fibers"}},[e._v("¶")])]),r("p",[e._v("El tamaño del stack puede incluso limitar la cantidad de Threads y Fibers que podemos instanciar en una instancia de MRI.")]),r("p",[e._v("Podemos comprobar rápidamente el tamaño de la pila para un "),r("code",{pre:!0},[e._v("Thread")]),e._v(" y para las"),r("code",{pre:!0},[e._v("Fibers")]),e._v(" en ruby ​​comprobando "),r("code",{pre:!0},[e._v("RubyVM :: DEFAULT_PARAMS")]),e._v(" en la consola irb o pry:")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v("pry(main)> RubyVM::DEFAULT_PARAMS\n=> {"),r("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v(":thread_vm_stack_size=>")]),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1048576")]),e._v(",\n "),r("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v(":thread_machine_stack_size=>")]),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1048576")]),e._v(",\n "),r("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v(":fiber_vm_stack_size=>")]),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("131072")]),e._v(",\n "),r("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v(":fiber_machine_stack_size=>")]),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("524288")]),e._v("}\n")])]),r("blockquote",[r("p",[e._v("Esto solo es valido para versiones de Ruby >= 2.0.0")])]),r("p",[e._v("Ahora podemos comprobar rápidamente el tamaño de la pila de los "),r("code",{pre:!0},[e._v("hilos")]),e._v(" tal como están")]),r("p",[e._v("Esto muestra claramente que el tamaño de la pila para los subprocesos en ruby ​​es solo de 1 MB, mientras que el tamaño de la pila para las fibras es de solo 512k. Podemos cambiar esto haciendo una exportación de cada una de las variables, como por ejemplo:")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-dotenv"}},[e._v("export RUBY_FIBER_VM_STACK_SIZE=2097152\nexport RUBY_THREAD_VM_STACK_SIZE=2097152\n")])]),r("p",[e._v("Esto aumentará el tamaño de la pila y las veces que podemos llamar a una pila anidada.")]),r("p",[e._v("Con stack size de 1MB")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v("$ ruby stack_size.rb \nMax Stack "),r("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v("Level:")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("10079")]),e._v("\n")])]),r("p",[e._v("Con un stack de 2MB")]),r("pre",{pre:!0},[r("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v("altair.λ"),r("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v(":~/utn/iasc/fibers-ruby/extras")]),e._v("$ ruby stack_size.rb \nMax Stack "),r("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v("Level:")]),e._v(" "),r("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("20161")]),e._v("\n")])]),r("p",[e._v("Podemos ver que es casi linea la cantidad de veces que podemos llamar al stack con el stack size que tenemos.")]),r("blockquote",[r("p",[e._v("Esto puede variar dependiendo de la información y de los datos que guardemos en el stack.")])])])}],n=a("2877"),o={},l=Object(n["a"])(o,r,t,!1,null,null,null);s["default"]=l.exports},"812c":function(e,s,a){e.exports=a.p+"img/fiversvsthreads.04634cfb.png"},d1ba:function(e,s,a){e.exports=a.p+"img/fiber_status.9c3f958e.png"}}]); +//# sourceMappingURL=chunk-36154627.a6b93af1.js.map \ No newline at end of file diff --git a/js/chunk-36154627.a6b93af1.js.map b/js/chunk-36154627.a6b93af1.js.map new file mode 100644 index 0000000..106e59e --- /dev/null +++ b/js/chunk-36154627.a6b93af1.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/images/fibers/secret.jpg","webpack:///./src/content/fibers.md?b6b1","webpack:///./src/content/fibers.md","webpack:///./src/images/fibers/fiversvsthreads.png","webpack:///./src/images/fibers/fiber_status.png"],"names":["module","exports","render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","pre","script","component"],"mappings":"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","file":"js/chunk-36154627.a6b93af1.js","sourcesContent":["module.exports = __webpack_public_path__ + \"img/secret.4995711d.jpg\";","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h1',{attrs:{\"id\":\"fibers-on-ruby\"}},[_vm._v(\"Fibers on Ruby \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#fibers-on-ruby\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Las fibras son estructuras que implementan un mecanismo de concurrencia cooperativa y liviana en Ruby. Básicamente, son un medio para crear bloques de código que se pueden pausar y reanudar, al igual que los hilos. La principal diferencia es que nunca se planifican implicitamente y que la planificación debe realizarla el programador y no la VM.\")]),_c('p',[_vm._v(\"O sea que en el caso de los \"),_c('code',{pre:true},[_vm._v(\"threads\")]),_vm._v(\", el scheduler se encarga de la planificacion y del manejo del ciclo de vida de esta abstracción. En el caso de los \"),_c('code',{pre:true},[_vm._v(\"fibers\")]),_vm._v(\", esta en nuestras manos la planificación, con lo cual en el código vamos a tener que también tener codigo en cuanto a manejo de los fibers que estamos usando, es decir vamos a tener que explícitamente manejar la planificación. Podemos armar algunas abstracciones pero no suele ser una tarea trivial.\")]),_c('p',[_vm._v(\"A diferencia de otros modelos de concurrencia ligeros sin stack, cada \"),_c('code',{pre:true},[_vm._v(\"fiber\")]),_vm._v(\" viene con un stack. Esto permite que el fiber se pause desde llamadas de función anidadas dentro del bloque del \"),_c('code',{pre:true},[_vm._v(\"Fiber\")]),_vm._v(\".\")]),_c('p',[_vm._v(\"Al ser un esquema colaborativo, nos da un mayor control de la ejecución, y es mas, proporcionan un control total al programador sore su ejecucion como mencionamos antes. Veamos un ejemplo de comparacion en cuanto a los tiempos..\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/fibers/fiversvsthreads.png\")}}),_c('p',[_vm._v(\"Dos threads que se ejecutan, uno se bloquea por 40ms con una llamada de IO, y después toma unos 10ms mas, el procesamiento de estos datos retornados de la llamada. Después hay un segundo thread, que necesita 50ms, de solo tiempo de CPU. El escenario es el mismo tanto con threads, como con fibers y su planificacion cooperativa.\")]),_c('p',[_vm._v(\"Por defecto, MRI usa un \"),_c('code',{pre:true},[_vm._v(\"fair scheduler\")]),_vm._v(\" (\"),_c('a',{attrs:{\"href\":\"https://es.wikipedia.org/wiki/Planificador_Completamente_Justo\"}},[_vm._v(\"mas aqui\")]),_vm._v(\"), que significa que cada thread recibe un mismo tiempo para ejecutar, con quantums de 10ms, antes que se suspendan y que el proximo thread se ponga bajo control. Si uno de los threads esta dentro de una llamada bloquante dentro de esos 10ms, se lo debe tomar como tiempo malgastado, es tiempo en el que seguramente todos los threads estan descansando, por estar bloqueados o esperando I/O. Por el otro lado, los Fibers, al ser scheduleados explicitamente por el programador, o sea nosotros, nos da una flexibilidad a la hora de determinar cuando debemos parar la ejecucion de nuestro fiber y cuando retomarlo. Esto trae, como desventaja, que tenemos ahora un codigo mas complejo, pero a su vez nos ayudan, en que en un caso casi ideal, no necesitemos casi el uso de locks.\")]),_c('blockquote',[_c('p',[_vm._v(\"Nota: Desde Ruby 3.0, el concepto de los \"),_c('code',{pre:true},[_vm._v(\"non-blocking fibers\")]),_vm._v(\" fue introducido. Todos los fibers ya son por defecto no bloqueantes. Mas sobre esto en la seccion de Ruby 3.\")])]),_c('h3',{attrs:{\"id\":\"diferencias-que-vemos-entre-los-threads-y-fibers\"}},[_vm._v(\"Diferencias que vemos entre los threads y fibers \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#diferencias-que-vemos-entre-los-threads-y-fibers\"}},[_vm._v(\"¶\")])]),_c('blockquote',[_c('p',[_vm._v(\"TL;DR..\")])]),_c('ul',[_c('li',[_vm._v(\"Los Fibers son ligeros en cuanto a la memoria que consumen y los tiempos del ciclo de vida\")]),_c('li',[_vm._v(\"Tenemos el control de los Fibers, de manera explicita, o sea que tenemos el control absoluto de su ciclo de vida y planificacion.\")]),_c('li',[_vm._v(\"Si bien con los threads tenemos al scheduler que decide cuando un thread se pausa o reanuda, en el caso de los Fibers es variable. O sea, al tener el control nosotros de la planificacion, tenemos que especificar cuando iniciar y parar la ejecucion de un Fiber.\")]),_c('li',[_vm._v(\"Los Fibers, son maneras de escribir bloques de codigo, que pueden ser pausados o resumidos, bastante parecidos a los threads, pero con la diferencia de la planificacion de nuestro lado.\")]),_c('li',[_vm._v(\"Los \"),_c('code',{pre:true},[_vm._v(\"Threads\")]),_vm._v(\" se ejecutan en un segundo plano, especialmente cuando hay una interrupcion. En el caso de los Fibers, se convierten en el programa principal, cuando se ejecutan, hasta que uno los para.\")])]),_c('h3',{attrs:{\"id\":\"uso-y-estados-de-los-fibers\"}},[_vm._v(\"Uso y estados de los Fibers \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#uso-y-estados-de-los-fibers\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Para invocar un fiber, basta con hacer algo como lo siguiente\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\"f = Fiber.new { puts \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'blah'\")]),_vm._v(\" }\\n\\nf.resume \\nblah\\n=> nil\\n\")])]),_c('p',[_vm._v(\"Algo interesante para mostrar es que un Fiber no se ejecuta automaticamente, luego de su creacion, sino que necesita que se llame primero a \"),_c('code',{pre:true},[_vm._v(\"Fiber#resume\")]),_vm._v(\" antes. Y seguira en el estado de \"),_c('code',{pre:true},[_vm._v(\"FIBER_RESUMED\")]),_vm._v(\", hasta que se pare su ejecucion o que termine de ejecutar todo el codigo que contiene en su bloque.\")]),_c('p',[_vm._v(\"Como se para un fiber?? por medio de \"),_c('code',{pre:true},[_vm._v(\"Fiber#yield\")]),_vm._v(\". se puede ver este ejemplo en el \"),_c('a',{attrs:{\"href\":\"https://github.com/arquitecturas-concurrentes/ruby-fibers/tree/main/examples/fibers_1.rb\"}},[_vm._v(\"fiber_1\")])]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\"fiber = Fiber.new \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"do\")]),_vm._v(\"\\n puts \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'hola 1'\")]),_vm._v(\"\\n Fiber.\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"yield\")]),_vm._v(\"\\n puts \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'hola 2'\")]),_vm._v(\"\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\")])]),_c('p',[_vm._v(\"en el momento que se ejecuta por primera vez \"),_c('code',{pre:true},[_vm._v(\"fiber.resume\")]),_vm._v(\", solo se ejecutara el primer puts, y cuando se llame a yield, el fiber actual se para y pasa su estado a \"),_c('code',{pre:true},[_vm._v(\"FIBER_SUSPENDED\")]),_vm._v(\". Solo una vez que se llame de nuevo a \"),_c('code',{pre:true},[_vm._v(\"fiber.resume\")]),_vm._v(\", se ejecutara el resto del codigo. Una pregunta valida puede ser, que pasa si una vez que corre todo el codigo del bloque que contiene el fiber, se llama de nuevo a \"),_c('code',{pre:true},[_vm._v(\"fiber.resume\")]),_vm._v(\"??\")]),_c('p',[_vm._v(\"Es una buena pregunta y es que una vez que termina, pasa su estado a \"),_c('code',{pre:true},[_vm._v(\"FIBER_TERMINATED\")]),_vm._v(\". Con lo cual nos va a dar un error:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\"[\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"5\")]),_vm._v(\"] pry(main)> fiber.resume\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\"FiberError:\")]),_vm._v(\" dead fiber called\\nfrom (pry)\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\":\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"9\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\":in\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"`resume'\\n\")])])]),_c('p',[_vm._v(\"Para siempre chequear este estado tenemos un metodo que es \"),_c('code',{pre:true},[_vm._v(\"Fiber#alive?\")]),_vm._v(\", que nos devuelve un booleano, de si un fiber esta vivo o no. Sobre nuestro ejemplo anterior:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\"[\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"6\")]),_vm._v(\"] pry(main)> fiber.alive?\\n=> false\\n\")])]),_c('p',[_vm._v(\"Un diagrama de transicion de los estados de un Fiber se puede ver a continuacion.\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/fibers/fiber_status.png\")}}),_c('h4',{attrs:{\"id\":\"para-que-sirven-los-fibers\"}},[_vm._v(\"Para que sirven los fibers? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#para-que-sirven-los-fibers\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Este tipo de abstracciones que modelan un contexto de ejecución, no se usan normalmente, sino que es algo que en general se utiliza en una libreria, implementando otras abstracciones sobre y que usen los fibers, para manejar bien los eventos, cuando parar un fiber y reanudarlo, y despues que nuestro codigo de aplicacion use a esta libreria, sin saber los detalles y que no tenga que operar usando fibers directamente.\")]),_c('p',[_vm._v(\"Un ejemplo de esto, puede verse, si implementamos un \"),_c('code',{pre:true},[_vm._v(\"reactor\")]),_vm._v(\", que es un \"),_c('a',{attrs:{\"href\":\"https://en.wikipedia.org/wiki/Reactor_pattern#:~:text=The%20reactor%20design%20pattern%20is,to%20the%20associated%20request%20handlers.\"}},[_vm._v(\"patron de diseno\")]),_vm._v(\" que nos va a permitir manejar eventos. Hay muchas manera de implementar un reactor. Vimos hace poco que el \"),_c('code',{pre:true},[_vm._v(\"event loop\")]),_vm._v(\" usa \"),_c('a',{attrs:{\"href\":\"https://man7.org/linux/man-pages/man2/epoll_wait.2.html\"}},[_vm._v(\"epoll\")]),_vm._v(\" para saber de nuevos eventos disponibles, que le llegan a un puerto. Otra manera, aunque no tan efectiva, pero mas sencilla de lograr, puede ser mediante \"),_c('a',{attrs:{\"href\":\"https://man7.org/linux/man-pages/man2/select.2.html\"}},[_vm._v(\"select\")]),_vm._v(\".\")]),_c('p',[_vm._v(\"Con \"),_c('code',{pre:true},[_vm._v(\"select\")]),_vm._v(\", que esta presente en Ruby, mediante un wrapper en \"),_c('code',{pre:true},[_vm._v(\"IO\")]),_vm._v(\", podemos implementar un \"),_c('code',{pre:true},[_vm._v(\"reactor\")]),_vm._v(\" simple. Un ejemplo de la cátedra, que usa una implementación mas completa con \"),_c('code',{pre:true},[_vm._v(\"timers\")]),_vm._v(\" y otras abstracciones se puede ver en este \"),_c('a',{attrs:{\"href\":\"https://github.com/arquitecturas-concurrentes/iasc-event-loop-reactor-ruby\"}},[_vm._v(\"repositorio\")]),_vm._v(\".\")]),_c('p',[_vm._v(\"De una manera mucho mas simple, podemos tener una clase \"),_c('code',{pre:true},[_vm._v(\"Reactor\")]),_vm._v(\", que tenga dos mapas para eventos de escritura o lectura.\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-class\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"class\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"Reactor\")])]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"initialize\")])]),_vm._v(\"\\n @readable = {}\\n @writable = {}\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"#...\")]),_vm._v(\"\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\")])]),_c('p',[_vm._v(\"y que tenga un ciclo de corridas en el que se esperan a que los eventos que esten encolados, la parte interesante de este codigo:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-class\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"class\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"Reactor\")])]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"initialize\")])]),_vm._v(\"\\n @readable = {}\\n @writable = {}\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"run\")])]),_vm._v(\"\\n _error_events = [] \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"# unused for now...\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"while\")]),_vm._v(\" @readable.any? \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"||\")]),_vm._v(\" @writable.any?\\n readable, writable = IO.select(@readable.keys, @writable.keys, _error_events)\\n\\n readable.each \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"do\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"|io|\")]),_vm._v(\"\\n @readable[io].resume\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\\n writable.each \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"do\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"|io|\")]),_vm._v(\"\\n @writable[io].resume\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\")])]),_c('p',[_vm._v(\"esta en la línea del select\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\"readable, writable = IO.select(@readable.keys, @writable.keys, _error_events)\\n\")])]),_c('p',[_vm._v(\"donde se esperan a que los eventos que tienen una llamada de IO pendiente terminen.\")]),_c('p',[_vm._v(\"Sobre el Reactor se pueden armar otras abstracicones, tales como un servidor de TCP\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\"server = TCPServer.new(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'localhost'\")]),_vm._v(\", port)\\nputs \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"\\\"Listening on 127.0.0.1:\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-subst\"}},[_vm._v(\"#{port}\")]),_vm._v(\"\\\"\")]),_vm._v(\"\\nreactor = Reactor.new\\n\")])]),_c('p',[_vm._v(\"y que use en un loop la aceptación de la conexión\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\"loop \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"do\")]),_vm._v(\"\\n client = reactor.wait_readable(server) { server.accept } \\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"# ....\")]),_vm._v(\"\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\")])]),_c('p',[_vm._v(\"despues hay que esperar desde el servidor a que termine el handshake contra el cliente, por lo que eso es otra llamada, y por lo tanto otro evento...\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\"reactor.wait_readable(client) { client.gets })\\n\")])]),_c('p',[_vm._v(\"Como unimos estos eventos en el reactor? Mediante alguna abstracción, o contexto de ejecución, que pueda bueno... ejecutarlas. Aquí es donde entran los Fibers..\")]),_c('p',[_vm._v(\"El loop queda entonces, como\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\"loop \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"do\")]),_vm._v(\"\\n client = reactor.wait_readable(server) { server.accept }\\n\\n Fiber.new \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"do\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"while\")]),_vm._v(\" (_buffer = reactor.wait_readable(client) { client.gets })\\n reactor.wait_writable(client)\\n client.puts(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"\\\"Pong!\\\"\")]),_vm._v(\")\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\\n client.close\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\".resume \\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\")])]),_c('p',[_vm._v(\"Despues hay que wrapear el loop en un ctx similar general, que es otro fiber y listo..\")]),_c('p',[_vm._v(\"El reactor toma los bloques de los eventos de io server y client como bloques que se ejecutaran como otros \"),_c('code',{pre:true},[_vm._v(\"fibers\")]),_vm._v(\".\")]),_c('p',[_vm._v(\"El ejemplo esta en este \"),_c('a',{attrs:{\"href\":\"https://github.com/arquitecturas-concurrentes/ruby-fibers/tree/main/examples/socket/tcp_reactor.rb\"}},[_vm._v(\"archivo\")])]),_c('h3',{attrs:{\"id\":\"fibers-en-ruby-30\"}},[_vm._v(\"Fibers en Ruby 3.0 \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#fibers-en-ruby-30\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Entre otras cosas Ruby 3, introduce el concepto de \"),_c('code',{pre:true},[_vm._v(\"fibers\")]),_vm._v(\" no bloqueantes. Ahora cuando hacemos un \"),_c('code',{pre:true},[_vm._v(\"Fiber.new() do ... end\")]),_vm._v(\", se le puede pasar un flag booleano llamado \"),_c('code',{pre:true},[_vm._v(\"blocking\")]),_vm._v(\". Por defecto el valor de este booleano es \"),_c('code',{pre:true},[_vm._v(\"false\")])]),_c('p',[_vm._v(\"Cuando se le pasa el valor \"),_c('code',{pre:true},[_vm._v(\"blocking: true\")]),_vm._v(\", el \"),_c('code',{pre:true},[_vm._v(\"Fiber\")]),_vm._v(\" se va a comportar como lo hacia en Ruby 2.x.\")]),_c('p',[_vm._v(\"Lo interesante es cuando no se le pasa este flag o el valor es \"),_c('code',{pre:true},[_vm._v(\"blocking: false\")]),_vm._v(\". Esto permite que el Fiber sea \"),_c('code',{pre:true},[_vm._v(\"no bloqueante\")]),_vm._v(\".\")]),_c('p',[_vm._v(\"Los \"),_c('code',{pre:true},[_vm._v(\"fibers no bloqueantes\")]),_vm._v(\", cuando llegan en el codigo que ejecutan, a una zona que es potencialmente bloqueante (sleep, esperar otro proceso, esperar datos de I/O, etc), en vez de congelarse y parar toda la ejecucion del thread, hace un \"),_c('code',{pre:true},[_vm._v(\"yield\")]),_vm._v(\" implicito, y permite que otros fibers tomen el control. Esto si se maneja mendiante un scheduler, permite que se pueda manejar bien a que fiber se le puede dar prioridad\")]),_c('p',[_vm._v(\"Que es el \"),_c('code',{pre:true},[_vm._v(\"scheduler\")]),_vm._v(\"?? En realidad la pregunta correcta sería, como nos damos cuenta ahora con un esquema \"),_c('code',{pre:true},[_vm._v(\"no bloquante\")]),_vm._v(\" cuando tenemos una respuesta con la cual nos va a surgir una nueva duda. Cómo podemos seguir con la ejecución de nuestro fiber? Esto surge porque aun tenemos que planificar a los fibers.\")]),_c('p',[_vm._v(\"Para poder saber y manejar cuando tenemos una respuesta, tendremos un \"),_c('code',{pre:true},[_vm._v(\"scheduler\")]),_vm._v(\", y en si es una clase que simula algo similar a un \"),_c('code',{pre:true},[_vm._v(\"event loop\")]),_vm._v(\". Nos va a permitir:\")]),_c('ul',[_c('li',[_vm._v(\"Rastrear y saber el estado de los fibers, y en caso que esten realizando alguna operación \"),_c('code',{pre:true},[_vm._v(\"bloqueante\")]),_vm._v(\", cual es.\")]),_c('li',[_vm._v(\"Permitir reanudar la ejecucion de los fibers que hicieron una operación bloqueante, y se les retorno un resultado.\")])]),_c('p',[_vm._v(\"Ruby por default no provee una clase \"),_c('code',{pre:true},[_vm._v(\"scheduler\")]),_vm._v(\", pero si una interfaz que debe cumplir, y se espera que sea implementado por el usuario, siguiendo, como se menciono la interfaz descrita en \"),_c('a',{attrs:{\"href\":\"https://ruby-doc.org/core-3.0.0/Fiber/SchedulerInterface.html\"}},[_vm._v(\"Fiber::SchedulerInterface\")]),_vm._v(\".\")]),_c('p',[_vm._v(\"Entonces para implementar un \"),_c('code',{pre:true},[_vm._v(\"scheduler\")]),_vm._v(\", tenemos que implementar los siguientes metodos:\")]),_c('ul',[_c('li',[_vm._v(\"io_wait. Se llama ante eventos del tipo \"),_c('code',{pre:true},[_vm._v(\"IO#wait, IO#wait_readable, IO#wait_writeable\")])]),_c('li',[_vm._v(\"process_wait. Se llama ante eventos de \"),_c('code',{pre:true},[_vm._v(\"Kernel#sleep, Mutex#sleep\")])]),_c('li',[_vm._v(\"kernel_sleep. Se llama ante eventos de \"),_c('code',{pre:true},[_vm._v(\"Process::Status.wait\")])]),_c('li',[_vm._v(\"block. Se llama ante eventos de \"),_c('code',{pre:true},[_vm._v(\"Thread#join, Mutex\")])]),_c('li',[_vm._v(\"unblock. Se llama cuando se desbloquea un fiber por alguno de los eventos antes mencionados\")]),_c('li',[_vm._v(\"close. Se llama cuando el thread donde corren los fibers recibe una señal de salida\")])]),_c('p',[_vm._v(\"por lo que un esqueleto de un scheduler es algo como\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-class\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"class\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"Scheduler\")])]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"# trigger by events: IO#wait, IO#wait_readable, IO#wait_writeable\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"io_wait\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(io, events, timeout)\")])]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"# trigger by events: Kernel#sleep, Mutex#sleep\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"kernel_sleep\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(duration = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-literal\"}},[_vm._v(\"nil\")]),_vm._v(\")\")])]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"# trigger by events: Process::Status.wait\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"process_wait\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(pid, flags)\")])]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"# trigger by events: Thread#join, Mutex\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"block\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(blocker, timeout = \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-literal\"}},[_vm._v(\"nil\")]),_vm._v(\")\")])]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"# trigger when a previous block called is unblock\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"unblock\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(blocker, fiber)\")])]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n \\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"# Called when current thread exits\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"close\")])]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\")])]),_c('p',[_vm._v(\"un ejemplo de un scheduler esta en la parte de \"),_c('a',{attrs:{\"href\":\"https://github.com/arquitecturas-concurrentes/ruby-fibers/tree/main/examples/simple_scheduler.rb\"}},[_vm._v(\"ejemplos\")]),_vm._v(\". Un poco basado en el reactor que implementamos en este \"),_c('a',{attrs:{\"href\":\"https://github.com/arquitecturas-concurrentes/iasc-event-loop-reactor-ruby\"}},[_vm._v(\"repositorio\")]),_vm._v(\". En este repo, en \"),_c('a',{attrs:{\"href\":\"https://github.com/arquitecturas-concurrentes/iasc-event-loop-reactor-ruby/blob/master/src/reactor.rb#L117\"}},[_vm._v(\"cada ciclo de nuestro reactor implementado\")]),_vm._v(\", hace un chequeo de \"),_c('a',{attrs:{\"href\":\"https://github.com/arquitecturas-concurrentes/iasc-event-loop-reactor-ruby/blob/master/src/reactor.rb#L122\"}},[_vm._v(\"los eventos cada un quantum de tiempo determinado\")]),_vm._v(\".\")]),_c('h5',{attrs:{\"id\":\"como-usamos-nuestro-scheduler-una-vez-que-lo-tenemos\"}},[_vm._v(\"Como usamos nuestro scheduler una vez que lo tenemos? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#como-usamos-nuestro-scheduler-una-vez-que-lo-tenemos\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Basta con hacer algo como\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"require\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'my_scheduler'\")]),_vm._v(\"\\n\\n\\nFiber.set_scheduler(MyScheduler.new)\\n\")])]),_c('p',[_vm._v(\"después de eso, podemos seguir usando los fibers, como antes en Ruby 2.x\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"# now using a non-blocking schema through a SimpleScheduler that does not block the Fibers\")]),_vm._v(\"\\nFiber.new \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"do\")]),_vm._v(\"\\n puts \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'Fiber 1: sleep for 2s'\")]),_vm._v(\"\\n sleep(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"2\")]),_vm._v(\")\\n puts \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'Fiber 1: wake up'\")]),_vm._v(\"\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\".resume\\n\\nFiber.new \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"do\")]),_vm._v(\"\\n puts \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'Fiber 2: sleep for 3s'\")]),_vm._v(\"\\n sleep(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"3\")]),_vm._v(\")\\n puts \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'Fiber 2: wake up'\")]),_vm._v(\"\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\".resume\\n\")])]),_c('h3',{attrs:{\"id\":\"que-son-los-fibers-por-atras\"}},[_vm._v(\"Que son los Fibers por atras?? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#que-son-los-fibers-por-atras\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"En realidad los Fibers, en su implementación al menos en MRI, son en suma ....\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/fibers/secret.jpg\")}}),_c('p',[_vm._v(\"corutinas, simples corutinas.\")]),_c('p',[_vm._v(\"Incluso las mejoras que se introdujeron en Ruby 2.6, son en base a soluciones en C, que ayudaron a mejorar la performance de \"),_c('code',{pre:true},[_vm._v(\"yield/resume\")]),_vm._v(\", en gran medida, usando \"),_c('code',{pre:true},[_vm._v(\"libcoro\")]),_vm._v(\". Se pueden ver mas detalles de esto \"),_c('a',{attrs:{\"href\":\"https://bugs.ruby-lang.org/issues/14739\"}},[_vm._v(\"aqui\")]),_vm._v(\", y una primera implementacion de esta propuesta se puede ver \"),_c('a',{attrs:{\"href\":\"https://github.com/ioquatix/ruby/commit/4a9c12d94aae1cf3a52ca5f026432cd03e9817bc\"}},[_vm._v(\"aqui\")])]),_c('p',[_vm._v(\"Un ejemplo de como mejoraron los tiempos en su momento puede verse haciendo un simple benchmark, que \"),_c('a',{attrs:{\"href\":\"https://github.com/arquitecturas-concurrentes/ruby-fibers/tree/main/extras/fibers_benchie.rb\"}},[_vm._v(\"usamos\")]),_vm._v(\" y que comparan una version < 2.6 y una en Ruby 3\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\" Using /home/ernesto/.rvm/gems/ruby-\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"2.5\")]),_vm._v(\".\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\"\\n altair.λ\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\":~/utn/iasc/fibers-ruby/lib\")]),_vm._v(\"$ ruby fibers_benchie.rb\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1220634.1484423832\")]),_vm._v(\"/s\\n Using /home/ernesto/.rvm/gems/ruby-\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"3.0\")]),_vm._v(\".\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\"-preview1\\n altair.λ\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\":~/utn/iasc/fibers-ruby/lib\")]),_vm._v(\"$ ruby fibers_benchie.rb\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"4197152.191945104\")]),_vm._v(\"/s\\n\")])]),_c('p',[_vm._v(\"Esta es una librería de \"),_c('a',{attrs:{\"href\":\"http://software.schmorp.de/pkg/libcoro.html\"}},[_vm._v(\"corutinas en C\")]),_vm._v(\", que tiene la implementacion de lo que seria el \"),_c('code',{pre:true},[_vm._v(\"\\\"context switch\\\"\")]),_vm._v(\" entre fibers, que es la parte que en general se va a a estar ejecutando muy a menudo, en \"),_c('a',{attrs:{\"href\":\"http://cvs.schmorp.de/libcoro/coro.c?revision=1.73&view=markup#l223\"}},[_vm._v(\"assembler\")]),_vm._v(\".\")]),_c('p',[_vm._v(\"Hoy en dia, ya no se delega el mecanismo de las corutinas en \"),_c('code',{pre:true},[_vm._v(\"libcoro\")]),_vm._v(\", y se lo trata nativamente, pero con los mismos conceptos. Incluso concepto de que la parte del cambio de contexto de los \"),_c('code',{pre:true},[_vm._v(\"fibers\")]),_vm._v(\" se hace, dependiendo de la arquitectura, con codigo en assembler. \"),_c('a',{attrs:{\"href\":\"https://github.com/ruby/ruby/blob/0ead818d81c975275238878c81f300dd404e0722/coroutine/x86/Context.S#L16\"}},[_vm._v(\"Ejemplo de x86 ec\")]),_vm._v(\", este context switch se llama desde la implementacion nativa de MRI de fibers en C en esta seccion de la funcion \"),_c('a',{attrs:{\"href\":\"https://github.com/ruby/ruby/blob/3d32c217586a48c709b762865a8abc46f9098455/cont.c#L1376\"}},[_vm._v(\"fiber_setcontext\")])]),_c('h2',{attrs:{\"id\":\"anexo\"}},[_vm._v(\"Anexo \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#anexo\"}},[_vm._v(\"¶\")])]),_c('h3',{attrs:{\"id\":\"sobre-el-tamaño-del-stack-de-threads-y-fibers\"}},[_vm._v(\"Sobre el tamaño del stack de Threads y Fibers \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#sobre-el-tamaño-del-stack-de-threads-y-fibers\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"El tamaño del stack puede incluso limitar la cantidad de Threads y Fibers que podemos instanciar en una instancia de MRI.\")]),_c('p',[_vm._v(\"Podemos comprobar rápidamente el tamaño de la pila para un \"),_c('code',{pre:true},[_vm._v(\"Thread\")]),_vm._v(\" y para las\"),_c('code',{pre:true},[_vm._v(\"Fibers\")]),_vm._v(\" en ruby ​​comprobando \"),_c('code',{pre:true},[_vm._v(\"RubyVM :: DEFAULT_PARAMS\")]),_vm._v(\" en la consola irb o pry:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\"pry(main)> RubyVM::DEFAULT_PARAMS\\n=> {\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\":thread_vm_stack_size=>\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1048576\")]),_vm._v(\",\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\":thread_machine_stack_size=>\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1048576\")]),_vm._v(\",\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\":fiber_vm_stack_size=>\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"131072\")]),_vm._v(\",\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\":fiber_machine_stack_size=>\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"524288\")]),_vm._v(\"}\\n\")])]),_c('blockquote',[_c('p',[_vm._v(\"Esto solo es valido para versiones de Ruby >= 2.0.0\")])]),_c('p',[_vm._v(\"Ahora podemos comprobar rápidamente el tamaño de la pila de los \"),_c('code',{pre:true},[_vm._v(\"hilos\")]),_vm._v(\" tal como están\")]),_c('p',[_vm._v(\"Esto muestra claramente que el tamaño de la pila para los subprocesos en ruby ​​es solo de 1 MB, mientras que el tamaño de la pila para las fibras es de solo 512k. Podemos cambiar esto haciendo una exportación de cada una de las variables, como por ejemplo:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-dotenv\"}},[_vm._v(\"export RUBY_FIBER_VM_STACK_SIZE=2097152\\nexport RUBY_THREAD_VM_STACK_SIZE=2097152\\n\")])]),_c('p',[_vm._v(\"Esto aumentará el tamaño de la pila y las veces que podemos llamar a una pila anidada.\")]),_c('p',[_vm._v(\"Con stack size de 1MB\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\"$ ruby stack_size.rb \\nMax Stack \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\"Level:\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"10079\")]),_vm._v(\"\\n\")])]),_c('p',[_vm._v(\"Con un stack de 2MB\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\"altair.λ\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\":~/utn/iasc/fibers-ruby/extras\")]),_vm._v(\"$ ruby stack_size.rb \\nMax Stack \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\"Level:\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"20161\")]),_vm._v(\"\\n\")])]),_c('p',[_vm._v(\"Podemos ver que es casi linea la cantidad de veces que podemos llamar al stack con el stack size que tenemos.\")]),_c('blockquote',[_c('p',[_vm._v(\"Esto puede variar dependiendo de la información y de los datos que guardemos en el stack.\")])])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./fibers.md?vue&type=template&id=649acd14&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","module.exports = __webpack_public_path__ + \"img/fiversvsthreads.04634cfb.png\";","module.exports = __webpack_public_path__ + \"img/fiber_status.9c3f958e.png\";"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-49b1d262.6ee7301b.js b/js/chunk-49b1d262.6ee7301b.js new file mode 100644 index 0000000..a60b3ea --- /dev/null +++ b/js/chunk-49b1d262.6ee7301b.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-49b1d262"],{"0d00":function(e,a,s){e.exports=s.p+"img/1.1ca539fd.png"},"7b02":function(e,a,s){"use strict";s.r(a);var n=function(){var e=this,a=e.$createElement;e._self._c;return e._m(0)},o=[function(){var e=this,a=e.$createElement,n=e._self._c||a;return n("section",[n("h2",{attrs:{id:"interleaving-y-netsplits"}},[e._v("Interleaving y netsplits "),n("a",{staticClass:"header-anchor",attrs:{href:"#interleaving-y-netsplits"}},[e._v("¶")])]),n("img",{staticClass:"center iasc-image",attrs:{src:s("b98f")}}),n("p",[e._v("Sucede a veces cuando tenemos una interconexión entre nodos, momentos en los que tal vez un nodo no empieza a responder a los heartbeats y perdemos conocimiento de él, después de un tiempo tendremos que asumir que esta muerto.")]),n("img",{staticClass:"center iasc-image",attrs:{src:s("0d00")}}),n("p",[e._v("En general se asume, y también en lenguajes que nos ayudan con algunos temas de distribución como Erlang, que si un nodo no se puede conocer si está vivo, está muerto, que es el caso más pesimista que es cuando se piensa que hay más fallos de hardware/software que de red. Otro esquema sería el optimista en el que el nodo está vivo y en realidad lo que pasó es que por un momento la red se cayó o había demasiada latencia y no llegaba al nodo extraviado. Este esquema supone que es más frecuente el fallo de red que de hardware/software. Imaginemos un sitio de compra y venta tipo mercadolibre con dos nodos y sucede este esquema, cuando se realizar una transacción en un nodo, se debe también sincronizar la transacción en el otro nodo ya que puede existir el caso que una de las dos partes tiene su cuenta en otro nodo, si funciona todo bien no hay problemas, pero en el caso de que uno de los nodos no responda, y luego en realidad haya pasado que había un fallo de la red, el nodo queda desincronizado, pero el esquema que tomemos puede tener una desventaja u otra, el pesimista es que no permita que haya transacciones y en consecuencia perdamos plata, no cobramos la comisión, pero el otro caso si es optimista, puede suceder que haya un interleave que deje que dos personas compre un mismo productos en los dos nodos y después no se sepa quien ganó.")])])}],t=s("2877"),r={},i=Object(t["a"])(r,n,o,!1,null,null,null);a["default"]=i.exports},b98f:function(e,a,s){e.exports=s.p+"img/0.a5ade99c.png"}}]); +//# sourceMappingURL=chunk-49b1d262.6ee7301b.js.map \ No newline at end of file diff --git a/js/chunk-49b1d262.6ee7301b.js.map b/js/chunk-49b1d262.6ee7301b.js.map new file mode 100644 index 0000000..aa3401f --- /dev/null +++ b/js/chunk-49b1d262.6ee7301b.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/images/interleaving/1.png","webpack:///./src/content/interleaving.md?bab3","webpack:///./src/content/interleaving.md","webpack:///./src/images/interleaving/0.png"],"names":["module","exports","render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","script","component"],"mappings":"qGAAAA,EAAOC,QAAU,IAA0B,sB,2CCA3C,IAAIC,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAsBH,EAAII,MAAMC,GAAO,OAAOL,EAAIM,GAAG,IACnGC,EAAkB,CAAC,WAAa,IAAIP,EAAIC,KAASC,EAAGF,EAAIG,eAAmBE,EAAGL,EAAII,MAAMC,IAAIH,EAAG,OAAOG,EAAG,UAAU,CAACA,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,6BAA6B,CAACR,EAAIS,GAAG,6BAA6BJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,8BAA8B,CAACR,EAAIS,GAAG,SAASJ,EAAG,MAAM,CAACK,YAAY,oBAAoBF,MAAM,CAAC,IAAM,EAAQ,WAAkCH,EAAG,IAAI,CAACL,EAAIS,GAAG,wOAAwOJ,EAAG,MAAM,CAACK,YAAY,oBAAoBF,MAAM,CAAC,IAAM,EAAQ,WAAkCH,EAAG,IAAI,CAACL,EAAIS,GAAG,u1C,YCApvBE,EAAS,GAKTC,EAAY,eACdD,EACAZ,EACAQ,GACA,EACA,KACA,KACA,MAIa,aAAAK,E,8BCjBff,EAAOC,QAAU,IAA0B","file":"js/chunk-49b1d262.6ee7301b.js","sourcesContent":["module.exports = __webpack_public_path__ + \"img/1.1ca539fd.png\";","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h2',{attrs:{\"id\":\"interleaving-y-netsplits\"}},[_vm._v(\"Interleaving y netsplits \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#interleaving-y-netsplits\"}},[_vm._v(\"¶\")])]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/interleaving/0.png\")}}),_c('p',[_vm._v(\"Sucede a veces cuando tenemos una interconexión entre nodos, momentos en los que tal vez un nodo no empieza a responder a los heartbeats y perdemos conocimiento de él, después de un tiempo tendremos que asumir que esta muerto.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/interleaving/1.png\")}}),_c('p',[_vm._v(\"En general se asume, y también en lenguajes que nos ayudan con algunos temas de distribución como Erlang, que si un nodo no se puede conocer si está vivo, está muerto, que es el caso más pesimista que es cuando se piensa que hay más fallos de hardware/software que de red. Otro esquema sería el optimista en el que el nodo está vivo y en realidad lo que pasó es que por un momento la red se cayó o había demasiada latencia y no llegaba al nodo extraviado. Este esquema supone que es más frecuente el fallo de red que de hardware/software. Imaginemos un sitio de compra y venta tipo mercadolibre con dos nodos y sucede este esquema, cuando se realizar una transacción en un nodo, se debe también sincronizar la transacción en el otro nodo ya que puede existir el caso que una de las dos partes tiene su cuenta en otro nodo, si funciona todo bien no hay problemas, pero en el caso de que uno de los nodos no responda, y luego en realidad haya pasado que había un fallo de la red, el nodo queda desincronizado, pero el esquema que tomemos puede tener una desventaja u otra, el pesimista es que no permita que haya transacciones y en consecuencia perdamos plata, no cobramos la comisión, pero el otro caso si es optimista, puede suceder que haya un interleave que deje que dos personas compre un mismo productos en los dos nodos y después no se sepa quien ganó.\")])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./interleaving.md?vue&type=template&id=df3e3ce2&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","module.exports = __webpack_public_path__ + \"img/0.a5ade99c.png\";"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-4c048be9.9564d16d.js b/js/chunk-4c048be9.9564d16d.js new file mode 100644 index 0000000..fb3fc50 --- /dev/null +++ b/js/chunk-4c048be9.9564d16d.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-4c048be9"],{7949:function(a,e,t){"use strict";t.r(e);var s=function(){var a=this,e=a.$createElement;a._self._c;return a._m(0)},n=[function(){var a=this,e=a.$createElement,s=a._self._c||e;return s("section",[s("p",[a._v("Esta es una pagina donde se van a ir actualizando el material y contenido de la materia.")]),s("h2",{attrs:{id:"objetivo"}},[a._v("Objetivo "),s("a",{staticClass:"header-anchor",attrs:{href:"#objetivo"}},[a._v("¶")])]),s("p",[a._v("Un poco la idea de esta seccion de la pagina de Arquitecturas Concurrentes es la de tener un lugar donde tengamos material para que puedan estudiar o como complemento despues de la clase. La idea es que esta pagina se vaya actualizando y ampliando de manera iterativa e incremental :)")]),s("h2",{attrs:{id:"kiss"}},[a._v("KISS "),s("a",{staticClass:"header-anchor",attrs:{href:"#kiss"}},[a._v("¶")])]),s("img",{staticClass:"center",attrs:{src:t("c8b4")}}),s("p",[a._v("La idea es tener una UI bastante basica, y que solo sea lo minimo indispensable para mostrar lo que mas nos importa, que es mostrar contenido sobre algun tema puntual de la materia.")]),s("h2",{attrs:{id:"got-typo"}},[a._v("Got typo? "),s("a",{staticClass:"header-anchor",attrs:{href:"#got-typo"}},[a._v("¶")])]),s("p",[a._v("Si alguno detecta algun problema o error puede levantar un nuevo issue y veremos de arreglar el mismo lo antes posible.")])])}],r=t("2877"),o={},i=Object(r["a"])(o,s,n,!1,null,null,null);e["default"]=i.exports},c8b4:function(a,e,t){a.exports=t.p+"img/principio-kiss.6dc64b42.jpg"}}]); +//# sourceMappingURL=chunk-4c048be9.9564d16d.js.map \ No newline at end of file diff --git a/js/chunk-4c048be9.9564d16d.js.map b/js/chunk-4c048be9.9564d16d.js.map new file mode 100644 index 0000000..7f56e58 --- /dev/null +++ b/js/chunk-4c048be9.9564d16d.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/content/main.md?2163","webpack:///./src/content/main.md","webpack:///./src/images/principio-kiss.jpg"],"names":["render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","_v","attrs","staticClass","script","component","module","exports"],"mappings":"uHAAA,IAAIA,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAsBH,EAAII,MAAMC,GAAO,OAAOL,EAAIM,GAAG,IACnGC,EAAkB,CAAC,WAAa,IAAIP,EAAIC,KAASC,EAAGF,EAAIG,eAAmBE,EAAGL,EAAII,MAAMC,IAAIH,EAAG,OAAOG,EAAG,UAAU,CAACA,EAAG,IAAI,CAACL,EAAIQ,GAAG,8FAA8FH,EAAG,KAAK,CAACI,MAAM,CAAC,GAAK,aAAa,CAACT,EAAIQ,GAAG,aAAaH,EAAG,IAAI,CAACK,YAAY,gBAAgBD,MAAM,CAAC,KAAO,cAAc,CAACT,EAAIQ,GAAG,SAASH,EAAG,IAAI,CAACL,EAAIQ,GAAG,kSAAkSH,EAAG,KAAK,CAACI,MAAM,CAAC,GAAK,SAAS,CAACT,EAAIQ,GAAG,SAASH,EAAG,IAAI,CAACK,YAAY,gBAAgBD,MAAM,CAAC,KAAO,UAAU,CAACT,EAAIQ,GAAG,SAASH,EAAG,MAAM,CAACK,YAAY,SAASD,MAAM,CAAC,IAAM,EAAQ,WAAkCJ,EAAG,IAAI,CAACL,EAAIQ,GAAG,2LAA2LH,EAAG,KAAK,CAACI,MAAM,CAAC,GAAK,aAAa,CAACT,EAAIQ,GAAG,cAAcH,EAAG,IAAI,CAACK,YAAY,gBAAgBD,MAAM,CAAC,KAAO,cAAc,CAACT,EAAIQ,GAAG,SAASH,EAAG,IAAI,CAACL,EAAIQ,GAAG,iI,YCA9sCG,EAAS,GAKTC,EAAY,eACdD,EACAZ,EACAQ,GACA,EACA,KACA,KACA,MAIa,aAAAK,E,8BCjBfC,EAAOC,QAAU,IAA0B","file":"js/chunk-4c048be9.9564d16d.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('p',[_vm._v(\"Esta es una pagina donde se van a ir actualizando el material y contenido de la materia.\")]),_c('h2',{attrs:{\"id\":\"objetivo\"}},[_vm._v(\"Objetivo \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#objetivo\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Un poco la idea de esta seccion de la pagina de Arquitecturas Concurrentes es la de tener un lugar donde tengamos material para que puedan estudiar o como complemento despues de la clase. La idea es que esta pagina se vaya actualizando y ampliando de manera iterativa e incremental :)\")]),_c('h2',{attrs:{\"id\":\"kiss\"}},[_vm._v(\"KISS \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#kiss\"}},[_vm._v(\"¶\")])]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/principio-kiss.jpg\")}}),_c('p',[_vm._v(\"La idea es tener una UI bastante basica, y que solo sea lo minimo indispensable para mostrar lo que mas nos importa, que es mostrar contenido sobre algun tema puntual de la materia.\")]),_c('h2',{attrs:{\"id\":\"got-typo\"}},[_vm._v(\"Got typo? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#got-typo\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Si alguno detecta algun problema o error puede levantar un nuevo issue y veremos de arreglar el mismo lo antes posible.\")])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./main.md?vue&type=template&id=713d1100&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","module.exports = __webpack_public_path__ + \"img/principio-kiss.6dc64b42.jpg\";"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-4fe8e0d3.6da585dc.js b/js/chunk-4fe8e0d3.6da585dc.js new file mode 100644 index 0000000..ec30fca --- /dev/null +++ b/js/chunk-4fe8e0d3.6da585dc.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-4fe8e0d3"],{"0799":function(e,a,s){e.exports=s.p+"img/2.3c408fb8.png"},4753:function(e,a,s){e.exports=s.p+"img/service-mesh.c04f75ea.png"},6467:function(e,a,s){e.exports=s.p+"img/1.1097a9e9.png"},a28e:function(e,a,s){e.exports=s.p+"img/control_plane.96aa0ab2.png"},a3db:function(e,a,s){e.exports=s.p+"img/3.ae7e51dc.png"},b874:function(e,a,s){e.exports=s.p+"img/service-mesh-generic-topology_social.74defb07.png"},d3c5:function(e,a,s){"use strict";s.r(a);var o=function(){var e=this,a=e.$createElement;e._self._c;return e._m(0)},i=[function(){var e=this,a=e.$createElement,o=e._self._c||a;return o("section",[o("h2",{attrs:{id:"introduccion"}},[e._v("Introduccion "),o("a",{staticClass:"header-anchor",attrs:{href:"#introduccion"}},[e._v("¶")])]),o("p",[e._v("Tal como lo vimos en la introduccion a distribucion, aprendimos que el tener sistemas distribuidos en cualquier dimension pueden causar casos de uso que no hubiesemos pensado antes, asi como varios problemas a resolver.")]),o("p",[e._v("Cuando estos sistemas eran simples, en general se trataba de minimizar la interaccion entre componentes remotos para que el impacto de la complejidad de los sistemas distribuidos sea minima. Y si bien en general, durante un tiempo hace un tiempo atras, si el sistema era dentro de todo simple o pequenio, solamente se trataba de evitar la distribucion aun si hubiese que duplicar logica o datos entre distintos sistemas.")]),o("p",[e._v("Obviamente no eran soluciones optimas, y hoy por hoy se trata de solucionar problemas tales como la duplicacion de codigo o de logica entre un componente o varios. Y en este nuevo mundo, cuando empezaron a verse de nuevo casos de sistemas que cada vez necesitaban escalar debido a que escalar verticalmente era demasiado costoso. Incluso estas dificultades hacian que fuese dificil de escalar (un ejemplo mencionado "),o("a",{attrs:{href:"http://highscalability.com/blog/2009/10/13/why-are-facebook-digg-and-twitter-so-hard-to-scale.html"}},[e._v("aqui")]),e._v(") Por eso varias soluciones iniciales fueron por asi decirlo ad-hoc para cada caso en un sistema en particular y de ahi fueron extrayendose nuevas soluciones cada vez mas sofisticadas. A medida que descubrimos más sobre el dominio del problema y diseñamos mejores soluciones, comenzamos a cristalizar algunas de las necesidades más comunes en patrones, bibliotecas y eventualmente plataformas.")]),o("p",[e._v("No solo se reduce esto a patrones, bibliotecas y codigo, sino tambien metodologias sobre como escalar y conceptos sobre sistemas distribuidos (mencion "),o("a",{attrs:{href:"http://highscalability.com/blog/2010/6/10/the-four-meta-secrets-of-scaling-at-facebook.html"}},[e._v("2")]),e._v(")")]),o("h2",{attrs:{id:"recapitulando-desde-microservicios"}},[e._v("Recapitulando desde microservicios "),o("a",{staticClass:"header-anchor",attrs:{href:"#recapitulando-desde-microservicios"}},[e._v("¶")])]),o("p",[e._v("Con los años, las computadoras se volvieron aún más baratas y más omnipresentes, y la pila de redes descrita anteriormente ha demostrado ser el conjunto de herramientas de facto para conectar sistemas de manera confiable. Con más nodos y conexiones estables, la industria ha jugado con varios tipos de sistemas en red, desde agentes y objetos distribuidos hasta arquitecturas orientadas a servicios compuestas de componentes más grandes pero aún muy distribuidos.")]),o("p",[e._v('En los años 90, Peter Deutsch y sus colegas ingenieros de Sun Microsystems compilaron "Las 8 falacias de la computación distribuida", en la que enumera algunas suposiciones que las personas tienden a hacer cuando trabajan con sistemas distribuidos. El punto de Peter es que estos podrían haber sido ciertos en arquitecturas de redes más primitivas o en modelos teóricos, pero no son válidos en el mundo moderno. Pueden ver un poco mas a '),o("a",{attrs:{href:"~@/mitos/"}},[e._v("aca")])]),o("p",[e._v("Incluso vimos que existen distintos problemas, tales como los que vimos hasta ahora como CAP, interleaving, netsplits, entre otras cosas. Incluso podemos mencionar otras cosas con la que deberiamos lidiar con una arquitectura distribuida:")]),o("ul",[o("li",[e._v("Provisionamiento rapido de los recursos (nuevas instancias)")]),o("li",[e._v("Monitoreo, en lo posible en tiempo real o poco delay")]),o("li",[e._v("Despliegue rapido")]),o("li",[e._v("Facil de provisionar mas almacenamiento (BBDD, disco, etc)")]),o("li",[e._v("Autenticacion")]),o("li",[e._v("Tener algun mecanismo de RPC estandarizado entre los compoenentes internos del sistema (protocols, gRPC por ej)")])]),o("p",[e._v("Entonces, aunque la pila TCP / IP y el modelo de red general desarrollado hace muchas décadas sigue siendo una herramienta poderosa para hacer que las computadoras se comuniquen entre sí, las arquitecturas más sofisticadas introdujeron otra capa de requisitos que, una vez más, deben cumplir los ingenieros que trabajan en tales arquitecturas.")]),o("p",[e._v("Hay ejemplos que podemos mencionar que se usaron para solucionar algunos problemas de resilencia y distribucion, algunos de estos son failover/takeover, circuit breaker (algunos detalles de este pueden verse "),o("a",{attrs:{href:"https://microservices.io/patterns/reliability/circuit-breaker.html"}},[e._v("aca tambien")]),e._v("), y tambien service discovery. Un ejemplo de servicios puede ser el siguiente:")]),o("img",{staticClass:"center",attrs:{src:s("6467")}}),o("p",[e._v("Entonces Service Discovery es el proceso de encontrar automáticamente qué instancias de servicio satisfacen una consulta determinada, por ejemplo un servicio llamado "),o("em",[e._v("Compras")]),e._v(" puede necesitar encontrar instancias de "),o("em",[e._v("Cotizacion de Envio")]),e._v(" con alguna con variable de entorno seteado en "),o("em",[e._v("prod")]),e._v(" por ejemplo. En ese caso se puede invocar un proceso de descubrimiento de servicio, que deberia devolver una lista de servidores adecuados.")]),o("p",[e._v("Para una estructura monolitica esto es facil, mediante un DNS, algun load balancer y algunas convenciones sobre los puertos basta. Pero en entornos mas distribuidos, esto no es tan trivial; y los servicios que anteriormente podían confiar ciegamente en sus búsquedas de DNS para encontrar dependencias ahora tienen que lidiar con cosas como el equilibrio de carga del lado del cliente, múltiples entornos diferentes.")]),o("p",[e._v("Si antes lo único que necesitaba era solo configuracion para resolver los nombres de host, ahora los servicios necesitan muchas líneas de repeticiones para lidiar con varios casos de esquina introducidos por una distribución más alta. Para esto se tiene este servicio de Service Discovery para encontrar las instancias a traves de la red que necesita un componente y las interconecta.")]),o("p",[e._v("Los circuit breakers son un patron catalogado por "),o("em",[e._v("Michael Nygard")]),e._v(" en el libro "),o("a",{attrs:{href:""}},[e._v("Release it")]),e._v(" del 2007. y lo que me gustaria mencionar aunque en ingles es la definicion de Martin Fowler en "),o("a",{attrs:{href:"https://martinfowler.com/bliki/CircuitBreaker.html"}},[e._v("3")])]),o("p",[o("cite",{attrs:{cite:"Martin Fowler"}},[e._v("The basic idea behind the circuit breaker is very simple. You wrap a protected function call in a circuit breaker object, which monitors for failures. Once the failures reach a certain threshold, the circuit breaker trips, and all further calls to the circuit breaker return with an error, without the protected call being made at all. Usually you’ll also want some kind of monitor alert if the circuit breaker trips.")])]),o("p",[e._v('Estos son patrones re simples que nos permiten tener mas confiabilidad en la interacciones entre los servicios. Sin embargo esto se empieza a complicar cuando se incrementa el mivel de distribucion. Por lo que puede pasar que tratar de "monitorear" una posible alerta en caso de que un circuit breaker se dispare, deja a veces de ser tan simple. Y una falla de un componente puede desencadenar tal vez una cascada de errores si lo tenemos todo')]),o("p",[e._v("These are great simple devices to add more reliability to interactions between your services. Nevertheless, just like everything else they tend to get much more complicated as the level of distribution increases. The likelihood of something going wrong in a system raises exponentially with distribution, so even simple things like “some kind of monitor alert if the circuit breaker trips” aren’t necessarily straightforward anymore. One failure in one component can create a cascade of effects across many clients, and clients of clients, triggering thousands of circuits to trip at the same time. Once more what used to be just a few lines of code now requires loads of boilerplate to handle situations that only exist in this new world.")]),o("p",[e._v("De hecho, los ejemplos enumerados anteriormente pueden ser tan difíciles de implementar correctamente que las bibliotecas grandes y sofisticadas como "),o("a",{attrs:{href:"https://twitter.github.io/finagle/"}},[e._v("Finagle")]),e._v(" entre otras se han hecho para evitar reescribir la misma lógica o solucion de estos ejemplos una y otra vez en distintos modulos del sistema.")]),o("p",[e._v("Entonces ahora podemos tener nuestra aplicacion de alguna manera separado de nuestra biblioteca pero aun en el mismo servicio x..")]),o("img",{staticClass:"center",attrs:{src:s("6467")}}),o("p",[e._v('Esta arquitectura de microservicios fue inicialmente utilizada por varias organizaciones que fueron pioneras de este tipo de arqutecturas como Twitter o Soundcloud. A medida que la cantidad de servicios aumento se empezo a ver de a poco las desventajas de esta solucion. La mayor limitante es que a medida que aumentan los servicios, se necesita una mayor cantidad de recursos, en terminos de ingenieros/desarrolladores para construir y de alguna manera "pegar" estas librerias en los servicios nuevos y mantenerlos tambien. Por lo que entre un 10-15% de los recursos se tienen que invertir en "pegar" y mantener estas librerias.')]),o("p",[e._v("Otra desventaja un poco viene por el lado de la libreria puede llegar a atarse al runtime y lenguajes tambien que se pueden usar en los microservicios. Porque es muy probable que estas librerias esten escritas en una plataforma en particular, por ejemplo Finagle esta escrito en Scala para la JVM, por lo que en el caso que se quiera agregar un nuevo servicio y quiere usarse esta libreria, se debe o bien ajustarse a la plataforma en la que estamos usando la libreria o usar un port o alguna libreria alternativa que nos resuelva el mismo problema.")]),o("h3",{attrs:{id:"mas-alla-de-los-microservicios"}},[e._v("Mas alla de los microservicios "),o("a",{staticClass:"header-anchor",attrs:{href:"#mas-alla-de-los-microservicios"}},[e._v("¶")])]),o("p",[e._v("De manera similar a lo que vimos en el stack de la red, sería altamente deseable extraer las características requeridas por los servicios distribuidos masivamente en una plataforma subyacente.")]),o("p",[e._v("Las empresas escriben aplicaciones y servicios sofisticados utilizando protocolos de nivel superior como HTTP sin siquiera pensar en cómo TCP controla los paquetes en su red. Esta situación es lo que necesitamos para los microservicios, donde los ingenieros que trabajan en servicios pueden centrarse en su lógica de negocios y evitar perder tiempo escribiendo su propio código de infraestructura de servicios o administrando bibliotecas y marcos en toda la flota de microservicios.")]),o("p",[e._v("Entonces nuestro diagrama vendria a quedar de esta manera..")]),o("img",{staticClass:"center",attrs:{src:s("0799")}}),o("p",[e._v("Pero esto no es tan trivial, agregar otro stack de la red involucra tambien que haya una interaccion entre la capa que antes era nuestra libreria y la superior, teniendo que ajustarlo o bien a un formato estandar sin tener que acoplarlo a la aplicacion, que haria que no fuese posible que se use a traves de varios servicios distintos.")]),o("p",[e._v("Hay una solucion alternativa que es la de implementar esto mismo pero a partir de un componente "),o("em",[e._v("proxy")]),e._v(". Por lo que un servicio no se conecta directamente con las dependencias sino que pasara todo su trafico a traves de otro modulo que agrega de manera transparente estas soluciones como el Circuit Breaker, Service Discovery, etc..")]),o("p",[e._v("Esto empezo a aparecer por primera vez con este articulo de "),o("a",{attrs:{href:"https://medium.com/airbnb-engineering/smartstack-service-discovery-in-the-cloud-4b8a080de619"}},[e._v("Airbnb")]),e._v(" en donde se describia a este servicio proxy como algo llamado "),o("em",[e._v("sidecar")]),e._v(". Un año despues Netflix hace algo muy similar pero para aplicaciones que no son basadas en la JVM, que es su implementacion de un sidecar llamado "),o("a",{attrs:{href:"https://medium.com/netflix-techblog/prana-a-sidecar-for-your-netflix-paas-based-applications-and-services-258a5790a015"}},[e._v("Prana")])]),o("img",{staticClass:"center",attrs:{src:s("a3db")}}),o("p",[e._v("Con el aumento de las arquitecturas basadas en microservicios, se siguio avanzando con esta arquitectura basada en proxies, y llegaron a aparecer en poco tiempo implementaciones de proxy que son lo suficientemente flexibles para adaptarse a distintos servicios y preferencias. Uno de los primeros fue "),o("a",{attrs:{href:"https://buoyant.io/2016/02/18/linkerd-twitter-style-operability-for-microservices/"}},[e._v("Linkerd")]),e._v(", creado por Twitter, y mas tarde por otra implementacion mas conocida hoy en dia llamado "),o("a",{attrs:{href:"https://eng.lyft.com/announcing-envoy-c-l7-proxy-and-communication-bus-92520b6c8191"}},[e._v("Envoy")])]),o("h2",{attrs:{id:"service-mesh"}},[e._v("Service Mesh "),o("a",{staticClass:"header-anchor",attrs:{href:"#service-mesh"}},[e._v("¶")])]),o("p",[e._v("El modelo de Service Mesh consiste en que, cada uno de sus servicios tendrá un sidecar proxy complementario. Dado que los servicios se comunican entre sí solo a través del proxy de sidecar, terminamos con una implementación similar al diagrama a continuación:")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("4753")}}),o("p",[e._v("Una definicion un poco mas formal lo podemos ver en lo que escribio "),o("a",{attrs:{href:"https://buoyant.io/2017/04/25/whats-a-service-mesh-and-why-do-i-need-one/"}},[o("em",[e._v("William Morgan")]),e._v(" de Buoyant en 2017")])]),o("cite",{attrs:{cite:"William Morgan"}},[e._v(" A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It’s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware. ")]),o("p",[e._v("Probablemente el aspecto más importante de su definición es que se aleja de pensar en los proxies como componentes aislados y reconoce en que la red que forman es algo valioso en sí mismo.")]),o("p",[e._v("A medida que las organizaciones trasladan sus implementaciones de microservicios a deployments más sofisticados como Kubernetes, las personas y las organizaciones han comenzado a usar las herramientas disponibles por esas plataformas para implementar esta idea de un service mesh correctamente. Se están alejando de un conjunto de servidores proxy independientes que trabajan de forma aislada a un plano de control, o sea algo centralizado.")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("b874")}}),o("p",[e._v("Viendo un poco nuestro diagrama de arriba,vemos que el tráfico real del servicio todavía fluye de proxy a proxy directamente, pero el plano de control conoce cada instancia de proxy. El plano de control permite a los proxies implementar cosas como el control de acceso y la recopilación de métricas, lo que requiere cooperación..")]),o("p",[e._v("Otro diagrama un poco mas detallado de plano de control ("),o("em",[e._v("Control Plane")]),e._v(") puede verse como el siguiente:")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("a28e")}}),o("p",[e._v("El proyecto que nos permite un poco utilizar el plano de control se llama "),o("a",{attrs:{href:"https://istio.io/"}},[e._v("Istio")]),e._v(" y es por el momento la herramienta mas utilizada y conocida para implementar el plano de control.")]),o("p",[e._v("Bibliografia")]),o("p",[o("a",{attrs:{href:"https://www.oreilly.com/library/view/the-enterprise-path/9781492041795/ch01.html"}},[e._v("The Enterprise Path to Service Mesh Architectures by Lee Calcote")])])])}],r=s("2877"),n={},t=Object(r["a"])(n,o,i,!1,null,null,null);a["default"]=t.exports}}]); +//# sourceMappingURL=chunk-4fe8e0d3.6da585dc.js.map \ No newline at end of file diff --git a/js/chunk-4fe8e0d3.6da585dc.js.map b/js/chunk-4fe8e0d3.6da585dc.js.map new file mode 100644 index 0000000..6fb597f --- /dev/null +++ b/js/chunk-4fe8e0d3.6da585dc.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/images/service_mesh/2.png","webpack:///./src/images/service_mesh/service-mesh.png","webpack:///./src/images/service_mesh/1.png","webpack:///./src/images/service_mesh/control_plane.png","webpack:///./src/images/service_mesh/3.png","webpack:///./src/images/service_mesh/service-mesh-generic-topology_social.png","webpack:///./src/content/service_mesh.md?1216","webpack:///./src/content/service_mesh.md"],"names":["module","exports","render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","script","component"],"mappings":"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","file":"js/chunk-4fe8e0d3.6da585dc.js","sourcesContent":["module.exports = __webpack_public_path__ + \"img/2.3c408fb8.png\";","module.exports = __webpack_public_path__ + \"img/service-mesh.c04f75ea.png\";","module.exports = __webpack_public_path__ + \"img/1.1097a9e9.png\";","module.exports = __webpack_public_path__ + \"img/control_plane.96aa0ab2.png\";","module.exports = __webpack_public_path__ + \"img/3.ae7e51dc.png\";","module.exports = __webpack_public_path__ + \"img/service-mesh-generic-topology_social.74defb07.png\";","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h2',{attrs:{\"id\":\"introduccion\"}},[_vm._v(\"Introduccion \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#introduccion\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Tal como lo vimos en la introduccion a distribucion, aprendimos que el tener sistemas distribuidos en cualquier dimension pueden causar casos de uso que no hubiesemos pensado antes, asi como varios problemas a resolver.\")]),_c('p',[_vm._v(\"Cuando estos sistemas eran simples, en general se trataba de minimizar la interaccion entre componentes remotos para que el impacto de la complejidad de los sistemas distribuidos sea minima. Y si bien en general, durante un tiempo hace un tiempo atras, si el sistema era dentro de todo simple o pequenio, solamente se trataba de evitar la distribucion aun si hubiese que duplicar logica o datos entre distintos sistemas.\")]),_c('p',[_vm._v(\"Obviamente no eran soluciones optimas, y hoy por hoy se trata de solucionar problemas tales como la duplicacion de codigo o de logica entre un componente o varios. Y en este nuevo mundo, cuando empezaron a verse de nuevo casos de sistemas que cada vez necesitaban escalar debido a que escalar verticalmente era demasiado costoso. Incluso estas dificultades hacian que fuese dificil de escalar (un ejemplo mencionado \"),_c('a',{attrs:{\"href\":\"http://highscalability.com/blog/2009/10/13/why-are-facebook-digg-and-twitter-so-hard-to-scale.html\"}},[_vm._v(\"aqui\")]),_vm._v(\") Por eso varias soluciones iniciales fueron por asi decirlo ad-hoc para cada caso en un sistema en particular y de ahi fueron extrayendose nuevas soluciones cada vez mas sofisticadas. A medida que descubrimos más sobre el dominio del problema y diseñamos mejores soluciones, comenzamos a cristalizar algunas de las necesidades más comunes en patrones, bibliotecas y eventualmente plataformas.\")]),_c('p',[_vm._v(\"No solo se reduce esto a patrones, bibliotecas y codigo, sino tambien metodologias sobre como escalar y conceptos sobre sistemas distribuidos (mencion \"),_c('a',{attrs:{\"href\":\"http://highscalability.com/blog/2010/6/10/the-four-meta-secrets-of-scaling-at-facebook.html\"}},[_vm._v(\"2\")]),_vm._v(\")\")]),_c('h2',{attrs:{\"id\":\"recapitulando-desde-microservicios\"}},[_vm._v(\"Recapitulando desde microservicios \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#recapitulando-desde-microservicios\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Con los años, las computadoras se volvieron aún más baratas y más omnipresentes, y la pila de redes descrita anteriormente ha demostrado ser el conjunto de herramientas de facto para conectar sistemas de manera confiable. Con más nodos y conexiones estables, la industria ha jugado con varios tipos de sistemas en red, desde agentes y objetos distribuidos hasta arquitecturas orientadas a servicios compuestas de componentes más grandes pero aún muy distribuidos.\")]),_c('p',[_vm._v(\"En los años 90, Peter Deutsch y sus colegas ingenieros de Sun Microsystems compilaron \\\"Las 8 falacias de la computación distribuida\\\", en la que enumera algunas suposiciones que las personas tienden a hacer cuando trabajan con sistemas distribuidos. El punto de Peter es que estos podrían haber sido ciertos en arquitecturas de redes más primitivas o en modelos teóricos, pero no son válidos en el mundo moderno. Pueden ver un poco mas a \"),_c('a',{attrs:{\"href\":\"~@/mitos/\"}},[_vm._v(\"aca\")])]),_c('p',[_vm._v(\"Incluso vimos que existen distintos problemas, tales como los que vimos hasta ahora como CAP, interleaving, netsplits, entre otras cosas. Incluso podemos mencionar otras cosas con la que deberiamos lidiar con una arquitectura distribuida:\")]),_c('ul',[_c('li',[_vm._v(\"Provisionamiento rapido de los recursos (nuevas instancias)\")]),_c('li',[_vm._v(\"Monitoreo, en lo posible en tiempo real o poco delay\")]),_c('li',[_vm._v(\"Despliegue rapido\")]),_c('li',[_vm._v(\"Facil de provisionar mas almacenamiento (BBDD, disco, etc)\")]),_c('li',[_vm._v(\"Autenticacion\")]),_c('li',[_vm._v(\"Tener algun mecanismo de RPC estandarizado entre los compoenentes internos del sistema (protocols, gRPC por ej)\")])]),_c('p',[_vm._v(\"Entonces, aunque la pila TCP / IP y el modelo de red general desarrollado hace muchas décadas sigue siendo una herramienta poderosa para hacer que las computadoras se comuniquen entre sí, las arquitecturas más sofisticadas introdujeron otra capa de requisitos que, una vez más, deben cumplir los ingenieros que trabajan en tales arquitecturas.\")]),_c('p',[_vm._v(\"Hay ejemplos que podemos mencionar que se usaron para solucionar algunos problemas de resilencia y distribucion, algunos de estos son failover/takeover, circuit breaker (algunos detalles de este pueden verse \"),_c('a',{attrs:{\"href\":\"https://microservices.io/patterns/reliability/circuit-breaker.html\"}},[_vm._v(\"aca tambien\")]),_vm._v(\"), y tambien service discovery. Un ejemplo de servicios puede ser el siguiente:\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/service_mesh/1.png\")}}),_c('p',[_vm._v(\"Entonces Service Discovery es el proceso de encontrar automáticamente qué instancias de servicio satisfacen una consulta determinada, por ejemplo un servicio llamado \"),_c('em',[_vm._v(\"Compras\")]),_vm._v(\" puede necesitar encontrar instancias de \"),_c('em',[_vm._v(\"Cotizacion de Envio\")]),_vm._v(\" con alguna con variable de entorno seteado en \"),_c('em',[_vm._v(\"prod\")]),_vm._v(\" por ejemplo. En ese caso se puede invocar un proceso de descubrimiento de servicio, que deberia devolver una lista de servidores adecuados.\")]),_c('p',[_vm._v(\"Para una estructura monolitica esto es facil, mediante un DNS, algun load balancer y algunas convenciones sobre los puertos basta. Pero en entornos mas distribuidos, esto no es tan trivial; y los servicios que anteriormente podían confiar ciegamente en sus búsquedas de DNS para encontrar dependencias ahora tienen que lidiar con cosas como el equilibrio de carga del lado del cliente, múltiples entornos diferentes.\")]),_c('p',[_vm._v(\"Si antes lo único que necesitaba era solo configuracion para resolver los nombres de host, ahora los servicios necesitan muchas líneas de repeticiones para lidiar con varios casos de esquina introducidos por una distribución más alta. Para esto se tiene este servicio de Service Discovery para encontrar las instancias a traves de la red que necesita un componente y las interconecta.\")]),_c('p',[_vm._v(\"Los circuit breakers son un patron catalogado por \"),_c('em',[_vm._v(\"Michael Nygard\")]),_vm._v(\" en el libro \"),_c('a',{attrs:{\"href\":\"\"}},[_vm._v(\"Release it\")]),_vm._v(\" del 2007. y lo que me gustaria mencionar aunque en ingles es la definicion de Martin Fowler en \"),_c('a',{attrs:{\"href\":\"https://martinfowler.com/bliki/CircuitBreaker.html\"}},[_vm._v(\"3\")])]),_c('p',[_c('cite',{attrs:{\"cite\":\"Martin Fowler\"}},[_vm._v(\"The basic idea behind the circuit breaker is very simple. You wrap a protected function call in a circuit breaker object, which monitors for failures. Once the failures reach a certain threshold, the circuit breaker trips, and all further calls to the circuit breaker return with an error, without the protected call being made at all. Usually you’ll also want some kind of monitor alert if the circuit breaker trips.\")])]),_c('p',[_vm._v(\"Estos son patrones re simples que nos permiten tener mas confiabilidad en la interacciones entre los servicios. Sin embargo esto se empieza a complicar cuando se incrementa el mivel de distribucion. Por lo que puede pasar que tratar de \\\"monitorear\\\" una posible alerta en caso de que un circuit breaker se dispare, deja a veces de ser tan simple. Y una falla de un componente puede desencadenar tal vez una cascada de errores si lo tenemos todo\")]),_c('p',[_vm._v(\"These are great simple devices to add more reliability to interactions between your services. Nevertheless, just like everything else they tend to get much more complicated as the level of distribution increases. The likelihood of something going wrong in a system raises exponentially with distribution, so even simple things like “some kind of monitor alert if the circuit breaker trips” aren’t necessarily straightforward anymore. One failure in one component can create a cascade of effects across many clients, and clients of clients, triggering thousands of circuits to trip at the same time. Once more what used to be just a few lines of code now requires loads of boilerplate to handle situations that only exist in this new world.\")]),_c('p',[_vm._v(\"De hecho, los ejemplos enumerados anteriormente pueden ser tan difíciles de implementar correctamente que las bibliotecas grandes y sofisticadas como \"),_c('a',{attrs:{\"href\":\"https://twitter.github.io/finagle/\"}},[_vm._v(\"Finagle\")]),_vm._v(\" entre otras se han hecho para evitar reescribir la misma lógica o solucion de estos ejemplos una y otra vez en distintos modulos del sistema.\")]),_c('p',[_vm._v(\"Entonces ahora podemos tener nuestra aplicacion de alguna manera separado de nuestra biblioteca pero aun en el mismo servicio x..\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/service_mesh/1.png\")}}),_c('p',[_vm._v(\"Esta arquitectura de microservicios fue inicialmente utilizada por varias organizaciones que fueron pioneras de este tipo de arqutecturas como Twitter o Soundcloud. A medida que la cantidad de servicios aumento se empezo a ver de a poco las desventajas de esta solucion. La mayor limitante es que a medida que aumentan los servicios, se necesita una mayor cantidad de recursos, en terminos de ingenieros/desarrolladores para construir y de alguna manera \\\"pegar\\\" estas librerias en los servicios nuevos y mantenerlos tambien. Por lo que entre un 10-15% de los recursos se tienen que invertir en \\\"pegar\\\" y mantener estas librerias.\")]),_c('p',[_vm._v(\"Otra desventaja un poco viene por el lado de la libreria puede llegar a atarse al runtime y lenguajes tambien que se pueden usar en los microservicios. Porque es muy probable que estas librerias esten escritas en una plataforma en particular, por ejemplo Finagle esta escrito en Scala para la JVM, por lo que en el caso que se quiera agregar un nuevo servicio y quiere usarse esta libreria, se debe o bien ajustarse a la plataforma en la que estamos usando la libreria o usar un port o alguna libreria alternativa que nos resuelva el mismo problema.\")]),_c('h3',{attrs:{\"id\":\"mas-alla-de-los-microservicios\"}},[_vm._v(\"Mas alla de los microservicios \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#mas-alla-de-los-microservicios\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"De manera similar a lo que vimos en el stack de la red, sería altamente deseable extraer las características requeridas por los servicios distribuidos masivamente en una plataforma subyacente.\")]),_c('p',[_vm._v(\"Las empresas escriben aplicaciones y servicios sofisticados utilizando protocolos de nivel superior como HTTP sin siquiera pensar en cómo TCP controla los paquetes en su red. Esta situación es lo que necesitamos para los microservicios, donde los ingenieros que trabajan en servicios pueden centrarse en su lógica de negocios y evitar perder tiempo escribiendo su propio código de infraestructura de servicios o administrando bibliotecas y marcos en toda la flota de microservicios.\")]),_c('p',[_vm._v(\"Entonces nuestro diagrama vendria a quedar de esta manera..\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/service_mesh/2.png\")}}),_c('p',[_vm._v(\"Pero esto no es tan trivial, agregar otro stack de la red involucra tambien que haya una interaccion entre la capa que antes era nuestra libreria y la superior, teniendo que ajustarlo o bien a un formato estandar sin tener que acoplarlo a la aplicacion, que haria que no fuese posible que se use a traves de varios servicios distintos.\")]),_c('p',[_vm._v(\"Hay una solucion alternativa que es la de implementar esto mismo pero a partir de un componente \"),_c('em',[_vm._v(\"proxy\")]),_vm._v(\". Por lo que un servicio no se conecta directamente con las dependencias sino que pasara todo su trafico a traves de otro modulo que agrega de manera transparente estas soluciones como el Circuit Breaker, Service Discovery, etc..\")]),_c('p',[_vm._v(\"Esto empezo a aparecer por primera vez con este articulo de \"),_c('a',{attrs:{\"href\":\"https://medium.com/airbnb-engineering/smartstack-service-discovery-in-the-cloud-4b8a080de619\"}},[_vm._v(\"Airbnb\")]),_vm._v(\" en donde se describia a este servicio proxy como algo llamado \"),_c('em',[_vm._v(\"sidecar\")]),_vm._v(\". Un año despues Netflix hace algo muy similar pero para aplicaciones que no son basadas en la JVM, que es su implementacion de un sidecar llamado \"),_c('a',{attrs:{\"href\":\"https://medium.com/netflix-techblog/prana-a-sidecar-for-your-netflix-paas-based-applications-and-services-258a5790a015\"}},[_vm._v(\"Prana\")])]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/service_mesh/3.png\")}}),_c('p',[_vm._v(\"Con el aumento de las arquitecturas basadas en microservicios, se siguio avanzando con esta arquitectura basada en proxies, y llegaron a aparecer en poco tiempo implementaciones de proxy que son lo suficientemente flexibles para adaptarse a distintos servicios y preferencias. Uno de los primeros fue \"),_c('a',{attrs:{\"href\":\"https://buoyant.io/2016/02/18/linkerd-twitter-style-operability-for-microservices/\"}},[_vm._v(\"Linkerd\")]),_vm._v(\", creado por Twitter, y mas tarde por otra implementacion mas conocida hoy en dia llamado \"),_c('a',{attrs:{\"href\":\"https://eng.lyft.com/announcing-envoy-c-l7-proxy-and-communication-bus-92520b6c8191\"}},[_vm._v(\"Envoy\")])]),_c('h2',{attrs:{\"id\":\"service-mesh\"}},[_vm._v(\"Service Mesh \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#service-mesh\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"El modelo de Service Mesh consiste en que, cada uno de sus servicios tendrá un sidecar proxy complementario. Dado que los servicios se comunican entre sí solo a través del proxy de sidecar, terminamos con una implementación similar al diagrama a continuación:\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/service_mesh/service-mesh.png\")}}),_c('p',[_vm._v(\"Una definicion un poco mas formal lo podemos ver en lo que escribio \"),_c('a',{attrs:{\"href\":\"https://buoyant.io/2017/04/25/whats-a-service-mesh-and-why-do-i-need-one/\"}},[_c('em',[_vm._v(\"William Morgan\")]),_vm._v(\" de Buoyant en 2017\")])]),_c('cite',{attrs:{\"cite\":\"William Morgan\"}},[_vm._v(\" A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It’s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware. \")]),_c('p',[_vm._v(\"Probablemente el aspecto más importante de su definición es que se aleja de pensar en los proxies como componentes aislados y reconoce en que la red que forman es algo valioso en sí mismo.\")]),_c('p',[_vm._v(\"A medida que las organizaciones trasladan sus implementaciones de microservicios a deployments más sofisticados como Kubernetes, las personas y las organizaciones han comenzado a usar las herramientas disponibles por esas plataformas para implementar esta idea de un service mesh correctamente. Se están alejando de un conjunto de servidores proxy independientes que trabajan de forma aislada a un plano de control, o sea algo centralizado.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/service_mesh/service-mesh-generic-topology_social.png\")}}),_c('p',[_vm._v(\"Viendo un poco nuestro diagrama de arriba,vemos que el tráfico real del servicio todavía fluye de proxy a proxy directamente, pero el plano de control conoce cada instancia de proxy. El plano de control permite a los proxies implementar cosas como el control de acceso y la recopilación de métricas, lo que requiere cooperación..\")]),_c('p',[_vm._v(\"Otro diagrama un poco mas detallado de plano de control (\"),_c('em',[_vm._v(\"Control Plane\")]),_vm._v(\") puede verse como el siguiente:\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/service_mesh/control_plane.png\")}}),_c('p',[_vm._v(\"El proyecto que nos permite un poco utilizar el plano de control se llama \"),_c('a',{attrs:{\"href\":\"https://istio.io/\"}},[_vm._v(\"Istio\")]),_vm._v(\" y es por el momento la herramienta mas utilizada y conocida para implementar el plano de control.\")]),_c('p',[_vm._v(\"Bibliografia\")]),_c('p',[_c('a',{attrs:{\"href\":\"https://www.oreilly.com/library/view/the-enterprise-path/9781492041795/ch01.html\"}},[_vm._v(\"The Enterprise Path to Service Mesh Architectures by Lee Calcote\")])])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./service_mesh.md?vue&type=template&id=1b1e95e5&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-5855597c.3ea0ef2b.js b/js/chunk-5855597c.3ea0ef2b.js new file mode 100644 index 0000000..e89e7ba --- /dev/null +++ b/js/chunk-5855597c.3ea0ef2b.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-5855597c"],{7250:function(e,a,s){e.exports=s.p+"img/image1.d0c1cc9e.png"},9838:function(e,a,s){e.exports=s.p+"img/image11.a37c77f8.jpg"},e4a4:function(e,a,s){"use strict";s.r(a);var o=function(){var e=this,a=e.$createElement;e._self._c;return e._m(0)},n=[function(){var e=this,a=e.$createElement,o=e._self._c||a;return o("section",[o("h1",{attrs:{id:"mi-otra-gorra-es-un-teorema"}},[e._v("Mi otra gorra es un teorema "),o("a",{staticClass:"header-anchor",attrs:{href:"#mi-otra-gorra-es-un-teorema"}},[e._v("¶")])]),o("p",[e._v("Hay alguna manera de que manteniendo la aplicación disponible durante intearleaves no haya pérdida de datos? La respuesta rápida es no. No hay manera que la aplicación funcione correctamente en un interleave. esta idea es conocida como el teorema "),o("abbr",{attrs:{title:"CAP es Consistency, Avaliability, Partition Tolerance"}},[e._v("CAP")]),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn1",id:"fnref1"}},[e._v("[1]")])]),e._v(".")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("7250")}}),o("p",[e._v("Consistencia: Esta es la habilidad que nuestra sistema, tenga 2 o 312123243 nodos que pueda responder a consultas y que tenga el mismo estado, no importa al nodo al que se la hace la consulta. Esto es algo que se logra con transacciones o un mecanismo equivalente. Entonces se tiene que poder ver a todos los nodos como un bloque indivisible. Esto es lo que vimos al comienzo con los contadores, que siempre quede en un estado conocido para el sistema y que no haya por ej. dos nodos que respondan algo distinto al mismo tiempo de realizar la consulta.")]),o("p",[e._v("Disponibilidad: Es simple que siempre que se le pida al sistema por algo de información el sistema me responda, y si no lo hace no está disponible.")]),o("p",[e._v("Particionamiento: Esta parte del teorema es un poco más capciosa. Tolerancia a las particiones significa que el sistema puede seguir funcionando (y contener información útil, estado) aún cuando las partes no puedan comunicarse entre sí. Todo el punto de la tolerancia a la partición es que ese sistema pueda trabajar con mensajes que estén posiblemente perdidos entre componentes. Esto es algo abstracto pero iremos explicando más de esto.")]),o("h2",{attrs:{id:"cap-clasico-o-tradicional"}},[o("abbr",{attrs:{title:"CAP es Consistency, Avaliability, Partition Tolerance"}},[e._v("CAP")]),e._v(" Clasico o Tradicional "),o("a",{staticClass:"header-anchor",attrs:{href:"#cap-clasico-o-tradicional"}},[e._v("¶")])]),o("p",[e._v("La interpretación que veremos ahora es la clásica en la que solo se puede tener dos de los tres conceptos de "),o("abbr",{attrs:{title:"CAP es Consistency, Avaliability, Partition Tolerance"}},[e._v("CAP")]),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn2",id:"fnref2"}},[e._v("[2]")])]),e._v(", es decir se puede tener CA, CP o AP. No hay manera de que se puedan tener los tres. Lo malo es que no es posible tener las tres cosas incluso con un fallo de red. Lo bueno es que es un teorema, después veremos que esto es más abierto en la interpretación gradual. tener Consistencia y Disponibilidad no es posible a menos que teóricamente no falle nunca la red, y si sucede en un nodo todo debería fallar. Entonces nos quedan las otras dos partes. AP o CP. Cuando hay un netsplit o interleave la disponibilidad o consistencia permanecen, pero no ambas.")]),o("p",[e._v("El esquema que toman ambas opciones son las siguientes:")]),o("p",[e._v("CP: El estado no cambio, no hay nada que hacer")]),o("p",[e._v("AP: Tiene más flexibilidad y problemas que resolver, se utilizan distintas estrategias:")]),o("ul",[o("li",[e._v("La última escritura gana, es una resolución del conflicto en donde cualquiera que haga la última escritura, es el valor del estado que queda.")]),o("li",[e._v("Esto puede ser algo abierto ya que en sistemas distribuidos, los timestamps generados pueden ser en el mismo momento o no estarlo incluso presente en el sistema.")]),o("li",[e._v("Se puede elegir al ganador de la escritura aleatoriamente")]),o("li",[e._v("Métodos más sofisticados ayudan a reducir los conflictos por medio de timestamps como el primer caso pero con relojes relativos. Los relojes relativos trabajan incrementalmente con un valor que se suma a cada escritura. Lamport Clocks extiende más esta idea")]),o("li",[e._v("El que almacena el estado, si es un nodo central u otro sistema debe elegir cual de los estados es el correcto, un poco lo que sucede con git cuando tenemos un conflicto.")])]),o("h3",{attrs:{id:"bbdd-y-cap"}},[e._v("BBDD y "),o("abbr",{attrs:{title:"CAP es Consistency, Avaliability, Partition Tolerance"}},[e._v("CAP")]),e._v(" "),o("a",{staticClass:"header-anchor",attrs:{href:"#bbdd-y-cap"}},[e._v("¶")])]),o("p",[e._v("Este es el gráfico que vimos en clase sobre "),o("abbr",{attrs:{title:"CAP es Consistency, Avaliability, Partition Tolerance"}},[e._v("CAP")]),e._v(" y BBDD, el post en el que se detalla más el siguiente: http://blog.nahurst.com/visual-guide-to-nosql-systems")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("f29d")}}),o("h2",{attrs:{id:"cap-gradual"}},[e._v("Cap Gradual "),o("a",{staticClass:"header-anchor",attrs:{href:"#cap-gradual"}},[e._v("¶")])]),o("p",[e._v("El otro concepto, un poco más gradual hace hincapié en que hoy por hoy no se puede solo tener dos de estos conceptos que permiten simplificar estos conceptos ya separados, y no hay que elegir entre uno u otro de los otros conceptos aparte de particiones, hablamos de consistencia y disponibilidad, sino que hay un rango de flexibilidad para manejar y recuperarse de las particiones"),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn3",id:"fnref3"}},[e._v("[3]")])]),e._v(".")]),o("h2",{attrs:{id:"mas-sobre-cap"}},[e._v("Mas Sobre "),o("abbr",{attrs:{title:"CAP es Consistency, Avaliability, Partition Tolerance"}},[e._v("CAP")]),e._v(" "),o("a",{staticClass:"header-anchor",attrs:{href:"#mas-sobre-cap"}},[e._v("¶")])]),o("p",[e._v("La manera más fácil de entender "),o("abbr",{attrs:{title:"CAP es Consistency, Avaliability, Partition Tolerance"}},[e._v("CAP")]),e._v(" es pensar que dos nodos separados de una partición, permitiendo que al menos de estos nodos se actualice, permite que el otro se vuelva inconsistente, entonces se deja de lado C. De la misma manera si se preserva la consistencia, un lado de la partición debe actuar como no disponible, dejando de lado A. Solo cuando se comunican los nodos es posible de preservar tanto C como A, dejando de la P. Entonces siempre se piensa en que se debe elegir dos de tres opciones, por el momento centrémonos en el caso en el que se necesiten realizar particiones, aunque dependendiendo del sistema, no siempre aparecen o se necesitan particiones. Entonces la elección entre C y A puede ocurrir varias veces en el sistema con una granularidad bastante fina, y no siempre es algo consistente en todo el sistema, pueden haber sistemas que prioricen una opción sobre otra. La disponibilidad es continuo entre 0 y 100 porciento, pero puede existir niveles de consistencia. En el caso de la interpretación clásica de "),o("abbr",{attrs:{title:"CAP es Consistency, Avaliability, Partition Tolerance"}},[e._v("CAP")]),e._v(", no se considera la latencia y se lo ignora, aunque en práctica, la latencia y las particiones están relacionadas en gran medida. La esencia de "),o("abbr",{attrs:{title:"CAP es Consistency, Avaliability, Partition Tolerance"}},[e._v("CAP")]),e._v(" toma parte durante un timeout, un período en el que programa debe tomar una decisión sobre la partición:")]),o("ul",[o("li",[e._v("Cancelar la operación y disminuir la disponibilidad")]),o("li",[e._v("Continuar con la operación y arriesgar a que aparezcan inconsistencias")])]),o("p",[e._v("Entonces si queremos volver a intentar comunicarnos con el otro nodo, para querer mantener la consistencia, solo demora la decisión si no responde, entonces se puede decir que una partición es algo atado al tiempo en una comunicación. Si no se puede mantener la consistencia con las implicaciones de tiempo en la conexión implican una operación entre C o A. A veces tan solo se puede sacrificar C en pos de tener mayor A o viceversa, y de acuerdo a la partición y el momento y el escenario en el que está el sistema, priorizar una u otra. Por ejemplo, PNUTS de Yahoo incurre en la inconsistencia manteniendo copias remotas asincrónicamente. Sin embargo, hace una copia local maestra, que decrementa la latencia. Esta estrategia trabaja bien en práctica porque los datos de un usuario simple es naturalmente particionado de acuerdo a la localización del usuario. Facebook, usa otra estrategia, que es la de tener la copia maestra en un lugar, y un usuario remoto en realidad tendría una copia stale más cercana a esta copia maestra. Sin embargo, cuando los usuarios actualizan su página, la actualización va a la copia maestra directamente y los usuarios leerán de esta copia maestra en poco tiempo, a los 20-30 segundos los usuarios empiezan a tener una idea más cercana de lo que está en la copia maestra. Entonces si tenemos particiones, tiene sentido elegir entre A y C? Elegir entre C y A existiendo particiones significa que la probabilidad de particiones puede existir y en caso de falla, fallen múltiples componentes simultáneamente. En realidad lo que sucede es que el sistema realmente pierde algo tanto de C como de A, entonces las tres propiedades en cierta manera son importantes. Hay veces en las que se tiene un sistema en un solo datacenter ( en un solo lugar) y como no poseen particiones, tales diseños incluyendo las RBDMS tradicionales, no necesitan considerar P y son en general AC en su totalidad, estos sistemas en cambio no se particionan sino que optan por el esquema de replicación.")]),o("h2",{attrs:{id:"manejando-particiones"}},[e._v("Manejando particiones "),o("a",{staticClass:"header-anchor",attrs:{href:"#manejando-particiones"}},[e._v("¶")])]),o("p",[e._v("En el caso en el que se deban manejar las particiones, estas solo dependen del tiempo en el que se generan y luego se debe unificar estas cuando se restauran, entonces una partición se ve como en la siguiente imagen:")]),o("img",{staticClass:"center",attrs:{src:s("9838")}}),o("p",[e._v("y hay tres momentos en una partición")]),o("ul",[o("li",[e._v("El momento en el que comienza una partición")]),o("li",[e._v("Entrar en una partición explícitamente, que puede limitar algunas operaciones")]),o("li",[e._v("Inicial la recuperación de una partición cuando se necesita unificar las particiones de un sistema.")])]),o("p",[e._v("El último paso apunta a restaurar la consistencia y arreglar los cambios y valores inválidos en las invariantes que se generaron cuando el sistema se particiona. La imagen muestra la evolución de una partición. Una operación normal es una secuencia de operaciones atómicas, y, por lo tanto las particiones empiezan entre operaciones. Si tenemos dos nodos que están interconectados y dejan de hablarse durante un tiempo entonces es muy probable que se haya iniciado una partición, en ese caso el primero inicializa este modo, si en realidad existe una partición, entonces el otro nodo también entrará en este modo, pero solo de un lado se admite la partición. En estos casos debe comunicarse esto al otro nodo para que solo quede de un lado. Cuando un sistema entre en modo partición, dos estrategias son posibles. La primera opción es limitar las operaciones reduciendo la disponibilidad y el segundo guardando información extra sobre las operaciones que pueden ser de ayuda en la recuperación de la partición. Entonces en este punto la comunicación se resume entre los nodos y debe volver a reunificarse el estado único del sistema, en este punto se sabe el estado de ambos nodos y sus historias, la historia en realidad es mejor que las invariantes que forman el estado por un tema que se puede determinar mejor cuál sería el estado final a tomar. El diseñador debe resolver dos problemas")]),o("ul",[o("li",[e._v("Ambos lados deben quedar consistentes")]),o("li",[e._v("Debe haber una compensación para los errores cometidos durante la fase de partición.")])]),o("p",[e._v("En general se hace una especie de merge dependiendo de la estrategia entre los estados, algo similar a lo que se ve en un CVS, pero hay muchos sistemas que no pueden hacer este mergeo de datos por un tema que no es posible, entonces es el caso en el que se reduce las operaciones disponibles en un sistema durante una partición, Google Docs es un caso de este tipo. Otras opciones son las de tomar por medio de algún algoritmo el dato más nuevo y tomar esas invariantes más nuevas como las definitivas en el sistema.")]),o("h3",{attrs:{id:"adicional"}},[e._v("Adicional "),o("a",{staticClass:"header-anchor",attrs:{href:"#adicional"}},[e._v("¶")])]),o("div",{staticClass:"warning"},[o("p",[o("em",[e._v("Advertencia: Esta seccion necesita un mayor desarrollo del tema y de citas.")])])]),o("p",[e._v("Existen tambien criticas al teorema"),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn4",id:"fnref4"}},[e._v("[4]")])]),e._v(", en el que se mencionan entre otras cosas, algunas confusiones y ambiguedades de los terminos, y algunos problemas en su formalización. Estas criticas se centran un poco en la dificil aplicacion que puede llegar a tener a veces sobre los sistemas reales.")]),o("hr",{staticClass:"footnotes-sep"}),o("section",{staticClass:"footnotes"},[o("ol",{staticClass:"footnotes-list"},[o("li",{staticClass:"footnote-item",attrs:{id:"fn1"}},[o("p",[o("a",{attrs:{href:"https://learnyousomeerlang.com/distribunomicon"}},[e._v("Distribunomicon - Learn you some Erlang for greater good")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref1"}},[e._v("↩︎")])])]),o("li",{staticClass:"footnote-item",attrs:{id:"fn2"}},[o("p",[o("a",{attrs:{href:"http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.67.6951&rep=rep1&type=pdf"}},[e._v("Gilbert and Lynch. Brewer conjecture and the feasibility of consistent, available, partition-tolerant web services. ACM SIGACT News (2002) vol. 33 (2) pp. 59")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref2"}},[e._v("↩︎")])])]),o("li",{staticClass:"footnote-item",attrs:{id:"fn3"}},[o("p",[o("a",{attrs:{href:"http://www.infoq.com/articles/cap-twelve-years-later-how-the-rules-have-changed"}},[e._v("Eric A Brewer. "),o("abbr",{attrs:{title:"CAP es Consistency, Avaliability, Partition Tolerance"}},[e._v("CAP")]),e._v(" twelve years later: How the “rules” have changed. IEEE Computer Magazine, 45(2):23–29, February 2012. doi:10.1109/MC.2012.37.")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref3"}},[e._v("↩︎")])])]),o("li",{staticClass:"footnote-item",attrs:{id:"fn4"}},[o("p",[e._v("Kleppmann, M. (2015). A Critique of the "),o("abbr",{attrs:{title:"CAP es Consistency, Avaliability, Partition Tolerance"}},[e._v("CAP")]),e._v(" Theorem. "),o("a",{attrs:{href:"https://doi.org/10.17863/CAM.13083"}},[e._v("https://doi.org/10.17863/CAM.13083")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref4"}},[e._v("↩︎")])])])])])])}],i=s("2877"),t={},r=Object(i["a"])(t,o,n,!1,null,null,null);a["default"]=r.exports},f29d:function(e,a,s){e.exports=s.p+"img/image14.3e72e131.png"}}]); +//# sourceMappingURL=chunk-5855597c.3ea0ef2b.js.map \ No newline at end of file diff --git a/js/chunk-5855597c.3ea0ef2b.js.map b/js/chunk-5855597c.3ea0ef2b.js.map new file mode 100644 index 0000000..acea02b --- /dev/null +++ b/js/chunk-5855597c.3ea0ef2b.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/images/distribucion/image1.png","webpack:///./src/images/distribucion/image11.jpg","webpack:///./src/content/cap.md?ef86","webpack:///./src/content/cap.md","webpack:///./src/images/distribucion/image14.png"],"names":["module","exports","render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","script","component"],"mappings":"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","file":"js/chunk-5855597c.3ea0ef2b.js","sourcesContent":["module.exports = __webpack_public_path__ + \"img/image1.d0c1cc9e.png\";","module.exports = __webpack_public_path__ + \"img/image11.a37c77f8.jpg\";","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h1',{attrs:{\"id\":\"mi-otra-gorra-es-un-teorema\"}},[_vm._v(\"Mi otra gorra es un teorema \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#mi-otra-gorra-es-un-teorema\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Hay alguna manera de que manteniendo la aplicación disponible durante intearleaves no haya pérdida de datos? La respuesta rápida es no. No hay manera que la aplicación funcione correctamente en un interleave. esta idea es conocida como el teorema \"),_c('abbr',{attrs:{\"title\":\"CAP es Consistency, Avaliability, Partition Tolerance\"}},[_vm._v(\"CAP\")]),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn1\",\"id\":\"fnref1\"}},[_vm._v(\"[1]\")])]),_vm._v(\".\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/distribucion/image1.png\")}}),_c('p',[_vm._v(\"Consistencia: Esta es la habilidad que nuestra sistema, tenga 2 o 312123243 nodos que pueda responder a consultas y que tenga el mismo estado, no importa al nodo al que se la hace la consulta. Esto es algo que se logra con transacciones o un mecanismo equivalente. Entonces se tiene que poder ver a todos los nodos como un bloque indivisible. Esto es lo que vimos al comienzo con los contadores, que siempre quede en un estado conocido para el sistema y que no haya por ej. dos nodos que respondan algo distinto al mismo tiempo de realizar la consulta.\")]),_c('p',[_vm._v(\"Disponibilidad: Es simple que siempre que se le pida al sistema por algo de información el sistema me responda, y si no lo hace no está disponible.\")]),_c('p',[_vm._v(\"Particionamiento: Esta parte del teorema es un poco más capciosa. Tolerancia a las particiones significa que el sistema puede seguir funcionando (y contener información útil, estado) aún cuando las partes no puedan comunicarse entre sí. Todo el punto de la tolerancia a la partición es que ese sistema pueda trabajar con mensajes que estén posiblemente perdidos entre componentes. Esto es algo abstracto pero iremos explicando más de esto.\")]),_c('h2',{attrs:{\"id\":\"cap-clasico-o-tradicional\"}},[_c('abbr',{attrs:{\"title\":\"CAP es Consistency, Avaliability, Partition Tolerance\"}},[_vm._v(\"CAP\")]),_vm._v(\" Clasico o Tradicional \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#cap-clasico-o-tradicional\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"La interpretación que veremos ahora es la clásica en la que solo se puede tener dos de los tres conceptos de \"),_c('abbr',{attrs:{\"title\":\"CAP es Consistency, Avaliability, Partition Tolerance\"}},[_vm._v(\"CAP\")]),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn2\",\"id\":\"fnref2\"}},[_vm._v(\"[2]\")])]),_vm._v(\", es decir se puede tener CA, CP o AP. No hay manera de que se puedan tener los tres. Lo malo es que no es posible tener las tres cosas incluso con un fallo de red. Lo bueno es que es un teorema, después veremos que esto es más abierto en la interpretación gradual. tener Consistencia y Disponibilidad no es posible a menos que teóricamente no falle nunca la red, y si sucede en un nodo todo debería fallar. Entonces nos quedan las otras dos partes. AP o CP. Cuando hay un netsplit o interleave la disponibilidad o consistencia permanecen, pero no ambas.\")]),_c('p',[_vm._v(\"El esquema que toman ambas opciones son las siguientes:\")]),_c('p',[_vm._v(\"CP: El estado no cambio, no hay nada que hacer\")]),_c('p',[_vm._v(\"AP: Tiene más flexibilidad y problemas que resolver, se utilizan distintas estrategias:\")]),_c('ul',[_c('li',[_vm._v(\"La última escritura gana, es una resolución del conflicto en donde cualquiera que haga la última escritura, es el valor del estado que queda.\")]),_c('li',[_vm._v(\"Esto puede ser algo abierto ya que en sistemas distribuidos, los timestamps generados pueden ser en el mismo momento o no estarlo incluso presente en el sistema.\")]),_c('li',[_vm._v(\"Se puede elegir al ganador de la escritura aleatoriamente\")]),_c('li',[_vm._v(\"Métodos más sofisticados ayudan a reducir los conflictos por medio de timestamps como el primer caso pero con relojes relativos. Los relojes relativos trabajan incrementalmente con un valor que se suma a cada escritura. Lamport Clocks extiende más esta idea\")]),_c('li',[_vm._v(\"El que almacena el estado, si es un nodo central u otro sistema debe elegir cual de los estados es el correcto, un poco lo que sucede con git cuando tenemos un conflicto.\")])]),_c('h3',{attrs:{\"id\":\"bbdd-y-cap\"}},[_vm._v(\"BBDD y \"),_c('abbr',{attrs:{\"title\":\"CAP es Consistency, Avaliability, Partition Tolerance\"}},[_vm._v(\"CAP\")]),_vm._v(\" \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#bbdd-y-cap\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Este es el gráfico que vimos en clase sobre \"),_c('abbr',{attrs:{\"title\":\"CAP es Consistency, Avaliability, Partition Tolerance\"}},[_vm._v(\"CAP\")]),_vm._v(\" y BBDD, el post en el que se detalla más el siguiente: http://blog.nahurst.com/visual-guide-to-nosql-systems\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/distribucion/image14.png\")}}),_c('h2',{attrs:{\"id\":\"cap-gradual\"}},[_vm._v(\"Cap Gradual \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#cap-gradual\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"El otro concepto, un poco más gradual hace hincapié en que hoy por hoy no se puede solo tener dos de estos conceptos que permiten simplificar estos conceptos ya separados, y no hay que elegir entre uno u otro de los otros conceptos aparte de particiones, hablamos de consistencia y disponibilidad, sino que hay un rango de flexibilidad para manejar y recuperarse de las particiones\"),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn3\",\"id\":\"fnref3\"}},[_vm._v(\"[3]\")])]),_vm._v(\".\")]),_c('h2',{attrs:{\"id\":\"mas-sobre-cap\"}},[_vm._v(\"Mas Sobre \"),_c('abbr',{attrs:{\"title\":\"CAP es Consistency, Avaliability, Partition Tolerance\"}},[_vm._v(\"CAP\")]),_vm._v(\" \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#mas-sobre-cap\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"La manera más fácil de entender \"),_c('abbr',{attrs:{\"title\":\"CAP es Consistency, Avaliability, Partition Tolerance\"}},[_vm._v(\"CAP\")]),_vm._v(\" es pensar que dos nodos separados de una partición, permitiendo que al menos de estos nodos se actualice, permite que el otro se vuelva inconsistente, entonces se deja de lado C. De la misma manera si se preserva la consistencia, un lado de la partición debe actuar como no disponible, dejando de lado A. Solo cuando se comunican los nodos es posible de preservar tanto C como A, dejando de la P. Entonces siempre se piensa en que se debe elegir dos de tres opciones, por el momento centrémonos en el caso en el que se necesiten realizar particiones, aunque dependendiendo del sistema, no siempre aparecen o se necesitan particiones. Entonces la elección entre C y A puede ocurrir varias veces en el sistema con una granularidad bastante fina, y no siempre es algo consistente en todo el sistema, pueden haber sistemas que prioricen una opción sobre otra. La disponibilidad es continuo entre 0 y 100 porciento, pero puede existir niveles de consistencia. En el caso de la interpretación clásica de \"),_c('abbr',{attrs:{\"title\":\"CAP es Consistency, Avaliability, Partition Tolerance\"}},[_vm._v(\"CAP\")]),_vm._v(\", no se considera la latencia y se lo ignora, aunque en práctica, la latencia y las particiones están relacionadas en gran medida. La esencia de \"),_c('abbr',{attrs:{\"title\":\"CAP es Consistency, Avaliability, Partition Tolerance\"}},[_vm._v(\"CAP\")]),_vm._v(\" toma parte durante un timeout, un período en el que programa debe tomar una decisión sobre la partición:\")]),_c('ul',[_c('li',[_vm._v(\"Cancelar la operación y disminuir la disponibilidad\")]),_c('li',[_vm._v(\"Continuar con la operación y arriesgar a que aparezcan inconsistencias\")])]),_c('p',[_vm._v(\"Entonces si queremos volver a intentar comunicarnos con el otro nodo, para querer mantener la consistencia, solo demora la decisión si no responde, entonces se puede decir que una partición es algo atado al tiempo en una comunicación. Si no se puede mantener la consistencia con las implicaciones de tiempo en la conexión implican una operación entre C o A. A veces tan solo se puede sacrificar C en pos de tener mayor A o viceversa, y de acuerdo a la partición y el momento y el escenario en el que está el sistema, priorizar una u otra. Por ejemplo, PNUTS de Yahoo incurre en la inconsistencia manteniendo copias remotas asincrónicamente. Sin embargo, hace una copia local maestra, que decrementa la latencia. Esta estrategia trabaja bien en práctica porque los datos de un usuario simple es naturalmente particionado de acuerdo a la localización del usuario. Facebook, usa otra estrategia, que es la de tener la copia maestra en un lugar, y un usuario remoto en realidad tendría una copia stale más cercana a esta copia maestra. Sin embargo, cuando los usuarios actualizan su página, la actualización va a la copia maestra directamente y los usuarios leerán de esta copia maestra en poco tiempo, a los 20-30 segundos los usuarios empiezan a tener una idea más cercana de lo que está en la copia maestra. Entonces si tenemos particiones, tiene sentido elegir entre A y C? Elegir entre C y A existiendo particiones significa que la probabilidad de particiones puede existir y en caso de falla, fallen múltiples componentes simultáneamente. En realidad lo que sucede es que el sistema realmente pierde algo tanto de C como de A, entonces las tres propiedades en cierta manera son importantes. Hay veces en las que se tiene un sistema en un solo datacenter ( en un solo lugar) y como no poseen particiones, tales diseños incluyendo las RBDMS tradicionales, no necesitan considerar P y son en general AC en su totalidad, estos sistemas en cambio no se particionan sino que optan por el esquema de replicación.\")]),_c('h2',{attrs:{\"id\":\"manejando-particiones\"}},[_vm._v(\"Manejando particiones \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#manejando-particiones\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"En el caso en el que se deban manejar las particiones, estas solo dependen del tiempo en el que se generan y luego se debe unificar estas cuando se restauran, entonces una partición se ve como en la siguiente imagen:\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/distribucion/image11.jpg\")}}),_c('p',[_vm._v(\"y hay tres momentos en una partición\")]),_c('ul',[_c('li',[_vm._v(\"El momento en el que comienza una partición\")]),_c('li',[_vm._v(\"Entrar en una partición explícitamente, que puede limitar algunas operaciones\")]),_c('li',[_vm._v(\"Inicial la recuperación de una partición cuando se necesita unificar las particiones de un sistema.\")])]),_c('p',[_vm._v(\"El último paso apunta a restaurar la consistencia y arreglar los cambios y valores inválidos en las invariantes que se generaron cuando el sistema se particiona. La imagen muestra la evolución de una partición. Una operación normal es una secuencia de operaciones atómicas, y, por lo tanto las particiones empiezan entre operaciones. Si tenemos dos nodos que están interconectados y dejan de hablarse durante un tiempo entonces es muy probable que se haya iniciado una partición, en ese caso el primero inicializa este modo, si en realidad existe una partición, entonces el otro nodo también entrará en este modo, pero solo de un lado se admite la partición. En estos casos debe comunicarse esto al otro nodo para que solo quede de un lado. Cuando un sistema entre en modo partición, dos estrategias son posibles. La primera opción es limitar las operaciones reduciendo la disponibilidad y el segundo guardando información extra sobre las operaciones que pueden ser de ayuda en la recuperación de la partición. Entonces en este punto la comunicación se resume entre los nodos y debe volver a reunificarse el estado único del sistema, en este punto se sabe el estado de ambos nodos y sus historias, la historia en realidad es mejor que las invariantes que forman el estado por un tema que se puede determinar mejor cuál sería el estado final a tomar. El diseñador debe resolver dos problemas\")]),_c('ul',[_c('li',[_vm._v(\"Ambos lados deben quedar consistentes\")]),_c('li',[_vm._v(\"Debe haber una compensación para los errores cometidos durante la fase de partición.\")])]),_c('p',[_vm._v(\"En general se hace una especie de merge dependiendo de la estrategia entre los estados, algo similar a lo que se ve en un CVS, pero hay muchos sistemas que no pueden hacer este mergeo de datos por un tema que no es posible, entonces es el caso en el que se reduce las operaciones disponibles en un sistema durante una partición, Google Docs es un caso de este tipo. Otras opciones son las de tomar por medio de algún algoritmo el dato más nuevo y tomar esas invariantes más nuevas como las definitivas en el sistema.\")]),_c('h3',{attrs:{\"id\":\"adicional\"}},[_vm._v(\"Adicional \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#adicional\"}},[_vm._v(\"¶\")])]),_c('div',{staticClass:\"warning\"},[_c('p',[_c('em',[_vm._v(\"Advertencia: Esta seccion necesita un mayor desarrollo del tema y de citas.\")])])]),_c('p',[_vm._v(\"Existen tambien criticas al teorema\"),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn4\",\"id\":\"fnref4\"}},[_vm._v(\"[4]\")])]),_vm._v(\", en el que se mencionan entre otras cosas, algunas confusiones y ambiguedades de los terminos, y algunos problemas en su formalización. Estas criticas se centran un poco en la dificil aplicacion que puede llegar a tener a veces sobre los sistemas reales.\")]),_c('hr',{staticClass:\"footnotes-sep\"}),_c('section',{staticClass:\"footnotes\"},[_c('ol',{staticClass:\"footnotes-list\"},[_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn1\"}},[_c('p',[_c('a',{attrs:{\"href\":\"https://learnyousomeerlang.com/distribunomicon\"}},[_vm._v(\"Distribunomicon - Learn you some Erlang for greater good\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref1\"}},[_vm._v(\"↩︎\")])])]),_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn2\"}},[_c('p',[_c('a',{attrs:{\"href\":\"http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.67.6951&rep=rep1&type=pdf\"}},[_vm._v(\"Gilbert and Lynch. Brewer conjecture and the feasibility of consistent, available, partition-tolerant web services. ACM SIGACT News (2002) vol. 33 (2) pp. 59\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref2\"}},[_vm._v(\"↩︎\")])])]),_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn3\"}},[_c('p',[_c('a',{attrs:{\"href\":\"http://www.infoq.com/articles/cap-twelve-years-later-how-the-rules-have-changed\"}},[_vm._v(\"Eric A Brewer. \"),_c('abbr',{attrs:{\"title\":\"CAP es Consistency, Avaliability, Partition Tolerance\"}},[_vm._v(\"CAP\")]),_vm._v(\" twelve years later: How the “rules” have changed. IEEE Computer Magazine, 45(2):23–29, February 2012. doi:10.1109/MC.2012.37.\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref3\"}},[_vm._v(\"↩︎\")])])]),_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn4\"}},[_c('p',[_vm._v(\"Kleppmann, M. (2015). A Critique of the \"),_c('abbr',{attrs:{\"title\":\"CAP es Consistency, Avaliability, Partition Tolerance\"}},[_vm._v(\"CAP\")]),_vm._v(\" Theorem. \"),_c('a',{attrs:{\"href\":\"https://doi.org/10.17863/CAM.13083\"}},[_vm._v(\"https://doi.org/10.17863/CAM.13083\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref4\"}},[_vm._v(\"↩︎\")])])])])])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./cap.md?vue&type=template&id=24d1055e&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","module.exports = __webpack_public_path__ + \"img/image14.3e72e131.png\";"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-687c6fec.e5ab64ac.js b/js/chunk-687c6fec.e5ab64ac.js new file mode 100644 index 0000000..0e9f0aa --- /dev/null +++ b/js/chunk-687c6fec.e5ab64ac.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-687c6fec"],{6419:function(t,r,e){"use strict";e("dadc")},dadc:function(t,r,e){},dce0:function(t,r,e){"use strict";e.r(r);var i=function(){var t=this,r=t.$createElement,e=t._self._c||r;return e("div",{staticClass:"error"},[e("div",{staticClass:"container"},[e("div",{staticClass:"row"},[e("div",{staticClass:"col-md-6 align-self-center"},[e("svg",{attrs:{version:"1.1",xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 800 600"}},[e("g",[e("defs",[e("clipPath",{attrs:{id:"GlassClip"}},[e("path",{attrs:{d:"M380.857,346.164c-1.247,4.651-4.668,8.421-9.196,10.06c-9.332,3.377-26.2,7.817-42.301,3.5\n s-28.485-16.599-34.877-24.192c-3.101-3.684-4.177-8.66-2.93-13.311l7.453-27.798c0.756-2.82,3.181-4.868,6.088-5.13\n c6.755-0.61,20.546-0.608,41.785,5.087s33.181,12.591,38.725,16.498c2.387,1.682,3.461,4.668,2.705,7.488L380.857,346.164z"}})]),e("clipPath",{attrs:{id:"cordClip"}},[e("rect",{attrs:{width:"800",height:"600"}})])]),e("g",{attrs:{id:"planet"}},[e("circle",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-miterlimit":"10",cx:"572.859",cy:"108.803",r:"90.788"}}),e("circle",{attrs:{id:"craterBig",fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-miterlimit":"10",cx:"548.891",cy:"62.319",r:"13.074"}}),e("circle",{attrs:{id:"craterSmall",fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-miterlimit":"10",cx:"591.743",cy:"158.918",r:"7.989"}}),e("path",{attrs:{id:"ring",fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",d:"\n M476.562,101.461c-30.404,2.164-49.691,4.221-49.691,8.007c0,6.853,63.166,12.408,141.085,12.408s141.085-5.555,141.085-12.408\n c0-3.378-15.347-4.988-40.243-7.225"}}),e("path",{attrs:{id:"ringShadow",opacity:"0.5",fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",d:"\n M483.985,127.43c23.462,1.531,52.515,2.436,83.972,2.436c36.069,0,68.978-1.19,93.922-3.149"}})]),e("g",{attrs:{id:"stars"}},[e("g",{attrs:{id:"starsBig"}},[e("g",[e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"518.07",y1:"245.375",x2:"518.07",y2:"266.581"}}),e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"508.129",y1:"255.978",x2:"528.01",y2:"255.978"}})]),e("g",[e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"154.55",y1:"231.391",x2:"154.55",y2:"252.598"}}),e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"144.609",y1:"241.995",x2:"164.49",y2:"241.995"}})]),e("g",[e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"320.135",y1:"132.746",x2:"320.135",y2:"153.952"}}),e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"310.194",y1:"143.349",x2:"330.075",y2:"143.349"}})]),e("g",[e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"200.67",y1:"483.11",x2:"200.67",y2:"504.316"}}),e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"210.611",y1:"493.713",x2:"190.73",y2:"493.713"}})])]),e("g",{attrs:{id:"starsSmall"}},[e("g",[e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"432.173",y1:"380.52",x2:"432.173",y2:"391.83"}}),e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"426.871",y1:"386.175",x2:"437.474",y2:"386.175"}})]),e("g",[e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"489.555",y1:"299.765",x2:"489.555",y2:"308.124"}}),e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"485.636",y1:"303.945",x2:"493.473",y2:"303.945"}})]),e("g",[e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"231.468",y1:"291.009",x2:"231.468",y2:"299.369"}}),e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"227.55",y1:"295.189",x2:"235.387",y2:"295.189"}})]),e("g",[e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"244.032",y1:"547.539",x2:"244.032",y2:"555.898"}}),e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"247.95",y1:"551.719",x2:"240.113",y2:"551.719"}})]),e("g",[e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"186.359",y1:"406.967",x2:"186.359",y2:"415.326"}}),e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"190.277",y1:"411.146",x2:"182.44",y2:"411.146"}})]),e("g",[e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"480.296",y1:"406.967",x2:"480.296",y2:"415.326"}}),e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",x1:"484.215",y1:"411.146",x2:"476.378",y2:"411.146"}})])]),e("g",{attrs:{id:"circlesBig"}},[e("circle",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",cx:"588.977",cy:"255.978",r:"7.952"}}),e("circle",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",cx:"450.066",cy:"320.259",r:"7.952"}}),e("circle",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",cx:"168.303",cy:"353.753",r:"7.952"}}),e("circle",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",cx:"429.522",cy:"201.185",r:"7.952"}}),e("circle",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",cx:"200.67",cy:"176.313",r:"7.952"}}),e("circle",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",cx:"133.343",cy:"477.014",r:"7.952"}}),e("circle",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",cx:"283.521",cy:"568.033",r:"7.952"}}),e("circle",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-miterlimit":"10",cx:"413.618",cy:"482.387",r:"7.952"}})]),e("g",{attrs:{id:"circlesSmall"}},[e("circle",{attrs:{fill:"#0E0620",cx:"549.879",cy:"296.402",r:"2.651"}}),e("circle",{attrs:{fill:"#0E0620",cx:"253.29",cy:"229.24",r:"2.651"}}),e("circle",{attrs:{fill:"#0E0620",cx:"434.824",cy:"263.931",r:"2.651"}}),e("circle",{attrs:{fill:"#0E0620",cx:"183.708",cy:"544.176",r:"2.651"}}),e("circle",{attrs:{fill:"#0E0620",cx:"382.515",cy:"530.923",r:"2.651"}}),e("circle",{attrs:{fill:"#0E0620",cx:"130.693",cy:"305.608",r:"2.651"}}),e("circle",{attrs:{fill:"#0E0620",cx:"480.296",cy:"477.014",r:"2.651"}})])]),e("g",{attrs:{id:"spaceman","clip-path":"url(cordClip)"}},[e("path",{attrs:{id:"cord",fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",d:"\n M273.813,410.969c0,0-54.527,39.501-115.34,38.218c-2.28-0.048-4.926-0.241-7.841-0.548\n c-68.038-7.178-134.288-43.963-167.33-103.87c-0.908-1.646-1.793-3.3-2.654-4.964c-18.395-35.511-37.259-83.385-32.075-118.817"}}),e("path",{attrs:{id:"backpack",fill:"#FFFFFF",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",d:"\n M338.164,454.689l-64.726-17.353c-11.086-2.972-17.664-14.369-14.692-25.455l15.694-58.537\n c3.889-14.504,18.799-23.11,33.303-19.221l52.349,14.035c14.504,3.889,23.11,18.799,19.221,33.303l-15.694,58.537\n C360.647,451.083,349.251,457.661,338.164,454.689z"}}),e("g",{attrs:{id:"antenna"}},[e("line",{attrs:{fill:"#FFFFFF",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",x1:"323.396",y1:"236.625",x2:"295.285",y2:"353.753"}}),e("circle",{attrs:{fill:"#FFFFFF",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",cx:"323.666",cy:"235.617",r:"6.375"}})]),e("g",{attrs:{id:"armR"}},[e("path",{attrs:{fill:"#FFFFFF",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",d:"\n M360.633,363.039c1.352,1.061,4.91,5.056,5.824,6.634l27.874,47.634c3.855,6.649,1.59,15.164-5.059,19.02l0,0\n c-6.649,3.855-15.164,1.59-19.02-5.059l-5.603-9.663"}}),e("path",{attrs:{fill:"#FFFFFF",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",d:"\n M388.762,434.677c5.234-3.039,7.731-8.966,6.678-14.594c2.344,1.343,4.383,3.289,5.837,5.793\n c4.411,7.596,1.829,17.33-5.767,21.741c-7.596,4.411-17.33,1.829-21.741-5.767c-1.754-3.021-2.817-5.818-2.484-9.046\n C375.625,437.355,383.087,437.973,388.762,434.677z"}})]),e("g",{attrs:{id:"armL"}},[e("path",{attrs:{fill:"#FFFFFF",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",d:"\n M301.301,347.66c-1.702,0.242-5.91,1.627-7.492,2.536l-47.965,27.301c-6.664,3.829-8.963,12.335-5.134,18.999h0\n c3.829,6.664,12.335,8.963,18.999,5.134l9.685-5.564"}}),e("path",{attrs:{fill:"#FFFFFF",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",d:"\n M241.978,395.324c-3.012-5.25-2.209-11.631,1.518-15.977c-2.701-0.009-5.44,0.656-7.952,2.096\n c-7.619,4.371-10.253,14.09-5.883,21.71c4.371,7.619,14.09,10.253,21.709,5.883c3.03-1.738,5.35-3.628,6.676-6.59\n C252.013,404.214,245.243,401.017,241.978,395.324z"}})]),e("g",{attrs:{id:"body"}},[e("path",{attrs:{fill:"#FFFFFF",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",d:"\n M353.351,365.387c-7.948,1.263-16.249,0.929-24.48-1.278c-8.232-2.207-15.586-6.07-21.836-11.14\n c-17.004,4.207-31.269,17.289-36.128,35.411l-1.374,5.123c-7.112,26.525,8.617,53.791,35.13,60.899l0,0\n c26.513,7.108,53.771-8.632,60.883-35.158l1.374-5.123C371.778,395.999,365.971,377.536,353.351,365.387z"}}),e("path",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",d:"\n M269.678,394.912L269.678,394.912c26.3,20.643,59.654,29.585,93.106,25.724l2.419-0.114"}})]),e("g",{attrs:{id:"legs"}},[e("g",{attrs:{id:"legR"}},[e("path",{attrs:{fill:"#FFFFFF",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",d:"\n M312.957,456.734l-14.315,53.395c-1.896,7.07,2.299,14.338,9.37,16.234l0,0c7.07,1.896,14.338-2.299,16.234-9.37l17.838-66.534\n C333.451,455.886,323.526,457.387,312.957,456.734z"}}),e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",x1:"304.883",y1:"486.849",x2:"330.487",y2:"493.713"}})]),e("g",{attrs:{id:"legL"}},[e("path",{attrs:{fill:"#FFFFFF",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",d:"\n M296.315,452.273L282,505.667c-1.896,7.07-9.164,11.265-16.234,9.37l0,0c-7.07-1.896-11.265-9.164-9.37-16.234l17.838-66.534\n C278.993,441.286,286.836,447.55,296.315,452.273z"}}),e("line",{attrs:{fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",x1:"262.638",y1:"475.522",x2:"288.241",y2:"482.387"}})])]),e("g",{attrs:{id:"head"}},[e("ellipse",{attrs:{transform:"matrix(0.259 -0.9659 0.9659 0.259 -51.5445 563.2371)",fill:"#FFFFFF",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",cx:"341.295",cy:"315.211",rx:"61.961",ry:"60.305"}}),e("path",{attrs:{id:"headStripe",fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",d:"\n M330.868,261.338c-7.929,1.72-15.381,5.246-21.799,10.246"}}),e("path",{attrs:{fill:"#FFFFFF",stroke:"#0E0620","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round","stroke-miterlimit":"10",d:"\n M380.857,346.164c-1.247,4.651-4.668,8.421-9.196,10.06c-9.332,3.377-26.2,7.817-42.301,3.5s-28.485-16.599-34.877-24.192\n c-3.101-3.684-4.177-8.66-2.93-13.311l7.453-27.798c0.756-2.82,3.181-4.868,6.088-5.13c6.755-0.61,20.546-0.608,41.785,5.087\n s33.181,12.591,38.725,16.498c2.387,1.682,3.461,4.668,2.705,7.488L380.857,346.164z"}}),e("g",{attrs:{"clip-path":"url(#GlassClip)"}},[e("polygon",{attrs:{id:"glassShine",fill:"none",stroke:"#0E0620","stroke-width":"3","stroke-miterlimit":"10",points:"\n 278.436,375.599 383.003,264.076 364.393,251.618 264.807,364.928 \t\t\t\t"}})])])])])])]),e("div",{staticClass:"col-md-6 align-self-center"},[e("h1",[t._v("404")]),e("h2",[t._v("UH OH! You're lost.")]),e("p",[t._v("The page you are looking for does not exist. How you got here is a mystery. But you can click the button below to go back to the homepage. ")]),e("router-link",{staticClass:"nav-link",attrs:{to:"/"}},[e("button",{staticClass:"btn orange"},[t._v("HOME")])])],1)])])])},o=[],s={name:"NotFound"},l=s,n=(e("6419"),e("2877")),k=Object(n["a"])(l,i,o,!1,null,"6e5db9d2",null);r["default"]=k.exports}}]); +//# sourceMappingURL=chunk-687c6fec.e5ab64ac.js.map \ No newline at end of file diff --git a/js/chunk-687c6fec.e5ab64ac.js.map b/js/chunk-687c6fec.e5ab64ac.js.map new file mode 100644 index 0000000..c748f2b --- /dev/null +++ b/js/chunk-687c6fec.e5ab64ac.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/views/errors/NotFound.vue?696f","webpack:///./src/views/errors/NotFound.vue?5f46","webpack:///src/views/errors/NotFound.vue","webpack:///./src/views/errors/NotFound.vue?2e9a","webpack:///./src/views/errors/NotFound.vue"],"names":["render","_vm","this","_h","$createElement","_c","_self","staticClass","attrs","_v","staticRenderFns","component"],"mappings":"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","file":"js/chunk-687c6fec.e5ab64ac.js","sourcesContent":["export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./NotFound.vue?vue&type=style&index=0&id=6e5db9d2&lang=scss&scoped=true&\"","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"error\"},[_c('div',{staticClass:\"container\"},[_c('div',{staticClass:\"row\"},[_c('div',{staticClass:\"col-md-6 align-self-center\"},[_c('svg',{attrs:{\"version\":\"1.1\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"xmlns:xlink\":\"http://www.w3.org/1999/xlink\",\"viewBox\":\"0 0 800 600\"}},[_c('g',[_c('defs',[_c('clipPath',{attrs:{\"id\":\"GlassClip\"}},[_c('path',{attrs:{\"d\":\"M380.857,346.164c-1.247,4.651-4.668,8.421-9.196,10.06c-9.332,3.377-26.2,7.817-42.301,3.5\\n s-28.485-16.599-34.877-24.192c-3.101-3.684-4.177-8.66-2.93-13.311l7.453-27.798c0.756-2.82,3.181-4.868,6.088-5.13\\n c6.755-0.61,20.546-0.608,41.785,5.087s33.181,12.591,38.725,16.498c2.387,1.682,3.461,4.668,2.705,7.488L380.857,346.164z\"}})]),_c('clipPath',{attrs:{\"id\":\"cordClip\"}},[_c('rect',{attrs:{\"width\":\"800\",\"height\":\"600\"}})])]),_c('g',{attrs:{\"id\":\"planet\"}},[_c('circle',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-miterlimit\":\"10\",\"cx\":\"572.859\",\"cy\":\"108.803\",\"r\":\"90.788\"}}),_c('circle',{attrs:{\"id\":\"craterBig\",\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-miterlimit\":\"10\",\"cx\":\"548.891\",\"cy\":\"62.319\",\"r\":\"13.074\"}}),_c('circle',{attrs:{\"id\":\"craterSmall\",\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-miterlimit\":\"10\",\"cx\":\"591.743\",\"cy\":\"158.918\",\"r\":\"7.989\"}}),_c('path',{attrs:{\"id\":\"ring\",\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"d\":\"\\n M476.562,101.461c-30.404,2.164-49.691,4.221-49.691,8.007c0,6.853,63.166,12.408,141.085,12.408s141.085-5.555,141.085-12.408\\n c0-3.378-15.347-4.988-40.243-7.225\"}}),_c('path',{attrs:{\"id\":\"ringShadow\",\"opacity\":\"0.5\",\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"d\":\"\\n M483.985,127.43c23.462,1.531,52.515,2.436,83.972,2.436c36.069,0,68.978-1.19,93.922-3.149\"}})]),_c('g',{attrs:{\"id\":\"stars\"}},[_c('g',{attrs:{\"id\":\"starsBig\"}},[_c('g',[_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"518.07\",\"y1\":\"245.375\",\"x2\":\"518.07\",\"y2\":\"266.581\"}}),_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"508.129\",\"y1\":\"255.978\",\"x2\":\"528.01\",\"y2\":\"255.978\"}})]),_c('g',[_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"154.55\",\"y1\":\"231.391\",\"x2\":\"154.55\",\"y2\":\"252.598\"}}),_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"144.609\",\"y1\":\"241.995\",\"x2\":\"164.49\",\"y2\":\"241.995\"}})]),_c('g',[_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"320.135\",\"y1\":\"132.746\",\"x2\":\"320.135\",\"y2\":\"153.952\"}}),_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"310.194\",\"y1\":\"143.349\",\"x2\":\"330.075\",\"y2\":\"143.349\"}})]),_c('g',[_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"200.67\",\"y1\":\"483.11\",\"x2\":\"200.67\",\"y2\":\"504.316\"}}),_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"210.611\",\"y1\":\"493.713\",\"x2\":\"190.73\",\"y2\":\"493.713\"}})])]),_c('g',{attrs:{\"id\":\"starsSmall\"}},[_c('g',[_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"432.173\",\"y1\":\"380.52\",\"x2\":\"432.173\",\"y2\":\"391.83\"}}),_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"426.871\",\"y1\":\"386.175\",\"x2\":\"437.474\",\"y2\":\"386.175\"}})]),_c('g',[_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"489.555\",\"y1\":\"299.765\",\"x2\":\"489.555\",\"y2\":\"308.124\"}}),_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"485.636\",\"y1\":\"303.945\",\"x2\":\"493.473\",\"y2\":\"303.945\"}})]),_c('g',[_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"231.468\",\"y1\":\"291.009\",\"x2\":\"231.468\",\"y2\":\"299.369\"}}),_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"227.55\",\"y1\":\"295.189\",\"x2\":\"235.387\",\"y2\":\"295.189\"}})]),_c('g',[_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"244.032\",\"y1\":\"547.539\",\"x2\":\"244.032\",\"y2\":\"555.898\"}}),_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"247.95\",\"y1\":\"551.719\",\"x2\":\"240.113\",\"y2\":\"551.719\"}})]),_c('g',[_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"186.359\",\"y1\":\"406.967\",\"x2\":\"186.359\",\"y2\":\"415.326\"}}),_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"190.277\",\"y1\":\"411.146\",\"x2\":\"182.44\",\"y2\":\"411.146\"}})]),_c('g',[_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"480.296\",\"y1\":\"406.967\",\"x2\":\"480.296\",\"y2\":\"415.326\"}}),_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"484.215\",\"y1\":\"411.146\",\"x2\":\"476.378\",\"y2\":\"411.146\"}})])]),_c('g',{attrs:{\"id\":\"circlesBig\"}},[_c('circle',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"cx\":\"588.977\",\"cy\":\"255.978\",\"r\":\"7.952\"}}),_c('circle',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"cx\":\"450.066\",\"cy\":\"320.259\",\"r\":\"7.952\"}}),_c('circle',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"cx\":\"168.303\",\"cy\":\"353.753\",\"r\":\"7.952\"}}),_c('circle',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"cx\":\"429.522\",\"cy\":\"201.185\",\"r\":\"7.952\"}}),_c('circle',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"cx\":\"200.67\",\"cy\":\"176.313\",\"r\":\"7.952\"}}),_c('circle',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"cx\":\"133.343\",\"cy\":\"477.014\",\"r\":\"7.952\"}}),_c('circle',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"cx\":\"283.521\",\"cy\":\"568.033\",\"r\":\"7.952\"}}),_c('circle',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-miterlimit\":\"10\",\"cx\":\"413.618\",\"cy\":\"482.387\",\"r\":\"7.952\"}})]),_c('g',{attrs:{\"id\":\"circlesSmall\"}},[_c('circle',{attrs:{\"fill\":\"#0E0620\",\"cx\":\"549.879\",\"cy\":\"296.402\",\"r\":\"2.651\"}}),_c('circle',{attrs:{\"fill\":\"#0E0620\",\"cx\":\"253.29\",\"cy\":\"229.24\",\"r\":\"2.651\"}}),_c('circle',{attrs:{\"fill\":\"#0E0620\",\"cx\":\"434.824\",\"cy\":\"263.931\",\"r\":\"2.651\"}}),_c('circle',{attrs:{\"fill\":\"#0E0620\",\"cx\":\"183.708\",\"cy\":\"544.176\",\"r\":\"2.651\"}}),_c('circle',{attrs:{\"fill\":\"#0E0620\",\"cx\":\"382.515\",\"cy\":\"530.923\",\"r\":\"2.651\"}}),_c('circle',{attrs:{\"fill\":\"#0E0620\",\"cx\":\"130.693\",\"cy\":\"305.608\",\"r\":\"2.651\"}}),_c('circle',{attrs:{\"fill\":\"#0E0620\",\"cx\":\"480.296\",\"cy\":\"477.014\",\"r\":\"2.651\"}})])]),_c('g',{attrs:{\"id\":\"spaceman\",\"clip-path\":\"url(cordClip)\"}},[_c('path',{attrs:{\"id\":\"cord\",\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"d\":\"\\n M273.813,410.969c0,0-54.527,39.501-115.34,38.218c-2.28-0.048-4.926-0.241-7.841-0.548\\n c-68.038-7.178-134.288-43.963-167.33-103.87c-0.908-1.646-1.793-3.3-2.654-4.964c-18.395-35.511-37.259-83.385-32.075-118.817\"}}),_c('path',{attrs:{\"id\":\"backpack\",\"fill\":\"#FFFFFF\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"d\":\"\\n M338.164,454.689l-64.726-17.353c-11.086-2.972-17.664-14.369-14.692-25.455l15.694-58.537\\n c3.889-14.504,18.799-23.11,33.303-19.221l52.349,14.035c14.504,3.889,23.11,18.799,19.221,33.303l-15.694,58.537\\n C360.647,451.083,349.251,457.661,338.164,454.689z\"}}),_c('g',{attrs:{\"id\":\"antenna\"}},[_c('line',{attrs:{\"fill\":\"#FFFFFF\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"323.396\",\"y1\":\"236.625\",\"x2\":\"295.285\",\"y2\":\"353.753\"}}),_c('circle',{attrs:{\"fill\":\"#FFFFFF\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"cx\":\"323.666\",\"cy\":\"235.617\",\"r\":\"6.375\"}})]),_c('g',{attrs:{\"id\":\"armR\"}},[_c('path',{attrs:{\"fill\":\"#FFFFFF\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"d\":\"\\n M360.633,363.039c1.352,1.061,4.91,5.056,5.824,6.634l27.874,47.634c3.855,6.649,1.59,15.164-5.059,19.02l0,0\\n c-6.649,3.855-15.164,1.59-19.02-5.059l-5.603-9.663\"}}),_c('path',{attrs:{\"fill\":\"#FFFFFF\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"d\":\"\\n M388.762,434.677c5.234-3.039,7.731-8.966,6.678-14.594c2.344,1.343,4.383,3.289,5.837,5.793\\n c4.411,7.596,1.829,17.33-5.767,21.741c-7.596,4.411-17.33,1.829-21.741-5.767c-1.754-3.021-2.817-5.818-2.484-9.046\\n C375.625,437.355,383.087,437.973,388.762,434.677z\"}})]),_c('g',{attrs:{\"id\":\"armL\"}},[_c('path',{attrs:{\"fill\":\"#FFFFFF\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"d\":\"\\n M301.301,347.66c-1.702,0.242-5.91,1.627-7.492,2.536l-47.965,27.301c-6.664,3.829-8.963,12.335-5.134,18.999h0\\n c3.829,6.664,12.335,8.963,18.999,5.134l9.685-5.564\"}}),_c('path',{attrs:{\"fill\":\"#FFFFFF\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"d\":\"\\n M241.978,395.324c-3.012-5.25-2.209-11.631,1.518-15.977c-2.701-0.009-5.44,0.656-7.952,2.096\\n c-7.619,4.371-10.253,14.09-5.883,21.71c4.371,7.619,14.09,10.253,21.709,5.883c3.03-1.738,5.35-3.628,6.676-6.59\\n C252.013,404.214,245.243,401.017,241.978,395.324z\"}})]),_c('g',{attrs:{\"id\":\"body\"}},[_c('path',{attrs:{\"fill\":\"#FFFFFF\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"d\":\"\\n M353.351,365.387c-7.948,1.263-16.249,0.929-24.48-1.278c-8.232-2.207-15.586-6.07-21.836-11.14\\n c-17.004,4.207-31.269,17.289-36.128,35.411l-1.374,5.123c-7.112,26.525,8.617,53.791,35.13,60.899l0,0\\n c26.513,7.108,53.771-8.632,60.883-35.158l1.374-5.123C371.778,395.999,365.971,377.536,353.351,365.387z\"}}),_c('path',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"d\":\"\\n M269.678,394.912L269.678,394.912c26.3,20.643,59.654,29.585,93.106,25.724l2.419-0.114\"}})]),_c('g',{attrs:{\"id\":\"legs\"}},[_c('g',{attrs:{\"id\":\"legR\"}},[_c('path',{attrs:{\"fill\":\"#FFFFFF\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"d\":\"\\n M312.957,456.734l-14.315,53.395c-1.896,7.07,2.299,14.338,9.37,16.234l0,0c7.07,1.896,14.338-2.299,16.234-9.37l17.838-66.534\\n C333.451,455.886,323.526,457.387,312.957,456.734z\"}}),_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"304.883\",\"y1\":\"486.849\",\"x2\":\"330.487\",\"y2\":\"493.713\"}})]),_c('g',{attrs:{\"id\":\"legL\"}},[_c('path',{attrs:{\"fill\":\"#FFFFFF\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"d\":\"\\n M296.315,452.273L282,505.667c-1.896,7.07-9.164,11.265-16.234,9.37l0,0c-7.07-1.896-11.265-9.164-9.37-16.234l17.838-66.534\\n C278.993,441.286,286.836,447.55,296.315,452.273z\"}}),_c('line',{attrs:{\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"x1\":\"262.638\",\"y1\":\"475.522\",\"x2\":\"288.241\",\"y2\":\"482.387\"}})])]),_c('g',{attrs:{\"id\":\"head\"}},[_c('ellipse',{attrs:{\"transform\":\"matrix(0.259 -0.9659 0.9659 0.259 -51.5445 563.2371)\",\"fill\":\"#FFFFFF\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"cx\":\"341.295\",\"cy\":\"315.211\",\"rx\":\"61.961\",\"ry\":\"60.305\"}}),_c('path',{attrs:{\"id\":\"headStripe\",\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"d\":\"\\n M330.868,261.338c-7.929,1.72-15.381,5.246-21.799,10.246\"}}),_c('path',{attrs:{\"fill\":\"#FFFFFF\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-linecap\":\"round\",\"stroke-linejoin\":\"round\",\"stroke-miterlimit\":\"10\",\"d\":\"\\n M380.857,346.164c-1.247,4.651-4.668,8.421-9.196,10.06c-9.332,3.377-26.2,7.817-42.301,3.5s-28.485-16.599-34.877-24.192\\n c-3.101-3.684-4.177-8.66-2.93-13.311l7.453-27.798c0.756-2.82,3.181-4.868,6.088-5.13c6.755-0.61,20.546-0.608,41.785,5.087\\n s33.181,12.591,38.725,16.498c2.387,1.682,3.461,4.668,2.705,7.488L380.857,346.164z\"}}),_c('g',{attrs:{\"clip-path\":\"url(#GlassClip)\"}},[_c('polygon',{attrs:{\"id\":\"glassShine\",\"fill\":\"none\",\"stroke\":\"#0E0620\",\"stroke-width\":\"3\",\"stroke-miterlimit\":\"10\",\"points\":\"\\n 278.436,375.599 383.003,264.076 364.393,251.618 264.807,364.928 \\t\\t\\t\\t\"}})])])])])])]),_c('div',{staticClass:\"col-md-6 align-self-center\"},[_c('h1',[_vm._v(\"404\")]),_c('h2',[_vm._v(\"UH OH! You're lost.\")]),_c('p',[_vm._v(\"The page you are looking for does not exist. How you got here is a mystery. But you can click the button below to go back to the homepage. \")]),_c('router-link',{staticClass:\"nav-link\",attrs:{\"to\":\"/\"}},[_c('button',{staticClass:\"btn orange\"},[_vm._v(\"HOME\")])])],1)])])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./NotFound.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./NotFound.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./NotFound.vue?vue&type=template&id=6e5db9d2&scoped=true&\"\nimport script from \"./NotFound.vue?vue&type=script&lang=js&\"\nexport * from \"./NotFound.vue?vue&type=script&lang=js&\"\nimport style0 from \"./NotFound.vue?vue&type=style&index=0&id=6e5db9d2&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"6e5db9d2\",\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-7095c905.6bcb0115.js b/js/chunk-7095c905.6bcb0115.js new file mode 100644 index 0000000..77a604e --- /dev/null +++ b/js/chunk-7095c905.6bcb0115.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-7095c905"],{1705:function(e,a,s){e.exports=s.p+"img/guilds_1.8b5d1a6a.png"},"321d":function(e,a,s){e.exports=s.p+"img/guilds_3.07dd8c32.png"},"33ef":function(e,a,s){e.exports=s.p+"img/guilds_0.c4d25035.png"},"4a3e":function(e,a,s){e.exports=s.p+"img/guilds_7.33caabec.png"},"58d5":function(e,a,s){e.exports=s.p+"img/puma-general-arch.4d403982.png"},6448:function(e,a,s){e.exports=s.p+"img/guilds_4.c4345142.png"},"6b49":function(e,a,s){e.exports=s.p+"img/in_rod_we_trust.61a8e21b.png"},"83e5":function(e,a,s){e.exports=s.p+"img/child-processes.bc85fc35.svg"},9176:function(e,a,s){e.exports=s.p+"img/guilds_2.3132ef15.png"},c546:function(e,a,s){e.exports=s.p+"img/xruby-gil-jvm.4771a258.png"},cba7:function(e,a,s){e.exports=s.p+"img/homer-grill.b73187de.gif"},d04f:function(e,a,s){e.exports=s.p+"img/pisa_tower.37378781.jpeg"},da47:function(e,a,s){e.exports=s.p+"img/guilds_8.dc175235.png"},dfd0:function(e,a,s){e.exports=s.p+"img/guilds_6.bdc76127.png"},f723:function(e,a,s){"use strict";s.r(a);var o=function(){var e=this,a=e.$createElement;e._self._c;return e._m(0)},r=[function(){var e=this,a=e.$createElement,o=e._self._c||a;return o("section",[o("h1",{attrs:{id:"guild-wars"}},[e._v("Guild wars (?) "),o("a",{staticClass:"header-anchor",attrs:{href:"#guild-wars"}},[e._v("¶")])]),o("p",[e._v('Como vimos en las clases anteriores, Ruby MRI posee "algunos problemas" en cuanto a como maneja el procesamiento en paralelo en múltiples procesadores. Si bien vimos que la concurrencia es algo que perfectamente puede darse sin necesidad de contextos de ejecución que se ejecuten al mismo tiempo'),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn1",id:"fnref1"}},[e._v("[1]")])]),e._v(", vamos a ver en esta sección, nuevos y existentes mecanismos para tratar de resolver este problema latente en MRI desde sus comienzos.")]),o("img",{staticClass:"center",staticStyle:{width:"200px"},attrs:{src:s("d04f")}}),o("br"),o("h3",{attrs:{id:"un-poco-de-historia"}},[e._v("Un poco de historia... "),o("a",{staticClass:"header-anchor",attrs:{href:"#un-poco-de-historia"}},[e._v("¶")])]),o("p",[e._v("Ruby puede implementar mecanismos concurrentes pero no paralelos debido al "),o("abbr",{attrs:{title:"Global VM Lock"}},[e._v("GVL")]),e._v(" a.k.a "),o("abbr",{attrs:{title:"Global Interpreter Lock"}},[e._v("GIL")]),e._v(" (Global VM Lock o Giant VM Lock), que es un bloqueo de exclusión mutua, en suma, un mutex. Este bloqueo lo mantiene el subproceso del intérprete y lo usa para evitar compartir código que no es seguro para subprocesos con otros subprocesos. Todos los hilos de intérpretes tienen su propio "),o("abbr",{attrs:{title:"Global Interpreter Lock"}},[e._v("GIL")]),e._v(". Debido a dicho "),o("abbr",{attrs:{title:"Global Interpreter Lock"}},[e._v("GIL")]),e._v(", si un programa Ruby tiene múltiples hilos, no pueden ejecutarse al mismo tiempo, porque "),o("abbr",{attrs:{title:"Global Interpreter Lock"}},[e._v("GIL")]),e._v(" solo permitirá que se ejecute un subproceso al mismo tiempo. Antes de Ruby 1.9, solo había un hilo del sistema operativo para todos los hilos de sistema de MRI que podemos crear mediante la librería standard de Ruby"),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn2",id:"fnref2"}},[e._v("[2]")])]),e._v(".")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("c546")}}),o("div",{staticClass:"warning"},[o("p",[o("em",[e._v("Extra")]),e._v(": El mecanismo de como se adquiere y libera el "),o("abbr",{attrs:{title:"Global VM Lock"}},[e._v("GVL")]),e._v(" se puede ver "),o("a",{attrs:{href:"https://github.com/ruby/ruby/blob/a8714b83c40c8736b4ddafef08fa5f0091c9b101/thread_pthread.c#L314"}},[e._v("aqui")]),e._v(" y "),o("a",{attrs:{href:"https://github.com/ruby/ruby/blob/a8714b83c40c8736b4ddafef08fa5f0091c9b101/thread_pthread.c#L236"}},[e._v("aqui")]),e._v(" se puede ver la lógica del timeslice donde se ejecuta el thread que pudo adquirir el "),o("abbr",{attrs:{title:"Global VM Lock"}},[e._v("GVL")]),e._v(".")])]),o("p",[e._v("Como vemos en la foto, después de Ruby 1.9, podemos tener varios hilos del sistema operativo y estos se relacionan 1:1 contra nuestros hilos de usuario, pero debido al "),o("abbr",{attrs:{title:"Global VM Lock"}},[e._v("GVL")]),e._v(", como se menciono antes, "),o("em",[e._v("solo y solo un hilo")]),e._v(", de todos los hilos del sistema operativo creados pueden ejecutarse al mismo tiempo, descartando la posibilidad de soporte "),o("abbr",{attrs:{title:"Symmetric Multi-Processor"}},[e._v("SMP")]),e._v(".")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("6b49")}}),o("p",{staticStyle:{"text-align":"center","font-size":"13px"}},[e._v("La inerte barra de carbono representa el GVL siendo tomado por un hilo..")]),o("p",[e._v("Este tipo de mecanismos son algo visto no solo en MRI sino también en CPython"),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn3",id:"fnref3"}},[e._v("[3]")])]),e._v(", y ambas máquinas virtuales sufren de los mismos problemas.")]),o("p",[e._v("En Java también se puede definir múltiples subprocesos,pero la diferencia es que en la JVM,se puede mapear cada hilo de la JVM a uno del sistema operativo. Esto permite aprovechar la arquitectura multinúcleo. En este caso cuando usamos JRuby, la librería de "),o("code",{pre:!0},[e._v("threads")]),e._v(" de Ruby, es en realidad un wrapper de los hilos de la JVM, por esta razón, vamos a poder tener exactamente el mismo código y vamos a poder tener soporte "),o("abbr",{attrs:{title:"Symmetric Multi-Processor"}},[e._v("SMP")]),e._v(".")]),o("h3",{attrs:{id:"status-quo-workers"}},[e._v("Status Quo: Workers "),o("a",{staticClass:"header-anchor",attrs:{href:"#status-quo-workers"}},[e._v("¶")])]),o("p",[e._v("Una manera de poder aprovechar la ejecución de múltiples procesadores, es algo que vimos en Puma"),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn4",id:"fnref4"}},[e._v("[4]")])]),e._v(", es que se pueda trabajar como si fuese un "),o("code",{pre:!0},[e._v("'cluster'")]),e._v(", en donde el proceso principal inicializa la aplicación, y luego se usa el syscall "),o("a",{attrs:{href:"https://man7.org/linux/man-pages/man2/fork.2.html"}},[o("code",{pre:!0},[e._v("fork()")])]),e._v(" para crear 1 o más procesos hijos. Estos procesos hijos, en el caso de Puma por ejemplo, escuchan al mismo socket que el proceso padre, y este último deja de escuchar al socket, para solo ser relegado para escuchar a señales de UNIX y posiblemente para matar/iniciar los procesos hijos.")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("58d5")}}),o("p",[e._v("Este mecanismo, si bien es simple, puede dar la sensación de que si bien empieza cada proceso hijo, con poca memoria, gradualmente ira creciendo hasta ser tan grande como el proceso padre. Incluso en grandes entornos de producción, esto puede significar una gran cantidad de memoria, y crear un problema de falta de memoria si tenemos muchos "),o("em",[e._v("workers/procesos hijos")]),e._v(".")]),o("p",[e._v("Sin embargo, los sistemas operativos modernos, tienen manejo de memoria virtual, que proveen de un mecanismo llamado "),o("em",[e._v("copy on write")]),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn5",id:"fnref5"}},[e._v("[5]")])]),e._v(", que previene del escenario que describimos antes. La memoria virtual de un proceso, esta separado en bloques de 4k, llamadas paginas. Cuando un proceso padre, crea un proceso hijo; el hijo inicialmente comparte todas las paginas de memoria con el padre. Solo cuando el proceso hijo empieza a modificar una o varias de estas paginas, el kernel se encargara de copiar las paginas de memoria modificadas, y de reasignarlo al nuevo proceso.")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("83e5")}}),o("p",[e._v("El diagrama visto más arriba, muestra un poco como van cambiando, y copiandose las paginas a medida que pasa el tiempo. El mecanismo de como MRI aloca memoria puede verse muy bien explicado en"),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn6",id:"fnref6"}},[e._v("[6]")])]),e._v(".")]),o("h3",{attrs:{id:"la-propuesta-guilds"}},[e._v("La propuesta: Guilds "),o("a",{staticClass:"header-anchor",attrs:{href:"#la-propuesta-guilds"}},[e._v("¶")])]),o("p",[e._v("Si bien tener múltiples procesos hijos permite de alguna manera saltear y poder aprovechar más procesadores, existen varias desventajas por lo que no es a veces una solución óptima.")]),o("p",[e._v('Una de ellas es que tengamos que realizar un offloading que no tengo demasiado estado, y por consiguiente, tengamos contextos de ejecución algo "pesados", y que consume más memoria de lo que realmente necesita o se justifica. En caso de que tengamos que trabajar con algún tipo de hardware que no posee tantos recursos, por ejemplo hardware embebido, tal vez necesitemos hacer un mejor uso de la memoria existente, con lo cual tener múltiples procesos puede llegar a ser muy costoso. Otra razón es que el uso de un '),o("code",{pre:!0},[e._v("fork()")]),e._v(", implica que hay que recurrir a una solución, que esta por afuera en parte de las abstracciones que maneja o soporta MRI.")]),o("p",[e._v("Estas razones, hicieron que en parte se busque por una solución parcial o definitiva, sin tener que recurrir a algo tan extremo, como el de eliminar por completo el "),o("abbr",{attrs:{title:"Global VM Lock"}},[e._v("GVL")]),e._v(", debido a que se necesiten realizar cambios muchos más drásticos, a nivel de manejo de memoria y GC.")]),o("p",[e._v("El origen de Ractor se remonta a 2016 cuando Koichi Sasada (diseñador de la máquina virtual Ruby y recolección de basura) presentó su propuesta sobre un nuevo modelo de concurrencia para Ruby. Antes de dicha propuesta, solo podíamos aprovechar múltiples procesadores mediante subprocesos hijos.")]),o("p",[e._v("En 2016, Koichi habló sobre los problemas de la programación de subprocesos múltiples en su presentación en Ruby Kaigi"),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn7",id:"fnref7"}},[e._v("[7]")])]),e._v(", así como sobre algunas formas comunes de resolverlos. Junto con eso, también presentó su concepto de "),o("code",{pre:!0},[e._v("Guilds")]),e._v(" por primera vez. Antes de pasar a Ractors, tomemos un momento para comprender los aspectos básicos de Ractors: "),o("code",{pre:!0},[e._v("Guilds")]),e._v(".")]),o("h4",{attrs:{id:"que-es-un-guild"}},[e._v("Que es un Guild? "),o("a",{staticClass:"header-anchor",attrs:{href:"#que-es-un-guild"}},[e._v("¶")])]),o("div",{staticClass:"warning"},[o("p",[e._v("Las imágenes a continuación fueron tomadas de la presentación de Koichi Sasada"),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn7",id:"fnref7:1"}},[e._v("[7:1]")])])])]),o("p",[e._v("Un Guild, fue propuesto, como una una nueva abstracción de concurrencia para Ruby. Donde cada uno de estos "),o("code",{pre:!0},[e._v("Guilds")]),e._v(', tendría uno o más hilos, y cada uno de estos, a su vez, albergaría una o más "fibers"/corutinas.')]),o("img",{staticClass:"center iasc-image",attrs:{src:s("33ef")}}),o("p",[e._v("Los hijos de dos "),o("code",{pre:!0},[e._v("Guilds")]),e._v(", podrían ejecutarse en paralelo, pero los hijos que estan enmarcados dentro de un mismo "),o("code",{pre:!0},[e._v("Guild")]),e._v(" no. Esto se garantizaría a través de un nuevo lock llamado "),o("abbr",{attrs:{title:"Giant Guild Lock, no Good Game Lock"}},[e._v("GGL")]),e._v(", que solo permite ejecutar en primer plano a un hilo a la vez.")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("1705")}}),o("p",[e._v("Además, todos los Guilds tendrían su propio conjunto de objetos mutables, y un "),o("code",{pre:!0},[e._v("Guild")]),e._v(" no podría modificar los objetos de otro "),o("code",{pre:!0},[e._v("Guild")]),e._v(". Esto se propuso para evitar problemas de inconsistencia de datos debido al acceso concurrente.")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("9176")}}),o("p",[e._v("Sin embargo, los "),o("code",{pre:!0},[e._v("Guilds")]),e._v(" aún podrían usar la interfaz "),o("code",{pre:!0},[e._v("Guild::Channel")]),e._v(" para facilitar la copia o el movimiento de objetos entre ellos. El método "),o("code",{pre:!0},[e._v("transfer(object)")]),e._v(" se propuso para permitir enviar una copia profunda del objeto al "),o("code",{pre:!0},[e._v("Guild")]),e._v(" objetivo, y "),o("code",{pre:!0},[e._v("transfer_membership(object)")]),e._v(" se propuso para permitir mover un objeto de un "),o("code",{pre:!0},[e._v("Guild")]),e._v(" a otro por completo.")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("321d")}}),o("img",{staticClass:"center iasc-image",attrs:{src:s("6448")}}),o("p",[e._v("Pero todo esto fue solo para objetos mutables, ya que los objetos inmutables no representan un riesgo de inconsistencia de datos. Esto es así porque una vez que se asigna un valor a los objetos inmutables, este no cambia durante la ejecución del programa, por lo que cualquier "),o("code",{pre:!0},[e._v("Guild")]),e._v(" que intente acceder a los datos de un objeto inmutable siempre recibirá el mismo valor consistente. Los objetos inmutables se podrían compartir en todos los "),o("code",{pre:!0},[e._v("Guilds")]),e._v(" para operaciones de lectura.")]),o("p",[e._v("Los objetos inmutables en Ruby consisten en:")]),o("ul",[o("li",[e._v("Integers, "),o("code",{pre:!0},[e._v("true")]),e._v(", "),o("code",{pre:!0},[e._v("false")]),e._v(", "),o("code",{pre:!0},[e._v("nil")]),e._v(" (a.k.a. "),o("a",{attrs:{href:"https://github.com/ruby/ruby/blob/d92f09a5eea009fa28cd046e9d0eb698e3d94c5c/include/ruby/internal/special_consts.h#L179"}},[e._v("SPECIAL_CONST_P()")]),e._v(")")]),o("li",[e._v("Todos los símbolos")]),o("li",[e._v("Strings u objetos 'frizados'. Ej: "),o("code",{pre:!0},[e._v('s = "str".freeze')]),e._v(", donde "),o("code",{pre:!0},[e._v("s")]),e._v(" es inmutable.")]),o("li",[e._v("Objetos numericos: Float, Complex, Rational, big integers ("),o("a",{attrs:{href:"https://github.com/ruby/ruby/blob/62bc4a9420fa5786d49391a713bd38b09b8db0ff/include/ruby/internal/value_type.h#L123"}},[e._v("T_BIGNUM in internal")]),e._v(")")]),o("li",[e._v("objetos como clases o modulos (T_CLASS, T_MODULE and T_ICLASS en internal).")]),o("li",[e._v("Ractor y otros objetos especiales usados para sincronización")])]),o("img",{staticClass:"center iasc-image",attrs:{src:s("f993")}}),o("h5",{attrs:{id:"uso-propuesto-de-los-guilds"}},[e._v("Uso propuesto de los Guilds "),o("a",{staticClass:"header-anchor",attrs:{href:"#uso-propuesto-de-los-guilds"}},[e._v("¶")])]),o("p",[e._v("Koichi habla en su presentación del uso de este nuevo tipo de abstracción"),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn7",id:"fnref7:2"}},[e._v("[7:2]")])]),e._v(", y que separa en distintos casos de uso")]),o("ul",[o("li",[e._v("Caso de Uso 1: Maestro - Worker")])]),o("p",[e._v("La idea de este caso de uso es que exista un "),o("code",{pre:!0},[e._v("Guild")]),e._v(" maestro, que inicialice la ejecución, y después existan, uno o más "),o("code",{pre:!0},[e._v("Guilds")]),e._v(" que realizaran el procesamiento (workers). Este modelo se basa en delegación de tareas repetitivas o conocidas por los "),o("code",{pre:!0},[e._v("Guilds")]),e._v(" workers, y el maestro, solo se encargará de enviar por medio de un channel, el dato de entrada para ser procesado por un worker y tratar de esperar por una respuesta a continuación. El código de ejemplo fue el cálculo de fibonacci, que se muestra a continuación:")]),o("pre",{pre:!0},[o("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[o("span",{pre:!0,attrs:{class:"hljs-function"}},[o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),o("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("fib")]),o("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(n)")])]),e._v(" ... "),o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n\ng_fib = Guild.new("),o("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v("script:")]),e._v(" "),o("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("%q{\n ch = Guild.default_channel\n while n, return_ch = ch.receive\n return_ch.transfer fib(n)\n end\n}")]),e._v(")\n\nch = Guild::Channel.new\n\ng_fib.transfer(["),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("3")]),e._v(", ch])\n\nputs ch.receive\n")])]),o("p",[e._v("En el ejemplo, solo se realiza el calculo de un solo valor, aunque puede llamarse múltiples veces a "),o("code",{pre:!0},[e._v("g_fib")]),e._v(", para que se creen nuevos "),o("code",{pre:!0},[e._v("guilds")]),e._v(", y puedan procesar en paralelo.")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("dfd0")}}),o("ul",[o("li",[e._v("Caso de Uso 2: Pipeline")])]),o("p",[e._v("El segundo caso es el de un pipeline, en donde una serie de procesos, se separan en varios pasos, y en cada uno de estos segmentos, se trata en un "),o("code",{pre:!0},[e._v("Guild")]),e._v(" distinto. Una vez que termina el procesamiento de uno, el dato resultante se transfiere al siguiente "),o("code",{pre:!0},[e._v("Guild")]),e._v(".")]),o("pre",{pre:!0},[o("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v("result_ch = Guild::Channel.new\n\ng_pipe3 = Guild.new("),o("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v("script:")]),e._v(" "),o("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("%q{\n while obj = Guild.default_channel.receive\n obj = modify_obj3(obj)\n Guild.argv[0].transfer_membership(obj)\n end\n}")]),e._v(", "),o("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v("argv:")]),e._v(" [result_ch])\n\ng_pipe2 = Guild.new("),o("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v("script:")]),e._v(" "),o("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("%q{\n while obj = Guild.default_channel.receive\n obj = modify_obj2(obj)\n Guild.argv[0].transfer_membership(obj)\n end\n}")]),e._v(", "),o("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v("argv:")]),e._v(" [g_pipe3])\n\ng_pipe1 = Guild.new("),o("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v("script:")]),e._v(" "),o("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("%q{\n while obj = Guild.default_channel.receive\n obj = modify_obj1(obj)\n Guild.argv[0].transfer_membership(obj)\n end\n}")]),e._v(", "),o("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v("argv:")]),e._v(" [g_pipe2])\n\nobj = SomeClass.new\n\ng_pipe1.transfer_membership(obj)\n\nobj = result_ch.receive\n")])]),o("p",[e._v("Aqui se muestra como la arquitectura se veria conceptualmente:")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("4a3e")}}),o("ul",[o("li",[e._v("Caso de Uso 3: Datos sensibles. Ej cuentas bancarias")])]),o("p",[e._v("Este es un caso de uso tradicional, donde tenemos datos que pueden mutar y que son sensibles. En este caso, es de alguna manera similar al caso 1, donde hay un "),o("code",{pre:!0},[e._v("Guild")]),e._v(' "maestro", que es el que posee los datos sensibles, y el estado que puede mutar. De esta manera permite aislar el estado y que solo el cambio del estado se genere con condiciones que sean controlables en un solo lugar. También permite que se puedan implementar sobre el Guild "maestro", mecanismos de seguridad y de transaccionalidad, donde se puede loggear todos los movimientos y en caso de que se tenga que volver para atrás se puede hacer, solo en un solo lugar.')]),o("pre",{pre:!0},[o("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[e._v("g_bank = Guild.new("),o("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v("script:")]),e._v(" "),o("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("%q{\n while account_from, account_to, amount,\n ch = Guild.default_channel.receive\n if (Bank[account_from].balance < amount)\n ch.transfer :NOPE\n else\n Bank[account_to].balance += amount\n Bank[account_from].balance -= amount\n ch.transfer :YEP\n end\n end\n}")]),e._v(")\n…\n")])]),o("p",[e._v("Si se observa el diagrama conceptual para esta arquitectura, se dará cuenta de que es lo mismo que el concepto que el "),o("code",{pre:!0},[e._v("caso 1")]),e._v(", pero el único cambio clave es que los datos, recursos, etc., pertenecen únicamente al "),o("code",{pre:!0},[e._v("guild")]),e._v(" maestro.")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("da47")}}),o("h4",{attrs:{id:"ractors-la-implementación-de-guilds"}},[e._v("Ractors, la implementación de Guilds "),o("a",{staticClass:"header-anchor",attrs:{href:"#ractors-la-implementación-de-guilds"}},[e._v("¶")])]),o("p",[e._v("Ractors, fue lanzado como experimental en "),o("a",{attrs:{href:"https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/"}},[e._v("Ruby 3.0.0")]),e._v(", y es la implementación, por el momento mas estable de la idea conceptual de Guilds.")]),o("img",{staticClass:"center iasc-image",attrs:{src:s("cba7")}}),o("p",[e._v("La idea por atrás es la misma, un "),o("code",{pre:!0},[e._v("ractor")]),e._v(' tiene uno o más hilos, y cada uno de estos, a su vez, alberga una o más "fibers"/corutinas. y dos '),o("code",{pre:!0},[e._v("ractors")]),e._v(", pueden ejecutarse potencialmente en paralelo, siempre y cuando el procesamiento que haya que realizar en estos sea bastante intensivo.")]),o("p",[e._v("La idea de aislamiento de variables o datos mutables es la misma que la planteada en los "),o("code",{pre:!0},[e._v("Guilds")]),e._v(". Un "),o("code",{pre:!0},[e._v("ractor")]),e._v(" no puede acceder a los datos de otro, a menos que se transfiera o copie el mismo, pero esto solo aplica a los datos mutables. Con respecto a las variables/datos inmutables, estos se pueden acceder sin problemas, entre los "),o("code",{pre:!0},[e._v("ractors")]),e._v(" que existan en el sistema.")]),o("p",[e._v("La mayor diferencia viene, en cuanto a la comunicación entre los "),o("code",{pre:!0},[e._v("ractors")]),e._v(". Estos a diferencia de los "),o("code",{pre:!0},[e._v("Guilds")]),e._v(", se comunican por medio de simples pasos de mensajes, en vez de "),o("code",{pre:!0},[e._v("channels")]),e._v(". La idea final es que dicho modelo sea similar al de actores. Pero lo es realmente? Esto lo veremos después. Veamos las 'ventajas'.")]),o("h5",{attrs:{id:"ventajas"}},[e._v("Ventajas?? "),o("a",{staticClass:"header-anchor",attrs:{href:"#ventajas"}},[e._v("¶")])]),o("p",[e._v("Con respecto a las ventajas, las mismas son obvias en cuanto a lo que apuntan a resolver. Permitir la ejecución, en múltiples procesadores/cores, permite de alguna manera una mejor performance, reduciendo el tiempo promedio de ejecución de tareas que lo son, y que no generan ningún tipo de relación directa. Veamos el ejemplo mostrado en el realease de Ruby 3.0.0, donde se ejecuta el algoritmo "),o("code",{pre:!0},[e._v("tak")]),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn8",id:"fnref8"}},[e._v("[8]")])]),e._v(" "),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn9",id:"fnref9"}},[e._v("[9]")])]),e._v(" secuencialmente y usando "),o("code",{pre:!0},[e._v("ractors")]),e._v(" 4 veces.")]),o("pre",{pre:!0},[o("code",{pre:!0,attrs:{"v-pre":"",class:"language-ruby"}},[o("span",{pre:!0,attrs:{class:"hljs-function"}},[o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("def")]),e._v(" "),o("span",{pre:!0,attrs:{class:"hljs-title"}},[e._v("tarai")]),o("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("(x, y, z)")])]),e._v(" =\n x <= y ? y : tarai(tarai(x-"),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(", y, z),\n tarai(y-"),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(", z, x),\n tarai(z-"),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("1")]),e._v(", x, y))\n"),o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("require")]),e._v(" "),o("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'benchmark'")]),e._v("\nBenchmark.bm "),o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("do")]),e._v(" "),o("span",{pre:!0,attrs:{class:"hljs-params"}},[e._v("|x|")]),e._v("\n "),o("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("# sequential version")]),e._v("\n x.report("),o("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'seq'")]),e._v("){ "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("4")]),e._v(".times{ tarai("),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("14")]),e._v(", "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("7")]),e._v(", "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v(") } }\n\n "),o("span",{pre:!0,attrs:{class:"hljs-comment"}},[e._v("# parallel version")]),e._v("\n x.report("),o("span",{pre:!0,attrs:{class:"hljs-string"}},[e._v("'par'")]),e._v("){\n "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("4")]),e._v(".times.map "),o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("do")]),e._v("\n Ractor.new { tarai("),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("14")]),e._v(", "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("7")]),e._v(", "),o("span",{pre:!0,attrs:{class:"hljs-number"}},[e._v("0")]),e._v(") }\n "),o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v(".each(&"),o("span",{pre:!0,attrs:{class:"hljs-symbol"}},[e._v(":take")]),e._v(")\n }\n"),o("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v("\n")])]),o("p",[e._v("Los resultados muestran las ventajas..")]),o("pre",{pre:!0},[o("code",{pre:!0,attrs:{"v-pre":""}},[e._v("Benchmark result:\n user system total real\nseq 64.560736 0.001101 64.561837 ( 64.562194)\npar 66.422010 0.015999 66.438009 ( 16.685797)\n")])]),o("p",[e._v("El codigo esta disponible también "),o("a",{attrs:{href:"https://github.com/bossiernesto/tarai"}},[e._v("aqui")])]),o("p",[e._v("Esta ventaja es facil de ver, aunque lo mas interesante en realidad, es la creación de una abstracción que permita que pueda convivir de alguna manera código que soporte "),o("abbr",{attrs:{title:"Symmetric Multi-Processor"}},[e._v("SMP")]),e._v(" y parte que no, sin tener que recurrir a eliminar definitivamente el "),o("abbr",{attrs:{title:"Global VM Lock"}},[e._v("GVL")]),e._v(".")]),o("h5",{attrs:{id:"problemas-latentes"}},[e._v("Problemas latentes "),o("a",{staticClass:"header-anchor",attrs:{href:"#problemas-latentes"}},[e._v("¶")])]),o("p",[e._v("Si bien se habla que en los Ractors son thread-safe dentro de su contexto, gracias (o no..) al "),o("abbr",{attrs:{title:"Giant Guild Lock, no Good Game Lock"}},[e._v("GGL")]),e._v("; en realidad no son completamente "),o("code",{pre:!0},[e._v("thread-safe")]),e._v(", ya que la interfaz que poseen todavía puede generar casos de deadlock o livelock incluso, si es que no se tiene cuidado.")]),o("p",[e._v("Esta estructura, tiene que ser siempre usada de una manera correcta (tanto como el resto), ya que un uso poco cuidadoso, usando módulos/clases entre varios Ractors"),o("sup",{staticClass:"footnote-ref"},[o("a",{attrs:{href:"#fn10",id:"fnref10"}},[e._v("[10]")])]),e._v(", puede introducir race conditions. También otra cosa a tener en cuenta, es que el envio de mensajes entre ractors(send, yield, take, etc), es el mismo que hay entre objetos, por lo que es siempre bloqueante. Si estos se usan incorrectamente pueden resultar en "),o("code",{pre:!0},[e._v("dead-locks")]),e._v(" o "),o("code",{pre:!0},[e._v("live-locks")]),e._v(" como se menciono antes.")]),o("p",[e._v("Por el momento, esta implementacion es experimental, por lo que pueden existir incluso bugs, tanto en el ciclo de vida, como en el manejo interno de estos en memoria (por ej. a nivel del GC de MRI aka gc.c).")]),o("h4",{attrs:{id:"uso-actual-de-ractors"}},[e._v("Uso actual de Ractors "),o("a",{staticClass:"header-anchor",attrs:{href:"#uso-actual-de-ractors"}},[e._v("¶")])]),o("div",{staticClass:"warning"},[o("p",[e._v("Esta sección puede cambiar a lo largo del tiempo, ya que el código actual de Ractors es experimental y puede deprecarse rápidamente. Puede verse mas en la doc oficial de "),o("a",{attrs:{href:"https://docs.ruby-lang.org/en/3.0.0/doc/ractor_md.html"}},[e._v("ractors.md")])])]),o("ul",[o("li",[o("p",[o("code",{pre:!0},[e._v("Ractor.new{expr}")]),e._v(" crea un nuevo Ractor y "),o("code",{pre:!0},[e._v("expr")]),e._v(" se ejecuta en paralelo en otro procesador.")])]),o("li",[o("p",[e._v("El intérprete invoca con el primer Ractor (llamado Ractor principal).")])]),o("li",[o("p",[e._v("Si el Ractor principal finaliza, todos los Ractores reciben una solicitud de finalización como hilos (si el hilo principal (el primer hilo invocado), el intérprete de Ruby envía todos los hilos en ejecución para finalizar la ejecución).")])]),o("li",[o("p",[e._v("Cada Ractor tiene 1 o más hilos.")])]),o("li",[o("p",[e._v("Los subprocesos en un Ractor comparten un bloqueo global en todo el Ractor, similar al "),o("abbr",{attrs:{title:"Global Interpreter Lock"}},[e._v("GIL")]),e._v(" ("),o("abbr",{attrs:{title:"Global VM Lock"}},[e._v("GVL")]),e._v(" en terminología de MRI), por lo que no pueden ejecutarse en paralelo (sin liberar "),o("abbr",{attrs:{title:"Global VM Lock"}},[e._v("GVL")]),e._v(" explícitamente en el nivel C). Los hilos en diferentes ractores se ejecutan en paralelo.")])]),o("li",[o("p",[e._v("La sobrecarga de crear un Ractor es similar a la sobrecarga de la creación de un hilo usuario y el hilo de OS asociado.")])])]),o("h5",{attrs:{id:"paso-de-mensajes"}},[e._v("Paso de mensajes "),o("a",{staticClass:"header-anchor",attrs:{href:"#paso-de-mensajes"}},[e._v("¶")])]),o("ul",[o("li",[o("p",[e._v("Paso de mensaje de tipo push: "),o("code",{pre:!0},[e._v("Ractor#send(obj")]),e._v(") y "),o("code",{pre:!0},[e._v("Ractor.receive()")]),e._v(".")]),o("ul",[o("li",[e._v("El ractor remitente pasa el obj al ractor r mediante "),o("code",{pre:!0},[e._v("r.send(obj)")]),e._v(" y el ractor receptor recibe el mensaje con Ractor.receive.")]),o("li",[e._v("El remitente conoce el Ractor de destino r y el receptor no conoce al remitente (acepte todos los mensajes de cualquier ractor).")]),o("li",[e._v("El receptor tiene una cola infinita y el remitente pone en cola el mensaje. El remitente no bloquea para poner el mensaje en esta cola.")]),o("li",[e._v("Este tipo de intercambio de mensajes se emplea en muchos otros lenguajes basados ​​en actores.")])])]),o("li",[o("p",[e._v("Comunicación de tipo pull: "),o("code",{pre:!0},[e._v("Ractor.yield(obj)")]),e._v(" y "),o("code",{pre:!0},[e._v("Ractor#take()")]),e._v(".")]),o("ul",[o("li",[e._v("El emisor ractor declara ceder el obj por "),o("code",{pre:!0},[e._v("Ractor.yield(obj)")]),e._v(" y el receptor Ractor lo toma con r.take.")]),o("li",[e._v("El remitente no conoce un Ractor de destino y el receptor conoce el Ractor r del remitente.")]),o("li",[e._v("El remitente o el receptor se bloquearán si no hay otro lado.")])])])]),o("h5",{attrs:{id:"ciclo-de-vida"}},[e._v("Ciclo de Vida "),o("a",{staticClass:"header-anchor",attrs:{href:"#ciclo-de-vida"}},[e._v("¶")])]),o("p",[e._v("Puede verse un resumen del ciclo de vida de un ractor en el siguiente "),o("a",{attrs:{href:"https://github.com/ruby/ruby/blob/83a744dd8c0d6e769258b734b9f6861a22eeb554/ractor.c#L1449"}},[e._v("diagrama")]),e._v(":")]),o("pre",{pre:!0},[o("code",{pre:!0,attrs:{"v-pre":""}},[e._v(" created\n | ready to run\n ====================== inserted to vm->ractor\n v\n blocking <---+ all threads are blocking\n | |\n v |\n running -----+\n | all threads are terminated.\n ====================== removed from vm->ractor\n v\n terminated\n\n status is protected by VM lock (global state)\n")])]),o("p",[e._v("El ciclo de vida empieza con "),o("code",{pre:!0},[e._v("Ractor.new")]),e._v(" donde una vez que se registra el mismo en "),o("code",{pre:!0},[e._v("vm->ractor")]),e._v(", esto sucede una vez que puede tomarse control del "),o("abbr",{attrs:{title:"Global VM Lock"}},[e._v("GVL")]),e._v(", para proceder a la creación e inicialización de memoria del contexto. Una vez que el ractor está creado, siempre tendrá como mínimo un hilo, y en caso de que el mismo pueda ejecutarse, pasara a estado "),o("code",{pre:!0},[e._v("running")]),e._v(". En caso de que se envíe un mensaje o se espere alguna acción se pasará a tener otro hilo planificado en primer plano del ractor, en caso de que todos los hilos se bloqueen, el estado pasa a "),o("code",{pre:!0},[e._v("bloqueado")]),e._v(". Cuando todos los hilos han finalizado, el ractor pasa a "),o("code",{pre:!0},[e._v("terminated")]),e._v(".")]),o("p",[e._v("Todos los cambios de estado implican un cambio del estado del ractor, y el mismo está protegido por el "),o("abbr",{attrs:{title:"Global VM Lock"}},[e._v("GVL")]),e._v(" de la VM.")]),o("hr",{staticClass:"footnotes-sep"}),o("section",{staticClass:"footnotes"},[o("ol",{staticClass:"footnotes-list"},[o("li",{staticClass:"footnote-item",attrs:{id:"fn1"}},[o("p",[o("a",{attrs:{href:"https://arquitecturas-concurrentes.github.io/iasc-book/concurrencia_paralelismo"}},[e._v("IASC UTN FRBA. (2020) .Concurrencia y Paralelismo")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref1"}},[e._v("↩︎")])])]),o("li",{staticClass:"footnote-item",attrs:{id:"fn2"}},[o("p",[o("a",{attrs:{href:"https://ruby-doc.org/core-3.0.2/Thread.html"}},[e._v("Ruby Doc. Retrieved 30 August 2021. Thread standard library")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref2"}},[e._v("↩︎")])])]),o("li",{staticClass:"footnote-item",attrs:{id:"fn3"}},[o("p",[o("a",{attrs:{href:"https://wiki.python.org/moin/GlobalInterpreterLock"}},[e._v("Python Moin. Retrieved 30 November 2015. GlobalInterpreterLock")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref3"}},[e._v("↩︎")])])]),o("li",{staticClass:"footnote-item",attrs:{id:"fn4"}},[o("p",[o("a",{attrs:{href:"https://puma.io/puma/file.architecture.html"}},[e._v("Puma Doc. Architecture Overview")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref4"}},[e._v("↩︎")])])]),o("li",{staticClass:"footnote-item",attrs:{id:"fn5"}},[o("p",[o("a",{attrs:{href:"http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=C97A7B66D788B7E4F6D6BF5FDD8EC451?doi=10.1.1.33.3144&rep=rep1&type=pdf"}},[e._v("Javier, Francisco & Guttman, Joshua. (1995). Copy on Write.")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref5"}},[e._v("↩︎")])])]),o("li",{staticClass:"footnote-item",attrs:{id:"fn6"}},[o("p",[o("a",{attrs:{href:"https://brandur.org/ruby-memory"}},[e._v("Brandur. (2017). The Limits of Copy-on-write: How Ruby Allocates Memory")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref6"}},[e._v("↩︎")])])]),o("li",{staticClass:"footnote-item",attrs:{id:"fn7"}},[o("p",[o("a",{attrs:{href:"http://www.atdot.net/~ko1/activities/2016_rubykaigi.pdf"}},[e._v("Sasada, Koichi. (2016). A proposal of new concurrency model for Ruby 3 (RubyKaigi2016)")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref7"}},[e._v("↩︎")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref7:1"}},[e._v("↩︎")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref7:2"}},[e._v("↩︎")])])]),o("li",{staticClass:"footnote-item",attrs:{id:"fn8"}},[o("p",[o("a",{attrs:{href:"https://www.amazon.com/exec/obidos/ISBN%3D0685479412/ericstreasuretroA/"}},[e._v("Vardi, I. The Running Time of TAK. Ch. 9 in Computational Recreations in Mathematica. Redwood City, CA: Addison-Wesley, pp. 179-199, 1991.")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref8"}},[e._v("↩︎")])])]),o("li",{staticClass:"footnote-item",attrs:{id:"fn9"}},[o("p",[o("a",{attrs:{href:"https://archive.org/details/AcornUser052-Nov86/page/n198/mode/1up"}},[e._v("Testing the Tak. Acorn User. pp. 197, 199.")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref9"}},[e._v("↩︎")])])]),o("li",{staticClass:"footnote-item",attrs:{id:"fn10"}},[o("p",[o("a",{attrs:{href:"https://docs.ruby-lang.org/en/3.0.0/doc/ractor_md.html#label-Thread-safety"}},[e._v("Ruby Lang. (2021). Ractor documentation. Thread-safety.")]),e._v(" "),o("a",{staticClass:"footnote-backref",attrs:{href:"#fnref10"}},[e._v("↩︎")])])])])])])}],t=s("2877"),n={},i=Object(t["a"])(n,o,r,!1,null,null,null);a["default"]=i.exports},f993:function(e,a,s){e.exports=s.p+"img/guilds_5.d4b578a0.png"}}]); +//# sourceMappingURL=chunk-7095c905.6bcb0115.js.map \ No newline at end of file diff --git a/js/chunk-7095c905.6bcb0115.js.map b/js/chunk-7095c905.6bcb0115.js.map new file mode 100644 index 0000000..3165b4d --- /dev/null +++ b/js/chunk-7095c905.6bcb0115.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/images/guilds/guilds_1.png","webpack:///./src/images/guilds/guilds_3.png","webpack:///./src/images/guilds/guilds_0.png","webpack:///./src/images/guilds/guilds_7.png","webpack:///./src/images/guilds/puma-general-arch.png","webpack:///./src/images/guilds/guilds_4.png","webpack:///./src/images/guilds/in_rod_we_trust.png","webpack:///./src/images/guilds/child-processes.svg","webpack:///./src/images/guilds/guilds_2.png","webpack:///./src/images/guilds/xruby-gil-jvm.png","webpack:///./src/images/guilds/homer-grill.gif","webpack:///./src/images/guilds/pisa_tower.jpeg","webpack:///./src/images/guilds/guilds_8.png","webpack:///./src/images/guilds/guilds_6.png","webpack:///./src/content/guild.md?d9f1","webpack:///./src/content/guild.md","webpack:///./src/images/guilds/guilds_5.png"],"names":["module","exports","render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","staticStyle","pre","script","component"],"mappings":"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","file":"js/chunk-7095c905.6bcb0115.js","sourcesContent":["module.exports = __webpack_public_path__ + \"img/guilds_1.8b5d1a6a.png\";","module.exports = __webpack_public_path__ + \"img/guilds_3.07dd8c32.png\";","module.exports = __webpack_public_path__ + \"img/guilds_0.c4d25035.png\";","module.exports = __webpack_public_path__ + \"img/guilds_7.33caabec.png\";","module.exports = __webpack_public_path__ + \"img/puma-general-arch.4d403982.png\";","module.exports = __webpack_public_path__ + \"img/guilds_4.c4345142.png\";","module.exports = __webpack_public_path__ + \"img/in_rod_we_trust.61a8e21b.png\";","module.exports = __webpack_public_path__ + \"img/child-processes.bc85fc35.svg\";","module.exports = __webpack_public_path__ + \"img/guilds_2.3132ef15.png\";","module.exports = __webpack_public_path__ + \"img/xruby-gil-jvm.4771a258.png\";","module.exports = __webpack_public_path__ + \"img/homer-grill.b73187de.gif\";","module.exports = __webpack_public_path__ + \"img/pisa_tower.37378781.jpeg\";","module.exports = __webpack_public_path__ + \"img/guilds_8.dc175235.png\";","module.exports = __webpack_public_path__ + \"img/guilds_6.bdc76127.png\";","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h1',{attrs:{\"id\":\"guild-wars\"}},[_vm._v(\"Guild wars (?) \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#guild-wars\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Como vimos en las clases anteriores, Ruby MRI posee \\\"algunos problemas\\\" en cuanto a como maneja el procesamiento en paralelo en múltiples procesadores. Si bien vimos que la concurrencia es algo que perfectamente puede darse sin necesidad de contextos de ejecución que se ejecuten al mismo tiempo\"),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn1\",\"id\":\"fnref1\"}},[_vm._v(\"[1]\")])]),_vm._v(\", vamos a ver en esta sección, nuevos y existentes mecanismos para tratar de resolver este problema latente en MRI desde sus comienzos.\")]),_c('img',{staticClass:\"center\",staticStyle:{\"width\":\"200px\"},attrs:{\"src\":require(\"@/images/guilds/pisa_tower.jpeg\")}}),_c('br'),_c('h3',{attrs:{\"id\":\"un-poco-de-historia\"}},[_vm._v(\"Un poco de historia... \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#un-poco-de-historia\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Ruby puede implementar mecanismos concurrentes pero no paralelos debido al \"),_c('abbr',{attrs:{\"title\":\"Global VM Lock\"}},[_vm._v(\"GVL\")]),_vm._v(\" a.k.a \"),_c('abbr',{attrs:{\"title\":\"Global Interpreter Lock\"}},[_vm._v(\"GIL\")]),_vm._v(\" (Global VM Lock o Giant VM Lock), que es un bloqueo de exclusión mutua, en suma, un mutex. Este bloqueo lo mantiene el subproceso del intérprete y lo usa para evitar compartir código que no es seguro para subprocesos con otros subprocesos. Todos los hilos de intérpretes tienen su propio \"),_c('abbr',{attrs:{\"title\":\"Global Interpreter Lock\"}},[_vm._v(\"GIL\")]),_vm._v(\". Debido a dicho \"),_c('abbr',{attrs:{\"title\":\"Global Interpreter Lock\"}},[_vm._v(\"GIL\")]),_vm._v(\", si un programa Ruby tiene múltiples hilos, no pueden ejecutarse al mismo tiempo, porque \"),_c('abbr',{attrs:{\"title\":\"Global Interpreter Lock\"}},[_vm._v(\"GIL\")]),_vm._v(\" solo permitirá que se ejecute un subproceso al mismo tiempo. Antes de Ruby 1.9, solo había un hilo del sistema operativo para todos los hilos de sistema de MRI que podemos crear mediante la librería standard de Ruby\"),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn2\",\"id\":\"fnref2\"}},[_vm._v(\"[2]\")])]),_vm._v(\".\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/guilds/xruby-gil-jvm.png\")}}),_c('div',{staticClass:\"warning\"},[_c('p',[_c('em',[_vm._v(\"Extra\")]),_vm._v(\": El mecanismo de como se adquiere y libera el \"),_c('abbr',{attrs:{\"title\":\"Global VM Lock\"}},[_vm._v(\"GVL\")]),_vm._v(\" se puede ver \"),_c('a',{attrs:{\"href\":\"https://github.com/ruby/ruby/blob/a8714b83c40c8736b4ddafef08fa5f0091c9b101/thread_pthread.c#L314\"}},[_vm._v(\"aqui\")]),_vm._v(\" y \"),_c('a',{attrs:{\"href\":\"https://github.com/ruby/ruby/blob/a8714b83c40c8736b4ddafef08fa5f0091c9b101/thread_pthread.c#L236\"}},[_vm._v(\"aqui\")]),_vm._v(\" se puede ver la lógica del timeslice donde se ejecuta el thread que pudo adquirir el \"),_c('abbr',{attrs:{\"title\":\"Global VM Lock\"}},[_vm._v(\"GVL\")]),_vm._v(\".\")])]),_c('p',[_vm._v(\"Como vemos en la foto, después de Ruby 1.9, podemos tener varios hilos del sistema operativo y estos se relacionan 1:1 contra nuestros hilos de usuario, pero debido al \"),_c('abbr',{attrs:{\"title\":\"Global VM Lock\"}},[_vm._v(\"GVL\")]),_vm._v(\", como se menciono antes, \"),_c('em',[_vm._v(\"solo y solo un hilo\")]),_vm._v(\", de todos los hilos del sistema operativo creados pueden ejecutarse al mismo tiempo, descartando la posibilidad de soporte \"),_c('abbr',{attrs:{\"title\":\"Symmetric Multi-Processor\"}},[_vm._v(\"SMP\")]),_vm._v(\".\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/guilds/in_rod_we_trust.png\")}}),_c('p',{staticStyle:{\"text-align\":\"center\",\"font-size\":\"13px\"}},[_vm._v(\"La inerte barra de carbono representa el GVL siendo tomado por un hilo..\")]),_c('p',[_vm._v(\"Este tipo de mecanismos son algo visto no solo en MRI sino también en CPython\"),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn3\",\"id\":\"fnref3\"}},[_vm._v(\"[3]\")])]),_vm._v(\", y ambas máquinas virtuales sufren de los mismos problemas.\")]),_c('p',[_vm._v(\"En Java también se puede definir múltiples subprocesos,pero la diferencia es que en la JVM,se puede mapear cada hilo de la JVM a uno del sistema operativo. Esto permite aprovechar la arquitectura multinúcleo. En este caso cuando usamos JRuby, la librería de \"),_c('code',{pre:true},[_vm._v(\"threads\")]),_vm._v(\" de Ruby, es en realidad un wrapper de los hilos de la JVM, por esta razón, vamos a poder tener exactamente el mismo código y vamos a poder tener soporte \"),_c('abbr',{attrs:{\"title\":\"Symmetric Multi-Processor\"}},[_vm._v(\"SMP\")]),_vm._v(\".\")]),_c('h3',{attrs:{\"id\":\"status-quo-workers\"}},[_vm._v(\"Status Quo: Workers \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#status-quo-workers\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Una manera de poder aprovechar la ejecución de múltiples procesadores, es algo que vimos en Puma\"),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn4\",\"id\":\"fnref4\"}},[_vm._v(\"[4]\")])]),_vm._v(\", es que se pueda trabajar como si fuese un \"),_c('code',{pre:true},[_vm._v(\"'cluster'\")]),_vm._v(\", en donde el proceso principal inicializa la aplicación, y luego se usa el syscall \"),_c('a',{attrs:{\"href\":\"https://man7.org/linux/man-pages/man2/fork.2.html\"}},[_c('code',{pre:true},[_vm._v(\"fork()\")])]),_vm._v(\" para crear 1 o más procesos hijos. Estos procesos hijos, en el caso de Puma por ejemplo, escuchan al mismo socket que el proceso padre, y este último deja de escuchar al socket, para solo ser relegado para escuchar a señales de UNIX y posiblemente para matar/iniciar los procesos hijos.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/guilds/puma-general-arch.png\")}}),_c('p',[_vm._v(\"Este mecanismo, si bien es simple, puede dar la sensación de que si bien empieza cada proceso hijo, con poca memoria, gradualmente ira creciendo hasta ser tan grande como el proceso padre. Incluso en grandes entornos de producción, esto puede significar una gran cantidad de memoria, y crear un problema de falta de memoria si tenemos muchos \"),_c('em',[_vm._v(\"workers/procesos hijos\")]),_vm._v(\".\")]),_c('p',[_vm._v(\"Sin embargo, los sistemas operativos modernos, tienen manejo de memoria virtual, que proveen de un mecanismo llamado \"),_c('em',[_vm._v(\"copy on write\")]),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn5\",\"id\":\"fnref5\"}},[_vm._v(\"[5]\")])]),_vm._v(\", que previene del escenario que describimos antes. La memoria virtual de un proceso, esta separado en bloques de 4k, llamadas paginas. Cuando un proceso padre, crea un proceso hijo; el hijo inicialmente comparte todas las paginas de memoria con el padre. Solo cuando el proceso hijo empieza a modificar una o varias de estas paginas, el kernel se encargara de copiar las paginas de memoria modificadas, y de reasignarlo al nuevo proceso.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/guilds/child-processes.svg\")}}),_c('p',[_vm._v(\"El diagrama visto más arriba, muestra un poco como van cambiando, y copiandose las paginas a medida que pasa el tiempo. El mecanismo de como MRI aloca memoria puede verse muy bien explicado en\"),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn6\",\"id\":\"fnref6\"}},[_vm._v(\"[6]\")])]),_vm._v(\".\")]),_c('h3',{attrs:{\"id\":\"la-propuesta-guilds\"}},[_vm._v(\"La propuesta: Guilds \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#la-propuesta-guilds\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Si bien tener múltiples procesos hijos permite de alguna manera saltear y poder aprovechar más procesadores, existen varias desventajas por lo que no es a veces una solución óptima.\")]),_c('p',[_vm._v(\"Una de ellas es que tengamos que realizar un offloading que no tengo demasiado estado, y por consiguiente, tengamos contextos de ejecución algo \\\"pesados\\\", y que consume más memoria de lo que realmente necesita o se justifica. En caso de que tengamos que trabajar con algún tipo de hardware que no posee tantos recursos, por ejemplo hardware embebido, tal vez necesitemos hacer un mejor uso de la memoria existente, con lo cual tener múltiples procesos puede llegar a ser muy costoso. Otra razón es que el uso de un \"),_c('code',{pre:true},[_vm._v(\"fork()\")]),_vm._v(\", implica que hay que recurrir a una solución, que esta por afuera en parte de las abstracciones que maneja o soporta MRI.\")]),_c('p',[_vm._v(\"Estas razones, hicieron que en parte se busque por una solución parcial o definitiva, sin tener que recurrir a algo tan extremo, como el de eliminar por completo el \"),_c('abbr',{attrs:{\"title\":\"Global VM Lock\"}},[_vm._v(\"GVL\")]),_vm._v(\", debido a que se necesiten realizar cambios muchos más drásticos, a nivel de manejo de memoria y GC.\")]),_c('p',[_vm._v(\"El origen de Ractor se remonta a 2016 cuando Koichi Sasada (diseñador de la máquina virtual Ruby y recolección de basura) presentó su propuesta sobre un nuevo modelo de concurrencia para Ruby. Antes de dicha propuesta, solo podíamos aprovechar múltiples procesadores mediante subprocesos hijos.\")]),_c('p',[_vm._v(\"En 2016, Koichi habló sobre los problemas de la programación de subprocesos múltiples en su presentación en Ruby Kaigi\"),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn7\",\"id\":\"fnref7\"}},[_vm._v(\"[7]\")])]),_vm._v(\", así como sobre algunas formas comunes de resolverlos. Junto con eso, también presentó su concepto de \"),_c('code',{pre:true},[_vm._v(\"Guilds\")]),_vm._v(\" por primera vez. Antes de pasar a Ractors, tomemos un momento para comprender los aspectos básicos de Ractors: \"),_c('code',{pre:true},[_vm._v(\"Guilds\")]),_vm._v(\".\")]),_c('h4',{attrs:{\"id\":\"que-es-un-guild\"}},[_vm._v(\"Que es un Guild? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#que-es-un-guild\"}},[_vm._v(\"¶\")])]),_c('div',{staticClass:\"warning\"},[_c('p',[_vm._v(\"Las imágenes a continuación fueron tomadas de la presentación de Koichi Sasada\"),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn7\",\"id\":\"fnref7:1\"}},[_vm._v(\"[7:1]\")])])])]),_c('p',[_vm._v(\"Un Guild, fue propuesto, como una una nueva abstracción de concurrencia para Ruby. Donde cada uno de estos \"),_c('code',{pre:true},[_vm._v(\"Guilds\")]),_vm._v(\", tendría uno o más hilos, y cada uno de estos, a su vez, albergaría una o más \\\"fibers\\\"/corutinas.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/guilds/guilds_0.png\")}}),_c('p',[_vm._v(\"Los hijos de dos \"),_c('code',{pre:true},[_vm._v(\"Guilds\")]),_vm._v(\", podrían ejecutarse en paralelo, pero los hijos que estan enmarcados dentro de un mismo \"),_c('code',{pre:true},[_vm._v(\"Guild\")]),_vm._v(\" no. Esto se garantizaría a través de un nuevo lock llamado \"),_c('abbr',{attrs:{\"title\":\"Giant Guild Lock, no Good Game Lock\"}},[_vm._v(\"GGL\")]),_vm._v(\", que solo permite ejecutar en primer plano a un hilo a la vez.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/guilds/guilds_1.png\")}}),_c('p',[_vm._v(\"Además, todos los Guilds tendrían su propio conjunto de objetos mutables, y un \"),_c('code',{pre:true},[_vm._v(\"Guild\")]),_vm._v(\" no podría modificar los objetos de otro \"),_c('code',{pre:true},[_vm._v(\"Guild\")]),_vm._v(\". Esto se propuso para evitar problemas de inconsistencia de datos debido al acceso concurrente.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/guilds/guilds_2.png\")}}),_c('p',[_vm._v(\"Sin embargo, los \"),_c('code',{pre:true},[_vm._v(\"Guilds\")]),_vm._v(\" aún podrían usar la interfaz \"),_c('code',{pre:true},[_vm._v(\"Guild::Channel\")]),_vm._v(\" para facilitar la copia o el movimiento de objetos entre ellos. El método \"),_c('code',{pre:true},[_vm._v(\"transfer(object)\")]),_vm._v(\" se propuso para permitir enviar una copia profunda del objeto al \"),_c('code',{pre:true},[_vm._v(\"Guild\")]),_vm._v(\" objetivo, y \"),_c('code',{pre:true},[_vm._v(\"transfer_membership(object)\")]),_vm._v(\" se propuso para permitir mover un objeto de un \"),_c('code',{pre:true},[_vm._v(\"Guild\")]),_vm._v(\" a otro por completo.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/guilds/guilds_3.png\")}}),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/guilds/guilds_4.png\")}}),_c('p',[_vm._v(\"Pero todo esto fue solo para objetos mutables, ya que los objetos inmutables no representan un riesgo de inconsistencia de datos. Esto es así porque una vez que se asigna un valor a los objetos inmutables, este no cambia durante la ejecución del programa, por lo que cualquier \"),_c('code',{pre:true},[_vm._v(\"Guild\")]),_vm._v(\" que intente acceder a los datos de un objeto inmutable siempre recibirá el mismo valor consistente. Los objetos inmutables se podrían compartir en todos los \"),_c('code',{pre:true},[_vm._v(\"Guilds\")]),_vm._v(\" para operaciones de lectura.\")]),_c('p',[_vm._v(\"Los objetos inmutables en Ruby consisten en:\")]),_c('ul',[_c('li',[_vm._v(\"Integers, \"),_c('code',{pre:true},[_vm._v(\"true\")]),_vm._v(\", \"),_c('code',{pre:true},[_vm._v(\"false\")]),_vm._v(\", \"),_c('code',{pre:true},[_vm._v(\"nil\")]),_vm._v(\" (a.k.a. \"),_c('a',{attrs:{\"href\":\"https://github.com/ruby/ruby/blob/d92f09a5eea009fa28cd046e9d0eb698e3d94c5c/include/ruby/internal/special_consts.h#L179\"}},[_vm._v(\"SPECIAL_CONST_P()\")]),_vm._v(\")\")]),_c('li',[_vm._v(\"Todos los símbolos\")]),_c('li',[_vm._v(\"Strings u objetos 'frizados'. Ej: \"),_c('code',{pre:true},[_vm._v(\"s = \\\"str\\\".freeze\")]),_vm._v(\", donde \"),_c('code',{pre:true},[_vm._v(\"s\")]),_vm._v(\" es inmutable.\")]),_c('li',[_vm._v(\"Objetos numericos: Float, Complex, Rational, big integers (\"),_c('a',{attrs:{\"href\":\"https://github.com/ruby/ruby/blob/62bc4a9420fa5786d49391a713bd38b09b8db0ff/include/ruby/internal/value_type.h#L123\"}},[_vm._v(\"T_BIGNUM in internal\")]),_vm._v(\")\")]),_c('li',[_vm._v(\"objetos como clases o modulos (T_CLASS, T_MODULE and T_ICLASS en internal).\")]),_c('li',[_vm._v(\"Ractor y otros objetos especiales usados para sincronización\")])]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/guilds/guilds_5.png\")}}),_c('h5',{attrs:{\"id\":\"uso-propuesto-de-los-guilds\"}},[_vm._v(\"Uso propuesto de los Guilds \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#uso-propuesto-de-los-guilds\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Koichi habla en su presentación del uso de este nuevo tipo de abstracción\"),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn7\",\"id\":\"fnref7:2\"}},[_vm._v(\"[7:2]\")])]),_vm._v(\", y que separa en distintos casos de uso\")]),_c('ul',[_c('li',[_vm._v(\"Caso de Uso 1: Maestro - Worker\")])]),_c('p',[_vm._v(\"La idea de este caso de uso es que exista un \"),_c('code',{pre:true},[_vm._v(\"Guild\")]),_vm._v(\" maestro, que inicialice la ejecución, y después existan, uno o más \"),_c('code',{pre:true},[_vm._v(\"Guilds\")]),_vm._v(\" que realizaran el procesamiento (workers). Este modelo se basa en delegación de tareas repetitivas o conocidas por los \"),_c('code',{pre:true},[_vm._v(\"Guilds\")]),_vm._v(\" workers, y el maestro, solo se encargará de enviar por medio de un channel, el dato de entrada para ser procesado por un worker y tratar de esperar por una respuesta a continuación. El código de ejemplo fue el cálculo de fibonacci, que se muestra a continuación:\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"fib\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(n)\")])]),_vm._v(\" ... \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\\ng_fib = Guild.new(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\"script:\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"%q{\\n ch = Guild.default_channel\\n while n, return_ch = ch.receive\\n return_ch.transfer fib(n)\\n end\\n}\")]),_vm._v(\")\\n\\nch = Guild::Channel.new\\n\\ng_fib.transfer([\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"3\")]),_vm._v(\", ch])\\n\\nputs ch.receive\\n\")])]),_c('p',[_vm._v(\"En el ejemplo, solo se realiza el calculo de un solo valor, aunque puede llamarse múltiples veces a \"),_c('code',{pre:true},[_vm._v(\"g_fib\")]),_vm._v(\", para que se creen nuevos \"),_c('code',{pre:true},[_vm._v(\"guilds\")]),_vm._v(\", y puedan procesar en paralelo.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/guilds/guilds_6.png\")}}),_c('ul',[_c('li',[_vm._v(\"Caso de Uso 2: Pipeline\")])]),_c('p',[_vm._v(\"El segundo caso es el de un pipeline, en donde una serie de procesos, se separan en varios pasos, y en cada uno de estos segmentos, se trata en un \"),_c('code',{pre:true},[_vm._v(\"Guild\")]),_vm._v(\" distinto. Una vez que termina el procesamiento de uno, el dato resultante se transfiere al siguiente \"),_c('code',{pre:true},[_vm._v(\"Guild\")]),_vm._v(\".\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\"result_ch = Guild::Channel.new\\n\\ng_pipe3 = Guild.new(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\"script:\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"%q{\\n while obj = Guild.default_channel.receive\\n obj = modify_obj3(obj)\\n Guild.argv[0].transfer_membership(obj)\\n end\\n}\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\"argv:\")]),_vm._v(\" [result_ch])\\n\\ng_pipe2 = Guild.new(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\"script:\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"%q{\\n while obj = Guild.default_channel.receive\\n obj = modify_obj2(obj)\\n Guild.argv[0].transfer_membership(obj)\\n end\\n}\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\"argv:\")]),_vm._v(\" [g_pipe3])\\n\\ng_pipe1 = Guild.new(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\"script:\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"%q{\\n while obj = Guild.default_channel.receive\\n obj = modify_obj1(obj)\\n Guild.argv[0].transfer_membership(obj)\\n end\\n}\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\"argv:\")]),_vm._v(\" [g_pipe2])\\n\\nobj = SomeClass.new\\n\\ng_pipe1.transfer_membership(obj)\\n\\nobj = result_ch.receive\\n\")])]),_c('p',[_vm._v(\"Aqui se muestra como la arquitectura se veria conceptualmente:\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/guilds/guilds_7.png\")}}),_c('ul',[_c('li',[_vm._v(\"Caso de Uso 3: Datos sensibles. Ej cuentas bancarias\")])]),_c('p',[_vm._v(\"Este es un caso de uso tradicional, donde tenemos datos que pueden mutar y que son sensibles. En este caso, es de alguna manera similar al caso 1, donde hay un \"),_c('code',{pre:true},[_vm._v(\"Guild\")]),_vm._v(\" \\\"maestro\\\", que es el que posee los datos sensibles, y el estado que puede mutar. De esta manera permite aislar el estado y que solo el cambio del estado se genere con condiciones que sean controlables en un solo lugar. También permite que se puedan implementar sobre el Guild \\\"maestro\\\", mecanismos de seguridad y de transaccionalidad, donde se puede loggear todos los movimientos y en caso de que se tenga que volver para atrás se puede hacer, solo en un solo lugar.\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_vm._v(\"g_bank = Guild.new(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\"script:\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"%q{\\n while account_from, account_to, amount,\\n ch = Guild.default_channel.receive\\n if (Bank[account_from].balance < amount)\\n ch.transfer :NOPE\\n else\\n Bank[account_to].balance += amount\\n Bank[account_from].balance -= amount\\n ch.transfer :YEP\\n end\\n end\\n}\")]),_vm._v(\")\\n…\\n\")])]),_c('p',[_vm._v(\"Si se observa el diagrama conceptual para esta arquitectura, se dará cuenta de que es lo mismo que el concepto que el \"),_c('code',{pre:true},[_vm._v(\"caso 1\")]),_vm._v(\", pero el único cambio clave es que los datos, recursos, etc., pertenecen únicamente al \"),_c('code',{pre:true},[_vm._v(\"guild\")]),_vm._v(\" maestro.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/guilds/guilds_8.png\")}}),_c('h4',{attrs:{\"id\":\"ractors-la-implementación-de-guilds\"}},[_vm._v(\"Ractors, la implementación de Guilds \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#ractors-la-implementación-de-guilds\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Ractors, fue lanzado como experimental en \"),_c('a',{attrs:{\"href\":\"https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/\"}},[_vm._v(\"Ruby 3.0.0\")]),_vm._v(\", y es la implementación, por el momento mas estable de la idea conceptual de Guilds.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/guilds/homer-grill.gif\")}}),_c('p',[_vm._v(\"La idea por atrás es la misma, un \"),_c('code',{pre:true},[_vm._v(\"ractor\")]),_vm._v(\" tiene uno o más hilos, y cada uno de estos, a su vez, alberga una o más \\\"fibers\\\"/corutinas. y dos \"),_c('code',{pre:true},[_vm._v(\"ractors\")]),_vm._v(\", pueden ejecutarse potencialmente en paralelo, siempre y cuando el procesamiento que haya que realizar en estos sea bastante intensivo.\")]),_c('p',[_vm._v(\"La idea de aislamiento de variables o datos mutables es la misma que la planteada en los \"),_c('code',{pre:true},[_vm._v(\"Guilds\")]),_vm._v(\". Un \"),_c('code',{pre:true},[_vm._v(\"ractor\")]),_vm._v(\" no puede acceder a los datos de otro, a menos que se transfiera o copie el mismo, pero esto solo aplica a los datos mutables. Con respecto a las variables/datos inmutables, estos se pueden acceder sin problemas, entre los \"),_c('code',{pre:true},[_vm._v(\"ractors\")]),_vm._v(\" que existan en el sistema.\")]),_c('p',[_vm._v(\"La mayor diferencia viene, en cuanto a la comunicación entre los \"),_c('code',{pre:true},[_vm._v(\"ractors\")]),_vm._v(\". Estos a diferencia de los \"),_c('code',{pre:true},[_vm._v(\"Guilds\")]),_vm._v(\", se comunican por medio de simples pasos de mensajes, en vez de \"),_c('code',{pre:true},[_vm._v(\"channels\")]),_vm._v(\". La idea final es que dicho modelo sea similar al de actores. Pero lo es realmente? Esto lo veremos después. Veamos las 'ventajas'.\")]),_c('h5',{attrs:{\"id\":\"ventajas\"}},[_vm._v(\"Ventajas?? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#ventajas\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Con respecto a las ventajas, las mismas son obvias en cuanto a lo que apuntan a resolver. Permitir la ejecución, en múltiples procesadores/cores, permite de alguna manera una mejor performance, reduciendo el tiempo promedio de ejecución de tareas que lo son, y que no generan ningún tipo de relación directa. Veamos el ejemplo mostrado en el realease de Ruby 3.0.0, donde se ejecuta el algoritmo \"),_c('code',{pre:true},[_vm._v(\"tak\")]),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn8\",\"id\":\"fnref8\"}},[_vm._v(\"[8]\")])]),_vm._v(\" \"),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn9\",\"id\":\"fnref9\"}},[_vm._v(\"[9]\")])]),_vm._v(\" secuencialmente y usando \"),_c('code',{pre:true},[_vm._v(\"ractors\")]),_vm._v(\" 4 veces.\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-ruby\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-function\"}},[_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"def\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-title\"}},[_vm._v(\"tarai\")]),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"(x, y, z)\")])]),_vm._v(\" =\\n x <= y ? y : tarai(tarai(x-\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\", y, z),\\n tarai(y-\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\", z, x),\\n tarai(z-\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"1\")]),_vm._v(\", x, y))\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"require\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'benchmark'\")]),_vm._v(\"\\nBenchmark.bm \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"do\")]),_vm._v(\" \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-params\"}},[_vm._v(\"|x|\")]),_vm._v(\"\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"# sequential version\")]),_vm._v(\"\\n x.report(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'seq'\")]),_vm._v(\"){ \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"4\")]),_vm._v(\".times{ tarai(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"14\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"7\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\") } }\\n\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-comment\"}},[_vm._v(\"# parallel version\")]),_vm._v(\"\\n x.report(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-string\"}},[_vm._v(\"'par'\")]),_vm._v(\"){\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"4\")]),_vm._v(\".times.map \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"do\")]),_vm._v(\"\\n Ractor.new { tarai(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"14\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"7\")]),_vm._v(\", \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-number\"}},[_vm._v(\"0\")]),_vm._v(\") }\\n \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\".each(&\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-symbol\"}},[_vm._v(\":take\")]),_vm._v(\")\\n }\\n\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\"\\n\")])]),_c('p',[_vm._v(\"Los resultados muestran las ventajas..\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\"}},[_vm._v(\"Benchmark result:\\n user system total real\\nseq 64.560736 0.001101 64.561837 ( 64.562194)\\npar 66.422010 0.015999 66.438009 ( 16.685797)\\n\")])]),_c('p',[_vm._v(\"El codigo esta disponible también \"),_c('a',{attrs:{\"href\":\"https://github.com/bossiernesto/tarai\"}},[_vm._v(\"aqui\")])]),_c('p',[_vm._v(\"Esta ventaja es facil de ver, aunque lo mas interesante en realidad, es la creación de una abstracción que permita que pueda convivir de alguna manera código que soporte \"),_c('abbr',{attrs:{\"title\":\"Symmetric Multi-Processor\"}},[_vm._v(\"SMP\")]),_vm._v(\" y parte que no, sin tener que recurrir a eliminar definitivamente el \"),_c('abbr',{attrs:{\"title\":\"Global VM Lock\"}},[_vm._v(\"GVL\")]),_vm._v(\".\")]),_c('h5',{attrs:{\"id\":\"problemas-latentes\"}},[_vm._v(\"Problemas latentes \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#problemas-latentes\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Si bien se habla que en los Ractors son thread-safe dentro de su contexto, gracias (o no..) al \"),_c('abbr',{attrs:{\"title\":\"Giant Guild Lock, no Good Game Lock\"}},[_vm._v(\"GGL\")]),_vm._v(\"; en realidad no son completamente \"),_c('code',{pre:true},[_vm._v(\"thread-safe\")]),_vm._v(\", ya que la interfaz que poseen todavía puede generar casos de deadlock o livelock incluso, si es que no se tiene cuidado.\")]),_c('p',[_vm._v(\"Esta estructura, tiene que ser siempre usada de una manera correcta (tanto como el resto), ya que un uso poco cuidadoso, usando módulos/clases entre varios Ractors\"),_c('sup',{staticClass:\"footnote-ref\"},[_c('a',{attrs:{\"href\":\"#fn10\",\"id\":\"fnref10\"}},[_vm._v(\"[10]\")])]),_vm._v(\", puede introducir race conditions. También otra cosa a tener en cuenta, es que el envio de mensajes entre ractors(send, yield, take, etc), es el mismo que hay entre objetos, por lo que es siempre bloqueante. Si estos se usan incorrectamente pueden resultar en \"),_c('code',{pre:true},[_vm._v(\"dead-locks\")]),_vm._v(\" o \"),_c('code',{pre:true},[_vm._v(\"live-locks\")]),_vm._v(\" como se menciono antes.\")]),_c('p',[_vm._v(\"Por el momento, esta implementacion es experimental, por lo que pueden existir incluso bugs, tanto en el ciclo de vida, como en el manejo interno de estos en memoria (por ej. a nivel del GC de MRI aka gc.c).\")]),_c('h4',{attrs:{\"id\":\"uso-actual-de-ractors\"}},[_vm._v(\"Uso actual de Ractors \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#uso-actual-de-ractors\"}},[_vm._v(\"¶\")])]),_c('div',{staticClass:\"warning\"},[_c('p',[_vm._v(\"Esta sección puede cambiar a lo largo del tiempo, ya que el código actual de Ractors es experimental y puede deprecarse rápidamente. Puede verse mas en la doc oficial de \"),_c('a',{attrs:{\"href\":\"https://docs.ruby-lang.org/en/3.0.0/doc/ractor_md.html\"}},[_vm._v(\"ractors.md\")])])]),_c('ul',[_c('li',[_c('p',[_c('code',{pre:true},[_vm._v(\"Ractor.new{expr}\")]),_vm._v(\" crea un nuevo Ractor y \"),_c('code',{pre:true},[_vm._v(\"expr\")]),_vm._v(\" se ejecuta en paralelo en otro procesador.\")])]),_c('li',[_c('p',[_vm._v(\"El intérprete invoca con el primer Ractor (llamado Ractor principal).\")])]),_c('li',[_c('p',[_vm._v(\"Si el Ractor principal finaliza, todos los Ractores reciben una solicitud de finalización como hilos (si el hilo principal (el primer hilo invocado), el intérprete de Ruby envía todos los hilos en ejecución para finalizar la ejecución).\")])]),_c('li',[_c('p',[_vm._v(\"Cada Ractor tiene 1 o más hilos.\")])]),_c('li',[_c('p',[_vm._v(\"Los subprocesos en un Ractor comparten un bloqueo global en todo el Ractor, similar al \"),_c('abbr',{attrs:{\"title\":\"Global Interpreter Lock\"}},[_vm._v(\"GIL\")]),_vm._v(\" (\"),_c('abbr',{attrs:{\"title\":\"Global VM Lock\"}},[_vm._v(\"GVL\")]),_vm._v(\" en terminología de MRI), por lo que no pueden ejecutarse en paralelo (sin liberar \"),_c('abbr',{attrs:{\"title\":\"Global VM Lock\"}},[_vm._v(\"GVL\")]),_vm._v(\" explícitamente en el nivel C). Los hilos en diferentes ractores se ejecutan en paralelo.\")])]),_c('li',[_c('p',[_vm._v(\"La sobrecarga de crear un Ractor es similar a la sobrecarga de la creación de un hilo usuario y el hilo de OS asociado.\")])])]),_c('h5',{attrs:{\"id\":\"paso-de-mensajes\"}},[_vm._v(\"Paso de mensajes \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#paso-de-mensajes\"}},[_vm._v(\"¶\")])]),_c('ul',[_c('li',[_c('p',[_vm._v(\"Paso de mensaje de tipo push: \"),_c('code',{pre:true},[_vm._v(\"Ractor#send(obj\")]),_vm._v(\") y \"),_c('code',{pre:true},[_vm._v(\"Ractor.receive()\")]),_vm._v(\".\")]),_c('ul',[_c('li',[_vm._v(\"El ractor remitente pasa el obj al ractor r mediante \"),_c('code',{pre:true},[_vm._v(\"r.send(obj)\")]),_vm._v(\" y el ractor receptor recibe el mensaje con Ractor.receive.\")]),_c('li',[_vm._v(\"El remitente conoce el Ractor de destino r y el receptor no conoce al remitente (acepte todos los mensajes de cualquier ractor).\")]),_c('li',[_vm._v(\"El receptor tiene una cola infinita y el remitente pone en cola el mensaje. El remitente no bloquea para poner el mensaje en esta cola.\")]),_c('li',[_vm._v(\"Este tipo de intercambio de mensajes se emplea en muchos otros lenguajes basados ​​en actores.\")])])]),_c('li',[_c('p',[_vm._v(\"Comunicación de tipo pull: \"),_c('code',{pre:true},[_vm._v(\"Ractor.yield(obj)\")]),_vm._v(\" y \"),_c('code',{pre:true},[_vm._v(\"Ractor#take()\")]),_vm._v(\".\")]),_c('ul',[_c('li',[_vm._v(\"El emisor ractor declara ceder el obj por \"),_c('code',{pre:true},[_vm._v(\"Ractor.yield(obj)\")]),_vm._v(\" y el receptor Ractor lo toma con r.take.\")]),_c('li',[_vm._v(\"El remitente no conoce un Ractor de destino y el receptor conoce el Ractor r del remitente.\")]),_c('li',[_vm._v(\"El remitente o el receptor se bloquearán si no hay otro lado.\")])])])]),_c('h5',{attrs:{\"id\":\"ciclo-de-vida\"}},[_vm._v(\"Ciclo de Vida \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#ciclo-de-vida\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Puede verse un resumen del ciclo de vida de un ractor en el siguiente \"),_c('a',{attrs:{\"href\":\"https://github.com/ruby/ruby/blob/83a744dd8c0d6e769258b734b9f6861a22eeb554/ractor.c#L1449\"}},[_vm._v(\"diagrama\")]),_vm._v(\":\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\"}},[_vm._v(\" created\\n | ready to run\\n ====================== inserted to vm->ractor\\n v\\n blocking <---+ all threads are blocking\\n | |\\n v |\\n running -----+\\n | all threads are terminated.\\n ====================== removed from vm->ractor\\n v\\n terminated\\n\\n status is protected by VM lock (global state)\\n\")])]),_c('p',[_vm._v(\"El ciclo de vida empieza con \"),_c('code',{pre:true},[_vm._v(\"Ractor.new\")]),_vm._v(\" donde una vez que se registra el mismo en \"),_c('code',{pre:true},[_vm._v(\"vm->ractor\")]),_vm._v(\", esto sucede una vez que puede tomarse control del \"),_c('abbr',{attrs:{\"title\":\"Global VM Lock\"}},[_vm._v(\"GVL\")]),_vm._v(\", para proceder a la creación e inicialización de memoria del contexto. Una vez que el ractor está creado, siempre tendrá como mínimo un hilo, y en caso de que el mismo pueda ejecutarse, pasara a estado \"),_c('code',{pre:true},[_vm._v(\"running\")]),_vm._v(\". En caso de que se envíe un mensaje o se espere alguna acción se pasará a tener otro hilo planificado en primer plano del ractor, en caso de que todos los hilos se bloqueen, el estado pasa a \"),_c('code',{pre:true},[_vm._v(\"bloqueado\")]),_vm._v(\". Cuando todos los hilos han finalizado, el ractor pasa a \"),_c('code',{pre:true},[_vm._v(\"terminated\")]),_vm._v(\".\")]),_c('p',[_vm._v(\"Todos los cambios de estado implican un cambio del estado del ractor, y el mismo está protegido por el \"),_c('abbr',{attrs:{\"title\":\"Global VM Lock\"}},[_vm._v(\"GVL\")]),_vm._v(\" de la VM.\")]),_c('hr',{staticClass:\"footnotes-sep\"}),_c('section',{staticClass:\"footnotes\"},[_c('ol',{staticClass:\"footnotes-list\"},[_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn1\"}},[_c('p',[_c('a',{attrs:{\"href\":\"https://arquitecturas-concurrentes.github.io/iasc-book/concurrencia_paralelismo\"}},[_vm._v(\"IASC UTN FRBA. (2020) .Concurrencia y Paralelismo\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref1\"}},[_vm._v(\"↩︎\")])])]),_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn2\"}},[_c('p',[_c('a',{attrs:{\"href\":\"https://ruby-doc.org/core-3.0.2/Thread.html\"}},[_vm._v(\"Ruby Doc. Retrieved 30 August 2021. Thread standard library\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref2\"}},[_vm._v(\"↩︎\")])])]),_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn3\"}},[_c('p',[_c('a',{attrs:{\"href\":\"https://wiki.python.org/moin/GlobalInterpreterLock\"}},[_vm._v(\"Python Moin. Retrieved 30 November 2015. GlobalInterpreterLock\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref3\"}},[_vm._v(\"↩︎\")])])]),_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn4\"}},[_c('p',[_c('a',{attrs:{\"href\":\"https://puma.io/puma/file.architecture.html\"}},[_vm._v(\"Puma Doc. Architecture Overview\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref4\"}},[_vm._v(\"↩︎\")])])]),_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn5\"}},[_c('p',[_c('a',{attrs:{\"href\":\"http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=C97A7B66D788B7E4F6D6BF5FDD8EC451?doi=10.1.1.33.3144&rep=rep1&type=pdf\"}},[_vm._v(\"Javier, Francisco & Guttman, Joshua. (1995). Copy on Write.\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref5\"}},[_vm._v(\"↩︎\")])])]),_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn6\"}},[_c('p',[_c('a',{attrs:{\"href\":\"https://brandur.org/ruby-memory\"}},[_vm._v(\"Brandur. (2017). The Limits of Copy-on-write: How Ruby Allocates Memory\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref6\"}},[_vm._v(\"↩︎\")])])]),_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn7\"}},[_c('p',[_c('a',{attrs:{\"href\":\"http://www.atdot.net/~ko1/activities/2016_rubykaigi.pdf\"}},[_vm._v(\"Sasada, Koichi. (2016). A proposal of new concurrency model for Ruby 3 (RubyKaigi2016)\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref7\"}},[_vm._v(\"↩︎\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref7:1\"}},[_vm._v(\"↩︎\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref7:2\"}},[_vm._v(\"↩︎\")])])]),_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn8\"}},[_c('p',[_c('a',{attrs:{\"href\":\"https://www.amazon.com/exec/obidos/ISBN%3D0685479412/ericstreasuretroA/\"}},[_vm._v(\"Vardi, I. The Running Time of TAK. Ch. 9 in Computational Recreations in Mathematica. Redwood City, CA: Addison-Wesley, pp. 179-199, 1991.\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref8\"}},[_vm._v(\"↩︎\")])])]),_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn9\"}},[_c('p',[_c('a',{attrs:{\"href\":\"https://archive.org/details/AcornUser052-Nov86/page/n198/mode/1up\"}},[_vm._v(\"Testing the Tak. Acorn User. pp. 197, 199.\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref9\"}},[_vm._v(\"↩︎\")])])]),_c('li',{staticClass:\"footnote-item\",attrs:{\"id\":\"fn10\"}},[_c('p',[_c('a',{attrs:{\"href\":\"https://docs.ruby-lang.org/en/3.0.0/doc/ractor_md.html#label-Thread-safety\"}},[_vm._v(\"Ruby Lang. (2021). Ractor documentation. Thread-safety.\")]),_vm._v(\" \"),_c('a',{staticClass:\"footnote-backref\",attrs:{\"href\":\"#fnref10\"}},[_vm._v(\"↩︎\")])])])])])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./guild.md?vue&type=template&id=b474fff4&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","module.exports = __webpack_public_path__ + \"img/guilds_5.d4b578a0.png\";"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-930b4194.30093d6b.js b/js/chunk-930b4194.30093d6b.js new file mode 100644 index 0000000..1baa192 --- /dev/null +++ b/js/chunk-930b4194.30093d6b.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-930b4194"],{"34f5":function(a,t,e){"use strict";e.r(t);var n=function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("div",[e("Navbar"),e("MainImage"),e("div",{staticClass:"container"},[e("div",{staticClass:"inner-content col-sm-8 col-md-10"},[e("router-view")],1)])],1)},s=[],i=function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("div",{staticClass:"wrap-banner"},[a._m(0),e("vue-particles",{staticClass:"particle-js",attrs:{color:"#dedede",particleOpacity:.7,particlesNumber:80,shapeType:"circle",particleSize:4,linesColor:"#dedede",linesWidth:1,lineLinked:!0,lineOpacity:.4,linesDistance:150,moveSpeed:3,hoverEffect:!0,hoverMode:"grab",clickEffect:!0,clickMode:"push"}})],1)},l=[function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("div",{staticClass:"main-title titulo-heading"},[e("h2",[a._v(" IASC BOOK ")]),e("p",{staticClass:"subtitle"},[a._v(" Pagina con el material de la materia de IASC ")])])}],r=(e("ea27"),e("2877")),c={},o=Object(r["a"])(c,i,l,!1,null,"7af6ec48",null),u=o.exports,v=e("d178"),d={name:"AppLayoutHome",components:{MainImage:u,Navbar:v["a"]}},p=d,b=Object(r["a"])(p,n,s,!1,null,"af2a1948",null);t["default"]=b.exports},"5dfc":function(a,t,e){"use strict";e("cba0")},cba0:function(a,t,e){},d178:function(a,t,e){"use strict";var n=function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("nav",{staticClass:"navbar navbar-expand-lg navbar-light"},[a._m(0),e("div",{staticClass:"collapse navbar-collapse",attrs:{id:"navbarNav"}},[e("ul",{staticClass:"navbar-nav ml-auto"},[e("li",{staticClass:"nav-item active"},[e("router-link",{staticClass:"nav-link",attrs:{to:"/"}},[a._v("Home "),e("span",{staticClass:"sr-only"},[a._v("(current)")])])],1),a._m(1)])])])},s=[function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("button",{staticClass:"navbar-toggler",attrs:{type:"button","data-toggle":"collapse","data-target":"#navbarNav","aria-controls":"navbarNav","aria-expanded":"false","aria-label":"Toggle navigation"}},[e("span",{staticClass:"navbar-toggler-icon"})])},function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("li",{staticClass:"nav-item"},[e("a",{staticClass:"nav-link navbar-button",attrs:{href:"http://arquitecturas-concurrentes.github.io/"}},[a._v("IASC")])])}],i=(e("5dfc"),e("2877")),l={},r=Object(i["a"])(l,n,s,!1,null,null,null);t["a"]=r.exports},ea27:function(a,t,e){"use strict";e("eab8")},eab8:function(a,t,e){}}]); +//# sourceMappingURL=chunk-930b4194.30093d6b.js.map \ No newline at end of file diff --git a/js/chunk-930b4194.30093d6b.js.map b/js/chunk-930b4194.30093d6b.js.map new file mode 100644 index 0000000..2c22d8b --- /dev/null +++ b/js/chunk-930b4194.30093d6b.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/layouts/AppLayoutHome.vue?bc27","webpack:///./src/components/MainImage.vue?4f3b","webpack:///./src/components/MainImage.vue","webpack:///src/layouts/AppLayoutHome.vue","webpack:///./src/layouts/AppLayoutHome.vue?352e","webpack:///./src/layouts/AppLayoutHome.vue","webpack:///./src/components/Navbar.vue?1166","webpack:///./src/components/Navbar.vue?a63b","webpack:///./src/components/Navbar.vue","webpack:///./src/components/MainImage.vue?8561"],"names":["render","_vm","this","_h","$createElement","_c","_self","staticClass","staticRenderFns","_m","attrs","_v","script","component","name","components","MainImage","Navbar"],"mappings":"yHAAA,IAAIA,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACA,EAAG,UAAUA,EAAG,aAAaA,EAAG,MAAM,CAACE,YAAY,aAAa,CAACF,EAAG,MAAM,CAACE,YAAY,oCAAoC,CAACF,EAAG,gBAAgB,MAAM,IAC3PG,EAAkB,GCDlB,EAAS,WAAa,IAAIP,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACE,YAAY,eAAe,CAACN,EAAIQ,GAAG,GAAGJ,EAAG,gBAAgB,CAACE,YAAY,cAAcG,MAAM,CAAC,MAAQ,UAAU,gBAAkB,GAAI,gBAAkB,GAAG,UAAY,SAAS,aAAe,EAAE,WAAa,UAAU,WAAa,EAAE,YAAa,EAAK,YAAc,GAAI,cAAgB,IAAI,UAAY,EAAE,aAAc,EAAK,UAAY,OAAO,aAAc,EAAK,UAAY,WAAW,IAChe,EAAkB,CAAC,WAAa,IAAIT,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACE,YAAY,6BAA6B,CAACF,EAAG,KAAK,CAACJ,EAAIU,GAAG,iBAAiBN,EAAG,IAAI,CAACE,YAAY,YAAY,CAACN,EAAIU,GAAG,wD,wBCAnOC,EAAS,GAMTC,EAAY,eACdD,EACA,EACA,GACA,EACA,KACA,WACA,MAIa,EAAAC,E,oBCFf,GACEC,KAAM,gBACNC,WAAY,CACVC,UAAJ,EACIC,OAAJ,SCpBuV,ICOnV,EAAY,eACd,EACAjB,EACAQ,GACA,EACA,KACA,WACA,MAIa,e,6CClBf,W,yDCAA,IAAIR,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACE,YAAY,wCAAwC,CAACN,EAAIQ,GAAG,GAAGJ,EAAG,MAAM,CAACE,YAAY,2BAA2BG,MAAM,CAAC,GAAK,cAAc,CAACL,EAAG,KAAK,CAACE,YAAY,sBAAsB,CAACF,EAAG,KAAK,CAACE,YAAY,mBAAmB,CAACF,EAAG,cAAc,CAACE,YAAY,WAAWG,MAAM,CAAC,GAAK,MAAM,CAACT,EAAIU,GAAG,SAASN,EAAG,OAAO,CAACE,YAAY,WAAW,CAACN,EAAIU,GAAG,kBAAkB,GAAGV,EAAIQ,GAAG,UACxdD,EAAkB,CAAC,WAAa,IAAIP,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,SAAS,CAACE,YAAY,iBAAiBG,MAAM,CAAC,KAAO,SAAS,cAAc,WAAW,cAAc,aAAa,gBAAgB,YAAY,gBAAgB,QAAQ,aAAa,sBAAsB,CAACL,EAAG,OAAO,CAACE,YAAY,2BAA2B,WAAa,IAAIN,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,KAAK,CAACE,YAAY,YAAY,CAACF,EAAG,IAAI,CAACE,YAAY,yBAAyBG,MAAM,CAAC,KAAO,iDAAiD,CAACT,EAAIU,GAAG,c,wBCA9kBC,EAAS,GAMTC,EAAY,eACdD,EACAZ,EACAQ,GACA,EACA,KACA,KACA,MAIa,OAAAK,E,2CClBf,W","file":"js/chunk-930b4194.30093d6b.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('Navbar'),_c('MainImage'),_c('div',{staticClass:\"container\"},[_c('div',{staticClass:\"inner-content col-sm-8 col-md-10\"},[_c('router-view')],1)])],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"wrap-banner\"},[_vm._m(0),_c('vue-particles',{staticClass:\"particle-js\",attrs:{\"color\":\"#dedede\",\"particleOpacity\":0.7,\"particlesNumber\":80,\"shapeType\":\"circle\",\"particleSize\":4,\"linesColor\":\"#dedede\",\"linesWidth\":1,\"lineLinked\":true,\"lineOpacity\":0.4,\"linesDistance\":150,\"moveSpeed\":3,\"hoverEffect\":true,\"hoverMode\":\"grab\",\"clickEffect\":true,\"clickMode\":\"push\"}})],1)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"main-title titulo-heading\"},[_c('h2',[_vm._v(\" IASC BOOK \")]),_c('p',{staticClass:\"subtitle\"},[_vm._v(\" Pagina con el material de la materia de IASC \")])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./MainImage.vue?vue&type=template&id=7af6ec48&scoped=true&\"\nvar script = {}\nimport style0 from \"./MainImage.vue?vue&type=style&index=0&id=7af6ec48&scoped=true&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"7af6ec48\",\n null\n \n)\n\nexport default component.exports","\n\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AppLayoutHome.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AppLayoutHome.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./AppLayoutHome.vue?vue&type=template&id=af2a1948&scoped=true&\"\nimport script from \"./AppLayoutHome.vue?vue&type=script&lang=js&\"\nexport * from \"./AppLayoutHome.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"af2a1948\",\n null\n \n)\n\nexport default component.exports","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Navbar.vue?vue&type=style&index=0&lang=css&\"","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('nav',{staticClass:\"navbar navbar-expand-lg navbar-light\"},[_vm._m(0),_c('div',{staticClass:\"collapse navbar-collapse\",attrs:{\"id\":\"navbarNav\"}},[_c('ul',{staticClass:\"navbar-nav ml-auto\"},[_c('li',{staticClass:\"nav-item active\"},[_c('router-link',{staticClass:\"nav-link\",attrs:{\"to\":\"/\"}},[_vm._v(\"Home \"),_c('span',{staticClass:\"sr-only\"},[_vm._v(\"(current)\")])])],1),_vm._m(1)])])])}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('button',{staticClass:\"navbar-toggler\",attrs:{\"type\":\"button\",\"data-toggle\":\"collapse\",\"data-target\":\"#navbarNav\",\"aria-controls\":\"navbarNav\",\"aria-expanded\":\"false\",\"aria-label\":\"Toggle navigation\"}},[_c('span',{staticClass:\"navbar-toggler-icon\"})])},function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('li',{staticClass:\"nav-item\"},[_c('a',{staticClass:\"nav-link navbar-button\",attrs:{\"href\":\"http://arquitecturas-concurrentes.github.io/\"}},[_vm._v(\"IASC\")])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./Navbar.vue?vue&type=template&id=7f0398a6&\"\nvar script = {}\nimport style0 from \"./Navbar.vue?vue&type=style&index=0&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./MainImage.vue?vue&type=style&index=0&id=7af6ec48&scoped=true&lang=css&\""],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-9b0b6b6c.a81ed39e.js b/js/chunk-9b0b6b6c.a81ed39e.js new file mode 100644 index 0000000..6bf8288 --- /dev/null +++ b/js/chunk-9b0b6b6c.a81ed39e.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-9b0b6b6c"],{"30d9":function(e,a,o){e.exports=o.p+"img/actors.12e50190.png"},"4d14":function(e,a,o){"use strict";o.r(a);var s=function(){var e=this,a=e.$createElement;e._self._c;return e._m(0)},n=[function(){var e=this,a=e.$createElement,s=e._self._c||a;return s("section",[s("h2",{attrs:{id:"introduccion"}},[e._v("Introduccion "),s("a",{staticClass:"header-anchor",attrs:{href:"#introduccion"}},[e._v("¶")])]),s("p",[e._v("El modelo de Actores, como vimos, tiene muchas similitudes al paradigma de objetos aunque con algunas diferencias. El modelo de actores en si se define como uno que puede lidiar con computaciones concurrentes, por lo que hay algunas reglas en cómo deben ser modelados estos componentes, su comportamiento e interacción. El modelo de actores tiene su unidad de computación más primitiva que es un actor, y que es una computación que recibe un mensaje y hace un procesamiento en base a eso, tambien ademas de recibir mensajes, puede enviar mensajes, tiene una identidad, que es mediante un id único en el sistema. Si empezamos a ver que un actor posee identidad, y envío/recepción de mensajes, uno pensaría que es bastante similar a la de un objeto, o no?. Bueno también un actor, cuando recibe un mensaje, hace algo dependiendo del mensaje que recibe ( similar a cuando llamamos a un método determinado a un objeto). Existen diferencias entre actores y objetos, y la más notoria es que en un modelo de objetos, varios objetos se ejecutan en una unidad de procesamiento (proceso o thread) y comparten recursos como memoria, esto no es lo mismo en el paradigma de actores en el que los actores son en realidad un contexto de ejecución y están completamente aislados uno de otros y nunca van a compartir memorias u otros recursos. También se debe aclarar que un actor puede mantener un estado privado y que este no puede ser cambiado directamente por otro actor (encapsulamiento). En el modelo de actores, nuestro sistema tiene que estar diagramado en actores y todo es un actor, y tienen que tener direcciones siempre, y esta dirección es lo que hablábamos antes que era el identificador en el ecosistema.")]),s("p",[e._v("Los Actores además tienen un mailbox (buzón), en donde van a poder recibir los mensajes de otros actores, y por qué es esto? Bueno porque el envío de mensajes entre actores es asincrónico, por lo cual nunca se sabe exactamente cuando un actor recibe un mensaje, y el modelo elige este modelo de envío de mensajes, ya que al ser una unidad de ejecucion tambien, si se hacen llamadas sincrónicas, el proceso se quedara esperando a una respuesta que puede tal vez nunca llegar o demorar mucho más tiempo, quedando este proceso bloqueado mientras tanto y no dejando de que se pueda ejecutar otro actor que tal vez puede procesar algo. Al poder un actor recibir más de un mensaje en poco tiempo, y al procesar estos de a uno, si se recibe otro mensaje, el actor no lo puede recibir y procesar inmediatamente, por lo que estos mensajes que por el momento el actor no puede procesar quedan encolados en el buzón. También estos escenarios suceden al tener múltiples actores que pueden ejecutarse al mismo tiempo, aunque un actor puede procesar un mensaje al mismo tiempo por lo que de nuevo, si un actor recibe al mismo tiempo 3 mensajes, va a ejecutar uno solo a la vez y por lo tanto hay que mantener un estado de que después hay dos mensajes más por ser procesados, esta es la razón de que los actores tengan un buzón. Si queremos que se ejecuten concurrentemente 3 mensajes, deberemos tener 3 actores y que se le envie un mensaje a cada uno.")]),s("img",{staticClass:"center",attrs:{src:o("30d9"),height:"350"}}),s("h2",{attrs:{id:"que-pueden-hacer-los-actores"}},[e._v("Que pueden hacer los actores "),s("a",{staticClass:"header-anchor",attrs:{href:"#que-pueden-hacer-los-actores"}},[e._v("¶")])]),s("ul",[s("li",[e._v("Enviar y procesar mensajes de otros actores")]),s("li",[e._v("Crear mas actores")]),s("li",[e._v("ejecutar otro código después de procesar un mensaje.")])]),s("p",[e._v("Mencionamos que los actores son también una abstracción que tiene un contexto de ejecución propio, quien se encarga entonces de ejecutar a los actores. En la VM de Erlang/Elixir, existe algo llamado Scheduler, que se encarga de la coordinación de los actores y de la ejecución sobre un procesador del actor. "),s("a",{attrs:{href:"http://erlang.org/pipermail/erlang-questions/2001-April/003132.html"}},[e._v("Mas sobre el scheduler de BEAM")])]),s("p",[e._v("Que pasa cuando un actor no tiene ningun mensaje mas para procesar? El mismo muere. El ciclo de vida de un actor es relativamente corto y está pensado para que realice una acción en particular, reciba, envíe mensajes y cree otros actores, pero cuando deja de tener acciones futuras a realizar el mismo muere. Cómo podemos evitar que esto suceda? Bueno si queremos que un actor pueda quedar vivo, esperando a que reciba un mensaje eventualmente, podemos tan solo hacer eso llamándose a sí mismo y haciendo eso. Podemos ver un ejemplo "),s("a",{attrs:{href:"https://github.com/arquitecturas-concurrentes/iasc-actors-intro-elixir/blob/master/elixir/intro_actors/lib/intro_actors.ex"}},[e._v("aquí")])]),s("p",[e._v("Otro tema importante es que un actor no tiene métodos como los objetos, y el comportamiento de esta última está provista por las clases siempre. En Elixir/Erlang, existe algo más o menos similar que son los módulos, que podemos definir funciones que podemos pasarlas al actor para que las ejecute, es importante la siguiente línea del ejemplo anterior")]),s("pre",{pre:!0},[s("code",{pre:!0,attrs:{"v-pre":"",class:"language-elixir"}},[e._v("spawn("),s("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("fn")]),e._v(" -> loop "),s("span",{pre:!0,attrs:{class:"hljs-keyword"}},[e._v("end")]),e._v(")\n")])]),s("p",[e._v("Spawn es la primitiva para crear un actor, y se le puede pasar una función que sea un loop que se llame a sí mismo y de acuerdo al mensaje que reciba realizará una acción. Esta es la manera más simple de que un actor quede vivo después de procesar los mensajes que tiene en el mailbox.")]),s("p",[e._v("Hay otra librería que nos ayuda mucho a no tener que preocuparnos por esto que es OTP, que nos va a ayudar a modelar, mediante módulos que son más bien recurrentes, diferente tipos de actores que harán distintas acciones puntuales que nos van a ayudar bastante a que nos centremos más en el dominio de nuestra aplicación.")]),s("p",[e._v("Que pasa si un actor falla por alguna razón? Bueno el mismo muere y hay que volver a crearlo y si recibió un mensaje en particular hay que enviarselo de nuevo, hay maneras de que podamos evitar esto mediante catcheo de excepciones, aunque puede ser a veces que pueda morir por otras razones, con lo cual a veces es mejor dejar de morir un actor solo… Entonces que hago para poder volver a levantar un actor que se murió sin que tenga que hacerlo uno a mano? Hay un módulo de OTP que veremos en la próxima sección que nos ayuda con este tema y son los supervisores.")]),s("p",[e._v("Más info sobre errores en el ecosistema de Erlang/Elixir "),s("a",{attrs:{href:"https://learnyousomeerlang.com/errors-and-exceptions#not-so-fast"}},[e._v("aqui")])]),s("p",[e._v("Adicional:")]),s("p",[e._v("Leer principalmente la primera parte que describe brevemente el paradigma de actores junto con actores en Erlang y el scheduling en Erlang.")]),s("p",[s("a",{attrs:{href:"https://rocketeer.be/articles/concurrency-in-erlang-scala/"}},[e._v("https://rocketeer.be/articles/concurrency-in-erlang-scala/")])])])}],r=o("2877"),t={},u=Object(r["a"])(t,s,n,!1,null,null,null);a["default"]=u.exports}}]); +//# sourceMappingURL=chunk-9b0b6b6c.a81ed39e.js.map \ No newline at end of file diff --git a/js/chunk-9b0b6b6c.a81ed39e.js.map b/js/chunk-9b0b6b6c.a81ed39e.js.map new file mode 100644 index 0000000..59408e7 --- /dev/null +++ b/js/chunk-9b0b6b6c.a81ed39e.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/images/actors.png","webpack:///./src/content/actores_intro.md?94b1","webpack:///./src/content/actores_intro.md"],"names":["module","exports","render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","pre","script","component"],"mappings":"qGAAAA,EAAOC,QAAU,IAA0B,2B,2CCA3C,IAAIC,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAsBH,EAAII,MAAMC,GAAO,OAAOL,EAAIM,GAAG,IACnGC,EAAkB,CAAC,WAAa,IAAIP,EAAIC,KAASC,EAAGF,EAAIG,eAAmBE,EAAGL,EAAII,MAAMC,IAAIH,EAAG,OAAOG,EAAG,UAAU,CAACA,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,iBAAiB,CAACR,EAAIS,GAAG,iBAAiBJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,kBAAkB,CAACR,EAAIS,GAAG,SAASJ,EAAG,IAAI,CAACL,EAAIS,GAAG,4qDAA4qDJ,EAAG,IAAI,CAACL,EAAIS,GAAG,m6CAAm6CJ,EAAG,MAAM,CAACK,YAAY,SAASF,MAAM,CAAC,IAAM,EAAQ,QAAuB,OAAS,SAASH,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,iCAAiC,CAACR,EAAIS,GAAG,iCAAiCJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,kCAAkC,CAACR,EAAIS,GAAG,SAASJ,EAAG,KAAK,CAACA,EAAG,KAAK,CAACL,EAAIS,GAAG,iDAAiDJ,EAAG,KAAK,CAACL,EAAIS,GAAG,uBAAuBJ,EAAG,KAAK,CAACL,EAAIS,GAAG,4DAA4DJ,EAAG,IAAI,CAACL,EAAIS,GAAG,wTAAwTJ,EAAG,IAAI,CAACG,MAAM,CAAC,KAAO,wEAAwE,CAACR,EAAIS,GAAG,sCAAsCJ,EAAG,IAAI,CAACL,EAAIS,GAAG,yhBAAyhBJ,EAAG,IAAI,CAACG,MAAM,CAAC,KAAO,+HAA+H,CAACR,EAAIS,GAAG,YAAYJ,EAAG,IAAI,CAACL,EAAIS,GAAG,qWAAqWJ,EAAG,MAAM,CAACM,KAAI,GAAM,CAACN,EAAG,OAAO,CAACM,KAAI,EAAKH,MAAM,CAAC,QAAQ,GAAG,MAAQ,oBAAoB,CAACR,EAAIS,GAAG,UAAUJ,EAAG,OAAO,CAACM,KAAI,EAAKH,MAAM,CAAC,MAAQ,iBAAiB,CAACR,EAAIS,GAAG,QAAQT,EAAIS,GAAG,aAAaJ,EAAG,OAAO,CAACM,KAAI,EAAKH,MAAM,CAAC,MAAQ,iBAAiB,CAACR,EAAIS,GAAG,SAAST,EAAIS,GAAG,WAAWJ,EAAG,IAAI,CAACL,EAAIS,GAAG,mSAAmSJ,EAAG,IAAI,CAACL,EAAIS,GAAG,uUAAuUJ,EAAG,IAAI,CAACL,EAAIS,GAAG,0jBAA0jBJ,EAAG,IAAI,CAACL,EAAIS,GAAG,6DAA6DJ,EAAG,IAAI,CAACG,MAAM,CAAC,KAAO,qEAAqE,CAACR,EAAIS,GAAG,YAAYJ,EAAG,IAAI,CAACL,EAAIS,GAAG,gBAAgBJ,EAAG,IAAI,CAACL,EAAIS,GAAG,iJAAiJJ,EAAG,IAAI,CAACA,EAAG,IAAI,CAACG,MAAM,CAAC,KAAO,+DAA+D,CAACR,EAAIS,GAAG,sE,YCAnzOG,EAAS,GAKTC,EAAY,eACdD,EACAb,EACAQ,GACA,EACA,KACA,KACA,MAIa,aAAAM,E","file":"js/chunk-9b0b6b6c.a81ed39e.js","sourcesContent":["module.exports = __webpack_public_path__ + \"img/actors.12e50190.png\";","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h2',{attrs:{\"id\":\"introduccion\"}},[_vm._v(\"Introduccion \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#introduccion\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"El modelo de Actores, como vimos, tiene muchas similitudes al paradigma de objetos aunque con algunas diferencias. El modelo de actores en si se define como uno que puede lidiar con computaciones concurrentes, por lo que hay algunas reglas en cómo deben ser modelados estos componentes, su comportamiento e interacción. El modelo de actores tiene su unidad de computación más primitiva que es un actor, y que es una computación que recibe un mensaje y hace un procesamiento en base a eso, tambien ademas de recibir mensajes, puede enviar mensajes, tiene una identidad, que es mediante un id único en el sistema. Si empezamos a ver que un actor posee identidad, y envío/recepción de mensajes, uno pensaría que es bastante similar a la de un objeto, o no?. Bueno también un actor, cuando recibe un mensaje, hace algo dependiendo del mensaje que recibe ( similar a cuando llamamos a un método determinado a un objeto). Existen diferencias entre actores y objetos, y la más notoria es que en un modelo de objetos, varios objetos se ejecutan en una unidad de procesamiento (proceso o thread) y comparten recursos como memoria, esto no es lo mismo en el paradigma de actores en el que los actores son en realidad un contexto de ejecución y están completamente aislados uno de otros y nunca van a compartir memorias u otros recursos. También se debe aclarar que un actor puede mantener un estado privado y que este no puede ser cambiado directamente por otro actor (encapsulamiento). En el modelo de actores, nuestro sistema tiene que estar diagramado en actores y todo es un actor, y tienen que tener direcciones siempre, y esta dirección es lo que hablábamos antes que era el identificador en el ecosistema.\")]),_c('p',[_vm._v(\"Los Actores además tienen un mailbox (buzón), en donde van a poder recibir los mensajes de otros actores, y por qué es esto? Bueno porque el envío de mensajes entre actores es asincrónico, por lo cual nunca se sabe exactamente cuando un actor recibe un mensaje, y el modelo elige este modelo de envío de mensajes, ya que al ser una unidad de ejecucion tambien, si se hacen llamadas sincrónicas, el proceso se quedara esperando a una respuesta que puede tal vez nunca llegar o demorar mucho más tiempo, quedando este proceso bloqueado mientras tanto y no dejando de que se pueda ejecutar otro actor que tal vez puede procesar algo. Al poder un actor recibir más de un mensaje en poco tiempo, y al procesar estos de a uno, si se recibe otro mensaje, el actor no lo puede recibir y procesar inmediatamente, por lo que estos mensajes que por el momento el actor no puede procesar quedan encolados en el buzón. También estos escenarios suceden al tener múltiples actores que pueden ejecutarse al mismo tiempo, aunque un actor puede procesar un mensaje al mismo tiempo por lo que de nuevo, si un actor recibe al mismo tiempo 3 mensajes, va a ejecutar uno solo a la vez y por lo tanto hay que mantener un estado de que después hay dos mensajes más por ser procesados, esta es la razón de que los actores tengan un buzón. Si queremos que se ejecuten concurrentemente 3 mensajes, deberemos tener 3 actores y que se le envie un mensaje a cada uno.\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/actors.png\"),\"height\":\"350\"}}),_c('h2',{attrs:{\"id\":\"que-pueden-hacer-los-actores\"}},[_vm._v(\"Que pueden hacer los actores \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#que-pueden-hacer-los-actores\"}},[_vm._v(\"¶\")])]),_c('ul',[_c('li',[_vm._v(\"Enviar y procesar mensajes de otros actores\")]),_c('li',[_vm._v(\"Crear mas actores\")]),_c('li',[_vm._v(\"ejecutar otro código después de procesar un mensaje.\")])]),_c('p',[_vm._v(\"Mencionamos que los actores son también una abstracción que tiene un contexto de ejecución propio, quien se encarga entonces de ejecutar a los actores. En la VM de Erlang/Elixir, existe algo llamado Scheduler, que se encarga de la coordinación de los actores y de la ejecución sobre un procesador del actor. \"),_c('a',{attrs:{\"href\":\"http://erlang.org/pipermail/erlang-questions/2001-April/003132.html\"}},[_vm._v(\"Mas sobre el scheduler de BEAM\")])]),_c('p',[_vm._v(\"Que pasa cuando un actor no tiene ningun mensaje mas para procesar? El mismo muere. El ciclo de vida de un actor es relativamente corto y está pensado para que realice una acción en particular, reciba, envíe mensajes y cree otros actores, pero cuando deja de tener acciones futuras a realizar el mismo muere. Cómo podemos evitar que esto suceda? Bueno si queremos que un actor pueda quedar vivo, esperando a que reciba un mensaje eventualmente, podemos tan solo hacer eso llamándose a sí mismo y haciendo eso. Podemos ver un ejemplo \"),_c('a',{attrs:{\"href\":\"https://github.com/arquitecturas-concurrentes/iasc-actors-intro-elixir/blob/master/elixir/intro_actors/lib/intro_actors.ex\"}},[_vm._v(\"aquí\")])]),_c('p',[_vm._v(\"Otro tema importante es que un actor no tiene métodos como los objetos, y el comportamiento de esta última está provista por las clases siempre. En Elixir/Erlang, existe algo más o menos similar que son los módulos, que podemos definir funciones que podemos pasarlas al actor para que las ejecute, es importante la siguiente línea del ejemplo anterior\")]),_c('pre',{pre:true},[_c('code',{pre:true,attrs:{\"v-pre\":\"\",\"class\":\"language-elixir\"}},[_vm._v(\"spawn(\"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"fn\")]),_vm._v(\" -> loop \"),_c('span',{pre:true,attrs:{\"class\":\"hljs-keyword\"}},[_vm._v(\"end\")]),_vm._v(\")\\n\")])]),_c('p',[_vm._v(\"Spawn es la primitiva para crear un actor, y se le puede pasar una función que sea un loop que se llame a sí mismo y de acuerdo al mensaje que reciba realizará una acción. Esta es la manera más simple de que un actor quede vivo después de procesar los mensajes que tiene en el mailbox.\")]),_c('p',[_vm._v(\"Hay otra librería que nos ayuda mucho a no tener que preocuparnos por esto que es OTP, que nos va a ayudar a modelar, mediante módulos que son más bien recurrentes, diferente tipos de actores que harán distintas acciones puntuales que nos van a ayudar bastante a que nos centremos más en el dominio de nuestra aplicación.\")]),_c('p',[_vm._v(\"Que pasa si un actor falla por alguna razón? Bueno el mismo muere y hay que volver a crearlo y si recibió un mensaje en particular hay que enviarselo de nuevo, hay maneras de que podamos evitar esto mediante catcheo de excepciones, aunque puede ser a veces que pueda morir por otras razones, con lo cual a veces es mejor dejar de morir un actor solo… Entonces que hago para poder volver a levantar un actor que se murió sin que tenga que hacerlo uno a mano? Hay un módulo de OTP que veremos en la próxima sección que nos ayuda con este tema y son los supervisores.\")]),_c('p',[_vm._v(\"Más info sobre errores en el ecosistema de Erlang/Elixir \"),_c('a',{attrs:{\"href\":\"https://learnyousomeerlang.com/errors-and-exceptions#not-so-fast\"}},[_vm._v(\"aqui\")])]),_c('p',[_vm._v(\"Adicional:\")]),_c('p',[_vm._v(\"Leer principalmente la primera parte que describe brevemente el paradigma de actores junto con actores en Erlang y el scheduling en Erlang.\")]),_c('p',[_c('a',{attrs:{\"href\":\"https://rocketeer.be/articles/concurrency-in-erlang-scala/\"}},[_vm._v(\"https://rocketeer.be/articles/concurrency-in-erlang-scala/\")])])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./actores_intro.md?vue&type=template&id=2fb25deb&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-b6b65a62.5b6cc0bd.js b/js/chunk-b6b65a62.5b6cc0bd.js new file mode 100644 index 0000000..5e09adc --- /dev/null +++ b/js/chunk-b6b65a62.5b6cc0bd.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-b6b65a62"],{"0068":function(e,t,r){"use strict";function n(e){return Object.prototype.toString.call(e)}function s(e){return"[object String]"===n(e)}var o=Object.prototype.hasOwnProperty;function i(e,t){return o.call(e,t)}function a(e){var t=Array.prototype.slice.call(arguments,1);return t.forEach((function(t){if(t){if("object"!==typeof t)throw new TypeError(t+"must be object");Object.keys(t).forEach((function(r){e[r]=t[r]}))}})),e}function c(e,t,r){return[].concat(e.slice(0,t),r,e.slice(t+1))}function u(e){return!(e>=55296&&e<=57343)&&(!(e>=64976&&e<=65007)&&(65535!==(65535&e)&&65534!==(65535&e)&&(!(e>=0&&e<=8)&&(11!==e&&(!(e>=14&&e<=31)&&(!(e>=127&&e<=159)&&!(e>1114111)))))))}function l(e){if(e>65535){e-=65536;var t=55296+(e>>10),r=56320+(1023&e);return String.fromCharCode(t,r)}return String.fromCharCode(e)}var p=/\\([!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~])/g,h=/&([a-z#][a-z0-9]{1,31});/gi,f=new RegExp(p.source+"|"+h.source,"gi"),d=/^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))/i,m=r("bd68");function g(e,t){var r=0;return i(m,t)?m[t]:35===t.charCodeAt(0)&&d.test(t)&&(r="x"===t[1].toLowerCase()?parseInt(t.slice(2),16):parseInt(t.slice(1),10),u(r))?l(r):e}function b(e){return e.indexOf("\\")<0?e:e.replace(p,"$1")}function _(e){return e.indexOf("\\")<0&&e.indexOf("&")<0?e:e.replace(f,(function(e,t,r){return t||g(e,r)}))}var k=/[&<>"]/,v=/[&<>"]/g,y={"&":"&","<":"<",">":">",'"':"""};function x(e){return y[e]}function C(e){return k.test(e)?e.replace(v,x):e}var w=/[.?*+^$[\]\\(){}|-]/g;function A(e){return e.replace(w,"\\$&")}function D(e){switch(e){case 9:case 32:return!0}return!1}function E(e){if(e>=8192&&e<=8202)return!0;switch(e){case 9:case 10:case 11:case 12:case 13:case 32:case 160:case 5760:case 8239:case 8287:case 12288:return!0}return!1}var q=r("7ca0");function S(e){return q.test(e)}function F(e){switch(e){case 33:case 34:case 35:case 36:case 37:case 38:case 39:case 40:case 41:case 42:case 43:case 44:case 45:case 46:case 47:case 58:case 59:case 60:case 61:case 62:case 63:case 64:case 91:case 92:case 93:case 94:case 95:case 96:case 123:case 124:case 125:case 126:return!0;default:return!1}}function L(e){return e=e.trim().replace(/\s+/g," "),"Ṿ"==="ẞ".toLowerCase()&&(e=e.replace(/ẞ/g,"ß")),e.toLowerCase().toUpperCase()}t.lib={},t.lib.mdurl=r("d8a6"),t.lib.ucmicro=r("d5d1"),t.assign=a,t.isString=s,t.has=i,t.unescapeMd=b,t.unescapeAll=_,t.isValidEntityCode=u,t.fromCodePoint=l,t.escapeHtml=C,t.arrayReplaceAt=c,t.isSpace=D,t.isWhiteSpace=E,t.isMdAsciiPunct=F,t.isPunctChar=S,t.escapeRE=A,t.normalizeReference=L},"0758":function(e,t,r){"use strict";var n=r("0068").isSpace;e.exports=function(e,t,r,s){var o,i,a,c,u=e.bMarks[t]+e.tShift[t],l=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4)return!1;if(o=e.src.charCodeAt(u),35!==o||u>=l)return!1;i=1,o=e.src.charCodeAt(++u);while(35===o&&u6||uu&&n(e.src.charCodeAt(a-1))&&(l=a),e.line=t+1,c=e.push("heading_open","h"+String(i),1),c.markup="########".slice(0,i),c.map=[t,e.line],c=e.push("inline","",0),c.content=e.src.slice(u,l).trim(),c.map=[t,e.line],c.children=[],c=e.push("heading_close","h"+String(i),-1),c.markup="########".slice(0,i)),!0)}},"08ae":function(e,t,r){"use strict";var n=r("0068"),s=r("565b"),o=r("7cc2"),i=r("a915"),a=r("7696"),c=r("4cb4"),u=r("fbcd"),l=r("d8a6"),p=r("1985"),h={default:r("8a31"),zero:r("1caa"),commonmark:r("428d")},f=/^(vbscript|javascript|file|data):/,d=/^data:image\/(gif|png|jpeg|webp);/;function m(e){var t=e.trim().toLowerCase();return!f.test(t)||!!d.test(t)}var g=["http:","https:","mailto:"];function b(e){var t=l.parse(e,!0);if(t.hostname&&(!t.protocol||g.indexOf(t.protocol)>=0))try{t.hostname=p.toASCII(t.hostname)}catch(r){}return l.encode(l.format(t))}function _(e){var t=l.parse(e,!0);if(t.hostname&&(!t.protocol||g.indexOf(t.protocol)>=0))try{t.hostname=p.toUnicode(t.hostname)}catch(r){}return l.decode(l.format(t),l.decode.defaultChars+"%")}function k(e,t){if(!(this instanceof k))return new k(e,t);t||n.isString(e)||(t=e||{},e="default"),this.inline=new c,this.block=new a,this.core=new i,this.renderer=new o,this.linkify=new u,this.validateLink=m,this.normalizeLink=b,this.normalizeLinkText=_,this.utils=n,this.helpers=n.assign({},s),this.options={},this.configure(e),t&&this.set(t)}k.prototype.set=function(e){return n.assign(this.options,e),this},k.prototype.configure=function(e){var t,r=this;if(n.isString(e)&&(t=e,e=h[t],!e))throw new Error('Wrong `markdown-it` preset "'+t+'", check name');if(!e)throw new Error("Wrong `markdown-it` preset, can't be empty");return e.options&&r.set(e.options),e.components&&Object.keys(e.components).forEach((function(t){e.components[t].rules&&r[t].ruler.enableOnly(e.components[t].rules),e.components[t].rules2&&r[t].ruler2.enableOnly(e.components[t].rules2)})),this},k.prototype.enable=function(e,t){var r=[];Array.isArray(e)||(e=[e]),["core","block","inline"].forEach((function(t){r=r.concat(this[t].ruler.enable(e,!0))}),this),r=r.concat(this.inline.ruler2.enable(e,!0));var n=e.filter((function(e){return r.indexOf(e)<0}));if(n.length&&!t)throw new Error("MarkdownIt. Failed to enable unknown rule(s): "+n);return this},k.prototype.disable=function(e,t){var r=[];Array.isArray(e)||(e=[e]),["core","block","inline"].forEach((function(t){r=r.concat(this[t].ruler.disable(e,!0))}),this),r=r.concat(this.inline.ruler2.disable(e,!0));var n=e.filter((function(e){return r.indexOf(e)<0}));if(n.length&&!t)throw new Error("MarkdownIt. Failed to disable unknown rule(s): "+n);return this},k.prototype.use=function(e){var t=[this].concat(Array.prototype.slice.call(arguments,1));return e.apply(e,t),this},k.prototype.parse=function(e,t){if("string"!==typeof e)throw new Error("Input data should be a String");var r=new this.core.State(e,this,t);return this.core.process(r),r.tokens},k.prototype.render=function(e,t){return t=t||{},this.renderer.render(this.parse(e,t),this.options,t)},k.prototype.parseInline=function(e,t){var r=new this.core.State(e,this,t);return r.inlineMode=!0,this.core.process(r),r.tokens},k.prototype.renderInline=function(e,t){return t=t||{},this.renderer.render(this.parseInline(e,t),this.options,t)},e.exports=k},"096b":function(e,t,r){"use strict";function n(e,t,r){this.type=e,this.tag=t,this.attrs=null,this.map=null,this.nesting=r,this.level=0,this.children=null,this.content="",this.markup="",this.info="",this.meta=null,this.block=!1,this.hidden=!1}n.prototype.attrIndex=function(e){var t,r,n;if(!this.attrs)return-1;for(t=this.attrs,r=0,n=t.length;r=0&&(r=this.attrs[t][1]),r},n.prototype.attrJoin=function(e,t){var r=this.attrIndex(e);r<0?this.attrPush([e,t]):this.attrs[r][1]=this.attrs[r][1]+" "+t},e.exports=n},"097b":function(e,t,r){"use strict";var n=r("096b"),s=r("0068").isWhiteSpace,o=r("0068").isPunctChar,i=r("0068").isMdAsciiPunct;function a(e,t,r,n){this.src=e,this.env=r,this.md=t,this.tokens=n,this.tokens_meta=Array(n.length),this.pos=0,this.posMax=this.src.length,this.level=0,this.pending="",this.pendingLevel=0,this.cache={},this.delimiters=[],this._prev_delimiters=[],this.backticks={},this.backticksScanned=!1}a.prototype.pushPending=function(){var e=new n("text","",0);return e.content=this.pending,e.level=this.pendingLevel,this.tokens.push(e),this.pending="",e},a.prototype.push=function(e,t,r){this.pending&&this.pushPending();var s=new n(e,t,r),o=null;return r<0&&(this.level--,this.delimiters=this._prev_delimiters.pop()),s.level=this.level,r>0&&(this.level++,this._prev_delimiters.push(this.delimiters),this.delimiters=[],o={delimiters:this.delimiters}),this.pendingLevel=this.level,this.tokens.push(s),this.tokens_meta.push(o),s},a.prototype.scanDelims=function(e,t){var r,n,a,c,u,l,p,h,f,d=e,m=!0,g=!0,b=this.posMax,_=this.src.charCodeAt(e);r=e>0?this.src.charCodeAt(e-1):32;while(d= 0x80 (not a basic code point)","invalid-input":"Invalid input"},y=u-l,x=Math.floor,C=String.fromCharCode;function w(e){throw new RangeError(v[e])}function A(e,t){var r=e.length,n=[];while(r--)n[r]=t(e[r]);return n}function D(e,t){var r=e.split("@"),n="";r.length>1&&(n=r[0]+"@",e=r[1]),e=e.replace(k,".");var s=e.split("."),o=A(s,t).join(".");return n+o}function E(e){var t,r,n=[],s=0,o=e.length;while(s=55296&&t<=56319&&s65535&&(e-=65536,t+=C(e>>>10&1023|55296),e=56320|1023&e),t+=C(e),t})).join("")}function S(e){return e-48<10?e-22:e-65<26?e-65:e-97<26?e-97:u}function F(e,t){return e+22+75*(e<26)-((0!=t)<<5)}function L(e,t,r){var n=0;for(e=r?x(e/f):e>>1,e+=x(e/t);e>y*p>>1;n+=u)e=x(e/y);return x(n+(y+1)*e/(e+h))}function T(e){var t,r,n,s,o,i,a,h,f,b,_=[],k=e.length,v=0,y=m,C=d;for(r=e.lastIndexOf(g),r<0&&(r=0),n=0;n=128&&w("not-basic"),_.push(e.charCodeAt(n));for(s=r>0?r+1:0;s=k&&w("invalid-input"),h=S(e.charCodeAt(s++)),(h>=u||h>x((c-v)/i))&&w("overflow"),v+=h*i,f=a<=C?l:a>=C+p?p:a-C,hx(c/b)&&w("overflow"),i*=b}t=_.length+1,C=L(v-o,t,0==o),x(v/t)>c-y&&w("overflow"),y+=x(v/t),v%=t,_.splice(v++,0,y)}return q(_)}function z(e){var t,r,n,s,o,i,a,h,f,b,_,k,v,y,A,D=[];for(e=E(e),k=e.length,t=m,r=0,o=d,i=0;i=t&&_x((c-r)/v)&&w("overflow"),r+=(a-t)*v,t=a,i=0;ic&&w("overflow"),_==t){for(h=r,f=u;;f+=u){if(b=f<=o?l:f>=o+p?p:f-o,h=4)return!1;for(h=e.parentType,e.parentType="paragraph";f3)){if(e.sCount[f]>=e.blkIndent&&(c=e.bMarks[f]+e.tShift[f],u=e.eMarks[f],c=u)))){l=61===p?1:2;break}if(!(e.sCount[f]<0)){for(s=!1,o=0,i=d.length;o0&&n++,"text"===s[t].type&&t+1=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*"}}};n.forEach(["delete","get","head"],(function(e){u.headers[e]={}})),n.forEach(["post","put","patch"],(function(e){u.headers[e]=n.merge(i)})),e.exports=u}).call(this,r("4362"))},"28ec":function(e,t,r){"use strict";var n=/^([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$/,s=/^([a-zA-Z][a-zA-Z0-9+.\-]{1,31}):([^<>\x00-\x20]*)$/;e.exports=function(e,t){var r,o,i,a,c,u,l=e.pos;if(60!==e.src.charCodeAt(l))return!1;for(c=e.pos,u=e.posMax;;){if(++l>=u)return!1;if(a=e.src.charCodeAt(l),60===a)return!1;if(62===a)break}return r=e.src.slice(c+1,l),s.test(r)?(o=e.md.normalizeLink(r),!!e.md.validateLink(o)&&(t||(i=e.push("link_open","a",1),i.attrs=[["href",o]],i.markup="autolink",i.info="auto",i=e.push("text","",0),i.content=e.md.normalizeLinkText(r),i=e.push("link_close","a",-1),i.markup="autolink",i.info="auto"),e.pos+=r.length+2,!0)):!!n.test(r)&&(o=e.md.normalizeLink("mailto:"+r),!!e.md.validateLink(o)&&(t||(i=e.push("link_open","a",1),i.attrs=[["href",o]],i.markup="autolink",i.info="auto",i=e.push("text","",0),i.content=e.md.normalizeLinkText(r),i=e.push("link_close","a",-1),i.markup="autolink",i.info="auto"),e.pos+=r.length+2,!0))}},"2d83":function(e,t,r){"use strict";var n=r("387f");e.exports=function(e,t,r,s,o){var i=new Error(e);return n(i,t,r,s,o)}},"2e67":function(e,t,r){"use strict";e.exports=function(e){return!(!e||!e.__CANCEL__)}},"30b5":function(e,t,r){"use strict";var n=r("c532");function s(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}e.exports=function(e,t,r){if(!t)return e;var o;if(r)o=r(t);else if(n.isURLSearchParams(t))o=t.toString();else{var i=[];n.forEach(t,(function(e,t){null!==e&&"undefined"!==typeof e&&(n.isArray(e)?t+="[]":e=[e],n.forEach(e,(function(e){n.isDate(e)?e=e.toISOString():n.isObject(e)&&(e=JSON.stringify(e)),i.push(s(t)+"="+s(e))})))})),o=i.join("&")}if(o){var a=e.indexOf("#");-1!==a&&(e=e.slice(0,a)),e+=(-1===e.indexOf("?")?"?":"&")+o}return e}},3408:function(e,t,r){"use strict";e.exports=function(e){var t;e.inlineMode?(t=new e.Token("inline","",0),t.content=e.src,t.map=[0,1],t.children=[],e.tokens.push(t)):e.md.block.parse(e.src,e.md,e.env,e.tokens)}},"387f":function(e,t,r){"use strict";e.exports=function(e,t,r,n,s){return e.config=t,r&&(e.code=r),e.request=n,e.response=s,e.isAxiosError=!0,e.toJSON=function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:this.config,code:this.code}},e}},3934:function(e,t,r){"use strict";var n=r("c532");e.exports=n.isStandardBrowserEnv()?function(){var e,t=/(msie|trident)/i.test(navigator.userAgent),r=document.createElement("a");function s(e){var n=e;return t&&(r.setAttribute("href",n),n=r.href),r.setAttribute("href",n),{href:r.href,protocol:r.protocol?r.protocol.replace(/:$/,""):"",host:r.host,search:r.search?r.search.replace(/^\?/,""):"",hash:r.hash?r.hash.replace(/^#/,""):"",hostname:r.hostname,port:r.port,pathname:"/"===r.pathname.charAt(0)?r.pathname:"/"+r.pathname}}return e=s(window.location.href),function(t){var r=n.isString(t)?s(t):t;return r.protocol===e.protocol&&r.host===e.host}}():function(){return function(){return!0}}()},4236:function(e,t,r){"use strict";var n=r("0068").isSpace;e.exports=function(e,t){var r,s,o,i=e.pos;if(10!==e.src.charCodeAt(i))return!1;if(r=e.pending.length-1,s=e.posMax,!t)if(r>=0&&32===e.pending.charCodeAt(r))if(r>=1&&32===e.pending.charCodeAt(r-1)){o=r-1;while(o>=1&&32===e.pending.charCodeAt(o-1))o--;e.pending=e.pending.slice(0,o),e.push("hardbreak","br",0)}else e.pending=e.pending.slice(0,-1),e.push("softbreak","br",0);else e.push("softbreak","br",0);i++;while(i3)&&!(e.sCount[c]<0)){for(n=!1,s=0,o=u.length;s=i)return-1;if(r=e.src.charCodeAt(o++),r<48||r>57)return-1;for(;;){if(o>=i)return-1;if(r=e.src.charCodeAt(o++),!(r>=48&&r<=57)){if(41===r||46===r)break;return-1}if(o-s>=10)return-1}return o=4)return!1;if(e.listIndent>=0&&e.sCount[t]-e.listIndent>=4&&e.sCount[t]=e.blkIndent&&(I=!0),(S=o(e,t))>=0){if(f=!0,L=e.bMarks[t]+e.tShift[t],k=Number(e.src.slice(L,S-1)),I&&1!==k)return!1}else{if(!((S=s(e,t))>=0))return!1;f=!1}if(I&&e.skipSpaces(S)>=e.eMarks[t])return!1;if(_=e.src.charCodeAt(S-1),n)return!0;b=e.tokens.length,f?(R=e.push("ordered_list_open","ol",1),1!==k&&(R.attrs=[["start",k]])):R=e.push("bullet_list_open","ul",1),R.map=g=[t,0],R.markup=String.fromCharCode(_),y=t,F=!1,z=e.md.block.ruler.getRules("list"),w=e.parentType,e.parentType="list";while(y=v?1:x-h,p>4&&(p=1),l=h+p,R=e.push("list_item_open","li",1),R.markup=String.fromCharCode(_),R.map=d=[t,0],f&&(R.info=e.src.slice(L,S-1)),E=e.tight,D=e.tShift[t],A=e.sCount[t],C=e.listIndent,e.listIndent=e.blkIndent,e.blkIndent=l,e.tight=!0,e.tShift[t]=c-e.bMarks[t],e.sCount[t]=x,c>=v&&e.isEmpty(t+1)?e.line=Math.min(e.line+2,r):e.md.block.tokenize(e,t,r,!0),e.tight&&!F||(O=!1),F=e.line-t>1&&e.isEmpty(e.line-1),e.blkIndent=e.listIndent,e.listIndent=C,e.tShift[t]=D,e.sCount[t]=A,e.tight=E,R=e.push("list_item_close","li",-1),R.markup=String.fromCharCode(_),y=t=e.line,d[1]=y,c=e.bMarks[t],y>=r)break;if(e.sCount[y]=4)break;for(T=!1,u=0,m=z.length;u=o)break}else e.pending+=e.src[e.pos++]}e.pending&&e.pushPending()},i.prototype.parse=function(e,t,r,n){var s,o,i,a=new this.State(e,t,r,n);for(this.tokenize(a),o=this.ruler2.getRules(""),i=o.length,s=0;s`\\x00-\\x20]+",o="'[^']*'",i='"[^"]*"',a="(?:"+s+"|"+o+"|"+i+")",c="(?:\\s+"+n+"(?:\\s*=\\s*"+a+")?)",u="<[A-Za-z][A-Za-z0-9\\-]*"+c+"*\\s*\\/?>",l="<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>",p="\x3c!----\x3e|\x3c!--(?:-?[^>-])(?:-?[^-])*--\x3e",h="<[?][\\s\\S]*?[?]>",f="]*>",d="",m=new RegExp("^(?:"+u+"|"+l+"|"+p+"|"+h+"|"+f+"|"+d+")"),g=new RegExp("^(?:"+u+"|"+l+")");e.exports.HTML_TAG_RE=m,e.exports.HTML_OPEN_CLOSE_TAG_RE=g},"5b54":function(e,t,r){"use strict";var n=r("bd68"),s=r("0068").has,o=r("0068").isValidEntityCode,i=r("0068").fromCodePoint,a=/^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i,c=/^&([a-z][a-z0-9]{1,31});/i;e.exports=function(e,t){var r,u,l,p=e.pos,h=e.posMax;if(38!==e.src.charCodeAt(p))return!1;if(p+1|$))/i,/<\/(script|pre|style|textarea)>/i,!0],[/^/,!0],[/^<\?/,/\?>/,!0],[/^/,!0],[/^/,!0],[new RegExp("^|$))","i"),/^$/,!0],[new RegExp(s.source+"\\s*$"),/^$/,!1]];e.exports=function(e,t,r,n){var s,i,a,c,u=e.bMarks[t]+e.tShift[t],l=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4)return!1;if(!e.md.options.html)return!1;if(60!==e.src.charCodeAt(u))return!1;for(c=e.src.slice(u,l),s=0;s?@[]^_`{|}~-".split("").forEach((function(e){s[e.charCodeAt(0)]=1})),e.exports=function(e,t){var r,o=e.pos,i=e.posMax;if(92!==e.src.charCodeAt(o))return!1;if(o++,o=r)break;if(e.sCount[a]=u){e.line=r;break}for(s=0;s"+o(e[t].content)+""},i.code_block=function(e,t,r,n,s){var i=e[t];return""+o(e[t].content)+"\n"},i.fence=function(e,t,r,n,i){var a,c,u,l,p,h=e[t],f=h.info?s(h.info).trim():"",d="",m="";return f&&(u=f.split(/(\s+)/g),d=u[0],m=u.slice(2).join("")),a=r.highlight&&r.highlight(h.content,d,m)||o(h.content),0===a.indexOf(""+a+"\n"):"
"+a+"
\n"},i.image=function(e,t,r,n,s){var o=e[t];return o.attrs[o.attrIndex("alt")][1]=s.renderInlineAsText(o.children,r,n),s.renderToken(e,t,r)},i.hardbreak=function(e,t,r){return r.xhtmlOut?"
\n":"
\n"},i.softbreak=function(e,t,r){return r.breaks?r.xhtmlOut?"
\n":"
\n":"\n"},i.text=function(e,t){return o(e[t].content)},i.html_block=function(e,t){return e[t].content},i.html_inline=function(e,t){return e[t].content},a.prototype.renderAttrs=function(e){var t,r,n;if(!e.attrs)return"";for(n="",t=0,r=e.attrs.length;t\n":">",s)},a.prototype.renderInline=function(e,t,r){for(var n,s="",o=this.rules,i=0,a=e.length;i=r)return c;if(o=e.charCodeAt(t),34!==o&&39!==o&&40!==o)return c;t++,40===o&&(o=41);while(tr)return!1;if(h=t+1,e.sCount[h]=4)return!1;if(u=e.bMarks[h]+e.tShift[h],u>=e.eMarks[h])return!1;if(C=e.src.charCodeAt(u++),124!==C&&45!==C&&58!==C)return!1;if(u>=e.eMarks[h])return!1;if(w=e.src.charCodeAt(u++),124!==w&&45!==w&&58!==w&&!n(w))return!1;if(45===C&&n(w))return!1;while(u=4)return!1;if(f=o(c),f.length&&""===f[0]&&f.shift(),f.length&&""===f[f.length-1]&&f.pop(),d=f.length,0===d||d!==g.length)return!1;if(i)return!0;for(v=e.parentType,e.parentType="table",x=e.md.block.ruler.getRules("blockquote"),m=e.push("table_open","table",1),m.map=_=[t,0],m=e.push("thead_open","thead",1),m.map=[t,t+1],m=e.push("tr_open","tr",1),m.map=[t,t+1],l=0;l=4)break;for(f=o(c),f.length&&""===f[0]&&f.shift(),f.length&&""===f[f.length-1]&&f.pop(),h===t+2&&(m=e.push("tbody_open","tbody",1),m.map=k=[t+2,0]),m=e.push("tr_open","tr",1),m.map=[h,h+1],l=0;l0&&this.level++,this.tokens.push(s),s},o.prototype.isEmpty=function(e){return this.bMarks[e]+this.tShift[e]>=this.eMarks[e]},o.prototype.skipEmptyLines=function(e){for(var t=this.lineMax;et)if(!s(this.src.charCodeAt(--e)))return e+1;return e},o.prototype.skipChars=function(e,t){for(var r=this.src.length;er)if(t!==this.src.charCodeAt(--e))return e+1;return e},o.prototype.getLines=function(e,t,r,n){var o,i,a,c,u,l,p,h=e;if(e>=t)return"";for(l=new Array(t-e),o=0;hr?new Array(i-r+1).join(" ")+this.src.slice(c,u):this.src.slice(c,u)}return l.join("")},o.prototype.Token=n,e.exports=o},"838d":function(e,t,r){"use strict";function n(e,t){var r,n,s,o,i,a,c,u,l={},p=t.length;if(p){var h=0,f=-2,d=[];for(r=0;ri;n-=d[n]+1)if(o=t[n],o.marker===s.marker&&o.open&&o.end<0&&(c=!1,(o.close||s.open)&&(o.length+s.length)%3===0&&(o.length%3===0&&s.length%3===0||(c=!0)),!c)){u=n>0&&!t[n-1].open?d[n-1]+1:0,d[r]=r-n+u,d[n]=u,s.open=!1,o.end=r,o.close=!1,a=-1,f=-2;break}-1!==a&&(l[s.marker][(s.open?3:0)+(s.length||0)%3]=a)}}}e.exports=function(e){var t,r=e.tokens_meta,s=e.tokens_meta.length;for(n(e,e.delimiters),t=0;tn[s])return!0;if(r[s]0){var o=n[s],i=t[o];if(i){var a=e[o],c=void 0===a||i(a,o,e);if(!0!==c)throw new TypeError("option "+o+" must be "+c)}else if(!0!==r)throw Error("Unknown option "+o)}}s.transitional=function(e,t,r){var s=t&&a(t);function i(e,t){return"[Axios v"+n.version+"] Transitional option '"+e+"'"+t+(r?". "+r:"")}return function(r,n,a){if(!1===e)throw new Error(i(n," has been removed in "+t));return s&&!o[n]&&(o[n]=!0,console.warn(i(n," has been deprecated since v"+t+" and will be removed in the near future"))),!e||e(r,n,a)}},e.exports={isOlderVersion:a,assertOptions:c,validators:s}},"8a31":function(e,t,r){"use strict";e.exports={options:{html:!1,xhtmlOut:!1,breaks:!1,langPrefix:"language-",linkify:!1,typographer:!1,quotes:"“”‘’",highlight:null,maxNesting:100},components:{core:{},block:{},inline:{}}}},"8df4":function(e,t,r){"use strict";var n=r("7a77");function s(e){if("function"!==typeof e)throw new TypeError("executor must be a function.");var t;this.promise=new Promise((function(e){t=e}));var r=this;e((function(e){r.reason||(r.reason=new n(e),t(r.reason))}))}s.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},s.source=function(){var e,t=new s((function(t){e=t}));return{token:t,cancel:e}},e.exports=s},"8f37":function(e,t,r){"use strict";var n={};function s(e){var t,r,s=n[e];if(s)return s;for(s=n[e]=[],t=0;t<128;t++)r=String.fromCharCode(t),s.push(r);for(t=0;t=55296&&c<=57343?"���":String.fromCharCode(c),t+=6):240===(248&s)&&t+91114111?u+="����":(c-=65536,u+=String.fromCharCode(55296+(c>>10),56320+(1023&c))),t+=9):u+="�";return u}))}o.defaultChars=";/?:@&=+$,#",o.componentChars="",e.exports=o},"922c":function(e,t,r){"use strict";function n(e,t){var r,n,s,o,i,a=[],c=t.length;for(r=0;r=k)return!1;for(g=l,h=e.md.helpers.parseLinkDestination(e.src,l,e.posMax),h.ok&&(b=e.md.normalizeLink(h.str),e.md.validateLink(b)?l=h.pos:b=""),g=l;l=k||41!==e.src.charCodeAt(l))return e.pos=_,!1;l++}else{if("undefined"===typeof e.env.references)return!1;if(l=0?a=e.src.slice(g,l++):l=c+1):l=c+1,a||(a=e.src.slice(u,c)),p=e.env.references[n(a)],!p)return e.pos=_,!1;b=p.href,f=p.title}return t||(i=e.src.slice(u,c),e.md.inline.parse(i,e.md,e.env,m=[]),d=e.push("image","img",0),d.attrs=r=[["src",b],["alt",""]],d.children=m,d.content=i,f&&r.push(["title",f])),e.pos=l,e.posMax=k,!0}},9454:function(e,t,r){"use strict";var n=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",[r("p",{domProps:{innerHTML:e._s(e.parsed_md)}})])},s=[],o=r("bc3a"),i=r.n(o),a=r("d4cd"),c=r.n(a),u=r("1c78"),l=r("19dd"),p=function(e){return l(e)},h=function(e){var t=c()().use(u["default"],{level:1,permalink:!0,permalinkClass:"header-anchor",permalinkSymbol:"¶",permalinkBefore:!1,slugify:p});return t.render(e)},f={name:"RemoteMarkdown",components:{},data:function(){return{parsed_md:null}},props:{url:String},mounted:function(){var e=this;i.a.get(this.url).then((function(t){e.parsed_md=h(t.data)}))}},d=f,m=r("2877"),g=Object(m["a"])(d,n,s,!1,null,null,null);t["a"]=g.exports},9921:function(e,t,r){"use strict";var n=r("0068").arrayReplaceAt;function s(e){return/^\s]/i.test(e)}function o(e){return/^<\/a\s*>/i.test(e)}e.exports=function(e){var t,r,i,a,c,u,l,p,h,f,d,m,g,b,_,k,v,y=e.tokens;if(e.md.options.linkify)for(r=0,i=y.length;r=0;t--)if(u=a[t],"link_close"!==u.type){if("html_inline"===u.type&&(s(u.content)&&g>0&&g--,o(u.content)&&g++),!(g>0)&&"text"===u.type&&e.md.linkify.test(u.content)){for(h=u.content,v=e.md.linkify.match(h),l=[],m=u.level,d=0,p=0;pd&&(c=new e.Token("text","",0),c.content=h.slice(d,f),c.level=m,l.push(c)),c=new e.Token("link_open","a",1),c.attrs=[["href",_]],c.level=m++,c.markup="linkify",c.info="auto",l.push(c),c=new e.Token("text","",0),c.content=k,c.level=m,l.push(c),c=new e.Token("link_close","a",-1),c.level=--m,c.markup="linkify",c.info="auto",l.push(c),d=v[p].lastIndex);d=4))break;n++,s=n}return e.line=s,o=e.push("code_block","code",0),o.content=e.getLines(t,s,4+e.blkIndent,!1)+"\n",o.map=[t,e.line],!0}},a124:function(e,t,r){"use strict";e.exports=function(e){var t,r,n,s=e.tokens;for(r=0,n=s.length;r","GT":">","Gt":"≫","gtdot":"⋗","gtlPar":"⦕","gtquest":"⩼","gtrapprox":"⪆","gtrarr":"⥸","gtrdot":"⋗","gtreqless":"⋛","gtreqqless":"⪌","gtrless":"≷","gtrsim":"≳","gvertneqq":"≩︀","gvnE":"≩︀","Hacek":"ˇ","hairsp":" ","half":"½","hamilt":"ℋ","HARDcy":"Ъ","hardcy":"ъ","harrcir":"⥈","harr":"↔","hArr":"⇔","harrw":"↭","Hat":"^","hbar":"ℏ","Hcirc":"Ĥ","hcirc":"ĥ","hearts":"♥","heartsuit":"♥","hellip":"…","hercon":"⊹","hfr":"𝔥","Hfr":"ℌ","HilbertSpace":"ℋ","hksearow":"⤥","hkswarow":"⤦","hoarr":"⇿","homtht":"∻","hookleftarrow":"↩","hookrightarrow":"↪","hopf":"𝕙","Hopf":"ℍ","horbar":"―","HorizontalLine":"─","hscr":"𝒽","Hscr":"ℋ","hslash":"ℏ","Hstrok":"Ħ","hstrok":"ħ","HumpDownHump":"≎","HumpEqual":"≏","hybull":"⁃","hyphen":"‐","Iacute":"Í","iacute":"í","ic":"⁣","Icirc":"Î","icirc":"î","Icy":"И","icy":"и","Idot":"İ","IEcy":"Е","iecy":"е","iexcl":"¡","iff":"⇔","ifr":"𝔦","Ifr":"ℑ","Igrave":"Ì","igrave":"ì","ii":"ⅈ","iiiint":"⨌","iiint":"∭","iinfin":"⧜","iiota":"℩","IJlig":"IJ","ijlig":"ij","Imacr":"Ī","imacr":"ī","image":"ℑ","ImaginaryI":"ⅈ","imagline":"ℐ","imagpart":"ℑ","imath":"ı","Im":"ℑ","imof":"⊷","imped":"Ƶ","Implies":"⇒","incare":"℅","in":"∈","infin":"∞","infintie":"⧝","inodot":"ı","intcal":"⊺","int":"∫","Int":"∬","integers":"ℤ","Integral":"∫","intercal":"⊺","Intersection":"⋂","intlarhk":"⨗","intprod":"⨼","InvisibleComma":"⁣","InvisibleTimes":"⁢","IOcy":"Ё","iocy":"ё","Iogon":"Į","iogon":"į","Iopf":"𝕀","iopf":"𝕚","Iota":"Ι","iota":"ι","iprod":"⨼","iquest":"¿","iscr":"𝒾","Iscr":"ℐ","isin":"∈","isindot":"⋵","isinE":"⋹","isins":"⋴","isinsv":"⋳","isinv":"∈","it":"⁢","Itilde":"Ĩ","itilde":"ĩ","Iukcy":"І","iukcy":"і","Iuml":"Ï","iuml":"ï","Jcirc":"Ĵ","jcirc":"ĵ","Jcy":"Й","jcy":"й","Jfr":"𝔍","jfr":"𝔧","jmath":"ȷ","Jopf":"𝕁","jopf":"𝕛","Jscr":"𝒥","jscr":"𝒿","Jsercy":"Ј","jsercy":"ј","Jukcy":"Є","jukcy":"є","Kappa":"Κ","kappa":"κ","kappav":"ϰ","Kcedil":"Ķ","kcedil":"ķ","Kcy":"К","kcy":"к","Kfr":"𝔎","kfr":"𝔨","kgreen":"ĸ","KHcy":"Х","khcy":"х","KJcy":"Ќ","kjcy":"ќ","Kopf":"𝕂","kopf":"𝕜","Kscr":"𝒦","kscr":"𝓀","lAarr":"⇚","Lacute":"Ĺ","lacute":"ĺ","laemptyv":"⦴","lagran":"ℒ","Lambda":"Λ","lambda":"λ","lang":"⟨","Lang":"⟪","langd":"⦑","langle":"⟨","lap":"⪅","Laplacetrf":"ℒ","laquo":"«","larrb":"⇤","larrbfs":"⤟","larr":"←","Larr":"↞","lArr":"⇐","larrfs":"⤝","larrhk":"↩","larrlp":"↫","larrpl":"⤹","larrsim":"⥳","larrtl":"↢","latail":"⤙","lAtail":"⤛","lat":"⪫","late":"⪭","lates":"⪭︀","lbarr":"⤌","lBarr":"⤎","lbbrk":"❲","lbrace":"{","lbrack":"[","lbrke":"⦋","lbrksld":"⦏","lbrkslu":"⦍","Lcaron":"Ľ","lcaron":"ľ","Lcedil":"Ļ","lcedil":"ļ","lceil":"⌈","lcub":"{","Lcy":"Л","lcy":"л","ldca":"⤶","ldquo":"“","ldquor":"„","ldrdhar":"⥧","ldrushar":"⥋","ldsh":"↲","le":"≤","lE":"≦","LeftAngleBracket":"⟨","LeftArrowBar":"⇤","leftarrow":"←","LeftArrow":"←","Leftarrow":"⇐","LeftArrowRightArrow":"⇆","leftarrowtail":"↢","LeftCeiling":"⌈","LeftDoubleBracket":"⟦","LeftDownTeeVector":"⥡","LeftDownVectorBar":"⥙","LeftDownVector":"⇃","LeftFloor":"⌊","leftharpoondown":"↽","leftharpoonup":"↼","leftleftarrows":"⇇","leftrightarrow":"↔","LeftRightArrow":"↔","Leftrightarrow":"⇔","leftrightarrows":"⇆","leftrightharpoons":"⇋","leftrightsquigarrow":"↭","LeftRightVector":"⥎","LeftTeeArrow":"↤","LeftTee":"⊣","LeftTeeVector":"⥚","leftthreetimes":"⋋","LeftTriangleBar":"⧏","LeftTriangle":"⊲","LeftTriangleEqual":"⊴","LeftUpDownVector":"⥑","LeftUpTeeVector":"⥠","LeftUpVectorBar":"⥘","LeftUpVector":"↿","LeftVectorBar":"⥒","LeftVector":"↼","lEg":"⪋","leg":"⋚","leq":"≤","leqq":"≦","leqslant":"⩽","lescc":"⪨","les":"⩽","lesdot":"⩿","lesdoto":"⪁","lesdotor":"⪃","lesg":"⋚︀","lesges":"⪓","lessapprox":"⪅","lessdot":"⋖","lesseqgtr":"⋚","lesseqqgtr":"⪋","LessEqualGreater":"⋚","LessFullEqual":"≦","LessGreater":"≶","lessgtr":"≶","LessLess":"⪡","lesssim":"≲","LessSlantEqual":"⩽","LessTilde":"≲","lfisht":"⥼","lfloor":"⌊","Lfr":"𝔏","lfr":"𝔩","lg":"≶","lgE":"⪑","lHar":"⥢","lhard":"↽","lharu":"↼","lharul":"⥪","lhblk":"▄","LJcy":"Љ","ljcy":"љ","llarr":"⇇","ll":"≪","Ll":"⋘","llcorner":"⌞","Lleftarrow":"⇚","llhard":"⥫","lltri":"◺","Lmidot":"Ŀ","lmidot":"ŀ","lmoustache":"⎰","lmoust":"⎰","lnap":"⪉","lnapprox":"⪉","lne":"⪇","lnE":"≨","lneq":"⪇","lneqq":"≨","lnsim":"⋦","loang":"⟬","loarr":"⇽","lobrk":"⟦","longleftarrow":"⟵","LongLeftArrow":"⟵","Longleftarrow":"⟸","longleftrightarrow":"⟷","LongLeftRightArrow":"⟷","Longleftrightarrow":"⟺","longmapsto":"⟼","longrightarrow":"⟶","LongRightArrow":"⟶","Longrightarrow":"⟹","looparrowleft":"↫","looparrowright":"↬","lopar":"⦅","Lopf":"𝕃","lopf":"𝕝","loplus":"⨭","lotimes":"⨴","lowast":"∗","lowbar":"_","LowerLeftArrow":"↙","LowerRightArrow":"↘","loz":"◊","lozenge":"◊","lozf":"⧫","lpar":"(","lparlt":"⦓","lrarr":"⇆","lrcorner":"⌟","lrhar":"⇋","lrhard":"⥭","lrm":"‎","lrtri":"⊿","lsaquo":"‹","lscr":"𝓁","Lscr":"ℒ","lsh":"↰","Lsh":"↰","lsim":"≲","lsime":"⪍","lsimg":"⪏","lsqb":"[","lsquo":"‘","lsquor":"‚","Lstrok":"Ł","lstrok":"ł","ltcc":"⪦","ltcir":"⩹","lt":"<","LT":"<","Lt":"≪","ltdot":"⋖","lthree":"⋋","ltimes":"⋉","ltlarr":"⥶","ltquest":"⩻","ltri":"◃","ltrie":"⊴","ltrif":"◂","ltrPar":"⦖","lurdshar":"⥊","luruhar":"⥦","lvertneqq":"≨︀","lvnE":"≨︀","macr":"¯","male":"♂","malt":"✠","maltese":"✠","Map":"⤅","map":"↦","mapsto":"↦","mapstodown":"↧","mapstoleft":"↤","mapstoup":"↥","marker":"▮","mcomma":"⨩","Mcy":"М","mcy":"м","mdash":"—","mDDot":"∺","measuredangle":"∡","MediumSpace":" ","Mellintrf":"ℳ","Mfr":"𝔐","mfr":"𝔪","mho":"℧","micro":"µ","midast":"*","midcir":"⫰","mid":"∣","middot":"·","minusb":"⊟","minus":"−","minusd":"∸","minusdu":"⨪","MinusPlus":"∓","mlcp":"⫛","mldr":"…","mnplus":"∓","models":"⊧","Mopf":"𝕄","mopf":"𝕞","mp":"∓","mscr":"𝓂","Mscr":"ℳ","mstpos":"∾","Mu":"Μ","mu":"μ","multimap":"⊸","mumap":"⊸","nabla":"∇","Nacute":"Ń","nacute":"ń","nang":"∠⃒","nap":"≉","napE":"⩰̸","napid":"≋̸","napos":"ʼn","napprox":"≉","natural":"♮","naturals":"ℕ","natur":"♮","nbsp":" ","nbump":"≎̸","nbumpe":"≏̸","ncap":"⩃","Ncaron":"Ň","ncaron":"ň","Ncedil":"Ņ","ncedil":"ņ","ncong":"≇","ncongdot":"⩭̸","ncup":"⩂","Ncy":"Н","ncy":"н","ndash":"–","nearhk":"⤤","nearr":"↗","neArr":"⇗","nearrow":"↗","ne":"≠","nedot":"≐̸","NegativeMediumSpace":"​","NegativeThickSpace":"​","NegativeThinSpace":"​","NegativeVeryThinSpace":"​","nequiv":"≢","nesear":"⤨","nesim":"≂̸","NestedGreaterGreater":"≫","NestedLessLess":"≪","NewLine":"\\n","nexist":"∄","nexists":"∄","Nfr":"𝔑","nfr":"𝔫","ngE":"≧̸","nge":"≱","ngeq":"≱","ngeqq":"≧̸","ngeqslant":"⩾̸","nges":"⩾̸","nGg":"⋙̸","ngsim":"≵","nGt":"≫⃒","ngt":"≯","ngtr":"≯","nGtv":"≫̸","nharr":"↮","nhArr":"⇎","nhpar":"⫲","ni":"∋","nis":"⋼","nisd":"⋺","niv":"∋","NJcy":"Њ","njcy":"њ","nlarr":"↚","nlArr":"⇍","nldr":"‥","nlE":"≦̸","nle":"≰","nleftarrow":"↚","nLeftarrow":"⇍","nleftrightarrow":"↮","nLeftrightarrow":"⇎","nleq":"≰","nleqq":"≦̸","nleqslant":"⩽̸","nles":"⩽̸","nless":"≮","nLl":"⋘̸","nlsim":"≴","nLt":"≪⃒","nlt":"≮","nltri":"⋪","nltrie":"⋬","nLtv":"≪̸","nmid":"∤","NoBreak":"⁠","NonBreakingSpace":" ","nopf":"𝕟","Nopf":"ℕ","Not":"⫬","not":"¬","NotCongruent":"≢","NotCupCap":"≭","NotDoubleVerticalBar":"∦","NotElement":"∉","NotEqual":"≠","NotEqualTilde":"≂̸","NotExists":"∄","NotGreater":"≯","NotGreaterEqual":"≱","NotGreaterFullEqual":"≧̸","NotGreaterGreater":"≫̸","NotGreaterLess":"≹","NotGreaterSlantEqual":"⩾̸","NotGreaterTilde":"≵","NotHumpDownHump":"≎̸","NotHumpEqual":"≏̸","notin":"∉","notindot":"⋵̸","notinE":"⋹̸","notinva":"∉","notinvb":"⋷","notinvc":"⋶","NotLeftTriangleBar":"⧏̸","NotLeftTriangle":"⋪","NotLeftTriangleEqual":"⋬","NotLess":"≮","NotLessEqual":"≰","NotLessGreater":"≸","NotLessLess":"≪̸","NotLessSlantEqual":"⩽̸","NotLessTilde":"≴","NotNestedGreaterGreater":"⪢̸","NotNestedLessLess":"⪡̸","notni":"∌","notniva":"∌","notnivb":"⋾","notnivc":"⋽","NotPrecedes":"⊀","NotPrecedesEqual":"⪯̸","NotPrecedesSlantEqual":"⋠","NotReverseElement":"∌","NotRightTriangleBar":"⧐̸","NotRightTriangle":"⋫","NotRightTriangleEqual":"⋭","NotSquareSubset":"⊏̸","NotSquareSubsetEqual":"⋢","NotSquareSuperset":"⊐̸","NotSquareSupersetEqual":"⋣","NotSubset":"⊂⃒","NotSubsetEqual":"⊈","NotSucceeds":"⊁","NotSucceedsEqual":"⪰̸","NotSucceedsSlantEqual":"⋡","NotSucceedsTilde":"≿̸","NotSuperset":"⊃⃒","NotSupersetEqual":"⊉","NotTilde":"≁","NotTildeEqual":"≄","NotTildeFullEqual":"≇","NotTildeTilde":"≉","NotVerticalBar":"∤","nparallel":"∦","npar":"∦","nparsl":"⫽⃥","npart":"∂̸","npolint":"⨔","npr":"⊀","nprcue":"⋠","nprec":"⊀","npreceq":"⪯̸","npre":"⪯̸","nrarrc":"⤳̸","nrarr":"↛","nrArr":"⇏","nrarrw":"↝̸","nrightarrow":"↛","nRightarrow":"⇏","nrtri":"⋫","nrtrie":"⋭","nsc":"⊁","nsccue":"⋡","nsce":"⪰̸","Nscr":"𝒩","nscr":"𝓃","nshortmid":"∤","nshortparallel":"∦","nsim":"≁","nsime":"≄","nsimeq":"≄","nsmid":"∤","nspar":"∦","nsqsube":"⋢","nsqsupe":"⋣","nsub":"⊄","nsubE":"⫅̸","nsube":"⊈","nsubset":"⊂⃒","nsubseteq":"⊈","nsubseteqq":"⫅̸","nsucc":"⊁","nsucceq":"⪰̸","nsup":"⊅","nsupE":"⫆̸","nsupe":"⊉","nsupset":"⊃⃒","nsupseteq":"⊉","nsupseteqq":"⫆̸","ntgl":"≹","Ntilde":"Ñ","ntilde":"ñ","ntlg":"≸","ntriangleleft":"⋪","ntrianglelefteq":"⋬","ntriangleright":"⋫","ntrianglerighteq":"⋭","Nu":"Ν","nu":"ν","num":"#","numero":"№","numsp":" ","nvap":"≍⃒","nvdash":"⊬","nvDash":"⊭","nVdash":"⊮","nVDash":"⊯","nvge":"≥⃒","nvgt":">⃒","nvHarr":"⤄","nvinfin":"⧞","nvlArr":"⤂","nvle":"≤⃒","nvlt":"<⃒","nvltrie":"⊴⃒","nvrArr":"⤃","nvrtrie":"⊵⃒","nvsim":"∼⃒","nwarhk":"⤣","nwarr":"↖","nwArr":"⇖","nwarrow":"↖","nwnear":"⤧","Oacute":"Ó","oacute":"ó","oast":"⊛","Ocirc":"Ô","ocirc":"ô","ocir":"⊚","Ocy":"О","ocy":"о","odash":"⊝","Odblac":"Ő","odblac":"ő","odiv":"⨸","odot":"⊙","odsold":"⦼","OElig":"Œ","oelig":"œ","ofcir":"⦿","Ofr":"𝔒","ofr":"𝔬","ogon":"˛","Ograve":"Ò","ograve":"ò","ogt":"⧁","ohbar":"⦵","ohm":"Ω","oint":"∮","olarr":"↺","olcir":"⦾","olcross":"⦻","oline":"‾","olt":"⧀","Omacr":"Ō","omacr":"ō","Omega":"Ω","omega":"ω","Omicron":"Ο","omicron":"ο","omid":"⦶","ominus":"⊖","Oopf":"𝕆","oopf":"𝕠","opar":"⦷","OpenCurlyDoubleQuote":"“","OpenCurlyQuote":"‘","operp":"⦹","oplus":"⊕","orarr":"↻","Or":"⩔","or":"∨","ord":"⩝","order":"ℴ","orderof":"ℴ","ordf":"ª","ordm":"º","origof":"⊶","oror":"⩖","orslope":"⩗","orv":"⩛","oS":"Ⓢ","Oscr":"𝒪","oscr":"ℴ","Oslash":"Ø","oslash":"ø","osol":"⊘","Otilde":"Õ","otilde":"õ","otimesas":"⨶","Otimes":"⨷","otimes":"⊗","Ouml":"Ö","ouml":"ö","ovbar":"⌽","OverBar":"‾","OverBrace":"⏞","OverBracket":"⎴","OverParenthesis":"⏜","para":"¶","parallel":"∥","par":"∥","parsim":"⫳","parsl":"⫽","part":"∂","PartialD":"∂","Pcy":"П","pcy":"п","percnt":"%","period":".","permil":"‰","perp":"⊥","pertenk":"‱","Pfr":"𝔓","pfr":"𝔭","Phi":"Φ","phi":"φ","phiv":"ϕ","phmmat":"ℳ","phone":"☎","Pi":"Π","pi":"π","pitchfork":"⋔","piv":"ϖ","planck":"ℏ","planckh":"ℎ","plankv":"ℏ","plusacir":"⨣","plusb":"⊞","pluscir":"⨢","plus":"+","plusdo":"∔","plusdu":"⨥","pluse":"⩲","PlusMinus":"±","plusmn":"±","plussim":"⨦","plustwo":"⨧","pm":"±","Poincareplane":"ℌ","pointint":"⨕","popf":"𝕡","Popf":"ℙ","pound":"£","prap":"⪷","Pr":"⪻","pr":"≺","prcue":"≼","precapprox":"⪷","prec":"≺","preccurlyeq":"≼","Precedes":"≺","PrecedesEqual":"⪯","PrecedesSlantEqual":"≼","PrecedesTilde":"≾","preceq":"⪯","precnapprox":"⪹","precneqq":"⪵","precnsim":"⋨","pre":"⪯","prE":"⪳","precsim":"≾","prime":"′","Prime":"″","primes":"ℙ","prnap":"⪹","prnE":"⪵","prnsim":"⋨","prod":"∏","Product":"∏","profalar":"⌮","profline":"⌒","profsurf":"⌓","prop":"∝","Proportional":"∝","Proportion":"∷","propto":"∝","prsim":"≾","prurel":"⊰","Pscr":"𝒫","pscr":"𝓅","Psi":"Ψ","psi":"ψ","puncsp":" ","Qfr":"𝔔","qfr":"𝔮","qint":"⨌","qopf":"𝕢","Qopf":"ℚ","qprime":"⁗","Qscr":"𝒬","qscr":"𝓆","quaternions":"ℍ","quatint":"⨖","quest":"?","questeq":"≟","quot":"\\"","QUOT":"\\"","rAarr":"⇛","race":"∽̱","Racute":"Ŕ","racute":"ŕ","radic":"√","raemptyv":"⦳","rang":"⟩","Rang":"⟫","rangd":"⦒","range":"⦥","rangle":"⟩","raquo":"»","rarrap":"⥵","rarrb":"⇥","rarrbfs":"⤠","rarrc":"⤳","rarr":"→","Rarr":"↠","rArr":"⇒","rarrfs":"⤞","rarrhk":"↪","rarrlp":"↬","rarrpl":"⥅","rarrsim":"⥴","Rarrtl":"⤖","rarrtl":"↣","rarrw":"↝","ratail":"⤚","rAtail":"⤜","ratio":"∶","rationals":"ℚ","rbarr":"⤍","rBarr":"⤏","RBarr":"⤐","rbbrk":"❳","rbrace":"}","rbrack":"]","rbrke":"⦌","rbrksld":"⦎","rbrkslu":"⦐","Rcaron":"Ř","rcaron":"ř","Rcedil":"Ŗ","rcedil":"ŗ","rceil":"⌉","rcub":"}","Rcy":"Р","rcy":"р","rdca":"⤷","rdldhar":"⥩","rdquo":"”","rdquor":"”","rdsh":"↳","real":"ℜ","realine":"ℛ","realpart":"ℜ","reals":"ℝ","Re":"ℜ","rect":"▭","reg":"®","REG":"®","ReverseElement":"∋","ReverseEquilibrium":"⇋","ReverseUpEquilibrium":"⥯","rfisht":"⥽","rfloor":"⌋","rfr":"𝔯","Rfr":"ℜ","rHar":"⥤","rhard":"⇁","rharu":"⇀","rharul":"⥬","Rho":"Ρ","rho":"ρ","rhov":"ϱ","RightAngleBracket":"⟩","RightArrowBar":"⇥","rightarrow":"→","RightArrow":"→","Rightarrow":"⇒","RightArrowLeftArrow":"⇄","rightarrowtail":"↣","RightCeiling":"⌉","RightDoubleBracket":"⟧","RightDownTeeVector":"⥝","RightDownVectorBar":"⥕","RightDownVector":"⇂","RightFloor":"⌋","rightharpoondown":"⇁","rightharpoonup":"⇀","rightleftarrows":"⇄","rightleftharpoons":"⇌","rightrightarrows":"⇉","rightsquigarrow":"↝","RightTeeArrow":"↦","RightTee":"⊢","RightTeeVector":"⥛","rightthreetimes":"⋌","RightTriangleBar":"⧐","RightTriangle":"⊳","RightTriangleEqual":"⊵","RightUpDownVector":"⥏","RightUpTeeVector":"⥜","RightUpVectorBar":"⥔","RightUpVector":"↾","RightVectorBar":"⥓","RightVector":"⇀","ring":"˚","risingdotseq":"≓","rlarr":"⇄","rlhar":"⇌","rlm":"‏","rmoustache":"⎱","rmoust":"⎱","rnmid":"⫮","roang":"⟭","roarr":"⇾","robrk":"⟧","ropar":"⦆","ropf":"𝕣","Ropf":"ℝ","roplus":"⨮","rotimes":"⨵","RoundImplies":"⥰","rpar":")","rpargt":"⦔","rppolint":"⨒","rrarr":"⇉","Rrightarrow":"⇛","rsaquo":"›","rscr":"𝓇","Rscr":"ℛ","rsh":"↱","Rsh":"↱","rsqb":"]","rsquo":"’","rsquor":"’","rthree":"⋌","rtimes":"⋊","rtri":"▹","rtrie":"⊵","rtrif":"▸","rtriltri":"⧎","RuleDelayed":"⧴","ruluhar":"⥨","rx":"℞","Sacute":"Ś","sacute":"ś","sbquo":"‚","scap":"⪸","Scaron":"Š","scaron":"š","Sc":"⪼","sc":"≻","sccue":"≽","sce":"⪰","scE":"⪴","Scedil":"Ş","scedil":"ş","Scirc":"Ŝ","scirc":"ŝ","scnap":"⪺","scnE":"⪶","scnsim":"⋩","scpolint":"⨓","scsim":"≿","Scy":"С","scy":"с","sdotb":"⊡","sdot":"⋅","sdote":"⩦","searhk":"⤥","searr":"↘","seArr":"⇘","searrow":"↘","sect":"§","semi":";","seswar":"⤩","setminus":"∖","setmn":"∖","sext":"✶","Sfr":"𝔖","sfr":"𝔰","sfrown":"⌢","sharp":"♯","SHCHcy":"Щ","shchcy":"щ","SHcy":"Ш","shcy":"ш","ShortDownArrow":"↓","ShortLeftArrow":"←","shortmid":"∣","shortparallel":"∥","ShortRightArrow":"→","ShortUpArrow":"↑","shy":"­","Sigma":"Σ","sigma":"σ","sigmaf":"ς","sigmav":"ς","sim":"∼","simdot":"⩪","sime":"≃","simeq":"≃","simg":"⪞","simgE":"⪠","siml":"⪝","simlE":"⪟","simne":"≆","simplus":"⨤","simrarr":"⥲","slarr":"←","SmallCircle":"∘","smallsetminus":"∖","smashp":"⨳","smeparsl":"⧤","smid":"∣","smile":"⌣","smt":"⪪","smte":"⪬","smtes":"⪬︀","SOFTcy":"Ь","softcy":"ь","solbar":"⌿","solb":"⧄","sol":"/","Sopf":"𝕊","sopf":"𝕤","spades":"♠","spadesuit":"♠","spar":"∥","sqcap":"⊓","sqcaps":"⊓︀","sqcup":"⊔","sqcups":"⊔︀","Sqrt":"√","sqsub":"⊏","sqsube":"⊑","sqsubset":"⊏","sqsubseteq":"⊑","sqsup":"⊐","sqsupe":"⊒","sqsupset":"⊐","sqsupseteq":"⊒","square":"□","Square":"□","SquareIntersection":"⊓","SquareSubset":"⊏","SquareSubsetEqual":"⊑","SquareSuperset":"⊐","SquareSupersetEqual":"⊒","SquareUnion":"⊔","squarf":"▪","squ":"□","squf":"▪","srarr":"→","Sscr":"𝒮","sscr":"𝓈","ssetmn":"∖","ssmile":"⌣","sstarf":"⋆","Star":"⋆","star":"☆","starf":"★","straightepsilon":"ϵ","straightphi":"ϕ","strns":"¯","sub":"⊂","Sub":"⋐","subdot":"⪽","subE":"⫅","sube":"⊆","subedot":"⫃","submult":"⫁","subnE":"⫋","subne":"⊊","subplus":"⪿","subrarr":"⥹","subset":"⊂","Subset":"⋐","subseteq":"⊆","subseteqq":"⫅","SubsetEqual":"⊆","subsetneq":"⊊","subsetneqq":"⫋","subsim":"⫇","subsub":"⫕","subsup":"⫓","succapprox":"⪸","succ":"≻","succcurlyeq":"≽","Succeeds":"≻","SucceedsEqual":"⪰","SucceedsSlantEqual":"≽","SucceedsTilde":"≿","succeq":"⪰","succnapprox":"⪺","succneqq":"⪶","succnsim":"⋩","succsim":"≿","SuchThat":"∋","sum":"∑","Sum":"∑","sung":"♪","sup1":"¹","sup2":"²","sup3":"³","sup":"⊃","Sup":"⋑","supdot":"⪾","supdsub":"⫘","supE":"⫆","supe":"⊇","supedot":"⫄","Superset":"⊃","SupersetEqual":"⊇","suphsol":"⟉","suphsub":"⫗","suplarr":"⥻","supmult":"⫂","supnE":"⫌","supne":"⊋","supplus":"⫀","supset":"⊃","Supset":"⋑","supseteq":"⊇","supseteqq":"⫆","supsetneq":"⊋","supsetneqq":"⫌","supsim":"⫈","supsub":"⫔","supsup":"⫖","swarhk":"⤦","swarr":"↙","swArr":"⇙","swarrow":"↙","swnwar":"⤪","szlig":"ß","Tab":"\\t","target":"⌖","Tau":"Τ","tau":"τ","tbrk":"⎴","Tcaron":"Ť","tcaron":"ť","Tcedil":"Ţ","tcedil":"ţ","Tcy":"Т","tcy":"т","tdot":"⃛","telrec":"⌕","Tfr":"𝔗","tfr":"𝔱","there4":"∴","therefore":"∴","Therefore":"∴","Theta":"Θ","theta":"θ","thetasym":"ϑ","thetav":"ϑ","thickapprox":"≈","thicksim":"∼","ThickSpace":"  ","ThinSpace":" ","thinsp":" ","thkap":"≈","thksim":"∼","THORN":"Þ","thorn":"þ","tilde":"˜","Tilde":"∼","TildeEqual":"≃","TildeFullEqual":"≅","TildeTilde":"≈","timesbar":"⨱","timesb":"⊠","times":"×","timesd":"⨰","tint":"∭","toea":"⤨","topbot":"⌶","topcir":"⫱","top":"⊤","Topf":"𝕋","topf":"𝕥","topfork":"⫚","tosa":"⤩","tprime":"‴","trade":"™","TRADE":"™","triangle":"▵","triangledown":"▿","triangleleft":"◃","trianglelefteq":"⊴","triangleq":"≜","triangleright":"▹","trianglerighteq":"⊵","tridot":"◬","trie":"≜","triminus":"⨺","TripleDot":"⃛","triplus":"⨹","trisb":"⧍","tritime":"⨻","trpezium":"⏢","Tscr":"𝒯","tscr":"𝓉","TScy":"Ц","tscy":"ц","TSHcy":"Ћ","tshcy":"ћ","Tstrok":"Ŧ","tstrok":"ŧ","twixt":"≬","twoheadleftarrow":"↞","twoheadrightarrow":"↠","Uacute":"Ú","uacute":"ú","uarr":"↑","Uarr":"↟","uArr":"⇑","Uarrocir":"⥉","Ubrcy":"Ў","ubrcy":"ў","Ubreve":"Ŭ","ubreve":"ŭ","Ucirc":"Û","ucirc":"û","Ucy":"У","ucy":"у","udarr":"⇅","Udblac":"Ű","udblac":"ű","udhar":"⥮","ufisht":"⥾","Ufr":"𝔘","ufr":"𝔲","Ugrave":"Ù","ugrave":"ù","uHar":"⥣","uharl":"↿","uharr":"↾","uhblk":"▀","ulcorn":"⌜","ulcorner":"⌜","ulcrop":"⌏","ultri":"◸","Umacr":"Ū","umacr":"ū","uml":"¨","UnderBar":"_","UnderBrace":"⏟","UnderBracket":"⎵","UnderParenthesis":"⏝","Union":"⋃","UnionPlus":"⊎","Uogon":"Ų","uogon":"ų","Uopf":"𝕌","uopf":"𝕦","UpArrowBar":"⤒","uparrow":"↑","UpArrow":"↑","Uparrow":"⇑","UpArrowDownArrow":"⇅","updownarrow":"↕","UpDownArrow":"↕","Updownarrow":"⇕","UpEquilibrium":"⥮","upharpoonleft":"↿","upharpoonright":"↾","uplus":"⊎","UpperLeftArrow":"↖","UpperRightArrow":"↗","upsi":"υ","Upsi":"ϒ","upsih":"ϒ","Upsilon":"Υ","upsilon":"υ","UpTeeArrow":"↥","UpTee":"⊥","upuparrows":"⇈","urcorn":"⌝","urcorner":"⌝","urcrop":"⌎","Uring":"Ů","uring":"ů","urtri":"◹","Uscr":"𝒰","uscr":"𝓊","utdot":"⋰","Utilde":"Ũ","utilde":"ũ","utri":"▵","utrif":"▴","uuarr":"⇈","Uuml":"Ü","uuml":"ü","uwangle":"⦧","vangrt":"⦜","varepsilon":"ϵ","varkappa":"ϰ","varnothing":"∅","varphi":"ϕ","varpi":"ϖ","varpropto":"∝","varr":"↕","vArr":"⇕","varrho":"ϱ","varsigma":"ς","varsubsetneq":"⊊︀","varsubsetneqq":"⫋︀","varsupsetneq":"⊋︀","varsupsetneqq":"⫌︀","vartheta":"ϑ","vartriangleleft":"⊲","vartriangleright":"⊳","vBar":"⫨","Vbar":"⫫","vBarv":"⫩","Vcy":"В","vcy":"в","vdash":"⊢","vDash":"⊨","Vdash":"⊩","VDash":"⊫","Vdashl":"⫦","veebar":"⊻","vee":"∨","Vee":"⋁","veeeq":"≚","vellip":"⋮","verbar":"|","Verbar":"‖","vert":"|","Vert":"‖","VerticalBar":"∣","VerticalLine":"|","VerticalSeparator":"❘","VerticalTilde":"≀","VeryThinSpace":" ","Vfr":"𝔙","vfr":"𝔳","vltri":"⊲","vnsub":"⊂⃒","vnsup":"⊃⃒","Vopf":"𝕍","vopf":"𝕧","vprop":"∝","vrtri":"⊳","Vscr":"𝒱","vscr":"𝓋","vsubnE":"⫋︀","vsubne":"⊊︀","vsupnE":"⫌︀","vsupne":"⊋︀","Vvdash":"⊪","vzigzag":"⦚","Wcirc":"Ŵ","wcirc":"ŵ","wedbar":"⩟","wedge":"∧","Wedge":"⋀","wedgeq":"≙","weierp":"℘","Wfr":"𝔚","wfr":"𝔴","Wopf":"𝕎","wopf":"𝕨","wp":"℘","wr":"≀","wreath":"≀","Wscr":"𝒲","wscr":"𝓌","xcap":"⋂","xcirc":"◯","xcup":"⋃","xdtri":"▽","Xfr":"𝔛","xfr":"𝔵","xharr":"⟷","xhArr":"⟺","Xi":"Ξ","xi":"ξ","xlarr":"⟵","xlArr":"⟸","xmap":"⟼","xnis":"⋻","xodot":"⨀","Xopf":"𝕏","xopf":"𝕩","xoplus":"⨁","xotime":"⨂","xrarr":"⟶","xrArr":"⟹","Xscr":"𝒳","xscr":"𝓍","xsqcup":"⨆","xuplus":"⨄","xutri":"△","xvee":"⋁","xwedge":"⋀","Yacute":"Ý","yacute":"ý","YAcy":"Я","yacy":"я","Ycirc":"Ŷ","ycirc":"ŷ","Ycy":"Ы","ycy":"ы","yen":"¥","Yfr":"𝔜","yfr":"𝔶","YIcy":"Ї","yicy":"ї","Yopf":"𝕐","yopf":"𝕪","Yscr":"𝒴","yscr":"𝓎","YUcy":"Ю","yucy":"ю","yuml":"ÿ","Yuml":"Ÿ","Zacute":"Ź","zacute":"ź","Zcaron":"Ž","zcaron":"ž","Zcy":"З","zcy":"з","Zdot":"Ż","zdot":"ż","zeetrf":"ℨ","ZeroWidthSpace":"​","Zeta":"Ζ","zeta":"ζ","zfr":"𝔷","Zfr":"ℨ","ZHcy":"Ж","zhcy":"ж","zigrarr":"⇝","zopf":"𝕫","Zopf":"ℤ","Zscr":"𝒵","zscr":"𝓏","zwj":"‍","zwnj":"‌"}')},af30:function(e,t,r){"use strict";var n=r("0068").isWhiteSpace,s=r("0068").isPunctChar,o=r("0068").isMdAsciiPunct,i=/['"]/,a=/['"]/g,c="’";function u(e,t,r){return e.substr(0,t)+r+e.substr(t+1)}function l(e,t){var r,i,l,p,h,f,d,m,g,b,_,k,v,y,x,C,w,A,D,E,q;for(D=[],r=0;r=0;w--)if(D[w].level<=d)break;if(D.length=w+1,"text"===i.type){l=i.content,h=0,f=l.length;e:while(h=0)g=l.charCodeAt(p.index-1);else for(w=r-1;w>=0;w--){if("softbreak"===e[w].type||"hardbreak"===e[w].type)break;if(e[w].content){g=e[w].content.charCodeAt(e[w].content.length-1);break}}if(b=32,h=48&&g<=57&&(C=x=!1),x&&C&&(x=_,C=k),x||C){if(C)for(w=D.length-1;w>=0;w--){if(m=D[w],D[w].level=0;t--)"inline"===e.tokens[t].type&&i.test(e.tokens[t].content)&&l(e.tokens[t].children,e)}},b117:function(e,t,r){"use strict";e.exports=function(e){var t={};t.src_Any=r("cbc7").source,t.src_Cc=r("a7bc").source,t.src_Z=r("4fc2").source,t.src_P=r("7ca0").source,t.src_ZPCc=[t.src_Z,t.src_P,t.src_Cc].join("|"),t.src_ZCc=[t.src_Z,t.src_Cc].join("|");var n="[><|]";return t.src_pseudo_letter="(?:(?!"+n+"|"+t.src_ZPCc+")"+t.src_Any+")",t.src_ip4="(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)",t.src_auth="(?:(?:(?!"+t.src_ZCc+"|[@/\\[\\]()]).)+@)?",t.src_port="(?::(?:6(?:[0-4]\\d{3}|5(?:[0-4]\\d{2}|5(?:[0-2]\\d|3[0-5])))|[1-5]?\\d{1,4}))?",t.src_host_terminator="(?=$|"+n+"|"+t.src_ZPCc+")(?!-|_|:\\d|\\.-|\\.(?!$|"+t.src_ZPCc+"))",t.src_path="(?:[/?#](?:(?!"+t.src_ZCc+"|"+n+"|[()[\\]{}.,\"'?!\\-]).|\\[(?:(?!"+t.src_ZCc+"|\\]).)*\\]|\\((?:(?!"+t.src_ZCc+"|[)]).)*\\)|\\{(?:(?!"+t.src_ZCc+'|[}]).)*\\}|\\"(?:(?!'+t.src_ZCc+'|["]).)+\\"|\\\'(?:(?!'+t.src_ZCc+"|[']).)+\\'|\\'(?="+t.src_pseudo_letter+"|[-]).|\\.{2,}[a-zA-Z0-9%/&]|\\.(?!"+t.src_ZCc+"|[.]).|"+(e&&e["---"]?"\\-(?!--(?:[^-]|$))(?:-*)|":"\\-+|")+"\\,(?!"+t.src_ZCc+").|\\!+(?!"+t.src_ZCc+"|[!]).|\\?(?!"+t.src_ZCc+"|[?]).)+|\\/)?",t.src_email_name='[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]*',t.src_xn="xn--[a-z0-9\\-]{1,59}",t.src_domain_root="(?:"+t.src_xn+"|"+t.src_pseudo_letter+"{1,63})",t.src_domain="(?:"+t.src_xn+"|(?:"+t.src_pseudo_letter+")|(?:"+t.src_pseudo_letter+"(?:-|"+t.src_pseudo_letter+"){0,61}"+t.src_pseudo_letter+"))",t.src_host="(?:(?:(?:(?:"+t.src_domain+")\\.)*"+t.src_domain+"))",t.tpl_host_fuzzy="(?:"+t.src_ip4+"|(?:(?:(?:"+t.src_domain+")\\.)+(?:%TLDS%)))",t.tpl_host_no_ip_fuzzy="(?:(?:(?:"+t.src_domain+")\\.)+(?:%TLDS%))",t.src_host_strict=t.src_host+t.src_host_terminator,t.tpl_host_fuzzy_strict=t.tpl_host_fuzzy+t.src_host_terminator,t.src_host_port_strict=t.src_host+t.src_port+t.src_host_terminator,t.tpl_host_port_fuzzy_strict=t.tpl_host_fuzzy+t.src_port+t.src_host_terminator,t.tpl_host_port_no_ip_fuzzy_strict=t.tpl_host_no_ip_fuzzy+t.src_port+t.src_host_terminator,t.tpl_host_fuzzy_test="localhost|www\\.|\\.\\d{1,3}\\.|(?:\\.(?:%TLDS%)(?:"+t.src_ZPCc+"|>|$))",t.tpl_email_fuzzy="(^|"+n+'|"|\\(|'+t.src_ZCc+")("+t.src_email_name+"@"+t.tpl_host_fuzzy_strict+")",t.tpl_link_fuzzy="(^|(?![.:/\\-_@])(?:[$+<=>^`||]|"+t.src_ZPCc+"))((?![$+<=>^`||])"+t.tpl_host_port_fuzzy_strict+t.src_path+")",t.tpl_link_no_ip_fuzzy="(^|(?![.:/\\-_@])(?:[$+<=>^`||]|"+t.src_ZPCc+"))((?![$+<=>^`||])"+t.tpl_host_port_no_ip_fuzzy_strict+t.src_path+")",t}},b50d:function(e,t,r){"use strict";var n=r("c532"),s=r("467f"),o=r("7aac"),i=r("30b5"),a=r("83b9"),c=r("c345"),u=r("3934"),l=r("2d83");e.exports=function(e){return new Promise((function(t,r){var p=e.data,h=e.headers,f=e.responseType;n.isFormData(p)&&delete h["Content-Type"];var d=new XMLHttpRequest;if(e.auth){var m=e.auth.username||"",g=e.auth.password?unescape(encodeURIComponent(e.auth.password)):"";h.Authorization="Basic "+btoa(m+":"+g)}var b=a(e.baseURL,e.url);function _(){if(d){var n="getAllResponseHeaders"in d?c(d.getAllResponseHeaders()):null,o=f&&"text"!==f&&"json"!==f?d.response:d.responseText,i={data:o,status:d.status,statusText:d.statusText,headers:n,config:e,request:d};s(t,r,i),d=null}}if(d.open(e.method.toUpperCase(),i(b,e.params,e.paramsSerializer),!0),d.timeout=e.timeout,"onloadend"in d?d.onloadend=_:d.onreadystatechange=function(){d&&4===d.readyState&&(0!==d.status||d.responseURL&&0===d.responseURL.indexOf("file:"))&&setTimeout(_)},d.onabort=function(){d&&(r(l("Request aborted",e,"ECONNABORTED",d)),d=null)},d.onerror=function(){r(l("Network Error",e,null,d)),d=null},d.ontimeout=function(){var t="timeout of "+e.timeout+"ms exceeded";e.timeoutErrorMessage&&(t=e.timeoutErrorMessage),r(l(t,e,e.transitional&&e.transitional.clarifyTimeoutError?"ETIMEDOUT":"ECONNABORTED",d)),d=null},n.isStandardBrowserEnv()){var k=(e.withCredentials||u(b))&&e.xsrfCookieName?o.read(e.xsrfCookieName):void 0;k&&(h[e.xsrfHeaderName]=k)}"setRequestHeader"in d&&n.forEach(h,(function(e,t){"undefined"===typeof p&&"content-type"===t.toLowerCase()?delete h[t]:d.setRequestHeader(t,e)})),n.isUndefined(e.withCredentials)||(d.withCredentials=!!e.withCredentials),f&&"json"!==f&&(d.responseType=e.responseType),"function"===typeof e.onDownloadProgress&&d.addEventListener("progress",e.onDownloadProgress),"function"===typeof e.onUploadProgress&&d.upload&&d.upload.addEventListener("progress",e.onUploadProgress),e.cancelToken&&e.cancelToken.promise.then((function(e){d&&(d.abort(),r(e),d=null)})),p||(p=null),d.send(p)}))}},baca:function(e,t,r){"use strict";function n(e){switch(e){case 10:case 33:case 35:case 36:case 37:case 38:case 42:case 43:case 45:case 58:case 60:case 61:case 62:case 64:case 91:case 92:case 93:case 94:case 95:case 96:case 123:case 125:case 126:return!0;default:return!1}}e.exports=function(e,t){var r=e.pos;while(r=0;t--)r=e[t],"text"!==r.type||n||(r.content=r.content.replace(o,a)),"link_open"===r.type&&"auto"===r.info&&n--,"link_close"===r.type&&"auto"===r.info&&n++}function u(e){var t,r,s=0;for(t=e.length-1;t>=0;t--)r=e[t],"text"!==r.type||s||n.test(r.content)&&(r.content=r.content.replace(/\+-/g,"±").replace(/\.{2,}/g,"…").replace(/([?!])…/g,"$1..").replace(/([?!]){4,}/g,"$1$1$1").replace(/,{2,}/g,",").replace(/(^|[^-])---(?=[^-]|$)/gm,"$1—").replace(/(^|\s)--(?=\s|$)/gm,"$1–").replace(/(^|[^-\s])--(?=[^-\s]|$)/gm,"$1–")),"link_open"===r.type&&"auto"===r.info&&s--,"link_close"===r.type&&"auto"===r.info&&s++}e.exports=function(e){var t;if(e.md.options.typographer)for(t=e.tokens.length-1;t>=0;t--)"inline"===e.tokens[t].type&&(s.test(e.tokens[t].content)&&c(e.tokens[t].children),n.test(e.tokens[t].content)&&u(e.tokens[t].children))}},bc3a:function(e,t,r){e.exports=r("cee4")},bd68:function(e,t,r){"use strict";e.exports=r("aced")},bf2b:function(e,t,r){"use strict";e.exports=function(e,t,r,n){var s,o,i,a,c,u,l,p=!1,h=e.bMarks[t]+e.tShift[t],f=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4)return!1;if(h+3>f)return!1;if(s=e.src.charCodeAt(h),126!==s&&96!==s)return!1;if(c=h,h=e.skipChars(h,s),o=h-c,o<3)return!1;if(l=e.src.slice(c,h),i=e.src.slice(h,f),96===s&&i.indexOf(String.fromCharCode(s))>=0)return!1;if(n)return!0;for(a=t;;){if(a++,a>=r)break;if(h=c=e.bMarks[a]+e.tShift[a],f=e.eMarks[a],h=4)&&(h=e.skipChars(h,s),!(h-c=97&&t<=122}e.exports=function(e,t){var r,o,i,a,c=e.pos;return!!e.md.options.html&&(i=e.posMax,!(60!==e.src.charCodeAt(c)||c+2>=i)&&(r=e.src.charCodeAt(c+1),!(33!==r&&63!==r&&47!==r&&!s(r))&&(o=e.src.slice(c).match(n),!!o&&(t||(a=e.push("html_inline","",0),a.content=e.src.slice(c,c+o[0].length)),e.pos+=o[0].length,!0))))}},c345:function(e,t,r){"use strict";var n=r("c532"),s=["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"];e.exports=function(e){var t,r,o,i={};return e?(n.forEach(e.split("\n"),(function(e){if(o=e.indexOf(":"),t=n.trim(e.substr(0,o)).toLowerCase(),r=n.trim(e.substr(o+1)),t){if(i[t]&&s.indexOf(t)>=0)return;i[t]="set-cookie"===t?(i[t]?i[t]:[]).concat([r]):i[t]?i[t]+", "+r:r}})),i):i}},c401:function(e,t,r){"use strict";var n=r("c532"),s=r("2444");e.exports=function(e,t,r){var o=this||s;return n.forEach(r,(function(r){e=r.call(o,e,t)})),e}},c464:function(e,t,r){"use strict";var n={};function s(e){var t,r,s=n[e];if(s)return s;for(s=n[e]=[],t=0;t<128;t++)r=String.fromCharCode(t),/^[0-9a-z]$/i.test(r)?s.push(r):s.push("%"+("0"+t.toString(16).toUpperCase()).slice(-2));for(t=0;t=55296&&a<=57343){if(a>=55296&&a<=56319&&n+1=56320&&c<=57343)){l+=encodeURIComponent(e[n]+e[n+1]),n++;continue}l+="%EF%BF%BD"}else l+=encodeURIComponent(e[n]);return l}o.defaultChars=";/?:@&=+$,-_.!~*'()#",o.componentChars="-_.!~*'()",e.exports=o},c532:function(e,t,r){"use strict";var n=r("1d2b"),s=Object.prototype.toString;function o(e){return"[object Array]"===s.call(e)}function i(e){return"undefined"===typeof e}function a(e){return null!==e&&!i(e)&&null!==e.constructor&&!i(e.constructor)&&"function"===typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)}function c(e){return"[object ArrayBuffer]"===s.call(e)}function u(e){return"undefined"!==typeof FormData&&e instanceof FormData}function l(e){var t;return t="undefined"!==typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&e.buffer instanceof ArrayBuffer,t}function p(e){return"string"===typeof e}function h(e){return"number"===typeof e}function f(e){return null!==e&&"object"===typeof e}function d(e){if("[object Object]"!==s.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function m(e){return"[object Date]"===s.call(e)}function g(e){return"[object File]"===s.call(e)}function b(e){return"[object Blob]"===s.call(e)}function _(e){return"[object Function]"===s.call(e)}function k(e){return f(e)&&_(e.pipe)}function v(e){return"undefined"!==typeof URLSearchParams&&e instanceof URLSearchParams}function y(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function x(){return("undefined"===typeof navigator||"ReactNative"!==navigator.product&&"NativeScript"!==navigator.product&&"NS"!==navigator.product)&&("undefined"!==typeof window&&"undefined"!==typeof document)}function C(e,t){if(null!==e&&"undefined"!==typeof e)if("object"!==typeof e&&(e=[e]),o(e))for(var r=0,n=e.length;r=0;r--)n=t[r],95!==n.marker&&42!==n.marker||-1!==n.end&&(s=t[n.end],a=r>0&&t[r-1].end===n.end+1&&t[r-1].marker===n.marker&&t[r-1].token===n.token-1&&t[n.end+1].token===s.token+1,i=String.fromCharCode(n.marker),o=e.tokens[n.token],o.type=a?"strong_open":"em_open",o.tag=a?"strong":"em",o.nesting=1,o.markup=a?i+i:i,o.content="",o=e.tokens[s.token],o.type=a?"strong_close":"em_close",o.tag=a?"strong":"em",o.nesting=-1,o.markup=a?i+i:i,o.content="",a&&(e.tokens[t[r-1].token].content="",e.tokens[t[n.end+1].token].content="",r--))}e.exports.tokenize=function(e,t){var r,n,s,o=e.pos,i=e.src.charCodeAt(o);if(t)return!1;if(95!==i&&42!==i)return!1;for(n=e.scanDelims(e.pos,42===i),r=0;r=g)return!1;if(b=u,l=e.md.helpers.parseLinkDestination(e.src,u,e.posMax),l.ok){for(f=e.md.normalizeLink(l.str),e.md.validateLink(f)?u=l.pos:f="",b=u;u=g||41!==e.src.charCodeAt(u))&&(_=!0),u++}if(_){if("undefined"===typeof e.env.references)return!1;if(u=0?i=e.src.slice(b,u++):u=a+1):u=a+1,i||(i=e.src.slice(c,a)),p=e.env.references[n(i)],!p)return e.pos=m,!1;f=p.href,d=p.title}return t||(e.pos=c,e.posMax=a,h=e.push("link_open","a",1),h.attrs=r=[["href",f]],d&&r.push(["title",d]),e.md.inline.tokenize(e),h=e.push("link_close","a",-1)),e.pos=u,e.posMax=g,!0}},cee4:function(e,t,r){"use strict";var n=r("c532"),s=r("1d2b"),o=r("0a06"),i=r("4a7b"),a=r("2444");function c(e){var t=new o(e),r=s(o.prototype.request,t);return n.extend(r,o.prototype,t),n.extend(r,t),r}var u=c(a);u.Axios=o,u.create=function(e){return c(i(u.defaults,e))},u.Cancel=r("7a77"),u.CancelToken=r("8df4"),u.isCancel=r("2e67"),u.all=function(e){return Promise.all(e)},u.spread=r("0df6"),u.isAxiosError=r("5f02"),e.exports=u,e.exports.default=u},d4cd:function(e,t,r){"use strict";e.exports=r("08ae")},d5d1:function(e,t,r){"use strict";t.Any=r("cbc7"),t.Cc=r("a7bc"),t.Cf=r("6fd1"),t.P=r("7ca0"),t.Z=r("4fc2")},d670:function(e,t,r){"use strict";var n=r("0068").normalizeReference,s=r("0068").isSpace;e.exports=function(e,t,r,o){var i,a,c,u,l,p,h,f,d,m,g,b,_,k,v,y,x=0,C=e.bMarks[t]+e.tShift[t],w=e.eMarks[t],A=t+1;if(e.sCount[t]-e.blkIndent>=4)return!1;if(91!==e.src.charCodeAt(C))return!1;while(++C3)&&!(e.sCount[A]<0)){for(k=!1,p=0,h=v.length;p",'"',"`"," ","\r","\n","\t"],c=["{","}","|","\\","^","`"].concat(a),u=["'"].concat(c),l=["%","/","?",";","#"].concat(u),p=["/","?","#"],h=255,f=/^[+a-z0-9A-Z_-]{0,63}$/,d=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,m={javascript:!0,"javascript:":!0},g={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0};function b(e,t){if(e&&e instanceof n)return e;var r=new n;return r.parse(e,t),r}n.prototype.parse=function(e,t){var r,n,o,a,c,u=e;if(u=u.trim(),!t&&1===e.split("#").length){var b=i.exec(u);if(b)return this.pathname=b[1],b[2]&&(this.search=b[2]),this}var _=s.exec(u);if(_&&(_=_[0],o=_.toLowerCase(),this.protocol=_,u=u.substr(_.length)),(t||_||u.match(/^\/\/[^@\/]+@[^@\/]+/))&&(c="//"===u.substr(0,2),!c||_&&m[_]||(u=u.substr(2),this.slashes=!0)),!m[_]&&(c||_&&!g[_])){var k,v,y=-1;for(r=0;r127?D+="x":D+=A[E];if(!D.match(f)){var S=w.slice(0,r),F=w.slice(r+1),L=A.match(d);L&&(S.push(L[1]),F.unshift(L[2])),F.length&&(u=F.join(".")+u),this.hostname=S.join(".");break}}}}this.hostname.length>h&&(this.hostname=""),C&&(this.hostname=this.hostname.substr(1,this.hostname.length-2))}var T=u.indexOf("#");-1!==T&&(this.hash=u.substr(T),u=u.slice(0,T));var z=u.indexOf("?");return-1!==z&&(this.search=u.substr(z),u=u.slice(0,z)),u&&(this.pathname=u),g[o]&&this.hostname&&!this.pathname&&(this.pathname=""),this},n.prototype.parseHost=function(e){var t=o.exec(e);t&&(t=t[0],":"!==t&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)},e.exports=b},df56:function(e,t,r){"use strict";e.exports=function(e,t,r){var n,s,o,i,a=-1,c=e.posMax,u=e.pos;e.pos=t+1,n=1;while(e.pos32))return c;if(41===s){if(0===o)break;o--}t++}}return a===t||0!==o||(c.str=n(e.slice(a,t)),c.lines=i,c.pos=t,c.ok=!0),c}},e683:function(e,t,r){"use strict";e.exports=function(e,t){return t?e.replace(/\/+$/,"")+"/"+t.replace(/^\/+/,""):e}},e80e:function(e,t,r){"use strict";var n=r("0068").isSpace;e.exports=function(e,t,r,s){var o,i,a,c,u,l,p,h,f,d,m,g,b,_,k,v,y,x,C,w,A=e.lineMax,D=e.bMarks[t]+e.tShift[t],E=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4)return!1;if(62!==e.src.charCodeAt(D++))return!1;if(s)return!0;c=f=e.sCount[t]+1,32===e.src.charCodeAt(D)?(D++,c++,f++,o=!1,v=!0):9===e.src.charCodeAt(D)?(v=!0,(e.bsCount[t]+f)%4===3?(D++,c++,f++,o=!1):o=!0):v=!1,d=[e.bMarks[t]],e.bMarks[t]=D;while(D=E,_=[e.sCount[t]],e.sCount[t]=f-c,k=[e.tShift[t]],e.tShift[t]=D-e.bMarks[t],x=e.md.block.ruler.getRules("blockquote"),b=e.parentType,e.parentType="blockquote",h=t+1;h=E)break;if(62!==e.src.charCodeAt(D++)||w){if(l)break;for(y=!1,a=0,u=x.length;a=E,m.push(e.bsCount[h]),e.bsCount[h]=e.sCount[h]+1+(v?1:0),_.push(e.sCount[h]),e.sCount[h]=f-c,k.push(e.tShift[h]),e.tShift[h]=D-e.bMarks[h]}}for(g=e.blkIndent,e.blkIndent=0,C=e.push("blockquote_open","blockquote",1),C.markup=">",C.map=p=[t,0],e.md.block.tokenize(e,t,h),C=e.push("blockquote_close","blockquote",-1),C.markup=">",e.lineMax=A,e.parentType=b,p[1]=e.line,a=0;a=3&&":"===e[t-3]||t>=3&&"/"===e[t-3]?0:n.match(r.re.no_http)[0].length:0}},"mailto:":{validate:function(e,t,r){var n=e.slice(t);return r.re.mailto||(r.re.mailto=new RegExp("^"+r.re.src_email_name+"@"+r.re.src_host_strict,"i")),r.re.mailto.test(n)?n.match(r.re.mailto)[0].length:0}}},f="a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvwxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]",d="biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф".split("|");function m(e){e.__index__=-1,e.__text_cache__=""}function g(e){return function(t,r){var n=t.slice(r);return e.test(n)?n.match(e)[0].length:0}}function b(){return function(e,t){t.normalize(e)}}function _(e){var t=e.re=r("b117")(e.__opts__),n=e.__tlds__.slice();function s(e){return e.replace("%TLDS%",t.src_tlds)}e.onCompile(),e.__tlds_replaced__||n.push(f),n.push(t.src_xn),t.src_tlds=n.join("|"),t.email_fuzzy=RegExp(s(t.tpl_email_fuzzy),"i"),t.link_fuzzy=RegExp(s(t.tpl_link_fuzzy),"i"),t.link_no_ip_fuzzy=RegExp(s(t.tpl_link_no_ip_fuzzy),"i"),t.host_fuzzy_test=RegExp(s(t.tpl_host_fuzzy_test),"i");var l=[];function p(e,t){throw new Error('(LinkifyIt) Invalid schema "'+e+'": '+t)}e.__compiled__={},Object.keys(e.__schemas__).forEach((function(t){var r=e.__schemas__[t];if(null!==r){var n={validate:null,link:null};if(e.__compiled__[t]=n,i(r))return a(r.validate)?n.validate=g(r.validate):c(r.validate)?n.validate=r.validate:p(t,r),void(c(r.normalize)?n.normalize=r.normalize:r.normalize?p(t,r):n.normalize=b());o(r)?l.push(t):p(t,r)}})),l.forEach((function(t){e.__compiled__[e.__schemas__[t]]&&(e.__compiled__[t].validate=e.__compiled__[e.__schemas__[t]].validate,e.__compiled__[t].normalize=e.__compiled__[e.__schemas__[t]].normalize)})),e.__compiled__[""]={validate:null,normalize:b()};var h=Object.keys(e.__compiled__).filter((function(t){return t.length>0&&e.__compiled__[t]})).map(u).join("|");e.re.schema_test=RegExp("(^|(?!_)(?:[><|]|"+t.src_ZPCc+"))("+h+")","i"),e.re.schema_search=RegExp("(^|(?!_)(?:[><|]|"+t.src_ZPCc+"))("+h+")","ig"),e.re.pretest=RegExp("("+e.re.schema_test.source+")|("+e.re.host_fuzzy_test.source+")|@","i"),m(e)}function k(e,t){var r=e.__index__,n=e.__last_index__,s=e.__text_cache__.slice(r,n);this.schema=e.__schema__.toLowerCase(),this.index=r+t,this.lastIndex=n+t,this.raw=s,this.text=s,this.url=s}function v(e,t){var r=new k(e,t);return e.__compiled__[r.schema].normalize(r,e),r}function y(e,t){if(!(this instanceof y))return new y(e,t);t||p(e)&&(t=e,e={}),this.__opts__=n({},l,t),this.__index__=-1,this.__last_index__=-1,this.__schema__="",this.__text_cache__="",this.__schemas__=n({},h,e),this.__compiled__={},this.__tlds__=d,this.__tlds_replaced__=!1,this.re={},_(this)}y.prototype.add=function(e,t){return this.__schemas__[e]=t,_(this),this},y.prototype.set=function(e){return this.__opts__=n(this.__opts__,e),this},y.prototype.test=function(e){if(this.__text_cache__=e,this.__index__=-1,!e.length)return!1;var t,r,n,s,o,i,a,c,u;if(this.re.schema_test.test(e)){a=this.re.schema_search,a.lastIndex=0;while(null!==(t=a.exec(e)))if(s=this.testSchemaAt(e,t[2],a.lastIndex),s){this.__schema__=t[2],this.__index__=t.index+t[1].length,this.__last_index__=t.index+t[0].length+s;break}}return this.__opts__.fuzzyLink&&this.__compiled__["http:"]&&(c=e.search(this.re.host_fuzzy_test),c>=0&&(this.__index__<0||c=0&&null!==(n=e.match(this.re.email_fuzzy))&&(o=n.index+n[1].length,i=n.index+n[0].length,(this.__index__<0||othis.__last_index__)&&(this.__schema__="mailto:",this.__index__=o,this.__last_index__=i))),this.__index__>=0},y.prototype.pretest=function(e){return this.re.pretest.test(e)},y.prototype.testSchemaAt=function(e,t,r){return this.__compiled__[t.toLowerCase()]?this.__compiled__[t.toLowerCase()].validate(e,r,this):0},y.prototype.match=function(e){var t=0,r=[];this.__index__>=0&&this.__text_cache__===e&&(r.push(v(this,t)),t=this.__last_index__);var n=t?e.slice(t):e;while(this.test(n))r.push(v(this,t)),n=n.slice(this.__last_index__),t+=this.__last_index__;return r.length?r:null},y.prototype.tlds=function(e,t){return e=Array.isArray(e)?e:[e],t?(this.__tlds__=this.__tlds__.concat(e).sort().filter((function(e,t,r){return e!==r[t-1]})).reverse(),_(this),this):(this.__tlds__=e.slice(),this.__tlds_replaced__=!0,_(this),this)},y.prototype.normalize=function(e){e.schema||(e.url="http://"+e.url),"mailto:"!==e.schema||/^mailto:/i.test(e.url)||(e.url="mailto:"+e.url)},y.prototype.onCompile=function(){},e.exports=y},fdfe:function(e,t,r){"use strict";var n=r("0068").isSpace;e.exports=function(e,t,r,s){var o,i,a,c,u=e.bMarks[t]+e.tShift[t],l=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4)return!1;if(o=e.src.charCodeAt(u++),42!==o&&45!==o&&95!==o)return!1;i=1;while(u= 0xD800 && c <= 0xDFFF) { return false; }\n // never used\n if (c >= 0xFDD0 && c <= 0xFDEF) { return false; }\n if ((c & 0xFFFF) === 0xFFFF || (c & 0xFFFF) === 0xFFFE) { return false; }\n // control codes\n if (c >= 0x00 && c <= 0x08) { return false; }\n if (c === 0x0B) { return false; }\n if (c >= 0x0E && c <= 0x1F) { return false; }\n if (c >= 0x7F && c <= 0x9F) { return false; }\n // out of range\n if (c > 0x10FFFF) { return false; }\n return true;\n}\n\nfunction fromCodePoint(c) {\n /*eslint no-bitwise:0*/\n if (c > 0xffff) {\n c -= 0x10000;\n var surrogate1 = 0xd800 + (c >> 10),\n surrogate2 = 0xdc00 + (c & 0x3ff);\n\n return String.fromCharCode(surrogate1, surrogate2);\n }\n return String.fromCharCode(c);\n}\n\n\nvar UNESCAPE_MD_RE = /\\\\([!\"#$%&'()*+,\\-.\\/:;<=>?@[\\\\\\]^_`{|}~])/g;\nvar ENTITY_RE = /&([a-z#][a-z0-9]{1,31});/gi;\nvar UNESCAPE_ALL_RE = new RegExp(UNESCAPE_MD_RE.source + '|' + ENTITY_RE.source, 'gi');\n\nvar DIGITAL_ENTITY_TEST_RE = /^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))/i;\n\nvar entities = require('./entities');\n\nfunction replaceEntityPattern(match, name) {\n var code = 0;\n\n if (has(entities, name)) {\n return entities[name];\n }\n\n if (name.charCodeAt(0) === 0x23/* # */ && DIGITAL_ENTITY_TEST_RE.test(name)) {\n code = name[1].toLowerCase() === 'x' ?\n parseInt(name.slice(2), 16) : parseInt(name.slice(1), 10);\n\n if (isValidEntityCode(code)) {\n return fromCodePoint(code);\n }\n }\n\n return match;\n}\n\n/*function replaceEntities(str) {\n if (str.indexOf('&') < 0) { return str; }\n\n return str.replace(ENTITY_RE, replaceEntityPattern);\n}*/\n\nfunction unescapeMd(str) {\n if (str.indexOf('\\\\') < 0) { return str; }\n return str.replace(UNESCAPE_MD_RE, '$1');\n}\n\nfunction unescapeAll(str) {\n if (str.indexOf('\\\\') < 0 && str.indexOf('&') < 0) { return str; }\n\n return str.replace(UNESCAPE_ALL_RE, function (match, escaped, entity) {\n if (escaped) { return escaped; }\n return replaceEntityPattern(match, entity);\n });\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nvar HTML_ESCAPE_TEST_RE = /[&<>\"]/;\nvar HTML_ESCAPE_REPLACE_RE = /[&<>\"]/g;\nvar HTML_REPLACEMENTS = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"'\n};\n\nfunction replaceUnsafeChar(ch) {\n return HTML_REPLACEMENTS[ch];\n}\n\nfunction escapeHtml(str) {\n if (HTML_ESCAPE_TEST_RE.test(str)) {\n return str.replace(HTML_ESCAPE_REPLACE_RE, replaceUnsafeChar);\n }\n return str;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nvar REGEXP_ESCAPE_RE = /[.?*+^$[\\]\\\\(){}|-]/g;\n\nfunction escapeRE(str) {\n return str.replace(REGEXP_ESCAPE_RE, '\\\\$&');\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nfunction isSpace(code) {\n switch (code) {\n case 0x09:\n case 0x20:\n return true;\n }\n return false;\n}\n\n// Zs (unicode class) || [\\t\\f\\v\\r\\n]\nfunction isWhiteSpace(code) {\n if (code >= 0x2000 && code <= 0x200A) { return true; }\n switch (code) {\n case 0x09: // \\t\n case 0x0A: // \\n\n case 0x0B: // \\v\n case 0x0C: // \\f\n case 0x0D: // \\r\n case 0x20:\n case 0xA0:\n case 0x1680:\n case 0x202F:\n case 0x205F:\n case 0x3000:\n return true;\n }\n return false;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\n/*eslint-disable max-len*/\nvar UNICODE_PUNCT_RE = require('uc.micro/categories/P/regex');\n\n// Currently without astral characters support.\nfunction isPunctChar(ch) {\n return UNICODE_PUNCT_RE.test(ch);\n}\n\n\n// Markdown ASCII punctuation characters.\n//\n// !, \", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \\, ], ^, _, `, {, |, }, or ~\n// http://spec.commonmark.org/0.15/#ascii-punctuation-character\n//\n// Don't confuse with unicode punctuation !!! It lacks some chars in ascii range.\n//\nfunction isMdAsciiPunct(ch) {\n switch (ch) {\n case 0x21/* ! */:\n case 0x22/* \" */:\n case 0x23/* # */:\n case 0x24/* $ */:\n case 0x25/* % */:\n case 0x26/* & */:\n case 0x27/* ' */:\n case 0x28/* ( */:\n case 0x29/* ) */:\n case 0x2A/* * */:\n case 0x2B/* + */:\n case 0x2C/* , */:\n case 0x2D/* - */:\n case 0x2E/* . */:\n case 0x2F/* / */:\n case 0x3A/* : */:\n case 0x3B/* ; */:\n case 0x3C/* < */:\n case 0x3D/* = */:\n case 0x3E/* > */:\n case 0x3F/* ? */:\n case 0x40/* @ */:\n case 0x5B/* [ */:\n case 0x5C/* \\ */:\n case 0x5D/* ] */:\n case 0x5E/* ^ */:\n case 0x5F/* _ */:\n case 0x60/* ` */:\n case 0x7B/* { */:\n case 0x7C/* | */:\n case 0x7D/* } */:\n case 0x7E/* ~ */:\n return true;\n default:\n return false;\n }\n}\n\n// Hepler to unify [reference labels].\n//\nfunction normalizeReference(str) {\n // Trim and collapse whitespace\n //\n str = str.trim().replace(/\\s+/g, ' ');\n\n // In node v10 'ẞ'.toLowerCase() === 'Ṿ', which is presumed to be a bug\n // fixed in v12 (couldn't find any details).\n //\n // So treat this one as a special case\n // (remove this when node v10 is no longer supported).\n //\n if ('ẞ'.toLowerCase() === 'Ṿ') {\n str = str.replace(/ẞ/g, 'ß');\n }\n\n // .toLowerCase().toUpperCase() should get rid of all differences\n // between letter variants.\n //\n // Simple .toLowerCase() doesn't normalize 125 code points correctly,\n // and .toUpperCase doesn't normalize 6 of them (list of exceptions:\n // İ, ϴ, ẞ, Ω, K, Å - those are already uppercased, but have differently\n // uppercased versions).\n //\n // Here's an example showing how it happens. Lets take greek letter omega:\n // uppercase U+0398 (Θ), U+03f4 (ϴ) and lowercase U+03b8 (θ), U+03d1 (ϑ)\n //\n // Unicode entries:\n // 0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8;\n // 03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398\n // 03D1;GREEK THETA SYMBOL;Ll;0;L; 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398\n // 03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L; 0398;;;;N;;;;03B8;\n //\n // Case-insensitive comparison should treat all of them as equivalent.\n //\n // But .toLowerCase() doesn't change ϑ (it's already lowercase),\n // and .toUpperCase() doesn't change ϴ (already uppercase).\n //\n // Applying first lower then upper case normalizes any character:\n // '\\u0398\\u03f4\\u03b8\\u03d1'.toLowerCase().toUpperCase() === '\\u0398\\u0398\\u0398\\u0398'\n //\n // Note: this is equivalent to unicode case folding; unicode normalization\n // is a different step that is not required here.\n //\n // Final result should be uppercased, because it's later stored in an object\n // (this avoid a conflict with Object.prototype members,\n // most notably, `__proto__`)\n //\n return str.toLowerCase().toUpperCase();\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\n// Re-export libraries commonly used in both markdown-it and its plugins,\n// so plugins won't have to depend on them explicitly, which reduces their\n// bundled size (e.g. a browser build).\n//\nexports.lib = {};\nexports.lib.mdurl = require('mdurl');\nexports.lib.ucmicro = require('uc.micro');\n\nexports.assign = assign;\nexports.isString = isString;\nexports.has = has;\nexports.unescapeMd = unescapeMd;\nexports.unescapeAll = unescapeAll;\nexports.isValidEntityCode = isValidEntityCode;\nexports.fromCodePoint = fromCodePoint;\n// exports.replaceEntities = replaceEntities;\nexports.escapeHtml = escapeHtml;\nexports.arrayReplaceAt = arrayReplaceAt;\nexports.isSpace = isSpace;\nexports.isWhiteSpace = isWhiteSpace;\nexports.isMdAsciiPunct = isMdAsciiPunct;\nexports.isPunctChar = isPunctChar;\nexports.escapeRE = escapeRE;\nexports.normalizeReference = normalizeReference;\n","// heading (#, ##, ...)\n\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\n\nmodule.exports = function heading(state, startLine, endLine, silent) {\n var ch, level, tmp, token,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine];\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n ch = state.src.charCodeAt(pos);\n\n if (ch !== 0x23/* # */ || pos >= max) { return false; }\n\n // count heading level\n level = 1;\n ch = state.src.charCodeAt(++pos);\n while (ch === 0x23/* # */ && pos < max && level <= 6) {\n level++;\n ch = state.src.charCodeAt(++pos);\n }\n\n if (level > 6 || (pos < max && !isSpace(ch))) { return false; }\n\n if (silent) { return true; }\n\n // Let's cut tails like ' ### ' from the end of string\n\n max = state.skipSpacesBack(max, pos);\n tmp = state.skipCharsBack(max, 0x23, pos); // #\n if (tmp > pos && isSpace(state.src.charCodeAt(tmp - 1))) {\n max = tmp;\n }\n\n state.line = startLine + 1;\n\n token = state.push('heading_open', 'h' + String(level), 1);\n token.markup = '########'.slice(0, level);\n token.map = [ startLine, state.line ];\n\n token = state.push('inline', '', 0);\n token.content = state.src.slice(pos, max).trim();\n token.map = [ startLine, state.line ];\n token.children = [];\n\n token = state.push('heading_close', 'h' + String(level), -1);\n token.markup = '########'.slice(0, level);\n\n return true;\n};\n","// Main parser class\n\n'use strict';\n\n\nvar utils = require('./common/utils');\nvar helpers = require('./helpers');\nvar Renderer = require('./renderer');\nvar ParserCore = require('./parser_core');\nvar ParserBlock = require('./parser_block');\nvar ParserInline = require('./parser_inline');\nvar LinkifyIt = require('linkify-it');\nvar mdurl = require('mdurl');\nvar punycode = require('punycode');\n\n\nvar config = {\n default: require('./presets/default'),\n zero: require('./presets/zero'),\n commonmark: require('./presets/commonmark')\n};\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// This validator can prohibit more than really needed to prevent XSS. It's a\n// tradeoff to keep code simple and to be secure by default.\n//\n// If you need different setup - override validator method as you wish. Or\n// replace it with dummy function and use external sanitizer.\n//\n\nvar BAD_PROTO_RE = /^(vbscript|javascript|file|data):/;\nvar GOOD_DATA_RE = /^data:image\\/(gif|png|jpeg|webp);/;\n\nfunction validateLink(url) {\n // url should be normalized at this point, and existing entities are decoded\n var str = url.trim().toLowerCase();\n\n return BAD_PROTO_RE.test(str) ? (GOOD_DATA_RE.test(str) ? true : false) : true;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\n\nvar RECODE_HOSTNAME_FOR = [ 'http:', 'https:', 'mailto:' ];\n\nfunction normalizeLink(url) {\n var parsed = mdurl.parse(url, true);\n\n if (parsed.hostname) {\n // Encode hostnames in urls like:\n // `http://host/`, `https://host/`, `mailto:user@host`, `//host/`\n //\n // We don't encode unknown schemas, because it's likely that we encode\n // something we shouldn't (e.g. `skype:name` treated as `skype:host`)\n //\n if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) {\n try {\n parsed.hostname = punycode.toASCII(parsed.hostname);\n } catch (er) { /**/ }\n }\n }\n\n return mdurl.encode(mdurl.format(parsed));\n}\n\nfunction normalizeLinkText(url) {\n var parsed = mdurl.parse(url, true);\n\n if (parsed.hostname) {\n // Encode hostnames in urls like:\n // `http://host/`, `https://host/`, `mailto:user@host`, `//host/`\n //\n // We don't encode unknown schemas, because it's likely that we encode\n // something we shouldn't (e.g. `skype:name` treated as `skype:host`)\n //\n if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) {\n try {\n parsed.hostname = punycode.toUnicode(parsed.hostname);\n } catch (er) { /**/ }\n }\n }\n\n // add '%' to exclude list because of https://github.com/markdown-it/markdown-it/issues/720\n return mdurl.decode(mdurl.format(parsed), mdurl.decode.defaultChars + '%');\n}\n\n\n/**\n * class MarkdownIt\n *\n * Main parser/renderer class.\n *\n * ##### Usage\n *\n * ```javascript\n * // node.js, \"classic\" way:\n * var MarkdownIt = require('markdown-it'),\n * md = new MarkdownIt();\n * var result = md.render('# markdown-it rulezz!');\n *\n * // node.js, the same, but with sugar:\n * var md = require('markdown-it')();\n * var result = md.render('# markdown-it rulezz!');\n *\n * // browser without AMD, added to \"window\" on script load\n * // Note, there are no dash.\n * var md = window.markdownit();\n * var result = md.render('# markdown-it rulezz!');\n * ```\n *\n * Single line rendering, without paragraph wrap:\n *\n * ```javascript\n * var md = require('markdown-it')();\n * var result = md.renderInline('__markdown-it__ rulezz!');\n * ```\n **/\n\n/**\n * new MarkdownIt([presetName, options])\n * - presetName (String): optional, `commonmark` / `zero`\n * - options (Object)\n *\n * Creates parser instanse with given config. Can be called without `new`.\n *\n * ##### presetName\n *\n * MarkdownIt provides named presets as a convenience to quickly\n * enable/disable active syntax rules and options for common use cases.\n *\n * - [\"commonmark\"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/commonmark.js) -\n * configures parser to strict [CommonMark](http://commonmark.org/) mode.\n * - [default](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/default.js) -\n * similar to GFM, used when no preset name given. Enables all available rules,\n * but still without html, typographer & autolinker.\n * - [\"zero\"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/zero.js) -\n * all rules disabled. Useful to quickly setup your config via `.enable()`.\n * For example, when you need only `bold` and `italic` markup and nothing else.\n *\n * ##### options:\n *\n * - __html__ - `false`. Set `true` to enable HTML tags in source. Be careful!\n * That's not safe! You may need external sanitizer to protect output from XSS.\n * It's better to extend features via plugins, instead of enabling HTML.\n * - __xhtmlOut__ - `false`. Set `true` to add '/' when closing single tags\n * (`
`). This is needed only for full CommonMark compatibility. In real\n * world you will need HTML output.\n * - __breaks__ - `false`. Set `true` to convert `\\n` in paragraphs into `
`.\n * - __langPrefix__ - `language-`. CSS language class prefix for fenced blocks.\n * Can be useful for external highlighters.\n * - __linkify__ - `false`. Set `true` to autoconvert URL-like text to links.\n * - __typographer__ - `false`. Set `true` to enable [some language-neutral\n * replacement](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.js) +\n * quotes beautification (smartquotes).\n * - __quotes__ - `“”‘’`, String or Array. Double + single quotes replacement\n * pairs, when typographer enabled and smartquotes on. For example, you can\n * use `'«»„“'` for Russian, `'„“‚‘'` for German, and\n * `['«\\xA0', '\\xA0»', '‹\\xA0', '\\xA0›']` for French (including nbsp).\n * - __highlight__ - `null`. Highlighter function for fenced code blocks.\n * Highlighter `function (str, lang)` should return escaped HTML. It can also\n * return empty string if the source was not changed and should be escaped\n * externaly. If result starts with `):\n *\n * ```javascript\n * var hljs = require('highlight.js') // https://highlightjs.org/\n *\n * // Actual default values\n * var md = require('markdown-it')({\n * highlight: function (str, lang) {\n * if (lang && hljs.getLanguage(lang)) {\n * try {\n * return '
' +\n *                hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +\n *                '
';\n * } catch (__) {}\n * }\n *\n * return '
' + md.utils.escapeHtml(str) + '
';\n * }\n * });\n * ```\n *\n **/\nfunction MarkdownIt(presetName, options) {\n if (!(this instanceof MarkdownIt)) {\n return new MarkdownIt(presetName, options);\n }\n\n if (!options) {\n if (!utils.isString(presetName)) {\n options = presetName || {};\n presetName = 'default';\n }\n }\n\n /**\n * MarkdownIt#inline -> ParserInline\n *\n * Instance of [[ParserInline]]. You may need it to add new rules when\n * writing plugins. For simple rules control use [[MarkdownIt.disable]] and\n * [[MarkdownIt.enable]].\n **/\n this.inline = new ParserInline();\n\n /**\n * MarkdownIt#block -> ParserBlock\n *\n * Instance of [[ParserBlock]]. You may need it to add new rules when\n * writing plugins. For simple rules control use [[MarkdownIt.disable]] and\n * [[MarkdownIt.enable]].\n **/\n this.block = new ParserBlock();\n\n /**\n * MarkdownIt#core -> Core\n *\n * Instance of [[Core]] chain executor. You may need it to add new rules when\n * writing plugins. For simple rules control use [[MarkdownIt.disable]] and\n * [[MarkdownIt.enable]].\n **/\n this.core = new ParserCore();\n\n /**\n * MarkdownIt#renderer -> Renderer\n *\n * Instance of [[Renderer]]. Use it to modify output look. Or to add rendering\n * rules for new token types, generated by plugins.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')();\n *\n * function myToken(tokens, idx, options, env, self) {\n * //...\n * return result;\n * };\n *\n * md.renderer.rules['my_token'] = myToken\n * ```\n *\n * See [[Renderer]] docs and [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js).\n **/\n this.renderer = new Renderer();\n\n /**\n * MarkdownIt#linkify -> LinkifyIt\n *\n * [linkify-it](https://github.com/markdown-it/linkify-it) instance.\n * Used by [linkify](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/linkify.js)\n * rule.\n **/\n this.linkify = new LinkifyIt();\n\n /**\n * MarkdownIt#validateLink(url) -> Boolean\n *\n * Link validation function. CommonMark allows too much in links. By default\n * we disable `javascript:`, `vbscript:`, `file:` schemas, and almost all `data:...` schemas\n * except some embedded image types.\n *\n * You can change this behaviour:\n *\n * ```javascript\n * var md = require('markdown-it')();\n * // enable everything\n * md.validateLink = function () { return true; }\n * ```\n **/\n this.validateLink = validateLink;\n\n /**\n * MarkdownIt#normalizeLink(url) -> String\n *\n * Function used to encode link url to a machine-readable format,\n * which includes url-encoding, punycode, etc.\n **/\n this.normalizeLink = normalizeLink;\n\n /**\n * MarkdownIt#normalizeLinkText(url) -> String\n *\n * Function used to decode link url to a human-readable format`\n **/\n this.normalizeLinkText = normalizeLinkText;\n\n\n // Expose utils & helpers for easy acces from plugins\n\n /**\n * MarkdownIt#utils -> utils\n *\n * Assorted utility functions, useful to write plugins. See details\n * [here](https://github.com/markdown-it/markdown-it/blob/master/lib/common/utils.js).\n **/\n this.utils = utils;\n\n /**\n * MarkdownIt#helpers -> helpers\n *\n * Link components parser functions, useful to write plugins. See details\n * [here](https://github.com/markdown-it/markdown-it/blob/master/lib/helpers).\n **/\n this.helpers = utils.assign({}, helpers);\n\n\n this.options = {};\n this.configure(presetName);\n\n if (options) { this.set(options); }\n}\n\n\n/** chainable\n * MarkdownIt.set(options)\n *\n * Set parser options (in the same format as in constructor). Probably, you\n * will never need it, but you can change options after constructor call.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')()\n * .set({ html: true, breaks: true })\n * .set({ typographer, true });\n * ```\n *\n * __Note:__ To achieve the best possible performance, don't modify a\n * `markdown-it` instance options on the fly. If you need multiple configurations\n * it's best to create multiple instances and initialize each with separate\n * config.\n **/\nMarkdownIt.prototype.set = function (options) {\n utils.assign(this.options, options);\n return this;\n};\n\n\n/** chainable, internal\n * MarkdownIt.configure(presets)\n *\n * Batch load of all options and compenent settings. This is internal method,\n * and you probably will not need it. But if you will - see available presets\n * and data structure [here](https://github.com/markdown-it/markdown-it/tree/master/lib/presets)\n *\n * We strongly recommend to use presets instead of direct config loads. That\n * will give better compatibility with next versions.\n **/\nMarkdownIt.prototype.configure = function (presets) {\n var self = this, presetName;\n\n if (utils.isString(presets)) {\n presetName = presets;\n presets = config[presetName];\n if (!presets) { throw new Error('Wrong `markdown-it` preset \"' + presetName + '\", check name'); }\n }\n\n if (!presets) { throw new Error('Wrong `markdown-it` preset, can\\'t be empty'); }\n\n if (presets.options) { self.set(presets.options); }\n\n if (presets.components) {\n Object.keys(presets.components).forEach(function (name) {\n if (presets.components[name].rules) {\n self[name].ruler.enableOnly(presets.components[name].rules);\n }\n if (presets.components[name].rules2) {\n self[name].ruler2.enableOnly(presets.components[name].rules2);\n }\n });\n }\n return this;\n};\n\n\n/** chainable\n * MarkdownIt.enable(list, ignoreInvalid)\n * - list (String|Array): rule name or list of rule names to enable\n * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.\n *\n * Enable list or rules. It will automatically find appropriate components,\n * containing rules with given names. If rule not found, and `ignoreInvalid`\n * not set - throws exception.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')()\n * .enable(['sub', 'sup'])\n * .disable('smartquotes');\n * ```\n **/\nMarkdownIt.prototype.enable = function (list, ignoreInvalid) {\n var result = [];\n\n if (!Array.isArray(list)) { list = [ list ]; }\n\n [ 'core', 'block', 'inline' ].forEach(function (chain) {\n result = result.concat(this[chain].ruler.enable(list, true));\n }, this);\n\n result = result.concat(this.inline.ruler2.enable(list, true));\n\n var missed = list.filter(function (name) { return result.indexOf(name) < 0; });\n\n if (missed.length && !ignoreInvalid) {\n throw new Error('MarkdownIt. Failed to enable unknown rule(s): ' + missed);\n }\n\n return this;\n};\n\n\n/** chainable\n * MarkdownIt.disable(list, ignoreInvalid)\n * - list (String|Array): rule name or list of rule names to disable.\n * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.\n *\n * The same as [[MarkdownIt.enable]], but turn specified rules off.\n **/\nMarkdownIt.prototype.disable = function (list, ignoreInvalid) {\n var result = [];\n\n if (!Array.isArray(list)) { list = [ list ]; }\n\n [ 'core', 'block', 'inline' ].forEach(function (chain) {\n result = result.concat(this[chain].ruler.disable(list, true));\n }, this);\n\n result = result.concat(this.inline.ruler2.disable(list, true));\n\n var missed = list.filter(function (name) { return result.indexOf(name) < 0; });\n\n if (missed.length && !ignoreInvalid) {\n throw new Error('MarkdownIt. Failed to disable unknown rule(s): ' + missed);\n }\n return this;\n};\n\n\n/** chainable\n * MarkdownIt.use(plugin, params)\n *\n * Load specified plugin with given params into current parser instance.\n * It's just a sugar to call `plugin(md, params)` with curring.\n *\n * ##### Example\n *\n * ```javascript\n * var iterator = require('markdown-it-for-inline');\n * var md = require('markdown-it')()\n * .use(iterator, 'foo_replace', 'text', function (tokens, idx) {\n * tokens[idx].content = tokens[idx].content.replace(/foo/g, 'bar');\n * });\n * ```\n **/\nMarkdownIt.prototype.use = function (plugin /*, params, ... */) {\n var args = [ this ].concat(Array.prototype.slice.call(arguments, 1));\n plugin.apply(plugin, args);\n return this;\n};\n\n\n/** internal\n * MarkdownIt.parse(src, env) -> Array\n * - src (String): source string\n * - env (Object): environment sandbox\n *\n * Parse input string and return list of block tokens (special token type\n * \"inline\" will contain list of inline tokens). You should not call this\n * method directly, until you write custom renderer (for example, to produce\n * AST).\n *\n * `env` is used to pass data between \"distributed\" rules and return additional\n * metadata like reference info, needed for the renderer. It also can be used to\n * inject data in specific cases. Usually, you will be ok to pass `{}`,\n * and then pass updated object to renderer.\n **/\nMarkdownIt.prototype.parse = function (src, env) {\n if (typeof src !== 'string') {\n throw new Error('Input data should be a String');\n }\n\n var state = new this.core.State(src, this, env);\n\n this.core.process(state);\n\n return state.tokens;\n};\n\n\n/**\n * MarkdownIt.render(src [, env]) -> String\n * - src (String): source string\n * - env (Object): environment sandbox\n *\n * Render markdown string into html. It does all magic for you :).\n *\n * `env` can be used to inject additional metadata (`{}` by default).\n * But you will not need it with high probability. See also comment\n * in [[MarkdownIt.parse]].\n **/\nMarkdownIt.prototype.render = function (src, env) {\n env = env || {};\n\n return this.renderer.render(this.parse(src, env), this.options, env);\n};\n\n\n/** internal\n * MarkdownIt.parseInline(src, env) -> Array\n * - src (String): source string\n * - env (Object): environment sandbox\n *\n * The same as [[MarkdownIt.parse]] but skip all block rules. It returns the\n * block tokens list with the single `inline` element, containing parsed inline\n * tokens in `children` property. Also updates `env` object.\n **/\nMarkdownIt.prototype.parseInline = function (src, env) {\n var state = new this.core.State(src, this, env);\n\n state.inlineMode = true;\n this.core.process(state);\n\n return state.tokens;\n};\n\n\n/**\n * MarkdownIt.renderInline(src [, env]) -> String\n * - src (String): source string\n * - env (Object): environment sandbox\n *\n * Similar to [[MarkdownIt.render]] but for single paragraph content. Result\n * will NOT be wrapped into `

` tags.\n **/\nMarkdownIt.prototype.renderInline = function (src, env) {\n env = env || {};\n\n return this.renderer.render(this.parseInline(src, env), this.options, env);\n};\n\n\nmodule.exports = MarkdownIt;\n","// Token class\n\n'use strict';\n\n\n/**\n * class Token\n **/\n\n/**\n * new Token(type, tag, nesting)\n *\n * Create new token and fill passed properties.\n **/\nfunction Token(type, tag, nesting) {\n /**\n * Token#type -> String\n *\n * Type of the token (string, e.g. \"paragraph_open\")\n **/\n this.type = type;\n\n /**\n * Token#tag -> String\n *\n * html tag name, e.g. \"p\"\n **/\n this.tag = tag;\n\n /**\n * Token#attrs -> Array\n *\n * Html attributes. Format: `[ [ name1, value1 ], [ name2, value2 ] ]`\n **/\n this.attrs = null;\n\n /**\n * Token#map -> Array\n *\n * Source map info. Format: `[ line_begin, line_end ]`\n **/\n this.map = null;\n\n /**\n * Token#nesting -> Number\n *\n * Level change (number in {-1, 0, 1} set), where:\n *\n * - `1` means the tag is opening\n * - `0` means the tag is self-closing\n * - `-1` means the tag is closing\n **/\n this.nesting = nesting;\n\n /**\n * Token#level -> Number\n *\n * nesting level, the same as `state.level`\n **/\n this.level = 0;\n\n /**\n * Token#children -> Array\n *\n * An array of child nodes (inline and img tokens)\n **/\n this.children = null;\n\n /**\n * Token#content -> String\n *\n * In a case of self-closing tag (code, html, fence, etc.),\n * it has contents of this tag.\n **/\n this.content = '';\n\n /**\n * Token#markup -> String\n *\n * '*' or '_' for emphasis, fence string for fence, etc.\n **/\n this.markup = '';\n\n /**\n * Token#info -> String\n *\n * Additional information:\n *\n * - Info string for \"fence\" tokens\n * - The value \"auto\" for autolink \"link_open\" and \"link_close\" tokens\n * - The string value of the item marker for ordered-list \"list_item_open\" tokens\n **/\n this.info = '';\n\n /**\n * Token#meta -> Object\n *\n * A place for plugins to store an arbitrary data\n **/\n this.meta = null;\n\n /**\n * Token#block -> Boolean\n *\n * True for block-level tokens, false for inline tokens.\n * Used in renderer to calculate line breaks\n **/\n this.block = false;\n\n /**\n * Token#hidden -> Boolean\n *\n * If it's true, ignore this element when rendering. Used for tight lists\n * to hide paragraphs.\n **/\n this.hidden = false;\n}\n\n\n/**\n * Token.attrIndex(name) -> Number\n *\n * Search attribute index by name.\n **/\nToken.prototype.attrIndex = function attrIndex(name) {\n var attrs, i, len;\n\n if (!this.attrs) { return -1; }\n\n attrs = this.attrs;\n\n for (i = 0, len = attrs.length; i < len; i++) {\n if (attrs[i][0] === name) { return i; }\n }\n return -1;\n};\n\n\n/**\n * Token.attrPush(attrData)\n *\n * Add `[ name, value ]` attribute to list. Init attrs if necessary\n **/\nToken.prototype.attrPush = function attrPush(attrData) {\n if (this.attrs) {\n this.attrs.push(attrData);\n } else {\n this.attrs = [ attrData ];\n }\n};\n\n\n/**\n * Token.attrSet(name, value)\n *\n * Set `name` attribute to `value`. Override old value if exists.\n **/\nToken.prototype.attrSet = function attrSet(name, value) {\n var idx = this.attrIndex(name),\n attrData = [ name, value ];\n\n if (idx < 0) {\n this.attrPush(attrData);\n } else {\n this.attrs[idx] = attrData;\n }\n};\n\n\n/**\n * Token.attrGet(name)\n *\n * Get the value of attribute `name`, or null if it does not exist.\n **/\nToken.prototype.attrGet = function attrGet(name) {\n var idx = this.attrIndex(name), value = null;\n if (idx >= 0) {\n value = this.attrs[idx][1];\n }\n return value;\n};\n\n\n/**\n * Token.attrJoin(name, value)\n *\n * Join value to existing attribute via space. Or create new attribute if not\n * exists. Useful to operate with token classes.\n **/\nToken.prototype.attrJoin = function attrJoin(name, value) {\n var idx = this.attrIndex(name);\n\n if (idx < 0) {\n this.attrPush([ name, value ]);\n } else {\n this.attrs[idx][1] = this.attrs[idx][1] + ' ' + value;\n }\n};\n\n\nmodule.exports = Token;\n","// Inline parser state\n\n'use strict';\n\n\nvar Token = require('../token');\nvar isWhiteSpace = require('../common/utils').isWhiteSpace;\nvar isPunctChar = require('../common/utils').isPunctChar;\nvar isMdAsciiPunct = require('../common/utils').isMdAsciiPunct;\n\n\nfunction StateInline(src, md, env, outTokens) {\n this.src = src;\n this.env = env;\n this.md = md;\n this.tokens = outTokens;\n this.tokens_meta = Array(outTokens.length);\n\n this.pos = 0;\n this.posMax = this.src.length;\n this.level = 0;\n this.pending = '';\n this.pendingLevel = 0;\n\n // Stores { start: end } pairs. Useful for backtrack\n // optimization of pairs parse (emphasis, strikes).\n this.cache = {};\n\n // List of emphasis-like delimiters for current tag\n this.delimiters = [];\n\n // Stack of delimiter lists for upper level tags\n this._prev_delimiters = [];\n\n // backtick length => last seen position\n this.backticks = {};\n this.backticksScanned = false;\n}\n\n\n// Flush pending text\n//\nStateInline.prototype.pushPending = function () {\n var token = new Token('text', '', 0);\n token.content = this.pending;\n token.level = this.pendingLevel;\n this.tokens.push(token);\n this.pending = '';\n return token;\n};\n\n\n// Push new token to \"stream\".\n// If pending text exists - flush it as text token\n//\nStateInline.prototype.push = function (type, tag, nesting) {\n if (this.pending) {\n this.pushPending();\n }\n\n var token = new Token(type, tag, nesting);\n var token_meta = null;\n\n if (nesting < 0) {\n // closing tag\n this.level--;\n this.delimiters = this._prev_delimiters.pop();\n }\n\n token.level = this.level;\n\n if (nesting > 0) {\n // opening tag\n this.level++;\n this._prev_delimiters.push(this.delimiters);\n this.delimiters = [];\n token_meta = { delimiters: this.delimiters };\n }\n\n this.pendingLevel = this.level;\n this.tokens.push(token);\n this.tokens_meta.push(token_meta);\n return token;\n};\n\n\n// Scan a sequence of emphasis-like markers, and determine whether\n// it can start an emphasis sequence or end an emphasis sequence.\n//\n// - start - position to scan from (it should point at a valid marker);\n// - canSplitWord - determine if these markers can be found inside a word\n//\nStateInline.prototype.scanDelims = function (start, canSplitWord) {\n var pos = start, lastChar, nextChar, count, can_open, can_close,\n isLastWhiteSpace, isLastPunctChar,\n isNextWhiteSpace, isNextPunctChar,\n left_flanking = true,\n right_flanking = true,\n max = this.posMax,\n marker = this.src.charCodeAt(start);\n\n // treat beginning of the line as a whitespace\n lastChar = start > 0 ? this.src.charCodeAt(start - 1) : 0x20;\n\n while (pos < max && this.src.charCodeAt(pos) === marker) { pos++; }\n\n count = pos - start;\n\n // treat end of the line as a whitespace\n nextChar = pos < max ? this.src.charCodeAt(pos) : 0x20;\n\n isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));\n isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));\n\n isLastWhiteSpace = isWhiteSpace(lastChar);\n isNextWhiteSpace = isWhiteSpace(nextChar);\n\n if (isNextWhiteSpace) {\n left_flanking = false;\n } else if (isNextPunctChar) {\n if (!(isLastWhiteSpace || isLastPunctChar)) {\n left_flanking = false;\n }\n }\n\n if (isLastWhiteSpace) {\n right_flanking = false;\n } else if (isLastPunctChar) {\n if (!(isNextWhiteSpace || isNextPunctChar)) {\n right_flanking = false;\n }\n }\n\n if (!canSplitWord) {\n can_open = left_flanking && (!right_flanking || isLastPunctChar);\n can_close = right_flanking && (!left_flanking || isNextPunctChar);\n } else {\n can_open = left_flanking;\n can_close = right_flanking;\n }\n\n return {\n can_open: can_open,\n can_close: can_close,\n length: count\n };\n};\n\n\n// re-export Token class to use in block rules\nStateInline.prototype.Token = Token;\n\n\nmodule.exports = StateInline;\n","'use strict';\n\nvar utils = require('./../utils');\nvar buildURL = require('../helpers/buildURL');\nvar InterceptorManager = require('./InterceptorManager');\nvar dispatchRequest = require('./dispatchRequest');\nvar mergeConfig = require('./mergeConfig');\nvar validator = require('../helpers/validator');\n\nvar validators = validator.validators;\n/**\n * Create a new instance of Axios\n *\n * @param {Object} instanceConfig The default config for the instance\n */\nfunction Axios(instanceConfig) {\n this.defaults = instanceConfig;\n this.interceptors = {\n request: new InterceptorManager(),\n response: new InterceptorManager()\n };\n}\n\n/**\n * Dispatch a request\n *\n * @param {Object} config The config specific for this request (merged with this.defaults)\n */\nAxios.prototype.request = function request(config) {\n /*eslint no-param-reassign:0*/\n // Allow for axios('example/url'[, config]) a la fetch API\n if (typeof config === 'string') {\n config = arguments[1] || {};\n config.url = arguments[0];\n } else {\n config = config || {};\n }\n\n config = mergeConfig(this.defaults, config);\n\n // Set config.method\n if (config.method) {\n config.method = config.method.toLowerCase();\n } else if (this.defaults.method) {\n config.method = this.defaults.method.toLowerCase();\n } else {\n config.method = 'get';\n }\n\n var transitional = config.transitional;\n\n if (transitional !== undefined) {\n validator.assertOptions(transitional, {\n silentJSONParsing: validators.transitional(validators.boolean, '1.0.0'),\n forcedJSONParsing: validators.transitional(validators.boolean, '1.0.0'),\n clarifyTimeoutError: validators.transitional(validators.boolean, '1.0.0')\n }, false);\n }\n\n // filter out skipped interceptors\n var requestInterceptorChain = [];\n var synchronousRequestInterceptors = true;\n this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {\n if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {\n return;\n }\n\n synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;\n\n requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);\n });\n\n var responseInterceptorChain = [];\n this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {\n responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);\n });\n\n var promise;\n\n if (!synchronousRequestInterceptors) {\n var chain = [dispatchRequest, undefined];\n\n Array.prototype.unshift.apply(chain, requestInterceptorChain);\n chain.concat(responseInterceptorChain);\n\n promise = Promise.resolve(config);\n while (chain.length) {\n promise = promise.then(chain.shift(), chain.shift());\n }\n\n return promise;\n }\n\n\n var newConfig = config;\n while (requestInterceptorChain.length) {\n var onFulfilled = requestInterceptorChain.shift();\n var onRejected = requestInterceptorChain.shift();\n try {\n newConfig = onFulfilled(newConfig);\n } catch (error) {\n onRejected(error);\n break;\n }\n }\n\n try {\n promise = dispatchRequest(newConfig);\n } catch (error) {\n return Promise.reject(error);\n }\n\n while (responseInterceptorChain.length) {\n promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift());\n }\n\n return promise;\n};\n\nAxios.prototype.getUri = function getUri(config) {\n config = mergeConfig(this.defaults, config);\n return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\\?/, '');\n};\n\n// Provide aliases for supported request methods\nutils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {\n /*eslint func-names:0*/\n Axios.prototype[method] = function(url, config) {\n return this.request(mergeConfig(config || {}, {\n method: method,\n url: url,\n data: (config || {}).data\n }));\n };\n});\n\nutils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {\n /*eslint func-names:0*/\n Axios.prototype[method] = function(url, data, config) {\n return this.request(mergeConfig(config || {}, {\n method: method,\n url: url,\n data: data\n }));\n };\n});\n\nmodule.exports = Axios;\n","'use strict';\n\n/**\n * Syntactic sugar for invoking a function and expanding an array for arguments.\n *\n * Common use case would be to use `Function.prototype.apply`.\n *\n * ```js\n * function f(x, y, z) {}\n * var args = [1, 2, 3];\n * f.apply(null, args);\n * ```\n *\n * With `spread` this example can be re-written.\n *\n * ```js\n * spread(function(x, y, z) {})([1, 2, 3]);\n * ```\n *\n * @param {Function} callback\n * @returns {Function}\n */\nmodule.exports = function spread(callback) {\n return function wrap(arr) {\n return callback.apply(null, arr);\n };\n};\n","/*! https://mths.be/punycode v1.4.1 by @mathias */\n;(function(root) {\n\n\t/** Detect free variables */\n\tvar freeExports = typeof exports == 'object' && exports &&\n\t\t!exports.nodeType && exports;\n\tvar freeModule = typeof module == 'object' && module &&\n\t\t!module.nodeType && module;\n\tvar freeGlobal = typeof global == 'object' && global;\n\tif (\n\t\tfreeGlobal.global === freeGlobal ||\n\t\tfreeGlobal.window === freeGlobal ||\n\t\tfreeGlobal.self === freeGlobal\n\t) {\n\t\troot = freeGlobal;\n\t}\n\n\t/**\n\t * The `punycode` object.\n\t * @name punycode\n\t * @type Object\n\t */\n\tvar punycode,\n\n\t/** Highest positive signed 32-bit float value */\n\tmaxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1\n\n\t/** Bootstring parameters */\n\tbase = 36,\n\ttMin = 1,\n\ttMax = 26,\n\tskew = 38,\n\tdamp = 700,\n\tinitialBias = 72,\n\tinitialN = 128, // 0x80\n\tdelimiter = '-', // '\\x2D'\n\n\t/** Regular expressions */\n\tregexPunycode = /^xn--/,\n\tregexNonASCII = /[^\\x20-\\x7E]/, // unprintable ASCII chars + non-ASCII chars\n\tregexSeparators = /[\\x2E\\u3002\\uFF0E\\uFF61]/g, // RFC 3490 separators\n\n\t/** Error messages */\n\terrors = {\n\t\t'overflow': 'Overflow: input needs wider integers to process',\n\t\t'not-basic': 'Illegal input >= 0x80 (not a basic code point)',\n\t\t'invalid-input': 'Invalid input'\n\t},\n\n\t/** Convenience shortcuts */\n\tbaseMinusTMin = base - tMin,\n\tfloor = Math.floor,\n\tstringFromCharCode = String.fromCharCode,\n\n\t/** Temporary variable */\n\tkey;\n\n\t/*--------------------------------------------------------------------------*/\n\n\t/**\n\t * A generic error utility function.\n\t * @private\n\t * @param {String} type The error type.\n\t * @returns {Error} Throws a `RangeError` with the applicable error message.\n\t */\n\tfunction error(type) {\n\t\tthrow new RangeError(errors[type]);\n\t}\n\n\t/**\n\t * A generic `Array#map` utility function.\n\t * @private\n\t * @param {Array} array The array to iterate over.\n\t * @param {Function} callback The function that gets called for every array\n\t * item.\n\t * @returns {Array} A new array of values returned by the callback function.\n\t */\n\tfunction map(array, fn) {\n\t\tvar length = array.length;\n\t\tvar result = [];\n\t\twhile (length--) {\n\t\t\tresult[length] = fn(array[length]);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * A simple `Array#map`-like wrapper to work with domain name strings or email\n\t * addresses.\n\t * @private\n\t * @param {String} domain The domain name or email address.\n\t * @param {Function} callback The function that gets called for every\n\t * character.\n\t * @returns {Array} A new string of characters returned by the callback\n\t * function.\n\t */\n\tfunction mapDomain(string, fn) {\n\t\tvar parts = string.split('@');\n\t\tvar result = '';\n\t\tif (parts.length > 1) {\n\t\t\t// In email addresses, only the domain name should be punycoded. Leave\n\t\t\t// the local part (i.e. everything up to `@`) intact.\n\t\t\tresult = parts[0] + '@';\n\t\t\tstring = parts[1];\n\t\t}\n\t\t// Avoid `split(regex)` for IE8 compatibility. See #17.\n\t\tstring = string.replace(regexSeparators, '\\x2E');\n\t\tvar labels = string.split('.');\n\t\tvar encoded = map(labels, fn).join('.');\n\t\treturn result + encoded;\n\t}\n\n\t/**\n\t * Creates an array containing the numeric code points of each Unicode\n\t * character in the string. While JavaScript uses UCS-2 internally,\n\t * this function will convert a pair of surrogate halves (each of which\n\t * UCS-2 exposes as separate characters) into a single code point,\n\t * matching UTF-16.\n\t * @see `punycode.ucs2.encode`\n\t * @see \n\t * @memberOf punycode.ucs2\n\t * @name decode\n\t * @param {String} string The Unicode input string (UCS-2).\n\t * @returns {Array} The new array of code points.\n\t */\n\tfunction ucs2decode(string) {\n\t\tvar output = [],\n\t\t counter = 0,\n\t\t length = string.length,\n\t\t value,\n\t\t extra;\n\t\twhile (counter < length) {\n\t\t\tvalue = string.charCodeAt(counter++);\n\t\t\tif (value >= 0xD800 && value <= 0xDBFF && counter < length) {\n\t\t\t\t// high surrogate, and there is a next character\n\t\t\t\textra = string.charCodeAt(counter++);\n\t\t\t\tif ((extra & 0xFC00) == 0xDC00) { // low surrogate\n\t\t\t\t\toutput.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);\n\t\t\t\t} else {\n\t\t\t\t\t// unmatched surrogate; only append this code unit, in case the next\n\t\t\t\t\t// code unit is the high surrogate of a surrogate pair\n\t\t\t\t\toutput.push(value);\n\t\t\t\t\tcounter--;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\toutput.push(value);\n\t\t\t}\n\t\t}\n\t\treturn output;\n\t}\n\n\t/**\n\t * Creates a string based on an array of numeric code points.\n\t * @see `punycode.ucs2.decode`\n\t * @memberOf punycode.ucs2\n\t * @name encode\n\t * @param {Array} codePoints The array of numeric code points.\n\t * @returns {String} The new Unicode string (UCS-2).\n\t */\n\tfunction ucs2encode(array) {\n\t\treturn map(array, function(value) {\n\t\t\tvar output = '';\n\t\t\tif (value > 0xFFFF) {\n\t\t\t\tvalue -= 0x10000;\n\t\t\t\toutput += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);\n\t\t\t\tvalue = 0xDC00 | value & 0x3FF;\n\t\t\t}\n\t\t\toutput += stringFromCharCode(value);\n\t\t\treturn output;\n\t\t}).join('');\n\t}\n\n\t/**\n\t * Converts a basic code point into a digit/integer.\n\t * @see `digitToBasic()`\n\t * @private\n\t * @param {Number} codePoint The basic numeric code point value.\n\t * @returns {Number} The numeric value of a basic code point (for use in\n\t * representing integers) in the range `0` to `base - 1`, or `base` if\n\t * the code point does not represent a value.\n\t */\n\tfunction basicToDigit(codePoint) {\n\t\tif (codePoint - 48 < 10) {\n\t\t\treturn codePoint - 22;\n\t\t}\n\t\tif (codePoint - 65 < 26) {\n\t\t\treturn codePoint - 65;\n\t\t}\n\t\tif (codePoint - 97 < 26) {\n\t\t\treturn codePoint - 97;\n\t\t}\n\t\treturn base;\n\t}\n\n\t/**\n\t * Converts a digit/integer into a basic code point.\n\t * @see `basicToDigit()`\n\t * @private\n\t * @param {Number} digit The numeric value of a basic code point.\n\t * @returns {Number} The basic code point whose value (when used for\n\t * representing integers) is `digit`, which needs to be in the range\n\t * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is\n\t * used; else, the lowercase form is used. The behavior is undefined\n\t * if `flag` is non-zero and `digit` has no uppercase form.\n\t */\n\tfunction digitToBasic(digit, flag) {\n\t\t// 0..25 map to ASCII a..z or A..Z\n\t\t// 26..35 map to ASCII 0..9\n\t\treturn digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);\n\t}\n\n\t/**\n\t * Bias adaptation function as per section 3.4 of RFC 3492.\n\t * https://tools.ietf.org/html/rfc3492#section-3.4\n\t * @private\n\t */\n\tfunction adapt(delta, numPoints, firstTime) {\n\t\tvar k = 0;\n\t\tdelta = firstTime ? floor(delta / damp) : delta >> 1;\n\t\tdelta += floor(delta / numPoints);\n\t\tfor (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {\n\t\t\tdelta = floor(delta / baseMinusTMin);\n\t\t}\n\t\treturn floor(k + (baseMinusTMin + 1) * delta / (delta + skew));\n\t}\n\n\t/**\n\t * Converts a Punycode string of ASCII-only symbols to a string of Unicode\n\t * symbols.\n\t * @memberOf punycode\n\t * @param {String} input The Punycode string of ASCII-only symbols.\n\t * @returns {String} The resulting string of Unicode symbols.\n\t */\n\tfunction decode(input) {\n\t\t// Don't use UCS-2\n\t\tvar output = [],\n\t\t inputLength = input.length,\n\t\t out,\n\t\t i = 0,\n\t\t n = initialN,\n\t\t bias = initialBias,\n\t\t basic,\n\t\t j,\n\t\t index,\n\t\t oldi,\n\t\t w,\n\t\t k,\n\t\t digit,\n\t\t t,\n\t\t /** Cached calculation results */\n\t\t baseMinusT;\n\n\t\t// Handle the basic code points: let `basic` be the number of input code\n\t\t// points before the last delimiter, or `0` if there is none, then copy\n\t\t// the first basic code points to the output.\n\n\t\tbasic = input.lastIndexOf(delimiter);\n\t\tif (basic < 0) {\n\t\t\tbasic = 0;\n\t\t}\n\n\t\tfor (j = 0; j < basic; ++j) {\n\t\t\t// if it's not a basic code point\n\t\t\tif (input.charCodeAt(j) >= 0x80) {\n\t\t\t\terror('not-basic');\n\t\t\t}\n\t\t\toutput.push(input.charCodeAt(j));\n\t\t}\n\n\t\t// Main decoding loop: start just after the last delimiter if any basic code\n\t\t// points were copied; start at the beginning otherwise.\n\n\t\tfor (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {\n\n\t\t\t// `index` is the index of the next character to be consumed.\n\t\t\t// Decode a generalized variable-length integer into `delta`,\n\t\t\t// which gets added to `i`. The overflow checking is easier\n\t\t\t// if we increase `i` as we go, then subtract off its starting\n\t\t\t// value at the end to obtain `delta`.\n\t\t\tfor (oldi = i, w = 1, k = base; /* no condition */; k += base) {\n\n\t\t\t\tif (index >= inputLength) {\n\t\t\t\t\terror('invalid-input');\n\t\t\t\t}\n\n\t\t\t\tdigit = basicToDigit(input.charCodeAt(index++));\n\n\t\t\t\tif (digit >= base || digit > floor((maxInt - i) / w)) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\ti += digit * w;\n\t\t\t\tt = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);\n\n\t\t\t\tif (digit < t) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tbaseMinusT = base - t;\n\t\t\t\tif (w > floor(maxInt / baseMinusT)) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\tw *= baseMinusT;\n\n\t\t\t}\n\n\t\t\tout = output.length + 1;\n\t\t\tbias = adapt(i - oldi, out, oldi == 0);\n\n\t\t\t// `i` was supposed to wrap around from `out` to `0`,\n\t\t\t// incrementing `n` each time, so we'll fix that now:\n\t\t\tif (floor(i / out) > maxInt - n) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\n\t\t\tn += floor(i / out);\n\t\t\ti %= out;\n\n\t\t\t// Insert `n` at position `i` of the output\n\t\t\toutput.splice(i++, 0, n);\n\n\t\t}\n\n\t\treturn ucs2encode(output);\n\t}\n\n\t/**\n\t * Converts a string of Unicode symbols (e.g. a domain name label) to a\n\t * Punycode string of ASCII-only symbols.\n\t * @memberOf punycode\n\t * @param {String} input The string of Unicode symbols.\n\t * @returns {String} The resulting Punycode string of ASCII-only symbols.\n\t */\n\tfunction encode(input) {\n\t\tvar n,\n\t\t delta,\n\t\t handledCPCount,\n\t\t basicLength,\n\t\t bias,\n\t\t j,\n\t\t m,\n\t\t q,\n\t\t k,\n\t\t t,\n\t\t currentValue,\n\t\t output = [],\n\t\t /** `inputLength` will hold the number of code points in `input`. */\n\t\t inputLength,\n\t\t /** Cached calculation results */\n\t\t handledCPCountPlusOne,\n\t\t baseMinusT,\n\t\t qMinusT;\n\n\t\t// Convert the input in UCS-2 to Unicode\n\t\tinput = ucs2decode(input);\n\n\t\t// Cache the length\n\t\tinputLength = input.length;\n\n\t\t// Initialize the state\n\t\tn = initialN;\n\t\tdelta = 0;\n\t\tbias = initialBias;\n\n\t\t// Handle the basic code points\n\t\tfor (j = 0; j < inputLength; ++j) {\n\t\t\tcurrentValue = input[j];\n\t\t\tif (currentValue < 0x80) {\n\t\t\t\toutput.push(stringFromCharCode(currentValue));\n\t\t\t}\n\t\t}\n\n\t\thandledCPCount = basicLength = output.length;\n\n\t\t// `handledCPCount` is the number of code points that have been handled;\n\t\t// `basicLength` is the number of basic code points.\n\n\t\t// Finish the basic string - if it is not empty - with a delimiter\n\t\tif (basicLength) {\n\t\t\toutput.push(delimiter);\n\t\t}\n\n\t\t// Main encoding loop:\n\t\twhile (handledCPCount < inputLength) {\n\n\t\t\t// All non-basic code points < n have been handled already. Find the next\n\t\t\t// larger one:\n\t\t\tfor (m = maxInt, j = 0; j < inputLength; ++j) {\n\t\t\t\tcurrentValue = input[j];\n\t\t\t\tif (currentValue >= n && currentValue < m) {\n\t\t\t\t\tm = currentValue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Increase `delta` enough to advance the decoder's state to ,\n\t\t\t// but guard against overflow\n\t\t\thandledCPCountPlusOne = handledCPCount + 1;\n\t\t\tif (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\n\t\t\tdelta += (m - n) * handledCPCountPlusOne;\n\t\t\tn = m;\n\n\t\t\tfor (j = 0; j < inputLength; ++j) {\n\t\t\t\tcurrentValue = input[j];\n\n\t\t\t\tif (currentValue < n && ++delta > maxInt) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\tif (currentValue == n) {\n\t\t\t\t\t// Represent delta as a generalized variable-length integer\n\t\t\t\t\tfor (q = delta, k = base; /* no condition */; k += base) {\n\t\t\t\t\t\tt = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);\n\t\t\t\t\t\tif (q < t) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tqMinusT = q - t;\n\t\t\t\t\t\tbaseMinusT = base - t;\n\t\t\t\t\t\toutput.push(\n\t\t\t\t\t\t\tstringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))\n\t\t\t\t\t\t);\n\t\t\t\t\t\tq = floor(qMinusT / baseMinusT);\n\t\t\t\t\t}\n\n\t\t\t\t\toutput.push(stringFromCharCode(digitToBasic(q, 0)));\n\t\t\t\t\tbias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);\n\t\t\t\t\tdelta = 0;\n\t\t\t\t\t++handledCPCount;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t++delta;\n\t\t\t++n;\n\n\t\t}\n\t\treturn output.join('');\n\t}\n\n\t/**\n\t * Converts a Punycode string representing a domain name or an email address\n\t * to Unicode. Only the Punycoded parts of the input will be converted, i.e.\n\t * it doesn't matter if you call it on a string that has already been\n\t * converted to Unicode.\n\t * @memberOf punycode\n\t * @param {String} input The Punycoded domain name or email address to\n\t * convert to Unicode.\n\t * @returns {String} The Unicode representation of the given Punycode\n\t * string.\n\t */\n\tfunction toUnicode(input) {\n\t\treturn mapDomain(input, function(string) {\n\t\t\treturn regexPunycode.test(string)\n\t\t\t\t? decode(string.slice(4).toLowerCase())\n\t\t\t\t: string;\n\t\t});\n\t}\n\n\t/**\n\t * Converts a Unicode string representing a domain name or an email address to\n\t * Punycode. Only the non-ASCII parts of the domain name will be converted,\n\t * i.e. it doesn't matter if you call it with a domain that's already in\n\t * ASCII.\n\t * @memberOf punycode\n\t * @param {String} input The domain name or email address to convert, as a\n\t * Unicode string.\n\t * @returns {String} The Punycode representation of the given domain name or\n\t * email address.\n\t */\n\tfunction toASCII(input) {\n\t\treturn mapDomain(input, function(string) {\n\t\t\treturn regexNonASCII.test(string)\n\t\t\t\t? 'xn--' + encode(string)\n\t\t\t\t: string;\n\t\t});\n\t}\n\n\t/*--------------------------------------------------------------------------*/\n\n\t/** Define the public API */\n\tpunycode = {\n\t\t/**\n\t\t * A string representing the current Punycode.js version number.\n\t\t * @memberOf punycode\n\t\t * @type String\n\t\t */\n\t\t'version': '1.4.1',\n\t\t/**\n\t\t * An object of methods to convert from JavaScript's internal character\n\t\t * representation (UCS-2) to Unicode code points, and back.\n\t\t * @see \n\t\t * @memberOf punycode\n\t\t * @type Object\n\t\t */\n\t\t'ucs2': {\n\t\t\t'decode': ucs2decode,\n\t\t\t'encode': ucs2encode\n\t\t},\n\t\t'decode': decode,\n\t\t'encode': encode,\n\t\t'toASCII': toASCII,\n\t\t'toUnicode': toUnicode\n\t};\n\n\t/** Expose `punycode` */\n\t// Some AMD build optimizers, like r.js, check for specific condition patterns\n\t// like the following:\n\tif (\n\t\ttypeof define == 'function' &&\n\t\ttypeof define.amd == 'object' &&\n\t\tdefine.amd\n\t) {\n\t\tdefine('punycode', function() {\n\t\t\treturn punycode;\n\t\t});\n\t} else if (freeExports && freeModule) {\n\t\tif (module.exports == freeExports) {\n\t\t\t// in Node.js, io.js, or RingoJS v0.8.0+\n\t\t\tfreeModule.exports = punycode;\n\t\t} else {\n\t\t\t// in Narwhal or RingoJS v0.7.0-\n\t\t\tfor (key in punycode) {\n\t\t\t\tpunycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// in Rhino or a web browser\n\t\troot.punycode = punycode;\n\t}\n\n}(this));\n","// lheading (---, ===)\n\n'use strict';\n\n\nmodule.exports = function lheading(state, startLine, endLine/*, silent*/) {\n var content, terminate, i, l, token, pos, max, level, marker,\n nextLine = startLine + 1, oldParentType,\n terminatorRules = state.md.block.ruler.getRules('paragraph');\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n oldParentType = state.parentType;\n state.parentType = 'paragraph'; // use paragraph to match terminatorRules\n\n // jump line-by-line until empty one or EOF\n for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {\n // this would be a code block normally, but after paragraph\n // it's considered a lazy continuation regardless of what's there\n if (state.sCount[nextLine] - state.blkIndent > 3) { continue; }\n\n //\n // Check for underline in setext header\n //\n if (state.sCount[nextLine] >= state.blkIndent) {\n pos = state.bMarks[nextLine] + state.tShift[nextLine];\n max = state.eMarks[nextLine];\n\n if (pos < max) {\n marker = state.src.charCodeAt(pos);\n\n if (marker === 0x2D/* - */ || marker === 0x3D/* = */) {\n pos = state.skipChars(pos, marker);\n pos = state.skipSpaces(pos);\n\n if (pos >= max) {\n level = (marker === 0x3D/* = */ ? 1 : 2);\n break;\n }\n }\n }\n }\n\n // quirk for blockquotes, this line should already be checked by that rule\n if (state.sCount[nextLine] < 0) { continue; }\n\n // Some tags can terminate paragraph without empty line.\n terminate = false;\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n if (terminate) { break; }\n }\n\n if (!level) {\n // Didn't find valid underline\n return false;\n }\n\n content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();\n\n state.line = nextLine + 1;\n\n token = state.push('heading_open', 'h' + String(level), 1);\n token.markup = String.fromCharCode(marker);\n token.map = [ startLine, state.line ];\n\n token = state.push('inline', '', 0);\n token.content = content;\n token.map = [ startLine, state.line - 1 ];\n token.children = [];\n\n token = state.push('heading_close', 'h' + String(level), -1);\n token.markup = String.fromCharCode(marker);\n\n state.parentType = oldParentType;\n\n return true;\n};\n","// \"Zero\" preset, with nothing enabled. Useful for manual configuring of simple\n// modes. For example, to parse bold/italic only.\n\n'use strict';\n\n\nmodule.exports = {\n options: {\n html: false, // Enable HTML tags in source\n xhtmlOut: false, // Use '/' to close single tags (
)\n breaks: false, // Convert '\\n' in paragraphs into
\n langPrefix: 'language-', // CSS language prefix for fenced blocks\n linkify: false, // autoconvert URL-like texts to links\n\n // Enable some language-neutral replacements + quotes beautification\n typographer: false,\n\n // Double + single quotes replacement pairs, when typographer enabled,\n // and smartquotes on. Could be either a String or an Array.\n //\n // For example, you can use '«»„“' for Russian, '„“‚‘' for German,\n // and ['«\\xA0', '\\xA0»', '‹\\xA0', '\\xA0›'] for French (including nbsp).\n quotes: '\\u201c\\u201d\\u2018\\u2019', /* “”‘’ */\n\n // Highlighter function. Should return escaped HTML,\n // or '' if the source string is not changed and should be escaped externaly.\n // If result starts with 0) level++; // opening tag\n\n if (tokens[curr].type === 'text' &&\n curr + 1 < max &&\n tokens[curr + 1].type === 'text') {\n\n // collapse two adjacent text nodes\n tokens[curr + 1].content = tokens[curr].content + tokens[curr + 1].content;\n } else {\n if (curr !== last) { tokens[last] = tokens[curr]; }\n\n last++;\n }\n }\n\n if (curr !== last) {\n tokens.length = last;\n }\n};\n","'use strict';\n\nvar utils = require('./utils');\nvar normalizeHeaderName = require('./helpers/normalizeHeaderName');\nvar enhanceError = require('./core/enhanceError');\n\nvar DEFAULT_CONTENT_TYPE = {\n 'Content-Type': 'application/x-www-form-urlencoded'\n};\n\nfunction setContentTypeIfUnset(headers, value) {\n if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {\n headers['Content-Type'] = value;\n }\n}\n\nfunction getDefaultAdapter() {\n var adapter;\n if (typeof XMLHttpRequest !== 'undefined') {\n // For browsers use XHR adapter\n adapter = require('./adapters/xhr');\n } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {\n // For node use HTTP adapter\n adapter = require('./adapters/http');\n }\n return adapter;\n}\n\nvar defaults = {\n\n transitional: {\n silentJSONParsing: true,\n forcedJSONParsing: true,\n clarifyTimeoutError: false\n },\n\n adapter: getDefaultAdapter(),\n\n transformRequest: [function transformRequest(data, headers) {\n normalizeHeaderName(headers, 'Accept');\n normalizeHeaderName(headers, 'Content-Type');\n\n if (utils.isFormData(data) ||\n utils.isArrayBuffer(data) ||\n utils.isBuffer(data) ||\n utils.isStream(data) ||\n utils.isFile(data) ||\n utils.isBlob(data)\n ) {\n return data;\n }\n if (utils.isArrayBufferView(data)) {\n return data.buffer;\n }\n if (utils.isURLSearchParams(data)) {\n setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');\n return data.toString();\n }\n if (utils.isObject(data) || (headers && headers['Content-Type'] === 'application/json')) {\n setContentTypeIfUnset(headers, 'application/json');\n return JSON.stringify(data);\n }\n return data;\n }],\n\n transformResponse: [function transformResponse(data) {\n var transitional = this.transitional;\n var silentJSONParsing = transitional && transitional.silentJSONParsing;\n var forcedJSONParsing = transitional && transitional.forcedJSONParsing;\n var strictJSONParsing = !silentJSONParsing && this.responseType === 'json';\n\n if (strictJSONParsing || (forcedJSONParsing && utils.isString(data) && data.length)) {\n try {\n return JSON.parse(data);\n } catch (e) {\n if (strictJSONParsing) {\n if (e.name === 'SyntaxError') {\n throw enhanceError(e, this, 'E_JSON_PARSE');\n }\n throw e;\n }\n }\n }\n\n return data;\n }],\n\n /**\n * A timeout in milliseconds to abort a request. If set to 0 (default) a\n * timeout is not created.\n */\n timeout: 0,\n\n xsrfCookieName: 'XSRF-TOKEN',\n xsrfHeaderName: 'X-XSRF-TOKEN',\n\n maxContentLength: -1,\n maxBodyLength: -1,\n\n validateStatus: function validateStatus(status) {\n return status >= 200 && status < 300;\n }\n};\n\ndefaults.headers = {\n common: {\n 'Accept': 'application/json, text/plain, */*'\n }\n};\n\nutils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {\n defaults.headers[method] = {};\n});\n\nutils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {\n defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);\n});\n\nmodule.exports = defaults;\n","// Process autolinks ''\n\n'use strict';\n\n\n/*eslint max-len:0*/\nvar EMAIL_RE = /^([a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$/;\nvar AUTOLINK_RE = /^([a-zA-Z][a-zA-Z0-9+.\\-]{1,31}):([^<>\\x00-\\x20]*)$/;\n\n\nmodule.exports = function autolink(state, silent) {\n var url, fullUrl, token, ch, start, max,\n pos = state.pos;\n\n if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false; }\n\n start = state.pos;\n max = state.posMax;\n\n for (;;) {\n if (++pos >= max) return false;\n\n ch = state.src.charCodeAt(pos);\n\n if (ch === 0x3C /* < */) return false;\n if (ch === 0x3E /* > */) break;\n }\n\n url = state.src.slice(start + 1, pos);\n\n if (AUTOLINK_RE.test(url)) {\n fullUrl = state.md.normalizeLink(url);\n if (!state.md.validateLink(fullUrl)) { return false; }\n\n if (!silent) {\n token = state.push('link_open', 'a', 1);\n token.attrs = [ [ 'href', fullUrl ] ];\n token.markup = 'autolink';\n token.info = 'auto';\n\n token = state.push('text', '', 0);\n token.content = state.md.normalizeLinkText(url);\n\n token = state.push('link_close', 'a', -1);\n token.markup = 'autolink';\n token.info = 'auto';\n }\n\n state.pos += url.length + 2;\n return true;\n }\n\n if (EMAIL_RE.test(url)) {\n fullUrl = state.md.normalizeLink('mailto:' + url);\n if (!state.md.validateLink(fullUrl)) { return false; }\n\n if (!silent) {\n token = state.push('link_open', 'a', 1);\n token.attrs = [ [ 'href', fullUrl ] ];\n token.markup = 'autolink';\n token.info = 'auto';\n\n token = state.push('text', '', 0);\n token.content = state.md.normalizeLinkText(url);\n\n token = state.push('link_close', 'a', -1);\n token.markup = 'autolink';\n token.info = 'auto';\n }\n\n state.pos += url.length + 2;\n return true;\n }\n\n return false;\n};\n","'use strict';\n\nvar enhanceError = require('./enhanceError');\n\n/**\n * Create an Error with the specified message, config, error code, request and response.\n *\n * @param {string} message The error message.\n * @param {Object} config The config.\n * @param {string} [code] The error code (for example, 'ECONNABORTED').\n * @param {Object} [request] The request.\n * @param {Object} [response] The response.\n * @returns {Error} The created error.\n */\nmodule.exports = function createError(message, config, code, request, response) {\n var error = new Error(message);\n return enhanceError(error, config, code, request, response);\n};\n","'use strict';\n\nmodule.exports = function isCancel(value) {\n return !!(value && value.__CANCEL__);\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\nfunction encode(val) {\n return encodeURIComponent(val).\n replace(/%3A/gi, ':').\n replace(/%24/g, '$').\n replace(/%2C/gi, ',').\n replace(/%20/g, '+').\n replace(/%5B/gi, '[').\n replace(/%5D/gi, ']');\n}\n\n/**\n * Build a URL by appending params to the end\n *\n * @param {string} url The base of the url (e.g., http://www.google.com)\n * @param {object} [params] The params to be appended\n * @returns {string} The formatted url\n */\nmodule.exports = function buildURL(url, params, paramsSerializer) {\n /*eslint no-param-reassign:0*/\n if (!params) {\n return url;\n }\n\n var serializedParams;\n if (paramsSerializer) {\n serializedParams = paramsSerializer(params);\n } else if (utils.isURLSearchParams(params)) {\n serializedParams = params.toString();\n } else {\n var parts = [];\n\n utils.forEach(params, function serialize(val, key) {\n if (val === null || typeof val === 'undefined') {\n return;\n }\n\n if (utils.isArray(val)) {\n key = key + '[]';\n } else {\n val = [val];\n }\n\n utils.forEach(val, function parseValue(v) {\n if (utils.isDate(v)) {\n v = v.toISOString();\n } else if (utils.isObject(v)) {\n v = JSON.stringify(v);\n }\n parts.push(encode(key) + '=' + encode(v));\n });\n });\n\n serializedParams = parts.join('&');\n }\n\n if (serializedParams) {\n var hashmarkIndex = url.indexOf('#');\n if (hashmarkIndex !== -1) {\n url = url.slice(0, hashmarkIndex);\n }\n\n url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;\n }\n\n return url;\n};\n","'use strict';\n\n\nmodule.exports = function block(state) {\n var token;\n\n if (state.inlineMode) {\n token = new state.Token('inline', '', 0);\n token.content = state.src;\n token.map = [ 0, 1 ];\n token.children = [];\n state.tokens.push(token);\n } else {\n state.md.block.parse(state.src, state.md, state.env, state.tokens);\n }\n};\n","'use strict';\n\n/**\n * Update an Error with the specified config, error code, and response.\n *\n * @param {Error} error The error to update.\n * @param {Object} config The config.\n * @param {string} [code] The error code (for example, 'ECONNABORTED').\n * @param {Object} [request] The request.\n * @param {Object} [response] The response.\n * @returns {Error} The error.\n */\nmodule.exports = function enhanceError(error, config, code, request, response) {\n error.config = config;\n if (code) {\n error.code = code;\n }\n\n error.request = request;\n error.response = response;\n error.isAxiosError = true;\n\n error.toJSON = function toJSON() {\n return {\n // Standard\n message: this.message,\n name: this.name,\n // Microsoft\n description: this.description,\n number: this.number,\n // Mozilla\n fileName: this.fileName,\n lineNumber: this.lineNumber,\n columnNumber: this.columnNumber,\n stack: this.stack,\n // Axios\n config: this.config,\n code: this.code\n };\n };\n return error;\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\nmodule.exports = (\n utils.isStandardBrowserEnv() ?\n\n // Standard browser envs have full support of the APIs needed to test\n // whether the request URL is of the same origin as current location.\n (function standardBrowserEnv() {\n var msie = /(msie|trident)/i.test(navigator.userAgent);\n var urlParsingNode = document.createElement('a');\n var originURL;\n\n /**\n * Parse a URL to discover it's components\n *\n * @param {String} url The URL to be parsed\n * @returns {Object}\n */\n function resolveURL(url) {\n var href = url;\n\n if (msie) {\n // IE needs attribute set twice to normalize properties\n urlParsingNode.setAttribute('href', href);\n href = urlParsingNode.href;\n }\n\n urlParsingNode.setAttribute('href', href);\n\n // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils\n return {\n href: urlParsingNode.href,\n protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',\n host: urlParsingNode.host,\n search: urlParsingNode.search ? urlParsingNode.search.replace(/^\\?/, '') : '',\n hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',\n hostname: urlParsingNode.hostname,\n port: urlParsingNode.port,\n pathname: (urlParsingNode.pathname.charAt(0) === '/') ?\n urlParsingNode.pathname :\n '/' + urlParsingNode.pathname\n };\n }\n\n originURL = resolveURL(window.location.href);\n\n /**\n * Determine if a URL shares the same origin as the current location\n *\n * @param {String} requestURL The URL to test\n * @returns {boolean} True if URL shares the same origin, otherwise false\n */\n return function isURLSameOrigin(requestURL) {\n var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL;\n return (parsed.protocol === originURL.protocol &&\n parsed.host === originURL.host);\n };\n })() :\n\n // Non standard browser envs (web workers, react-native) lack needed support.\n (function nonStandardBrowserEnv() {\n return function isURLSameOrigin() {\n return true;\n };\n })()\n);\n","// Proceess '\\n'\n\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\n\nmodule.exports = function newline(state, silent) {\n var pmax, max, ws, pos = state.pos;\n\n if (state.src.charCodeAt(pos) !== 0x0A/* \\n */) { return false; }\n\n pmax = state.pending.length - 1;\n max = state.posMax;\n\n // ' \\n' -> hardbreak\n // Lookup in pending chars is bad practice! Don't copy to other rules!\n // Pending string is stored in concat mode, indexed lookups will cause\n // convertion to flat mode.\n if (!silent) {\n if (pmax >= 0 && state.pending.charCodeAt(pmax) === 0x20) {\n if (pmax >= 1 && state.pending.charCodeAt(pmax - 1) === 0x20) {\n // Find whitespaces tail of pending chars.\n ws = pmax - 1;\n while (ws >= 1 && state.pending.charCodeAt(ws - 1) === 0x20) ws--;\n\n state.pending = state.pending.slice(0, ws);\n state.push('hardbreak', 'br', 0);\n } else {\n state.pending = state.pending.slice(0, -1);\n state.push('softbreak', 'br', 0);\n }\n\n } else {\n state.push('softbreak', 'br', 0);\n }\n }\n\n pos++;\n\n // skip heading spaces for next line\n while (pos < max && isSpace(state.src.charCodeAt(pos))) { pos++; }\n\n state.pos = pos;\n return true;\n};\n","// Commonmark default options\n\n'use strict';\n\n\nmodule.exports = {\n options: {\n html: true, // Enable HTML tags in source\n xhtmlOut: true, // Use '/' to close single tags (
)\n breaks: false, // Convert '\\n' in paragraphs into
\n langPrefix: 'language-', // CSS language prefix for fenced blocks\n linkify: false, // autoconvert URL-like texts to links\n\n // Enable some language-neutral replacements + quotes beautification\n typographer: false,\n\n // Double + single quotes replacement pairs, when typographer enabled,\n // and smartquotes on. Could be either a String or an Array.\n //\n // For example, you can use '«»„“' for Russian, '„“‚‘' for German,\n // and ['«\\xA0', '\\xA0»', '‹\\xA0', '\\xA0›'] for French (including nbsp).\n quotes: '\\u201c\\u201d\\u2018\\u2019', /* “”‘’ */\n\n // Highlighter function. Should return escaped HTML,\n // or '' if the source string is not changed and should be escaped externaly.\n // If result starts with 3) { continue; }\n\n // quirk for blockquotes, this line should already be checked by that rule\n if (state.sCount[nextLine] < 0) { continue; }\n\n // Some tags can terminate paragraph without empty line.\n terminate = false;\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n if (terminate) { break; }\n }\n\n content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();\n\n state.line = nextLine;\n\n token = state.push('paragraph_open', 'p', 1);\n token.map = [ startLine, state.line ];\n\n token = state.push('inline', '', 0);\n token.content = content;\n token.map = [ startLine, state.line ];\n token.children = [];\n\n token = state.push('paragraph_close', 'p', -1);\n\n state.parentType = oldParentType;\n\n return true;\n};\n","'use strict';\n\nvar createError = require('./createError');\n\n/**\n * Resolve or reject a Promise based on response status.\n *\n * @param {Function} resolve A function that resolves the promise.\n * @param {Function} reject A function that rejects the promise.\n * @param {object} response The response.\n */\nmodule.exports = function settle(resolve, reject, response) {\n var validateStatus = response.config.validateStatus;\n if (!response.status || !validateStatus || validateStatus(response.status)) {\n resolve(response);\n } else {\n reject(createError(\n 'Request failed with status code ' + response.status,\n response.config,\n null,\n response.request,\n response\n ));\n }\n};\n","/**\n * class Ruler\n *\n * Helper class, used by [[MarkdownIt#core]], [[MarkdownIt#block]] and\n * [[MarkdownIt#inline]] to manage sequences of functions (rules):\n *\n * - keep rules in defined order\n * - assign the name to each rule\n * - enable/disable rules\n * - add/replace rules\n * - allow assign rules to additional named chains (in the same)\n * - cacheing lists of active rules\n *\n * You will not need use this class directly until write plugins. For simple\n * rules control use [[MarkdownIt.disable]], [[MarkdownIt.enable]] and\n * [[MarkdownIt.use]].\n **/\n'use strict';\n\n\n/**\n * new Ruler()\n **/\nfunction Ruler() {\n // List of added rules. Each element is:\n //\n // {\n // name: XXX,\n // enabled: Boolean,\n // fn: Function(),\n // alt: [ name2, name3 ]\n // }\n //\n this.__rules__ = [];\n\n // Cached rule chains.\n //\n // First level - chain name, '' for default.\n // Second level - diginal anchor for fast filtering by charcodes.\n //\n this.__cache__ = null;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Helper methods, should not be used directly\n\n\n// Find rule index by name\n//\nRuler.prototype.__find__ = function (name) {\n for (var i = 0; i < this.__rules__.length; i++) {\n if (this.__rules__[i].name === name) {\n return i;\n }\n }\n return -1;\n};\n\n\n// Build rules lookup cache\n//\nRuler.prototype.__compile__ = function () {\n var self = this;\n var chains = [ '' ];\n\n // collect unique names\n self.__rules__.forEach(function (rule) {\n if (!rule.enabled) { return; }\n\n rule.alt.forEach(function (altName) {\n if (chains.indexOf(altName) < 0) {\n chains.push(altName);\n }\n });\n });\n\n self.__cache__ = {};\n\n chains.forEach(function (chain) {\n self.__cache__[chain] = [];\n self.__rules__.forEach(function (rule) {\n if (!rule.enabled) { return; }\n\n if (chain && rule.alt.indexOf(chain) < 0) { return; }\n\n self.__cache__[chain].push(rule.fn);\n });\n });\n};\n\n\n/**\n * Ruler.at(name, fn [, options])\n * - name (String): rule name to replace.\n * - fn (Function): new rule function.\n * - options (Object): new rule options (not mandatory).\n *\n * Replace rule by name with new function & options. Throws error if name not\n * found.\n *\n * ##### Options:\n *\n * - __alt__ - array with names of \"alternate\" chains.\n *\n * ##### Example\n *\n * Replace existing typographer replacement rule with new one:\n *\n * ```javascript\n * var md = require('markdown-it')();\n *\n * md.core.ruler.at('replacements', function replace(state) {\n * //...\n * });\n * ```\n **/\nRuler.prototype.at = function (name, fn, options) {\n var index = this.__find__(name);\n var opt = options || {};\n\n if (index === -1) { throw new Error('Parser rule not found: ' + name); }\n\n this.__rules__[index].fn = fn;\n this.__rules__[index].alt = opt.alt || [];\n this.__cache__ = null;\n};\n\n\n/**\n * Ruler.before(beforeName, ruleName, fn [, options])\n * - beforeName (String): new rule will be added before this one.\n * - ruleName (String): name of added rule.\n * - fn (Function): rule function.\n * - options (Object): rule options (not mandatory).\n *\n * Add new rule to chain before one with given name. See also\n * [[Ruler.after]], [[Ruler.push]].\n *\n * ##### Options:\n *\n * - __alt__ - array with names of \"alternate\" chains.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')();\n *\n * md.block.ruler.before('paragraph', 'my_rule', function replace(state) {\n * //...\n * });\n * ```\n **/\nRuler.prototype.before = function (beforeName, ruleName, fn, options) {\n var index = this.__find__(beforeName);\n var opt = options || {};\n\n if (index === -1) { throw new Error('Parser rule not found: ' + beforeName); }\n\n this.__rules__.splice(index, 0, {\n name: ruleName,\n enabled: true,\n fn: fn,\n alt: opt.alt || []\n });\n\n this.__cache__ = null;\n};\n\n\n/**\n * Ruler.after(afterName, ruleName, fn [, options])\n * - afterName (String): new rule will be added after this one.\n * - ruleName (String): name of added rule.\n * - fn (Function): rule function.\n * - options (Object): rule options (not mandatory).\n *\n * Add new rule to chain after one with given name. See also\n * [[Ruler.before]], [[Ruler.push]].\n *\n * ##### Options:\n *\n * - __alt__ - array with names of \"alternate\" chains.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')();\n *\n * md.inline.ruler.after('text', 'my_rule', function replace(state) {\n * //...\n * });\n * ```\n **/\nRuler.prototype.after = function (afterName, ruleName, fn, options) {\n var index = this.__find__(afterName);\n var opt = options || {};\n\n if (index === -1) { throw new Error('Parser rule not found: ' + afterName); }\n\n this.__rules__.splice(index + 1, 0, {\n name: ruleName,\n enabled: true,\n fn: fn,\n alt: opt.alt || []\n });\n\n this.__cache__ = null;\n};\n\n/**\n * Ruler.push(ruleName, fn [, options])\n * - ruleName (String): name of added rule.\n * - fn (Function): rule function.\n * - options (Object): rule options (not mandatory).\n *\n * Push new rule to the end of chain. See also\n * [[Ruler.before]], [[Ruler.after]].\n *\n * ##### Options:\n *\n * - __alt__ - array with names of \"alternate\" chains.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')();\n *\n * md.core.ruler.push('my_rule', function replace(state) {\n * //...\n * });\n * ```\n **/\nRuler.prototype.push = function (ruleName, fn, options) {\n var opt = options || {};\n\n this.__rules__.push({\n name: ruleName,\n enabled: true,\n fn: fn,\n alt: opt.alt || []\n });\n\n this.__cache__ = null;\n};\n\n\n/**\n * Ruler.enable(list [, ignoreInvalid]) -> Array\n * - list (String|Array): list of rule names to enable.\n * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.\n *\n * Enable rules with given names. If any rule name not found - throw Error.\n * Errors can be disabled by second param.\n *\n * Returns list of found rule names (if no exception happened).\n *\n * See also [[Ruler.disable]], [[Ruler.enableOnly]].\n **/\nRuler.prototype.enable = function (list, ignoreInvalid) {\n if (!Array.isArray(list)) { list = [ list ]; }\n\n var result = [];\n\n // Search by name and enable\n list.forEach(function (name) {\n var idx = this.__find__(name);\n\n if (idx < 0) {\n if (ignoreInvalid) { return; }\n throw new Error('Rules manager: invalid rule name ' + name);\n }\n this.__rules__[idx].enabled = true;\n result.push(name);\n }, this);\n\n this.__cache__ = null;\n return result;\n};\n\n\n/**\n * Ruler.enableOnly(list [, ignoreInvalid])\n * - list (String|Array): list of rule names to enable (whitelist).\n * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.\n *\n * Enable rules with given names, and disable everything else. If any rule name\n * not found - throw Error. Errors can be disabled by second param.\n *\n * See also [[Ruler.disable]], [[Ruler.enable]].\n **/\nRuler.prototype.enableOnly = function (list, ignoreInvalid) {\n if (!Array.isArray(list)) { list = [ list ]; }\n\n this.__rules__.forEach(function (rule) { rule.enabled = false; });\n\n this.enable(list, ignoreInvalid);\n};\n\n\n/**\n * Ruler.disable(list [, ignoreInvalid]) -> Array\n * - list (String|Array): list of rule names to disable.\n * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.\n *\n * Disable rules with given names. If any rule name not found - throw Error.\n * Errors can be disabled by second param.\n *\n * Returns list of found rule names (if no exception happened).\n *\n * See also [[Ruler.enable]], [[Ruler.enableOnly]].\n **/\nRuler.prototype.disable = function (list, ignoreInvalid) {\n if (!Array.isArray(list)) { list = [ list ]; }\n\n var result = [];\n\n // Search by name and disable\n list.forEach(function (name) {\n var idx = this.__find__(name);\n\n if (idx < 0) {\n if (ignoreInvalid) { return; }\n throw new Error('Rules manager: invalid rule name ' + name);\n }\n this.__rules__[idx].enabled = false;\n result.push(name);\n }, this);\n\n this.__cache__ = null;\n return result;\n};\n\n\n/**\n * Ruler.getRules(chainName) -> Array\n *\n * Return array of active functions (rules) for given chain name. It analyzes\n * rules configuration, compiles caches if not exists and returns result.\n *\n * Default chain name is `''` (empty string). It can't be skipped. That's\n * done intentionally, to keep signature monomorphic for high speed.\n **/\nRuler.prototype.getRules = function (chainName) {\n if (this.__cache__ === null) {\n this.__compile__();\n }\n\n // Chain can be empty, if rules disabled. But we still have to return Array.\n return this.__cache__[chainName] || [];\n};\n\nmodule.exports = Ruler;\n","'use strict';\n\nvar utils = require('../utils');\n\n/**\n * Config-specific merge-function which creates a new config-object\n * by merging two configuration objects together.\n *\n * @param {Object} config1\n * @param {Object} config2\n * @returns {Object} New object resulting from merging config2 to config1\n */\nmodule.exports = function mergeConfig(config1, config2) {\n // eslint-disable-next-line no-param-reassign\n config2 = config2 || {};\n var config = {};\n\n var valueFromConfig2Keys = ['url', 'method', 'data'];\n var mergeDeepPropertiesKeys = ['headers', 'auth', 'proxy', 'params'];\n var defaultToConfig2Keys = [\n 'baseURL', 'transformRequest', 'transformResponse', 'paramsSerializer',\n 'timeout', 'timeoutMessage', 'withCredentials', 'adapter', 'responseType', 'xsrfCookieName',\n 'xsrfHeaderName', 'onUploadProgress', 'onDownloadProgress', 'decompress',\n 'maxContentLength', 'maxBodyLength', 'maxRedirects', 'transport', 'httpAgent',\n 'httpsAgent', 'cancelToken', 'socketPath', 'responseEncoding'\n ];\n var directMergeKeys = ['validateStatus'];\n\n function getMergedValue(target, source) {\n if (utils.isPlainObject(target) && utils.isPlainObject(source)) {\n return utils.merge(target, source);\n } else if (utils.isPlainObject(source)) {\n return utils.merge({}, source);\n } else if (utils.isArray(source)) {\n return source.slice();\n }\n return source;\n }\n\n function mergeDeepProperties(prop) {\n if (!utils.isUndefined(config2[prop])) {\n config[prop] = getMergedValue(config1[prop], config2[prop]);\n } else if (!utils.isUndefined(config1[prop])) {\n config[prop] = getMergedValue(undefined, config1[prop]);\n }\n }\n\n utils.forEach(valueFromConfig2Keys, function valueFromConfig2(prop) {\n if (!utils.isUndefined(config2[prop])) {\n config[prop] = getMergedValue(undefined, config2[prop]);\n }\n });\n\n utils.forEach(mergeDeepPropertiesKeys, mergeDeepProperties);\n\n utils.forEach(defaultToConfig2Keys, function defaultToConfig2(prop) {\n if (!utils.isUndefined(config2[prop])) {\n config[prop] = getMergedValue(undefined, config2[prop]);\n } else if (!utils.isUndefined(config1[prop])) {\n config[prop] = getMergedValue(undefined, config1[prop]);\n }\n });\n\n utils.forEach(directMergeKeys, function merge(prop) {\n if (prop in config2) {\n config[prop] = getMergedValue(config1[prop], config2[prop]);\n } else if (prop in config1) {\n config[prop] = getMergedValue(undefined, config1[prop]);\n }\n });\n\n var axiosKeys = valueFromConfig2Keys\n .concat(mergeDeepPropertiesKeys)\n .concat(defaultToConfig2Keys)\n .concat(directMergeKeys);\n\n var otherKeys = Object\n .keys(config1)\n .concat(Object.keys(config2))\n .filter(function filterAxiosKeys(key) {\n return axiosKeys.indexOf(key) === -1;\n });\n\n utils.forEach(otherKeys, mergeDeepProperties);\n\n return config;\n};\n","// Parse backticks\n\n'use strict';\n\n\nmodule.exports = function backtick(state, silent) {\n var start, max, marker, token, matchStart, matchEnd, openerLength, closerLength,\n pos = state.pos,\n ch = state.src.charCodeAt(pos);\n\n if (ch !== 0x60/* ` */) { return false; }\n\n start = pos;\n pos++;\n max = state.posMax;\n\n // scan marker length\n while (pos < max && state.src.charCodeAt(pos) === 0x60/* ` */) { pos++; }\n\n marker = state.src.slice(start, pos);\n openerLength = marker.length;\n\n if (state.backticksScanned && (state.backticks[openerLength] || 0) <= start) {\n if (!silent) state.pending += marker;\n state.pos += openerLength;\n return true;\n }\n\n matchStart = matchEnd = pos;\n\n // Nothing found in the cache, scan until the end of the line (or until marker is found)\n while ((matchStart = state.src.indexOf('`', matchEnd)) !== -1) {\n matchEnd = matchStart + 1;\n\n // scan marker length\n while (matchEnd < max && state.src.charCodeAt(matchEnd) === 0x60/* ` */) { matchEnd++; }\n\n closerLength = matchEnd - matchStart;\n\n if (closerLength === openerLength) {\n // Found matching closer length.\n if (!silent) {\n token = state.push('code_inline', 'code', 0);\n token.markup = marker;\n token.content = state.src.slice(pos, matchStart)\n .replace(/\\n/g, ' ')\n .replace(/^ (.+) $/, '$1');\n }\n state.pos = matchEnd;\n return true;\n }\n\n // Some different length found, put it in cache as upper limit of where closer can be found\n state.backticks[closerLength] = matchStart;\n }\n\n // Scanned through the end, didn't find anything\n state.backticksScanned = true;\n\n if (!silent) state.pending += marker;\n state.pos += openerLength;\n return true;\n};\n","// Lists\n\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\n\n// Search `[-+*][\\n ]`, returns next pos after marker on success\n// or -1 on fail.\nfunction skipBulletListMarker(state, startLine) {\n var marker, pos, max, ch;\n\n pos = state.bMarks[startLine] + state.tShift[startLine];\n max = state.eMarks[startLine];\n\n marker = state.src.charCodeAt(pos++);\n // Check bullet\n if (marker !== 0x2A/* * */ &&\n marker !== 0x2D/* - */ &&\n marker !== 0x2B/* + */) {\n return -1;\n }\n\n if (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (!isSpace(ch)) {\n // \" -test \" - is not a list item\n return -1;\n }\n }\n\n return pos;\n}\n\n// Search `\\d+[.)][\\n ]`, returns next pos after marker on success\n// or -1 on fail.\nfunction skipOrderedListMarker(state, startLine) {\n var ch,\n start = state.bMarks[startLine] + state.tShift[startLine],\n pos = start,\n max = state.eMarks[startLine];\n\n // List marker should have at least 2 chars (digit + dot)\n if (pos + 1 >= max) { return -1; }\n\n ch = state.src.charCodeAt(pos++);\n\n if (ch < 0x30/* 0 */ || ch > 0x39/* 9 */) { return -1; }\n\n for (;;) {\n // EOL -> fail\n if (pos >= max) { return -1; }\n\n ch = state.src.charCodeAt(pos++);\n\n if (ch >= 0x30/* 0 */ && ch <= 0x39/* 9 */) {\n\n // List marker should have no more than 9 digits\n // (prevents integer overflow in browsers)\n if (pos - start >= 10) { return -1; }\n\n continue;\n }\n\n // found valid marker\n if (ch === 0x29/* ) */ || ch === 0x2e/* . */) {\n break;\n }\n\n return -1;\n }\n\n\n if (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (!isSpace(ch)) {\n // \" 1.test \" - is not a list item\n return -1;\n }\n }\n return pos;\n}\n\nfunction markTightParagraphs(state, idx) {\n var i, l,\n level = state.level + 2;\n\n for (i = idx + 2, l = state.tokens.length - 2; i < l; i++) {\n if (state.tokens[i].level === level && state.tokens[i].type === 'paragraph_open') {\n state.tokens[i + 2].hidden = true;\n state.tokens[i].hidden = true;\n i += 2;\n }\n }\n}\n\n\nmodule.exports = function list(state, startLine, endLine, silent) {\n var ch,\n contentStart,\n i,\n indent,\n indentAfterMarker,\n initial,\n isOrdered,\n itemLines,\n l,\n listLines,\n listTokIdx,\n markerCharCode,\n markerValue,\n max,\n nextLine,\n offset,\n oldListIndent,\n oldParentType,\n oldSCount,\n oldTShift,\n oldTight,\n pos,\n posAfterMarker,\n prevEmptyEnd,\n start,\n terminate,\n terminatorRules,\n token,\n isTerminatingParagraph = false,\n tight = true;\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n // Special case:\n // - item 1\n // - item 2\n // - item 3\n // - item 4\n // - this one is a paragraph continuation\n if (state.listIndent >= 0 &&\n state.sCount[startLine] - state.listIndent >= 4 &&\n state.sCount[startLine] < state.blkIndent) {\n return false;\n }\n\n // limit conditions when list can interrupt\n // a paragraph (validation mode only)\n if (silent && state.parentType === 'paragraph') {\n // Next list item should still terminate previous list item;\n //\n // This code can fail if plugins use blkIndent as well as lists,\n // but I hope the spec gets fixed long before that happens.\n //\n if (state.sCount[startLine] >= state.blkIndent) {\n isTerminatingParagraph = true;\n }\n }\n\n // Detect list type and position after marker\n if ((posAfterMarker = skipOrderedListMarker(state, startLine)) >= 0) {\n isOrdered = true;\n start = state.bMarks[startLine] + state.tShift[startLine];\n markerValue = Number(state.src.slice(start, posAfterMarker - 1));\n\n // If we're starting a new ordered list right after\n // a paragraph, it should start with 1.\n if (isTerminatingParagraph && markerValue !== 1) return false;\n\n } else if ((posAfterMarker = skipBulletListMarker(state, startLine)) >= 0) {\n isOrdered = false;\n\n } else {\n return false;\n }\n\n // If we're starting a new unordered list right after\n // a paragraph, first line should not be empty.\n if (isTerminatingParagraph) {\n if (state.skipSpaces(posAfterMarker) >= state.eMarks[startLine]) return false;\n }\n\n // We should terminate list on style change. Remember first one to compare.\n markerCharCode = state.src.charCodeAt(posAfterMarker - 1);\n\n // For validation mode we can terminate immediately\n if (silent) { return true; }\n\n // Start list\n listTokIdx = state.tokens.length;\n\n if (isOrdered) {\n token = state.push('ordered_list_open', 'ol', 1);\n if (markerValue !== 1) {\n token.attrs = [ [ 'start', markerValue ] ];\n }\n\n } else {\n token = state.push('bullet_list_open', 'ul', 1);\n }\n\n token.map = listLines = [ startLine, 0 ];\n token.markup = String.fromCharCode(markerCharCode);\n\n //\n // Iterate list items\n //\n\n nextLine = startLine;\n prevEmptyEnd = false;\n terminatorRules = state.md.block.ruler.getRules('list');\n\n oldParentType = state.parentType;\n state.parentType = 'list';\n\n while (nextLine < endLine) {\n pos = posAfterMarker;\n max = state.eMarks[nextLine];\n\n initial = offset = state.sCount[nextLine] + posAfterMarker - (state.bMarks[startLine] + state.tShift[startLine]);\n\n while (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (ch === 0x09) {\n offset += 4 - (offset + state.bsCount[nextLine]) % 4;\n } else if (ch === 0x20) {\n offset++;\n } else {\n break;\n }\n\n pos++;\n }\n\n contentStart = pos;\n\n if (contentStart >= max) {\n // trimming space in \"- \\n 3\" case, indent is 1 here\n indentAfterMarker = 1;\n } else {\n indentAfterMarker = offset - initial;\n }\n\n // If we have more than 4 spaces, the indent is 1\n // (the rest is just indented code block)\n if (indentAfterMarker > 4) { indentAfterMarker = 1; }\n\n // \" - test\"\n // ^^^^^ - calculating total length of this thing\n indent = initial + indentAfterMarker;\n\n // Run subparser & write tokens\n token = state.push('list_item_open', 'li', 1);\n token.markup = String.fromCharCode(markerCharCode);\n token.map = itemLines = [ startLine, 0 ];\n if (isOrdered) {\n token.info = state.src.slice(start, posAfterMarker - 1);\n }\n\n // change current state, then restore it after parser subcall\n oldTight = state.tight;\n oldTShift = state.tShift[startLine];\n oldSCount = state.sCount[startLine];\n\n // - example list\n // ^ listIndent position will be here\n // ^ blkIndent position will be here\n //\n oldListIndent = state.listIndent;\n state.listIndent = state.blkIndent;\n state.blkIndent = indent;\n\n state.tight = true;\n state.tShift[startLine] = contentStart - state.bMarks[startLine];\n state.sCount[startLine] = offset;\n\n if (contentStart >= max && state.isEmpty(startLine + 1)) {\n // workaround for this case\n // (list item is empty, list terminates before \"foo\"):\n // ~~~~~~~~\n // -\n //\n // foo\n // ~~~~~~~~\n state.line = Math.min(state.line + 2, endLine);\n } else {\n state.md.block.tokenize(state, startLine, endLine, true);\n }\n\n // If any of list item is tight, mark list as tight\n if (!state.tight || prevEmptyEnd) {\n tight = false;\n }\n // Item become loose if finish with empty line,\n // but we should filter last element, because it means list finish\n prevEmptyEnd = (state.line - startLine) > 1 && state.isEmpty(state.line - 1);\n\n state.blkIndent = state.listIndent;\n state.listIndent = oldListIndent;\n state.tShift[startLine] = oldTShift;\n state.sCount[startLine] = oldSCount;\n state.tight = oldTight;\n\n token = state.push('list_item_close', 'li', -1);\n token.markup = String.fromCharCode(markerCharCode);\n\n nextLine = startLine = state.line;\n itemLines[1] = nextLine;\n contentStart = state.bMarks[startLine];\n\n if (nextLine >= endLine) { break; }\n\n //\n // Try to check if list is terminated or continued.\n //\n if (state.sCount[nextLine] < state.blkIndent) { break; }\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { break; }\n\n // fail if terminating block found\n terminate = false;\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n if (terminate) { break; }\n\n // fail if list has another type\n if (isOrdered) {\n posAfterMarker = skipOrderedListMarker(state, nextLine);\n if (posAfterMarker < 0) { break; }\n start = state.bMarks[nextLine] + state.tShift[nextLine];\n } else {\n posAfterMarker = skipBulletListMarker(state, nextLine);\n if (posAfterMarker < 0) { break; }\n }\n\n if (markerCharCode !== state.src.charCodeAt(posAfterMarker - 1)) { break; }\n }\n\n // Finalize list\n if (isOrdered) {\n token = state.push('ordered_list_close', 'ol', -1);\n } else {\n token = state.push('bullet_list_close', 'ul', -1);\n }\n token.markup = String.fromCharCode(markerCharCode);\n\n listLines[1] = nextLine;\n state.line = nextLine;\n\n state.parentType = oldParentType;\n\n // mark paragraphs tight if needed\n if (tight) {\n markTightParagraphs(state, listTokIdx);\n }\n\n return true;\n};\n","// Normalize input string\n\n'use strict';\n\n\n// https://spec.commonmark.org/0.29/#line-ending\nvar NEWLINES_RE = /\\r\\n?|\\n/g;\nvar NULL_RE = /\\0/g;\n\n\nmodule.exports = function normalize(state) {\n var str;\n\n // Normalize newlines\n str = state.src.replace(NEWLINES_RE, '\\n');\n\n // Replace NULL characters\n str = str.replace(NULL_RE, '\\uFFFD');\n\n state.src = str;\n};\n","/** internal\n * class ParserInline\n *\n * Tokenizes paragraph content.\n **/\n'use strict';\n\n\nvar Ruler = require('./ruler');\n\n\n////////////////////////////////////////////////////////////////////////////////\n// Parser rules\n\nvar _rules = [\n [ 'text', require('./rules_inline/text') ],\n [ 'newline', require('./rules_inline/newline') ],\n [ 'escape', require('./rules_inline/escape') ],\n [ 'backticks', require('./rules_inline/backticks') ],\n [ 'strikethrough', require('./rules_inline/strikethrough').tokenize ],\n [ 'emphasis', require('./rules_inline/emphasis').tokenize ],\n [ 'link', require('./rules_inline/link') ],\n [ 'image', require('./rules_inline/image') ],\n [ 'autolink', require('./rules_inline/autolink') ],\n [ 'html_inline', require('./rules_inline/html_inline') ],\n [ 'entity', require('./rules_inline/entity') ]\n];\n\nvar _rules2 = [\n [ 'balance_pairs', require('./rules_inline/balance_pairs') ],\n [ 'strikethrough', require('./rules_inline/strikethrough').postProcess ],\n [ 'emphasis', require('./rules_inline/emphasis').postProcess ],\n [ 'text_collapse', require('./rules_inline/text_collapse') ]\n];\n\n\n/**\n * new ParserInline()\n **/\nfunction ParserInline() {\n var i;\n\n /**\n * ParserInline#ruler -> Ruler\n *\n * [[Ruler]] instance. Keep configuration of inline rules.\n **/\n this.ruler = new Ruler();\n\n for (i = 0; i < _rules.length; i++) {\n this.ruler.push(_rules[i][0], _rules[i][1]);\n }\n\n /**\n * ParserInline#ruler2 -> Ruler\n *\n * [[Ruler]] instance. Second ruler used for post-processing\n * (e.g. in emphasis-like rules).\n **/\n this.ruler2 = new Ruler();\n\n for (i = 0; i < _rules2.length; i++) {\n this.ruler2.push(_rules2[i][0], _rules2[i][1]);\n }\n}\n\n\n// Skip single token by running all rules in validation mode;\n// returns `true` if any rule reported success\n//\nParserInline.prototype.skipToken = function (state) {\n var ok, i, pos = state.pos,\n rules = this.ruler.getRules(''),\n len = rules.length,\n maxNesting = state.md.options.maxNesting,\n cache = state.cache;\n\n\n if (typeof cache[pos] !== 'undefined') {\n state.pos = cache[pos];\n return;\n }\n\n if (state.level < maxNesting) {\n for (i = 0; i < len; i++) {\n // Increment state.level and decrement it later to limit recursion.\n // It's harmless to do here, because no tokens are created. But ideally,\n // we'd need a separate private state variable for this purpose.\n //\n state.level++;\n ok = rules[i](state, true);\n state.level--;\n\n if (ok) { break; }\n }\n } else {\n // Too much nesting, just skip until the end of the paragraph.\n //\n // NOTE: this will cause links to behave incorrectly in the following case,\n // when an amount of `[` is exactly equal to `maxNesting + 1`:\n //\n // [[[[[[[[[[[[[[[[[[[[[foo]()\n //\n // TODO: remove this workaround when CM standard will allow nested links\n // (we can replace it by preventing links from being parsed in\n // validation mode)\n //\n state.pos = state.posMax;\n }\n\n if (!ok) { state.pos++; }\n cache[pos] = state.pos;\n};\n\n\n// Generate tokens for input range\n//\nParserInline.prototype.tokenize = function (state) {\n var ok, i,\n rules = this.ruler.getRules(''),\n len = rules.length,\n end = state.posMax,\n maxNesting = state.md.options.maxNesting;\n\n while (state.pos < end) {\n // Try all possible rules.\n // On success, rule should:\n //\n // - update `state.pos`\n // - update `state.tokens`\n // - return true\n\n if (state.level < maxNesting) {\n for (i = 0; i < len; i++) {\n ok = rules[i](state, false);\n if (ok) { break; }\n }\n }\n\n if (ok) {\n if (state.pos >= end) { break; }\n continue;\n }\n\n state.pending += state.src[state.pos++];\n }\n\n if (state.pending) {\n state.pushPending();\n }\n};\n\n\n/**\n * ParserInline.parse(str, md, env, outTokens)\n *\n * Process input string and push inline tokens into `outTokens`\n **/\nParserInline.prototype.parse = function (str, md, env, outTokens) {\n var i, rules, len;\n var state = new this.State(str, md, env, outTokens);\n\n this.tokenize(state);\n\n rules = this.ruler2.getRules('');\n len = rules.length;\n\n for (i = 0; i < len; i++) {\n rules[i](state);\n }\n};\n\n\nParserInline.prototype.State = require('./rules_inline/state_inline');\n\n\nmodule.exports = ParserInline;\n","module.exports=/[ \\xA0\\u1680\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]/","'use strict';\n\nvar utils = require('./../utils');\nvar transformData = require('./transformData');\nvar isCancel = require('../cancel/isCancel');\nvar defaults = require('../defaults');\n\n/**\n * Throws a `Cancel` if cancellation has been requested.\n */\nfunction throwIfCancellationRequested(config) {\n if (config.cancelToken) {\n config.cancelToken.throwIfRequested();\n }\n}\n\n/**\n * Dispatch a request to the server using the configured adapter.\n *\n * @param {object} config The config that is to be used for the request\n * @returns {Promise} The Promise to be fulfilled\n */\nmodule.exports = function dispatchRequest(config) {\n throwIfCancellationRequested(config);\n\n // Ensure headers exist\n config.headers = config.headers || {};\n\n // Transform request data\n config.data = transformData.call(\n config,\n config.data,\n config.headers,\n config.transformRequest\n );\n\n // Flatten headers\n config.headers = utils.merge(\n config.headers.common || {},\n config.headers[config.method] || {},\n config.headers\n );\n\n utils.forEach(\n ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],\n function cleanHeaderConfig(method) {\n delete config.headers[method];\n }\n );\n\n var adapter = config.adapter || defaults.adapter;\n\n return adapter(config).then(function onAdapterResolution(response) {\n throwIfCancellationRequested(config);\n\n // Transform response data\n response.data = transformData.call(\n config,\n response.data,\n response.headers,\n config.transformResponse\n );\n\n return response;\n }, function onAdapterRejection(reason) {\n if (!isCancel(reason)) {\n throwIfCancellationRequested(config);\n\n // Transform response data\n if (reason && reason.response) {\n reason.response.data = transformData.call(\n config,\n reason.response.data,\n reason.response.headers,\n config.transformResponse\n );\n }\n }\n\n return Promise.reject(reason);\n });\n};\n","// Just a shortcut for bulk export\n'use strict';\n\n\nexports.parseLinkLabel = require('./parse_link_label');\nexports.parseLinkDestination = require('./parse_link_destination');\nexports.parseLinkTitle = require('./parse_link_title');\n","// Regexps to match html elements\n\n'use strict';\n\nvar attr_name = '[a-zA-Z_:][a-zA-Z0-9:._-]*';\n\nvar unquoted = '[^\"\\'=<>`\\\\x00-\\\\x20]+';\nvar single_quoted = \"'[^']*'\";\nvar double_quoted = '\"[^\"]*\"';\n\nvar attr_value = '(?:' + unquoted + '|' + single_quoted + '|' + double_quoted + ')';\n\nvar attribute = '(?:\\\\s+' + attr_name + '(?:\\\\s*=\\\\s*' + attr_value + ')?)';\n\nvar open_tag = '<[A-Za-z][A-Za-z0-9\\\\-]*' + attribute + '*\\\\s*\\\\/?>';\n\nvar close_tag = '<\\\\/[A-Za-z][A-Za-z0-9\\\\-]*\\\\s*>';\nvar comment = '|';\nvar processing = '<[?][\\\\s\\\\S]*?[?]>';\nvar declaration = ']*>';\nvar cdata = '';\n\nvar HTML_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag + '|' + comment +\n '|' + processing + '|' + declaration + '|' + cdata + ')');\nvar HTML_OPEN_CLOSE_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag + ')');\n\nmodule.exports.HTML_TAG_RE = HTML_TAG_RE;\nmodule.exports.HTML_OPEN_CLOSE_TAG_RE = HTML_OPEN_CLOSE_TAG_RE;\n","// Process html entity - {, ¯, ", ...\n\n'use strict';\n\nvar entities = require('../common/entities');\nvar has = require('../common/utils').has;\nvar isValidEntityCode = require('../common/utils').isValidEntityCode;\nvar fromCodePoint = require('../common/utils').fromCodePoint;\n\n\nvar DIGITAL_RE = /^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i;\nvar NAMED_RE = /^&([a-z][a-z0-9]{1,31});/i;\n\n\nmodule.exports = function entity(state, silent) {\n var ch, code, match, pos = state.pos, max = state.posMax;\n\n if (state.src.charCodeAt(pos) !== 0x26/* & */) { return false; }\n\n if (pos + 1 < max) {\n ch = state.src.charCodeAt(pos + 1);\n\n if (ch === 0x23 /* # */) {\n match = state.src.slice(pos).match(DIGITAL_RE);\n if (match) {\n if (!silent) {\n code = match[1][0].toLowerCase() === 'x' ? parseInt(match[1].slice(1), 16) : parseInt(match[1], 10);\n state.pending += isValidEntityCode(code) ? fromCodePoint(code) : fromCodePoint(0xFFFD);\n }\n state.pos += match[0].length;\n return true;\n }\n } else {\n match = state.src.slice(pos).match(NAMED_RE);\n if (match) {\n if (has(entities, match[1])) {\n if (!silent) { state.pending += entities[match[1]]; }\n state.pos += match[0].length;\n return true;\n }\n }\n }\n }\n\n if (!silent) { state.pending += '&'; }\n state.pos++;\n return true;\n};\n","'use strict';\n\n/**\n * Determines whether the payload is an error thrown by Axios\n *\n * @param {*} payload The value to test\n * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false\n */\nmodule.exports = function isAxiosError(payload) {\n return (typeof payload === 'object') && (payload.isAxiosError === true);\n};\n","// HTML block\n\n'use strict';\n\n\nvar block_names = require('../common/html_blocks');\nvar HTML_OPEN_CLOSE_TAG_RE = require('../common/html_re').HTML_OPEN_CLOSE_TAG_RE;\n\n// An array of opening and corresponding closing sequences for html tags,\n// last argument defines whether it can terminate a paragraph or not\n//\nvar HTML_SEQUENCES = [\n [ /^<(script|pre|style|textarea)(?=(\\s|>|$))/i, /<\\/(script|pre|style|textarea)>/i, true ],\n [ /^/, true ],\n [ /^<\\?/, /\\?>/, true ],\n [ /^/, true ],\n [ /^/, true ],\n [ new RegExp('^|$))', 'i'), /^$/, true ],\n [ new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + '\\\\s*$'), /^$/, false ]\n];\n\n\nmodule.exports = function html_block(state, startLine, endLine, silent) {\n var i, nextLine, token, lineText,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine];\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n if (!state.md.options.html) { return false; }\n\n if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false; }\n\n lineText = state.src.slice(pos, max);\n\n for (i = 0; i < HTML_SEQUENCES.length; i++) {\n if (HTML_SEQUENCES[i][0].test(lineText)) { break; }\n }\n\n if (i === HTML_SEQUENCES.length) { return false; }\n\n if (silent) {\n // true if this sequence can be a terminator, false otherwise\n return HTML_SEQUENCES[i][2];\n }\n\n nextLine = startLine + 1;\n\n // If we are here - we detected HTML block.\n // Let's roll down till block end.\n if (!HTML_SEQUENCES[i][1].test(lineText)) {\n for (; nextLine < endLine; nextLine++) {\n if (state.sCount[nextLine] < state.blkIndent) { break; }\n\n pos = state.bMarks[nextLine] + state.tShift[nextLine];\n max = state.eMarks[nextLine];\n lineText = state.src.slice(pos, max);\n\n if (HTML_SEQUENCES[i][1].test(lineText)) {\n if (lineText.length !== 0) { nextLine++; }\n break;\n }\n }\n }\n\n state.line = nextLine;\n\n token = state.push('html_block', '', 0);\n token.map = [ startLine, nextLine ];\n token.content = state.getLines(startLine, nextLine, state.blkIndent, true);\n\n return true;\n};\n","module.exports = function(module) {\n\tif (!module.webpackPolyfill) {\n\t\tmodule.deprecate = function() {};\n\t\tmodule.paths = [];\n\t\t// module.parent = undefined by default\n\t\tif (!module.children) module.children = [];\n\t\tObject.defineProperty(module, \"loaded\", {\n\t\t\tenumerable: true,\n\t\t\tget: function() {\n\t\t\t\treturn module.l;\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(module, \"id\", {\n\t\t\tenumerable: true,\n\t\t\tget: function() {\n\t\t\t\treturn module.i;\n\t\t\t}\n\t\t});\n\t\tmodule.webpackPolyfill = 1;\n\t}\n\treturn module;\n};\n","// Process escaped chars and hardbreaks\n\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\nvar ESCAPED = [];\n\nfor (var i = 0; i < 256; i++) { ESCAPED.push(0); }\n\n'\\\\!\"#$%&\\'()*+,./:;<=>?@[]^_`{|}~-'\n .split('').forEach(function (ch) { ESCAPED[ch.charCodeAt(0)] = 1; });\n\n\nmodule.exports = function escape(state, silent) {\n var ch, pos = state.pos, max = state.posMax;\n\n if (state.src.charCodeAt(pos) !== 0x5C/* \\ */) { return false; }\n\n pos++;\n\n if (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (ch < 256 && ESCAPED[ch] !== 0) {\n if (!silent) { state.pending += state.src[pos]; }\n state.pos += 2;\n return true;\n }\n\n if (ch === 0x0A) {\n if (!silent) {\n state.push('hardbreak', 'br', 0);\n }\n\n pos++;\n // skip leading whitespaces from next line\n while (pos < max) {\n ch = state.src.charCodeAt(pos);\n if (!isSpace(ch)) { break; }\n pos++;\n }\n\n state.pos = pos;\n return true;\n }\n }\n\n if (!silent) { state.pending += '\\\\'; }\n state.pos++;\n return true;\n};\n","module.exports=/[\\xAD\\u0600-\\u0605\\u061C\\u06DD\\u070F\\u08E2\\u180E\\u200B-\\u200F\\u202A-\\u202E\\u2060-\\u2064\\u2066-\\u206F\\uFEFF\\uFFF9-\\uFFFB]|\\uD804[\\uDCBD\\uDCCD]|\\uD82F[\\uDCA0-\\uDCA3]|\\uD834[\\uDD73-\\uDD7A]|\\uDB40[\\uDC01\\uDC20-\\uDC7F]/","// Core state object\n//\n'use strict';\n\nvar Token = require('../token');\n\n\nfunction StateCore(src, md, env) {\n this.src = src;\n this.env = env;\n this.tokens = [];\n this.inlineMode = false;\n this.md = md; // link to parser instance\n}\n\n// re-export Token class to use in core rules\nStateCore.prototype.Token = Token;\n\n\nmodule.exports = StateCore;\n","/** internal\n * class ParserBlock\n *\n * Block-level tokenizer.\n **/\n'use strict';\n\n\nvar Ruler = require('./ruler');\n\n\nvar _rules = [\n // First 2 params - rule name & source. Secondary array - list of rules,\n // which can be terminated by this one.\n [ 'table', require('./rules_block/table'), [ 'paragraph', 'reference' ] ],\n [ 'code', require('./rules_block/code') ],\n [ 'fence', require('./rules_block/fence'), [ 'paragraph', 'reference', 'blockquote', 'list' ] ],\n [ 'blockquote', require('./rules_block/blockquote'), [ 'paragraph', 'reference', 'blockquote', 'list' ] ],\n [ 'hr', require('./rules_block/hr'), [ 'paragraph', 'reference', 'blockquote', 'list' ] ],\n [ 'list', require('./rules_block/list'), [ 'paragraph', 'reference', 'blockquote' ] ],\n [ 'reference', require('./rules_block/reference') ],\n [ 'html_block', require('./rules_block/html_block'), [ 'paragraph', 'reference', 'blockquote' ] ],\n [ 'heading', require('./rules_block/heading'), [ 'paragraph', 'reference', 'blockquote' ] ],\n [ 'lheading', require('./rules_block/lheading') ],\n [ 'paragraph', require('./rules_block/paragraph') ]\n];\n\n\n/**\n * new ParserBlock()\n **/\nfunction ParserBlock() {\n /**\n * ParserBlock#ruler -> Ruler\n *\n * [[Ruler]] instance. Keep configuration of block rules.\n **/\n this.ruler = new Ruler();\n\n for (var i = 0; i < _rules.length; i++) {\n this.ruler.push(_rules[i][0], _rules[i][1], { alt: (_rules[i][2] || []).slice() });\n }\n}\n\n\n// Generate tokens for input range\n//\nParserBlock.prototype.tokenize = function (state, startLine, endLine) {\n var ok, i,\n rules = this.ruler.getRules(''),\n len = rules.length,\n line = startLine,\n hasEmptyLines = false,\n maxNesting = state.md.options.maxNesting;\n\n while (line < endLine) {\n state.line = line = state.skipEmptyLines(line);\n if (line >= endLine) { break; }\n\n // Termination condition for nested calls.\n // Nested calls currently used for blockquotes & lists\n if (state.sCount[line] < state.blkIndent) { break; }\n\n // If nesting level exceeded - skip tail to the end. That's not ordinary\n // situation and we should not care about content.\n if (state.level >= maxNesting) {\n state.line = endLine;\n break;\n }\n\n // Try all possible rules.\n // On success, rule should:\n //\n // - update `state.line`\n // - update `state.tokens`\n // - return true\n\n for (i = 0; i < len; i++) {\n ok = rules[i](state, line, endLine, false);\n if (ok) { break; }\n }\n\n // set state.tight if we had an empty line before current tag\n // i.e. latest empty line should not count\n state.tight = !hasEmptyLines;\n\n // paragraph might \"eat\" one newline after it in nested lists\n if (state.isEmpty(state.line - 1)) {\n hasEmptyLines = true;\n }\n\n line = state.line;\n\n if (line < endLine && state.isEmpty(line)) {\n hasEmptyLines = true;\n line++;\n state.line = line;\n }\n }\n};\n\n\n/**\n * ParserBlock.parse(str, md, env, outTokens)\n *\n * Process input string and push block tokens into `outTokens`\n **/\nParserBlock.prototype.parse = function (src, md, env, outTokens) {\n var state;\n\n if (!src) { return; }\n\n state = new this.State(src, md, env, outTokens);\n\n this.tokenize(state, state.line, state.lineMax);\n};\n\n\nParserBlock.prototype.State = require('./rules_block/state_block');\n\n\nmodule.exports = ParserBlock;\n","'use strict';\n\n/**\n * A `Cancel` is an object that is thrown when an operation is canceled.\n *\n * @class\n * @param {string=} message The message.\n */\nfunction Cancel(message) {\n this.message = message;\n}\n\nCancel.prototype.toString = function toString() {\n return 'Cancel' + (this.message ? ': ' + this.message : '');\n};\n\nCancel.prototype.__CANCEL__ = true;\n\nmodule.exports = Cancel;\n","'use strict';\n\nvar utils = require('./../utils');\n\nmodule.exports = (\n utils.isStandardBrowserEnv() ?\n\n // Standard browser envs support document.cookie\n (function standardBrowserEnv() {\n return {\n write: function write(name, value, expires, path, domain, secure) {\n var cookie = [];\n cookie.push(name + '=' + encodeURIComponent(value));\n\n if (utils.isNumber(expires)) {\n cookie.push('expires=' + new Date(expires).toGMTString());\n }\n\n if (utils.isString(path)) {\n cookie.push('path=' + path);\n }\n\n if (utils.isString(domain)) {\n cookie.push('domain=' + domain);\n }\n\n if (secure === true) {\n cookie.push('secure');\n }\n\n document.cookie = cookie.join('; ');\n },\n\n read: function read(name) {\n var match = document.cookie.match(new RegExp('(^|;\\\\s*)(' + name + ')=([^;]*)'));\n return (match ? decodeURIComponent(match[3]) : null);\n },\n\n remove: function remove(name) {\n this.write(name, '', Date.now() - 86400000);\n }\n };\n })() :\n\n // Non standard browser env (web workers, react-native) lack needed support.\n (function nonStandardBrowserEnv() {\n return {\n write: function write() {},\n read: function read() { return null; },\n remove: function remove() {}\n };\n })()\n);\n","module.exports=/[!-#%-\\*,-\\/:;\\?@\\[-\\]_\\{\\}\\xA1\\xA7\\xAB\\xB6\\xB7\\xBB\\xBF\\u037E\\u0387\\u055A-\\u055F\\u0589\\u058A\\u05BE\\u05C0\\u05C3\\u05C6\\u05F3\\u05F4\\u0609\\u060A\\u060C\\u060D\\u061B\\u061E\\u061F\\u066A-\\u066D\\u06D4\\u0700-\\u070D\\u07F7-\\u07F9\\u0830-\\u083E\\u085E\\u0964\\u0965\\u0970\\u09FD\\u0A76\\u0AF0\\u0C84\\u0DF4\\u0E4F\\u0E5A\\u0E5B\\u0F04-\\u0F12\\u0F14\\u0F3A-\\u0F3D\\u0F85\\u0FD0-\\u0FD4\\u0FD9\\u0FDA\\u104A-\\u104F\\u10FB\\u1360-\\u1368\\u1400\\u166D\\u166E\\u169B\\u169C\\u16EB-\\u16ED\\u1735\\u1736\\u17D4-\\u17D6\\u17D8-\\u17DA\\u1800-\\u180A\\u1944\\u1945\\u1A1E\\u1A1F\\u1AA0-\\u1AA6\\u1AA8-\\u1AAD\\u1B5A-\\u1B60\\u1BFC-\\u1BFF\\u1C3B-\\u1C3F\\u1C7E\\u1C7F\\u1CC0-\\u1CC7\\u1CD3\\u2010-\\u2027\\u2030-\\u2043\\u2045-\\u2051\\u2053-\\u205E\\u207D\\u207E\\u208D\\u208E\\u2308-\\u230B\\u2329\\u232A\\u2768-\\u2775\\u27C5\\u27C6\\u27E6-\\u27EF\\u2983-\\u2998\\u29D8-\\u29DB\\u29FC\\u29FD\\u2CF9-\\u2CFC\\u2CFE\\u2CFF\\u2D70\\u2E00-\\u2E2E\\u2E30-\\u2E4E\\u3001-\\u3003\\u3008-\\u3011\\u3014-\\u301F\\u3030\\u303D\\u30A0\\u30FB\\uA4FE\\uA4FF\\uA60D-\\uA60F\\uA673\\uA67E\\uA6F2-\\uA6F7\\uA874-\\uA877\\uA8CE\\uA8CF\\uA8F8-\\uA8FA\\uA8FC\\uA92E\\uA92F\\uA95F\\uA9C1-\\uA9CD\\uA9DE\\uA9DF\\uAA5C-\\uAA5F\\uAADE\\uAADF\\uAAF0\\uAAF1\\uABEB\\uFD3E\\uFD3F\\uFE10-\\uFE19\\uFE30-\\uFE52\\uFE54-\\uFE61\\uFE63\\uFE68\\uFE6A\\uFE6B\\uFF01-\\uFF03\\uFF05-\\uFF0A\\uFF0C-\\uFF0F\\uFF1A\\uFF1B\\uFF1F\\uFF20\\uFF3B-\\uFF3D\\uFF3F\\uFF5B\\uFF5D\\uFF5F-\\uFF65]|\\uD800[\\uDD00-\\uDD02\\uDF9F\\uDFD0]|\\uD801\\uDD6F|\\uD802[\\uDC57\\uDD1F\\uDD3F\\uDE50-\\uDE58\\uDE7F\\uDEF0-\\uDEF6\\uDF39-\\uDF3F\\uDF99-\\uDF9C]|\\uD803[\\uDF55-\\uDF59]|\\uD804[\\uDC47-\\uDC4D\\uDCBB\\uDCBC\\uDCBE-\\uDCC1\\uDD40-\\uDD43\\uDD74\\uDD75\\uDDC5-\\uDDC8\\uDDCD\\uDDDB\\uDDDD-\\uDDDF\\uDE38-\\uDE3D\\uDEA9]|\\uD805[\\uDC4B-\\uDC4F\\uDC5B\\uDC5D\\uDCC6\\uDDC1-\\uDDD7\\uDE41-\\uDE43\\uDE60-\\uDE6C\\uDF3C-\\uDF3E]|\\uD806[\\uDC3B\\uDE3F-\\uDE46\\uDE9A-\\uDE9C\\uDE9E-\\uDEA2]|\\uD807[\\uDC41-\\uDC45\\uDC70\\uDC71\\uDEF7\\uDEF8]|\\uD809[\\uDC70-\\uDC74]|\\uD81A[\\uDE6E\\uDE6F\\uDEF5\\uDF37-\\uDF3B\\uDF44]|\\uD81B[\\uDE97-\\uDE9A]|\\uD82F\\uDC9F|\\uD836[\\uDE87-\\uDE8B]|\\uD83A[\\uDD5E\\uDD5F]/","/**\n * class Renderer\n *\n * Generates HTML from parsed token stream. Each instance has independent\n * copy of rules. Those can be rewritten with ease. Also, you can add new\n * rules if you create plugin and adds new token types.\n **/\n'use strict';\n\n\nvar assign = require('./common/utils').assign;\nvar unescapeAll = require('./common/utils').unescapeAll;\nvar escapeHtml = require('./common/utils').escapeHtml;\n\n\n////////////////////////////////////////////////////////////////////////////////\n\nvar default_rules = {};\n\n\ndefault_rules.code_inline = function (tokens, idx, options, env, slf) {\n var token = tokens[idx];\n\n return '' +\n escapeHtml(tokens[idx].content) +\n '';\n};\n\n\ndefault_rules.code_block = function (tokens, idx, options, env, slf) {\n var token = tokens[idx];\n\n return '' +\n escapeHtml(tokens[idx].content) +\n '\\n';\n};\n\n\ndefault_rules.fence = function (tokens, idx, options, env, slf) {\n var token = tokens[idx],\n info = token.info ? unescapeAll(token.info).trim() : '',\n langName = '',\n langAttrs = '',\n highlighted, i, arr, tmpAttrs, tmpToken;\n\n if (info) {\n arr = info.split(/(\\s+)/g);\n langName = arr[0];\n langAttrs = arr.slice(2).join('');\n }\n\n if (options.highlight) {\n highlighted = options.highlight(token.content, langName, langAttrs) || escapeHtml(token.content);\n } else {\n highlighted = escapeHtml(token.content);\n }\n\n if (highlighted.indexOf(''\n + highlighted\n + '\\n';\n }\n\n\n return '

'\n        + highlighted\n        + '
\\n';\n};\n\n\ndefault_rules.image = function (tokens, idx, options, env, slf) {\n var token = tokens[idx];\n\n // \"alt\" attr MUST be set, even if empty. Because it's mandatory and\n // should be placed on proper position for tests.\n //\n // Replace content with actual value\n\n token.attrs[token.attrIndex('alt')][1] =\n slf.renderInlineAsText(token.children, options, env);\n\n return slf.renderToken(tokens, idx, options);\n};\n\n\ndefault_rules.hardbreak = function (tokens, idx, options /*, env */) {\n return options.xhtmlOut ? '
\\n' : '
\\n';\n};\ndefault_rules.softbreak = function (tokens, idx, options /*, env */) {\n return options.breaks ? (options.xhtmlOut ? '
\\n' : '
\\n') : '\\n';\n};\n\n\ndefault_rules.text = function (tokens, idx /*, options, env */) {\n return escapeHtml(tokens[idx].content);\n};\n\n\ndefault_rules.html_block = function (tokens, idx /*, options, env */) {\n return tokens[idx].content;\n};\ndefault_rules.html_inline = function (tokens, idx /*, options, env */) {\n return tokens[idx].content;\n};\n\n\n/**\n * new Renderer()\n *\n * Creates new [[Renderer]] instance and fill [[Renderer#rules]] with defaults.\n **/\nfunction Renderer() {\n\n /**\n * Renderer#rules -> Object\n *\n * Contains render rules for tokens. Can be updated and extended.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')();\n *\n * md.renderer.rules.strong_open = function () { return ''; };\n * md.renderer.rules.strong_close = function () { return ''; };\n *\n * var result = md.renderInline(...);\n * ```\n *\n * Each rule is called as independent static function with fixed signature:\n *\n * ```javascript\n * function my_token_render(tokens, idx, options, env, renderer) {\n * // ...\n * return renderedHTML;\n * }\n * ```\n *\n * See [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js)\n * for more details and examples.\n **/\n this.rules = assign({}, default_rules);\n}\n\n\n/**\n * Renderer.renderAttrs(token) -> String\n *\n * Render token attributes to string.\n **/\nRenderer.prototype.renderAttrs = function renderAttrs(token) {\n var i, l, result;\n\n if (!token.attrs) { return ''; }\n\n result = '';\n\n for (i = 0, l = token.attrs.length; i < l; i++) {\n result += ' ' + escapeHtml(token.attrs[i][0]) + '=\"' + escapeHtml(token.attrs[i][1]) + '\"';\n }\n\n return result;\n};\n\n\n/**\n * Renderer.renderToken(tokens, idx, options) -> String\n * - tokens (Array): list of tokens\n * - idx (Numbed): token index to render\n * - options (Object): params of parser instance\n *\n * Default token renderer. Can be overriden by custom function\n * in [[Renderer#rules]].\n **/\nRenderer.prototype.renderToken = function renderToken(tokens, idx, options) {\n var nextToken,\n result = '',\n needLf = false,\n token = tokens[idx];\n\n // Tight list paragraphs\n if (token.hidden) {\n return '';\n }\n\n // Insert a newline between hidden paragraph and subsequent opening\n // block-level tag.\n //\n // For example, here we should insert a newline before blockquote:\n // - a\n // >\n //\n if (token.block && token.nesting !== -1 && idx && tokens[idx - 1].hidden) {\n result += '\\n';\n }\n\n // Add token name, e.g. ``.\n //\n needLf = false;\n }\n }\n }\n }\n\n result += needLf ? '>\\n' : '>';\n\n return result;\n};\n\n\n/**\n * Renderer.renderInline(tokens, options, env) -> String\n * - tokens (Array): list on block tokens to render\n * - options (Object): params of parser instance\n * - env (Object): additional data from parsed input (references, for example)\n *\n * The same as [[Renderer.render]], but for single token of `inline` type.\n **/\nRenderer.prototype.renderInline = function (tokens, options, env) {\n var type,\n result = '',\n rules = this.rules;\n\n for (var i = 0, len = tokens.length; i < len; i++) {\n type = tokens[i].type;\n\n if (typeof rules[type] !== 'undefined') {\n result += rules[type](tokens, i, options, env, this);\n } else {\n result += this.renderToken(tokens, i, options);\n }\n }\n\n return result;\n};\n\n\n/** internal\n * Renderer.renderInlineAsText(tokens, options, env) -> String\n * - tokens (Array): list on block tokens to render\n * - options (Object): params of parser instance\n * - env (Object): additional data from parsed input (references, for example)\n *\n * Special kludge for image `alt` attributes to conform CommonMark spec.\n * Don't try to use it! Spec requires to show `alt` content with stripped markup,\n * instead of simple escaping.\n **/\nRenderer.prototype.renderInlineAsText = function (tokens, options, env) {\n var result = '';\n\n for (var i = 0, len = tokens.length; i < len; i++) {\n if (tokens[i].type === 'text') {\n result += tokens[i].content;\n } else if (tokens[i].type === 'image') {\n result += this.renderInlineAsText(tokens[i].children, options, env);\n } else if (tokens[i].type === 'softbreak') {\n result += '\\n';\n }\n }\n\n return result;\n};\n\n\n/**\n * Renderer.render(tokens, options, env) -> String\n * - tokens (Array): list on block tokens to render\n * - options (Object): params of parser instance\n * - env (Object): additional data from parsed input (references, for example)\n *\n * Takes token stream and generates HTML. Probably, you will never need to call\n * this method directly.\n **/\nRenderer.prototype.render = function (tokens, options, env) {\n var i, len, type,\n result = '',\n rules = this.rules;\n\n for (i = 0, len = tokens.length; i < len; i++) {\n type = tokens[i].type;\n\n if (type === 'inline') {\n result += this.renderInline(tokens[i].children, options, env);\n } else if (typeof rules[type] !== 'undefined') {\n result += rules[tokens[i].type](tokens, i, options, env, this);\n } else {\n result += this.renderToken(tokens, i, options, env);\n }\n }\n\n return result;\n};\n\nmodule.exports = Renderer;\n","// Parse link title\n//\n'use strict';\n\n\nvar unescapeAll = require('../common/utils').unescapeAll;\n\n\nmodule.exports = function parseLinkTitle(str, pos, max) {\n var code,\n marker,\n lines = 0,\n start = pos,\n result = {\n ok: false,\n pos: 0,\n lines: 0,\n str: ''\n };\n\n if (pos >= max) { return result; }\n\n marker = str.charCodeAt(pos);\n\n if (marker !== 0x22 /* \" */ && marker !== 0x27 /* ' */ && marker !== 0x28 /* ( */) { return result; }\n\n pos++;\n\n // if opening marker is \"(\", switch it to closing marker \")\"\n if (marker === 0x28) { marker = 0x29; }\n\n while (pos < max) {\n code = str.charCodeAt(pos);\n if (code === marker) {\n result.pos = pos + 1;\n result.lines = lines;\n result.str = unescapeAll(str.slice(start + 1, pos));\n result.ok = true;\n return result;\n } else if (code === 0x28 /* ( */ && marker === 0x29 /* ) */) {\n return result;\n } else if (code === 0x0A) {\n lines++;\n } else if (code === 0x5C /* \\ */ && pos + 1 < max) {\n pos++;\n if (str.charCodeAt(pos) === 0x0A) {\n lines++;\n }\n }\n\n pos++;\n }\n\n return result;\n};\n","// GFM table, https://github.github.com/gfm/#tables-extension-\n\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\n\nfunction getLine(state, line) {\n var pos = state.bMarks[line] + state.tShift[line],\n max = state.eMarks[line];\n\n return state.src.substr(pos, max - pos);\n}\n\nfunction escapedSplit(str) {\n var result = [],\n pos = 0,\n max = str.length,\n ch,\n isEscaped = false,\n lastPos = 0,\n current = '';\n\n ch = str.charCodeAt(pos);\n\n while (pos < max) {\n if (ch === 0x7c/* | */) {\n if (!isEscaped) {\n // pipe separating cells, '|'\n result.push(current + str.substring(lastPos, pos));\n current = '';\n lastPos = pos + 1;\n } else {\n // escaped pipe, '\\|'\n current += str.substring(lastPos, pos - 1);\n lastPos = pos;\n }\n }\n\n isEscaped = (ch === 0x5c/* \\ */);\n pos++;\n\n ch = str.charCodeAt(pos);\n }\n\n result.push(current + str.substring(lastPos));\n\n return result;\n}\n\n\nmodule.exports = function table(state, startLine, endLine, silent) {\n var ch, lineText, pos, i, l, nextLine, columns, columnCount, token,\n aligns, t, tableLines, tbodyLines, oldParentType, terminate,\n terminatorRules, firstCh, secondCh;\n\n // should have at least two lines\n if (startLine + 2 > endLine) { return false; }\n\n nextLine = startLine + 1;\n\n if (state.sCount[nextLine] < state.blkIndent) { return false; }\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[nextLine] - state.blkIndent >= 4) { return false; }\n\n // first character of the second line should be '|', '-', ':',\n // and no other characters are allowed but spaces;\n // basically, this is the equivalent of /^[-:|][-:|\\s]*$/ regexp\n\n pos = state.bMarks[nextLine] + state.tShift[nextLine];\n if (pos >= state.eMarks[nextLine]) { return false; }\n\n firstCh = state.src.charCodeAt(pos++);\n if (firstCh !== 0x7C/* | */ && firstCh !== 0x2D/* - */ && firstCh !== 0x3A/* : */) { return false; }\n\n if (pos >= state.eMarks[nextLine]) { return false; }\n\n secondCh = state.src.charCodeAt(pos++);\n if (secondCh !== 0x7C/* | */ && secondCh !== 0x2D/* - */ && secondCh !== 0x3A/* : */ && !isSpace(secondCh)) {\n return false;\n }\n\n // if first character is '-', then second character must not be a space\n // (due to parsing ambiguity with list)\n if (firstCh === 0x2D/* - */ && isSpace(secondCh)) { return false; }\n\n while (pos < state.eMarks[nextLine]) {\n ch = state.src.charCodeAt(pos);\n\n if (ch !== 0x7C/* | */ && ch !== 0x2D/* - */ && ch !== 0x3A/* : */ && !isSpace(ch)) { return false; }\n\n pos++;\n }\n\n lineText = getLine(state, startLine + 1);\n\n columns = lineText.split('|');\n aligns = [];\n for (i = 0; i < columns.length; i++) {\n t = columns[i].trim();\n if (!t) {\n // allow empty columns before and after table, but not in between columns;\n // e.g. allow ` |---| `, disallow ` ---||--- `\n if (i === 0 || i === columns.length - 1) {\n continue;\n } else {\n return false;\n }\n }\n\n if (!/^:?-+:?$/.test(t)) { return false; }\n if (t.charCodeAt(t.length - 1) === 0x3A/* : */) {\n aligns.push(t.charCodeAt(0) === 0x3A/* : */ ? 'center' : 'right');\n } else if (t.charCodeAt(0) === 0x3A/* : */) {\n aligns.push('left');\n } else {\n aligns.push('');\n }\n }\n\n lineText = getLine(state, startLine).trim();\n if (lineText.indexOf('|') === -1) { return false; }\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n columns = escapedSplit(lineText);\n if (columns.length && columns[0] === '') columns.shift();\n if (columns.length && columns[columns.length - 1] === '') columns.pop();\n\n // header row will define an amount of columns in the entire table,\n // and align row should be exactly the same (the rest of the rows can differ)\n columnCount = columns.length;\n if (columnCount === 0 || columnCount !== aligns.length) { return false; }\n\n if (silent) { return true; }\n\n oldParentType = state.parentType;\n state.parentType = 'table';\n\n // use 'blockquote' lists for termination because it's\n // the most similar to tables\n terminatorRules = state.md.block.ruler.getRules('blockquote');\n\n token = state.push('table_open', 'table', 1);\n token.map = tableLines = [ startLine, 0 ];\n\n token = state.push('thead_open', 'thead', 1);\n token.map = [ startLine, startLine + 1 ];\n\n token = state.push('tr_open', 'tr', 1);\n token.map = [ startLine, startLine + 1 ];\n\n for (i = 0; i < columns.length; i++) {\n token = state.push('th_open', 'th', 1);\n if (aligns[i]) {\n token.attrs = [ [ 'style', 'text-align:' + aligns[i] ] ];\n }\n\n token = state.push('inline', '', 0);\n token.content = columns[i].trim();\n token.children = [];\n\n token = state.push('th_close', 'th', -1);\n }\n\n token = state.push('tr_close', 'tr', -1);\n token = state.push('thead_close', 'thead', -1);\n\n for (nextLine = startLine + 2; nextLine < endLine; nextLine++) {\n if (state.sCount[nextLine] < state.blkIndent) { break; }\n\n terminate = false;\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n\n if (terminate) { break; }\n lineText = getLine(state, nextLine).trim();\n if (!lineText) { break; }\n if (state.sCount[nextLine] - state.blkIndent >= 4) { break; }\n columns = escapedSplit(lineText);\n if (columns.length && columns[0] === '') columns.shift();\n if (columns.length && columns[columns.length - 1] === '') columns.pop();\n\n if (nextLine === startLine + 2) {\n token = state.push('tbody_open', 'tbody', 1);\n token.map = tbodyLines = [ startLine + 2, 0 ];\n }\n\n token = state.push('tr_open', 'tr', 1);\n token.map = [ nextLine, nextLine + 1 ];\n\n for (i = 0; i < columnCount; i++) {\n token = state.push('td_open', 'td', 1);\n if (aligns[i]) {\n token.attrs = [ [ 'style', 'text-align:' + aligns[i] ] ];\n }\n\n token = state.push('inline', '', 0);\n token.content = columns[i] ? columns[i].trim() : '';\n token.children = [];\n\n token = state.push('td_close', 'td', -1);\n }\n token = state.push('tr_close', 'tr', -1);\n }\n\n if (tbodyLines) {\n token = state.push('tbody_close', 'tbody', -1);\n tbodyLines[1] = nextLine;\n }\n\n token = state.push('table_close', 'table', -1);\n tableLines[1] = nextLine;\n\n state.parentType = oldParentType;\n state.line = nextLine;\n return true;\n};\n","// Parser state class\n\n'use strict';\n\nvar Token = require('../token');\nvar isSpace = require('../common/utils').isSpace;\n\n\nfunction StateBlock(src, md, env, tokens) {\n var ch, s, start, pos, len, indent, offset, indent_found;\n\n this.src = src;\n\n // link to parser instance\n this.md = md;\n\n this.env = env;\n\n //\n // Internal state vartiables\n //\n\n this.tokens = tokens;\n\n this.bMarks = []; // line begin offsets for fast jumps\n this.eMarks = []; // line end offsets for fast jumps\n this.tShift = []; // offsets of the first non-space characters (tabs not expanded)\n this.sCount = []; // indents for each line (tabs expanded)\n\n // An amount of virtual spaces (tabs expanded) between beginning\n // of each line (bMarks) and real beginning of that line.\n //\n // It exists only as a hack because blockquotes override bMarks\n // losing information in the process.\n //\n // It's used only when expanding tabs, you can think about it as\n // an initial tab length, e.g. bsCount=21 applied to string `\\t123`\n // means first tab should be expanded to 4-21%4 === 3 spaces.\n //\n this.bsCount = [];\n\n // block parser variables\n this.blkIndent = 0; // required block content indent (for example, if we are\n // inside a list, it would be positioned after list marker)\n this.line = 0; // line index in src\n this.lineMax = 0; // lines count\n this.tight = false; // loose/tight mode for lists\n this.ddIndent = -1; // indent of the current dd block (-1 if there isn't any)\n this.listIndent = -1; // indent of the current list block (-1 if there isn't any)\n\n // can be 'blockquote', 'list', 'root', 'paragraph' or 'reference'\n // used in lists to determine if they interrupt a paragraph\n this.parentType = 'root';\n\n this.level = 0;\n\n // renderer\n this.result = '';\n\n // Create caches\n // Generate markers.\n s = this.src;\n indent_found = false;\n\n for (start = pos = indent = offset = 0, len = s.length; pos < len; pos++) {\n ch = s.charCodeAt(pos);\n\n if (!indent_found) {\n if (isSpace(ch)) {\n indent++;\n\n if (ch === 0x09) {\n offset += 4 - offset % 4;\n } else {\n offset++;\n }\n continue;\n } else {\n indent_found = true;\n }\n }\n\n if (ch === 0x0A || pos === len - 1) {\n if (ch !== 0x0A) { pos++; }\n this.bMarks.push(start);\n this.eMarks.push(pos);\n this.tShift.push(indent);\n this.sCount.push(offset);\n this.bsCount.push(0);\n\n indent_found = false;\n indent = 0;\n offset = 0;\n start = pos + 1;\n }\n }\n\n // Push fake entry to simplify cache bounds checks\n this.bMarks.push(s.length);\n this.eMarks.push(s.length);\n this.tShift.push(0);\n this.sCount.push(0);\n this.bsCount.push(0);\n\n this.lineMax = this.bMarks.length - 1; // don't count last fake line\n}\n\n// Push new token to \"stream\".\n//\nStateBlock.prototype.push = function (type, tag, nesting) {\n var token = new Token(type, tag, nesting);\n token.block = true;\n\n if (nesting < 0) this.level--; // closing tag\n token.level = this.level;\n if (nesting > 0) this.level++; // opening tag\n\n this.tokens.push(token);\n return token;\n};\n\nStateBlock.prototype.isEmpty = function isEmpty(line) {\n return this.bMarks[line] + this.tShift[line] >= this.eMarks[line];\n};\n\nStateBlock.prototype.skipEmptyLines = function skipEmptyLines(from) {\n for (var max = this.lineMax; from < max; from++) {\n if (this.bMarks[from] + this.tShift[from] < this.eMarks[from]) {\n break;\n }\n }\n return from;\n};\n\n// Skip spaces from given position.\nStateBlock.prototype.skipSpaces = function skipSpaces(pos) {\n var ch;\n\n for (var max = this.src.length; pos < max; pos++) {\n ch = this.src.charCodeAt(pos);\n if (!isSpace(ch)) { break; }\n }\n return pos;\n};\n\n// Skip spaces from given position in reverse.\nStateBlock.prototype.skipSpacesBack = function skipSpacesBack(pos, min) {\n if (pos <= min) { return pos; }\n\n while (pos > min) {\n if (!isSpace(this.src.charCodeAt(--pos))) { return pos + 1; }\n }\n return pos;\n};\n\n// Skip char codes from given position\nStateBlock.prototype.skipChars = function skipChars(pos, code) {\n for (var max = this.src.length; pos < max; pos++) {\n if (this.src.charCodeAt(pos) !== code) { break; }\n }\n return pos;\n};\n\n// Skip char codes reverse from given position - 1\nStateBlock.prototype.skipCharsBack = function skipCharsBack(pos, code, min) {\n if (pos <= min) { return pos; }\n\n while (pos > min) {\n if (code !== this.src.charCodeAt(--pos)) { return pos + 1; }\n }\n return pos;\n};\n\n// cut lines range from source.\nStateBlock.prototype.getLines = function getLines(begin, end, indent, keepLastLF) {\n var i, lineIndent, ch, first, last, queue, lineStart,\n line = begin;\n\n if (begin >= end) {\n return '';\n }\n\n queue = new Array(end - begin);\n\n for (i = 0; line < end; line++, i++) {\n lineIndent = 0;\n lineStart = first = this.bMarks[line];\n\n if (line + 1 < end || keepLastLF) {\n // No need for bounds check because we have fake entry on tail.\n last = this.eMarks[line] + 1;\n } else {\n last = this.eMarks[line];\n }\n\n while (first < last && lineIndent < indent) {\n ch = this.src.charCodeAt(first);\n\n if (isSpace(ch)) {\n if (ch === 0x09) {\n lineIndent += 4 - (lineIndent + this.bsCount[line]) % 4;\n } else {\n lineIndent++;\n }\n } else if (first - lineStart < this.tShift[line]) {\n // patched tShift masked characters to look like spaces (blockquotes, list markers)\n lineIndent++;\n } else {\n break;\n }\n\n first++;\n }\n\n if (lineIndent > indent) {\n // partially expanding tabs in code blocks, e.g '\\t\\tfoobar'\n // with indent=2 becomes ' \\tfoobar'\n queue[i] = new Array(lineIndent - indent + 1).join(' ') + this.src.slice(first, last);\n } else {\n queue[i] = this.src.slice(first, last);\n }\n }\n\n return queue.join('');\n};\n\n// re-export Token class to use in block rules\nStateBlock.prototype.Token = Token;\n\n\nmodule.exports = StateBlock;\n","// For each opening emphasis-like marker find a matching closing one\n//\n'use strict';\n\n\nfunction processDelimiters(state, delimiters) {\n var closerIdx, openerIdx, closer, opener, minOpenerIdx, newMinOpenerIdx,\n isOddMatch, lastJump,\n openersBottom = {},\n max = delimiters.length;\n\n if (!max) return;\n\n // headerIdx is the first delimiter of the current (where closer is) delimiter run\n var headerIdx = 0;\n var lastTokenIdx = -2; // needs any value lower than -1\n var jumps = [];\n\n for (closerIdx = 0; closerIdx < max; closerIdx++) {\n closer = delimiters[closerIdx];\n\n jumps.push(0);\n\n // markers belong to same delimiter run if:\n // - they have adjacent tokens\n // - AND markers are the same\n //\n if (delimiters[headerIdx].marker !== closer.marker || lastTokenIdx !== closer.token - 1) {\n headerIdx = closerIdx;\n }\n\n lastTokenIdx = closer.token;\n\n // Length is only used for emphasis-specific \"rule of 3\",\n // if it's not defined (in strikethrough or 3rd party plugins),\n // we can default it to 0 to disable those checks.\n //\n closer.length = closer.length || 0;\n\n if (!closer.close) continue;\n\n // Previously calculated lower bounds (previous fails)\n // for each marker, each delimiter length modulo 3,\n // and for whether this closer can be an opener;\n // https://github.com/commonmark/cmark/commit/34250e12ccebdc6372b8b49c44fab57c72443460\n if (!openersBottom.hasOwnProperty(closer.marker)) {\n openersBottom[closer.marker] = [ -1, -1, -1, -1, -1, -1 ];\n }\n\n minOpenerIdx = openersBottom[closer.marker][(closer.open ? 3 : 0) + (closer.length % 3)];\n\n openerIdx = headerIdx - jumps[headerIdx] - 1;\n\n newMinOpenerIdx = openerIdx;\n\n for (; openerIdx > minOpenerIdx; openerIdx -= jumps[openerIdx] + 1) {\n opener = delimiters[openerIdx];\n\n if (opener.marker !== closer.marker) continue;\n\n if (opener.open && opener.end < 0) {\n\n isOddMatch = false;\n\n // from spec:\n //\n // If one of the delimiters can both open and close emphasis, then the\n // sum of the lengths of the delimiter runs containing the opening and\n // closing delimiters must not be a multiple of 3 unless both lengths\n // are multiples of 3.\n //\n if (opener.close || closer.open) {\n if ((opener.length + closer.length) % 3 === 0) {\n if (opener.length % 3 !== 0 || closer.length % 3 !== 0) {\n isOddMatch = true;\n }\n }\n }\n\n if (!isOddMatch) {\n // If previous delimiter cannot be an opener, we can safely skip\n // the entire sequence in future checks. This is required to make\n // sure algorithm has linear complexity (see *_*_*_*_*_... case).\n //\n lastJump = openerIdx > 0 && !delimiters[openerIdx - 1].open ?\n jumps[openerIdx - 1] + 1 :\n 0;\n\n jumps[closerIdx] = closerIdx - openerIdx + lastJump;\n jumps[openerIdx] = lastJump;\n\n closer.open = false;\n opener.end = closerIdx;\n opener.close = false;\n newMinOpenerIdx = -1;\n // treat next token as start of run,\n // it optimizes skips in **<...>**a**<...>** pathological case\n lastTokenIdx = -2;\n break;\n }\n }\n }\n\n if (newMinOpenerIdx !== -1) {\n // If match for this delimiter run failed, we want to set lower bound for\n // future lookups. This is required to make sure algorithm has linear\n // complexity.\n //\n // See details here:\n // https://github.com/commonmark/cmark/issues/178#issuecomment-270417442\n //\n openersBottom[closer.marker][(closer.open ? 3 : 0) + ((closer.length || 0) % 3)] = newMinOpenerIdx;\n }\n }\n}\n\n\nmodule.exports = function link_pairs(state) {\n var curr,\n tokens_meta = state.tokens_meta,\n max = state.tokens_meta.length;\n\n processDelimiters(state, state.delimiters);\n\n for (curr = 0; curr < max; curr++) {\n if (tokens_meta[curr] && tokens_meta[curr].delimiters) {\n processDelimiters(state, tokens_meta[curr].delimiters);\n }\n }\n};\n","'use strict';\n\nvar isAbsoluteURL = require('../helpers/isAbsoluteURL');\nvar combineURLs = require('../helpers/combineURLs');\n\n/**\n * Creates a new URL by combining the baseURL with the requestedURL,\n * only when the requestedURL is not already an absolute URL.\n * If the requestURL is absolute, this function returns the requestedURL untouched.\n *\n * @param {string} baseURL The base URL\n * @param {string} requestedURL Absolute or relative URL to combine\n * @returns {string} The combined full path\n */\nmodule.exports = function buildFullPath(baseURL, requestedURL) {\n if (baseURL && !isAbsoluteURL(requestedURL)) {\n return combineURLs(baseURL, requestedURL);\n }\n return requestedURL;\n};\n","'use strict';\n\nvar pkg = require('./../../package.json');\n\nvar validators = {};\n\n// eslint-disable-next-line func-names\n['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach(function(type, i) {\n validators[type] = function validator(thing) {\n return typeof thing === type || 'a' + (i < 1 ? 'n ' : ' ') + type;\n };\n});\n\nvar deprecatedWarnings = {};\nvar currentVerArr = pkg.version.split('.');\n\n/**\n * Compare package versions\n * @param {string} version\n * @param {string?} thanVersion\n * @returns {boolean}\n */\nfunction isOlderVersion(version, thanVersion) {\n var pkgVersionArr = thanVersion ? thanVersion.split('.') : currentVerArr;\n var destVer = version.split('.');\n for (var i = 0; i < 3; i++) {\n if (pkgVersionArr[i] > destVer[i]) {\n return true;\n } else if (pkgVersionArr[i] < destVer[i]) {\n return false;\n }\n }\n return false;\n}\n\n/**\n * Transitional option validator\n * @param {function|boolean?} validator\n * @param {string?} version\n * @param {string} message\n * @returns {function}\n */\nvalidators.transitional = function transitional(validator, version, message) {\n var isDeprecated = version && isOlderVersion(version);\n\n function formatMessage(opt, desc) {\n return '[Axios v' + pkg.version + '] Transitional option \\'' + opt + '\\'' + desc + (message ? '. ' + message : '');\n }\n\n // eslint-disable-next-line func-names\n return function(value, opt, opts) {\n if (validator === false) {\n throw new Error(formatMessage(opt, ' has been removed in ' + version));\n }\n\n if (isDeprecated && !deprecatedWarnings[opt]) {\n deprecatedWarnings[opt] = true;\n // eslint-disable-next-line no-console\n console.warn(\n formatMessage(\n opt,\n ' has been deprecated since v' + version + ' and will be removed in the near future'\n )\n );\n }\n\n return validator ? validator(value, opt, opts) : true;\n };\n};\n\n/**\n * Assert object's properties type\n * @param {object} options\n * @param {object} schema\n * @param {boolean?} allowUnknown\n */\n\nfunction assertOptions(options, schema, allowUnknown) {\n if (typeof options !== 'object') {\n throw new TypeError('options must be an object');\n }\n var keys = Object.keys(options);\n var i = keys.length;\n while (i-- > 0) {\n var opt = keys[i];\n var validator = schema[opt];\n if (validator) {\n var value = options[opt];\n var result = value === undefined || validator(value, opt, options);\n if (result !== true) {\n throw new TypeError('option ' + opt + ' must be ' + result);\n }\n continue;\n }\n if (allowUnknown !== true) {\n throw Error('Unknown option ' + opt);\n }\n }\n}\n\nmodule.exports = {\n isOlderVersion: isOlderVersion,\n assertOptions: assertOptions,\n validators: validators\n};\n","// markdown-it default options\n\n'use strict';\n\n\nmodule.exports = {\n options: {\n html: false, // Enable HTML tags in source\n xhtmlOut: false, // Use '/' to close single tags (
)\n breaks: false, // Convert '\\n' in paragraphs into
\n langPrefix: 'language-', // CSS language prefix for fenced blocks\n linkify: false, // autoconvert URL-like texts to links\n\n // Enable some language-neutral replacements + quotes beautification\n typographer: false,\n\n // Double + single quotes replacement pairs, when typographer enabled,\n // and smartquotes on. Could be either a String or an Array.\n //\n // For example, you can use '«»„“' for Russian, '„“‚‘' for German,\n // and ['«\\xA0', '\\xA0»', '‹\\xA0', '\\xA0›'] for French (including nbsp).\n quotes: '\\u201c\\u201d\\u2018\\u2019', /* “”‘’ */\n\n // Highlighter function. Should return escaped HTML,\n // or '' if the source string is not changed and should be escaped externaly.\n // If result starts with = 0xD800 && chr <= 0xDFFF)) {\n result += '\\ufffd\\ufffd\\ufffd';\n } else {\n result += String.fromCharCode(chr);\n }\n\n i += 6;\n continue;\n }\n }\n\n if ((b1 & 0xF8) === 0xF0 && (i + 9 < l)) {\n // 111110xx 10xxxxxx 10xxxxxx 10xxxxxx\n b2 = parseInt(seq.slice(i + 4, i + 6), 16);\n b3 = parseInt(seq.slice(i + 7, i + 9), 16);\n b4 = parseInt(seq.slice(i + 10, i + 12), 16);\n\n if ((b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80 && (b4 & 0xC0) === 0x80) {\n chr = ((b1 << 18) & 0x1C0000) | ((b2 << 12) & 0x3F000) | ((b3 << 6) & 0xFC0) | (b4 & 0x3F);\n\n if (chr < 0x10000 || chr > 0x10FFFF) {\n result += '\\ufffd\\ufffd\\ufffd\\ufffd';\n } else {\n chr -= 0x10000;\n result += String.fromCharCode(0xD800 + (chr >> 10), 0xDC00 + (chr & 0x3FF));\n }\n\n i += 9;\n continue;\n }\n }\n\n result += '\\ufffd';\n }\n\n return result;\n });\n}\n\n\ndecode.defaultChars = ';/?:@&=+$,#';\ndecode.componentChars = '';\n\n\nmodule.exports = decode;\n","// ~~strike through~~\n//\n'use strict';\n\n\n// Insert each marker as a separate text token, and add it to delimiter list\n//\nmodule.exports.tokenize = function strikethrough(state, silent) {\n var i, scanned, token, len, ch,\n start = state.pos,\n marker = state.src.charCodeAt(start);\n\n if (silent) { return false; }\n\n if (marker !== 0x7E/* ~ */) { return false; }\n\n scanned = state.scanDelims(state.pos, true);\n len = scanned.length;\n ch = String.fromCharCode(marker);\n\n if (len < 2) { return false; }\n\n if (len % 2) {\n token = state.push('text', '', 0);\n token.content = ch;\n len--;\n }\n\n for (i = 0; i < len; i += 2) {\n token = state.push('text', '', 0);\n token.content = ch + ch;\n\n state.delimiters.push({\n marker: marker,\n length: 0, // disable \"rule of 3\" length checks meant for emphasis\n token: state.tokens.length - 1,\n end: -1,\n open: scanned.can_open,\n close: scanned.can_close\n });\n }\n\n state.pos += scanned.length;\n\n return true;\n};\n\n\nfunction postProcess(state, delimiters) {\n var i, j,\n startDelim,\n endDelim,\n token,\n loneMarkers = [],\n max = delimiters.length;\n\n for (i = 0; i < max; i++) {\n startDelim = delimiters[i];\n\n if (startDelim.marker !== 0x7E/* ~ */) {\n continue;\n }\n\n if (startDelim.end === -1) {\n continue;\n }\n\n endDelim = delimiters[startDelim.end];\n\n token = state.tokens[startDelim.token];\n token.type = 's_open';\n token.tag = 's';\n token.nesting = 1;\n token.markup = '~~';\n token.content = '';\n\n token = state.tokens[endDelim.token];\n token.type = 's_close';\n token.tag = 's';\n token.nesting = -1;\n token.markup = '~~';\n token.content = '';\n\n if (state.tokens[endDelim.token - 1].type === 'text' &&\n state.tokens[endDelim.token - 1].content === '~') {\n\n loneMarkers.push(endDelim.token - 1);\n }\n }\n\n // If a marker sequence has an odd number of characters, it's splitted\n // like this: `~~~~~` -> `~` + `~~` + `~~`, leaving one marker at the\n // start of the sequence.\n //\n // So, we have to move all those markers after subsequent s_close tags.\n //\n while (loneMarkers.length) {\n i = loneMarkers.pop();\n j = i + 1;\n\n while (j < state.tokens.length && state.tokens[j].type === 's_close') {\n j++;\n }\n\n j--;\n\n if (i !== j) {\n token = state.tokens[j];\n state.tokens[j] = state.tokens[i];\n state.tokens[i] = token;\n }\n }\n}\n\n\n// Walk through delimiter list and replace text tokens with tags\n//\nmodule.exports.postProcess = function strikethrough(state) {\n var curr,\n tokens_meta = state.tokens_meta,\n max = state.tokens_meta.length;\n\n postProcess(state, state.delimiters);\n\n for (curr = 0; curr < max; curr++) {\n if (tokens_meta[curr] && tokens_meta[curr].delimiters) {\n postProcess(state, tokens_meta[curr].delimiters);\n }\n }\n};\n","// Process ![image]( \"title\")\n\n'use strict';\n\nvar normalizeReference = require('../common/utils').normalizeReference;\nvar isSpace = require('../common/utils').isSpace;\n\n\nmodule.exports = function image(state, silent) {\n var attrs,\n code,\n content,\n label,\n labelEnd,\n labelStart,\n pos,\n ref,\n res,\n title,\n token,\n tokens,\n start,\n href = '',\n oldPos = state.pos,\n max = state.posMax;\n\n if (state.src.charCodeAt(state.pos) !== 0x21/* ! */) { return false; }\n if (state.src.charCodeAt(state.pos + 1) !== 0x5B/* [ */) { return false; }\n\n labelStart = state.pos + 2;\n labelEnd = state.md.helpers.parseLinkLabel(state, state.pos + 1, false);\n\n // parser failed to find ']', so it's not a valid link\n if (labelEnd < 0) { return false; }\n\n pos = labelEnd + 1;\n if (pos < max && state.src.charCodeAt(pos) === 0x28/* ( */) {\n //\n // Inline link\n //\n\n // [link]( \"title\" )\n // ^^ skipping these spaces\n pos++;\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n if (!isSpace(code) && code !== 0x0A) { break; }\n }\n if (pos >= max) { return false; }\n\n // [link]( \"title\" )\n // ^^^^^^ parsing link destination\n start = pos;\n res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax);\n if (res.ok) {\n href = state.md.normalizeLink(res.str);\n if (state.md.validateLink(href)) {\n pos = res.pos;\n } else {\n href = '';\n }\n }\n\n // [link]( \"title\" )\n // ^^ skipping these spaces\n start = pos;\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n if (!isSpace(code) && code !== 0x0A) { break; }\n }\n\n // [link]( \"title\" )\n // ^^^^^^^ parsing link title\n res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax);\n if (pos < max && start !== pos && res.ok) {\n title = res.str;\n pos = res.pos;\n\n // [link]( \"title\" )\n // ^^ skipping these spaces\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n if (!isSpace(code) && code !== 0x0A) { break; }\n }\n } else {\n title = '';\n }\n\n if (pos >= max || state.src.charCodeAt(pos) !== 0x29/* ) */) {\n state.pos = oldPos;\n return false;\n }\n pos++;\n } else {\n //\n // Link reference\n //\n if (typeof state.env.references === 'undefined') { return false; }\n\n if (pos < max && state.src.charCodeAt(pos) === 0x5B/* [ */) {\n start = pos + 1;\n pos = state.md.helpers.parseLinkLabel(state, pos);\n if (pos >= 0) {\n label = state.src.slice(start, pos++);\n } else {\n pos = labelEnd + 1;\n }\n } else {\n pos = labelEnd + 1;\n }\n\n // covers label === '' and label === undefined\n // (collapsed reference link and shortcut reference link respectively)\n if (!label) { label = state.src.slice(labelStart, labelEnd); }\n\n ref = state.env.references[normalizeReference(label)];\n if (!ref) {\n state.pos = oldPos;\n return false;\n }\n href = ref.href;\n title = ref.title;\n }\n\n //\n // We found the end of the link, and know for a fact it's a valid link;\n // so all that's left to do is to call tokenizer.\n //\n if (!silent) {\n content = state.src.slice(labelStart, labelEnd);\n\n state.md.inline.parse(\n content,\n state.md,\n state.env,\n tokens = []\n );\n\n token = state.push('image', 'img', 0);\n token.attrs = attrs = [ [ 'src', href ], [ 'alt', '' ] ];\n token.children = tokens;\n token.content = content;\n\n if (title) {\n attrs.push([ 'title', title ]);\n }\n }\n\n state.pos = pos;\n state.posMax = max;\n return true;\n};\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('p',{domProps:{\"innerHTML\":_vm._s(_vm.parsed_md)}})])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./RemoteMarkdown.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./RemoteMarkdown.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./RemoteMarkdown.vue?vue&type=template&id=e9305c8c&\"\nimport script from \"./RemoteMarkdown.vue?vue&type=script&lang=js&\"\nexport * from \"./RemoteMarkdown.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","// Replace link-like texts with link nodes.\n//\n// Currently restricted by `md.validateLink()` to http/https/ftp\n//\n'use strict';\n\n\nvar arrayReplaceAt = require('../common/utils').arrayReplaceAt;\n\n\nfunction isLinkOpen(str) {\n return /^\\s]/i.test(str);\n}\nfunction isLinkClose(str) {\n return /^<\\/a\\s*>/i.test(str);\n}\n\n\nmodule.exports = function linkify(state) {\n var i, j, l, tokens, token, currentToken, nodes, ln, text, pos, lastPos,\n level, htmlLinkLevel, url, fullUrl, urlText,\n blockTokens = state.tokens,\n links;\n\n if (!state.md.options.linkify) { return; }\n\n for (j = 0, l = blockTokens.length; j < l; j++) {\n if (blockTokens[j].type !== 'inline' ||\n !state.md.linkify.pretest(blockTokens[j].content)) {\n continue;\n }\n\n tokens = blockTokens[j].children;\n\n htmlLinkLevel = 0;\n\n // We scan from the end, to keep position when new tags added.\n // Use reversed logic in links start/end match\n for (i = tokens.length - 1; i >= 0; i--) {\n currentToken = tokens[i];\n\n // Skip content of markdown links\n if (currentToken.type === 'link_close') {\n i--;\n while (tokens[i].level !== currentToken.level && tokens[i].type !== 'link_open') {\n i--;\n }\n continue;\n }\n\n // Skip content of html tag links\n if (currentToken.type === 'html_inline') {\n if (isLinkOpen(currentToken.content) && htmlLinkLevel > 0) {\n htmlLinkLevel--;\n }\n if (isLinkClose(currentToken.content)) {\n htmlLinkLevel++;\n }\n }\n if (htmlLinkLevel > 0) { continue; }\n\n if (currentToken.type === 'text' && state.md.linkify.test(currentToken.content)) {\n\n text = currentToken.content;\n links = state.md.linkify.match(text);\n\n // Now split string to nodes\n nodes = [];\n level = currentToken.level;\n lastPos = 0;\n\n for (ln = 0; ln < links.length; ln++) {\n\n url = links[ln].url;\n fullUrl = state.md.normalizeLink(url);\n if (!state.md.validateLink(fullUrl)) { continue; }\n\n urlText = links[ln].text;\n\n // Linkifier might send raw hostnames like \"example.com\", where url\n // starts with domain name. So we prepend http:// in those cases,\n // and remove it afterwards.\n //\n if (!links[ln].schema) {\n urlText = state.md.normalizeLinkText('http://' + urlText).replace(/^http:\\/\\//, '');\n } else if (links[ln].schema === 'mailto:' && !/^mailto:/i.test(urlText)) {\n urlText = state.md.normalizeLinkText('mailto:' + urlText).replace(/^mailto:/, '');\n } else {\n urlText = state.md.normalizeLinkText(urlText);\n }\n\n pos = links[ln].index;\n\n if (pos > lastPos) {\n token = new state.Token('text', '', 0);\n token.content = text.slice(lastPos, pos);\n token.level = level;\n nodes.push(token);\n }\n\n token = new state.Token('link_open', 'a', 1);\n token.attrs = [ [ 'href', fullUrl ] ];\n token.level = level++;\n token.markup = 'linkify';\n token.info = 'auto';\n nodes.push(token);\n\n token = new state.Token('text', '', 0);\n token.content = urlText;\n token.level = level;\n nodes.push(token);\n\n token = new state.Token('link_close', 'a', -1);\n token.level = --level;\n token.markup = 'linkify';\n token.info = 'auto';\n nodes.push(token);\n\n lastPos = links[ln].lastIndex;\n }\n if (lastPos < text.length) {\n token = new state.Token('text', '', 0);\n token.content = text.slice(lastPos);\n token.level = level;\n nodes.push(token);\n }\n\n // replace current node\n blockTokens[j].children = tokens = arrayReplaceAt(tokens, i, nodes);\n }\n }\n }\n};\n","// Code block (4 spaces padded)\n\n'use strict';\n\n\nmodule.exports = function code(state, startLine, endLine/*, silent*/) {\n var nextLine, last, token;\n\n if (state.sCount[startLine] - state.blkIndent < 4) { return false; }\n\n last = nextLine = startLine + 1;\n\n while (nextLine < endLine) {\n if (state.isEmpty(nextLine)) {\n nextLine++;\n continue;\n }\n\n if (state.sCount[nextLine] - state.blkIndent >= 4) {\n nextLine++;\n last = nextLine;\n continue;\n }\n break;\n }\n\n state.line = last;\n\n token = state.push('code_block', 'code', 0);\n token.content = state.getLines(startLine, last, 4 + state.blkIndent, false) + '\\n';\n token.map = [ startLine, state.line ];\n\n return true;\n};\n","'use strict';\n\nmodule.exports = function inline(state) {\n var tokens = state.tokens, tok, i, l;\n\n // Parse inlines\n for (i = 0, l = tokens.length; i < l; i++) {\n tok = tokens[i];\n if (tok.type === 'inline') {\n state.md.inline.parse(tok.content, state.md, state.env, tok.children);\n }\n }\n};\n","module.exports=/[\\0-\\x1F\\x7F-\\x9F]/","/** internal\n * class Core\n *\n * Top-level rules executor. Glues block/inline parsers and does intermediate\n * transformations.\n **/\n'use strict';\n\n\nvar Ruler = require('./ruler');\n\n\nvar _rules = [\n [ 'normalize', require('./rules_core/normalize') ],\n [ 'block', require('./rules_core/block') ],\n [ 'inline', require('./rules_core/inline') ],\n [ 'linkify', require('./rules_core/linkify') ],\n [ 'replacements', require('./rules_core/replacements') ],\n [ 'smartquotes', require('./rules_core/smartquotes') ]\n];\n\n\n/**\n * new Core()\n **/\nfunction Core() {\n /**\n * Core#ruler -> Ruler\n *\n * [[Ruler]] instance. Keep configuration of core rules.\n **/\n this.ruler = new Ruler();\n\n for (var i = 0; i < _rules.length; i++) {\n this.ruler.push(_rules[i][0], _rules[i][1]);\n }\n}\n\n\n/**\n * Core.process(state)\n *\n * Executes core chain rules.\n **/\nCore.prototype.process = function (state) {\n var i, l, rules;\n\n rules = this.ruler.getRules('');\n\n for (i = 0, l = rules.length; i < l; i++) {\n rules[i](state);\n }\n};\n\nCore.prototype.State = require('./rules_core/state_core');\n\n\nmodule.exports = Core;\n","// Convert straight quotation marks to typographic ones\n//\n'use strict';\n\n\nvar isWhiteSpace = require('../common/utils').isWhiteSpace;\nvar isPunctChar = require('../common/utils').isPunctChar;\nvar isMdAsciiPunct = require('../common/utils').isMdAsciiPunct;\n\nvar QUOTE_TEST_RE = /['\"]/;\nvar QUOTE_RE = /['\"]/g;\nvar APOSTROPHE = '\\u2019'; /* ’ */\n\n\nfunction replaceAt(str, index, ch) {\n return str.substr(0, index) + ch + str.substr(index + 1);\n}\n\nfunction process_inlines(tokens, state) {\n var i, token, text, t, pos, max, thisLevel, item, lastChar, nextChar,\n isLastPunctChar, isNextPunctChar, isLastWhiteSpace, isNextWhiteSpace,\n canOpen, canClose, j, isSingle, stack, openQuote, closeQuote;\n\n stack = [];\n\n for (i = 0; i < tokens.length; i++) {\n token = tokens[i];\n\n thisLevel = tokens[i].level;\n\n for (j = stack.length - 1; j >= 0; j--) {\n if (stack[j].level <= thisLevel) { break; }\n }\n stack.length = j + 1;\n\n if (token.type !== 'text') { continue; }\n\n text = token.content;\n pos = 0;\n max = text.length;\n\n /*eslint no-labels:0,block-scoped-var:0*/\n OUTER:\n while (pos < max) {\n QUOTE_RE.lastIndex = pos;\n t = QUOTE_RE.exec(text);\n if (!t) { break; }\n\n canOpen = canClose = true;\n pos = t.index + 1;\n isSingle = (t[0] === \"'\");\n\n // Find previous character,\n // default to space if it's the beginning of the line\n //\n lastChar = 0x20;\n\n if (t.index - 1 >= 0) {\n lastChar = text.charCodeAt(t.index - 1);\n } else {\n for (j = i - 1; j >= 0; j--) {\n if (tokens[j].type === 'softbreak' || tokens[j].type === 'hardbreak') break; // lastChar defaults to 0x20\n if (!tokens[j].content) continue; // should skip all tokens except 'text', 'html_inline' or 'code_inline'\n\n lastChar = tokens[j].content.charCodeAt(tokens[j].content.length - 1);\n break;\n }\n }\n\n // Find next character,\n // default to space if it's the end of the line\n //\n nextChar = 0x20;\n\n if (pos < max) {\n nextChar = text.charCodeAt(pos);\n } else {\n for (j = i + 1; j < tokens.length; j++) {\n if (tokens[j].type === 'softbreak' || tokens[j].type === 'hardbreak') break; // nextChar defaults to 0x20\n if (!tokens[j].content) continue; // should skip all tokens except 'text', 'html_inline' or 'code_inline'\n\n nextChar = tokens[j].content.charCodeAt(0);\n break;\n }\n }\n\n isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));\n isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));\n\n isLastWhiteSpace = isWhiteSpace(lastChar);\n isNextWhiteSpace = isWhiteSpace(nextChar);\n\n if (isNextWhiteSpace) {\n canOpen = false;\n } else if (isNextPunctChar) {\n if (!(isLastWhiteSpace || isLastPunctChar)) {\n canOpen = false;\n }\n }\n\n if (isLastWhiteSpace) {\n canClose = false;\n } else if (isLastPunctChar) {\n if (!(isNextWhiteSpace || isNextPunctChar)) {\n canClose = false;\n }\n }\n\n if (nextChar === 0x22 /* \" */ && t[0] === '\"') {\n if (lastChar >= 0x30 /* 0 */ && lastChar <= 0x39 /* 9 */) {\n // special case: 1\"\" - count first quote as an inch\n canClose = canOpen = false;\n }\n }\n\n if (canOpen && canClose) {\n // Replace quotes in the middle of punctuation sequence, but not\n // in the middle of the words, i.e.:\n //\n // 1. foo \" bar \" baz - not replaced\n // 2. foo-\"-bar-\"-baz - replaced\n // 3. foo\"bar\"baz - not replaced\n //\n canOpen = isLastPunctChar;\n canClose = isNextPunctChar;\n }\n\n if (!canOpen && !canClose) {\n // middle of word\n if (isSingle) {\n token.content = replaceAt(token.content, t.index, APOSTROPHE);\n }\n continue;\n }\n\n if (canClose) {\n // this could be a closing quote, rewind the stack to get a match\n for (j = stack.length - 1; j >= 0; j--) {\n item = stack[j];\n if (stack[j].level < thisLevel) { break; }\n if (item.single === isSingle && stack[j].level === thisLevel) {\n item = stack[j];\n\n if (isSingle) {\n openQuote = state.md.options.quotes[2];\n closeQuote = state.md.options.quotes[3];\n } else {\n openQuote = state.md.options.quotes[0];\n closeQuote = state.md.options.quotes[1];\n }\n\n // replace token.content *before* tokens[item.token].content,\n // because, if they are pointing at the same token, replaceAt\n // could mess up indices when quote length != 1\n token.content = replaceAt(token.content, t.index, closeQuote);\n tokens[item.token].content = replaceAt(\n tokens[item.token].content, item.pos, openQuote);\n\n pos += closeQuote.length - 1;\n if (item.token === i) { pos += openQuote.length - 1; }\n\n text = token.content;\n max = text.length;\n\n stack.length = j;\n continue OUTER;\n }\n }\n }\n\n if (canOpen) {\n stack.push({\n token: i,\n pos: t.index,\n single: isSingle,\n level: thisLevel\n });\n } else if (canClose && isSingle) {\n token.content = replaceAt(token.content, t.index, APOSTROPHE);\n }\n }\n }\n}\n\n\nmodule.exports = function smartquotes(state) {\n /*eslint max-depth:0*/\n var blkIdx;\n\n if (!state.md.options.typographer) { return; }\n\n for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {\n\n if (state.tokens[blkIdx].type !== 'inline' ||\n !QUOTE_TEST_RE.test(state.tokens[blkIdx].content)) {\n continue;\n }\n\n process_inlines(state.tokens[blkIdx].children, state);\n }\n};\n","'use strict';\n\n\nmodule.exports = function (opts) {\n var re = {};\n\n // Use direct extract instead of `regenerate` to reduse browserified size\n re.src_Any = require('uc.micro/properties/Any/regex').source;\n re.src_Cc = require('uc.micro/categories/Cc/regex').source;\n re.src_Z = require('uc.micro/categories/Z/regex').source;\n re.src_P = require('uc.micro/categories/P/regex').source;\n\n // \\p{\\Z\\P\\Cc\\CF} (white spaces + control + format + punctuation)\n re.src_ZPCc = [ re.src_Z, re.src_P, re.src_Cc ].join('|');\n\n // \\p{\\Z\\Cc} (white spaces + control)\n re.src_ZCc = [ re.src_Z, re.src_Cc ].join('|');\n\n // Experimental. List of chars, completely prohibited in links\n // because can separate it from other part of text\n var text_separators = '[><\\uff5c]';\n\n // All possible word characters (everything without punctuation, spaces & controls)\n // Defined via punctuation & spaces to save space\n // Should be something like \\p{\\L\\N\\S\\M} (\\w but without `_`)\n re.src_pseudo_letter = '(?:(?!' + text_separators + '|' + re.src_ZPCc + ')' + re.src_Any + ')';\n // The same as abothe but without [0-9]\n // var src_pseudo_letter_non_d = '(?:(?![0-9]|' + src_ZPCc + ')' + src_Any + ')';\n\n ////////////////////////////////////////////////////////////////////////////////\n\n re.src_ip4 =\n\n '(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)';\n\n // Prohibit any of \"@/[]()\" in user/pass to avoid wrong domain fetch.\n re.src_auth = '(?:(?:(?!' + re.src_ZCc + '|[@/\\\\[\\\\]()]).)+@)?';\n\n re.src_port =\n\n '(?::(?:6(?:[0-4]\\\\d{3}|5(?:[0-4]\\\\d{2}|5(?:[0-2]\\\\d|3[0-5])))|[1-5]?\\\\d{1,4}))?';\n\n re.src_host_terminator =\n\n '(?=$|' + text_separators + '|' + re.src_ZPCc + ')(?!-|_|:\\\\d|\\\\.-|\\\\.(?!$|' + re.src_ZPCc + '))';\n\n re.src_path =\n\n '(?:' +\n '[/?#]' +\n '(?:' +\n '(?!' + re.src_ZCc + '|' + text_separators + '|[()[\\\\]{}.,\"\\'?!\\\\-]).|' +\n '\\\\[(?:(?!' + re.src_ZCc + '|\\\\]).)*\\\\]|' +\n '\\\\((?:(?!' + re.src_ZCc + '|[)]).)*\\\\)|' +\n '\\\\{(?:(?!' + re.src_ZCc + '|[}]).)*\\\\}|' +\n '\\\\\"(?:(?!' + re.src_ZCc + '|[\"]).)+\\\\\"|' +\n \"\\\\'(?:(?!\" + re.src_ZCc + \"|[']).)+\\\\'|\" +\n \"\\\\'(?=\" + re.src_pseudo_letter + '|[-]).|' + // allow `I'm_king` if no pair found\n '\\\\.{2,}[a-zA-Z0-9%/&]|' + // google has many dots in \"google search\" links (#66, #81).\n // github has ... in commit range links,\n // Restrict to\n // - english\n // - percent-encoded\n // - parts of file path\n // - params separator\n // until more examples found.\n '\\\\.(?!' + re.src_ZCc + '|[.]).|' +\n (opts && opts['---'] ?\n '\\\\-(?!--(?:[^-]|$))(?:-*)|' // `---` => long dash, terminate\n :\n '\\\\-+|'\n ) +\n '\\\\,(?!' + re.src_ZCc + ').|' + // allow `,,,` in paths\n '\\\\!+(?!' + re.src_ZCc + '|[!]).|' + // allow `!!!` in paths, but not at the end\n '\\\\?(?!' + re.src_ZCc + '|[?]).' +\n ')+' +\n '|\\\\/' +\n ')?';\n\n // Allow anything in markdown spec, forbid quote (\") at the first position\n // because emails enclosed in quotes are far more common\n re.src_email_name =\n\n '[\\\\-;:&=\\\\+\\\\$,\\\\.a-zA-Z0-9_][\\\\-;:&=\\\\+\\\\$,\\\\\"\\\\.a-zA-Z0-9_]*';\n\n re.src_xn =\n\n 'xn--[a-z0-9\\\\-]{1,59}';\n\n // More to read about domain names\n // http://serverfault.com/questions/638260/\n\n re.src_domain_root =\n\n // Allow letters & digits (http://test1)\n '(?:' +\n re.src_xn +\n '|' +\n re.src_pseudo_letter + '{1,63}' +\n ')';\n\n re.src_domain =\n\n '(?:' +\n re.src_xn +\n '|' +\n '(?:' + re.src_pseudo_letter + ')' +\n '|' +\n '(?:' + re.src_pseudo_letter + '(?:-|' + re.src_pseudo_letter + '){0,61}' + re.src_pseudo_letter + ')' +\n ')';\n\n re.src_host =\n\n '(?:' +\n // Don't need IP check, because digits are already allowed in normal domain names\n // src_ip4 +\n // '|' +\n '(?:(?:(?:' + re.src_domain + ')\\\\.)*' + re.src_domain/*_root*/ + ')' +\n ')';\n\n re.tpl_host_fuzzy =\n\n '(?:' +\n re.src_ip4 +\n '|' +\n '(?:(?:(?:' + re.src_domain + ')\\\\.)+(?:%TLDS%))' +\n ')';\n\n re.tpl_host_no_ip_fuzzy =\n\n '(?:(?:(?:' + re.src_domain + ')\\\\.)+(?:%TLDS%))';\n\n re.src_host_strict =\n\n re.src_host + re.src_host_terminator;\n\n re.tpl_host_fuzzy_strict =\n\n re.tpl_host_fuzzy + re.src_host_terminator;\n\n re.src_host_port_strict =\n\n re.src_host + re.src_port + re.src_host_terminator;\n\n re.tpl_host_port_fuzzy_strict =\n\n re.tpl_host_fuzzy + re.src_port + re.src_host_terminator;\n\n re.tpl_host_port_no_ip_fuzzy_strict =\n\n re.tpl_host_no_ip_fuzzy + re.src_port + re.src_host_terminator;\n\n\n ////////////////////////////////////////////////////////////////////////////////\n // Main rules\n\n // Rude test fuzzy links by host, for quick deny\n re.tpl_host_fuzzy_test =\n\n 'localhost|www\\\\.|\\\\.\\\\d{1,3}\\\\.|(?:\\\\.(?:%TLDS%)(?:' + re.src_ZPCc + '|>|$))';\n\n re.tpl_email_fuzzy =\n\n '(^|' + text_separators + '|\"|\\\\(|' + re.src_ZCc + ')' +\n '(' + re.src_email_name + '@' + re.tpl_host_fuzzy_strict + ')';\n\n re.tpl_link_fuzzy =\n // Fuzzy link can't be prepended with .:/\\- and non punctuation.\n // but can start with > (markdown blockquote)\n '(^|(?![.:/\\\\-_@])(?:[$+<=>^`|\\uff5c]|' + re.src_ZPCc + '))' +\n '((?![$+<=>^`|\\uff5c])' + re.tpl_host_port_fuzzy_strict + re.src_path + ')';\n\n re.tpl_link_no_ip_fuzzy =\n // Fuzzy link can't be prepended with .:/\\- and non punctuation.\n // but can start with > (markdown blockquote)\n '(^|(?![.:/\\\\-_@])(?:[$+<=>^`|\\uff5c]|' + re.src_ZPCc + '))' +\n '((?![$+<=>^`|\\uff5c])' + re.tpl_host_port_no_ip_fuzzy_strict + re.src_path + ')';\n\n return re;\n};\n","'use strict';\n\nvar utils = require('./../utils');\nvar settle = require('./../core/settle');\nvar cookies = require('./../helpers/cookies');\nvar buildURL = require('./../helpers/buildURL');\nvar buildFullPath = require('../core/buildFullPath');\nvar parseHeaders = require('./../helpers/parseHeaders');\nvar isURLSameOrigin = require('./../helpers/isURLSameOrigin');\nvar createError = require('../core/createError');\n\nmodule.exports = function xhrAdapter(config) {\n return new Promise(function dispatchXhrRequest(resolve, reject) {\n var requestData = config.data;\n var requestHeaders = config.headers;\n var responseType = config.responseType;\n\n if (utils.isFormData(requestData)) {\n delete requestHeaders['Content-Type']; // Let the browser set it\n }\n\n var request = new XMLHttpRequest();\n\n // HTTP basic authentication\n if (config.auth) {\n var username = config.auth.username || '';\n var password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : '';\n requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);\n }\n\n var fullPath = buildFullPath(config.baseURL, config.url);\n request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);\n\n // Set the request timeout in MS\n request.timeout = config.timeout;\n\n function onloadend() {\n if (!request) {\n return;\n }\n // Prepare the response\n var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;\n var responseData = !responseType || responseType === 'text' || responseType === 'json' ?\n request.responseText : request.response;\n var response = {\n data: responseData,\n status: request.status,\n statusText: request.statusText,\n headers: responseHeaders,\n config: config,\n request: request\n };\n\n settle(resolve, reject, response);\n\n // Clean up request\n request = null;\n }\n\n if ('onloadend' in request) {\n // Use onloadend if available\n request.onloadend = onloadend;\n } else {\n // Listen for ready state to emulate onloadend\n request.onreadystatechange = function handleLoad() {\n if (!request || request.readyState !== 4) {\n return;\n }\n\n // The request errored out and we didn't get a response, this will be\n // handled by onerror instead\n // With one exception: request that using file: protocol, most browsers\n // will return status as 0 even though it's a successful request\n if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {\n return;\n }\n // readystate handler is calling before onerror or ontimeout handlers,\n // so we should call onloadend on the next 'tick'\n setTimeout(onloadend);\n };\n }\n\n // Handle browser request cancellation (as opposed to a manual cancellation)\n request.onabort = function handleAbort() {\n if (!request) {\n return;\n }\n\n reject(createError('Request aborted', config, 'ECONNABORTED', request));\n\n // Clean up request\n request = null;\n };\n\n // Handle low level network errors\n request.onerror = function handleError() {\n // Real errors are hidden from us by the browser\n // onerror should only fire if it's a network error\n reject(createError('Network Error', config, null, request));\n\n // Clean up request\n request = null;\n };\n\n // Handle timeout\n request.ontimeout = function handleTimeout() {\n var timeoutErrorMessage = 'timeout of ' + config.timeout + 'ms exceeded';\n if (config.timeoutErrorMessage) {\n timeoutErrorMessage = config.timeoutErrorMessage;\n }\n reject(createError(\n timeoutErrorMessage,\n config,\n config.transitional && config.transitional.clarifyTimeoutError ? 'ETIMEDOUT' : 'ECONNABORTED',\n request));\n\n // Clean up request\n request = null;\n };\n\n // Add xsrf header\n // This is only done if running in a standard browser environment.\n // Specifically not if we're in a web worker, or react-native.\n if (utils.isStandardBrowserEnv()) {\n // Add xsrf header\n var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ?\n cookies.read(config.xsrfCookieName) :\n undefined;\n\n if (xsrfValue) {\n requestHeaders[config.xsrfHeaderName] = xsrfValue;\n }\n }\n\n // Add headers to the request\n if ('setRequestHeader' in request) {\n utils.forEach(requestHeaders, function setRequestHeader(val, key) {\n if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {\n // Remove Content-Type if data is undefined\n delete requestHeaders[key];\n } else {\n // Otherwise add header to the request\n request.setRequestHeader(key, val);\n }\n });\n }\n\n // Add withCredentials to request if needed\n if (!utils.isUndefined(config.withCredentials)) {\n request.withCredentials = !!config.withCredentials;\n }\n\n // Add responseType to request if needed\n if (responseType && responseType !== 'json') {\n request.responseType = config.responseType;\n }\n\n // Handle progress if needed\n if (typeof config.onDownloadProgress === 'function') {\n request.addEventListener('progress', config.onDownloadProgress);\n }\n\n // Not all browsers support upload events\n if (typeof config.onUploadProgress === 'function' && request.upload) {\n request.upload.addEventListener('progress', config.onUploadProgress);\n }\n\n if (config.cancelToken) {\n // Handle cancellation\n config.cancelToken.promise.then(function onCanceled(cancel) {\n if (!request) {\n return;\n }\n\n request.abort();\n reject(cancel);\n // Clean up request\n request = null;\n });\n }\n\n if (!requestData) {\n requestData = null;\n }\n\n // Send the request\n request.send(requestData);\n });\n};\n","// Skip text characters for text token, place those to pending buffer\n// and increment current pos\n\n'use strict';\n\n\n// Rule to skip pure text\n// '{}$%@~+=:' reserved for extentions\n\n// !, \", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \\, ], ^, _, `, {, |, }, or ~\n\n// !!!! Don't confuse with \"Markdown ASCII Punctuation\" chars\n// http://spec.commonmark.org/0.15/#ascii-punctuation-character\nfunction isTerminatorChar(ch) {\n switch (ch) {\n case 0x0A/* \\n */:\n case 0x21/* ! */:\n case 0x23/* # */:\n case 0x24/* $ */:\n case 0x25/* % */:\n case 0x26/* & */:\n case 0x2A/* * */:\n case 0x2B/* + */:\n case 0x2D/* - */:\n case 0x3A/* : */:\n case 0x3C/* < */:\n case 0x3D/* = */:\n case 0x3E/* > */:\n case 0x40/* @ */:\n case 0x5B/* [ */:\n case 0x5C/* \\ */:\n case 0x5D/* ] */:\n case 0x5E/* ^ */:\n case 0x5F/* _ */:\n case 0x60/* ` */:\n case 0x7B/* { */:\n case 0x7D/* } */:\n case 0x7E/* ~ */:\n return true;\n default:\n return false;\n }\n}\n\nmodule.exports = function text(state, silent) {\n var pos = state.pos;\n\n while (pos < state.posMax && !isTerminatorChar(state.src.charCodeAt(pos))) {\n pos++;\n }\n\n if (pos === state.pos) { return false; }\n\n if (!silent) { state.pending += state.src.slice(state.pos, pos); }\n\n state.pos = pos;\n\n return true;\n};\n\n// Alternative implementation, for memory.\n//\n// It costs 10% of performance, but allows extend terminators list, if place it\n// to `ParcerInline` property. Probably, will switch to it sometime, such\n// flexibility required.\n\n/*\nvar TERMINATOR_RE = /[\\n!#$%&*+\\-:<=>@[\\\\\\]^_`{}~]/;\n\nmodule.exports = function text(state, silent) {\n var pos = state.pos,\n idx = state.src.slice(pos).search(TERMINATOR_RE);\n\n // first char is terminator -> empty text\n if (idx === 0) { return false; }\n\n // no terminator -> text till end of string\n if (idx < 0) {\n if (!silent) { state.pending += state.src.slice(pos); }\n state.pos = state.src.length;\n return true;\n }\n\n if (!silent) { state.pending += state.src.slice(pos, pos + idx); }\n\n state.pos += idx;\n\n return true;\n};*/\n","// Simple typographic replacements\n//\n// (c) (C) → ©\n// (tm) (TM) → ™\n// (r) (R) → ®\n// +- → ±\n// (p) (P) -> §\n// ... → … (also ?.... → ?.., !.... → !..)\n// ???????? → ???, !!!!! → !!!, `,,` → `,`\n// -- → –, --- → —\n//\n'use strict';\n\n// TODO:\n// - fractionals 1/2, 1/4, 3/4 -> ½, ¼, ¾\n// - miltiplication 2 x 4 -> 2 × 4\n\nvar RARE_RE = /\\+-|\\.\\.|\\?\\?\\?\\?|!!!!|,,|--/;\n\n// Workaround for phantomjs - need regex without /g flag,\n// or root check will fail every second time\nvar SCOPED_ABBR_TEST_RE = /\\((c|tm|r|p)\\)/i;\n\nvar SCOPED_ABBR_RE = /\\((c|tm|r|p)\\)/ig;\nvar SCOPED_ABBR = {\n c: '©',\n r: '®',\n p: '§',\n tm: '™'\n};\n\nfunction replaceFn(match, name) {\n return SCOPED_ABBR[name.toLowerCase()];\n}\n\nfunction replace_scoped(inlineTokens) {\n var i, token, inside_autolink = 0;\n\n for (i = inlineTokens.length - 1; i >= 0; i--) {\n token = inlineTokens[i];\n\n if (token.type === 'text' && !inside_autolink) {\n token.content = token.content.replace(SCOPED_ABBR_RE, replaceFn);\n }\n\n if (token.type === 'link_open' && token.info === 'auto') {\n inside_autolink--;\n }\n\n if (token.type === 'link_close' && token.info === 'auto') {\n inside_autolink++;\n }\n }\n}\n\nfunction replace_rare(inlineTokens) {\n var i, token, inside_autolink = 0;\n\n for (i = inlineTokens.length - 1; i >= 0; i--) {\n token = inlineTokens[i];\n\n if (token.type === 'text' && !inside_autolink) {\n if (RARE_RE.test(token.content)) {\n token.content = token.content\n .replace(/\\+-/g, '±')\n // .., ..., ....... -> …\n // but ?..... & !..... -> ?.. & !..\n .replace(/\\.{2,}/g, '…').replace(/([?!])…/g, '$1..')\n .replace(/([?!]){4,}/g, '$1$1$1').replace(/,{2,}/g, ',')\n // em-dash\n .replace(/(^|[^-])---(?=[^-]|$)/mg, '$1\\u2014')\n // en-dash\n .replace(/(^|\\s)--(?=\\s|$)/mg, '$1\\u2013')\n .replace(/(^|[^-\\s])--(?=[^-\\s]|$)/mg, '$1\\u2013');\n }\n }\n\n if (token.type === 'link_open' && token.info === 'auto') {\n inside_autolink--;\n }\n\n if (token.type === 'link_close' && token.info === 'auto') {\n inside_autolink++;\n }\n }\n}\n\n\nmodule.exports = function replace(state) {\n var blkIdx;\n\n if (!state.md.options.typographer) { return; }\n\n for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {\n\n if (state.tokens[blkIdx].type !== 'inline') { continue; }\n\n if (SCOPED_ABBR_TEST_RE.test(state.tokens[blkIdx].content)) {\n replace_scoped(state.tokens[blkIdx].children);\n }\n\n if (RARE_RE.test(state.tokens[blkIdx].content)) {\n replace_rare(state.tokens[blkIdx].children);\n }\n\n }\n};\n","module.exports = require('./lib/axios');","// HTML5 entities map: { name -> utf16string }\n//\n'use strict';\n\n/*eslint quotes:0*/\nmodule.exports = require('entities/lib/maps/entities.json');\n","// fences (``` lang, ~~~ lang)\n\n'use strict';\n\n\nmodule.exports = function fence(state, startLine, endLine, silent) {\n var marker, len, params, nextLine, mem, token, markup,\n haveEndMarker = false,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine];\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n if (pos + 3 > max) { return false; }\n\n marker = state.src.charCodeAt(pos);\n\n if (marker !== 0x7E/* ~ */ && marker !== 0x60 /* ` */) {\n return false;\n }\n\n // scan marker length\n mem = pos;\n pos = state.skipChars(pos, marker);\n\n len = pos - mem;\n\n if (len < 3) { return false; }\n\n markup = state.src.slice(mem, pos);\n params = state.src.slice(pos, max);\n\n if (marker === 0x60 /* ` */) {\n if (params.indexOf(String.fromCharCode(marker)) >= 0) {\n return false;\n }\n }\n\n // Since start is found, we can report success here in validation mode\n if (silent) { return true; }\n\n // search end of block\n nextLine = startLine;\n\n for (;;) {\n nextLine++;\n if (nextLine >= endLine) {\n // unclosed block should be autoclosed by end of document.\n // also block seems to be autoclosed by end of parent\n break;\n }\n\n pos = mem = state.bMarks[nextLine] + state.tShift[nextLine];\n max = state.eMarks[nextLine];\n\n if (pos < max && state.sCount[nextLine] < state.blkIndent) {\n // non-empty line with negative indent should stop the list:\n // - ```\n // test\n break;\n }\n\n if (state.src.charCodeAt(pos) !== marker) { continue; }\n\n if (state.sCount[nextLine] - state.blkIndent >= 4) {\n // closing fence should be indented less than 4 spaces\n continue;\n }\n\n pos = state.skipChars(pos, marker);\n\n // closing code fence must be at least as long as the opening one\n if (pos - mem < len) { continue; }\n\n // make sure tail has spaces only\n pos = state.skipSpaces(pos);\n\n if (pos < max) { continue; }\n\n haveEndMarker = true;\n // found!\n break;\n }\n\n // If a fence has heading spaces, they should be removed from its inner block\n len = state.sCount[startLine];\n\n state.line = nextLine + (haveEndMarker ? 1 : 0);\n\n token = state.push('fence', 'code', 0);\n token.info = params;\n token.content = state.getLines(startLine + 1, nextLine, len, true);\n token.markup = markup;\n token.map = [ startLine, state.line ];\n\n return true;\n};\n","// Process html tags\n\n'use strict';\n\n\nvar HTML_TAG_RE = require('../common/html_re').HTML_TAG_RE;\n\n\nfunction isLetter(ch) {\n /*eslint no-bitwise:0*/\n var lc = ch | 0x20; // to lower case\n return (lc >= 0x61/* a */) && (lc <= 0x7a/* z */);\n}\n\n\nmodule.exports = function html_inline(state, silent) {\n var ch, match, max, token,\n pos = state.pos;\n\n if (!state.md.options.html) { return false; }\n\n // Check start\n max = state.posMax;\n if (state.src.charCodeAt(pos) !== 0x3C/* < */ ||\n pos + 2 >= max) {\n return false;\n }\n\n // Quick fail on second char\n ch = state.src.charCodeAt(pos + 1);\n if (ch !== 0x21/* ! */ &&\n ch !== 0x3F/* ? */ &&\n ch !== 0x2F/* / */ &&\n !isLetter(ch)) {\n return false;\n }\n\n match = state.src.slice(pos).match(HTML_TAG_RE);\n if (!match) { return false; }\n\n if (!silent) {\n token = state.push('html_inline', '', 0);\n token.content = state.src.slice(pos, pos + match[0].length);\n }\n state.pos += match[0].length;\n return true;\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\n// Headers whose duplicates are ignored by node\n// c.f. https://nodejs.org/api/http.html#http_message_headers\nvar ignoreDuplicateOf = [\n 'age', 'authorization', 'content-length', 'content-type', 'etag',\n 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since',\n 'last-modified', 'location', 'max-forwards', 'proxy-authorization',\n 'referer', 'retry-after', 'user-agent'\n];\n\n/**\n * Parse headers into an object\n *\n * ```\n * Date: Wed, 27 Aug 2014 08:58:49 GMT\n * Content-Type: application/json\n * Connection: keep-alive\n * Transfer-Encoding: chunked\n * ```\n *\n * @param {String} headers Headers needing to be parsed\n * @returns {Object} Headers parsed into an object\n */\nmodule.exports = function parseHeaders(headers) {\n var parsed = {};\n var key;\n var val;\n var i;\n\n if (!headers) { return parsed; }\n\n utils.forEach(headers.split('\\n'), function parser(line) {\n i = line.indexOf(':');\n key = utils.trim(line.substr(0, i)).toLowerCase();\n val = utils.trim(line.substr(i + 1));\n\n if (key) {\n if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) {\n return;\n }\n if (key === 'set-cookie') {\n parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]);\n } else {\n parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;\n }\n }\n });\n\n return parsed;\n};\n","'use strict';\n\nvar utils = require('./../utils');\nvar defaults = require('./../defaults');\n\n/**\n * Transform the data for a request or a response\n *\n * @param {Object|String} data The data to be transformed\n * @param {Array} headers The headers for the request or response\n * @param {Array|Function} fns A single function or Array of functions\n * @returns {*} The resulting transformed data\n */\nmodule.exports = function transformData(data, headers, fns) {\n var context = this || defaults;\n /*eslint no-param-reassign:0*/\n utils.forEach(fns, function transform(fn) {\n data = fn.call(context, data, headers);\n });\n\n return data;\n};\n","\n'use strict';\n\n\nvar encodeCache = {};\n\n\n// Create a lookup array where anything but characters in `chars` string\n// and alphanumeric chars is percent-encoded.\n//\nfunction getEncodeCache(exclude) {\n var i, ch, cache = encodeCache[exclude];\n if (cache) { return cache; }\n\n cache = encodeCache[exclude] = [];\n\n for (i = 0; i < 128; i++) {\n ch = String.fromCharCode(i);\n\n if (/^[0-9a-z]$/i.test(ch)) {\n // always allow unencoded alphanumeric characters\n cache.push(ch);\n } else {\n cache.push('%' + ('0' + i.toString(16).toUpperCase()).slice(-2));\n }\n }\n\n for (i = 0; i < exclude.length; i++) {\n cache[exclude.charCodeAt(i)] = exclude[i];\n }\n\n return cache;\n}\n\n\n// Encode unsafe characters with percent-encoding, skipping already\n// encoded sequences.\n//\n// - string - string to encode\n// - exclude - list of characters to ignore (in addition to a-zA-Z0-9)\n// - keepEscaped - don't encode '%' in a correct escape sequence (default: true)\n//\nfunction encode(string, exclude, keepEscaped) {\n var i, l, code, nextCode, cache,\n result = '';\n\n if (typeof exclude !== 'string') {\n // encode(string, keepEscaped)\n keepEscaped = exclude;\n exclude = encode.defaultChars;\n }\n\n if (typeof keepEscaped === 'undefined') {\n keepEscaped = true;\n }\n\n cache = getEncodeCache(exclude);\n\n for (i = 0, l = string.length; i < l; i++) {\n code = string.charCodeAt(i);\n\n if (keepEscaped && code === 0x25 /* % */ && i + 2 < l) {\n if (/^[0-9a-f]{2}$/i.test(string.slice(i + 1, i + 3))) {\n result += string.slice(i, i + 3);\n i += 2;\n continue;\n }\n }\n\n if (code < 128) {\n result += cache[code];\n continue;\n }\n\n if (code >= 0xD800 && code <= 0xDFFF) {\n if (code >= 0xD800 && code <= 0xDBFF && i + 1 < l) {\n nextCode = string.charCodeAt(i + 1);\n if (nextCode >= 0xDC00 && nextCode <= 0xDFFF) {\n result += encodeURIComponent(string[i] + string[i + 1]);\n i++;\n continue;\n }\n }\n result += '%EF%BF%BD';\n continue;\n }\n\n result += encodeURIComponent(string[i]);\n }\n\n return result;\n}\n\nencode.defaultChars = \";/?:@&=+$,-_.!~*'()#\";\nencode.componentChars = \"-_.!~*'()\";\n\n\nmodule.exports = encode;\n","'use strict';\n\nvar bind = require('./helpers/bind');\n\n// utils is a library of generic helper functions non-specific to axios\n\nvar toString = Object.prototype.toString;\n\n/**\n * Determine if a value is an Array\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an Array, otherwise false\n */\nfunction isArray(val) {\n return toString.call(val) === '[object Array]';\n}\n\n/**\n * Determine if a value is undefined\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if the value is undefined, otherwise false\n */\nfunction isUndefined(val) {\n return typeof val === 'undefined';\n}\n\n/**\n * Determine if a value is a Buffer\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Buffer, otherwise false\n */\nfunction isBuffer(val) {\n return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)\n && typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val);\n}\n\n/**\n * Determine if a value is an ArrayBuffer\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an ArrayBuffer, otherwise false\n */\nfunction isArrayBuffer(val) {\n return toString.call(val) === '[object ArrayBuffer]';\n}\n\n/**\n * Determine if a value is a FormData\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an FormData, otherwise false\n */\nfunction isFormData(val) {\n return (typeof FormData !== 'undefined') && (val instanceof FormData);\n}\n\n/**\n * Determine if a value is a view on an ArrayBuffer\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false\n */\nfunction isArrayBufferView(val) {\n var result;\n if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {\n result = ArrayBuffer.isView(val);\n } else {\n result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer);\n }\n return result;\n}\n\n/**\n * Determine if a value is a String\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a String, otherwise false\n */\nfunction isString(val) {\n return typeof val === 'string';\n}\n\n/**\n * Determine if a value is a Number\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Number, otherwise false\n */\nfunction isNumber(val) {\n return typeof val === 'number';\n}\n\n/**\n * Determine if a value is an Object\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an Object, otherwise false\n */\nfunction isObject(val) {\n return val !== null && typeof val === 'object';\n}\n\n/**\n * Determine if a value is a plain Object\n *\n * @param {Object} val The value to test\n * @return {boolean} True if value is a plain Object, otherwise false\n */\nfunction isPlainObject(val) {\n if (toString.call(val) !== '[object Object]') {\n return false;\n }\n\n var prototype = Object.getPrototypeOf(val);\n return prototype === null || prototype === Object.prototype;\n}\n\n/**\n * Determine if a value is a Date\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Date, otherwise false\n */\nfunction isDate(val) {\n return toString.call(val) === '[object Date]';\n}\n\n/**\n * Determine if a value is a File\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a File, otherwise false\n */\nfunction isFile(val) {\n return toString.call(val) === '[object File]';\n}\n\n/**\n * Determine if a value is a Blob\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Blob, otherwise false\n */\nfunction isBlob(val) {\n return toString.call(val) === '[object Blob]';\n}\n\n/**\n * Determine if a value is a Function\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Function, otherwise false\n */\nfunction isFunction(val) {\n return toString.call(val) === '[object Function]';\n}\n\n/**\n * Determine if a value is a Stream\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Stream, otherwise false\n */\nfunction isStream(val) {\n return isObject(val) && isFunction(val.pipe);\n}\n\n/**\n * Determine if a value is a URLSearchParams object\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a URLSearchParams object, otherwise false\n */\nfunction isURLSearchParams(val) {\n return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;\n}\n\n/**\n * Trim excess whitespace off the beginning and end of a string\n *\n * @param {String} str The String to trim\n * @returns {String} The String freed of excess whitespace\n */\nfunction trim(str) {\n return str.trim ? str.trim() : str.replace(/^\\s+|\\s+$/g, '');\n}\n\n/**\n * Determine if we're running in a standard browser environment\n *\n * This allows axios to run in a web worker, and react-native.\n * Both environments support XMLHttpRequest, but not fully standard globals.\n *\n * web workers:\n * typeof window -> undefined\n * typeof document -> undefined\n *\n * react-native:\n * navigator.product -> 'ReactNative'\n * nativescript\n * navigator.product -> 'NativeScript' or 'NS'\n */\nfunction isStandardBrowserEnv() {\n if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' ||\n navigator.product === 'NativeScript' ||\n navigator.product === 'NS')) {\n return false;\n }\n return (\n typeof window !== 'undefined' &&\n typeof document !== 'undefined'\n );\n}\n\n/**\n * Iterate over an Array or an Object invoking a function for each item.\n *\n * If `obj` is an Array callback will be called passing\n * the value, index, and complete array for each item.\n *\n * If 'obj' is an Object callback will be called passing\n * the value, key, and complete object for each property.\n *\n * @param {Object|Array} obj The object to iterate\n * @param {Function} fn The callback to invoke for each item\n */\nfunction forEach(obj, fn) {\n // Don't bother if no value provided\n if (obj === null || typeof obj === 'undefined') {\n return;\n }\n\n // Force an array if not already something iterable\n if (typeof obj !== 'object') {\n /*eslint no-param-reassign:0*/\n obj = [obj];\n }\n\n if (isArray(obj)) {\n // Iterate over array values\n for (var i = 0, l = obj.length; i < l; i++) {\n fn.call(null, obj[i], i, obj);\n }\n } else {\n // Iterate over object keys\n for (var key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n fn.call(null, obj[key], key, obj);\n }\n }\n }\n}\n\n/**\n * Accepts varargs expecting each argument to be an object, then\n * immutably merges the properties of each object and returns result.\n *\n * When multiple objects contain the same key the later object in\n * the arguments list will take precedence.\n *\n * Example:\n *\n * ```js\n * var result = merge({foo: 123}, {foo: 456});\n * console.log(result.foo); // outputs 456\n * ```\n *\n * @param {Object} obj1 Object to merge\n * @returns {Object} Result of all merge properties\n */\nfunction merge(/* obj1, obj2, obj3, ... */) {\n var result = {};\n function assignValue(val, key) {\n if (isPlainObject(result[key]) && isPlainObject(val)) {\n result[key] = merge(result[key], val);\n } else if (isPlainObject(val)) {\n result[key] = merge({}, val);\n } else if (isArray(val)) {\n result[key] = val.slice();\n } else {\n result[key] = val;\n }\n }\n\n for (var i = 0, l = arguments.length; i < l; i++) {\n forEach(arguments[i], assignValue);\n }\n return result;\n}\n\n/**\n * Extends object a by mutably adding to it the properties of object b.\n *\n * @param {Object} a The object to be extended\n * @param {Object} b The object to copy properties from\n * @param {Object} thisArg The object to bind function to\n * @return {Object} The resulting value of object a\n */\nfunction extend(a, b, thisArg) {\n forEach(b, function assignValue(val, key) {\n if (thisArg && typeof val === 'function') {\n a[key] = bind(val, thisArg);\n } else {\n a[key] = val;\n }\n });\n return a;\n}\n\n/**\n * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)\n *\n * @param {string} content with BOM\n * @return {string} content value without BOM\n */\nfunction stripBOM(content) {\n if (content.charCodeAt(0) === 0xFEFF) {\n content = content.slice(1);\n }\n return content;\n}\n\nmodule.exports = {\n isArray: isArray,\n isArrayBuffer: isArrayBuffer,\n isBuffer: isBuffer,\n isFormData: isFormData,\n isArrayBufferView: isArrayBufferView,\n isString: isString,\n isNumber: isNumber,\n isObject: isObject,\n isPlainObject: isPlainObject,\n isUndefined: isUndefined,\n isDate: isDate,\n isFile: isFile,\n isBlob: isBlob,\n isFunction: isFunction,\n isStream: isStream,\n isURLSearchParams: isURLSearchParams,\n isStandardBrowserEnv: isStandardBrowserEnv,\n forEach: forEach,\n merge: merge,\n extend: extend,\n trim: trim,\n stripBOM: stripBOM\n};\n","// Process *this* and _that_\n//\n'use strict';\n\n\n// Insert each marker as a separate text token, and add it to delimiter list\n//\nmodule.exports.tokenize = function emphasis(state, silent) {\n var i, scanned, token,\n start = state.pos,\n marker = state.src.charCodeAt(start);\n\n if (silent) { return false; }\n\n if (marker !== 0x5F /* _ */ && marker !== 0x2A /* * */) { return false; }\n\n scanned = state.scanDelims(state.pos, marker === 0x2A);\n\n for (i = 0; i < scanned.length; i++) {\n token = state.push('text', '', 0);\n token.content = String.fromCharCode(marker);\n\n state.delimiters.push({\n // Char code of the starting marker (number).\n //\n marker: marker,\n\n // Total length of these series of delimiters.\n //\n length: scanned.length,\n\n // A position of the token this delimiter corresponds to.\n //\n token: state.tokens.length - 1,\n\n // If this delimiter is matched as a valid opener, `end` will be\n // equal to its position, otherwise it's `-1`.\n //\n end: -1,\n\n // Boolean flags that determine if this delimiter could open or close\n // an emphasis.\n //\n open: scanned.can_open,\n close: scanned.can_close\n });\n }\n\n state.pos += scanned.length;\n\n return true;\n};\n\n\nfunction postProcess(state, delimiters) {\n var i,\n startDelim,\n endDelim,\n token,\n ch,\n isStrong,\n max = delimiters.length;\n\n for (i = max - 1; i >= 0; i--) {\n startDelim = delimiters[i];\n\n if (startDelim.marker !== 0x5F/* _ */ && startDelim.marker !== 0x2A/* * */) {\n continue;\n }\n\n // Process only opening markers\n if (startDelim.end === -1) {\n continue;\n }\n\n endDelim = delimiters[startDelim.end];\n\n // If the previous delimiter has the same marker and is adjacent to this one,\n // merge those into one strong delimiter.\n //\n // `whatever` -> `whatever`\n //\n isStrong = i > 0 &&\n delimiters[i - 1].end === startDelim.end + 1 &&\n // check that first two markers match and adjacent\n delimiters[i - 1].marker === startDelim.marker &&\n delimiters[i - 1].token === startDelim.token - 1 &&\n // check that last two markers are adjacent (we can safely assume they match)\n delimiters[startDelim.end + 1].token === endDelim.token + 1;\n\n ch = String.fromCharCode(startDelim.marker);\n\n token = state.tokens[startDelim.token];\n token.type = isStrong ? 'strong_open' : 'em_open';\n token.tag = isStrong ? 'strong' : 'em';\n token.nesting = 1;\n token.markup = isStrong ? ch + ch : ch;\n token.content = '';\n\n token = state.tokens[endDelim.token];\n token.type = isStrong ? 'strong_close' : 'em_close';\n token.tag = isStrong ? 'strong' : 'em';\n token.nesting = -1;\n token.markup = isStrong ? ch + ch : ch;\n token.content = '';\n\n if (isStrong) {\n state.tokens[delimiters[i - 1].token].content = '';\n state.tokens[delimiters[startDelim.end + 1].token].content = '';\n i--;\n }\n }\n}\n\n\n// Walk through delimiter list and replace text tokens with tags\n//\nmodule.exports.postProcess = function emphasis(state) {\n var curr,\n tokens_meta = state.tokens_meta,\n max = state.tokens_meta.length;\n\n postProcess(state, state.delimiters);\n\n for (curr = 0; curr < max; curr++) {\n if (tokens_meta[curr] && tokens_meta[curr].delimiters) {\n postProcess(state, tokens_meta[curr].delimiters);\n }\n }\n};\n","'use strict';\n\nvar utils = require('../utils');\n\nmodule.exports = function normalizeHeaderName(headers, normalizedName) {\n utils.forEach(headers, function processHeader(value, name) {\n if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {\n headers[normalizedName] = value;\n delete headers[name];\n }\n });\n};\n","module.exports=/[\\0-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/","// Process [link]( \"stuff\")\n\n'use strict';\n\nvar normalizeReference = require('../common/utils').normalizeReference;\nvar isSpace = require('../common/utils').isSpace;\n\n\nmodule.exports = function link(state, silent) {\n var attrs,\n code,\n label,\n labelEnd,\n labelStart,\n pos,\n res,\n ref,\n token,\n href = '',\n title = '',\n oldPos = state.pos,\n max = state.posMax,\n start = state.pos,\n parseReference = true;\n\n if (state.src.charCodeAt(state.pos) !== 0x5B/* [ */) { return false; }\n\n labelStart = state.pos + 1;\n labelEnd = state.md.helpers.parseLinkLabel(state, state.pos, true);\n\n // parser failed to find ']', so it's not a valid link\n if (labelEnd < 0) { return false; }\n\n pos = labelEnd + 1;\n if (pos < max && state.src.charCodeAt(pos) === 0x28/* ( */) {\n //\n // Inline link\n //\n\n // might have found a valid shortcut link, disable reference parsing\n parseReference = false;\n\n // [link]( \"title\" )\n // ^^ skipping these spaces\n pos++;\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n if (!isSpace(code) && code !== 0x0A) { break; }\n }\n if (pos >= max) { return false; }\n\n // [link]( \"title\" )\n // ^^^^^^ parsing link destination\n start = pos;\n res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax);\n if (res.ok) {\n href = state.md.normalizeLink(res.str);\n if (state.md.validateLink(href)) {\n pos = res.pos;\n } else {\n href = '';\n }\n\n // [link]( \"title\" )\n // ^^ skipping these spaces\n start = pos;\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n if (!isSpace(code) && code !== 0x0A) { break; }\n }\n\n // [link]( \"title\" )\n // ^^^^^^^ parsing link title\n res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax);\n if (pos < max && start !== pos && res.ok) {\n title = res.str;\n pos = res.pos;\n\n // [link]( \"title\" )\n // ^^ skipping these spaces\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n if (!isSpace(code) && code !== 0x0A) { break; }\n }\n }\n }\n\n if (pos >= max || state.src.charCodeAt(pos) !== 0x29/* ) */) {\n // parsing a valid shortcut link failed, fallback to reference\n parseReference = true;\n }\n pos++;\n }\n\n if (parseReference) {\n //\n // Link reference\n //\n if (typeof state.env.references === 'undefined') { return false; }\n\n if (pos < max && state.src.charCodeAt(pos) === 0x5B/* [ */) {\n start = pos + 1;\n pos = state.md.helpers.parseLinkLabel(state, pos);\n if (pos >= 0) {\n label = state.src.slice(start, pos++);\n } else {\n pos = labelEnd + 1;\n }\n } else {\n pos = labelEnd + 1;\n }\n\n // covers label === '' and label === undefined\n // (collapsed reference link and shortcut reference link respectively)\n if (!label) { label = state.src.slice(labelStart, labelEnd); }\n\n ref = state.env.references[normalizeReference(label)];\n if (!ref) {\n state.pos = oldPos;\n return false;\n }\n href = ref.href;\n title = ref.title;\n }\n\n //\n // We found the end of the link, and know for a fact it's a valid link;\n // so all that's left to do is to call tokenizer.\n //\n if (!silent) {\n state.pos = labelStart;\n state.posMax = labelEnd;\n\n token = state.push('link_open', 'a', 1);\n token.attrs = attrs = [ [ 'href', href ] ];\n if (title) {\n attrs.push([ 'title', title ]);\n }\n\n state.md.inline.tokenize(state);\n\n token = state.push('link_close', 'a', -1);\n }\n\n state.pos = pos;\n state.posMax = max;\n return true;\n};\n","'use strict';\n\nvar utils = require('./utils');\nvar bind = require('./helpers/bind');\nvar Axios = require('./core/Axios');\nvar mergeConfig = require('./core/mergeConfig');\nvar defaults = require('./defaults');\n\n/**\n * Create an instance of Axios\n *\n * @param {Object} defaultConfig The default config for the instance\n * @return {Axios} A new instance of Axios\n */\nfunction createInstance(defaultConfig) {\n var context = new Axios(defaultConfig);\n var instance = bind(Axios.prototype.request, context);\n\n // Copy axios.prototype to instance\n utils.extend(instance, Axios.prototype, context);\n\n // Copy context to instance\n utils.extend(instance, context);\n\n return instance;\n}\n\n// Create the default instance to be exported\nvar axios = createInstance(defaults);\n\n// Expose Axios class to allow class inheritance\naxios.Axios = Axios;\n\n// Factory for creating new instances\naxios.create = function create(instanceConfig) {\n return createInstance(mergeConfig(axios.defaults, instanceConfig));\n};\n\n// Expose Cancel & CancelToken\naxios.Cancel = require('./cancel/Cancel');\naxios.CancelToken = require('./cancel/CancelToken');\naxios.isCancel = require('./cancel/isCancel');\n\n// Expose all/spread\naxios.all = function all(promises) {\n return Promise.all(promises);\n};\naxios.spread = require('./helpers/spread');\n\n// Expose isAxiosError\naxios.isAxiosError = require('./helpers/isAxiosError');\n\nmodule.exports = axios;\n\n// Allow use of default import syntax in TypeScript\nmodule.exports.default = axios;\n","'use strict';\n\n\nmodule.exports = require('./lib/');\n","'use strict';\n\nexports.Any = require('./properties/Any/regex');\nexports.Cc = require('./categories/Cc/regex');\nexports.Cf = require('./categories/Cf/regex');\nexports.P = require('./categories/P/regex');\nexports.Z = require('./categories/Z/regex');\n","'use strict';\n\n\nvar normalizeReference = require('../common/utils').normalizeReference;\nvar isSpace = require('../common/utils').isSpace;\n\n\nmodule.exports = function reference(state, startLine, _endLine, silent) {\n var ch,\n destEndPos,\n destEndLineNo,\n endLine,\n href,\n i,\n l,\n label,\n labelEnd,\n oldParentType,\n res,\n start,\n str,\n terminate,\n terminatorRules,\n title,\n lines = 0,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine],\n nextLine = startLine + 1;\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n if (state.src.charCodeAt(pos) !== 0x5B/* [ */) { return false; }\n\n // Simple check to quickly interrupt scan on [link](url) at the start of line.\n // Can be useful on practice: https://github.com/markdown-it/markdown-it/issues/54\n while (++pos < max) {\n if (state.src.charCodeAt(pos) === 0x5D /* ] */ &&\n state.src.charCodeAt(pos - 1) !== 0x5C/* \\ */) {\n if (pos + 1 === max) { return false; }\n if (state.src.charCodeAt(pos + 1) !== 0x3A/* : */) { return false; }\n break;\n }\n }\n\n endLine = state.lineMax;\n\n // jump line-by-line until empty one or EOF\n terminatorRules = state.md.block.ruler.getRules('reference');\n\n oldParentType = state.parentType;\n state.parentType = 'reference';\n\n for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {\n // this would be a code block normally, but after paragraph\n // it's considered a lazy continuation regardless of what's there\n if (state.sCount[nextLine] - state.blkIndent > 3) { continue; }\n\n // quirk for blockquotes, this line should already be checked by that rule\n if (state.sCount[nextLine] < 0) { continue; }\n\n // Some tags can terminate paragraph without empty line.\n terminate = false;\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n if (terminate) { break; }\n }\n\n str = state.getLines(startLine, nextLine, state.blkIndent, false).trim();\n max = str.length;\n\n for (pos = 1; pos < max; pos++) {\n ch = str.charCodeAt(pos);\n if (ch === 0x5B /* [ */) {\n return false;\n } else if (ch === 0x5D /* ] */) {\n labelEnd = pos;\n break;\n } else if (ch === 0x0A /* \\n */) {\n lines++;\n } else if (ch === 0x5C /* \\ */) {\n pos++;\n if (pos < max && str.charCodeAt(pos) === 0x0A) {\n lines++;\n }\n }\n }\n\n if (labelEnd < 0 || str.charCodeAt(labelEnd + 1) !== 0x3A/* : */) { return false; }\n\n // [label]: destination 'title'\n // ^^^ skip optional whitespace here\n for (pos = labelEnd + 2; pos < max; pos++) {\n ch = str.charCodeAt(pos);\n if (ch === 0x0A) {\n lines++;\n } else if (isSpace(ch)) {\n /*eslint no-empty:0*/\n } else {\n break;\n }\n }\n\n // [label]: destination 'title'\n // ^^^^^^^^^^^ parse this\n res = state.md.helpers.parseLinkDestination(str, pos, max);\n if (!res.ok) { return false; }\n\n href = state.md.normalizeLink(res.str);\n if (!state.md.validateLink(href)) { return false; }\n\n pos = res.pos;\n lines += res.lines;\n\n // save cursor state, we could require to rollback later\n destEndPos = pos;\n destEndLineNo = lines;\n\n // [label]: destination 'title'\n // ^^^ skipping those spaces\n start = pos;\n for (; pos < max; pos++) {\n ch = str.charCodeAt(pos);\n if (ch === 0x0A) {\n lines++;\n } else if (isSpace(ch)) {\n /*eslint no-empty:0*/\n } else {\n break;\n }\n }\n\n // [label]: destination 'title'\n // ^^^^^^^ parse this\n res = state.md.helpers.parseLinkTitle(str, pos, max);\n if (pos < max && start !== pos && res.ok) {\n title = res.str;\n pos = res.pos;\n lines += res.lines;\n } else {\n title = '';\n pos = destEndPos;\n lines = destEndLineNo;\n }\n\n // skip trailing spaces until the rest of the line\n while (pos < max) {\n ch = str.charCodeAt(pos);\n if (!isSpace(ch)) { break; }\n pos++;\n }\n\n if (pos < max && str.charCodeAt(pos) !== 0x0A) {\n if (title) {\n // garbage at the end of the line after title,\n // but it could still be a valid reference if we roll back\n title = '';\n pos = destEndPos;\n lines = destEndLineNo;\n while (pos < max) {\n ch = str.charCodeAt(pos);\n if (!isSpace(ch)) { break; }\n pos++;\n }\n }\n }\n\n if (pos < max && str.charCodeAt(pos) !== 0x0A) {\n // garbage at the end of the line\n return false;\n }\n\n label = normalizeReference(str.slice(1, labelEnd));\n if (!label) {\n // CommonMark 0.20 disallows empty labels\n return false;\n }\n\n // Reference can not terminate anything. This check is for safety only.\n /*istanbul ignore if*/\n if (silent) { return true; }\n\n if (typeof state.env.references === 'undefined') {\n state.env.references = {};\n }\n if (typeof state.env.references[label] === 'undefined') {\n state.env.references[label] = { title: title, href: href };\n }\n\n state.parentType = oldParentType;\n\n state.line = startLine + lines + 1;\n return true;\n};\n","'use strict';\n\n\nmodule.exports.encode = require('./encode');\nmodule.exports.decode = require('./decode');\nmodule.exports.format = require('./format');\nmodule.exports.parse = require('./parse');\n","'use strict';\n\n/**\n * Determines whether the specified URL is absolute\n *\n * @param {string} url The URL to test\n * @returns {boolean} True if the specified URL is absolute, otherwise false\n */\nmodule.exports = function isAbsoluteURL(url) {\n // A URL is considered absolute if it begins with \"://\" or \"//\" (protocol-relative URL).\n // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed\n // by any combination of letters, digits, plus, period, or hyphen.\n return /^([a-z][a-z\\d\\+\\-\\.]*:)?\\/\\//i.test(url);\n};\n","// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\n//\n// Changes from joyent/node:\n//\n// 1. No leading slash in paths,\n// e.g. in `url.parse('http://foo?bar')` pathname is ``, not `/`\n//\n// 2. Backslashes are not replaced with slashes,\n// so `http:\\\\example.org\\` is treated like a relative path\n//\n// 3. Trailing colon is treated like a part of the path,\n// i.e. in `http://example.org:foo` pathname is `:foo`\n//\n// 4. Nothing is URL-encoded in the resulting object,\n// (in joyent/node some chars in auth and paths are encoded)\n//\n// 5. `url.parse()` does not have `parseQueryString` argument\n//\n// 6. Removed extraneous result properties: `host`, `path`, `query`, etc.,\n// which can be constructed using other parts of the url.\n//\n\n\nfunction Url() {\n this.protocol = null;\n this.slashes = null;\n this.auth = null;\n this.port = null;\n this.hostname = null;\n this.hash = null;\n this.search = null;\n this.pathname = null;\n}\n\n// Reference: RFC 3986, RFC 1808, RFC 2396\n\n// define these here so at least they only have to be\n// compiled once on the first module load.\nvar protocolPattern = /^([a-z0-9.+-]+:)/i,\n portPattern = /:[0-9]*$/,\n\n // Special case for a simple path URL\n simplePathPattern = /^(\\/\\/?(?!\\/)[^\\?\\s]*)(\\?[^\\s]*)?$/,\n\n // RFC 2396: characters reserved for delimiting URLs.\n // We actually just auto-escape these.\n delims = [ '<', '>', '\"', '`', ' ', '\\r', '\\n', '\\t' ],\n\n // RFC 2396: characters not allowed for various reasons.\n unwise = [ '{', '}', '|', '\\\\', '^', '`' ].concat(delims),\n\n // Allowed by RFCs, but cause of XSS attacks. Always escape these.\n autoEscape = [ '\\'' ].concat(unwise),\n // Characters that are never ever allowed in a hostname.\n // Note that any invalid chars are also handled, but these\n // are the ones that are *expected* to be seen, so we fast-path\n // them.\n nonHostChars = [ '%', '/', '?', ';', '#' ].concat(autoEscape),\n hostEndingChars = [ '/', '?', '#' ],\n hostnameMaxLen = 255,\n hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,\n hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,\n // protocols that can allow \"unsafe\" and \"unwise\" chars.\n /* eslint-disable no-script-url */\n // protocols that never have a hostname.\n hostlessProtocol = {\n 'javascript': true,\n 'javascript:': true\n },\n // protocols that always contain a // bit.\n slashedProtocol = {\n 'http': true,\n 'https': true,\n 'ftp': true,\n 'gopher': true,\n 'file': true,\n 'http:': true,\n 'https:': true,\n 'ftp:': true,\n 'gopher:': true,\n 'file:': true\n };\n /* eslint-enable no-script-url */\n\nfunction urlParse(url, slashesDenoteHost) {\n if (url && url instanceof Url) { return url; }\n\n var u = new Url();\n u.parse(url, slashesDenoteHost);\n return u;\n}\n\nUrl.prototype.parse = function(url, slashesDenoteHost) {\n var i, l, lowerProto, hec, slashes,\n rest = url;\n\n // trim before proceeding.\n // This is to support parse stuff like \" http://foo.com \\n\"\n rest = rest.trim();\n\n if (!slashesDenoteHost && url.split('#').length === 1) {\n // Try fast path regexp\n var simplePath = simplePathPattern.exec(rest);\n if (simplePath) {\n this.pathname = simplePath[1];\n if (simplePath[2]) {\n this.search = simplePath[2];\n }\n return this;\n }\n }\n\n var proto = protocolPattern.exec(rest);\n if (proto) {\n proto = proto[0];\n lowerProto = proto.toLowerCase();\n this.protocol = proto;\n rest = rest.substr(proto.length);\n }\n\n // figure out if it's got a host\n // user@server is *always* interpreted as a hostname, and url\n // resolution will treat //foo/bar as host=foo,path=bar because that's\n // how the browser resolves relative URLs.\n if (slashesDenoteHost || proto || rest.match(/^\\/\\/[^@\\/]+@[^@\\/]+/)) {\n slashes = rest.substr(0, 2) === '//';\n if (slashes && !(proto && hostlessProtocol[proto])) {\n rest = rest.substr(2);\n this.slashes = true;\n }\n }\n\n if (!hostlessProtocol[proto] &&\n (slashes || (proto && !slashedProtocol[proto]))) {\n\n // there's a hostname.\n // the first instance of /, ?, ;, or # ends the host.\n //\n // If there is an @ in the hostname, then non-host chars *are* allowed\n // to the left of the last @ sign, unless some host-ending character\n // comes *before* the @-sign.\n // URLs are obnoxious.\n //\n // ex:\n // http://a@b@c/ => user:a@b host:c\n // http://a@b?@c => user:a host:c path:/?@c\n\n // v0.12 TODO(isaacs): This is not quite how Chrome does things.\n // Review our test case against browsers more comprehensively.\n\n // find the first instance of any hostEndingChars\n var hostEnd = -1;\n for (i = 0; i < hostEndingChars.length; i++) {\n hec = rest.indexOf(hostEndingChars[i]);\n if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) {\n hostEnd = hec;\n }\n }\n\n // at this point, either we have an explicit point where the\n // auth portion cannot go past, or the last @ char is the decider.\n var auth, atSign;\n if (hostEnd === -1) {\n // atSign can be anywhere.\n atSign = rest.lastIndexOf('@');\n } else {\n // atSign must be in auth portion.\n // http://a@b/c@d => host:b auth:a path:/c@d\n atSign = rest.lastIndexOf('@', hostEnd);\n }\n\n // Now we have a portion which is definitely the auth.\n // Pull that off.\n if (atSign !== -1) {\n auth = rest.slice(0, atSign);\n rest = rest.slice(atSign + 1);\n this.auth = auth;\n }\n\n // the host is the remaining to the left of the first non-host char\n hostEnd = -1;\n for (i = 0; i < nonHostChars.length; i++) {\n hec = rest.indexOf(nonHostChars[i]);\n if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) {\n hostEnd = hec;\n }\n }\n // if we still have not hit it, then the entire thing is a host.\n if (hostEnd === -1) {\n hostEnd = rest.length;\n }\n\n if (rest[hostEnd - 1] === ':') { hostEnd--; }\n var host = rest.slice(0, hostEnd);\n rest = rest.slice(hostEnd);\n\n // pull out port.\n this.parseHost(host);\n\n // we've indicated that there is a hostname,\n // so even if it's empty, it has to be present.\n this.hostname = this.hostname || '';\n\n // if hostname begins with [ and ends with ]\n // assume that it's an IPv6 address.\n var ipv6Hostname = this.hostname[0] === '[' &&\n this.hostname[this.hostname.length - 1] === ']';\n\n // validate a little.\n if (!ipv6Hostname) {\n var hostparts = this.hostname.split(/\\./);\n for (i = 0, l = hostparts.length; i < l; i++) {\n var part = hostparts[i];\n if (!part) { continue; }\n if (!part.match(hostnamePartPattern)) {\n var newpart = '';\n for (var j = 0, k = part.length; j < k; j++) {\n if (part.charCodeAt(j) > 127) {\n // we replace non-ASCII char with a temporary placeholder\n // we need this to make sure size of hostname is not\n // broken by replacing non-ASCII by nothing\n newpart += 'x';\n } else {\n newpart += part[j];\n }\n }\n // we test again with ASCII char only\n if (!newpart.match(hostnamePartPattern)) {\n var validParts = hostparts.slice(0, i);\n var notHost = hostparts.slice(i + 1);\n var bit = part.match(hostnamePartStart);\n if (bit) {\n validParts.push(bit[1]);\n notHost.unshift(bit[2]);\n }\n if (notHost.length) {\n rest = notHost.join('.') + rest;\n }\n this.hostname = validParts.join('.');\n break;\n }\n }\n }\n }\n\n if (this.hostname.length > hostnameMaxLen) {\n this.hostname = '';\n }\n\n // strip [ and ] from the hostname\n // the host field still retains them, though\n if (ipv6Hostname) {\n this.hostname = this.hostname.substr(1, this.hostname.length - 2);\n }\n }\n\n // chop off from the tail first.\n var hash = rest.indexOf('#');\n if (hash !== -1) {\n // got a fragment string.\n this.hash = rest.substr(hash);\n rest = rest.slice(0, hash);\n }\n var qm = rest.indexOf('?');\n if (qm !== -1) {\n this.search = rest.substr(qm);\n rest = rest.slice(0, qm);\n }\n if (rest) { this.pathname = rest; }\n if (slashedProtocol[lowerProto] &&\n this.hostname && !this.pathname) {\n this.pathname = '';\n }\n\n return this;\n};\n\nUrl.prototype.parseHost = function(host) {\n var port = portPattern.exec(host);\n if (port) {\n port = port[0];\n if (port !== ':') {\n this.port = port.substr(1);\n }\n host = host.substr(0, host.length - port.length);\n }\n if (host) { this.hostname = host; }\n};\n\nmodule.exports = urlParse;\n","// Parse link label\n//\n// this function assumes that first character (\"[\") already matches;\n// returns the end of the label\n//\n'use strict';\n\nmodule.exports = function parseLinkLabel(state, start, disableNested) {\n var level, found, marker, prevPos,\n labelEnd = -1,\n max = state.posMax,\n oldPos = state.pos;\n\n state.pos = start + 1;\n level = 1;\n\n while (state.pos < max) {\n marker = state.src.charCodeAt(state.pos);\n if (marker === 0x5D /* ] */) {\n level--;\n if (level === 0) {\n found = true;\n break;\n }\n }\n\n prevPos = state.pos;\n state.md.inline.skipToken(state);\n if (marker === 0x5B /* [ */) {\n if (prevPos === state.pos - 1) {\n // increase level if we find text `[`, which is not a part of any token\n level++;\n } else if (disableNested) {\n state.pos = oldPos;\n return -1;\n }\n }\n }\n\n if (found) {\n labelEnd = state.pos;\n }\n\n // restore old state\n state.pos = oldPos;\n\n return labelEnd;\n};\n","// List of valid html blocks names, accorting to commonmark spec\n// http://jgm.github.io/CommonMark/spec.html#html-blocks\n\n'use strict';\n\n\nmodule.exports = [\n 'address',\n 'article',\n 'aside',\n 'base',\n 'basefont',\n 'blockquote',\n 'body',\n 'caption',\n 'center',\n 'col',\n 'colgroup',\n 'dd',\n 'details',\n 'dialog',\n 'dir',\n 'div',\n 'dl',\n 'dt',\n 'fieldset',\n 'figcaption',\n 'figure',\n 'footer',\n 'form',\n 'frame',\n 'frameset',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'head',\n 'header',\n 'hr',\n 'html',\n 'iframe',\n 'legend',\n 'li',\n 'link',\n 'main',\n 'menu',\n 'menuitem',\n 'nav',\n 'noframes',\n 'ol',\n 'optgroup',\n 'option',\n 'p',\n 'param',\n 'section',\n 'source',\n 'summary',\n 'table',\n 'tbody',\n 'td',\n 'tfoot',\n 'th',\n 'thead',\n 'title',\n 'tr',\n 'track',\n 'ul'\n];\n","// Parse link destination\n//\n'use strict';\n\n\nvar unescapeAll = require('../common/utils').unescapeAll;\n\n\nmodule.exports = function parseLinkDestination(str, pos, max) {\n var code, level,\n lines = 0,\n start = pos,\n result = {\n ok: false,\n pos: 0,\n lines: 0,\n str: ''\n };\n\n if (str.charCodeAt(pos) === 0x3C /* < */) {\n pos++;\n while (pos < max) {\n code = str.charCodeAt(pos);\n if (code === 0x0A /* \\n */) { return result; }\n if (code === 0x3C /* < */) { return result; }\n if (code === 0x3E /* > */) {\n result.pos = pos + 1;\n result.str = unescapeAll(str.slice(start + 1, pos));\n result.ok = true;\n return result;\n }\n if (code === 0x5C /* \\ */ && pos + 1 < max) {\n pos += 2;\n continue;\n }\n\n pos++;\n }\n\n // no closing '>'\n return result;\n }\n\n // this should be ... } else { ... branch\n\n level = 0;\n while (pos < max) {\n code = str.charCodeAt(pos);\n\n if (code === 0x20) { break; }\n\n // ascii control characters\n if (code < 0x20 || code === 0x7F) { break; }\n\n if (code === 0x5C /* \\ */ && pos + 1 < max) {\n if (str.charCodeAt(pos + 1) === 0x20) { break; }\n pos += 2;\n continue;\n }\n\n if (code === 0x28 /* ( */) {\n level++;\n if (level > 32) { return result; }\n }\n\n if (code === 0x29 /* ) */) {\n if (level === 0) { break; }\n level--;\n }\n\n pos++;\n }\n\n if (start === pos) { return result; }\n if (level !== 0) { return result; }\n\n result.str = unescapeAll(str.slice(start, pos));\n result.lines = lines;\n result.pos = pos;\n result.ok = true;\n return result;\n};\n","'use strict';\n\n/**\n * Creates a new URL by combining the specified URLs\n *\n * @param {string} baseURL The base URL\n * @param {string} relativeURL The relative URL\n * @returns {string} The combined URL\n */\nmodule.exports = function combineURLs(baseURL, relativeURL) {\n return relativeURL\n ? baseURL.replace(/\\/+$/, '') + '/' + relativeURL.replace(/^\\/+/, '')\n : baseURL;\n};\n","// Block quotes\n\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\n\nmodule.exports = function blockquote(state, startLine, endLine, silent) {\n var adjustTab,\n ch,\n i,\n initial,\n l,\n lastLineEmpty,\n lines,\n nextLine,\n offset,\n oldBMarks,\n oldBSCount,\n oldIndent,\n oldParentType,\n oldSCount,\n oldTShift,\n spaceAfterMarker,\n terminate,\n terminatorRules,\n token,\n isOutdented,\n oldLineMax = state.lineMax,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine];\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n // check the block quote marker\n if (state.src.charCodeAt(pos++) !== 0x3E/* > */) { return false; }\n\n // we know that it's going to be a valid blockquote,\n // so no point trying to find the end of it in silent mode\n if (silent) { return true; }\n\n // set offset past spaces and \">\"\n initial = offset = state.sCount[startLine] + 1;\n\n // skip one optional space after '>'\n if (state.src.charCodeAt(pos) === 0x20 /* space */) {\n // ' > test '\n // ^ -- position start of line here:\n pos++;\n initial++;\n offset++;\n adjustTab = false;\n spaceAfterMarker = true;\n } else if (state.src.charCodeAt(pos) === 0x09 /* tab */) {\n spaceAfterMarker = true;\n\n if ((state.bsCount[startLine] + offset) % 4 === 3) {\n // ' >\\t test '\n // ^ -- position start of line here (tab has width===1)\n pos++;\n initial++;\n offset++;\n adjustTab = false;\n } else {\n // ' >\\t test '\n // ^ -- position start of line here + shift bsCount slightly\n // to make extra space appear\n adjustTab = true;\n }\n } else {\n spaceAfterMarker = false;\n }\n\n oldBMarks = [ state.bMarks[startLine] ];\n state.bMarks[startLine] = pos;\n\n while (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (isSpace(ch)) {\n if (ch === 0x09) {\n offset += 4 - (offset + state.bsCount[startLine] + (adjustTab ? 1 : 0)) % 4;\n } else {\n offset++;\n }\n } else {\n break;\n }\n\n pos++;\n }\n\n oldBSCount = [ state.bsCount[startLine] ];\n state.bsCount[startLine] = state.sCount[startLine] + 1 + (spaceAfterMarker ? 1 : 0);\n\n lastLineEmpty = pos >= max;\n\n oldSCount = [ state.sCount[startLine] ];\n state.sCount[startLine] = offset - initial;\n\n oldTShift = [ state.tShift[startLine] ];\n state.tShift[startLine] = pos - state.bMarks[startLine];\n\n terminatorRules = state.md.block.ruler.getRules('blockquote');\n\n oldParentType = state.parentType;\n state.parentType = 'blockquote';\n\n // Search the end of the block\n //\n // Block ends with either:\n // 1. an empty line outside:\n // ```\n // > test\n //\n // ```\n // 2. an empty line inside:\n // ```\n // >\n // test\n // ```\n // 3. another tag:\n // ```\n // > test\n // - - -\n // ```\n for (nextLine = startLine + 1; nextLine < endLine; nextLine++) {\n // check if it's outdented, i.e. it's inside list item and indented\n // less than said list item:\n //\n // ```\n // 1. anything\n // > current blockquote\n // 2. checking this line\n // ```\n isOutdented = state.sCount[nextLine] < state.blkIndent;\n\n pos = state.bMarks[nextLine] + state.tShift[nextLine];\n max = state.eMarks[nextLine];\n\n if (pos >= max) {\n // Case 1: line is not inside the blockquote, and this line is empty.\n break;\n }\n\n if (state.src.charCodeAt(pos++) === 0x3E/* > */ && !isOutdented) {\n // This line is inside the blockquote.\n\n // set offset past spaces and \">\"\n initial = offset = state.sCount[nextLine] + 1;\n\n // skip one optional space after '>'\n if (state.src.charCodeAt(pos) === 0x20 /* space */) {\n // ' > test '\n // ^ -- position start of line here:\n pos++;\n initial++;\n offset++;\n adjustTab = false;\n spaceAfterMarker = true;\n } else if (state.src.charCodeAt(pos) === 0x09 /* tab */) {\n spaceAfterMarker = true;\n\n if ((state.bsCount[nextLine] + offset) % 4 === 3) {\n // ' >\\t test '\n // ^ -- position start of line here (tab has width===1)\n pos++;\n initial++;\n offset++;\n adjustTab = false;\n } else {\n // ' >\\t test '\n // ^ -- position start of line here + shift bsCount slightly\n // to make extra space appear\n adjustTab = true;\n }\n } else {\n spaceAfterMarker = false;\n }\n\n oldBMarks.push(state.bMarks[nextLine]);\n state.bMarks[nextLine] = pos;\n\n while (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (isSpace(ch)) {\n if (ch === 0x09) {\n offset += 4 - (offset + state.bsCount[nextLine] + (adjustTab ? 1 : 0)) % 4;\n } else {\n offset++;\n }\n } else {\n break;\n }\n\n pos++;\n }\n\n lastLineEmpty = pos >= max;\n\n oldBSCount.push(state.bsCount[nextLine]);\n state.bsCount[nextLine] = state.sCount[nextLine] + 1 + (spaceAfterMarker ? 1 : 0);\n\n oldSCount.push(state.sCount[nextLine]);\n state.sCount[nextLine] = offset - initial;\n\n oldTShift.push(state.tShift[nextLine]);\n state.tShift[nextLine] = pos - state.bMarks[nextLine];\n continue;\n }\n\n // Case 2: line is not inside the blockquote, and the last line was empty.\n if (lastLineEmpty) { break; }\n\n // Case 3: another tag found.\n terminate = false;\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n\n if (terminate) {\n // Quirk to enforce \"hard termination mode\" for paragraphs;\n // normally if you call `tokenize(state, startLine, nextLine)`,\n // paragraphs will look below nextLine for paragraph continuation,\n // but if blockquote is terminated by another tag, they shouldn't\n state.lineMax = nextLine;\n\n if (state.blkIndent !== 0) {\n // state.blkIndent was non-zero, we now set it to zero,\n // so we need to re-calculate all offsets to appear as\n // if indent wasn't changed\n oldBMarks.push(state.bMarks[nextLine]);\n oldBSCount.push(state.bsCount[nextLine]);\n oldTShift.push(state.tShift[nextLine]);\n oldSCount.push(state.sCount[nextLine]);\n state.sCount[nextLine] -= state.blkIndent;\n }\n\n break;\n }\n\n oldBMarks.push(state.bMarks[nextLine]);\n oldBSCount.push(state.bsCount[nextLine]);\n oldTShift.push(state.tShift[nextLine]);\n oldSCount.push(state.sCount[nextLine]);\n\n // A negative indentation means that this is a paragraph continuation\n //\n state.sCount[nextLine] = -1;\n }\n\n oldIndent = state.blkIndent;\n state.blkIndent = 0;\n\n token = state.push('blockquote_open', 'blockquote', 1);\n token.markup = '>';\n token.map = lines = [ startLine, 0 ];\n\n state.md.block.tokenize(state, startLine, nextLine);\n\n token = state.push('blockquote_close', 'blockquote', -1);\n token.markup = '>';\n\n state.lineMax = oldLineMax;\n state.parentType = oldParentType;\n lines[1] = state.line;\n\n // Restore original tShift; this might not be necessary since the parser\n // has already been here, but just to make sure we can do that.\n for (i = 0; i < oldTShift.length; i++) {\n state.bMarks[i + startLine] = oldBMarks[i];\n state.tShift[i + startLine] = oldTShift[i];\n state.sCount[i + startLine] = oldSCount[i];\n state.bsCount[i + startLine] = oldBSCount[i];\n }\n state.blkIndent = oldIndent;\n\n return true;\n};\n","'use strict';\n\nvar utils = require('./../utils');\n\nfunction InterceptorManager() {\n this.handlers = [];\n}\n\n/**\n * Add a new interceptor to the stack\n *\n * @param {Function} fulfilled The function to handle `then` for a `Promise`\n * @param {Function} rejected The function to handle `reject` for a `Promise`\n *\n * @return {Number} An ID used to remove interceptor later\n */\nInterceptorManager.prototype.use = function use(fulfilled, rejected, options) {\n this.handlers.push({\n fulfilled: fulfilled,\n rejected: rejected,\n synchronous: options ? options.synchronous : false,\n runWhen: options ? options.runWhen : null\n });\n return this.handlers.length - 1;\n};\n\n/**\n * Remove an interceptor from the stack\n *\n * @param {Number} id The ID that was returned by `use`\n */\nInterceptorManager.prototype.eject = function eject(id) {\n if (this.handlers[id]) {\n this.handlers[id] = null;\n }\n};\n\n/**\n * Iterate over all the registered interceptors\n *\n * This method is particularly useful for skipping over any\n * interceptors that may have become `null` calling `eject`.\n *\n * @param {Function} fn The function to call for each interceptor\n */\nInterceptorManager.prototype.forEach = function forEach(fn) {\n utils.forEach(this.handlers, function forEachHandler(h) {\n if (h !== null) {\n fn(h);\n }\n });\n};\n\nmodule.exports = InterceptorManager;\n","'use strict';\n\n\n////////////////////////////////////////////////////////////////////////////////\n// Helpers\n\n// Merge objects\n//\nfunction assign(obj /*from1, from2, from3, ...*/) {\n var sources = Array.prototype.slice.call(arguments, 1);\n\n sources.forEach(function (source) {\n if (!source) { return; }\n\n Object.keys(source).forEach(function (key) {\n obj[key] = source[key];\n });\n });\n\n return obj;\n}\n\nfunction _class(obj) { return Object.prototype.toString.call(obj); }\nfunction isString(obj) { return _class(obj) === '[object String]'; }\nfunction isObject(obj) { return _class(obj) === '[object Object]'; }\nfunction isRegExp(obj) { return _class(obj) === '[object RegExp]'; }\nfunction isFunction(obj) { return _class(obj) === '[object Function]'; }\n\n\nfunction escapeRE(str) { return str.replace(/[.?*+^$[\\]\\\\(){}|-]/g, '\\\\$&'); }\n\n////////////////////////////////////////////////////////////////////////////////\n\n\nvar defaultOptions = {\n fuzzyLink: true,\n fuzzyEmail: true,\n fuzzyIP: false\n};\n\n\nfunction isOptionsObj(obj) {\n return Object.keys(obj || {}).reduce(function (acc, k) {\n return acc || defaultOptions.hasOwnProperty(k);\n }, false);\n}\n\n\nvar defaultSchemas = {\n 'http:': {\n validate: function (text, pos, self) {\n var tail = text.slice(pos);\n\n if (!self.re.http) {\n // compile lazily, because \"host\"-containing variables can change on tlds update.\n self.re.http = new RegExp(\n '^\\\\/\\\\/' + self.re.src_auth + self.re.src_host_port_strict + self.re.src_path, 'i'\n );\n }\n if (self.re.http.test(tail)) {\n return tail.match(self.re.http)[0].length;\n }\n return 0;\n }\n },\n 'https:': 'http:',\n 'ftp:': 'http:',\n '//': {\n validate: function (text, pos, self) {\n var tail = text.slice(pos);\n\n if (!self.re.no_http) {\n // compile lazily, because \"host\"-containing variables can change on tlds update.\n self.re.no_http = new RegExp(\n '^' +\n self.re.src_auth +\n // Don't allow single-level domains, because of false positives like '//test'\n // with code comments\n '(?:localhost|(?:(?:' + self.re.src_domain + ')\\\\.)+' + self.re.src_domain_root + ')' +\n self.re.src_port +\n self.re.src_host_terminator +\n self.re.src_path,\n\n 'i'\n );\n }\n\n if (self.re.no_http.test(tail)) {\n // should not be `://` & `///`, that protects from errors in protocol name\n if (pos >= 3 && text[pos - 3] === ':') { return 0; }\n if (pos >= 3 && text[pos - 3] === '/') { return 0; }\n return tail.match(self.re.no_http)[0].length;\n }\n return 0;\n }\n },\n 'mailto:': {\n validate: function (text, pos, self) {\n var tail = text.slice(pos);\n\n if (!self.re.mailto) {\n self.re.mailto = new RegExp(\n '^' + self.re.src_email_name + '@' + self.re.src_host_strict, 'i'\n );\n }\n if (self.re.mailto.test(tail)) {\n return tail.match(self.re.mailto)[0].length;\n }\n return 0;\n }\n }\n};\n\n/*eslint-disable max-len*/\n\n// RE pattern for 2-character tlds (autogenerated by ./support/tlds_2char_gen.js)\nvar tlds_2ch_src_re = 'a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvwxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]';\n\n// DON'T try to make PRs with changes. Extend TLDs with LinkifyIt.tlds() instead\nvar tlds_default = 'biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф'.split('|');\n\n/*eslint-enable max-len*/\n\n////////////////////////////////////////////////////////////////////////////////\n\nfunction resetScanCache(self) {\n self.__index__ = -1;\n self.__text_cache__ = '';\n}\n\nfunction createValidator(re) {\n return function (text, pos) {\n var tail = text.slice(pos);\n\n if (re.test(tail)) {\n return tail.match(re)[0].length;\n }\n return 0;\n };\n}\n\nfunction createNormalizer() {\n return function (match, self) {\n self.normalize(match);\n };\n}\n\n// Schemas compiler. Build regexps.\n//\nfunction compile(self) {\n\n // Load & clone RE patterns.\n var re = self.re = require('./lib/re')(self.__opts__);\n\n // Define dynamic patterns\n var tlds = self.__tlds__.slice();\n\n self.onCompile();\n\n if (!self.__tlds_replaced__) {\n tlds.push(tlds_2ch_src_re);\n }\n tlds.push(re.src_xn);\n\n re.src_tlds = tlds.join('|');\n\n function untpl(tpl) { return tpl.replace('%TLDS%', re.src_tlds); }\n\n re.email_fuzzy = RegExp(untpl(re.tpl_email_fuzzy), 'i');\n re.link_fuzzy = RegExp(untpl(re.tpl_link_fuzzy), 'i');\n re.link_no_ip_fuzzy = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'i');\n re.host_fuzzy_test = RegExp(untpl(re.tpl_host_fuzzy_test), 'i');\n\n //\n // Compile each schema\n //\n\n var aliases = [];\n\n self.__compiled__ = {}; // Reset compiled data\n\n function schemaError(name, val) {\n throw new Error('(LinkifyIt) Invalid schema \"' + name + '\": ' + val);\n }\n\n Object.keys(self.__schemas__).forEach(function (name) {\n var val = self.__schemas__[name];\n\n // skip disabled methods\n if (val === null) { return; }\n\n var compiled = { validate: null, link: null };\n\n self.__compiled__[name] = compiled;\n\n if (isObject(val)) {\n if (isRegExp(val.validate)) {\n compiled.validate = createValidator(val.validate);\n } else if (isFunction(val.validate)) {\n compiled.validate = val.validate;\n } else {\n schemaError(name, val);\n }\n\n if (isFunction(val.normalize)) {\n compiled.normalize = val.normalize;\n } else if (!val.normalize) {\n compiled.normalize = createNormalizer();\n } else {\n schemaError(name, val);\n }\n\n return;\n }\n\n if (isString(val)) {\n aliases.push(name);\n return;\n }\n\n schemaError(name, val);\n });\n\n //\n // Compile postponed aliases\n //\n\n aliases.forEach(function (alias) {\n if (!self.__compiled__[self.__schemas__[alias]]) {\n // Silently fail on missed schemas to avoid errons on disable.\n // schemaError(alias, self.__schemas__[alias]);\n return;\n }\n\n self.__compiled__[alias].validate =\n self.__compiled__[self.__schemas__[alias]].validate;\n self.__compiled__[alias].normalize =\n self.__compiled__[self.__schemas__[alias]].normalize;\n });\n\n //\n // Fake record for guessed links\n //\n self.__compiled__[''] = { validate: null, normalize: createNormalizer() };\n\n //\n // Build schema condition\n //\n var slist = Object.keys(self.__compiled__)\n .filter(function (name) {\n // Filter disabled & fake schemas\n return name.length > 0 && self.__compiled__[name];\n })\n .map(escapeRE)\n .join('|');\n // (?!_) cause 1.5x slowdown\n self.re.schema_test = RegExp('(^|(?!_)(?:[><\\uff5c]|' + re.src_ZPCc + '))(' + slist + ')', 'i');\n self.re.schema_search = RegExp('(^|(?!_)(?:[><\\uff5c]|' + re.src_ZPCc + '))(' + slist + ')', 'ig');\n\n self.re.pretest = RegExp(\n '(' + self.re.schema_test.source + ')|(' + self.re.host_fuzzy_test.source + ')|@',\n 'i'\n );\n\n //\n // Cleanup\n //\n\n resetScanCache(self);\n}\n\n/**\n * class Match\n *\n * Match result. Single element of array, returned by [[LinkifyIt#match]]\n **/\nfunction Match(self, shift) {\n var start = self.__index__,\n end = self.__last_index__,\n text = self.__text_cache__.slice(start, end);\n\n /**\n * Match#schema -> String\n *\n * Prefix (protocol) for matched string.\n **/\n this.schema = self.__schema__.toLowerCase();\n /**\n * Match#index -> Number\n *\n * First position of matched string.\n **/\n this.index = start + shift;\n /**\n * Match#lastIndex -> Number\n *\n * Next position after matched string.\n **/\n this.lastIndex = end + shift;\n /**\n * Match#raw -> String\n *\n * Matched string.\n **/\n this.raw = text;\n /**\n * Match#text -> String\n *\n * Notmalized text of matched string.\n **/\n this.text = text;\n /**\n * Match#url -> String\n *\n * Normalized url of matched string.\n **/\n this.url = text;\n}\n\nfunction createMatch(self, shift) {\n var match = new Match(self, shift);\n\n self.__compiled__[match.schema].normalize(match, self);\n\n return match;\n}\n\n\n/**\n * class LinkifyIt\n **/\n\n/**\n * new LinkifyIt(schemas, options)\n * - schemas (Object): Optional. Additional schemas to validate (prefix/validator)\n * - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false }\n *\n * Creates new linkifier instance with optional additional schemas.\n * Can be called without `new` keyword for convenience.\n *\n * By default understands:\n *\n * - `http(s)://...` , `ftp://...`, `mailto:...` & `//...` links\n * - \"fuzzy\" links and emails (example.com, foo@bar.com).\n *\n * `schemas` is an object, where each key/value describes protocol/rule:\n *\n * - __key__ - link prefix (usually, protocol name with `:` at the end, `skype:`\n * for example). `linkify-it` makes shure that prefix is not preceeded with\n * alphanumeric char and symbols. Only whitespaces and punctuation allowed.\n * - __value__ - rule to check tail after link prefix\n * - _String_ - just alias to existing rule\n * - _Object_\n * - _validate_ - validator function (should return matched length on success),\n * or `RegExp`.\n * - _normalize_ - optional function to normalize text & url of matched result\n * (for example, for @twitter mentions).\n *\n * `options`:\n *\n * - __fuzzyLink__ - recognige URL-s without `http(s):` prefix. Default `true`.\n * - __fuzzyIP__ - allow IPs in fuzzy links above. Can conflict with some texts\n * like version numbers. Default `false`.\n * - __fuzzyEmail__ - recognize emails without `mailto:` prefix.\n *\n **/\nfunction LinkifyIt(schemas, options) {\n if (!(this instanceof LinkifyIt)) {\n return new LinkifyIt(schemas, options);\n }\n\n if (!options) {\n if (isOptionsObj(schemas)) {\n options = schemas;\n schemas = {};\n }\n }\n\n this.__opts__ = assign({}, defaultOptions, options);\n\n // Cache last tested result. Used to skip repeating steps on next `match` call.\n this.__index__ = -1;\n this.__last_index__ = -1; // Next scan position\n this.__schema__ = '';\n this.__text_cache__ = '';\n\n this.__schemas__ = assign({}, defaultSchemas, schemas);\n this.__compiled__ = {};\n\n this.__tlds__ = tlds_default;\n this.__tlds_replaced__ = false;\n\n this.re = {};\n\n compile(this);\n}\n\n\n/** chainable\n * LinkifyIt#add(schema, definition)\n * - schema (String): rule name (fixed pattern prefix)\n * - definition (String|RegExp|Object): schema definition\n *\n * Add new rule definition. See constructor description for details.\n **/\nLinkifyIt.prototype.add = function add(schema, definition) {\n this.__schemas__[schema] = definition;\n compile(this);\n return this;\n};\n\n\n/** chainable\n * LinkifyIt#set(options)\n * - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false }\n *\n * Set recognition options for links without schema.\n **/\nLinkifyIt.prototype.set = function set(options) {\n this.__opts__ = assign(this.__opts__, options);\n return this;\n};\n\n\n/**\n * LinkifyIt#test(text) -> Boolean\n *\n * Searches linkifiable pattern and returns `true` on success or `false` on fail.\n **/\nLinkifyIt.prototype.test = function test(text) {\n // Reset scan cache\n this.__text_cache__ = text;\n this.__index__ = -1;\n\n if (!text.length) { return false; }\n\n var m, ml, me, len, shift, next, re, tld_pos, at_pos;\n\n // try to scan for link with schema - that's the most simple rule\n if (this.re.schema_test.test(text)) {\n re = this.re.schema_search;\n re.lastIndex = 0;\n while ((m = re.exec(text)) !== null) {\n len = this.testSchemaAt(text, m[2], re.lastIndex);\n if (len) {\n this.__schema__ = m[2];\n this.__index__ = m.index + m[1].length;\n this.__last_index__ = m.index + m[0].length + len;\n break;\n }\n }\n }\n\n if (this.__opts__.fuzzyLink && this.__compiled__['http:']) {\n // guess schemaless links\n tld_pos = text.search(this.re.host_fuzzy_test);\n if (tld_pos >= 0) {\n // if tld is located after found link - no need to check fuzzy pattern\n if (this.__index__ < 0 || tld_pos < this.__index__) {\n if ((ml = text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy)) !== null) {\n\n shift = ml.index + ml[1].length;\n\n if (this.__index__ < 0 || shift < this.__index__) {\n this.__schema__ = '';\n this.__index__ = shift;\n this.__last_index__ = ml.index + ml[0].length;\n }\n }\n }\n }\n }\n\n if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) {\n // guess schemaless emails\n at_pos = text.indexOf('@');\n if (at_pos >= 0) {\n // We can't skip this check, because this cases are possible:\n // 192.168.1.1@gmail.com, my.in@example.com\n if ((me = text.match(this.re.email_fuzzy)) !== null) {\n\n shift = me.index + me[1].length;\n next = me.index + me[0].length;\n\n if (this.__index__ < 0 || shift < this.__index__ ||\n (shift === this.__index__ && next > this.__last_index__)) {\n this.__schema__ = 'mailto:';\n this.__index__ = shift;\n this.__last_index__ = next;\n }\n }\n }\n }\n\n return this.__index__ >= 0;\n};\n\n\n/**\n * LinkifyIt#pretest(text) -> Boolean\n *\n * Very quick check, that can give false positives. Returns true if link MAY BE\n * can exists. Can be used for speed optimization, when you need to check that\n * link NOT exists.\n **/\nLinkifyIt.prototype.pretest = function pretest(text) {\n return this.re.pretest.test(text);\n};\n\n\n/**\n * LinkifyIt#testSchemaAt(text, name, position) -> Number\n * - text (String): text to scan\n * - name (String): rule (schema) name\n * - position (Number): text offset to check from\n *\n * Similar to [[LinkifyIt#test]] but checks only specific protocol tail exactly\n * at given position. Returns length of found pattern (0 on fail).\n **/\nLinkifyIt.prototype.testSchemaAt = function testSchemaAt(text, schema, pos) {\n // If not supported schema check requested - terminate\n if (!this.__compiled__[schema.toLowerCase()]) {\n return 0;\n }\n return this.__compiled__[schema.toLowerCase()].validate(text, pos, this);\n};\n\n\n/**\n * LinkifyIt#match(text) -> Array|null\n *\n * Returns array of found link descriptions or `null` on fail. We strongly\n * recommend to use [[LinkifyIt#test]] first, for best speed.\n *\n * ##### Result match description\n *\n * - __schema__ - link schema, can be empty for fuzzy links, or `//` for\n * protocol-neutral links.\n * - __index__ - offset of matched text\n * - __lastIndex__ - index of next char after mathch end\n * - __raw__ - matched text\n * - __text__ - normalized text\n * - __url__ - link, generated from matched text\n **/\nLinkifyIt.prototype.match = function match(text) {\n var shift = 0, result = [];\n\n // Try to take previous element from cache, if .test() called before\n if (this.__index__ >= 0 && this.__text_cache__ === text) {\n result.push(createMatch(this, shift));\n shift = this.__last_index__;\n }\n\n // Cut head if cache was used\n var tail = shift ? text.slice(shift) : text;\n\n // Scan string until end reached\n while (this.test(tail)) {\n result.push(createMatch(this, shift));\n\n tail = tail.slice(this.__last_index__);\n shift += this.__last_index__;\n }\n\n if (result.length) {\n return result;\n }\n\n return null;\n};\n\n\n/** chainable\n * LinkifyIt#tlds(list [, keepOld]) -> this\n * - list (Array): list of tlds\n * - keepOld (Boolean): merge with current list if `true` (`false` by default)\n *\n * Load (or merge) new tlds list. Those are user for fuzzy links (without prefix)\n * to avoid false positives. By default this algorythm used:\n *\n * - hostname with any 2-letter root zones are ok.\n * - biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф\n * are ok.\n * - encoded (`xn--...`) root zones are ok.\n *\n * If list is replaced, then exact match for 2-chars root zones will be checked.\n **/\nLinkifyIt.prototype.tlds = function tlds(list, keepOld) {\n list = Array.isArray(list) ? list : [ list ];\n\n if (!keepOld) {\n this.__tlds__ = list.slice();\n this.__tlds_replaced__ = true;\n compile(this);\n return this;\n }\n\n this.__tlds__ = this.__tlds__.concat(list)\n .sort()\n .filter(function (el, idx, arr) {\n return el !== arr[idx - 1];\n })\n .reverse();\n\n compile(this);\n return this;\n};\n\n/**\n * LinkifyIt#normalize(match)\n *\n * Default normalizer (if schema does not define it's own).\n **/\nLinkifyIt.prototype.normalize = function normalize(match) {\n\n // Do minimal possible changes by default. Need to collect feedback prior\n // to move forward https://github.com/markdown-it/linkify-it/issues/1\n\n if (!match.schema) { match.url = 'http://' + match.url; }\n\n if (match.schema === 'mailto:' && !/^mailto:/i.test(match.url)) {\n match.url = 'mailto:' + match.url;\n }\n};\n\n\n/**\n * LinkifyIt#onCompile()\n *\n * Override to modify basic RegExp-s.\n **/\nLinkifyIt.prototype.onCompile = function onCompile() {\n};\n\n\nmodule.exports = LinkifyIt;\n","// Horizontal rule\n\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\n\nmodule.exports = function hr(state, startLine, endLine, silent) {\n var marker, cnt, ch, token,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine];\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n marker = state.src.charCodeAt(pos++);\n\n // Check hr marker\n if (marker !== 0x2A/* * */ &&\n marker !== 0x2D/* - */ &&\n marker !== 0x5F/* _ */) {\n return false;\n }\n\n // markers can be mixed with spaces, but there should be at least 3 of them\n\n cnt = 1;\n while (pos < max) {\n ch = state.src.charCodeAt(pos++);\n if (ch !== marker && !isSpace(ch)) { return false; }\n if (ch === marker) { cnt++; }\n }\n\n if (cnt < 3) { return false; }\n\n if (silent) { return true; }\n\n state.line = startLine + 1;\n\n token = state.push('hr', 'hr', 0);\n token.map = [ startLine, state.line ];\n token.markup = Array(cnt + 1).join(String.fromCharCode(marker));\n\n return true;\n};\n"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-fef08b62.6a3a0578.js b/js/chunk-fef08b62.6a3a0578.js new file mode 100644 index 0000000..7c76471 --- /dev/null +++ b/js/chunk-fef08b62.6a3a0578.js @@ -0,0 +1,2 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-fef08b62"],{"0c1a":function(e,a,o){e.exports=o.p+"img/virtualizacion_diagrama.40320551.png"},"2a9f":function(e,a,o){e.exports=o.p+"img/compose.41295c5b.png"},"3ad8":function(e,a,o){e.exports=o.p+"img/contenedores_diagrama.858e4572.png"},a4f8:function(e,a,o){e.exports=o.p+"img/swarm.71963495.png"},b080:function(e,a,o){e.exports=o.p+"img/docker.16d69f9e.png"},df66:function(e,a,o){e.exports=o.p+"img/docker_intro.1a2ca7e8.png"},e07e:function(e,a,o){"use strict";o.r(a);var n=function(){var e=this,a=e.$createElement;e._self._c;return e._m(0)},s=[function(){var e=this,a=e.$createElement,n=e._self._c||a;return n("section",[n("h1",{attrs:{id:"containers-y-docker"}},[e._v("Containers y Docker "),n("a",{staticClass:"header-anchor",attrs:{href:"#containers-y-docker"}},[e._v("¶")])]),n("p",[e._v("Los contenedores, junto con la tecnología de contenedorización como Docker y Kubernetes , se han convertido en componentes cada vez más comunes en los kits de herramientas de muchos desarrolladores. El objetivo de los contenedores, en esencia, es ofrecer una mejor manera de crear, empaquetar e implementar software en diferentes entornos de una manera predecible y fácil de administrar.")]),n("h2",{attrs:{id:"que-es-un-contenedor"}},[e._v("Que es un Contenedor??? "),n("a",{staticClass:"header-anchor",attrs:{href:"#que-es-un-contenedor"}},[e._v("¶")])]),n("p",[e._v("Los contenedores son una tecnología de virtualización del sistema operativo que se utiliza para empaquetar aplicaciones y sus dependencias y ejecutarlas en entornos aislados. Proporcionan un método ligero de empaquetar e implementar aplicaciones de manera estandarizada en muchos tipos diferentes de infraestructura.")]),n("p",[e._v("Estos objetivos hacen que los contenedores sean una opción atractiva tanto para desarrolladores como para sys ops. Los contenedores se ejecutan constantemente en cualquier host con capacidad de hostearlos, por lo que los desarrolladores pueden probar el mismo software localmente que luego implementarán en entornos de producción completos. El formato del contenedor también asegura que las dependencias de la aplicación se cuecen en la imagen misma, simplificando los procesos de entrega y liberación. Debido a que los hosts y las plataformas que ejecutan contenedores son genéricos, la gestión de la infraestructura para sistemas basados ​​en contenedores puede estandarizarse.")]),n("p",[e._v("Los contenedores se crean a partir de imágenes: paquetes que representan el sistema, las aplicaciones y el entorno del contenedor. Las imágenes de contenedor actúan como plantillas para crear contenedores específicos, y la misma imagen se puede usar para generar cualquier cantidad de contenedores en ejecución.")]),n("p",[e._v("Esto es similar a cómo funcionan las clases y las instancias en la programación orientada a objetos; Se puede usar una sola clase para crear cualquier número de instancias así como se puede usar una sola imagen de contenedor para crear cualquier número de contenedores. Esta analogía también es válida con respecto a la herencia, ya que las imágenes de contenedor pueden actuar como el padre de otras imágenes de contenedor más personalizadas. Los usuarios pueden descargar contenedores preconstruidos de fuentes externas o crear sus propias imágenes personalizadas según sus necesidades.")]),n("h2",{attrs:{id:"introduccion-a-docker"}},[e._v("Introduccion a Docker "),n("a",{staticClass:"header-anchor",attrs:{href:"#introduccion-a-docker"}},[e._v("¶")])]),n("img",{staticClass:"center",attrs:{src:o("b080")}}),n("p",[e._v("Si bien los contenedores de Linux son una tecnología algo genérica que se puede implementar y administrar de diferentes maneras, Docker es, con mucho, la forma más común de ejecutar contenedores de construcción y ejecución. Docker es un conjunto de herramientas que permiten a los usuarios crear imágenes de contenedores, insertar o extraer imágenes de registros externos, y ejecutar y administrar contenedores en muchos entornos diferentes. El aumento en la popularidad de los contenedores en Linux se puede atribuir directamente a los esfuerzos de Docker después de su lanzamiento en 2013.")]),n("p",[e._v("En docker podemos ejecutar y administrar contenedores, actuando como administrador de procesos para cargas de trabajo de contenedores. Se puede crear nuevas imágenes de contenedor leyendo y ejecutando comandos desde el Dockerfile tomando snapshots de contenedores que ya se están ejecutando. El comando también puede interactuar con Docker Hub, que es un registro de imágenes de contenedor, para desplegar nuevas imágenes de contenedor o subir imágenes locales para guardarlas o publicarlas.")]),n("p",[e._v("Si bien Docker proporciona sólo una de las muchas implementaciones de contenedores en Linux, tiene la distinción de ser el punto de entrada más común en el mundo de los contenedores y la solución más comúnmente implementada. Si bien se han desarrollado estándares abiertos para contenedores para garantizar la interoperabilidad, la mayoría de las plataformas y herramientas relacionadas con contenedores tratan a Docker como su objetivo principal al probar y lanzar software. Docker puede no ser siempre la solución más eficiente para un entorno dado, pero es probable que sea una de las opciones mejor probadas.")]),n("p",[e._v("En términos prácticos, si bien existen alternativas para los contenedores en Linux, generalmente tiene sentido aprender Docker primero debido a su ubicuidad y su influencia en la terminología, los estándares y las herramientas del ecosistema.")]),n("h3",{attrs:{id:"cómo-funcionan-los-contenedores"}},[e._v("Cómo funcionan los contenedores "),n("a",{staticClass:"header-anchor",attrs:{href:"#cómo-funcionan-los-contenedores"}},[e._v("¶")])]),n("p",[e._v("Docker implementa una API de alto nivel para proporcionar contenedores livianos que ejecutan procesos de manera aislada. Construido sobre el kernel Linux, es decir, usa directamente las funciones que este proporciona, lo que lo hace mucho más liviano que una máquina virtual. utiliza el aislamiento de recursos (CPU, la memoria, el bloque E / S, red, etc.) y namespaces separados para aislar la vista de una aplicación del sistema operativo. Docker accede a la virtualización del kernel Linux ya sea directamente a través de la biblioteca libcontainer.")]),n("img",{staticClass:"center iasc-image",attrs:{src:o("df66")}}),n("p",[n("em",[e._v("Libcontainer")]),e._v(" es una abstracción, para soportar una gama más amplia de tecnologías de aislamiento.")]),n("p",[n("em",[e._v("Libvirt")]),e._v(" es una API de código abierto, demonio y herramienta de administración para administrar la virtualización de la plataforma.")]),n("p",[n("em",[e._v("LXC (Linux Containers)")]),e._v(" es una tecnología de virtualización en el nivel de SO. Permite que un servidor físico ejecute múltiples instancias de sistemas operativos aislados, conocidos como Servidores Privados Virtuales (VPS en inglés). LXC no provee de una máquina virtual, más bien provee un entorno virtual que tiene su propio espacio de procesos y redes.")]),n("p",[n("em",[e._v("Systemd")]),e._v(" es un conjunto de demonios o daemons de administración de sistema, bibliotecas y herramientas diseñados como una plataforma de administración y configuración central para interactuar con el núcleo del Sistema operativo GNU/Linux.")]),n("h3",{attrs:{id:"cómo-funcionan-internamente-los-contenedores-en-linux"}},[e._v("Cómo funcionan internamente los contenedores en linux? "),n("a",{staticClass:"header-anchor",attrs:{href:"#cómo-funcionan-internamente-los-contenedores-en-linux"}},[e._v("¶")])]),n("p",[e._v("El kernel de linux posee algo llamado grupos de control de Linux , o cgroups , y que son una característica del núcleo que permite que los procesos y sus recursos se agrupen, aislen y administren como una unidad. cgroups permite agrupar procesos, determinar a qué recursos pueden acceder y proporcionar un mecanismo para administrar y monitorear su comportamiento. Siguen un sistema jerárquico que permite que los procesos secundarios heredan las condiciones de sus padres y potencialmente adopten más restricciones. Los cgroups proporcionan la funcionalidad necesaria para agrupar procesos como un grupo y limitar los recursos a los que pueden acceder.")]),n("p",[e._v("La otra característica principal del núcleo en la que confían los contenedores son los espacios de nombres de Linux . Los espacios de nombres limitan lo que los procesos pueden ver del resto del sistema. Los procesos que se ejecutan dentro de los espacios de nombres no conocen nada que se ejecute fuera de su espacio de nombres. Debido a que los espacios de nombres definen un contexto distinto que está separado del resto del sistema, el árbol de procesos del espacio de nombres debe reflejar ese contexto. Dentro del espacio de nombres, el proceso principal se convierte en PID 1 (ID de proceso 1), el PID tradicionalmente reservado para el sistema init del sistema operativo. Este árbol de procesos virtuales muy manipulado construido dentro del espacio de nombres permite que los procesos que se ejecutan dentro de los contenedores se comporten como si estuvieran operando en un entorno normal y sin restricciones.")]),n("h2",{attrs:{id:"máquinas-virtuales-vs-contenedores"}},[e._v("Máquinas Virtuales vs Contenedores "),n("a",{staticClass:"header-anchor",attrs:{href:"#máquinas-virtuales-vs-contenedores"}},[e._v("¶")])]),n("p",[e._v("Las máquinas virtuales , o VM, son una tecnología de virtualización de hardware que le permite virtualizar completamente el hardware y los recursos de una computadora. Un sistema operativo invitado (guest) separado administra la máquina virtual, completamente separada del sistema operativo que se ejecuta en el sistema host. En el sistema host, un software llamado hipervisor (hypervisor) es responsable de iniciar, detener y administrar las máquinas virtuales.")]),n("p",[e._v("Debido a que las máquinas virtuales funcionan como computadoras completamente distintas que, en condiciones normales de funcionamiento, no pueden afectar el sistema host u otras máquinas virtuales, las máquinas virtuales ofrecen un gran aislamiento y seguridad. Sin embargo, tienen sus inconvenientes. Por ejemplo, la virtualización de una computadora completa requiere que las máquinas virtuales utilizan una cantidad significativa de recursos. Dado que la máquina virtual es operada por un sistema operativo invitado completo, el aprovisionamiento de la máquina virtual y los tiempos de arranque pueden ser bastante lentos. Del mismo modo, dado que la VM funciona como una máquina independiente, los administradores a menudo necesitan adoptar herramientas y procesos de administración similares a la infraestructura para actualizar y ejecutar los entornos individuales.")]),n("img",{staticClass:"center",attrs:{src:o("0c1a")}}),n("p",[e._v("En general, las máquinas virtuales le permiten subdividir los recursos de una máquina en computadoras individuales más pequeñas, pero el resultado final no difiere significativamente de la administración de una flota de computadoras físicas. La membresía de la flota se expande y la responsabilidad de cada host puede centrarse más, pero las herramientas, estrategias y procesos que emplea y las capacidades de su sistema probablemente no cambiarán notablemente.")]),n("p",[e._v("Los contenedores toman un enfoque diferente como vimos antes. En lugar de virtualizar toda la computadora, los contenedores virtualizan el sistema operativo directamente. Se ejecutan como procesos especializados administrados por el núcleo del sistema operativo host, pero con una visión restringida y muy manipulada de los procesos, recursos y entorno del sistema.")]),n("img",{staticClass:"center",attrs:{src:o("3ad8")}}),n("p",[e._v("Los contenedores no son conscientes de que existen en un sistema compartido y funcionan como si tuvieran el control total de la computadora.")]),n("h3",{attrs:{id:"ventajas-de-utilizar-contenedores"}},[e._v("Ventajas de utilizar contenedores "),n("a",{staticClass:"header-anchor",attrs:{href:"#ventajas-de-utilizar-contenedores"}},[e._v("¶")])]),n("ul",[n("li",[e._v("Aislamiento")])]),n("p",[e._v("Construido sobre las facilidades proporcionadas por el kernel Linux (principalmente cgroups y namespaces), un contenedor Docker, a diferencia de una máquina virtual, no requiere incluir un sistema operativo independiente.En su lugar, se basa en las funcionalidades del kernel y utiliza el aislamiento de recursos (CPU, la memoria, el bloque E / S, red, etc.) y namespaces separados para aislar la vista de una aplicación del sistema operativo. Docker accede a la virtualización del kernel Linux ya sea directamente a través de la biblioteca libcontainer o indirectamente a través de libvirt, LXC o systemd.")]),n("p",[e._v("Mediante el uso de contenedores, los recursos pueden ser aislados, los servicios restringidos, y se otorga a los procesos la capacidad de tener una visión casi completamente privada del sistema operativo con su propio identificador de espacio de proceso, la estructura del sistema de archivos, y las interfaces de red.")]),n("ul",[n("li",[e._v("Virtualización Ligera")])]),n("p",[e._v('Es la principal diferencia con las máquinas virtuales, ya que estas virtualizan todo un sistema operativo con sus componentes, compartiendo recursos con el host. La filosofía de los contenedores es distinta, si bien tratan también de aislar a las aplicaciones y de generar un entorno replicable y estable para que funcionen, en lugar de albergar un sistema operativo completo lo que hacen es compartir los recursos del propio sistema operativo "host" sobre el que se ejecutan.')]),n("h3",{attrs:{id:"que-pasa-cuando-quiero-crear-y-utilizarlevantar-múltiples-contenedores-intro-a-docker-compose"}},[e._v("Que pasa cuando quiero crear y utilizar/levantar múltiples contenedores (Intro a docker compose) "),n("a",{staticClass:"header-anchor",attrs:{href:"#que-pasa-cuando-quiero-crear-y-utilizarlevantar-múltiples-contenedores-intro-a-docker-compose"}},[e._v("¶")])]),n("p",[e._v("Docker compose es una herramienta para definir y ejecutar aplicaciones Docker de contenedores múltiples. Utiliza archivos YAML para configurar los servicios de la aplicación y realiza el proceso de creación y puesta en marcha de todos los contenedores con un solo comando. La utilidad cliente (CLI) docker-compose permite a los usuarios ejecutar comandos en varios contenedores a la vez, por ejemplo, crear imágenes, escalar contenedores, ejecutar contenedores que se detuvieron y más.")]),n("img",{staticClass:"center iasc-image",attrs:{src:o("2a9f")}}),n("h2",{attrs:{id:"orquestación-de-contenedores-con-swarm"}},[e._v("Orquestación de contenedores con Swarm "),n("a",{staticClass:"header-anchor",attrs:{href:"#orquestación-de-contenedores-con-swarm"}},[e._v("¶")])]),n("p",[e._v("Docker Swarm proporciona una funcionalidad de agrupación nativa para contenedores Docker, que convierte un grupo de “Docker Engines” en un único “Docker engine” virtual. Swarm está integrado con Docker Engine. El cliente de docker swarm permite a los usuarios ejecutar contenedores Swarm, crear tokens, enumerar nodos en el clúster y más. También permite a los usuarios ejecutar varios comandos para administrar nodos en manada (Swarm). Docker maneja el swarm usando el algoritmo Raft. Según Raft, para que se realice una actualización, la mayoría de los nodos de Swarm deben estar de acuerdo con la actualización.")]),n("img",{staticClass:"center iasc-image",attrs:{src:o("a4f8")}})])}],r=o("2877"),i={},t=Object(r["a"])(i,n,s,!1,null,null,null);a["default"]=t.exports}}]); +//# sourceMappingURL=chunk-fef08b62.6a3a0578.js.map \ No newline at end of file diff --git a/js/chunk-fef08b62.6a3a0578.js.map b/js/chunk-fef08b62.6a3a0578.js.map new file mode 100644 index 0000000..1031689 --- /dev/null +++ b/js/chunk-fef08b62.6a3a0578.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/images/contenedores/virtualizacion_diagrama.png","webpack:///./src/images/contenedores/compose.png","webpack:///./src/images/contenedores/contenedores_diagrama.png","webpack:///./src/images/contenedores/swarm.png","webpack:///./src/images/contenedores/docker.png","webpack:///./src/images/contenedores/docker_intro.png","webpack:///./src/content/contenedores.md?8fba","webpack:///./src/content/contenedores.md"],"names":["module","exports","render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","attrs","_v","staticClass","script","component"],"mappings":"qGAAAA,EAAOC,QAAU,IAA0B,4C,uBCA3CD,EAAOC,QAAU,IAA0B,4B,uBCA3CD,EAAOC,QAAU,IAA0B,0C,qBCA3CD,EAAOC,QAAU,IAA0B,0B,qBCA3CD,EAAOC,QAAU,IAA0B,2B,qBCA3CD,EAAOC,QAAU,IAA0B,iC,yCCA3C,IAAIC,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAsBH,EAAII,MAAMC,GAAO,OAAOL,EAAIM,GAAG,IACnGC,EAAkB,CAAC,WAAa,IAAIP,EAAIC,KAASC,EAAGF,EAAIG,eAAmBE,EAAGL,EAAII,MAAMC,IAAIH,EAAG,OAAOG,EAAG,UAAU,CAACA,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,wBAAwB,CAACR,EAAIS,GAAG,wBAAwBJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,yBAAyB,CAACR,EAAIS,GAAG,SAASJ,EAAG,IAAI,CAACL,EAAIS,GAAG,yYAAyYJ,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,yBAAyB,CAACR,EAAIS,GAAG,4BAA4BJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,0BAA0B,CAACR,EAAIS,GAAG,SAASJ,EAAG,IAAI,CAACL,EAAIS,GAAG,kUAAkUJ,EAAG,IAAI,CAACL,EAAIS,GAAG,6qBAA6qBJ,EAAG,IAAI,CAACL,EAAIS,GAAG,6TAA6TJ,EAAG,IAAI,CAACL,EAAIS,GAAG,klBAAklBJ,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,0BAA0B,CAACR,EAAIS,GAAG,0BAA0BJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,2BAA2B,CAACR,EAAIS,GAAG,SAASJ,EAAG,MAAM,CAACK,YAAY,SAASF,MAAM,CAAC,IAAM,EAAQ,WAAuCH,EAAG,IAAI,CAACL,EAAIS,GAAG,qlBAAqlBJ,EAAG,IAAI,CAACL,EAAIS,GAAG,ifAAifJ,EAAG,IAAI,CAACL,EAAIS,GAAG,0mBAA0mBJ,EAAG,IAAI,CAACL,EAAIS,GAAG,wPAAwPJ,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,oCAAoC,CAACR,EAAIS,GAAG,oCAAoCJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,qCAAqC,CAACR,EAAIS,GAAG,SAASJ,EAAG,IAAI,CAACL,EAAIS,GAAG,8iBAA8iBJ,EAAG,MAAM,CAACK,YAAY,oBAAoBF,MAAM,CAAC,IAAM,EAAQ,WAA6CH,EAAG,IAAI,CAACA,EAAG,KAAK,CAACL,EAAIS,GAAG,kBAAkBT,EAAIS,GAAG,2FAA2FJ,EAAG,IAAI,CAACA,EAAG,KAAK,CAACL,EAAIS,GAAG,aAAaT,EAAIS,GAAG,iIAAiIJ,EAAG,IAAI,CAACA,EAAG,KAAK,CAACL,EAAIS,GAAG,4BAA4BT,EAAIS,GAAG,kVAAkVJ,EAAG,IAAI,CAACA,EAAG,KAAK,CAACL,EAAIS,GAAG,aAAaT,EAAIS,GAAG,4OAA4OJ,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,0DAA0D,CAACR,EAAIS,GAAG,2DAA2DJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,2DAA2D,CAACR,EAAIS,GAAG,SAASJ,EAAG,IAAI,CAACL,EAAIS,GAAG,mpBAAmpBJ,EAAG,IAAI,CAACL,EAAIS,GAAG,65BAA65BJ,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,uCAAuC,CAACR,EAAIS,GAAG,uCAAuCJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,wCAAwC,CAACR,EAAIS,GAAG,SAASJ,EAAG,IAAI,CAACL,EAAIS,GAAG,odAAodJ,EAAG,IAAI,CAACL,EAAIS,GAAG,62BAA62BJ,EAAG,MAAM,CAACK,YAAY,SAASF,MAAM,CAAC,IAAM,EAAQ,WAAwDH,EAAG,IAAI,CAACL,EAAIS,GAAG,odAAodJ,EAAG,IAAI,CAACL,EAAIS,GAAG,mXAAmXJ,EAAG,MAAM,CAACK,YAAY,SAASF,MAAM,CAAC,IAAM,EAAQ,WAAsDH,EAAG,IAAI,CAACL,EAAIS,GAAG,kJAAkJJ,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,sCAAsC,CAACR,EAAIS,GAAG,sCAAsCJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,uCAAuC,CAACR,EAAIS,GAAG,SAASJ,EAAG,KAAK,CAACA,EAAG,KAAK,CAACL,EAAIS,GAAG,mBAAmBJ,EAAG,IAAI,CAACL,EAAIS,GAAG,omBAAomBJ,EAAG,IAAI,CAACL,EAAIS,GAAG,oUAAoUJ,EAAG,KAAK,CAACA,EAAG,KAAK,CAACL,EAAIS,GAAG,6BAA6BJ,EAAG,IAAI,CAACL,EAAIS,GAAG,keAAoeJ,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,kGAAkG,CAACR,EAAIS,GAAG,qGAAqGJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,mGAAmG,CAACR,EAAIS,GAAG,SAASJ,EAAG,IAAI,CAACL,EAAIS,GAAG,2eAA2eJ,EAAG,MAAM,CAACK,YAAY,oBAAoBF,MAAM,CAAC,IAAM,EAAQ,WAAwCH,EAAG,KAAK,CAACG,MAAM,CAAC,GAAK,2CAA2C,CAACR,EAAIS,GAAG,2CAA2CJ,EAAG,IAAI,CAACK,YAAY,gBAAgBF,MAAM,CAAC,KAAO,4CAA4C,CAACR,EAAIS,GAAG,SAASJ,EAAG,IAAI,CAACL,EAAIS,GAAG,4mBAA4mBJ,EAAG,MAAM,CAACK,YAAY,oBAAoBF,MAAM,CAAC,IAAM,EAAQ,e,YCApkeG,EAAS,GAKTC,EAAY,eACdD,EACAZ,EACAQ,GACA,EACA,KACA,KACA,MAIa,aAAAK,E","file":"js/chunk-fef08b62.6a3a0578.js","sourcesContent":["module.exports = __webpack_public_path__ + \"img/virtualizacion_diagrama.40320551.png\";","module.exports = __webpack_public_path__ + \"img/compose.41295c5b.png\";","module.exports = __webpack_public_path__ + \"img/contenedores_diagrama.858e4572.png\";","module.exports = __webpack_public_path__ + \"img/swarm.71963495.png\";","module.exports = __webpack_public_path__ + \"img/docker.16d69f9e.png\";","module.exports = __webpack_public_path__ + \"img/docker_intro.1a2ca7e8.png\";","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('h1',{attrs:{\"id\":\"containers-y-docker\"}},[_vm._v(\"Containers y Docker \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#containers-y-docker\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Los contenedores, junto con la tecnología de contenedorización como Docker y Kubernetes , se han convertido en componentes cada vez más comunes en los kits de herramientas de muchos desarrolladores. El objetivo de los contenedores, en esencia, es ofrecer una mejor manera de crear, empaquetar e implementar software en diferentes entornos de una manera predecible y fácil de administrar.\")]),_c('h2',{attrs:{\"id\":\"que-es-un-contenedor\"}},[_vm._v(\"Que es un Contenedor??? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#que-es-un-contenedor\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Los contenedores son una tecnología de virtualización del sistema operativo que se utiliza para empaquetar aplicaciones y sus dependencias y ejecutarlas en entornos aislados. Proporcionan un método ligero de empaquetar e implementar aplicaciones de manera estandarizada en muchos tipos diferentes de infraestructura.\")]),_c('p',[_vm._v(\"Estos objetivos hacen que los contenedores sean una opción atractiva tanto para desarrolladores como para sys ops. Los contenedores se ejecutan constantemente en cualquier host con capacidad de hostearlos, por lo que los desarrolladores pueden probar el mismo software localmente que luego implementarán en entornos de producción completos. El formato del contenedor también asegura que las dependencias de la aplicación se cuecen en la imagen misma, simplificando los procesos de entrega y liberación. Debido a que los hosts y las plataformas que ejecutan contenedores son genéricos, la gestión de la infraestructura para sistemas basados ​​en contenedores puede estandarizarse.\")]),_c('p',[_vm._v(\"Los contenedores se crean a partir de imágenes: paquetes que representan el sistema, las aplicaciones y el entorno del contenedor. Las imágenes de contenedor actúan como plantillas para crear contenedores específicos, y la misma imagen se puede usar para generar cualquier cantidad de contenedores en ejecución.\")]),_c('p',[_vm._v(\"Esto es similar a cómo funcionan las clases y las instancias en la programación orientada a objetos; Se puede usar una sola clase para crear cualquier número de instancias así como se puede usar una sola imagen de contenedor para crear cualquier número de contenedores. Esta analogía también es válida con respecto a la herencia, ya que las imágenes de contenedor pueden actuar como el padre de otras imágenes de contenedor más personalizadas. Los usuarios pueden descargar contenedores preconstruidos de fuentes externas o crear sus propias imágenes personalizadas según sus necesidades.\")]),_c('h2',{attrs:{\"id\":\"introduccion-a-docker\"}},[_vm._v(\"Introduccion a Docker \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#introduccion-a-docker\"}},[_vm._v(\"¶\")])]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/contenedores/docker.png\")}}),_c('p',[_vm._v(\"Si bien los contenedores de Linux son una tecnología algo genérica que se puede implementar y administrar de diferentes maneras, Docker es, con mucho, la forma más común de ejecutar contenedores de construcción y ejecución. Docker es un conjunto de herramientas que permiten a los usuarios crear imágenes de contenedores, insertar o extraer imágenes de registros externos, y ejecutar y administrar contenedores en muchos entornos diferentes. El aumento en la popularidad de los contenedores en Linux se puede atribuir directamente a los esfuerzos de Docker después de su lanzamiento en 2013.\")]),_c('p',[_vm._v(\"En docker podemos ejecutar y administrar contenedores, actuando como administrador de procesos para cargas de trabajo de contenedores. Se puede crear nuevas imágenes de contenedor leyendo y ejecutando comandos desde el Dockerfile tomando snapshots de contenedores que ya se están ejecutando. El comando también puede interactuar con Docker Hub, que es un registro de imágenes de contenedor, para desplegar nuevas imágenes de contenedor o subir imágenes locales para guardarlas o publicarlas.\")]),_c('p',[_vm._v(\"Si bien Docker proporciona sólo una de las muchas implementaciones de contenedores en Linux, tiene la distinción de ser el punto de entrada más común en el mundo de los contenedores y la solución más comúnmente implementada. Si bien se han desarrollado estándares abiertos para contenedores para garantizar la interoperabilidad, la mayoría de las plataformas y herramientas relacionadas con contenedores tratan a Docker como su objetivo principal al probar y lanzar software. Docker puede no ser siempre la solución más eficiente para un entorno dado, pero es probable que sea una de las opciones mejor probadas.\")]),_c('p',[_vm._v(\"En términos prácticos, si bien existen alternativas para los contenedores en Linux, generalmente tiene sentido aprender Docker primero debido a su ubicuidad y su influencia en la terminología, los estándares y las herramientas del ecosistema.\")]),_c('h3',{attrs:{\"id\":\"cómo-funcionan-los-contenedores\"}},[_vm._v(\"Cómo funcionan los contenedores \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#cómo-funcionan-los-contenedores\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Docker implementa una API de alto nivel para proporcionar contenedores livianos que ejecutan procesos de manera aislada. Construido sobre el kernel Linux, es decir, usa directamente las funciones que este proporciona, lo que lo hace mucho más liviano que una máquina virtual. utiliza el aislamiento de recursos (CPU, la memoria, el bloque E / S, red, etc.) y namespaces separados para aislar la vista de una aplicación del sistema operativo. Docker accede a la virtualización del kernel Linux ya sea directamente a través de la biblioteca libcontainer.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/contenedores/docker_intro.png\")}}),_c('p',[_c('em',[_vm._v(\"Libcontainer\")]),_vm._v(\" es una abstracción, para soportar una gama más amplia de tecnologías de aislamiento.\")]),_c('p',[_c('em',[_vm._v(\"Libvirt\")]),_vm._v(\" es una API de código abierto, demonio y herramienta de administración para administrar la virtualización de la plataforma.\")]),_c('p',[_c('em',[_vm._v(\"LXC (Linux Containers)\")]),_vm._v(\" es una tecnología de virtualización en el nivel de SO. Permite que un servidor físico ejecute múltiples instancias de sistemas operativos aislados, conocidos como Servidores Privados Virtuales (VPS en inglés). LXC no provee de una máquina virtual, más bien provee un entorno virtual que tiene su propio espacio de procesos y redes.\")]),_c('p',[_c('em',[_vm._v(\"Systemd\")]),_vm._v(\" es un conjunto de demonios o daemons de administración de sistema, bibliotecas y herramientas diseñados como una plataforma de administración y configuración central para interactuar con el núcleo del Sistema operativo GNU/Linux.\")]),_c('h3',{attrs:{\"id\":\"cómo-funcionan-internamente-los-contenedores-en-linux\"}},[_vm._v(\"Cómo funcionan internamente los contenedores en linux? \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#cómo-funcionan-internamente-los-contenedores-en-linux\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"El kernel de linux posee algo llamado grupos de control de Linux , o cgroups , y que son una característica del núcleo que permite que los procesos y sus recursos se agrupen, aislen y administren como una unidad. cgroups permite agrupar procesos, determinar a qué recursos pueden acceder y proporcionar un mecanismo para administrar y monitorear su comportamiento. Siguen un sistema jerárquico que permite que los procesos secundarios heredan las condiciones de sus padres y potencialmente adopten más restricciones. Los cgroups proporcionan la funcionalidad necesaria para agrupar procesos como un grupo y limitar los recursos a los que pueden acceder.\")]),_c('p',[_vm._v(\"La otra característica principal del núcleo en la que confían los contenedores son los espacios de nombres de Linux . Los espacios de nombres limitan lo que los procesos pueden ver del resto del sistema. Los procesos que se ejecutan dentro de los espacios de nombres no conocen nada que se ejecute fuera de su espacio de nombres. Debido a que los espacios de nombres definen un contexto distinto que está separado del resto del sistema, el árbol de procesos del espacio de nombres debe reflejar ese contexto. Dentro del espacio de nombres, el proceso principal se convierte en PID 1 (ID de proceso 1), el PID tradicionalmente reservado para el sistema init del sistema operativo. Este árbol de procesos virtuales muy manipulado construido dentro del espacio de nombres permite que los procesos que se ejecutan dentro de los contenedores se comporten como si estuvieran operando en un entorno normal y sin restricciones.\")]),_c('h2',{attrs:{\"id\":\"máquinas-virtuales-vs-contenedores\"}},[_vm._v(\"Máquinas Virtuales vs Contenedores \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#máquinas-virtuales-vs-contenedores\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Las máquinas virtuales , o VM, son una tecnología de virtualización de hardware que le permite virtualizar completamente el hardware y los recursos de una computadora. Un sistema operativo invitado (guest) separado administra la máquina virtual, completamente separada del sistema operativo que se ejecuta en el sistema host. En el sistema host, un software llamado hipervisor (hypervisor) es responsable de iniciar, detener y administrar las máquinas virtuales.\")]),_c('p',[_vm._v(\"Debido a que las máquinas virtuales funcionan como computadoras completamente distintas que, en condiciones normales de funcionamiento, no pueden afectar el sistema host u otras máquinas virtuales, las máquinas virtuales ofrecen un gran aislamiento y seguridad. Sin embargo, tienen sus inconvenientes. Por ejemplo, la virtualización de una computadora completa requiere que las máquinas virtuales utilizan una cantidad significativa de recursos. Dado que la máquina virtual es operada por un sistema operativo invitado completo, el aprovisionamiento de la máquina virtual y los tiempos de arranque pueden ser bastante lentos. Del mismo modo, dado que la VM funciona como una máquina independiente, los administradores a menudo necesitan adoptar herramientas y procesos de administración similares a la infraestructura para actualizar y ejecutar los entornos individuales.\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/contenedores/virtualizacion_diagrama.png\")}}),_c('p',[_vm._v(\"En general, las máquinas virtuales le permiten subdividir los recursos de una máquina en computadoras individuales más pequeñas, pero el resultado final no difiere significativamente de la administración de una flota de computadoras físicas. La membresía de la flota se expande y la responsabilidad de cada host puede centrarse más, pero las herramientas, estrategias y procesos que emplea y las capacidades de su sistema probablemente no cambiarán notablemente.\")]),_c('p',[_vm._v(\"Los contenedores toman un enfoque diferente como vimos antes. En lugar de virtualizar toda la computadora, los contenedores virtualizan el sistema operativo directamente. Se ejecutan como procesos especializados administrados por el núcleo del sistema operativo host, pero con una visión restringida y muy manipulada de los procesos, recursos y entorno del sistema.\")]),_c('img',{staticClass:\"center\",attrs:{\"src\":require(\"@/images/contenedores/contenedores_diagrama.png\")}}),_c('p',[_vm._v(\"Los contenedores no son conscientes de que existen en un sistema compartido y funcionan como si tuvieran el control total de la computadora.\")]),_c('h3',{attrs:{\"id\":\"ventajas-de-utilizar-contenedores\"}},[_vm._v(\"Ventajas de utilizar contenedores \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#ventajas-de-utilizar-contenedores\"}},[_vm._v(\"¶\")])]),_c('ul',[_c('li',[_vm._v(\"Aislamiento\")])]),_c('p',[_vm._v(\"Construido sobre las facilidades proporcionadas por el kernel Linux (principalmente cgroups y namespaces), un contenedor Docker, a diferencia de una máquina virtual, no requiere incluir un sistema operativo independiente.En su lugar, se basa en las funcionalidades del kernel y utiliza el aislamiento de recursos (CPU, la memoria, el bloque E / S, red, etc.) y namespaces separados para aislar la vista de una aplicación del sistema operativo. Docker accede a la virtualización del kernel Linux ya sea directamente a través de la biblioteca libcontainer o indirectamente a través de libvirt, LXC o systemd.\")]),_c('p',[_vm._v(\"Mediante el uso de contenedores, los recursos pueden ser aislados, los servicios restringidos, y se otorga a los procesos la capacidad de tener una visión casi completamente privada del sistema operativo con su propio identificador de espacio de proceso, la estructura del sistema de archivos, y las interfaces de red.\")]),_c('ul',[_c('li',[_vm._v(\"Virtualización Ligera\")])]),_c('p',[_vm._v(\"Es la principal diferencia con las máquinas virtuales, ya que estas virtualizan todo un sistema operativo con sus componentes, compartiendo recursos con el host. La filosofía de los contenedores es distinta, si bien tratan también de aislar a las aplicaciones y de generar un entorno replicable y estable para que funcionen, en lugar de albergar un sistema operativo completo lo que hacen es compartir los recursos del propio sistema operativo \\\"host\\\" sobre el que se ejecutan.\")]),_c('h3',{attrs:{\"id\":\"que-pasa-cuando-quiero-crear-y-utilizarlevantar-múltiples-contenedores-intro-a-docker-compose\"}},[_vm._v(\"Que pasa cuando quiero crear y utilizar/levantar múltiples contenedores (Intro a docker compose) \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#que-pasa-cuando-quiero-crear-y-utilizarlevantar-múltiples-contenedores-intro-a-docker-compose\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Docker compose es una herramienta para definir y ejecutar aplicaciones Docker de contenedores múltiples. Utiliza archivos YAML para configurar los servicios de la aplicación y realiza el proceso de creación y puesta en marcha de todos los contenedores con un solo comando. La utilidad cliente (CLI) docker-compose permite a los usuarios ejecutar comandos en varios contenedores a la vez, por ejemplo, crear imágenes, escalar contenedores, ejecutar contenedores que se detuvieron y más.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/contenedores/compose.png\")}}),_c('h2',{attrs:{\"id\":\"orquestación-de-contenedores-con-swarm\"}},[_vm._v(\"Orquestación de contenedores con Swarm \"),_c('a',{staticClass:\"header-anchor\",attrs:{\"href\":\"#orquestación-de-contenedores-con-swarm\"}},[_vm._v(\"¶\")])]),_c('p',[_vm._v(\"Docker Swarm proporciona una funcionalidad de agrupación nativa para contenedores Docker, que convierte un grupo de “Docker Engines” en un único “Docker engine” virtual. Swarm está integrado con Docker Engine. El cliente de docker swarm permite a los usuarios ejecutar contenedores Swarm, crear tokens, enumerar nodos en el clúster y más. También permite a los usuarios ejecutar varios comandos para administrar nodos en manada (Swarm). Docker maneja el swarm usando el algoritmo Raft. Según Raft, para que se realice una actualización, la mayoría de los nodos de Swarm deben estar de acuerdo con la actualización.\")]),_c('img',{staticClass:\"center iasc-image\",attrs:{\"src\":require(\"@/images/contenedores/swarm.png\")}})])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./contenedores.md?vue&type=template&id=c7d7bf74&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""} \ No newline at end of file diff --git a/js/chunk-vendors.03a78278.js b/js/chunk-vendors.03a78278.js new file mode 100644 index 0000000..6bc1b8d --- /dev/null +++ b/js/chunk-vendors.03a78278.js @@ -0,0 +1,27 @@ +(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-vendors"],{"00b4":function(e,t,n){"use strict";n("ac1f");var r=n("23e7"),i=n("861d"),o=function(){var e=!1,t=/[ac]/;return t.exec=function(){return e=!0,/./.exec.apply(this,arguments)},!0===t.test("abc")&&e}(),a=/./.test;r({target:"RegExp",proto:!0,forced:!o},{test:function(e){if("function"!==typeof this.exec)return a.call(this,e);var t=this.exec(e);if(null!==t&&!i(t))throw new Error("RegExp exec method returned something other than an Object or null");return!!t}})},"00ee":function(e,t,n){var r=n("b622"),i=r("toStringTag"),o={};o[i]="z",e.exports="[object z]"===String(o)},"0261":function(e,t,n){var r=n("23e7"),i=n("d039"),o=n("8eb5"),a=Math.abs,s=Math.exp,c=Math.E,u=i((function(){return-2e-17!=Math.sinh(-2e-17)}));r({target:"Math",stat:!0,forced:u},{sinh:function(e){return a(e=+e)<1?(o(e)-o(-e))/2:(s(e-1)-s(-e-1))*(c/2)}})},"0366":function(e,t,n){var r=n("1c0b");e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 0:return function(){return e.call(t)};case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,i){return e.call(t,n,r,i)}}return function(){return e.apply(t,arguments)}}},"0481":function(e,t,n){"use strict";var r=n("23e7"),i=n("a2bf"),o=n("7b0b"),a=n("50c4"),s=n("a691"),c=n("65f0");r({target:"Array",proto:!0},{flat:function(){var e=arguments.length?arguments[0]:void 0,t=o(this),n=a(t.length),r=c(t,0);return r.length=i(r,t,t,n,0,void 0===e?1:s(e)),r}})},"04d3":function(e,t,n){"use strict";var r=n("23e7"),i=n("857a"),o=n("af03");r({target:"String",proto:!0,forced:o("blink")},{blink:function(){return i(this,"blink","","")}})},"0538":function(e,t,n){"use strict";var r=n("1c0b"),i=n("861d"),o=[].slice,a={},s=function(e,t,n){if(!(t in a)){for(var r=[],i=0;i]*>)/g,s=/\$([$&'`]|\d{1,2})/g;e.exports=function(e,t,n,c,u,l){var f=n+e.length,d=c.length,p=s;return void 0!==u&&(u=r(u),p=a),o.call(l,p,(function(r,o){var a;switch(o.charAt(0)){case"$":return"$";case"&":return e;case"`":return t.slice(0,n);case"'":return t.slice(f);case"<":a=u[o.slice(1,-1)];break;default:var s=+o;if(0===s)return r;if(s>d){var l=i(s/10);return 0===l?r:l<=d?void 0===c[l-1]?o.charAt(1):c[l-1]+o.charAt(1):r}a=c[s-1]}return void 0===a?"":a}))}},"0ccb":function(e,t,n){var r=n("50c4"),i=n("1148"),o=n("1d80"),a=Math.ceil,s=function(e){return function(t,n,s){var c,u,l=String(o(t)),f=l.length,d=void 0===s?" ":String(s),p=r(n);return p<=f||""==d?l:(c=p-f,u=i.call(d,a(c/d.length)),u.length>c&&(u=u.slice(0,c)),e?l+u:u+l)}};e.exports={start:s(!1),end:s(!0)}},"0cdd":function(e,t){window.MutationObserver||(window.MutationObserver=function(e){function t(e){this.i=[],this.m=e}function n(e){(function n(){var r=e.takeRecords();r.length&&e.m(r,e),e.h=setTimeout(n,t._period)})()}function r(t){var n,r={type:null,target:null,addedNodes:[],removedNodes:[],previousSibling:null,nextSibling:null,attributeName:null,attributeNamespace:null,oldValue:null};for(n in t)r[n]!==e&&t[n]!==e&&(r[n]=t[n]);return r}function i(e,t){var n=u(e,t);return function(i){var o=i.length;if(t.a&&3===e.nodeType&&e.nodeValue!==n.a&&i.push(new r({type:"characterData",target:e,oldValue:n.a})),t.b&&n.b&&s(i,e,n.b,t.f),t.c||t.g)var a=c(i,e,n,t);(a||i.length!==o)&&(n=u(e,t))}}function o(e,t){return t.value}function a(e,t){return"style"!==t.name?t.value:e.style.cssText}function s(t,n,i,o){for(var a,s,c={},u=n.attributes,l=u.length;l--;)a=u[l],s=a.name,o&&o[s]===e||(v(n,a)!==i[s]&&t.push(r({type:"attributes",target:n,attributeName:s,oldValue:i[s],attributeNamespace:a.namespaceURI})),c[s]=!0);for(s in i)c[s]||t.push(r({target:n,type:"attributes",attributeName:s,oldValue:i[s]}))}function c(t,n,i,o){function a(e,n,i,a,u){var l,f,d,p=e.length-1;for(u=-~((p-u)/2);d=e.pop();)l=i[d.j],f=a[d.l],o.c&&u&&Math.abs(d.j-d.l)>=p&&(t.push(r({type:"childList",target:n,addedNodes:[l],removedNodes:[l],nextSibling:l.nextSibling,previousSibling:l.previousSibling})),u--),o.b&&f.b&&s(t,l,f.b,o.f),o.a&&3===l.nodeType&&l.nodeValue!==f.a&&t.push(r({type:"characterData",target:l,oldValue:f.a})),o.g&&c(l,f)}function c(n,i){for(var f,d,h,v,g,b=n.childNodes,m=i.c,y=b.length,w=m?m.length:0,_=0,x=0,E=0;x0;(o>>>=1)&&(t+=t))1&o&&(n+=t);return n}},1276:function(e,t,n){"use strict";var r=n("d784"),i=n("44e7"),o=n("825a"),a=n("1d80"),s=n("4840"),c=n("8aa5"),u=n("50c4"),l=n("14c3"),f=n("9263"),d=n("9f7f"),p=d.UNSUPPORTED_Y,h=[].push,v=Math.min,g=4294967295;r("split",2,(function(e,t,n){var r;return r="c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length?function(e,n){var r=String(a(this)),o=void 0===n?g:n>>>0;if(0===o)return[];if(void 0===e)return[r];if(!i(e))return t.call(r,e,o);var s,c,u,l=[],d=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),p=0,v=new RegExp(e.source,d+"g");while(s=f.call(v,r)){if(c=v.lastIndex,c>p&&(l.push(r.slice(p,s.index)),s.length>1&&s.index=o))break;v.lastIndex===s.index&&v.lastIndex++}return p===r.length?!u&&v.test("")||l.push(""):l.push(r.slice(p)),l.length>o?l.slice(0,o):l}:"0".split(void 0,0).length?function(e,n){return void 0===e&&0===n?[]:t.call(this,e,n)}:t,[function(t,n){var i=a(this),o=void 0==t?void 0:t[e];return void 0!==o?o.call(t,i,n):r.call(String(i),t,n)},function(e,i){var a=n(r,e,this,i,r!==t);if(a.done)return a.value;var f=o(e),d=String(this),h=s(f,RegExp),b=f.unicode,m=(f.ignoreCase?"i":"")+(f.multiline?"m":"")+(f.unicode?"u":"")+(p?"g":"y"),y=new h(p?"^(?:"+f.source+")":f,m),w=void 0===i?g:i>>>0;if(0===w)return[];if(0===d.length)return null===l(y,d)?[d]:[];var _=0,x=0,E=[];while(x79&&a<83;r({target:"Array",proto:!0,forced:!c||u},{reduce:function(e){return i(this,e,arguments.length,arguments.length>1?arguments[1]:void 0)}})},"143c":function(e,t,n){var r=n("74e8");r("Int32",(function(e){return function(t,n,r){return e(this,t,n,r)}}))},1448:function(e,t,n){var r=n("ebb5").aTypedArrayConstructor,i=n("4840");e.exports=function(e,t){var n=i(e,e.constructor),o=0,a=t.length,s=new(r(n))(a);while(a>o)s[o]=t[o++];return s}},"145e":function(e,t,n){"use strict";var r=n("7b0b"),i=n("23cb"),o=n("50c4"),a=Math.min;e.exports=[].copyWithin||function(e,t){var n=r(this),s=o(n.length),c=i(e,s),u=i(t,s),l=arguments.length>2?arguments[2]:void 0,f=a((void 0===l?s:i(l,s))-u,s-c),d=1;u0)u in n?n[c]=n[u]:delete n[c],c+=d,u+=d;return n}},"14c3":function(e,t,n){var r=n("c6b6"),i=n("9263");e.exports=function(e,t){var n=e.exec;if("function"===typeof n){var o=n.call(e,t);if("object"!==typeof o)throw TypeError("RegExp exec method returned something other than an Object or null");return o}if("RegExp"!==r(e))throw TypeError("RegExp#exec called on incompatible receiver");return i.call(e,t)}},"159b":function(e,t,n){var r=n("da84"),i=n("fdbc"),o=n("17c2"),a=n("9112");for(var s in i){var c=r[s],u=c&&c.prototype;if(u&&u.forEach!==o)try{a(u,"forEach",o)}catch(l){u.forEach=o}}},"170b":function(e,t,n){"use strict";var r=n("ebb5"),i=n("50c4"),o=n("23cb"),a=n("4840"),s=r.aTypedArray,c=r.exportTypedArrayMethod;c("subarray",(function(e,t){var n=s(this),r=n.length,c=o(e,r);return new(a(n,n.constructor))(n.buffer,n.byteOffset+c*n.BYTES_PER_ELEMENT,i((void 0===t?r:o(t,r))-c))}))},"17c2":function(e,t,n){"use strict";var r=n("b727").forEach,i=n("a640"),o=i("forEach");e.exports=o?[].forEach:function(e){return r(this,e,arguments.length>1?arguments[1]:void 0)}},"182d":function(e,t,n){var r=n("f8cd");e.exports=function(e,t){var n=r(e);if(n%t)throw RangeError("Wrong offset");return n}},"18a5":function(e,t,n){"use strict";var r=n("23e7"),i=n("857a"),o=n("af03");r({target:"String",proto:!0,forced:o("anchor")},{anchor:function(e){return i(this,"a","name",e)}})},1913:function(e,t,n){"use strict";var r=n("23e7"),i=n("857a"),o=n("af03");r({target:"String",proto:!0,forced:o("fontsize")},{fontsize:function(e){return i(this,"font","size",e)}})},"197b":function(e,t,n){var r=n("746f");r("species")},"19aa":function(e,t){e.exports=function(e,t,n){if(!(e instanceof t))throw TypeError("Incorrect "+(n?n+" ":"")+"invocation");return e}},"19dd":function(e,t,n){e.exports=n("e4cb")},"1be4":function(e,t,n){var r=n("d066");e.exports=r("document","documentElement")},"1bf2":function(e,t,n){var r=n("23e7"),i=n("56ef");r({target:"Reflect",stat:!0},{ownKeys:i})},"1c0b":function(e,t){e.exports=function(e){if("function"!=typeof e)throw TypeError(String(e)+" is not a function");return e}},"1c78":function(e,t,n){"use strict";n.r(t);var r={false:"push",true:"unshift"},i=Object.prototype.hasOwnProperty,o=function(e,t,n,r){var o=e,a=r;if(n&&i.call(t,o))throw Error("User defined id attribute '"+e+"' is NOT unique. Please fix it in your markdown to continue.");for(;i.call(t,o);)o=e+"-"+a++;return t[o]=!0,o},a=function e(t,n){n=Object.assign({},e.defaults,n),t.core.ruler.push("anchor",(function(e){var t,r={},i=e.tokens,a=Array.isArray(n.level)?(t=n.level,function(e){return t.includes(e)}):function(e){return function(t){return t>=e}}(n.level);i.filter((function(e){return"heading_open"===e.type})).filter((function(e){return a(Number(e.tag.substr(1)))})).forEach((function(t){var a=i[i.indexOf(t)+1].children.filter((function(e){return"text"===e.type||"code_inline"===e.type})).reduce((function(e,t){return e+t.content}),""),s=t.attrGet("id");s=null==s?o(n.slugify(a),r,!1,n.uniqueSlugStartIndex):o(s,r,!0,n.uniqueSlugStartIndex),t.attrSet("id",s),n.permalink&&n.renderPermalink(s,n,e,i.indexOf(t)),n.callback&&n.callback(t,{slug:s,title:a})}))}))};a.defaults={level:1,slugify:function(e){return encodeURIComponent(String(e).trim().toLowerCase().replace(/\s+/g,"-"))},uniqueSlugStartIndex:1,permalink:!1,renderPermalink:function(e,t,n,i){var o,a=[Object.assign(new n.Token("link_open","a",1),{attrs:[].concat(t.permalinkClass?[["class",t.permalinkClass]]:[],[["href",t.permalinkHref(e,n)]],Object.entries(t.permalinkAttrs(e,n)))}),Object.assign(new n.Token("html_block","",0),{content:t.permalinkSymbol}),new n.Token("link_close","a",-1)];t.permalinkSpace&&a[r[!t.permalinkBefore]](Object.assign(new n.Token("text","",0),{content:" "})),(o=n.tokens[i+1].children)[r[t.permalinkBefore]].apply(o,a)},permalinkClass:"header-anchor",permalinkSpace:!0,permalinkSymbol:"¶",permalinkBefore:!1,permalinkHref:function(e){return"#"+e},permalinkAttrs:function(e){return{}}},t["default"]=a},"1c7e":function(e,t,n){var r=n("b622"),i=r("iterator"),o=!1;try{var a=0,s={next:function(){return{done:!!a++}},return:function(){o=!0}};s[i]=function(){return this},Array.from(s,(function(){throw 2}))}catch(c){}e.exports=function(e,t){if(!t&&!o)return!1;var n=!1;try{var r={};r[i]=function(){return{next:function(){return{done:n=!0}}}},e(r)}catch(c){}return n}},"1cdc":function(e,t,n){var r=n("342f");e.exports=/(?:iphone|ipod|ipad).*applewebkit/i.test(r)},"1d1c":function(e,t,n){var r=n("23e7"),i=n("83ab"),o=n("37e8");r({target:"Object",stat:!0,forced:!i,sham:!i},{defineProperties:o})},"1d80":function(e,t){e.exports=function(e){if(void 0==e)throw TypeError("Can't call method on "+e);return e}},"1dde":function(e,t,n){var r=n("d039"),i=n("b622"),o=n("2d00"),a=i("species");e.exports=function(e){return o>=51||!r((function(){var t=[],n=t.constructor={};return n[a]=function(){return{foo:1}},1!==t[e](Boolean).foo}))}},"1e25":function(e,t,n){"use strict";var r=n("23e7"),i=n("58a8").end,o=n("c8d2"),a=o("trimEnd"),s=a?function(){return i(this)}:"".trimEnd;r({target:"String",proto:!0,forced:a},{trimEnd:s,trimRight:s})},"1ec1":function(e,t){var n=Math.log;e.exports=Math.log1p||function(e){return(e=+e)>-1e-8&&e<1e-8?e-e*e/2:n(1+e)}},"1fe2":function(e,t,n){"use strict";var r=n("6d61"),i=n("acac");r("WeakSet",(function(e){return function(){return e(this,arguments.length?arguments[0]:void 0)}}),i)},"201b":function(e,t,n){"use strict";e.exports=e=>{const t=e.match(/^[ \t]*(?=\S)/gm);if(!t)return e;const n=Math.min.apply(Math,t.map(e=>e.length)),r=new RegExp(`^[ \\t]{${n}}`,"gm");return n>0?e.replace(r,""):e}},"20bf":function(e,t,n){"use strict";var r=n("8aa7"),i=n("ebb5").exportTypedArrayStaticMethod,o=n("a078");i("from",o,r)},"219c":function(e,t,n){"use strict";var r=n("ebb5"),i=r.aTypedArray,o=r.exportTypedArrayMethod,a=[].sort;o("sort",(function(e){return a.call(i(this),e)}))},2266:function(e,t,n){var r=n("825a"),i=n("e95a"),o=n("50c4"),a=n("0366"),s=n("35a1"),c=n("2a62"),u=function(e,t){this.stopped=e,this.result=t};e.exports=function(e,t,n){var l,f,d,p,h,v,g,b=n&&n.that,m=!(!n||!n.AS_ENTRIES),y=!(!n||!n.IS_ITERATOR),w=!(!n||!n.INTERRUPTED),_=a(t,b,1+m+w),x=function(e){return l&&c(l),new u(!0,e)},E=function(e){return m?(r(e),w?_(e[0],e[1],x):_(e[0],e[1])):w?_(e,x):_(e)};if(y)l=e;else{if(f=s(e),"function"!=typeof f)throw TypeError("Target is not iterable");if(i(f)){for(d=0,p=o(e.length);p>d;d++)if(h=E(e[d]),h&&h instanceof u)return h;return new u(!1)}l=f.call(e)}v=l.next;while(!(g=v.call(l)).done){try{h=E(g.value)}catch(S){throw c(l),S}if("object"==typeof h&&h&&h instanceof u)return h}return new u(!1)}},2315:function(e,t,n){"use strict";var r=n("23e7"),i=n("857a"),o=n("af03");r({target:"String",proto:!0,forced:o("strike")},{strike:function(){return i(this,"strike","","")}})},2351:function(e,t,n){var r=n("746f");r("split")},"23cb":function(e,t,n){var r=n("a691"),i=Math.max,o=Math.min;e.exports=function(e,t){var n=r(e);return n<0?i(n+t,0):o(n,t)}},"23dc":function(e,t,n){var r=n("d44e");r(Math,"Math",!0)},"23e7":function(e,t,n){var r=n("da84"),i=n("06cf").f,o=n("9112"),a=n("6eeb"),s=n("ce4e"),c=n("e893"),u=n("94ca");e.exports=function(e,t){var n,l,f,d,p,h,v=e.target,g=e.global,b=e.stat;if(l=g?r:b?r[v]||s(v,{}):(r[v]||{}).prototype,l)for(f in t){if(p=t[f],e.noTargetGet?(h=i(l,f),d=h&&h.value):d=l[f],n=u(g?f:v+(b?".":"#")+f,e.forced),!n&&void 0!==d){if(typeof p===typeof d)continue;c(p,d)}(e.sham||d&&d.sham)&&o(p,"sham",!0),a(l,f,p,e)}}},"241c":function(e,t,n){var r=n("ca84"),i=n("7839"),o=i.concat("length","prototype");t.f=Object.getOwnPropertyNames||function(e){return r(e,o)}},2532:function(e,t,n){"use strict";var r=n("23e7"),i=n("5a34"),o=n("1d80"),a=n("ab13");r({target:"String",proto:!0,forced:!a("includes")},{includes:function(e){return!!~String(o(this)).indexOf(i(e),arguments.length>1?arguments[1]:void 0)}})},"25a1":function(e,t,n){"use strict";var r=n("ebb5"),i=n("d58f").right,o=r.aTypedArray,a=r.exportTypedArrayMethod;a("reduceRight",(function(e){return i(o(this),e,arguments.length,arguments.length>1?arguments[1]:void 0)}))},"25eb":function(e,t,n){var r=n("23e7"),i=n("c20d");r({target:"Number",stat:!0,forced:Number.parseInt!=i},{parseInt:i})},"25f0":function(e,t,n){"use strict";var r=n("6eeb"),i=n("825a"),o=n("d039"),a=n("ad6d"),s="toString",c=RegExp.prototype,u=c[s],l=o((function(){return"/a/b"!=u.call({source:"a",flags:"b"})})),f=u.name!=s;(l||f)&&r(RegExp.prototype,s,(function(){var e=i(this),t=String(e.source),n=e.flags,r=String(void 0===n&&e instanceof RegExp&&!("flags"in c)?a.call(e):n);return"/"+t+"/"+r}),{unsafe:!0})},2626:function(e,t,n){"use strict";var r=n("d066"),i=n("9bf2"),o=n("b622"),a=n("83ab"),s=o("species");e.exports=function(e){var t=r(e),n=i.f;a&&t&&!t[s]&&n(t,s,{configurable:!0,get:function(){return this}})}},"26e9":function(e,t,n){"use strict";var r=n("23e7"),i=n("e8b5"),o=[].reverse,a=[1,2];r({target:"Array",proto:!0,forced:String(a)===String(a.reverse())},{reverse:function(){return i(this)&&(this.length=this.length),o.call(this)}})},"277d":function(e,t,n){var r=n("23e7"),i=n("e8b5");r({target:"Array",stat:!0},{isArray:i})},2877:function(e,t,n){"use strict";function r(e,t,n,r,i,o,a,s){var c,u="function"===typeof e?e.options:e;if(t&&(u.render=t,u.staticRenderFns=n,u._compiled=!0),r&&(u.functional=!0),o&&(u._scopeId="data-v-"+o),a?(c=function(e){e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,e||"undefined"===typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),i&&i.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(a)},u._ssrRegister=c):i&&(c=s?function(){i.call(this,(u.functional?this.parent:this).$root.$options.shadowRoot)}:i),c)if(u.functional){u._injectStyles=c;var l=u.render;u.render=function(e,t){return c.call(t),l(e,t)}}else{var f=u.beforeCreate;u.beforeCreate=f?[].concat(f,c):[c]}return{exports:e,options:u}}n.d(t,"a",(function(){return r}))},2909:function(e,t,n){"use strict";function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);no)l[o]=n[o++];return l}),l)},"2a1b":function(e,t,n){var r=n("746f");r("match")},"2a62":function(e,t,n){var r=n("825a");e.exports=function(e){var t=e["return"];if(void 0!==t)return r(t.call(e)).value}},"2af1":function(e,t,n){var r=n("23e7"),i=n("f748");r({target:"Math",stat:!0},{sign:i})},"2b0e":function(e,t,n){"use strict";(function(e){ +/*! + * Vue.js v2.6.12 + * (c) 2014-2020 Evan You + * Released under the MIT License. + */ +var n=Object.freeze({});function r(e){return void 0===e||null===e}function i(e){return void 0!==e&&null!==e}function o(e){return!0===e}function a(e){return!1===e}function s(e){return"string"===typeof e||"number"===typeof e||"symbol"===typeof e||"boolean"===typeof e}function c(e){return null!==e&&"object"===typeof e}var u=Object.prototype.toString;function l(e){return"[object Object]"===u.call(e)}function f(e){return"[object RegExp]"===u.call(e)}function d(e){var t=parseFloat(String(e));return t>=0&&Math.floor(t)===t&&isFinite(e)}function p(e){return i(e)&&"function"===typeof e.then&&"function"===typeof e.catch}function h(e){return null==e?"":Array.isArray(e)||l(e)&&e.toString===u?JSON.stringify(e,null,2):String(e)}function v(e){var t=parseFloat(e);return isNaN(t)?e:t}function g(e,t){for(var n=Object.create(null),r=e.split(","),i=0;i-1)return e.splice(n,1)}}var y=Object.prototype.hasOwnProperty;function w(e,t){return y.call(e,t)}function _(e){var t=Object.create(null);return function(n){var r=t[n];return r||(t[n]=e(n))}}var x=/-(\w)/g,E=_((function(e){return e.replace(x,(function(e,t){return t?t.toUpperCase():""}))})),S=_((function(e){return e.charAt(0).toUpperCase()+e.slice(1)})),A=/\B([A-Z])/g,k=_((function(e){return e.replace(A,"-$1").toLowerCase()}));function O(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n}function C(e,t){return e.bind(t)}var M=Function.prototype.bind?C:O;function T(e,t){t=t||0;var n=e.length-t,r=new Array(n);while(n--)r[n]=e[n+t];return r}function R(e,t){for(var n in t)e[n]=t[n];return e}function I(e){for(var t={},n=0;n0,ne=Q&&Q.indexOf("edge/")>0,re=(Q&&Q.indexOf("android"),Q&&/iphone|ipad|ipod|ios/.test(Q)||"ios"===Z),ie=(Q&&/chrome\/\d+/.test(Q),Q&&/phantomjs/.test(Q),Q&&Q.match(/firefox\/(\d+)/)),oe={}.watch,ae=!1;if(X)try{var se={};Object.defineProperty(se,"passive",{get:function(){ae=!0}}),window.addEventListener("test-passive",null,se)}catch(Ea){}var ce=function(){return void 0===G&&(G=!X&&!Y&&"undefined"!==typeof e&&(e["process"]&&"server"===e["process"].env.VUE_ENV)),G},ue=X&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function le(e){return"function"===typeof e&&/native code/.test(e.toString())}var fe,de="undefined"!==typeof Symbol&&le(Symbol)&&"undefined"!==typeof Reflect&&le(Reflect.ownKeys);fe="undefined"!==typeof Set&&le(Set)?Set:function(){function e(){this.set=Object.create(null)}return e.prototype.has=function(e){return!0===this.set[e]},e.prototype.add=function(e){this.set[e]=!0},e.prototype.clear=function(){this.set=Object.create(null)},e}();var pe=N,he=0,ve=function(){this.id=he++,this.subs=[]};ve.prototype.addSub=function(e){this.subs.push(e)},ve.prototype.removeSub=function(e){m(this.subs,e)},ve.prototype.depend=function(){ve.target&&ve.target.addDep(this)},ve.prototype.notify=function(){var e=this.subs.slice();for(var t=0,n=e.length;t-1)if(o&&!w(i,"default"))a=!1;else if(""===a||a===k(e)){var c=et(String,i.type);(c<0||s0&&(a=Ot(a,(t||"")+"_"+n),kt(a[0])&&kt(u)&&(l[c]=xe(u.text+a[0].text),a.shift()),l.push.apply(l,a)):s(a)?kt(u)?l[c]=xe(u.text+a):""!==a&&l.push(xe(a)):kt(a)&&kt(u)?l[c]=xe(u.text+a.text):(o(e._isVList)&&i(a.tag)&&r(a.key)&&i(t)&&(a.key="__vlist"+t+"_"+n+"__"),l.push(a)));return l}function Ct(e){var t=e.$options.provide;t&&(e._provided="function"===typeof t?t.call(e):t)}function Mt(e){var t=Tt(e.$options.inject,e);t&&(Me(!1),Object.keys(t).forEach((function(n){je(e,n,t[n])})),Me(!0))}function Tt(e,t){if(e){for(var n=Object.create(null),r=de?Reflect.ownKeys(e):Object.keys(e),i=0;i0,a=e?!!e.$stable:!o,s=e&&e.$key;if(e){if(e._normalized)return e._normalized;if(a&&r&&r!==n&&s===r.$key&&!o&&!r.$hasNormal)return r;for(var c in i={},e)e[c]&&"$"!==c[0]&&(i[c]=jt(t,c,e[c]))}else i={};for(var u in t)u in i||(i[u]=Pt(t,u));return e&&Object.isExtensible(e)&&(e._normalized=i),W(i,"$stable",a),W(i,"$key",s),W(i,"$hasNormal",o),i}function jt(e,t,n){var r=function(){var e=arguments.length?n.apply(null,arguments):n({});return e=e&&"object"===typeof e&&!Array.isArray(e)?[e]:At(e),e&&(0===e.length||1===e.length&&e[0].isComment)?void 0:e};return n.proxy&&Object.defineProperty(e,t,{get:r,enumerable:!0,configurable:!0}),r}function Pt(e,t){return function(){return e[t]}}function Lt(e,t){var n,r,o,a,s;if(Array.isArray(e)||"string"===typeof e)for(n=new Array(e.length),r=0,o=e.length;r1?T(n):n;for(var r=T(arguments,1),i='event handler for "'+e+'"',o=0,a=n.length;odocument.createEvent("Event").timeStamp&&(Gn=function(){return Jn.now()})}function Xn(){var e,t;for(Kn=Gn(),qn=!0,Bn.sort((function(e,t){return e.id-t.id})),Wn=0;WnWn&&Bn[n].id>e.id)n--;Bn.splice(n+1,0,e)}else Bn.push(e);Hn||(Hn=!0,ht(Xn))}}var tr=0,nr=function(e,t,n,r,i){this.vm=e,i&&(e._watcher=this),e._watchers.push(this),r?(this.deep=!!r.deep,this.user=!!r.user,this.lazy=!!r.lazy,this.sync=!!r.sync,this.before=r.before):this.deep=this.user=this.lazy=this.sync=!1,this.cb=n,this.id=++tr,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=new fe,this.newDepIds=new fe,this.expression="","function"===typeof t?this.getter=t:(this.getter=K(t),this.getter||(this.getter=N)),this.value=this.lazy?void 0:this.get()};nr.prototype.get=function(){var e;be(this);var t=this.vm;try{e=this.getter.call(t,t)}catch(Ea){if(!this.user)throw Ea;tt(Ea,t,'getter for watcher "'+this.expression+'"')}finally{this.deep&>(e),me(),this.cleanupDeps()}return e},nr.prototype.addDep=function(e){var t=e.id;this.newDepIds.has(t)||(this.newDepIds.add(t),this.newDeps.push(e),this.depIds.has(t)||e.addSub(this))},nr.prototype.cleanupDeps=function(){var e=this.deps.length;while(e--){var t=this.deps[e];this.newDepIds.has(t.id)||t.removeSub(this)}var n=this.depIds;this.depIds=this.newDepIds,this.newDepIds=n,this.newDepIds.clear(),n=this.deps,this.deps=this.newDeps,this.newDeps=n,this.newDeps.length=0},nr.prototype.update=function(){this.lazy?this.dirty=!0:this.sync?this.run():er(this)},nr.prototype.run=function(){if(this.active){var e=this.get();if(e!==this.value||c(e)||this.deep){var t=this.value;if(this.value=e,this.user)try{this.cb.call(this.vm,e,t)}catch(Ea){tt(Ea,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,e,t)}}},nr.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},nr.prototype.depend=function(){var e=this.deps.length;while(e--)this.deps[e].depend()},nr.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||m(this.vm._watchers,this);var e=this.deps.length;while(e--)this.deps[e].removeSub(this);this.active=!1}};var rr={enumerable:!0,configurable:!0,get:N,set:N};function ir(e,t,n){rr.get=function(){return this[t][n]},rr.set=function(e){this[t][n]=e},Object.defineProperty(e,n,rr)}function or(e){e._watchers=[];var t=e.$options;t.props&&ar(e,t.props),t.methods&&hr(e,t.methods),t.data?sr(e):Ne(e._data={},!0),t.computed&&lr(e,t.computed),t.watch&&t.watch!==oe&&vr(e,t.watch)}function ar(e,t){var n=e.$options.propsData||{},r=e._props={},i=e.$options._propKeys=[],o=!e.$parent;o||Me(!1);var a=function(o){i.push(o);var a=Xe(o,t,n,e);je(r,o,a),o in e||ir(e,"_props",o)};for(var s in t)a(s);Me(!0)}function sr(e){var t=e.$options.data;t=e._data="function"===typeof t?cr(t,e):t||{},l(t)||(t={});var n=Object.keys(t),r=e.$options.props,i=(e.$options.methods,n.length);while(i--){var o=n[i];0,r&&w(r,o)||q(o)||ir(e,"_data",o)}Ne(t,!0)}function cr(e,t){be();try{return e.call(t,t)}catch(Ea){return tt(Ea,t,"data()"),{}}finally{me()}}var ur={lazy:!0};function lr(e,t){var n=e._computedWatchers=Object.create(null),r=ce();for(var i in t){var o=t[i],a="function"===typeof o?o:o.get;0,r||(n[i]=new nr(e,a||N,N,ur)),i in e||fr(e,i,o)}}function fr(e,t,n){var r=!ce();"function"===typeof n?(rr.get=r?dr(t):pr(n),rr.set=N):(rr.get=n.get?r&&!1!==n.cache?dr(t):pr(n.get):N,rr.set=n.set||N),Object.defineProperty(e,t,rr)}function dr(e){return function(){var t=this._computedWatchers&&this._computedWatchers[e];if(t)return t.dirty&&t.evaluate(),ve.target&&t.depend(),t.value}}function pr(e){return function(){return e.call(this,this)}}function hr(e,t){e.$options.props;for(var n in t)e[n]="function"!==typeof t[n]?N:M(t[n],e)}function vr(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var i=0;i-1)return this;var n=T(arguments,1);return n.unshift(this),"function"===typeof e.install?e.install.apply(e,n):"function"===typeof e&&e.apply(null,n),t.push(e),this}}function Ar(e){e.mixin=function(e){return this.options=Ge(this.options,e),this}}function kr(e){e.cid=0;var t=1;e.extend=function(e){e=e||{};var n=this,r=n.cid,i=e._Ctor||(e._Ctor={});if(i[r])return i[r];var o=e.name||n.options.name;var a=function(e){this._init(e)};return a.prototype=Object.create(n.prototype),a.prototype.constructor=a,a.cid=t++,a.options=Ge(n.options,e),a["super"]=n,a.options.props&&Or(a),a.options.computed&&Cr(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,B.forEach((function(e){a[e]=n[e]})),o&&(a.options.components[o]=a),a.superOptions=n.options,a.extendOptions=e,a.sealedOptions=R({},a.options),i[r]=a,a}}function Or(e){var t=e.options.props;for(var n in t)ir(e.prototype,"_props",n)}function Cr(e){var t=e.options.computed;for(var n in t)fr(e.prototype,n,t[n])}function Mr(e){B.forEach((function(t){e[t]=function(e,n){return n?("component"===t&&l(n)&&(n.name=n.name||e,n=this.options._base.extend(n)),"directive"===t&&"function"===typeof n&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}}))}function Tr(e){return e&&(e.Ctor.options.name||e.tag)}function Rr(e,t){return Array.isArray(e)?e.indexOf(t)>-1:"string"===typeof e?e.split(",").indexOf(t)>-1:!!f(e)&&e.test(t)}function Ir(e,t){var n=e.cache,r=e.keys,i=e._vnode;for(var o in n){var a=n[o];if(a){var s=Tr(a.componentOptions);s&&!t(s)&&Nr(n,o,r,i)}}}function Nr(e,t,n,r){var i=e[t];!i||r&&i.tag===r.tag||i.componentInstance.$destroy(),e[t]=null,m(n,t)}yr(Er),br(Er),Mn(Er),Nn(Er),mn(Er);var jr=[String,RegExp,Array],Pr={name:"keep-alive",abstract:!0,props:{include:jr,exclude:jr,max:[String,Number]},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var e in this.cache)Nr(this.cache,e,this.keys)},mounted:function(){var e=this;this.$watch("include",(function(t){Ir(e,(function(e){return Rr(t,e)}))})),this.$watch("exclude",(function(t){Ir(e,(function(e){return!Rr(t,e)}))}))},render:function(){var e=this.$slots.default,t=En(e),n=t&&t.componentOptions;if(n){var r=Tr(n),i=this,o=i.include,a=i.exclude;if(o&&(!r||!Rr(o,r))||a&&r&&Rr(a,r))return t;var s=this,c=s.cache,u=s.keys,l=null==t.key?n.Ctor.cid+(n.tag?"::"+n.tag:""):t.key;c[l]?(t.componentInstance=c[l].componentInstance,m(u,l),u.push(l)):(c[l]=t,u.push(l),this.max&&u.length>parseInt(this.max)&&Nr(c,u[0],u,this._vnode)),t.data.keepAlive=!0}return t||e&&e[0]}},Lr={KeepAlive:Pr};function $r(e){var t={get:function(){return z}};Object.defineProperty(e,"config",t),e.util={warn:pe,extend:R,mergeOptions:Ge,defineReactive:je},e.set=Pe,e.delete=Le,e.nextTick=ht,e.observable=function(e){return Ne(e),e},e.options=Object.create(null),B.forEach((function(t){e.options[t+"s"]=Object.create(null)})),e.options._base=e,R(e.options.components,Lr),Sr(e),Ar(e),kr(e),Mr(e)}$r(Er),Object.defineProperty(Er.prototype,"$isServer",{get:ce}),Object.defineProperty(Er.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(Er,"FunctionalRenderContext",{value:Yt}),Er.version="2.6.12";var Dr=g("style,class"),Fr=g("input,textarea,option,select,progress"),Br=function(e,t,n){return"value"===n&&Fr(e)&&"button"!==t||"selected"===n&&"option"===e||"checked"===n&&"input"===e||"muted"===n&&"video"===e},Ur=g("contenteditable,draggable,spellcheck"),zr=g("events,caret,typing,plaintext-only"),Hr=function(e,t){return Gr(t)||"false"===t?"false":"contenteditable"===e&&zr(t)?t:"true"},qr=g("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),Wr="http://www.w3.org/1999/xlink",Vr=function(e){return":"===e.charAt(5)&&"xlink"===e.slice(0,5)},Kr=function(e){return Vr(e)?e.slice(6,e.length):""},Gr=function(e){return null==e||!1===e};function Jr(e){var t=e.data,n=e,r=e;while(i(r.componentInstance))r=r.componentInstance._vnode,r&&r.data&&(t=Xr(r.data,t));while(i(n=n.parent))n&&n.data&&(t=Xr(t,n.data));return Yr(t.staticClass,t.class)}function Xr(e,t){return{staticClass:Zr(e.staticClass,t.staticClass),class:i(e.class)?[e.class,t.class]:t.class}}function Yr(e,t){return i(e)||i(t)?Zr(e,Qr(t)):""}function Zr(e,t){return e?t?e+" "+t:e:t||""}function Qr(e){return Array.isArray(e)?ei(e):c(e)?ti(e):"string"===typeof e?e:""}function ei(e){for(var t,n="",r=0,o=e.length;r-1?si[e]=t.constructor===window.HTMLUnknownElement||t.constructor===window.HTMLElement:si[e]=/HTMLUnknownElement/.test(t.toString())}var ui=g("text,number,password,search,email,tel,url");function li(e){if("string"===typeof e){var t=document.querySelector(e);return t||document.createElement("div")}return e}function fi(e,t){var n=document.createElement(e);return"select"!==e||t.data&&t.data.attrs&&void 0!==t.data.attrs.multiple&&n.setAttribute("multiple","multiple"),n}function di(e,t){return document.createElementNS(ni[e],t)}function pi(e){return document.createTextNode(e)}function hi(e){return document.createComment(e)}function vi(e,t,n){e.insertBefore(t,n)}function gi(e,t){e.removeChild(t)}function bi(e,t){e.appendChild(t)}function mi(e){return e.parentNode}function yi(e){return e.nextSibling}function wi(e){return e.tagName}function _i(e,t){e.textContent=t}function xi(e,t){e.setAttribute(t,"")}var Ei=Object.freeze({createElement:fi,createElementNS:di,createTextNode:pi,createComment:hi,insertBefore:vi,removeChild:gi,appendChild:bi,parentNode:mi,nextSibling:yi,tagName:wi,setTextContent:_i,setStyleScope:xi}),Si={create:function(e,t){Ai(t)},update:function(e,t){e.data.ref!==t.data.ref&&(Ai(e,!0),Ai(t))},destroy:function(e){Ai(e,!0)}};function Ai(e,t){var n=e.data.ref;if(i(n)){var r=e.context,o=e.componentInstance||e.elm,a=r.$refs;t?Array.isArray(a[n])?m(a[n],o):a[n]===o&&(a[n]=void 0):e.data.refInFor?Array.isArray(a[n])?a[n].indexOf(o)<0&&a[n].push(o):a[n]=[o]:a[n]=o}}var ki=new ye("",{},[]),Oi=["create","activate","update","remove","destroy"];function Ci(e,t){return e.key===t.key&&(e.tag===t.tag&&e.isComment===t.isComment&&i(e.data)===i(t.data)&&Mi(e,t)||o(e.isAsyncPlaceholder)&&e.asyncFactory===t.asyncFactory&&r(t.asyncFactory.error))}function Mi(e,t){if("input"!==e.tag)return!0;var n,r=i(n=e.data)&&i(n=n.attrs)&&n.type,o=i(n=t.data)&&i(n=n.attrs)&&n.type;return r===o||ui(r)&&ui(o)}function Ti(e,t,n){var r,o,a={};for(r=t;r<=n;++r)o=e[r].key,i(o)&&(a[o]=r);return a}function Ri(e){var t,n,a={},c=e.modules,u=e.nodeOps;for(t=0;tv?(f=r(n[m+1])?null:n[m+1].elm,E(e,f,n,h,m,o)):h>m&&A(t,d,v)}function C(e,t,n,r){for(var o=n;o-1?zi(e,t,n):qr(t)?Gr(n)?e.removeAttribute(t):(n="allowfullscreen"===t&&"EMBED"===e.tagName?"true":t,e.setAttribute(t,n)):Ur(t)?e.setAttribute(t,Hr(t,n)):Vr(t)?Gr(n)?e.removeAttributeNS(Wr,Kr(t)):e.setAttributeNS(Wr,t,n):zi(e,t,n)}function zi(e,t,n){if(Gr(n))e.removeAttribute(t);else{if(ee&&!te&&"TEXTAREA"===e.tagName&&"placeholder"===t&&""!==n&&!e.__ieph){var r=function(t){t.stopImmediatePropagation(),e.removeEventListener("input",r)};e.addEventListener("input",r),e.__ieph=!0}e.setAttribute(t,n)}}var Hi={create:Bi,update:Bi};function qi(e,t){var n=t.elm,o=t.data,a=e.data;if(!(r(o.staticClass)&&r(o.class)&&(r(a)||r(a.staticClass)&&r(a.class)))){var s=Jr(t),c=n._transitionClasses;i(c)&&(s=Zr(s,Qr(c))),s!==n._prevClass&&(n.setAttribute("class",s),n._prevClass=s)}}var Wi,Vi={create:qi,update:qi},Ki="__r",Gi="__c";function Ji(e){if(i(e[Ki])){var t=ee?"change":"input";e[t]=[].concat(e[Ki],e[t]||[]),delete e[Ki]}i(e[Gi])&&(e.change=[].concat(e[Gi],e.change||[]),delete e[Gi])}function Xi(e,t,n){var r=Wi;return function i(){var o=t.apply(null,arguments);null!==o&&Qi(e,i,n,r)}}var Yi=at&&!(ie&&Number(ie[1])<=53);function Zi(e,t,n,r){if(Yi){var i=Kn,o=t;t=o._wrapper=function(e){if(e.target===e.currentTarget||e.timeStamp>=i||e.timeStamp<=0||e.target.ownerDocument!==document)return o.apply(this,arguments)}}Wi.addEventListener(e,t,ae?{capture:n,passive:r}:n)}function Qi(e,t,n,r){(r||Wi).removeEventListener(e,t._wrapper||t,n)}function eo(e,t){if(!r(e.data.on)||!r(t.data.on)){var n=t.data.on||{},i=e.data.on||{};Wi=t.elm,Ji(n),wt(n,i,Zi,Qi,Xi,t.context),Wi=void 0}}var to,no={create:eo,update:eo};function ro(e,t){if(!r(e.data.domProps)||!r(t.data.domProps)){var n,o,a=t.elm,s=e.data.domProps||{},c=t.data.domProps||{};for(n in i(c.__ob__)&&(c=t.data.domProps=R({},c)),s)n in c||(a[n]="");for(n in c){if(o=c[n],"textContent"===n||"innerHTML"===n){if(t.children&&(t.children.length=0),o===s[n])continue;1===a.childNodes.length&&a.removeChild(a.childNodes[0])}if("value"===n&&"PROGRESS"!==a.tagName){a._value=o;var u=r(o)?"":String(o);io(a,u)&&(a.value=u)}else if("innerHTML"===n&&ii(a.tagName)&&r(a.innerHTML)){to=to||document.createElement("div"),to.innerHTML=""+o+"";var l=to.firstChild;while(a.firstChild)a.removeChild(a.firstChild);while(l.firstChild)a.appendChild(l.firstChild)}else if(o!==s[n])try{a[n]=o}catch(Ea){}}}}function io(e,t){return!e.composing&&("OPTION"===e.tagName||oo(e,t)||ao(e,t))}function oo(e,t){var n=!0;try{n=document.activeElement!==e}catch(Ea){}return n&&e.value!==t}function ao(e,t){var n=e.value,r=e._vModifiers;if(i(r)){if(r.number)return v(n)!==v(t);if(r.trim)return n.trim()!==t.trim()}return n!==t}var so={create:ro,update:ro},co=_((function(e){var t={},n=/;(?![^(]*\))/g,r=/:(.+)/;return e.split(n).forEach((function(e){if(e){var n=e.split(r);n.length>1&&(t[n[0].trim()]=n[1].trim())}})),t}));function uo(e){var t=lo(e.style);return e.staticStyle?R(e.staticStyle,t):t}function lo(e){return Array.isArray(e)?I(e):"string"===typeof e?co(e):e}function fo(e,t){var n,r={};if(t){var i=e;while(i.componentInstance)i=i.componentInstance._vnode,i&&i.data&&(n=uo(i.data))&&R(r,n)}(n=uo(e.data))&&R(r,n);var o=e;while(o=o.parent)o.data&&(n=uo(o.data))&&R(r,n);return r}var po,ho=/^--/,vo=/\s*!important$/,go=function(e,t,n){if(ho.test(t))e.style.setProperty(t,n);else if(vo.test(n))e.style.setProperty(k(t),n.replace(vo,""),"important");else{var r=mo(t);if(Array.isArray(n))for(var i=0,o=n.length;i-1?t.split(_o).forEach((function(t){return e.classList.add(t)})):e.classList.add(t);else{var n=" "+(e.getAttribute("class")||"")+" ";n.indexOf(" "+t+" ")<0&&e.setAttribute("class",(n+t).trim())}}function Eo(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(_o).forEach((function(t){return e.classList.remove(t)})):e.classList.remove(t),e.classList.length||e.removeAttribute("class");else{var n=" "+(e.getAttribute("class")||"")+" ",r=" "+t+" ";while(n.indexOf(r)>=0)n=n.replace(r," ");n=n.trim(),n?e.setAttribute("class",n):e.removeAttribute("class")}}function So(e){if(e){if("object"===typeof e){var t={};return!1!==e.css&&R(t,Ao(e.name||"v")),R(t,e),t}return"string"===typeof e?Ao(e):void 0}}var Ao=_((function(e){return{enterClass:e+"-enter",enterToClass:e+"-enter-to",enterActiveClass:e+"-enter-active",leaveClass:e+"-leave",leaveToClass:e+"-leave-to",leaveActiveClass:e+"-leave-active"}})),ko=X&&!te,Oo="transition",Co="animation",Mo="transition",To="transitionend",Ro="animation",Io="animationend";ko&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(Mo="WebkitTransition",To="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(Ro="WebkitAnimation",Io="webkitAnimationEnd"));var No=X?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(e){return e()};function jo(e){No((function(){No(e)}))}function Po(e,t){var n=e._transitionClasses||(e._transitionClasses=[]);n.indexOf(t)<0&&(n.push(t),xo(e,t))}function Lo(e,t){e._transitionClasses&&m(e._transitionClasses,t),Eo(e,t)}function $o(e,t,n){var r=Fo(e,t),i=r.type,o=r.timeout,a=r.propCount;if(!i)return n();var s=i===Oo?To:Io,c=0,u=function(){e.removeEventListener(s,l),n()},l=function(t){t.target===e&&++c>=a&&u()};setTimeout((function(){c0&&(n=Oo,l=a,f=o.length):t===Co?u>0&&(n=Co,l=u,f=c.length):(l=Math.max(a,u),n=l>0?a>u?Oo:Co:null,f=n?n===Oo?o.length:c.length:0);var d=n===Oo&&Do.test(r[Mo+"Property"]);return{type:n,timeout:l,propCount:f,hasTransform:d}}function Bo(e,t){while(e.length1}function Vo(e,t){!0!==t.data.show&&zo(t)}var Ko=X?{create:Vo,activate:Vo,remove:function(e,t){!0!==e.data.show?Ho(e,t):t()}}:{},Go=[Hi,Vi,no,so,wo,Ko],Jo=Go.concat(Fi),Xo=Ri({nodeOps:Ei,modules:Jo});te&&document.addEventListener("selectionchange",(function(){var e=document.activeElement;e&&e.vmodel&&ia(e,"input")}));var Yo={inserted:function(e,t,n,r){"select"===n.tag?(r.elm&&!r.elm._vOptions?_t(n,"postpatch",(function(){Yo.componentUpdated(e,t,n)})):Zo(e,t,n.context),e._vOptions=[].map.call(e.options,ta)):("textarea"===n.tag||ui(e.type))&&(e._vModifiers=t.modifiers,t.modifiers.lazy||(e.addEventListener("compositionstart",na),e.addEventListener("compositionend",ra),e.addEventListener("change",ra),te&&(e.vmodel=!0)))},componentUpdated:function(e,t,n){if("select"===n.tag){Zo(e,t,n.context);var r=e._vOptions,i=e._vOptions=[].map.call(e.options,ta);if(i.some((function(e,t){return!L(e,r[t])}))){var o=e.multiple?t.value.some((function(e){return ea(e,i)})):t.value!==t.oldValue&&ea(t.value,i);o&&ia(e,"change")}}}};function Zo(e,t,n){Qo(e,t,n),(ee||ne)&&setTimeout((function(){Qo(e,t,n)}),0)}function Qo(e,t,n){var r=t.value,i=e.multiple;if(!i||Array.isArray(r)){for(var o,a,s=0,c=e.options.length;s-1,a.selected!==o&&(a.selected=o);else if(L(ta(a),r))return void(e.selectedIndex!==s&&(e.selectedIndex=s));i||(e.selectedIndex=-1)}}function ea(e,t){return t.every((function(t){return!L(t,e)}))}function ta(e){return"_value"in e?e._value:e.value}function na(e){e.target.composing=!0}function ra(e){e.target.composing&&(e.target.composing=!1,ia(e.target,"input"))}function ia(e,t){var n=document.createEvent("HTMLEvents");n.initEvent(t,!0,!0),e.dispatchEvent(n)}function oa(e){return!e.componentInstance||e.data&&e.data.transition?e:oa(e.componentInstance._vnode)}var aa={bind:function(e,t,n){var r=t.value;n=oa(n);var i=n.data&&n.data.transition,o=e.__vOriginalDisplay="none"===e.style.display?"":e.style.display;r&&i?(n.data.show=!0,zo(n,(function(){e.style.display=o}))):e.style.display=r?o:"none"},update:function(e,t,n){var r=t.value,i=t.oldValue;if(!r!==!i){n=oa(n);var o=n.data&&n.data.transition;o?(n.data.show=!0,r?zo(n,(function(){e.style.display=e.__vOriginalDisplay})):Ho(n,(function(){e.style.display="none"}))):e.style.display=r?e.__vOriginalDisplay:"none"}},unbind:function(e,t,n,r,i){i||(e.style.display=e.__vOriginalDisplay)}},sa={model:Yo,show:aa},ca={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function ua(e){var t=e&&e.componentOptions;return t&&t.Ctor.options.abstract?ua(En(t.children)):e}function la(e){var t={},n=e.$options;for(var r in n.propsData)t[r]=e[r];var i=n._parentListeners;for(var o in i)t[E(o)]=i[o];return t}function fa(e,t){if(/\d-keep-alive$/.test(t.tag))return e("keep-alive",{props:t.componentOptions.propsData})}function da(e){while(e=e.parent)if(e.data.transition)return!0}function pa(e,t){return t.key===e.key&&t.tag===e.tag}var ha=function(e){return e.tag||xn(e)},va=function(e){return"show"===e.name},ga={name:"transition",props:ca,abstract:!0,render:function(e){var t=this,n=this.$slots.default;if(n&&(n=n.filter(ha),n.length)){0;var r=this.mode;0;var i=n[0];if(da(this.$vnode))return i;var o=ua(i);if(!o)return i;if(this._leaving)return fa(e,i);var a="__transition-"+this._uid+"-";o.key=null==o.key?o.isComment?a+"comment":a+o.tag:s(o.key)?0===String(o.key).indexOf(a)?o.key:a+o.key:o.key;var c=(o.data||(o.data={})).transition=la(this),u=this._vnode,l=ua(u);if(o.data.directives&&o.data.directives.some(va)&&(o.data.show=!0),l&&l.data&&!pa(o,l)&&!xn(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=R({},c);if("out-in"===r)return this._leaving=!0,_t(f,"afterLeave",(function(){t._leaving=!1,t.$forceUpdate()})),fa(e,i);if("in-out"===r){if(xn(o))return u;var d,p=function(){d()};_t(c,"afterEnter",p),_t(c,"enterCancelled",p),_t(f,"delayLeave",(function(e){d=e}))}}return i}}},ba=R({tag:String,moveClass:String},ca);delete ba.mode;var ma={props:ba,beforeMount:function(){var e=this,t=this._update;this._update=function(n,r){var i=Rn(e);e.__patch__(e._vnode,e.kept,!1,!0),e._vnode=e.kept,i(),t.call(e,n,r)}},render:function(e){for(var t=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,i=this.$slots.default||[],o=this.children=[],a=la(this),s=0;s4)return e;for(n=[],r=0;r1&&"0"==i.charAt(0)&&(o=N.test(i)?16:8,i=i.slice(8==o?1:2)),""===i)a=0;else{if(!(10==o?P:8==o?j:L).test(i))return e;a=parseInt(i,o)}n.push(a)}for(r=0;r=A(256,5-t))return null}else if(a>255)return null;for(s=n.pop(),r=0;r6)return;r=0;while(d()){if(i=null,r>0){if(!("."==d()&&r<4))return;f++}if(!I.test(d()))return;while(I.test(d())){if(o=parseInt(d(),10),null===i)i=o;else{if(0==i)return;i=10*i+o}if(i>255)return;f++}c[u]=256*c[u]+i,r++,2!=r&&4!=r||u++}if(4!=r)return;break}if(":"==d()){if(f++,!d())return}else if(d())return;c[u++]=t}else{if(null!==l)return;f++,u++,l=u}}if(null!==l){a=u-l,u=7;while(0!=u&&a>0)s=c[u],c[u--]=c[l+a-1],c[l+--a]=s}else if(8!=u)return;return c},q=function(e){for(var t=null,n=1,r=null,i=0,o=0;o<8;o++)0!==e[o]?(i>n&&(t=r,n=i),r=null,i=0):(null===r&&(r=o),++i);return i>n&&(t=r,n=i),t},W=function(e){var t,n,r,i;if("number"==typeof e){for(t=[],n=0;n<4;n++)t.unshift(e%256),e=S(e/256);return t.join(".")}if("object"==typeof e){for(t="",r=q(e),n=0;n<8;n++)i&&0===e[n]||(i&&(i=!1),r===n?(t+=n?":":"::",i=!0):(t+=e[n].toString(16),n<7&&(t+=":")));return"["+t+"]"}return e},V={},K=d({},V,{" ":1,'"':1,"<":1,">":1,"`":1}),G=d({},K,{"#":1,"?":1,"{":1,"}":1}),J=d({},G,{"/":1,":":1,";":1,"=":1,"@":1,"[":1,"\\":1,"]":1,"^":1,"|":1}),X=function(e,t){var n=h(e,0);return n>32&&n<127&&!f(t,e)?e:encodeURIComponent(e)},Y={ftp:21,file:null,http:80,https:443,ws:80,wss:443},Z=function(e){return f(Y,e.scheme)},Q=function(e){return""!=e.username||""!=e.password},ee=function(e){return!e.host||e.cannotBeABaseURL||"file"==e.scheme},te=function(e,t){var n;return 2==e.length&&T.test(e.charAt(0))&&(":"==(n=e.charAt(1))||!t&&"|"==n)},ne=function(e){var t;return e.length>1&&te(e.slice(0,2))&&(2==e.length||"/"===(t=e.charAt(2))||"\\"===t||"?"===t||"#"===t)},re=function(e){var t=e.path,n=t.length;!n||"file"==e.scheme&&1==n&&te(t[0],!0)||t.pop()},ie=function(e){return"."===e||"%2e"===e.toLowerCase()},oe=function(e){return e=e.toLowerCase(),".."===e||"%2e."===e||".%2e"===e||"%2e%2e"===e},ae={},se={},ce={},ue={},le={},fe={},de={},pe={},he={},ve={},ge={},be={},me={},ye={},we={},_e={},xe={},Ee={},Se={},Ae={},ke={},Oe=function(e,t,n,i){var o,a,s,c,u=n||ae,l=0,d="",h=!1,v=!1,g=!1;n||(e.scheme="",e.username="",e.password="",e.host=null,e.port=null,e.path=[],e.query=null,e.fragment=null,e.cannotBeABaseURL=!1,t=t.replace(F,"")),t=t.replace(B,""),o=p(t);while(l<=o.length){switch(a=o[l],u){case ae:if(!a||!T.test(a)){if(n)return O;u=ce;continue}d+=a.toLowerCase(),u=se;break;case se:if(a&&(R.test(a)||"+"==a||"-"==a||"."==a))d+=a.toLowerCase();else{if(":"!=a){if(n)return O;d="",u=ce,l=0;continue}if(n&&(Z(e)!=f(Y,d)||"file"==d&&(Q(e)||null!==e.port)||"file"==e.scheme&&!e.host))return;if(e.scheme=d,n)return void(Z(e)&&Y[e.scheme]==e.port&&(e.port=null));d="","file"==e.scheme?u=ye:Z(e)&&i&&i.scheme==e.scheme?u=ue:Z(e)?u=pe:"/"==o[l+1]?(u=le,l++):(e.cannotBeABaseURL=!0,e.path.push(""),u=Se)}break;case ce:if(!i||i.cannotBeABaseURL&&"#"!=a)return O;if(i.cannotBeABaseURL&&"#"==a){e.scheme=i.scheme,e.path=i.path.slice(),e.query=i.query,e.fragment="",e.cannotBeABaseURL=!0,u=ke;break}u="file"==i.scheme?ye:fe;continue;case ue:if("/"!=a||"/"!=o[l+1]){u=fe;continue}u=he,l++;break;case le:if("/"==a){u=ve;break}u=Ee;continue;case fe:if(e.scheme=i.scheme,a==r)e.username=i.username,e.password=i.password,e.host=i.host,e.port=i.port,e.path=i.path.slice(),e.query=i.query;else if("/"==a||"\\"==a&&Z(e))u=de;else if("?"==a)e.username=i.username,e.password=i.password,e.host=i.host,e.port=i.port,e.path=i.path.slice(),e.query="",u=Ae;else{if("#"!=a){e.username=i.username,e.password=i.password,e.host=i.host,e.port=i.port,e.path=i.path.slice(),e.path.pop(),u=Ee;continue}e.username=i.username,e.password=i.password,e.host=i.host,e.port=i.port,e.path=i.path.slice(),e.query=i.query,e.fragment="",u=ke}break;case de:if(!Z(e)||"/"!=a&&"\\"!=a){if("/"!=a){e.username=i.username,e.password=i.password,e.host=i.host,e.port=i.port,u=Ee;continue}u=ve}else u=he;break;case pe:if(u=he,"/"!=a||"/"!=d.charAt(l+1))continue;l++;break;case he:if("/"!=a&&"\\"!=a){u=ve;continue}break;case ve:if("@"==a){h&&(d="%40"+d),h=!0,s=p(d);for(var b=0;b65535)return M;e.port=Z(e)&&w===Y[e.scheme]?null:w,d=""}if(n)return;u=xe;continue}return M}d+=a;break;case ye:if(e.scheme="file","/"==a||"\\"==a)u=we;else{if(!i||"file"!=i.scheme){u=Ee;continue}if(a==r)e.host=i.host,e.path=i.path.slice(),e.query=i.query;else if("?"==a)e.host=i.host,e.path=i.path.slice(),e.query="",u=Ae;else{if("#"!=a){ne(o.slice(l).join(""))||(e.host=i.host,e.path=i.path.slice(),re(e)),u=Ee;continue}e.host=i.host,e.path=i.path.slice(),e.query=i.query,e.fragment="",u=ke}}break;case we:if("/"==a||"\\"==a){u=_e;break}i&&"file"==i.scheme&&!ne(o.slice(l).join(""))&&(te(i.path[0],!0)?e.path.push(i.path[0]):e.host=i.host),u=Ee;continue;case _e:if(a==r||"/"==a||"\\"==a||"?"==a||"#"==a){if(!n&&te(d))u=Ee;else if(""==d){if(e.host="",n)return;u=xe}else{if(c=U(e,d),c)return c;if("localhost"==e.host&&(e.host=""),n)return;d="",u=xe}continue}d+=a;break;case xe:if(Z(e)){if(u=Ee,"/"!=a&&"\\"!=a)continue}else if(n||"?"!=a)if(n||"#"!=a){if(a!=r&&(u=Ee,"/"!=a))continue}else e.fragment="",u=ke;else e.query="",u=Ae;break;case Ee:if(a==r||"/"==a||"\\"==a&&Z(e)||!n&&("?"==a||"#"==a)){if(oe(d)?(re(e),"/"==a||"\\"==a&&Z(e)||e.path.push("")):ie(d)?"/"==a||"\\"==a&&Z(e)||e.path.push(""):("file"==e.scheme&&!e.path.length&&te(d)&&(e.host&&(e.host=""),d=d.charAt(0)+":"),e.path.push(d)),d="","file"==e.scheme&&(a==r||"?"==a||"#"==a))while(e.path.length>1&&""===e.path[0])e.path.shift();"?"==a?(e.query="",u=Ae):"#"==a&&(e.fragment="",u=ke)}else d+=X(a,G);break;case Se:"?"==a?(e.query="",u=Ae):"#"==a?(e.fragment="",u=ke):a!=r&&(e.path[0]+=X(a,V));break;case Ae:n||"#"!=a?a!=r&&("'"==a&&Z(e)?e.query+="%27":e.query+="#"==a?"%23":X(a,V)):(e.fragment="",u=ke);break;case ke:a!=r&&(e.fragment+=X(a,K));break}l++}},Ce=function(e){var t,n,r=l(this,Ce,"URL"),i=arguments.length>1?arguments[1]:void 0,a=String(e),s=x(r,{type:"URL"});if(void 0!==i)if(i instanceof Ce)t=E(i);else if(n=Oe(t={},String(i)),n)throw TypeError(n);if(n=Oe(s,a,null,t),n)throw TypeError(n);var c=s.searchParams=new w,u=_(c);u.updateSearchParams(s.query),u.updateURL=function(){s.query=String(c)||null},o||(r.href=Te.call(r),r.origin=Re.call(r),r.protocol=Ie.call(r),r.username=Ne.call(r),r.password=je.call(r),r.host=Pe.call(r),r.hostname=Le.call(r),r.port=$e.call(r),r.pathname=De.call(r),r.search=Fe.call(r),r.searchParams=Be.call(r),r.hash=Ue.call(r))},Me=Ce.prototype,Te=function(){var e=E(this),t=e.scheme,n=e.username,r=e.password,i=e.host,o=e.port,a=e.path,s=e.query,c=e.fragment,u=t+":";return null!==i?(u+="//",Q(e)&&(u+=n+(r?":"+r:"")+"@"),u+=W(i),null!==o&&(u+=":"+o)):"file"==t&&(u+="//"),u+=e.cannotBeABaseURL?a[0]:a.length?"/"+a.join("/"):"",null!==s&&(u+="?"+s),null!==c&&(u+="#"+c),u},Re=function(){var e=E(this),t=e.scheme,n=e.port;if("blob"==t)try{return new Ce(t.path[0]).origin}catch(r){return"null"}return"file"!=t&&Z(e)?t+"://"+W(e.host)+(null!==n?":"+n:""):"null"},Ie=function(){return E(this).scheme+":"},Ne=function(){return E(this).username},je=function(){return E(this).password},Pe=function(){var e=E(this),t=e.host,n=e.port;return null===t?"":null===n?W(t):W(t)+":"+n},Le=function(){var e=E(this).host;return null===e?"":W(e)},$e=function(){var e=E(this).port;return null===e?"":String(e)},De=function(){var e=E(this),t=e.path;return e.cannotBeABaseURL?t[0]:t.length?"/"+t.join("/"):""},Fe=function(){var e=E(this).query;return e?"?"+e:""},Be=function(){return E(this).searchParams},Ue=function(){var e=E(this).fragment;return e?"#"+e:""},ze=function(e,t){return{get:e,set:t,configurable:!0,enumerable:!0}};if(o&&c(Me,{href:ze(Te,(function(e){var t=E(this),n=String(e),r=Oe(t,n);if(r)throw TypeError(r);_(t.searchParams).updateSearchParams(t.query)})),origin:ze(Re),protocol:ze(Ie,(function(e){var t=E(this);Oe(t,String(e)+":",ae)})),username:ze(Ne,(function(e){var t=E(this),n=p(String(e));if(!ee(t)){t.username="";for(var r=0;r1?arguments[1]:void 0,t.length)),r=String(e);return l?l.call(t,r,n):t.slice(n,n+r.length)===r}})},"2ce5":function(e,t,n){(function(t){"use strict";for(var n=[null,0,{}],r=10,i=44032,o=4352,a=4449,s=4519,c=19,u=21,l=28,f=u*l,d=c*f,p=function(e,t){this.codepoint=e,this.feature=t},h={},v=[],g=0;g<=255;++g)v[g]=0;function b(e,t,n){var i=h[t];return i||(i=e(t,n),i.feature&&++v[t>>8&255]>r&&(h[t]=i)),i}function m(e,t,r){var i=65280&t,o=p.udata[i]||{},a=o[t];return new p(t,a||n)}function y(e,t,n){return n?e(t,n):new p(t,null)}function w(e,t,n){var r;if(t=55296&&e<=56319},p.isLowSurrogate=function(e){return e>=56320&&e<=57343},p.prototype.prepFeature=function(){this.feature||(this.feature=p.fromCharCode(this.codepoint,!0).feature)},p.prototype.toString=function(){if(this.codepoint<65536)return String.fromCharCode(this.codepoint);var e=this.codepoint-65536;return String.fromCharCode(Math.floor(e/1024)+55296,e%1024+56320)},p.prototype.getDecomp=function(){return this.prepFeature(),this.feature[0]||null},p.prototype.isCompatibility=function(){return this.prepFeature(),!!this.feature[1]&&256&this.feature[1]},p.prototype.isExclude=function(){return this.prepFeature(),!!this.feature[1]&&512&this.feature[1]},p.prototype.getCanonicalClass=function(){return this.prepFeature(),this.feature[1]?255&this.feature[1]:0},p.prototype.getComposite=function(e){if(this.prepFeature(),!this.feature[2])return null;var t=this.feature[2][e.codepoint];return t?p.fromCharCode(t):null};var E=function(e){this.str=e,this.cursor=0};E.prototype.next=function(){if(this.str&&this.cursor0;--n){var r=this.resBuf[n-1],i=r.getCanonicalClass();if(i<=e)break}this.resBuf.splice(n,0,t)}while(0!==e);return this.resBuf.shift()};var k=function(e){this.it=e,this.procBuf=[],this.resBuf=[],this.lastClass=null};k.prototype.next=function(){while(0===this.resBuf.length){var e=this.it.next();if(!e){this.resBuf=this.procBuf,this.procBuf=[];break}if(0===this.procBuf.length)this.lastClass=e.getCanonicalClass(),this.procBuf.push(e);else{var t=this.procBuf[0],n=t.getComposite(e),r=e.getCanonicalClass();n&&(this.lastClassn)t.push(arguments[n++]);return w[++y]=function(){("function"==typeof e?e:Function(e)).apply(void 0,t)},r(y),y},v=function(e){delete w[e]},d?r=function(e){g.nextTick(E(e))}:m&&m.now?r=function(e){m.now(E(e))}:b&&!f?(i=new b,o=i.port2,i.port1.onmessage=S,r=c(o.postMessage,o,1)):a.addEventListener&&"function"==typeof postMessage&&!a.importScripts&&p&&"file:"!==p.protocol&&!s(A)?(r=A,a.addEventListener("message",S,!1)):r=_ in l("script")?function(e){u.appendChild(l("script"))[_]=function(){u.removeChild(this),x(e)}}:function(e){setTimeout(E(e),0)}),e.exports={set:h,clear:v}},"2d00":function(e,t,n){var r,i,o=n("da84"),a=n("342f"),s=o.process,c=s&&s.versions,u=c&&c.v8;u?(r=u.split("."),i=r[0]<4?1:r[0]+r[1]):a&&(r=a.match(/Edge\/(\d+)/),(!r||r[1]>=74)&&(r=a.match(/Chrome\/(\d+)/),r&&(i=r[1]))),e.exports=i&&+i},"2d26":function(e,t,n){n("a4d3"),n("e01a"),n("b636"),n("dc8d"),n("efe9"),n("d28b"),n("2a1b"),n("8edd"),n("80e0"),n("6b9e"),n("197b"),n("2351"),n("8172"),n("944a"),n("81b8"),n("967a"),n("99af"),n("a874"),n("a623"),n("cb29"),n("4de4"),n("7db0"),n("c740"),n("0481"),n("5db7"),n("4160"),n("a630"),n("caad"),n("c975"),n("277d"),n("e260"),n("a15b"),n("baa5"),n("d81d"),n("5ded"),n("13d5"),n("f4dd"),n("26e9"),n("fb6a"),n("45fc"),n("4e82"),n("f785"),n("a434"),n("4069"),n("73d9"),n("c19f"),n("82da"),n("ace4"),n("b420"),n("6eba"),n("accc"),n("f4b3"),n("efec"),n("0d03"),n("c0b6"),n("b56e"),n("b0c0"),n("6c57"),n("e9c4"),n("0c47"),n("4ec9"),n("5327"),n("79a8"),n("9ff9"),n("3ea3"),n("40d9"),n("ff9c"),n("0ac8"),n("f664"),n("4057"),n("bc01"),n("6b93"),n("ca21"),n("90d7"),n("2af1"),n("0261"),n("7898"),n("23dc"),n("b65f"),n("a9e3"),n("35b3"),n("f00c"),n("8ba4"),n("9129"),n("583b"),n("aff5"),n("e6e1"),n("c35a"),n("25eb"),n("b680"),n("542d"),n("cca6"),n("b8bf"),n("12a8"),n("1d1c"),n("7a82"),n("e71b"),n("4fad"),n("dca8"),n("c1f9"),n("e439"),n("dbb4"),n("7039"),n("3410"),n("2b19"),n("c906"),n("e21d"),n("e43e"),n("b64b"),n("bf96"),n("5bf7"),n("cee8"),n("af93"),n("131a"),n("d3b7"),n("07ac"),n("acd8"),n("e25e"),n("e6cf"),n("820e"),n("dbfa"),n("a79d"),n("a6fd"),n("4ae1"),n("3f3a"),n("ac16"),n("5d41"),n("9e4a"),n("7f78"),n("c760"),n("db96"),n("1bf2"),n("d6dd"),n("7ed3"),n("8b9a"),n("f8c9"),n("4d63"),n("ac1f"),n("5377"),n("2c3e"),n("00b4"),n("25f0"),n("6062"),n("f5b2"),n("8a79"),n("f6d6"),n("2532"),n("3ca3"),n("466d"),n("a1f0"),n("843c"),n("4d90"),n("d80f"),n("38cf"),n("5319"),n("5b81"),n("841c"),n("1276"),n("2ca0"),n("498a"),n("1e25"),n("eee7"),n("18a5"),n("1393"),n("04d3"),n("cc71"),n("c7cd"),n("9767"),n("1913"),n("c5d0"),n("9911"),n("c96a"),n("2315"),n("4c53"),n("664f"),n("cfc3"),n("4a9b"),n("fd87"),n("8b09"),n("143c"),n("5cc6"),n("8a59"),n("84c3"),n("fb2c"),n("9a8c"),n("a975"),n("735e"),n("c1ac"),n("d139"),n("3a7b"),n("d5d6"),n("20bf"),n("82f8"),n("e91f"),n("60bd"),n("5f96"),n("3280"),n("3fcc"),n("ec97"),n("ca91"),n("25a1"),n("cd26"),n("3c5d"),n("2954"),n("649e"),n("219c"),n("170b"),n("b39a"),n("72f7"),n("10d1"),n("1fe2"),n("159b"),n("ddb0"),n("130f"),n("9f96"),n("4795"),n("2b3d"),n("bf19"),n("9861"),e.exports=n("428f")},"2d93":function(e,t){t.Z=[32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8232,8233,8239,8287,12288]},3280:function(e,t,n){"use strict";var r=n("ebb5"),i=n("e58c"),o=r.aTypedArray,a=r.exportTypedArrayMethod;a("lastIndexOf",(function(e){return i.apply(o(this),arguments)}))},3393:function(e,t){t.L=[65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,170,181,186,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,710,711,712,713,714,715,716,717,718,719,720,721,736,737,738,739,740,748,750,880,881,882,883,884,886,887,890,891,892,893,895,902,904,905,906,908,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1e3,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1369,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1520,1521,1522,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1646,1647,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1749,1765,1766,1774,1775,1786,1787,1788,1791,1808,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1969,1994,1995,1996,1997,1998,1999,2e3,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2036,2037,2042,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2074,2084,2088,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2365,2384,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2431,2432,2437,2438,2439,2440,2441,2442,2443,2444,2447,2448,2451,2452,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2474,2475,2476,2477,2478,2479,2480,2482,2486,2487,2488,2489,2493,2510,2524,2525,2527,2528,2529,2544,2545,2565,2566,2567,2568,2569,2570,2575,2576,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2602,2603,2604,2605,2606,2607,2608,2610,2611,2613,2614,2616,2617,2649,2650,2651,2652,2654,2674,2675,2676,2693,2694,2695,2696,2697,2698,2699,2700,2701,2703,2704,2705,2707,2708,2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,2730,2731,2732,2733,2734,2735,2736,2738,2739,2741,2742,2743,2744,2745,2749,2768,2784,2785,2809,2821,2822,2823,2824,2825,2826,2827,2828,2831,2832,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2858,2859,2860,2861,2862,2863,2864,2866,2867,2869,2870,2871,2872,2873,2877,2908,2909,2911,2912,2913,2929,2947,2949,2950,2951,2952,2953,2954,2958,2959,2960,2962,2963,2964,2965,2969,2970,2972,2974,2975,2979,2980,2984,2985,2986,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3e3,3001,3024,3077,3078,3079,3080,3081,3082,3083,3084,3086,3087,3088,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,3133,3160,3161,3162,3168,3169,3205,3206,3207,3208,3209,3210,3211,3212,3214,3215,3216,3218,3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3253,3254,3255,3256,3257,3261,3294,3296,3297,3313,3314,3333,3334,3335,3336,3337,3338,3339,3340,3342,3343,3344,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3389,3406,3423,3424,3425,3450,3451,3452,3453,3454,3455,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3507,3508,3509,3510,3511,3512,3513,3514,3515,3517,3520,3521,3522,3523,3524,3525,3526,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3634,3635,3648,3649,3650,3651,3652,3653,3654,3713,3714,3716,3719,3720,3722,3725,3732,3733,3734,3735,3737,3738,3739,3740,3741,3742,3743,3745,3746,3747,3749,3751,3754,3755,3757,3758,3759,3760,3762,3763,3773,3776,3777,3778,3779,3780,3782,3804,3805,3806,3807,3840,3904,3905,3906,3907,3908,3909,3910,3911,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3976,3977,3978,3979,3980,4096,4097,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,4138,4159,4176,4177,4178,4179,4180,4181,4186,4187,4188,4189,4193,4197,4198,4206,4207,4208,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,4225,4238,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,4295,4301,4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,4330,4331,4332,4333,4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,4345,4346,4348,4349,4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,4419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,4675,4676,4677,4678,4679,4680,4682,4683,4684,4685,4688,4689,4690,4691,4692,4693,4694,4696,4698,4699,4700,4701,4704,4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4746,4747,4748,4749,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,4780,4781,4782,4783,4784,4786,4787,4788,4789,4792,4793,4794,4795,4796,4797,4798,4800,4802,4803,4804,4805,4808,4809,4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4824,4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4882,4883,4884,4885,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4992,4993,4994,4995,4996,4997,4998,4999,5e3,5001,5002,5003,5004,5005,5006,5007,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,5112,5113,5114,5115,5116,5117,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664,5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,5759,5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5792,5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,5860,5861,5862,5863,5864,5865,5866,5873,5874,5875,5876,5877,5878,5879,5880,5888,5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5902,5903,5904,5905,5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936,5937,5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968,5969,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5998,5999,6e3,6016,6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6103,6108,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,6189,6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,6249,6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,6272,6273,6274,6275,6276,6277,6278,6279,6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,6294,6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,6309,6310,6311,6312,6314,6320,6321,6322,6323,6324,6325,6326,6327,6328,6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,6339,6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,6354,6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,6384,6385,6386,6387,6388,6389,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,6429,6430,6480,6481,6482,6483,6484,6485,6486,6487,6488,6489,6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,6504,6505,6506,6507,6508,6509,6512,6513,6514,6515,6516,6528,6529,6530,6531,6532,6533,6534,6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,6565,6566,6567,6568,6569,6570,6571,6576,6577,6578,6579,6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,6595,6596,6597,6598,6599,6600,6601,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,6669,6670,6671,6672,6673,6674,6675,6676,6677,6678,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,6715,6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6823,6917,6918,6919,6920,6921,6922,6923,6924,6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,6939,6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6981,6982,6983,6984,6985,6986,6987,7043,7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059,7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7086,7087,7098,7099,7100,7101,7102,7103,7104,7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136,7137,7138,7139,7140,7141,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,7194,7195,7196,7197,7198,7199,7200,7201,7202,7203,7245,7246,7247,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,7269,7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,7284,7285,7286,7287,7288,7289,7290,7291,7292,7293,7401,7402,7403,7404,7406,7407,7408,7409,7413,7414,7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,7448,7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,7463,7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,7478,7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491,7492,7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,7538,7539,7540,7541,7542,7543,7544,7545,7546,7547,7548,7549,7550,7551,7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567,7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614,7615,7680,7681,7682,7683,7684,7685,7686,7687,7688,7689,7690,7691,7692,7693,7694,7695,7696,7697,7698,7699,7700,7701,7702,7703,7704,7705,7706,7707,7708,7709,7710,7711,7712,7713,7714,7715,7716,7717,7718,7719,7720,7721,7722,7723,7724,7725,7726,7727,7728,7729,7730,7731,7732,7733,7734,7735,7736,7737,7738,7739,7740,7741,7742,7743,7744,7745,7746,7747,7748,7749,7750,7751,7752,7753,7754,7755,7756,7757,7758,7759,7760,7761,7762,7763,7764,7765,7766,7767,7768,7769,7770,7771,7772,7773,7774,7775,7776,7777,7778,7779,7780,7781,7782,7783,7784,7785,7786,7787,7788,7789,7790,7791,7792,7793,7794,7795,7796,7797,7798,7799,7800,7801,7802,7803,7804,7805,7806,7807,7808,7809,7810,7811,7812,7813,7814,7815,7816,7817,7818,7819,7820,7821,7822,7823,7824,7825,7826,7827,7828,7829,7830,7831,7832,7833,7834,7835,7836,7837,7838,7839,7840,7841,7842,7843,7844,7845,7846,7847,7848,7849,7850,7851,7852,7853,7854,7855,7856,7857,7858,7859,7860,7861,7862,7863,7864,7865,7866,7867,7868,7869,7870,7871,7872,7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886,7887,7888,7889,7890,7891,7892,7893,7894,7895,7896,7897,7898,7899,7900,7901,7902,7903,7904,7905,7906,7907,7908,7909,7910,7911,7912,7913,7914,7915,7916,7917,7918,7919,7920,7921,7922,7923,7924,7925,7926,7927,7928,7929,7930,7931,7932,7933,7934,7935,7936,7937,7938,7939,7940,7941,7942,7943,7944,7945,7946,7947,7948,7949,7950,7951,7952,7953,7954,7955,7956,7957,7960,7961,7962,7963,7964,7965,7968,7969,7970,7971,7972,7973,7974,7975,7976,7977,7978,7979,7980,7981,7982,7983,7984,7985,7986,7987,7988,7989,7990,7991,7992,7993,7994,7995,7996,7997,7998,7999,8e3,8001,8002,8003,8004,8005,8008,8009,8010,8011,8012,8013,8016,8017,8018,8019,8020,8021,8022,8023,8025,8027,8029,8031,8032,8033,8034,8035,8036,8037,8038,8039,8040,8041,8042,8043,8044,8045,8046,8047,8048,8049,8050,8051,8052,8053,8054,8055,8056,8057,8058,8059,8060,8061,8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,8096,8097,8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110,8111,8112,8113,8114,8115,8116,8118,8119,8120,8121,8122,8123,8124,8126,8130,8131,8132,8134,8135,8136,8137,8138,8139,8140,8144,8145,8146,8147,8150,8151,8152,8153,8154,8155,8160,8161,8162,8163,8164,8165,8166,8167,8168,8169,8170,8171,8172,8178,8179,8180,8182,8183,8184,8185,8186,8187,8188,8305,8319,8336,8337,8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,8348,8450,8455,8458,8459,8460,8461,8462,8463,8464,8465,8466,8467,8469,8473,8474,8475,8476,8477,8484,8486,8488,8490,8491,8492,8493,8495,8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8508,8509,8510,8511,8517,8518,8519,8520,8521,8526,8579,8580,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,11306,11307,11308,11309,11310,11312,11313,11314,11315,11316,11317,11318,11319,11320,11321,11322,11323,11324,11325,11326,11327,11328,11329,11330,11331,11332,11333,11334,11335,11336,11337,11338,11339,11340,11341,11342,11343,11344,11345,11346,11347,11348,11349,11350,11351,11352,11353,11354,11355,11356,11357,11358,11360,11361,11362,11363,11364,11365,11366,11367,11368,11369,11370,11371,11372,11373,11374,11375,11376,11377,11378,11379,11380,11381,11382,11383,11384,11385,11386,11387,11388,11389,11390,11391,11392,11393,11394,11395,11396,11397,11398,11399,11400,11401,11402,11403,11404,11405,11406,11407,11408,11409,11410,11411,11412,11413,11414,11415,11416,11417,11418,11419,11420,11421,11422,11423,11424,11425,11426,11427,11428,11429,11430,11431,11432,11433,11434,11435,11436,11437,11438,11439,11440,11441,11442,11443,11444,11445,11446,11447,11448,11449,11450,11451,11452,11453,11454,11455,11456,11457,11458,11459,11460,11461,11462,11463,11464,11465,11466,11467,11468,11469,11470,11471,11472,11473,11474,11475,11476,11477,11478,11479,11480,11481,11482,11483,11484,11485,11486,11487,11488,11489,11490,11491,11492,11499,11500,11501,11502,11506,11507,11520,11521,11522,11523,11524,11525,11526,11527,11528,11529,11530,11531,11532,11533,11534,11535,11536,11537,11538,11539,11540,11541,11542,11543,11544,11545,11546,11547,11548,11549,11550,11551,11552,11553,11554,11555,11556,11557,11559,11565,11568,11569,11570,11571,11572,11573,11574,11575,11576,11577,11578,11579,11580,11581,11582,11583,11584,11585,11586,11587,11588,11589,11590,11591,11592,11593,11594,11595,11596,11597,11598,11599,11600,11601,11602,11603,11604,11605,11606,11607,11608,11609,11610,11611,11612,11613,11614,11615,11616,11617,11618,11619,11620,11621,11622,11623,11631,11648,11649,11650,11651,11652,11653,11654,11655,11656,11657,11658,11659,11660,11661,11662,11663,11664,11665,11666,11667,11668,11669,11670,11680,11681,11682,11683,11684,11685,11686,11688,11689,11690,11691,11692,11693,11694,11696,11697,11698,11699,11700,11701,11702,11704,11705,11706,11707,11708,11709,11710,11712,11713,11714,11715,11716,11717,11718,11720,11721,11722,11723,11724,11725,11726,11728,11729,11730,11731,11732,11733,11734,11736,11737,11738,11739,11740,11741,11742,11823,12293,12294,12337,12338,12339,12340,12341,12347,12348,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,12436,12437,12438,12445,12446,12447,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,12535,12536,12537,12538,12540,12541,12542,12543,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,12586,12587,12588,12589,12593,12594,12595,12596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,12632,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679,12680,12681,12682,12683,12684,12685,12686,12704,12705,12706,12707,12708,12709,12710,12711,12712,12713,12714,12715,12716,12717,12718,12719,12720,12721,12722,12723,12724,12725,12726,12727,12728,12729,12730,12784,12785,12786,12787,12788,12789,12790,12791,12792,12793,12794,12795,12796,12797,12798,12799,13312,19893,19968,40917,40960,40961,40962,40963,40964,40965,40966,40967,40968,40969,40970,40971,40972,40973,40974,40975,40976,40977,40978,40979,40980,40981,40982,40983,40984,40985,40986,40987,40988,40989,40990,40991,40992,40993,40994,40995,40996,40997,40998,40999,41e3,41001,41002,41003,41004,41005,41006,41007,41008,41009,41010,41011,41012,41013,41014,41015,41016,41017,41018,41019,41020,41021,41022,41023,41024,41025,41026,41027,41028,41029,41030,41031,41032,41033,41034,41035,41036,41037,41038,41039,41040,41041,41042,41043,41044,41045,41046,41047,41048,41049,41050,41051,41052,41053,41054,41055,41056,41057,41058,41059,41060,41061,41062,41063,41064,41065,41066,41067,41068,41069,41070,41071,41072,41073,41074,41075,41076,41077,41078,41079,41080,41081,41082,41083,41084,41085,41086,41087,41088,41089,41090,41091,41092,41093,41094,41095,41096,41097,41098,41099,41100,41101,41102,41103,41104,41105,41106,41107,41108,41109,41110,41111,41112,41113,41114,41115,41116,41117,41118,41119,41120,41121,41122,41123,41124,41125,41126,41127,41128,41129,41130,41131,41132,41133,41134,41135,41136,41137,41138,41139,41140,41141,41142,41143,41144,41145,41146,41147,41148,41149,41150,41151,41152,41153,41154,41155,41156,41157,41158,41159,41160,41161,41162,41163,41164,41165,41166,41167,41168,41169,41170,41171,41172,41173,41174,41175,41176,41177,41178,41179,41180,41181,41182,41183,41184,41185,41186,41187,41188,41189,41190,41191,41192,41193,41194,41195,41196,41197,41198,41199,41200,41201,41202,41203,41204,41205,41206,41207,41208,41209,41210,41211,41212,41213,41214,41215,41216,41217,41218,41219,41220,41221,41222,41223,41224,41225,41226,41227,41228,41229,41230,41231,41232,41233,41234,41235,41236,41237,41238,41239,41240,41241,41242,41243,41244,41245,41246,41247,41248,41249,41250,41251,41252,41253,41254,41255,41256,41257,41258,41259,41260,41261,41262,41263,41264,41265,41266,41267,41268,41269,41270,41271,41272,41273,41274,41275,41276,41277,41278,41279,41280,41281,41282,41283,41284,41285,41286,41287,41288,41289,41290,41291,41292,41293,41294,41295,41296,41297,41298,41299,41300,41301,41302,41303,41304,41305,41306,41307,41308,41309,41310,41311,41312,41313,41314,41315,41316,41317,41318,41319,41320,41321,41322,41323,41324,41325,41326,41327,41328,41329,41330,41331,41332,41333,41334,41335,41336,41337,41338,41339,41340,41341,41342,41343,41344,41345,41346,41347,41348,41349,41350,41351,41352,41353,41354,41355,41356,41357,41358,41359,41360,41361,41362,41363,41364,41365,41366,41367,41368,41369,41370,41371,41372,41373,41374,41375,41376,41377,41378,41379,41380,41381,41382,41383,41384,41385,41386,41387,41388,41389,41390,41391,41392,41393,41394,41395,41396,41397,41398,41399,41400,41401,41402,41403,41404,41405,41406,41407,41408,41409,41410,41411,41412,41413,41414,41415,41416,41417,41418,41419,41420,41421,41422,41423,41424,41425,41426,41427,41428,41429,41430,41431,41432,41433,41434,41435,41436,41437,41438,41439,41440,41441,41442,41443,41444,41445,41446,41447,41448,41449,41450,41451,41452,41453,41454,41455,41456,41457,41458,41459,41460,41461,41462,41463,41464,41465,41466,41467,41468,41469,41470,41471,41472,41473,41474,41475,41476,41477,41478,41479,41480,41481,41482,41483,41484,41485,41486,41487,41488,41489,41490,41491,41492,41493,41494,41495,41496,41497,41498,41499,41500,41501,41502,41503,41504,41505,41506,41507,41508,41509,41510,41511,41512,41513,41514,41515,41516,41517,41518,41519,41520,41521,41522,41523,41524,41525,41526,41527,41528,41529,41530,41531,41532,41533,41534,41535,41536,41537,41538,41539,41540,41541,41542,41543,41544,41545,41546,41547,41548,41549,41550,41551,41552,41553,41554,41555,41556,41557,41558,41559,41560,41561,41562,41563,41564,41565,41566,41567,41568,41569,41570,41571,41572,41573,41574,41575,41576,41577,41578,41579,41580,41581,41582,41583,41584,41585,41586,41587,41588,41589,41590,41591,41592,41593,41594,41595,41596,41597,41598,41599,41600,41601,41602,41603,41604,41605,41606,41607,41608,41609,41610,41611,41612,41613,41614,41615,41616,41617,41618,41619,41620,41621,41622,41623,41624,41625,41626,41627,41628,41629,41630,41631,41632,41633,41634,41635,41636,41637,41638,41639,41640,41641,41642,41643,41644,41645,41646,41647,41648,41649,41650,41651,41652,41653,41654,41655,41656,41657,41658,41659,41660,41661,41662,41663,41664,41665,41666,41667,41668,41669,41670,41671,41672,41673,41674,41675,41676,41677,41678,41679,41680,41681,41682,41683,41684,41685,41686,41687,41688,41689,41690,41691,41692,41693,41694,41695,41696,41697,41698,41699,41700,41701,41702,41703,41704,41705,41706,41707,41708,41709,41710,41711,41712,41713,41714,41715,41716,41717,41718,41719,41720,41721,41722,41723,41724,41725,41726,41727,41728,41729,41730,41731,41732,41733,41734,41735,41736,41737,41738,41739,41740,41741,41742,41743,41744,41745,41746,41747,41748,41749,41750,41751,41752,41753,41754,41755,41756,41757,41758,41759,41760,41761,41762,41763,41764,41765,41766,41767,41768,41769,41770,41771,41772,41773,41774,41775,41776,41777,41778,41779,41780,41781,41782,41783,41784,41785,41786,41787,41788,41789,41790,41791,41792,41793,41794,41795,41796,41797,41798,41799,41800,41801,41802,41803,41804,41805,41806,41807,41808,41809,41810,41811,41812,41813,41814,41815,41816,41817,41818,41819,41820,41821,41822,41823,41824,41825,41826,41827,41828,41829,41830,41831,41832,41833,41834,41835,41836,41837,41838,41839,41840,41841,41842,41843,41844,41845,41846,41847,41848,41849,41850,41851,41852,41853,41854,41855,41856,41857,41858,41859,41860,41861,41862,41863,41864,41865,41866,41867,41868,41869,41870,41871,41872,41873,41874,41875,41876,41877,41878,41879,41880,41881,41882,41883,41884,41885,41886,41887,41888,41889,41890,41891,41892,41893,41894,41895,41896,41897,41898,41899,41900,41901,41902,41903,41904,41905,41906,41907,41908,41909,41910,41911,41912,41913,41914,41915,41916,41917,41918,41919,41920,41921,41922,41923,41924,41925,41926,41927,41928,41929,41930,41931,41932,41933,41934,41935,41936,41937,41938,41939,41940,41941,41942,41943,41944,41945,41946,41947,41948,41949,41950,41951,41952,41953,41954,41955,41956,41957,41958,41959,41960,41961,41962,41963,41964,41965,41966,41967,41968,41969,41970,41971,41972,41973,41974,41975,41976,41977,41978,41979,41980,41981,41982,41983,41984,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,41997,41998,41999,42e3,42001,42002,42003,42004,42005,42006,42007,42008,42009,42010,42011,42012,42013,42014,42015,42016,42017,42018,42019,42020,42021,42022,42023,42024,42025,42026,42027,42028,42029,42030,42031,42032,42033,42034,42035,42036,42037,42038,42039,42040,42041,42042,42043,42044,42045,42046,42047,42048,42049,42050,42051,42052,42053,42054,42055,42056,42057,42058,42059,42060,42061,42062,42063,42064,42065,42066,42067,42068,42069,42070,42071,42072,42073,42074,42075,42076,42077,42078,42079,42080,42081,42082,42083,42084,42085,42086,42087,42088,42089,42090,42091,42092,42093,42094,42095,42096,42097,42098,42099,42100,42101,42102,42103,42104,42105,42106,42107,42108,42109,42110,42111,42112,42113,42114,42115,42116,42117,42118,42119,42120,42121,42122,42123,42124,42192,42193,42194,42195,42196,42197,42198,42199,42200,42201,42202,42203,42204,42205,42206,42207,42208,42209,42210,42211,42212,42213,42214,42215,42216,42217,42218,42219,42220,42221,42222,42223,42224,42225,42226,42227,42228,42229,42230,42231,42232,42233,42234,42235,42236,42237,42240,42241,42242,42243,42244,42245,42246,42247,42248,42249,42250,42251,42252,42253,42254,42255,42256,42257,42258,42259,42260,42261,42262,42263,42264,42265,42266,42267,42268,42269,42270,42271,42272,42273,42274,42275,42276,42277,42278,42279,42280,42281,42282,42283,42284,42285,42286,42287,42288,42289,42290,42291,42292,42293,42294,42295,42296,42297,42298,42299,42300,42301,42302,42303,42304,42305,42306,42307,42308,42309,42310,42311,42312,42313,42314,42315,42316,42317,42318,42319,42320,42321,42322,42323,42324,42325,42326,42327,42328,42329,42330,42331,42332,42333,42334,42335,42336,42337,42338,42339,42340,42341,42342,42343,42344,42345,42346,42347,42348,42349,42350,42351,42352,42353,42354,42355,42356,42357,42358,42359,42360,42361,42362,42363,42364,42365,42366,42367,42368,42369,42370,42371,42372,42373,42374,42375,42376,42377,42378,42379,42380,42381,42382,42383,42384,42385,42386,42387,42388,42389,42390,42391,42392,42393,42394,42395,42396,42397,42398,42399,42400,42401,42402,42403,42404,42405,42406,42407,42408,42409,42410,42411,42412,42413,42414,42415,42416,42417,42418,42419,42420,42421,42422,42423,42424,42425,42426,42427,42428,42429,42430,42431,42432,42433,42434,42435,42436,42437,42438,42439,42440,42441,42442,42443,42444,42445,42446,42447,42448,42449,42450,42451,42452,42453,42454,42455,42456,42457,42458,42459,42460,42461,42462,42463,42464,42465,42466,42467,42468,42469,42470,42471,42472,42473,42474,42475,42476,42477,42478,42479,42480,42481,42482,42483,42484,42485,42486,42487,42488,42489,42490,42491,42492,42493,42494,42495,42496,42497,42498,42499,42500,42501,42502,42503,42504,42505,42506,42507,42508,42512,42513,42514,42515,42516,42517,42518,42519,42520,42521,42522,42523,42524,42525,42526,42527,42538,42539,42560,42561,42562,42563,42564,42565,42566,42567,42568,42569,42570,42571,42572,42573,42574,42575,42576,42577,42578,42579,42580,42581,42582,42583,42584,42585,42586,42587,42588,42589,42590,42591,42592,42593,42594,42595,42596,42597,42598,42599,42600,42601,42602,42603,42604,42605,42606,42623,42624,42625,42626,42627,42628,42629,42630,42631,42632,42633,42634,42635,42636,42637,42638,42639,42640,42641,42642,42643,42644,42645,42646,42647,42648,42649,42650,42651,42652,42653,42656,42657,42658,42659,42660,42661,42662,42663,42664,42665,42666,42667,42668,42669,42670,42671,42672,42673,42674,42675,42676,42677,42678,42679,42680,42681,42682,42683,42684,42685,42686,42687,42688,42689,42690,42691,42692,42693,42694,42695,42696,42697,42698,42699,42700,42701,42702,42703,42704,42705,42706,42707,42708,42709,42710,42711,42712,42713,42714,42715,42716,42717,42718,42719,42720,42721,42722,42723,42724,42725,42775,42776,42777,42778,42779,42780,42781,42782,42783,42786,42787,42788,42789,42790,42791,42792,42793,42794,42795,42796,42797,42798,42799,42800,42801,42802,42803,42804,42805,42806,42807,42808,42809,42810,42811,42812,42813,42814,42815,42816,42817,42818,42819,42820,42821,42822,42823,42824,42825,42826,42827,42828,42829,42830,42831,42832,42833,42834,42835,42836,42837,42838,42839,42840,42841,42842,42843,42844,42845,42846,42847,42848,42849,42850,42851,42852,42853,42854,42855,42856,42857,42858,42859,42860,42861,42862,42863,42864,42865,42866,42867,42868,42869,42870,42871,42872,42873,42874,42875,42876,42877,42878,42879,42880,42881,42882,42883,42884,42885,42886,42887,42888,42891,42892,42893,42894,42895,42896,42897,42898,42899,42900,42901,42902,42903,42904,42905,42906,42907,42908,42909,42910,42911,42912,42913,42914,42915,42916,42917,42918,42919,42920,42921,42922,42923,42924,42925,42928,42929,42930,42931,42932,42933,42934,42935,42999,43e3,43001,43002,43003,43004,43005,43006,43007,43008,43009,43011,43012,43013,43015,43016,43017,43018,43020,43021,43022,43023,43024,43025,43026,43027,43028,43029,43030,43031,43032,43033,43034,43035,43036,43037,43038,43039,43040,43041,43042,43072,43073,43074,43075,43076,43077,43078,43079,43080,43081,43082,43083,43084,43085,43086,43087,43088,43089,43090,43091,43092,43093,43094,43095,43096,43097,43098,43099,43100,43101,43102,43103,43104,43105,43106,43107,43108,43109,43110,43111,43112,43113,43114,43115,43116,43117,43118,43119,43120,43121,43122,43123,43138,43139,43140,43141,43142,43143,43144,43145,43146,43147,43148,43149,43150,43151,43152,43153,43154,43155,43156,43157,43158,43159,43160,43161,43162,43163,43164,43165,43166,43167,43168,43169,43170,43171,43172,43173,43174,43175,43176,43177,43178,43179,43180,43181,43182,43183,43184,43185,43186,43187,43250,43251,43252,43253,43254,43255,43259,43261,43274,43275,43276,43277,43278,43279,43280,43281,43282,43283,43284,43285,43286,43287,43288,43289,43290,43291,43292,43293,43294,43295,43296,43297,43298,43299,43300,43301,43312,43313,43314,43315,43316,43317,43318,43319,43320,43321,43322,43323,43324,43325,43326,43327,43328,43329,43330,43331,43332,43333,43334,43360,43361,43362,43363,43364,43365,43366,43367,43368,43369,43370,43371,43372,43373,43374,43375,43376,43377,43378,43379,43380,43381,43382,43383,43384,43385,43386,43387,43388,43396,43397,43398,43399,43400,43401,43402,43403,43404,43405,43406,43407,43408,43409,43410,43411,43412,43413,43414,43415,43416,43417,43418,43419,43420,43421,43422,43423,43424,43425,43426,43427,43428,43429,43430,43431,43432,43433,43434,43435,43436,43437,43438,43439,43440,43441,43442,43471,43488,43489,43490,43491,43492,43494,43495,43496,43497,43498,43499,43500,43501,43502,43503,43514,43515,43516,43517,43518,43520,43521,43522,43523,43524,43525,43526,43527,43528,43529,43530,43531,43532,43533,43534,43535,43536,43537,43538,43539,43540,43541,43542,43543,43544,43545,43546,43547,43548,43549,43550,43551,43552,43553,43554,43555,43556,43557,43558,43559,43560,43584,43585,43586,43588,43589,43590,43591,43592,43593,43594,43595,43616,43617,43618,43619,43620,43621,43622,43623,43624,43625,43626,43627,43628,43629,43630,43631,43632,43633,43634,43635,43636,43637,43638,43642,43646,43647,43648,43649,43650,43651,43652,43653,43654,43655,43656,43657,43658,43659,43660,43661,43662,43663,43664,43665,43666,43667,43668,43669,43670,43671,43672,43673,43674,43675,43676,43677,43678,43679,43680,43681,43682,43683,43684,43685,43686,43687,43688,43689,43690,43691,43692,43693,43694,43695,43697,43701,43702,43705,43706,43707,43708,43709,43712,43714,43739,43740,43741,43744,43745,43746,43747,43748,43749,43750,43751,43752,43753,43754,43762,43763,43764,43777,43778,43779,43780,43781,43782,43785,43786,43787,43788,43789,43790,43793,43794,43795,43796,43797,43798,43808,43809,43810,43811,43812,43813,43814,43816,43817,43818,43819,43820,43821,43822,43824,43825,43826,43827,43828,43829,43830,43831,43832,43833,43834,43835,43836,43837,43838,43839,43840,43841,43842,43843,43844,43845,43846,43847,43848,43849,43850,43851,43852,43853,43854,43855,43856,43857,43858,43859,43860,43861,43862,43863,43864,43865,43866,43868,43869,43870,43871,43872,43873,43874,43875,43876,43877,43888,43889,43890,43891,43892,43893,43894,43895,43896,43897,43898,43899,43900,43901,43902,43903,43904,43905,43906,43907,43908,43909,43910,43911,43912,43913,43914,43915,43916,43917,43918,43919,43920,43921,43922,43923,43924,43925,43926,43927,43928,43929,43930,43931,43932,43933,43934,43935,43936,43937,43938,43939,43940,43941,43942,43943,43944,43945,43946,43947,43948,43949,43950,43951,43952,43953,43954,43955,43956,43957,43958,43959,43960,43961,43962,43963,43964,43965,43966,43967,43968,43969,43970,43971,43972,43973,43974,43975,43976,43977,43978,43979,43980,43981,43982,43983,43984,43985,43986,43987,43988,43989,43990,43991,43992,43993,43994,43995,43996,43997,43998,43999,44e3,44001,44002,44032,55203,55216,55217,55218,55219,55220,55221,55222,55223,55224,55225,55226,55227,55228,55229,55230,55231,55232,55233,55234,55235,55236,55237,55238,55243,55244,55245,55246,55247,55248,55249,55250,55251,55252,55253,55254,55255,55256,55257,55258,55259,55260,55261,55262,55263,55264,55265,55266,55267,55268,55269,55270,55271,55272,55273,55274,55275,55276,55277,55278,55279,55280,55281,55282,55283,55284,55285,55286,55287,55288,55289,55290,55291,63744,63745,63746,63747,63748,63749,63750,63751,63752,63753,63754,63755,63756,63757,63758,63759,63760,63761,63762,63763,63764,63765,63766,63767,63768,63769,63770,63771,63772,63773,63774,63775,63776,63777,63778,63779,63780,63781,63782,63783,63784,63785,63786,63787,63788,63789,63790,63791,63792,63793,63794,63795,63796,63797,63798,63799,63800,63801,63802,63803,63804,63805,63806,63807,63808,63809,63810,63811,63812,63813,63814,63815,63816,63817,63818,63819,63820,63821,63822,63823,63824,63825,63826,63827,63828,63829,63830,63831,63832,63833,63834,63835,63836,63837,63838,63839,63840,63841,63842,63843,63844,63845,63846,63847,63848,63849,63850,63851,63852,63853,63854,63855,63856,63857,63858,63859,63860,63861,63862,63863,63864,63865,63866,63867,63868,63869,63870,63871,63872,63873,63874,63875,63876,63877,63878,63879,63880,63881,63882,63883,63884,63885,63886,63887,63888,63889,63890,63891,63892,63893,63894,63895,63896,63897,63898,63899,63900,63901,63902,63903,63904,63905,63906,63907,63908,63909,63910,63911,63912,63913,63914,63915,63916,63917,63918,63919,63920,63921,63922,63923,63924,63925,63926,63927,63928,63929,63930,63931,63932,63933,63934,63935,63936,63937,63938,63939,63940,63941,63942,63943,63944,63945,63946,63947,63948,63949,63950,63951,63952,63953,63954,63955,63956,63957,63958,63959,63960,63961,63962,63963,63964,63965,63966,63967,63968,63969,63970,63971,63972,63973,63974,63975,63976,63977,63978,63979,63980,63981,63982,63983,63984,63985,63986,63987,63988,63989,63990,63991,63992,63993,63994,63995,63996,63997,63998,63999,64e3,64001,64002,64003,64004,64005,64006,64007,64008,64009,64010,64011,64012,64013,64014,64015,64016,64017,64018,64019,64020,64021,64022,64023,64024,64025,64026,64027,64028,64029,64030,64031,64032,64033,64034,64035,64036,64037,64038,64039,64040,64041,64042,64043,64044,64045,64046,64047,64048,64049,64050,64051,64052,64053,64054,64055,64056,64057,64058,64059,64060,64061,64062,64063,64064,64065,64066,64067,64068,64069,64070,64071,64072,64073,64074,64075,64076,64077,64078,64079,64080,64081,64082,64083,64084,64085,64086,64087,64088,64089,64090,64091,64092,64093,64094,64095,64096,64097,64098,64099,64100,64101,64102,64103,64104,64105,64106,64107,64108,64109,64112,64113,64114,64115,64116,64117,64118,64119,64120,64121,64122,64123,64124,64125,64126,64127,64128,64129,64130,64131,64132,64133,64134,64135,64136,64137,64138,64139,64140,64141,64142,64143,64144,64145,64146,64147,64148,64149,64150,64151,64152,64153,64154,64155,64156,64157,64158,64159,64160,64161,64162,64163,64164,64165,64166,64167,64168,64169,64170,64171,64172,64173,64174,64175,64176,64177,64178,64179,64180,64181,64182,64183,64184,64185,64186,64187,64188,64189,64190,64191,64192,64193,64194,64195,64196,64197,64198,64199,64200,64201,64202,64203,64204,64205,64206,64207,64208,64209,64210,64211,64212,64213,64214,64215,64216,64217,64256,64257,64258,64259,64260,64261,64262,64275,64276,64277,64278,64279,64285,64287,64288,64289,64290,64291,64292,64293,64294,64295,64296,64298,64299,64300,64301,64302,64303,64304,64305,64306,64307,64308,64309,64310,64312,64313,64314,64315,64316,64318,64320,64321,64323,64324,64326,64327,64328,64329,64330,64331,64332,64333,64334,64335,64336,64337,64338,64339,64340,64341,64342,64343,64344,64345,64346,64347,64348,64349,64350,64351,64352,64353,64354,64355,64356,64357,64358,64359,64360,64361,64362,64363,64364,64365,64366,64367,64368,64369,64370,64371,64372,64373,64374,64375,64376,64377,64378,64379,64380,64381,64382,64383,64384,64385,64386,64387,64388,64389,64390,64391,64392,64393,64394,64395,64396,64397,64398,64399,64400,64401,64402,64403,64404,64405,64406,64407,64408,64409,64410,64411,64412,64413,64414,64415,64416,64417,64418,64419,64420,64421,64422,64423,64424,64425,64426,64427,64428,64429,64430,64431,64432,64433,64467,64468,64469,64470,64471,64472,64473,64474,64475,64476,64477,64478,64479,64480,64481,64482,64483,64484,64485,64486,64487,64488,64489,64490,64491,64492,64493,64494,64495,64496,64497,64498,64499,64500,64501,64502,64503,64504,64505,64506,64507,64508,64509,64510,64511,64512,64513,64514,64515,64516,64517,64518,64519,64520,64521,64522,64523,64524,64525,64526,64527,64528,64529,64530,64531,64532,64533,64534,64535,64536,64537,64538,64539,64540,64541,64542,64543,64544,64545,64546,64547,64548,64549,64550,64551,64552,64553,64554,64555,64556,64557,64558,64559,64560,64561,64562,64563,64564,64565,64566,64567,64568,64569,64570,64571,64572,64573,64574,64575,64576,64577,64578,64579,64580,64581,64582,64583,64584,64585,64586,64587,64588,64589,64590,64591,64592,64593,64594,64595,64596,64597,64598,64599,64600,64601,64602,64603,64604,64605,64606,64607,64608,64609,64610,64611,64612,64613,64614,64615,64616,64617,64618,64619,64620,64621,64622,64623,64624,64625,64626,64627,64628,64629,64630,64631,64632,64633,64634,64635,64636,64637,64638,64639,64640,64641,64642,64643,64644,64645,64646,64647,64648,64649,64650,64651,64652,64653,64654,64655,64656,64657,64658,64659,64660,64661,64662,64663,64664,64665,64666,64667,64668,64669,64670,64671,64672,64673,64674,64675,64676,64677,64678,64679,64680,64681,64682,64683,64684,64685,64686,64687,64688,64689,64690,64691,64692,64693,64694,64695,64696,64697,64698,64699,64700,64701,64702,64703,64704,64705,64706,64707,64708,64709,64710,64711,64712,64713,64714,64715,64716,64717,64718,64719,64720,64721,64722,64723,64724,64725,64726,64727,64728,64729,64730,64731,64732,64733,64734,64735,64736,64737,64738,64739,64740,64741,64742,64743,64744,64745,64746,64747,64748,64749,64750,64751,64752,64753,64754,64755,64756,64757,64758,64759,64760,64761,64762,64763,64764,64765,64766,64767,64768,64769,64770,64771,64772,64773,64774,64775,64776,64777,64778,64779,64780,64781,64782,64783,64784,64785,64786,64787,64788,64789,64790,64791,64792,64793,64794,64795,64796,64797,64798,64799,64800,64801,64802,64803,64804,64805,64806,64807,64808,64809,64810,64811,64812,64813,64814,64815,64816,64817,64818,64819,64820,64821,64822,64823,64824,64825,64826,64827,64828,64829,64848,64849,64850,64851,64852,64853,64854,64855,64856,64857,64858,64859,64860,64861,64862,64863,64864,64865,64866,64867,64868,64869,64870,64871,64872,64873,64874,64875,64876,64877,64878,64879,64880,64881,64882,64883,64884,64885,64886,64887,64888,64889,64890,64891,64892,64893,64894,64895,64896,64897,64898,64899,64900,64901,64902,64903,64904,64905,64906,64907,64908,64909,64910,64911,64914,64915,64916,64917,64918,64919,64920,64921,64922,64923,64924,64925,64926,64927,64928,64929,64930,64931,64932,64933,64934,64935,64936,64937,64938,64939,64940,64941,64942,64943,64944,64945,64946,64947,64948,64949,64950,64951,64952,64953,64954,64955,64956,64957,64958,64959,64960,64961,64962,64963,64964,64965,64966,64967,65008,65009,65010,65011,65012,65013,65014,65015,65016,65017,65018,65019,65136,65137,65138,65139,65140,65142,65143,65144,65145,65146,65147,65148,65149,65150,65151,65152,65153,65154,65155,65156,65157,65158,65159,65160,65161,65162,65163,65164,65165,65166,65167,65168,65169,65170,65171,65172,65173,65174,65175,65176,65177,65178,65179,65180,65181,65182,65183,65184,65185,65186,65187,65188,65189,65190,65191,65192,65193,65194,65195,65196,65197,65198,65199,65200,65201,65202,65203,65204,65205,65206,65207,65208,65209,65210,65211,65212,65213,65214,65215,65216,65217,65218,65219,65220,65221,65222,65223,65224,65225,65226,65227,65228,65229,65230,65231,65232,65233,65234,65235,65236,65237,65238,65239,65240,65241,65242,65243,65244,65245,65246,65247,65248,65249,65250,65251,65252,65253,65254,65255,65256,65257,65258,65259,65260,65261,65262,65263,65264,65265,65266,65267,65268,65269,65270,65271,65272,65273,65274,65275,65276,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,65382,65383,65384,65385,65386,65387,65388,65389,65390,65391,65392,65393,65394,65395,65396,65397,65398,65399,65400,65401,65402,65403,65404,65405,65406,65407,65408,65409,65410,65411,65412,65413,65414,65415,65416,65417,65418,65419,65420,65421,65422,65423,65424,65425,65426,65427,65428,65429,65430,65431,65432,65433,65434,65435,65436,65437,65438,65439,65440,65441,65442,65443,65444,65445,65446,65447,65448,65449,65450,65451,65452,65453,65454,65455,65456,65457,65458,65459,65460,65461,65462,65463,65464,65465,65466,65467,65468,65469,65470,65474,65475,65476,65477,65478,65479,65482,65483,65484,65485,65486,65487,65490,65491,65492,65493,65494,65495,65498,65499,65500,65536,65537,65538,65539,65540,65541,65542,65543,65544,65545,65546,65547,65549,65550,65551,65552,65553,65554,65555,65556,65557,65558,65559,65560,65561,65562,65563,65564,65565,65566,65567,65568,65569,65570,65571,65572,65573,65574,65576,65577,65578,65579,65580,65581,65582,65583,65584,65585,65586,65587,65588,65589,65590,65591,65592,65593,65594,65596,65597,65599,65600,65601,65602,65603,65604,65605,65606,65607,65608,65609,65610,65611,65612,65613,65616,65617,65618,65619,65620,65621,65622,65623,65624,65625,65626,65627,65628,65629,65664,65665,65666,65667,65668,65669,65670,65671,65672,65673,65674,65675,65676,65677,65678,65679,65680,65681,65682,65683,65684,65685,65686,65687,65688,65689,65690,65691,65692,65693,65694,65695,65696,65697,65698,65699,65700,65701,65702,65703,65704,65705,65706,65707,65708,65709,65710,65711,65712,65713,65714,65715,65716,65717,65718,65719,65720,65721,65722,65723,65724,65725,65726,65727,65728,65729,65730,65731,65732,65733,65734,65735,65736,65737,65738,65739,65740,65741,65742,65743,65744,65745,65746,65747,65748,65749,65750,65751,65752,65753,65754,65755,65756,65757,65758,65759,65760,65761,65762,65763,65764,65765,65766,65767,65768,65769,65770,65771,65772,65773,65774,65775,65776,65777,65778,65779,65780,65781,65782,65783,65784,65785,65786,66176,66177,66178,66179,66180,66181,66182,66183,66184,66185,66186,66187,66188,66189,66190,66191,66192,66193,66194,66195,66196,66197,66198,66199,66200,66201,66202,66203,66204,66208,66209,66210,66211,66212,66213,66214,66215,66216,66217,66218,66219,66220,66221,66222,66223,66224,66225,66226,66227,66228,66229,66230,66231,66232,66233,66234,66235,66236,66237,66238,66239,66240,66241,66242,66243,66244,66245,66246,66247,66248,66249,66250,66251,66252,66253,66254,66255,66256,66304,66305,66306,66307,66308,66309,66310,66311,66312,66313,66314,66315,66316,66317,66318,66319,66320,66321,66322,66323,66324,66325,66326,66327,66328,66329,66330,66331,66332,66333,66334,66335,66352,66353,66354,66355,66356,66357,66358,66359,66360,66361,66362,66363,66364,66365,66366,66367,66368,66370,66371,66372,66373,66374,66375,66376,66377,66384,66385,66386,66387,66388,66389,66390,66391,66392,66393,66394,66395,66396,66397,66398,66399,66400,66401,66402,66403,66404,66405,66406,66407,66408,66409,66410,66411,66412,66413,66414,66415,66416,66417,66418,66419,66420,66421,66432,66433,66434,66435,66436,66437,66438,66439,66440,66441,66442,66443,66444,66445,66446,66447,66448,66449,66450,66451,66452,66453,66454,66455,66456,66457,66458,66459,66460,66461,66464,66465,66466,66467,66468,66469,66470,66471,66472,66473,66474,66475,66476,66477,66478,66479,66480,66481,66482,66483,66484,66485,66486,66487,66488,66489,66490,66491,66492,66493,66494,66495,66496,66497,66498,66499,66504,66505,66506,66507,66508,66509,66510,66511,66560,66561,66562,66563,66564,66565,66566,66567,66568,66569,66570,66571,66572,66573,66574,66575,66576,66577,66578,66579,66580,66581,66582,66583,66584,66585,66586,66587,66588,66589,66590,66591,66592,66593,66594,66595,66596,66597,66598,66599,66600,66601,66602,66603,66604,66605,66606,66607,66608,66609,66610,66611,66612,66613,66614,66615,66616,66617,66618,66619,66620,66621,66622,66623,66624,66625,66626,66627,66628,66629,66630,66631,66632,66633,66634,66635,66636,66637,66638,66639,66640,66641,66642,66643,66644,66645,66646,66647,66648,66649,66650,66651,66652,66653,66654,66655,66656,66657,66658,66659,66660,66661,66662,66663,66664,66665,66666,66667,66668,66669,66670,66671,66672,66673,66674,66675,66676,66677,66678,66679,66680,66681,66682,66683,66684,66685,66686,66687,66688,66689,66690,66691,66692,66693,66694,66695,66696,66697,66698,66699,66700,66701,66702,66703,66704,66705,66706,66707,66708,66709,66710,66711,66712,66713,66714,66715,66716,66717,66816,66817,66818,66819,66820,66821,66822,66823,66824,66825,66826,66827,66828,66829,66830,66831,66832,66833,66834,66835,66836,66837,66838,66839,66840,66841,66842,66843,66844,66845,66846,66847,66848,66849,66850,66851,66852,66853,66854,66855,66864,66865,66866,66867,66868,66869,66870,66871,66872,66873,66874,66875,66876,66877,66878,66879,66880,66881,66882,66883,66884,66885,66886,66887,66888,66889,66890,66891,66892,66893,66894,66895,66896,66897,66898,66899,66900,66901,66902,66903,66904,66905,66906,66907,66908,66909,66910,66911,66912,66913,66914,66915,67072,67073,67074,67075,67076,67077,67078,67079,67080,67081,67082,67083,67084,67085,67086,67087,67088,67089,67090,67091,67092,67093,67094,67095,67096,67097,67098,67099,67100,67101,67102,67103,67104,67105,67106,67107,67108,67109,67110,67111,67112,67113,67114,67115,67116,67117,67118,67119,67120,67121,67122,67123,67124,67125,67126,67127,67128,67129,67130,67131,67132,67133,67134,67135,67136,67137,67138,67139,67140,67141,67142,67143,67144,67145,67146,67147,67148,67149,67150,67151,67152,67153,67154,67155,67156,67157,67158,67159,67160,67161,67162,67163,67164,67165,67166,67167,67168,67169,67170,67171,67172,67173,67174,67175,67176,67177,67178,67179,67180,67181,67182,67183,67184,67185,67186,67187,67188,67189,67190,67191,67192,67193,67194,67195,67196,67197,67198,67199,67200,67201,67202,67203,67204,67205,67206,67207,67208,67209,67210,67211,67212,67213,67214,67215,67216,67217,67218,67219,67220,67221,67222,67223,67224,67225,67226,67227,67228,67229,67230,67231,67232,67233,67234,67235,67236,67237,67238,67239,67240,67241,67242,67243,67244,67245,67246,67247,67248,67249,67250,67251,67252,67253,67254,67255,67256,67257,67258,67259,67260,67261,67262,67263,67264,67265,67266,67267,67268,67269,67270,67271,67272,67273,67274,67275,67276,67277,67278,67279,67280,67281,67282,67283,67284,67285,67286,67287,67288,67289,67290,67291,67292,67293,67294,67295,67296,67297,67298,67299,67300,67301,67302,67303,67304,67305,67306,67307,67308,67309,67310,67311,67312,67313,67314,67315,67316,67317,67318,67319,67320,67321,67322,67323,67324,67325,67326,67327,67328,67329,67330,67331,67332,67333,67334,67335,67336,67337,67338,67339,67340,67341,67342,67343,67344,67345,67346,67347,67348,67349,67350,67351,67352,67353,67354,67355,67356,67357,67358,67359,67360,67361,67362,67363,67364,67365,67366,67367,67368,67369,67370,67371,67372,67373,67374,67375,67376,67377,67378,67379,67380,67381,67382,67392,67393,67394,67395,67396,67397,67398,67399,67400,67401,67402,67403,67404,67405,67406,67407,67408,67409,67410,67411,67412,67413,67424,67425,67426,67427,67428,67429,67430,67431,67584,67585,67586,67587,67588,67589,67592,67594,67595,67596,67597,67598,67599,67600,67601,67602,67603,67604,67605,67606,67607,67608,67609,67610,67611,67612,67613,67614,67615,67616,67617,67618,67619,67620,67621,67622,67623,67624,67625,67626,67627,67628,67629,67630,67631,67632,67633,67634,67635,67636,67637,67639,67640,67644,67647,67648,67649,67650,67651,67652,67653,67654,67655,67656,67657,67658,67659,67660,67661,67662,67663,67664,67665,67666,67667,67668,67669,67680,67681,67682,67683,67684,67685,67686,67687,67688,67689,67690,67691,67692,67693,67694,67695,67696,67697,67698,67699,67700,67701,67702,67712,67713,67714,67715,67716,67717,67718,67719,67720,67721,67722,67723,67724,67725,67726,67727,67728,67729,67730,67731,67732,67733,67734,67735,67736,67737,67738,67739,67740,67741,67742,67808,67809,67810,67811,67812,67813,67814,67815,67816,67817,67818,67819,67820,67821,67822,67823,67824,67825,67826,67828,67829,67840,67841,67842,67843,67844,67845,67846,67847,67848,67849,67850,67851,67852,67853,67854,67855,67856,67857,67858,67859,67860,67861,67872,67873,67874,67875,67876,67877,67878,67879,67880,67881,67882,67883,67884,67885,67886,67887,67888,67889,67890,67891,67892,67893,67894,67895,67896,67897,67968,67969,67970,67971,67972,67973,67974,67975,67976,67977,67978,67979,67980,67981,67982,67983,67984,67985,67986,67987,67988,67989,67990,67991,67992,67993,67994,67995,67996,67997,67998,67999,68e3,68001,68002,68003,68004,68005,68006,68007,68008,68009,68010,68011,68012,68013,68014,68015,68016,68017,68018,68019,68020,68021,68022,68023,68030,68031,68096,68112,68113,68114,68115,68117,68118,68119,68121,68122,68123,68124,68125,68126,68127,68128,68129,68130,68131,68132,68133,68134,68135,68136,68137,68138,68139,68140,68141,68142,68143,68144,68145,68146,68147,68192,68193,68194,68195,68196,68197,68198,68199,68200,68201,68202,68203,68204,68205,68206,68207,68208,68209,68210,68211,68212,68213,68214,68215,68216,68217,68218,68219,68220,68224,68225,68226,68227,68228,68229,68230,68231,68232,68233,68234,68235,68236,68237,68238,68239,68240,68241,68242,68243,68244,68245,68246,68247,68248,68249,68250,68251,68252,68288,68289,68290,68291,68292,68293,68294,68295,68297,68298,68299,68300,68301,68302,68303,68304,68305,68306,68307,68308,68309,68310,68311,68312,68313,68314,68315,68316,68317,68318,68319,68320,68321,68322,68323,68324,68352,68353,68354,68355,68356,68357,68358,68359,68360,68361,68362,68363,68364,68365,68366,68367,68368,68369,68370,68371,68372,68373,68374,68375,68376,68377,68378,68379,68380,68381,68382,68383,68384,68385,68386,68387,68388,68389,68390,68391,68392,68393,68394,68395,68396,68397,68398,68399,68400,68401,68402,68403,68404,68405,68416,68417,68418,68419,68420,68421,68422,68423,68424,68425,68426,68427,68428,68429,68430,68431,68432,68433,68434,68435,68436,68437,68448,68449,68450,68451,68452,68453,68454,68455,68456,68457,68458,68459,68460,68461,68462,68463,68464,68465,68466,68480,68481,68482,68483,68484,68485,68486,68487,68488,68489,68490,68491,68492,68493,68494,68495,68496,68497,68608,68609,68610,68611,68612,68613,68614,68615,68616,68617,68618,68619,68620,68621,68622,68623,68624,68625,68626,68627,68628,68629,68630,68631,68632,68633,68634,68635,68636,68637,68638,68639,68640,68641,68642,68643,68644,68645,68646,68647,68648,68649,68650,68651,68652,68653,68654,68655,68656,68657,68658,68659,68660,68661,68662,68663,68664,68665,68666,68667,68668,68669,68670,68671,68672,68673,68674,68675,68676,68677,68678,68679,68680,68736,68737,68738,68739,68740,68741,68742,68743,68744,68745,68746,68747,68748,68749,68750,68751,68752,68753,68754,68755,68756,68757,68758,68759,68760,68761,68762,68763,68764,68765,68766,68767,68768,68769,68770,68771,68772,68773,68774,68775,68776,68777,68778,68779,68780,68781,68782,68783,68784,68785,68786,68800,68801,68802,68803,68804,68805,68806,68807,68808,68809,68810,68811,68812,68813,68814,68815,68816,68817,68818,68819,68820,68821,68822,68823,68824,68825,68826,68827,68828,68829,68830,68831,68832,68833,68834,68835,68836,68837,68838,68839,68840,68841,68842,68843,68844,68845,68846,68847,68848,68849,68850,69635,69636,69637,69638,69639,69640,69641,69642,69643,69644,69645,69646,69647,69648,69649,69650,69651,69652,69653,69654,69655,69656,69657,69658,69659,69660,69661,69662,69663,69664,69665,69666,69667,69668,69669,69670,69671,69672,69673,69674,69675,69676,69677,69678,69679,69680,69681,69682,69683,69684,69685,69686,69687,69763,69764,69765,69766,69767,69768,69769,69770,69771,69772,69773,69774,69775,69776,69777,69778,69779,69780,69781,69782,69783,69784,69785,69786,69787,69788,69789,69790,69791,69792,69793,69794,69795,69796,69797,69798,69799,69800,69801,69802,69803,69804,69805,69806,69807,69840,69841,69842,69843,69844,69845,69846,69847,69848,69849,69850,69851,69852,69853,69854,69855,69856,69857,69858,69859,69860,69861,69862,69863,69864,69891,69892,69893,69894,69895,69896,69897,69898,69899,69900,69901,69902,69903,69904,69905,69906,69907,69908,69909,69910,69911,69912,69913,69914,69915,69916,69917,69918,69919,69920,69921,69922,69923,69924,69925,69926,69968,69969,69970,69971,69972,69973,69974,69975,69976,69977,69978,69979,69980,69981,69982,69983,69984,69985,69986,69987,69988,69989,69990,69991,69992,69993,69994,69995,69996,69997,69998,69999,7e4,70001,70002,70006,70019,70020,70021,70022,70023,70024,70025,70026,70027,70028,70029,70030,70031,70032,70033,70034,70035,70036,70037,70038,70039,70040,70041,70042,70043,70044,70045,70046,70047,70048,70049,70050,70051,70052,70053,70054,70055,70056,70057,70058,70059,70060,70061,70062,70063,70064,70065,70066,70081,70082,70083,70084,70106,70108,70144,70145,70146,70147,70148,70149,70150,70151,70152,70153,70154,70155,70156,70157,70158,70159,70160,70161,70163,70164,70165,70166,70167,70168,70169,70170,70171,70172,70173,70174,70175,70176,70177,70178,70179,70180,70181,70182,70183,70184,70185,70186,70187,70272,70273,70274,70275,70276,70277,70278,70280,70282,70283,70284,70285,70287,70288,70289,70290,70291,70292,70293,70294,70295,70296,70297,70298,70299,70300,70301,70303,70304,70305,70306,70307,70308,70309,70310,70311,70312,70320,70321,70322,70323,70324,70325,70326,70327,70328,70329,70330,70331,70332,70333,70334,70335,70336,70337,70338,70339,70340,70341,70342,70343,70344,70345,70346,70347,70348,70349,70350,70351,70352,70353,70354,70355,70356,70357,70358,70359,70360,70361,70362,70363,70364,70365,70366,70405,70406,70407,70408,70409,70410,70411,70412,70415,70416,70419,70420,70421,70422,70423,70424,70425,70426,70427,70428,70429,70430,70431,70432,70433,70434,70435,70436,70437,70438,70439,70440,70442,70443,70444,70445,70446,70447,70448,70450,70451,70453,70454,70455,70456,70457,70461,70480,70493,70494,70495,70496,70497,70784,70785,70786,70787,70788,70789,70790,70791,70792,70793,70794,70795,70796,70797,70798,70799,70800,70801,70802,70803,70804,70805,70806,70807,70808,70809,70810,70811,70812,70813,70814,70815,70816,70817,70818,70819,70820,70821,70822,70823,70824,70825,70826,70827,70828,70829,70830,70831,70852,70853,70855,71040,71041,71042,71043,71044,71045,71046,71047,71048,71049,71050,71051,71052,71053,71054,71055,71056,71057,71058,71059,71060,71061,71062,71063,71064,71065,71066,71067,71068,71069,71070,71071,71072,71073,71074,71075,71076,71077,71078,71079,71080,71081,71082,71083,71084,71085,71086,71128,71129,71130,71131,71168,71169,71170,71171,71172,71173,71174,71175,71176,71177,71178,71179,71180,71181,71182,71183,71184,71185,71186,71187,71188,71189,71190,71191,71192,71193,71194,71195,71196,71197,71198,71199,71200,71201,71202,71203,71204,71205,71206,71207,71208,71209,71210,71211,71212,71213,71214,71215,71236,71296,71297,71298,71299,71300,71301,71302,71303,71304,71305,71306,71307,71308,71309,71310,71311,71312,71313,71314,71315,71316,71317,71318,71319,71320,71321,71322,71323,71324,71325,71326,71327,71328,71329,71330,71331,71332,71333,71334,71335,71336,71337,71338,71424,71425,71426,71427,71428,71429,71430,71431,71432,71433,71434,71435,71436,71437,71438,71439,71440,71441,71442,71443,71444,71445,71446,71447,71448,71449,71840,71841,71842,71843,71844,71845,71846,71847,71848,71849,71850,71851,71852,71853,71854,71855,71856,71857,71858,71859,71860,71861,71862,71863,71864,71865,71866,71867,71868,71869,71870,71871,71872,71873,71874,71875,71876,71877,71878,71879,71880,71881,71882,71883,71884,71885,71886,71887,71888,71889,71890,71891,71892,71893,71894,71895,71896,71897,71898,71899,71900,71901,71902,71903,71935,72384,72385,72386,72387,72388,72389,72390,72391,72392,72393,72394,72395,72396,72397,72398,72399,72400,72401,72402,72403,72404,72405,72406,72407,72408,72409,72410,72411,72412,72413,72414,72415,72416,72417,72418,72419,72420,72421,72422,72423,72424,72425,72426,72427,72428,72429,72430,72431,72432,72433,72434,72435,72436,72437,72438,72439,72440,73728,73729,73730,73731,73732,73733,73734,73735,73736,73737,73738,73739,73740,73741,73742,73743,73744,73745,73746,73747,73748,73749,73750,73751,73752,73753,73754,73755,73756,73757,73758,73759,73760,73761,73762,73763,73764,73765,73766,73767,73768,73769,73770,73771,73772,73773,73774,73775,73776,73777,73778,73779,73780,73781,73782,73783,73784,73785,73786,73787,73788,73789,73790,73791,73792,73793,73794,73795,73796,73797,73798,73799,73800,73801,73802,73803,73804,73805,73806,73807,73808,73809,73810,73811,73812,73813,73814,73815,73816,73817,73818,73819,73820,73821,73822,73823,73824,73825,73826,73827,73828,73829,73830,73831,73832,73833,73834,73835,73836,73837,73838,73839,73840,73841,73842,73843,73844,73845,73846,73847,73848,73849,73850,73851,73852,73853,73854,73855,73856,73857,73858,73859,73860,73861,73862,73863,73864,73865,73866,73867,73868,73869,73870,73871,73872,73873,73874,73875,73876,73877,73878,73879,73880,73881,73882,73883,73884,73885,73886,73887,73888,73889,73890,73891,73892,73893,73894,73895,73896,73897,73898,73899,73900,73901,73902,73903,73904,73905,73906,73907,73908,73909,73910,73911,73912,73913,73914,73915,73916,73917,73918,73919,73920,73921,73922,73923,73924,73925,73926,73927,73928,73929,73930,73931,73932,73933,73934,73935,73936,73937,73938,73939,73940,73941,73942,73943,73944,73945,73946,73947,73948,73949,73950,73951,73952,73953,73954,73955,73956,73957,73958,73959,73960,73961,73962,73963,73964,73965,73966,73967,73968,73969,73970,73971,73972,73973,73974,73975,73976,73977,73978,73979,73980,73981,73982,73983,73984,73985,73986,73987,73988,73989,73990,73991,73992,73993,73994,73995,73996,73997,73998,73999,74e3,74001,74002,74003,74004,74005,74006,74007,74008,74009,74010,74011,74012,74013,74014,74015,74016,74017,74018,74019,74020,74021,74022,74023,74024,74025,74026,74027,74028,74029,74030,74031,74032,74033,74034,74035,74036,74037,74038,74039,74040,74041,74042,74043,74044,74045,74046,74047,74048,74049,74050,74051,74052,74053,74054,74055,74056,74057,74058,74059,74060,74061,74062,74063,74064,74065,74066,74067,74068,74069,74070,74071,74072,74073,74074,74075,74076,74077,74078,74079,74080,74081,74082,74083,74084,74085,74086,74087,74088,74089,74090,74091,74092,74093,74094,74095,74096,74097,74098,74099,74100,74101,74102,74103,74104,74105,74106,74107,74108,74109,74110,74111,74112,74113,74114,74115,74116,74117,74118,74119,74120,74121,74122,74123,74124,74125,74126,74127,74128,74129,74130,74131,74132,74133,74134,74135,74136,74137,74138,74139,74140,74141,74142,74143,74144,74145,74146,74147,74148,74149,74150,74151,74152,74153,74154,74155,74156,74157,74158,74159,74160,74161,74162,74163,74164,74165,74166,74167,74168,74169,74170,74171,74172,74173,74174,74175,74176,74177,74178,74179,74180,74181,74182,74183,74184,74185,74186,74187,74188,74189,74190,74191,74192,74193,74194,74195,74196,74197,74198,74199,74200,74201,74202,74203,74204,74205,74206,74207,74208,74209,74210,74211,74212,74213,74214,74215,74216,74217,74218,74219,74220,74221,74222,74223,74224,74225,74226,74227,74228,74229,74230,74231,74232,74233,74234,74235,74236,74237,74238,74239,74240,74241,74242,74243,74244,74245,74246,74247,74248,74249,74250,74251,74252,74253,74254,74255,74256,74257,74258,74259,74260,74261,74262,74263,74264,74265,74266,74267,74268,74269,74270,74271,74272,74273,74274,74275,74276,74277,74278,74279,74280,74281,74282,74283,74284,74285,74286,74287,74288,74289,74290,74291,74292,74293,74294,74295,74296,74297,74298,74299,74300,74301,74302,74303,74304,74305,74306,74307,74308,74309,74310,74311,74312,74313,74314,74315,74316,74317,74318,74319,74320,74321,74322,74323,74324,74325,74326,74327,74328,74329,74330,74331,74332,74333,74334,74335,74336,74337,74338,74339,74340,74341,74342,74343,74344,74345,74346,74347,74348,74349,74350,74351,74352,74353,74354,74355,74356,74357,74358,74359,74360,74361,74362,74363,74364,74365,74366,74367,74368,74369,74370,74371,74372,74373,74374,74375,74376,74377,74378,74379,74380,74381,74382,74383,74384,74385,74386,74387,74388,74389,74390,74391,74392,74393,74394,74395,74396,74397,74398,74399,74400,74401,74402,74403,74404,74405,74406,74407,74408,74409,74410,74411,74412,74413,74414,74415,74416,74417,74418,74419,74420,74421,74422,74423,74424,74425,74426,74427,74428,74429,74430,74431,74432,74433,74434,74435,74436,74437,74438,74439,74440,74441,74442,74443,74444,74445,74446,74447,74448,74449,74450,74451,74452,74453,74454,74455,74456,74457,74458,74459,74460,74461,74462,74463,74464,74465,74466,74467,74468,74469,74470,74471,74472,74473,74474,74475,74476,74477,74478,74479,74480,74481,74482,74483,74484,74485,74486,74487,74488,74489,74490,74491,74492,74493,74494,74495,74496,74497,74498,74499,74500,74501,74502,74503,74504,74505,74506,74507,74508,74509,74510,74511,74512,74513,74514,74515,74516,74517,74518,74519,74520,74521,74522,74523,74524,74525,74526,74527,74528,74529,74530,74531,74532,74533,74534,74535,74536,74537,74538,74539,74540,74541,74542,74543,74544,74545,74546,74547,74548,74549,74550,74551,74552,74553,74554,74555,74556,74557,74558,74559,74560,74561,74562,74563,74564,74565,74566,74567,74568,74569,74570,74571,74572,74573,74574,74575,74576,74577,74578,74579,74580,74581,74582,74583,74584,74585,74586,74587,74588,74589,74590,74591,74592,74593,74594,74595,74596,74597,74598,74599,74600,74601,74602,74603,74604,74605,74606,74607,74608,74609,74610,74611,74612,74613,74614,74615,74616,74617,74618,74619,74620,74621,74622,74623,74624,74625,74626,74627,74628,74629,74630,74631,74632,74633,74634,74635,74636,74637,74638,74639,74640,74641,74642,74643,74644,74645,74646,74647,74648,74649,74880,74881,74882,74883,74884,74885,74886,74887,74888,74889,74890,74891,74892,74893,74894,74895,74896,74897,74898,74899,74900,74901,74902,74903,74904,74905,74906,74907,74908,74909,74910,74911,74912,74913,74914,74915,74916,74917,74918,74919,74920,74921,74922,74923,74924,74925,74926,74927,74928,74929,74930,74931,74932,74933,74934,74935,74936,74937,74938,74939,74940,74941,74942,74943,74944,74945,74946,74947,74948,74949,74950,74951,74952,74953,74954,74955,74956,74957,74958,74959,74960,74961,74962,74963,74964,74965,74966,74967,74968,74969,74970,74971,74972,74973,74974,74975,74976,74977,74978,74979,74980,74981,74982,74983,74984,74985,74986,74987,74988,74989,74990,74991,74992,74993,74994,74995,74996,74997,74998,74999,75e3,75001,75002,75003,75004,75005,75006,75007,75008,75009,75010,75011,75012,75013,75014,75015,75016,75017,75018,75019,75020,75021,75022,75023,75024,75025,75026,75027,75028,75029,75030,75031,75032,75033,75034,75035,75036,75037,75038,75039,75040,75041,75042,75043,75044,75045,75046,75047,75048,75049,75050,75051,75052,75053,75054,75055,75056,75057,75058,75059,75060,75061,75062,75063,75064,75065,75066,75067,75068,75069,75070,75071,75072,75073,75074,75075,77824,77825,77826,77827,77828,77829,77830,77831,77832,77833,77834,77835,77836,77837,77838,77839,77840,77841,77842,77843,77844,77845,77846,77847,77848,77849,77850,77851,77852,77853,77854,77855,77856,77857,77858,77859,77860,77861,77862,77863,77864,77865,77866,77867,77868,77869,77870,77871,77872,77873,77874,77875,77876,77877,77878,77879,77880,77881,77882,77883,77884,77885,77886,77887,77888,77889,77890,77891,77892,77893,77894,77895,77896,77897,77898,77899,77900,77901,77902,77903,77904,77905,77906,77907,77908,77909,77910,77911,77912,77913,77914,77915,77916,77917,77918,77919,77920,77921,77922,77923,77924,77925,77926,77927,77928,77929,77930,77931,77932,77933,77934,77935,77936,77937,77938,77939,77940,77941,77942,77943,77944,77945,77946,77947,77948,77949,77950,77951,77952,77953,77954,77955,77956,77957,77958,77959,77960,77961,77962,77963,77964,77965,77966,77967,77968,77969,77970,77971,77972,77973,77974,77975,77976,77977,77978,77979,77980,77981,77982,77983,77984,77985,77986,77987,77988,77989,77990,77991,77992,77993,77994,77995,77996,77997,77998,77999,78e3,78001,78002,78003,78004,78005,78006,78007,78008,78009,78010,78011,78012,78013,78014,78015,78016,78017,78018,78019,78020,78021,78022,78023,78024,78025,78026,78027,78028,78029,78030,78031,78032,78033,78034,78035,78036,78037,78038,78039,78040,78041,78042,78043,78044,78045,78046,78047,78048,78049,78050,78051,78052,78053,78054,78055,78056,78057,78058,78059,78060,78061,78062,78063,78064,78065,78066,78067,78068,78069,78070,78071,78072,78073,78074,78075,78076,78077,78078,78079,78080,78081,78082,78083,78084,78085,78086,78087,78088,78089,78090,78091,78092,78093,78094,78095,78096,78097,78098,78099,78100,78101,78102,78103,78104,78105,78106,78107,78108,78109,78110,78111,78112,78113,78114,78115,78116,78117,78118,78119,78120,78121,78122,78123,78124,78125,78126,78127,78128,78129,78130,78131,78132,78133,78134,78135,78136,78137,78138,78139,78140,78141,78142,78143,78144,78145,78146,78147,78148,78149,78150,78151,78152,78153,78154,78155,78156,78157,78158,78159,78160,78161,78162,78163,78164,78165,78166,78167,78168,78169,78170,78171,78172,78173,78174,78175,78176,78177,78178,78179,78180,78181,78182,78183,78184,78185,78186,78187,78188,78189,78190,78191,78192,78193,78194,78195,78196,78197,78198,78199,78200,78201,78202,78203,78204,78205,78206,78207,78208,78209,78210,78211,78212,78213,78214,78215,78216,78217,78218,78219,78220,78221,78222,78223,78224,78225,78226,78227,78228,78229,78230,78231,78232,78233,78234,78235,78236,78237,78238,78239,78240,78241,78242,78243,78244,78245,78246,78247,78248,78249,78250,78251,78252,78253,78254,78255,78256,78257,78258,78259,78260,78261,78262,78263,78264,78265,78266,78267,78268,78269,78270,78271,78272,78273,78274,78275,78276,78277,78278,78279,78280,78281,78282,78283,78284,78285,78286,78287,78288,78289,78290,78291,78292,78293,78294,78295,78296,78297,78298,78299,78300,78301,78302,78303,78304,78305,78306,78307,78308,78309,78310,78311,78312,78313,78314,78315,78316,78317,78318,78319,78320,78321,78322,78323,78324,78325,78326,78327,78328,78329,78330,78331,78332,78333,78334,78335,78336,78337,78338,78339,78340,78341,78342,78343,78344,78345,78346,78347,78348,78349,78350,78351,78352,78353,78354,78355,78356,78357,78358,78359,78360,78361,78362,78363,78364,78365,78366,78367,78368,78369,78370,78371,78372,78373,78374,78375,78376,78377,78378,78379,78380,78381,78382,78383,78384,78385,78386,78387,78388,78389,78390,78391,78392,78393,78394,78395,78396,78397,78398,78399,78400,78401,78402,78403,78404,78405,78406,78407,78408,78409,78410,78411,78412,78413,78414,78415,78416,78417,78418,78419,78420,78421,78422,78423,78424,78425,78426,78427,78428,78429,78430,78431,78432,78433,78434,78435,78436,78437,78438,78439,78440,78441,78442,78443,78444,78445,78446,78447,78448,78449,78450,78451,78452,78453,78454,78455,78456,78457,78458,78459,78460,78461,78462,78463,78464,78465,78466,78467,78468,78469,78470,78471,78472,78473,78474,78475,78476,78477,78478,78479,78480,78481,78482,78483,78484,78485,78486,78487,78488,78489,78490,78491,78492,78493,78494,78495,78496,78497,78498,78499,78500,78501,78502,78503,78504,78505,78506,78507,78508,78509,78510,78511,78512,78513,78514,78515,78516,78517,78518,78519,78520,78521,78522,78523,78524,78525,78526,78527,78528,78529,78530,78531,78532,78533,78534,78535,78536,78537,78538,78539,78540,78541,78542,78543,78544,78545,78546,78547,78548,78549,78550,78551,78552,78553,78554,78555,78556,78557,78558,78559,78560,78561,78562,78563,78564,78565,78566,78567,78568,78569,78570,78571,78572,78573,78574,78575,78576,78577,78578,78579,78580,78581,78582,78583,78584,78585,78586,78587,78588,78589,78590,78591,78592,78593,78594,78595,78596,78597,78598,78599,78600,78601,78602,78603,78604,78605,78606,78607,78608,78609,78610,78611,78612,78613,78614,78615,78616,78617,78618,78619,78620,78621,78622,78623,78624,78625,78626,78627,78628,78629,78630,78631,78632,78633,78634,78635,78636,78637,78638,78639,78640,78641,78642,78643,78644,78645,78646,78647,78648,78649,78650,78651,78652,78653,78654,78655,78656,78657,78658,78659,78660,78661,78662,78663,78664,78665,78666,78667,78668,78669,78670,78671,78672,78673,78674,78675,78676,78677,78678,78679,78680,78681,78682,78683,78684,78685,78686,78687,78688,78689,78690,78691,78692,78693,78694,78695,78696,78697,78698,78699,78700,78701,78702,78703,78704,78705,78706,78707,78708,78709,78710,78711,78712,78713,78714,78715,78716,78717,78718,78719,78720,78721,78722,78723,78724,78725,78726,78727,78728,78729,78730,78731,78732,78733,78734,78735,78736,78737,78738,78739,78740,78741,78742,78743,78744,78745,78746,78747,78748,78749,78750,78751,78752,78753,78754,78755,78756,78757,78758,78759,78760,78761,78762,78763,78764,78765,78766,78767,78768,78769,78770,78771,78772,78773,78774,78775,78776,78777,78778,78779,78780,78781,78782,78783,78784,78785,78786,78787,78788,78789,78790,78791,78792,78793,78794,78795,78796,78797,78798,78799,78800,78801,78802,78803,78804,78805,78806,78807,78808,78809,78810,78811,78812,78813,78814,78815,78816,78817,78818,78819,78820,78821,78822,78823,78824,78825,78826,78827,78828,78829,78830,78831,78832,78833,78834,78835,78836,78837,78838,78839,78840,78841,78842,78843,78844,78845,78846,78847,78848,78849,78850,78851,78852,78853,78854,78855,78856,78857,78858,78859,78860,78861,78862,78863,78864,78865,78866,78867,78868,78869,78870,78871,78872,78873,78874,78875,78876,78877,78878,78879,78880,78881,78882,78883,78884,78885,78886,78887,78888,78889,78890,78891,78892,78893,78894,82944,82945,82946,82947,82948,82949,82950,82951,82952,82953,82954,82955,82956,82957,82958,82959,82960,82961,82962,82963,82964,82965,82966,82967,82968,82969,82970,82971,82972,82973,82974,82975,82976,82977,82978,82979,82980,82981,82982,82983,82984,82985,82986,82987,82988,82989,82990,82991,82992,82993,82994,82995,82996,82997,82998,82999,83e3,83001,83002,83003,83004,83005,83006,83007,83008,83009,83010,83011,83012,83013,83014,83015,83016,83017,83018,83019,83020,83021,83022,83023,83024,83025,83026,83027,83028,83029,83030,83031,83032,83033,83034,83035,83036,83037,83038,83039,83040,83041,83042,83043,83044,83045,83046,83047,83048,83049,83050,83051,83052,83053,83054,83055,83056,83057,83058,83059,83060,83061,83062,83063,83064,83065,83066,83067,83068,83069,83070,83071,83072,83073,83074,83075,83076,83077,83078,83079,83080,83081,83082,83083,83084,83085,83086,83087,83088,83089,83090,83091,83092,83093,83094,83095,83096,83097,83098,83099,83100,83101,83102,83103,83104,83105,83106,83107,83108,83109,83110,83111,83112,83113,83114,83115,83116,83117,83118,83119,83120,83121,83122,83123,83124,83125,83126,83127,83128,83129,83130,83131,83132,83133,83134,83135,83136,83137,83138,83139,83140,83141,83142,83143,83144,83145,83146,83147,83148,83149,83150,83151,83152,83153,83154,83155,83156,83157,83158,83159,83160,83161,83162,83163,83164,83165,83166,83167,83168,83169,83170,83171,83172,83173,83174,83175,83176,83177,83178,83179,83180,83181,83182,83183,83184,83185,83186,83187,83188,83189,83190,83191,83192,83193,83194,83195,83196,83197,83198,83199,83200,83201,83202,83203,83204,83205,83206,83207,83208,83209,83210,83211,83212,83213,83214,83215,83216,83217,83218,83219,83220,83221,83222,83223,83224,83225,83226,83227,83228,83229,83230,83231,83232,83233,83234,83235,83236,83237,83238,83239,83240,83241,83242,83243,83244,83245,83246,83247,83248,83249,83250,83251,83252,83253,83254,83255,83256,83257,83258,83259,83260,83261,83262,83263,83264,83265,83266,83267,83268,83269,83270,83271,83272,83273,83274,83275,83276,83277,83278,83279,83280,83281,83282,83283,83284,83285,83286,83287,83288,83289,83290,83291,83292,83293,83294,83295,83296,83297,83298,83299,83300,83301,83302,83303,83304,83305,83306,83307,83308,83309,83310,83311,83312,83313,83314,83315,83316,83317,83318,83319,83320,83321,83322,83323,83324,83325,83326,83327,83328,83329,83330,83331,83332,83333,83334,83335,83336,83337,83338,83339,83340,83341,83342,83343,83344,83345,83346,83347,83348,83349,83350,83351,83352,83353,83354,83355,83356,83357,83358,83359,83360,83361,83362,83363,83364,83365,83366,83367,83368,83369,83370,83371,83372,83373,83374,83375,83376,83377,83378,83379,83380,83381,83382,83383,83384,83385,83386,83387,83388,83389,83390,83391,83392,83393,83394,83395,83396,83397,83398,83399,83400,83401,83402,83403,83404,83405,83406,83407,83408,83409,83410,83411,83412,83413,83414,83415,83416,83417,83418,83419,83420,83421,83422,83423,83424,83425,83426,83427,83428,83429,83430,83431,83432,83433,83434,83435,83436,83437,83438,83439,83440,83441,83442,83443,83444,83445,83446,83447,83448,83449,83450,83451,83452,83453,83454,83455,83456,83457,83458,83459,83460,83461,83462,83463,83464,83465,83466,83467,83468,83469,83470,83471,83472,83473,83474,83475,83476,83477,83478,83479,83480,83481,83482,83483,83484,83485,83486,83487,83488,83489,83490,83491,83492,83493,83494,83495,83496,83497,83498,83499,83500,83501,83502,83503,83504,83505,83506,83507,83508,83509,83510,83511,83512,83513,83514,83515,83516,83517,83518,83519,83520,83521,83522,83523,83524,83525,83526,92160,92161,92162,92163,92164,92165,92166,92167,92168,92169,92170,92171,92172,92173,92174,92175,92176,92177,92178,92179,92180,92181,92182,92183,92184,92185,92186,92187,92188,92189,92190,92191,92192,92193,92194,92195,92196,92197,92198,92199,92200,92201,92202,92203,92204,92205,92206,92207,92208,92209,92210,92211,92212,92213,92214,92215,92216,92217,92218,92219,92220,92221,92222,92223,92224,92225,92226,92227,92228,92229,92230,92231,92232,92233,92234,92235,92236,92237,92238,92239,92240,92241,92242,92243,92244,92245,92246,92247,92248,92249,92250,92251,92252,92253,92254,92255,92256,92257,92258,92259,92260,92261,92262,92263,92264,92265,92266,92267,92268,92269,92270,92271,92272,92273,92274,92275,92276,92277,92278,92279,92280,92281,92282,92283,92284,92285,92286,92287,92288,92289,92290,92291,92292,92293,92294,92295,92296,92297,92298,92299,92300,92301,92302,92303,92304,92305,92306,92307,92308,92309,92310,92311,92312,92313,92314,92315,92316,92317,92318,92319,92320,92321,92322,92323,92324,92325,92326,92327,92328,92329,92330,92331,92332,92333,92334,92335,92336,92337,92338,92339,92340,92341,92342,92343,92344,92345,92346,92347,92348,92349,92350,92351,92352,92353,92354,92355,92356,92357,92358,92359,92360,92361,92362,92363,92364,92365,92366,92367,92368,92369,92370,92371,92372,92373,92374,92375,92376,92377,92378,92379,92380,92381,92382,92383,92384,92385,92386,92387,92388,92389,92390,92391,92392,92393,92394,92395,92396,92397,92398,92399,92400,92401,92402,92403,92404,92405,92406,92407,92408,92409,92410,92411,92412,92413,92414,92415,92416,92417,92418,92419,92420,92421,92422,92423,92424,92425,92426,92427,92428,92429,92430,92431,92432,92433,92434,92435,92436,92437,92438,92439,92440,92441,92442,92443,92444,92445,92446,92447,92448,92449,92450,92451,92452,92453,92454,92455,92456,92457,92458,92459,92460,92461,92462,92463,92464,92465,92466,92467,92468,92469,92470,92471,92472,92473,92474,92475,92476,92477,92478,92479,92480,92481,92482,92483,92484,92485,92486,92487,92488,92489,92490,92491,92492,92493,92494,92495,92496,92497,92498,92499,92500,92501,92502,92503,92504,92505,92506,92507,92508,92509,92510,92511,92512,92513,92514,92515,92516,92517,92518,92519,92520,92521,92522,92523,92524,92525,92526,92527,92528,92529,92530,92531,92532,92533,92534,92535,92536,92537,92538,92539,92540,92541,92542,92543,92544,92545,92546,92547,92548,92549,92550,92551,92552,92553,92554,92555,92556,92557,92558,92559,92560,92561,92562,92563,92564,92565,92566,92567,92568,92569,92570,92571,92572,92573,92574,92575,92576,92577,92578,92579,92580,92581,92582,92583,92584,92585,92586,92587,92588,92589,92590,92591,92592,92593,92594,92595,92596,92597,92598,92599,92600,92601,92602,92603,92604,92605,92606,92607,92608,92609,92610,92611,92612,92613,92614,92615,92616,92617,92618,92619,92620,92621,92622,92623,92624,92625,92626,92627,92628,92629,92630,92631,92632,92633,92634,92635,92636,92637,92638,92639,92640,92641,92642,92643,92644,92645,92646,92647,92648,92649,92650,92651,92652,92653,92654,92655,92656,92657,92658,92659,92660,92661,92662,92663,92664,92665,92666,92667,92668,92669,92670,92671,92672,92673,92674,92675,92676,92677,92678,92679,92680,92681,92682,92683,92684,92685,92686,92687,92688,92689,92690,92691,92692,92693,92694,92695,92696,92697,92698,92699,92700,92701,92702,92703,92704,92705,92706,92707,92708,92709,92710,92711,92712,92713,92714,92715,92716,92717,92718,92719,92720,92721,92722,92723,92724,92725,92726,92727,92728,92736,92737,92738,92739,92740,92741,92742,92743,92744,92745,92746,92747,92748,92749,92750,92751,92752,92753,92754,92755,92756,92757,92758,92759,92760,92761,92762,92763,92764,92765,92766,92880,92881,92882,92883,92884,92885,92886,92887,92888,92889,92890,92891,92892,92893,92894,92895,92896,92897,92898,92899,92900,92901,92902,92903,92904,92905,92906,92907,92908,92909,92928,92929,92930,92931,92932,92933,92934,92935,92936,92937,92938,92939,92940,92941,92942,92943,92944,92945,92946,92947,92948,92949,92950,92951,92952,92953,92954,92955,92956,92957,92958,92959,92960,92961,92962,92963,92964,92965,92966,92967,92968,92969,92970,92971,92972,92973,92974,92975,92992,92993,92994,92995,93027,93028,93029,93030,93031,93032,93033,93034,93035,93036,93037,93038,93039,93040,93041,93042,93043,93044,93045,93046,93047,93053,93054,93055,93056,93057,93058,93059,93060,93061,93062,93063,93064,93065,93066,93067,93068,93069,93070,93071,93952,93953,93954,93955,93956,93957,93958,93959,93960,93961,93962,93963,93964,93965,93966,93967,93968,93969,93970,93971,93972,93973,93974,93975,93976,93977,93978,93979,93980,93981,93982,93983,93984,93985,93986,93987,93988,93989,93990,93991,93992,93993,93994,93995,93996,93997,93998,93999,94e3,94001,94002,94003,94004,94005,94006,94007,94008,94009,94010,94011,94012,94013,94014,94015,94016,94017,94018,94019,94020,94032,94099,94100,94101,94102,94103,94104,94105,94106,94107,94108,94109,94110,94111,110592,110593,113664,113665,113666,113667,113668,113669,113670,113671,113672,113673,113674,113675,113676,113677,113678,113679,113680,113681,113682,113683,113684,113685,113686,113687,113688,113689,113690,113691,113692,113693,113694,113695,113696,113697,113698,113699,113700,113701,113702,113703,113704,113705,113706,113707,113708,113709,113710,113711,113712,113713,113714,113715,113716,113717,113718,113719,113720,113721,113722,113723,113724,113725,113726,113727,113728,113729,113730,113731,113732,113733,113734,113735,113736,113737,113738,113739,113740,113741,113742,113743,113744,113745,113746,113747,113748,113749,113750,113751,113752,113753,113754,113755,113756,113757,113758,113759,113760,113761,113762,113763,113764,113765,113766,113767,113768,113769,113770,113776,113777,113778,113779,113780,113781,113782,113783,113784,113785,113786,113787,113788,113792,113793,113794,113795,113796,113797,113798,113799,113800,113808,113809,113810,113811,113812,113813,113814,113815,113816,113817,119808,119809,119810,119811,119812,119813,119814,119815,119816,119817,119818,119819,119820,119821,119822,119823,119824,119825,119826,119827,119828,119829,119830,119831,119832,119833,119834,119835,119836,119837,119838,119839,119840,119841,119842,119843,119844,119845,119846,119847,119848,119849,119850,119851,119852,119853,119854,119855,119856,119857,119858,119859,119860,119861,119862,119863,119864,119865,119866,119867,119868,119869,119870,119871,119872,119873,119874,119875,119876,119877,119878,119879,119880,119881,119882,119883,119884,119885,119886,119887,119888,119889,119890,119891,119892,119894,119895,119896,119897,119898,119899,119900,119901,119902,119903,119904,119905,119906,119907,119908,119909,119910,119911,119912,119913,119914,119915,119916,119917,119918,119919,119920,119921,119922,119923,119924,119925,119926,119927,119928,119929,119930,119931,119932,119933,119934,119935,119936,119937,119938,119939,119940,119941,119942,119943,119944,119945,119946,119947,119948,119949,119950,119951,119952,119953,119954,119955,119956,119957,119958,119959,119960,119961,119962,119963,119964,119966,119967,119970,119973,119974,119977,119978,119979,119980,119982,119983,119984,119985,119986,119987,119988,119989,119990,119991,119992,119993,119995,119997,119998,119999,12e4,120001,120002,120003,120005,120006,120007,120008,120009,120010,120011,120012,120013,120014,120015,120016,120017,120018,120019,120020,120021,120022,120023,120024,120025,120026,120027,120028,120029,120030,120031,120032,120033,120034,120035,120036,120037,120038,120039,120040,120041,120042,120043,120044,120045,120046,120047,120048,120049,120050,120051,120052,120053,120054,120055,120056,120057,120058,120059,120060,120061,120062,120063,120064,120065,120066,120067,120068,120069,120071,120072,120073,120074,120077,120078,120079,120080,120081,120082,120083,120084,120086,120087,120088,120089,120090,120091,120092,120094,120095,120096,120097,120098,120099,120100,120101,120102,120103,120104,120105,120106,120107,120108,120109,120110,120111,120112,120113,120114,120115,120116,120117,120118,120119,120120,120121,120123,120124,120125,120126,120128,120129,120130,120131,120132,120134,120138,120139,120140,120141,120142,120143,120144,120146,120147,120148,120149,120150,120151,120152,120153,120154,120155,120156,120157,120158,120159,120160,120161,120162,120163,120164,120165,120166,120167,120168,120169,120170,120171,120172,120173,120174,120175,120176,120177,120178,120179,120180,120181,120182,120183,120184,120185,120186,120187,120188,120189,120190,120191,120192,120193,120194,120195,120196,120197,120198,120199,120200,120201,120202,120203,120204,120205,120206,120207,120208,120209,120210,120211,120212,120213,120214,120215,120216,120217,120218,120219,120220,120221,120222,120223,120224,120225,120226,120227,120228,120229,120230,120231,120232,120233,120234,120235,120236,120237,120238,120239,120240,120241,120242,120243,120244,120245,120246,120247,120248,120249,120250,120251,120252,120253,120254,120255,120256,120257,120258,120259,120260,120261,120262,120263,120264,120265,120266,120267,120268,120269,120270,120271,120272,120273,120274,120275,120276,120277,120278,120279,120280,120281,120282,120283,120284,120285,120286,120287,120288,120289,120290,120291,120292,120293,120294,120295,120296,120297,120298,120299,120300,120301,120302,120303,120304,120305,120306,120307,120308,120309,120310,120311,120312,120313,120314,120315,120316,120317,120318,120319,120320,120321,120322,120323,120324,120325,120326,120327,120328,120329,120330,120331,120332,120333,120334,120335,120336,120337,120338,120339,120340,120341,120342,120343,120344,120345,120346,120347,120348,120349,120350,120351,120352,120353,120354,120355,120356,120357,120358,120359,120360,120361,120362,120363,120364,120365,120366,120367,120368,120369,120370,120371,120372,120373,120374,120375,120376,120377,120378,120379,120380,120381,120382,120383,120384,120385,120386,120387,120388,120389,120390,120391,120392,120393,120394,120395,120396,120397,120398,120399,120400,120401,120402,120403,120404,120405,120406,120407,120408,120409,120410,120411,120412,120413,120414,120415,120416,120417,120418,120419,120420,120421,120422,120423,120424,120425,120426,120427,120428,120429,120430,120431,120432,120433,120434,120435,120436,120437,120438,120439,120440,120441,120442,120443,120444,120445,120446,120447,120448,120449,120450,120451,120452,120453,120454,120455,120456,120457,120458,120459,120460,120461,120462,120463,120464,120465,120466,120467,120468,120469,120470,120471,120472,120473,120474,120475,120476,120477,120478,120479,120480,120481,120482,120483,120484,120485,120488,120489,120490,120491,120492,120493,120494,120495,120496,120497,120498,120499,120500,120501,120502,120503,120504,120505,120506,120507,120508,120509,120510,120511,120512,120514,120515,120516,120517,120518,120519,120520,120521,120522,120523,120524,120525,120526,120527,120528,120529,120530,120531,120532,120533,120534,120535,120536,120537,120538,120540,120541,120542,120543,120544,120545,120546,120547,120548,120549,120550,120551,120552,120553,120554,120555,120556,120557,120558,120559,120560,120561,120562,120563,120564,120565,120566,120567,120568,120569,120570,120572,120573,120574,120575,120576,120577,120578,120579,120580,120581,120582,120583,120584,120585,120586,120587,120588,120589,120590,120591,120592,120593,120594,120595,120596,120598,120599,120600,120601,120602,120603,120604,120605,120606,120607,120608,120609,120610,120611,120612,120613,120614,120615,120616,120617,120618,120619,120620,120621,120622,120623,120624,120625,120626,120627,120628,120630,120631,120632,120633,120634,120635,120636,120637,120638,120639,120640,120641,120642,120643,120644,120645,120646,120647,120648,120649,120650,120651,120652,120653,120654,120656,120657,120658,120659,120660,120661,120662,120663,120664,120665,120666,120667,120668,120669,120670,120671,120672,120673,120674,120675,120676,120677,120678,120679,120680,120681,120682,120683,120684,120685,120686,120688,120689,120690,120691,120692,120693,120694,120695,120696,120697,120698,120699,120700,120701,120702,120703,120704,120705,120706,120707,120708,120709,120710,120711,120712,120714,120715,120716,120717,120718,120719,120720,120721,120722,120723,120724,120725,120726,120727,120728,120729,120730,120731,120732,120733,120734,120735,120736,120737,120738,120739,120740,120741,120742,120743,120744,120746,120747,120748,120749,120750,120751,120752,120753,120754,120755,120756,120757,120758,120759,120760,120761,120762,120763,120764,120765,120766,120767,120768,120769,120770,120772,120773,120774,120775,120776,120777,120778,120779,124928,124929,124930,124931,124932,124933,124934,124935,124936,124937,124938,124939,124940,124941,124942,124943,124944,124945,124946,124947,124948,124949,124950,124951,124952,124953,124954,124955,124956,124957,124958,124959,124960,124961,124962,124963,124964,124965,124966,124967,124968,124969,124970,124971,124972,124973,124974,124975,124976,124977,124978,124979,124980,124981,124982,124983,124984,124985,124986,124987,124988,124989,124990,124991,124992,124993,124994,124995,124996,124997,124998,124999,125e3,125001,125002,125003,125004,125005,125006,125007,125008,125009,125010,125011,125012,125013,125014,125015,125016,125017,125018,125019,125020,125021,125022,125023,125024,125025,125026,125027,125028,125029,125030,125031,125032,125033,125034,125035,125036,125037,125038,125039,125040,125041,125042,125043,125044,125045,125046,125047,125048,125049,125050,125051,125052,125053,125054,125055,125056,125057,125058,125059,125060,125061,125062,125063,125064,125065,125066,125067,125068,125069,125070,125071,125072,125073,125074,125075,125076,125077,125078,125079,125080,125081,125082,125083,125084,125085,125086,125087,125088,125089,125090,125091,125092,125093,125094,125095,125096,125097,125098,125099,125100,125101,125102,125103,125104,125105,125106,125107,125108,125109,125110,125111,125112,125113,125114,125115,125116,125117,125118,125119,125120,125121,125122,125123,125124,126464,126465,126466,126467,126469,126470,126471,126472,126473,126474,126475,126476,126477,126478,126479,126480,126481,126482,126483,126484,126485,126486,126487,126488,126489,126490,126491,126492,126493,126494,126495,126497,126498,126500,126503,126505,126506,126507,126508,126509,126510,126511,126512,126513,126514,126516,126517,126518,126519,126521,126523,126530,126535,126537,126539,126541,126542,126543,126545,126546,126548,126551,126553,126555,126557,126559,126561,126562,126564,126567,126568,126569,126570,126572,126573,126574,126575,126576,126577,126578,126580,126581,126582,126583,126585,126586,126587,126588,126590,126592,126593,126594,126595,126596,126597,126598,126599,126600,126601,126603,126604,126605,126606,126607,126608,126609,126610,126611,126612,126613,126614,126615,126616,126617,126618,126619,126625,126626,126627,126629,126630,126631,126632,126633,126635,126636,126637,126638,126639,126640,126641,126642,126643,126644,126645,126646,126647,126648,126649,126650,126651,131072,173782,173824,177972,177984,178205,178208,183969,194560,194561,194562,194563,194564,194565,194566,194567,194568,194569,194570,194571,194572,194573,194574,194575,194576,194577,194578,194579,194580,194581,194582,194583,194584,194585,194586,194587,194588,194589,194590,194591,194592,194593,194594,194595,194596,194597,194598,194599,194600,194601,194602,194603,194604,194605,194606,194607,194608,194609,194610,194611,194612,194613,194614,194615,194616,194617,194618,194619,194620,194621,194622,194623,194624,194625,194626,194627,194628,194629,194630,194631,194632,194633,194634,194635,194636,194637,194638,194639,194640,194641,194642,194643,194644,194645,194646,194647,194648,194649,194650,194651,194652,194653,194654,194655,194656,194657,194658,194659,194660,194661,194662,194663,194664,194665,194666,194667,194668,194669,194670,194671,194672,194673,194674,194675,194676,194677,194678,194679,194680,194681,194682,194683,194684,194685,194686,194687,194688,194689,194690,194691,194692,194693,194694,194695,194696,194697,194698,194699,194700,194701,194702,194703,194704,194705,194706,194707,194708,194709,194710,194711,194712,194713,194714,194715,194716,194717,194718,194719,194720,194721,194722,194723,194724,194725,194726,194727,194728,194729,194730,194731,194732,194733,194734,194735,194736,194737,194738,194739,194740,194741,194742,194743,194744,194745,194746,194747,194748,194749,194750,194751,194752,194753,194754,194755,194756,194757,194758,194759,194760,194761,194762,194763,194764,194765,194766,194767,194768,194769,194770,194771,194772,194773,194774,194775,194776,194777,194778,194779,194780,194781,194782,194783,194784,194785,194786,194787,194788,194789,194790,194791,194792,194793,194794,194795,194796,194797,194798,194799,194800,194801,194802,194803,194804,194805,194806,194807,194808,194809,194810,194811,194812,194813,194814,194815,194816,194817,194818,194819,194820,194821,194822,194823,194824,194825,194826,194827,194828,194829,194830,194831,194832,194833,194834,194835,194836,194837,194838,194839,194840,194841,194842,194843,194844,194845,194846,194847,194848,194849,194850,194851,194852,194853,194854,194855,194856,194857,194858,194859,194860,194861,194862,194863,194864,194865,194866,194867,194868,194869,194870,194871,194872,194873,194874,194875,194876,194877,194878,194879,194880,194881,194882,194883,194884,194885,194886,194887,194888,194889,194890,194891,194892,194893,194894,194895,194896,194897,194898,194899,194900,194901,194902,194903,194904,194905,194906,194907,194908,194909,194910,194911,194912,194913,194914,194915,194916,194917,194918,194919,194920,194921,194922,194923,194924,194925,194926,194927,194928,194929,194930,194931,194932,194933,194934,194935,194936,194937,194938,194939,194940,194941,194942,194943,194944,194945,194946,194947,194948,194949,194950,194951,194952,194953,194954,194955,194956,194957,194958,194959,194960,194961,194962,194963,194964,194965,194966,194967,194968,194969,194970,194971,194972,194973,194974,194975,194976,194977,194978,194979,194980,194981,194982,194983,194984,194985,194986,194987,194988,194989,194990,194991,194992,194993,194994,194995,194996,194997,194998,194999,195e3,195001,195002,195003,195004,195005,195006,195007,195008,195009,195010,195011,195012,195013,195014,195015,195016,195017,195018,195019,195020,195021,195022,195023,195024,195025,195026,195027,195028,195029,195030,195031,195032,195033,195034,195035,195036,195037,195038,195039,195040,195041,195042,195043,195044,195045,195046,195047,195048,195049,195050,195051,195052,195053,195054,195055,195056,195057,195058,195059,195060,195061,195062,195063,195064,195065,195066,195067,195068,195069,195070,195071,195072,195073,195074,195075,195076,195077,195078,195079,195080,195081,195082,195083,195084,195085,195086,195087,195088,195089,195090,195091,195092,195093,195094,195095,195096,195097,195098,195099,195100,195101]},3410:function(e,t,n){var r=n("23e7"),i=n("d039"),o=n("7b0b"),a=n("e163"),s=n("e177"),c=i((function(){a(1)}));r({target:"Object",stat:!0,forced:c,sham:!s},{getPrototypeOf:function(e){return a(o(e))}})},"342f":function(e,t,n){var r=n("d066");e.exports=r("navigator","userAgent")||""},"35a1":function(e,t,n){var r=n("f5df"),i=n("3f8c"),o=n("b622"),a=o("iterator");e.exports=function(e){if(void 0!=e)return e[a]||e["@@iterator"]||i[r(e)]}},"35b3":function(e,t,n){var r=n("23e7");r({target:"Number",stat:!0},{EPSILON:Math.pow(2,-52)})},"37e8":function(e,t,n){var r=n("83ab"),i=n("9bf2"),o=n("825a"),a=n("df75");e.exports=r?Object.defineProperties:function(e,t){o(e);var n,r=a(t),s=r.length,c=0;while(s>c)i.f(e,n=r[c++],t[n]);return e}},"38cf":function(e,t,n){var r=n("23e7"),i=n("1148");r({target:"String",proto:!0},{repeat:i})},"3a7b":function(e,t,n){"use strict";var r=n("ebb5"),i=n("b727").findIndex,o=r.aTypedArray,a=r.exportTypedArrayMethod;a("findIndex",(function(e){return i(o(this),e,arguments.length>1?arguments[1]:void 0)}))},"3bbe":function(e,t,n){var r=n("861d");e.exports=function(e){if(!r(e)&&null!==e)throw TypeError("Can't set "+String(e)+" as a prototype");return e}},"3c5d":function(e,t,n){"use strict";var r=n("ebb5"),i=n("50c4"),o=n("182d"),a=n("7b0b"),s=n("d039"),c=r.aTypedArray,u=r.exportTypedArrayMethod,l=s((function(){new Int8Array(1).set({})}));u("set",(function(e){c(this);var t=o(arguments.length>1?arguments[1]:void 0,1),n=this.length,r=a(e),s=i(r.length),u=0;if(s+t>n)throw RangeError("Wrong length");while(u=n.length?{value:void 0,done:!0}:(e=r(n,i),t.index+=e.length,{value:e,done:!1})}))},"3ea3":function(e,t,n){var r=n("23e7"),i=n("f748"),o=Math.abs,a=Math.pow;r({target:"Math",stat:!0},{cbrt:function(e){return i(e=+e)*a(o(e),1/3)}})},"3f38":function(e,t){e.exports=function(e){var t={variants:[e.COMMENT("--","$"),e.COMMENT("{-","-}",{contains:["self"]})]},n={className:"meta",begin:"{-#",end:"#-}"},r={className:"meta",begin:"^#",end:"$"},i={className:"type",begin:"\\b[A-Z][\\w']*",relevance:0},o={begin:"\\(",end:"\\)",illegal:'"',contains:[n,r,{className:"type",begin:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},e.inherit(e.TITLE_MODE,{begin:"[_a-z][\\w']*"}),t]},a={begin:"{",end:"}",contains:o.contains};return{aliases:["hs"],keywords:"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec",contains:[{beginKeywords:"module",end:"where",keywords:"module where",contains:[o,t],illegal:"\\W\\.|;"},{begin:"\\bimport\\b",end:"$",keywords:"import qualified as hiding",contains:[o,t],illegal:"\\W\\.|;"},{className:"class",begin:"^(\\s*)?(class|instance)\\b",end:"where",keywords:"class family instance where",contains:[i,o,t]},{className:"class",begin:"\\b(data|(new)?type)\\b",end:"$",keywords:"data family type newtype deriving",contains:[n,i,o,a,t]},{beginKeywords:"default",end:"$",contains:[i,o,t]},{beginKeywords:"infix infixl infixr",end:"$",contains:[e.C_NUMBER_MODE,t]},{begin:"\\bforeign\\b",end:"$",keywords:"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe",contains:[i,e.QUOTE_STRING_MODE,t]},{className:"meta",begin:"#!\\/usr\\/bin\\/env runhaskell",end:"$"},n,r,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,i,e.inherit(e.TITLE_MODE,{begin:"^[_a-z][\\w']*"}),t,{begin:"->|<-"}]}}},"3f3a":function(e,t,n){var r=n("23e7"),i=n("83ab"),o=n("825a"),a=n("c04e"),s=n("9bf2"),c=n("d039"),u=c((function(){Reflect.defineProperty(s.f({},1,{value:1}),1,{value:2})}));r({target:"Reflect",stat:!0,forced:u,sham:!i},{defineProperty:function(e,t,n){o(e);var r=a(t,!0);o(n);try{return s.f(e,r,n),!0}catch(i){return!1}}})},"3f8c":function(e,t){e.exports={}},"3fcc":function(e,t,n){"use strict";var r=n("ebb5"),i=n("b727").map,o=n("4840"),a=r.aTypedArray,s=r.aTypedArrayConstructor,c=r.exportTypedArrayMethod;c("map",(function(e){return i(a(this),e,arguments.length>1?arguments[1]:void 0,(function(e,t){return new(s(o(e,e.constructor)))(t)}))}))},4057:function(e,t,n){var r=n("23e7"),i=Math.hypot,o=Math.abs,a=Math.sqrt,s=!!i&&i(1/0,NaN)!==1/0;r({target:"Math",stat:!0,forced:s},{hypot:function(e,t){var n,r,i=0,s=0,c=arguments.length,u=0;while(s0?(r=n/u,i+=r*r):i+=n;return u===1/0?1/0:u*a(i)}})},4069:function(e,t,n){var r=n("44d2");r("flat")},"408a":function(e,t,n){var r=n("c6b6");e.exports=function(e){if("number"!=typeof e&&"Number"!=r(e))throw TypeError("Incorrect invocation");return+e}},"40d9":function(e,t,n){var r=n("23e7"),i=Math.floor,o=Math.log,a=Math.LOG2E;r({target:"Math",stat:!0},{clz32:function(e){return(e>>>=0)?31-i(o(e+.5)*a):32}})},4160:function(e,t,n){"use strict";var r=n("23e7"),i=n("17c2");r({target:"Array",proto:!0,forced:[].forEach!=i},{forEach:i})},"428f":function(e,t,n){var r=n("da84");e.exports=r},4362:function(e,t,n){t.nextTick=function(e){var t=Array.prototype.slice.call(arguments);t.shift(),setTimeout((function(){e.apply(null,t)}),0)},t.platform=t.arch=t.execPath=t.title="browser",t.pid=1,t.browser=!0,t.env={},t.argv=[],t.binding=function(e){throw new Error("No such module. (Possibly not yet loaded)")},function(){var e,r="/";t.cwd=function(){return r},t.chdir=function(t){e||(e=n("df7c")),r=e.resolve(t,r)}}(),t.exit=t.kill=t.umask=t.dlopen=t.uptime=t.memoryUsage=t.uvCounters=function(){},t.features={}},"44ad":function(e,t,n){var r=n("d039"),i=n("c6b6"),o="".split;e.exports=r((function(){return!Object("z").propertyIsEnumerable(0)}))?function(e){return"String"==i(e)?o.call(e,""):Object(e)}:Object},"44d2":function(e,t,n){var r=n("b622"),i=n("7c73"),o=n("9bf2"),a=r("unscopables"),s=Array.prototype;void 0==s[a]&&o.f(s,a,{configurable:!0,value:i(null)}),e.exports=function(e){s[a][e]=!0}},"44de":function(e,t,n){var r=n("da84");e.exports=function(e,t){var n=r.console;n&&n.error&&(1===arguments.length?n.error(e):n.error(e,t))}},"44e7":function(e,t,n){var r=n("861d"),i=n("c6b6"),o=n("b622"),a=o("match");e.exports=function(e){var t;return r(e)&&(void 0!==(t=e[a])?!!t:"RegExp"==i(e))}},"45fc":function(e,t,n){"use strict";var r=n("23e7"),i=n("b727").some,o=n("a640"),a=o("some");r({target:"Array",proto:!0,forced:!a},{some:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0)}})},"466d":function(e,t,n){"use strict";var r=n("d784"),i=n("825a"),o=n("50c4"),a=n("1d80"),s=n("8aa5"),c=n("14c3");r("match",1,(function(e,t,n){return[function(t){var n=a(this),r=void 0==t?void 0:t[e];return void 0!==r?r.call(t,n):new RegExp(t)[e](String(n))},function(e){var r=n(t,e,this);if(r.done)return r.value;var a=i(e),u=String(this);if(!a.global)return c(a,u);var l=a.unicode;a.lastIndex=0;var f,d=[],p=0;while(null!==(f=c(a,u))){var h=String(f[0]);d[p]=h,""===h&&(a.lastIndex=s(u,o(a.lastIndex),l)),p++}return 0===p?null:d}]}))},4776:function(e,t,n){!function(t,n){e.exports=n()}(0,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=4)}([function(e,t,n){},function(e,t,n){var r=n(2);e.exports=p,e.exports.parse=o,e.exports.compile=function(e,t){return s(o(e,t))},e.exports.tokensToFunction=s,e.exports.tokensToRegExp=d;var i=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function o(e,t){for(var n,r=[],o=0,a=0,s="",l=t&&t.delimiter||"/";null!=(n=i.exec(e));){var f=n[0],d=n[1],p=n.index;if(s+=e.slice(a,p),a=p+f.length,d)s+=d[1];else{var h=e[a],v=n[2],g=n[3],b=n[4],m=n[5],y=n[6],w=n[7];s&&(r.push(s),s="");var _=null!=v&&null!=h&&h!==v,x="+"===y||"*"===y,E="?"===y||"*"===y,S=n[2]||l,A=b||m;r.push({name:g||o++,prefix:v||"",delimiter:S,optional:E,repeat:x,partial:_,asterisk:!!w,pattern:A?u(A):w?".*":"[^"+c(S)+"]+?"})}}return a0)}},watch:{$route:function(){var e=this;setTimeout((function(){e.item.header||e.item.component||e.initState()}),1)},item:function(e,t){this.emitItemUpdate(e,t)},activeShow:function(){this.itemShow=this.item===this.activeShow}},created:function(){this.item.header||this.item.component||this.initState()},mounted:function(){this.$router||window.addEventListener("hashchange",this.initState)},destroyed:function(){this.$router||window.removeEventListener("hashchange",this.initState)},methods:{isLinkActive:function(e){return this.matchRoute(e)||this.isChildActive(e.child)||this.isAliasActive(e)},isLinkExactActive:function(e){return this.matchExactRoute(e.href)},isChildActive:function(e){var t=this;return!!e&&e.some((function(e){return t.isLinkActive(e)}))},isAliasActive:function(e){if(e.alias){var t=this.$router?this.$route.fullPath:window.location.pathname+window.location.search+window.location.hash;return Array.isArray(e.alias)?e.alias.some((function(e){return i()(e).test(t)})):i()(e.alias).test(t)}return!1},matchRoute:function(e){var t=e.href,n=e.exactPath;if(!t)return!1;if(this.$router){var r=this.$router.resolve(t).route;return n?r.path===this.$route.path:this.matchExactRoute(t)}return n?t===window.location.pathname:this.matchExactRoute(t)},matchExactRoute:function(e){return!!e&&(this.$router?this.$router.resolve(e).route.fullPath===this.$route.fullPath:e===window.location.pathname+window.location.search+window.location.hash)},clickEvent:function(e){this.item.disabled||(this.item.href||e.preventDefault(),this.emitItemClick(e,this.item,this),this.emitMobileItem(e,e.currentTarget.offsetParent),!this.itemHasChild||this.showChild||this.isMobileItem||this.item.href&&!this.exactActive||(this.show=!this.show))},emitMobileItem:function(e,t){var n=this;this.hover||this.isCollapsed&&this.isFirstLevel&&!this.isMobileItem&&(this.$emit("unset-mobile-item",!0),setTimeout((function(){n.mobileItem!==n.item&&n.$emit("set-mobile-item",{item:n.item,itemEl:t}),"click"!==e.type||n.itemHasChild||n.$emit("unset-mobile-item",!1)}),0))},initState:function(){this.initActiveState(),this.initShowState()},initActiveState:function(){this.active=this.isLinkActive(this.item),this.exactActive=this.isLinkExactActive(this.item)},initShowState:function(){this.itemHasChild&&!this.showChild&&(this.showOneChild&&this.active&&!this.show||this.active&&!this.show?this.show=!0:this.showOneChild&&!this.active&&this.show&&(this.show=!1))},mouseOverEvent:function(e){this.item.disabled||(e.stopPropagation(),this.itemHover=!0,this.disableHover||this.emitMobileItem(e,e.currentTarget))},mouseOutEvent:function(e){e.stopPropagation(),this.itemHover=!1},expandEnter:function(e){e.style.height=e.scrollHeight+"px"},expandAfterEnter:function(e){e.style.height="auto"},expandBeforeLeave:function(e){this.isCollapsed&&this.isFirstLevel?e.style.display="none":e.style.height=e.scrollHeight+"px"}},inject:["emitActiveShow","emitItemClick","emitItemUpdate"]},(function(){var e=this,t=e.$createElement,n=e._self._c||t;return e.item.component&&!e.isItemHidden?n(e.item.component,e._b({tag:"component"},"component",e.item.props,!1)):e.item.header&&!e.isItemHidden?n("div",e._b({staticClass:"vsm--header",class:e.item.class},"div",e.item.attributes,!1),[e._v("\n "+e._s(e.item.title)+"\n")]):e.isItemHidden?e._e():n("div",{staticClass:"vsm--item",class:[{"vsm--item_open":e.show}],on:{mouseover:e.mouseOverEvent,mouseout:e.mouseOutEvent}},[n("sidebar-menu-link",{class:e.itemLinkClass,attrs:{item:e.item,attributes:e.item.attributes},nativeOn:{click:function(t){return e.clickEvent(t)}}},[e.item.icon&&!e.isMobileItem?n("sidebar-menu-icon",{attrs:{icon:e.item.icon}}):e._e(),e._v(" "),n("transition",{attrs:{name:"fade-animation",appear:e.isMobileItem}},[e.isCollapsed&&!e.isFirstLevel||!e.isCollapsed||e.isMobileItem?[n("span",{staticClass:"vsm--title"},[e._v(e._s(e.item.title))])]:e._e()],2),e._v(" "),e.isCollapsed&&!e.isFirstLevel||!e.isCollapsed||e.isMobileItem?[e.item.badge?n("sidebar-menu-badge",{attrs:{badge:e.item.badge}}):e._e(),e._v(" "),e.itemHasChild?n("div",{staticClass:"vsm--arrow",class:[{"vsm--arrow_open":e.show},{"vsm--arrow_slot":e.$slots["dropdown-icon"]}]},[e._t("dropdown-icon")],2):e._e()]:e._e()],2),e._v(" "),e.itemHasChild?[e.isCollapsed&&!e.isFirstLevel||!e.isCollapsed||e.isMobileItem?[n("transition",{attrs:{appear:e.isMobileItem,name:"expand"},on:{enter:e.expandEnter,afterEnter:e.expandAfterEnter,beforeLeave:e.expandBeforeLeave}},[e.show?n("div",{staticClass:"vsm--dropdown",class:e.isMobileItem&&"vsm--dropdown_mobile-item",style:e.isMobileItem&&e.mobileItemStyle.dropdown},[n("div",{staticClass:"vsm--list"},e._l(e.item.child,(function(t,r){return n("sidebar-menu-item",{key:r,attrs:{item:t,level:e.level+1,"show-child":e.showChild,rtl:e.rtl,"is-collapsed":e.isCollapsed}},[e._t("dropdown-icon",null,{slot:"dropdown-icon"})],2)})),1)]):e._e()])]:e._e()]:e._e()],2)}),[],!1,null,null,null);f.options.__file="SidebarMenuItem.vue";var d={name:"SidebarMenu",components:{SidebarMenuItem:f.exports},props:{menu:{type:Array,required:!0},collapsed:{type:Boolean,default:!1},width:{type:String,default:"350px"},widthCollapsed:{type:String,default:"50px"},showChild:{type:Boolean,default:!1},theme:{type:String,default:""},showOneChild:{type:Boolean,default:!1},rtl:{type:Boolean,default:!1},relative:{type:Boolean,default:!1},hideToggle:{type:Boolean,default:!1},disableHover:{type:Boolean,default:!1}},data:function(){return{isCollapsed:this.collapsed,mobileItem:null,mobileItemPos:0,mobileItemHeight:0,mobileItemTimeout:null,activeShow:null,parentHeight:0,parentWidth:0,parentOffsetTop:0,parentOffsetLeft:0}},computed:{sidebarWidth:function(){return this.isCollapsed?this.widthCollapsed:this.width},sidebarClass:function(){return[this.isCollapsed?"vsm_collapsed":"vsm_expanded",this.theme?"vsm_"+this.theme:"",this.rtl?"vsm_rtl":"",this.relative?"vsm_relative":""]},mobileItemStyle:function(){return{item:[{position:"absolute"},{top:this.mobileItemPos+"px"},this.rtl?{right:"0px"}:{left:"0px"},this.rtl?{"padding-right":this.sidebarWidth}:{"padding-left":this.sidebarWidth},this.rtl&&{direction:"rtl"},{"z-index":0},{width:this.parentWidth-this.parentOffsetLeft+"px"},{"max-width":this.width}],dropdown:[{position:"absolute"},{top:this.mobileItemHeight+"px"},{width:"100%"},{"max-height":this.parentHeight-(this.mobileItemPos+this.mobileItemHeight)-this.parentOffsetTop+"px"},{"overflow-y":"auto"}],background:[{position:"absolute"},{top:"0px"},{left:"0px"},{right:"0px"},{width:"100%"},{height:this.mobileItemHeight+"px"},{"z-index":-1}]}}},watch:{collapsed:function(e){this.isCollapsed!==this.collapsed&&(this.isCollapsed=e,this.mobileItem=null)}},methods:{onMouseLeave:function(){this.unsetMobileItem(!1,300)},onMouseEnter:function(){this.isCollapsed&&this.mobileItemTimeout&&clearTimeout(this.mobileItemTimeout)},onToggleClick:function(){this.isCollapsed=!this.isCollapsed,this.mobileItem=null,this.$emit("toggle-collapse",this.isCollapsed)},onActiveShow:function(e){this.activeShow=e},onItemClick:function(e,t,n){this.$emit("item-click",e,t,n)},setMobileItem:function(e){var t=e.item,n=e.itemEl;if(this.mobileItem!==t){var r=this.$el.getBoundingClientRect().top,i=n.children[0].getBoundingClientRect(),o=i.top,a=i.height,s=o-r;this.initParentOffsets(),this.mobileItem=t,this.mobileItemPos=s,this.mobileItemHeight=a}},unsetMobileItem:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:800;this.mobileItem&&(this.mobileItemTimeout&&clearTimeout(this.mobileItemTimeout),e?this.mobileItem=null:this.mobileItemTimeout=setTimeout((function(){t.mobileItem=null}),n))},initParentOffsets:function(){var e=this.$el.getBoundingClientRect(),t=e.top,n=e.left,r=e.right,i=this.relative?this.$el.parentElement:document.documentElement;if(this.parentHeight=i.clientHeight,this.parentWidth=i.clientWidth,this.relative){var o=i.getBoundingClientRect(),a=o.top,s=o.left;this.parentOffsetTop=t-(a+i.clientTop),this.parentOffsetLeft=this.rtl?this.parentWidth-r+(s+i.clientLeft):n-(s+i.clientLeft)}else this.parentOffsetTop=t,this.parentOffsetLeft=this.rtl?this.parentWidth-r:n},onItemUpdate:function(e,t){t===this.mobileItem&&(this.mobileItem=e),t===this.activeShow&&(this.activeShow=e)}},provide:function(){return{emitActiveShow:this.onActiveShow,emitItemClick:this.onItemClick,emitItemUpdate:this.onItemUpdate}}},p=(n(3),o(d,(function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"v-sidebar-menu",class:e.sidebarClass,style:[{"max-width":e.sidebarWidth}],on:{mouseleave:e.onMouseLeave,mouseenter:e.onMouseEnter}},[e._t("header"),e._v(" "),n("div",{staticClass:"vsm--scroll-wrapper",style:e.isCollapsed&&[e.rtl?{"margin-left":"-17px"}:{"margin-right":"-17px"}]},[n("div",{staticClass:"vsm--list",style:e.isCollapsed&&{width:e.widthCollapsed}},e._l(e.menu,(function(t,r){return n("sidebar-menu-item",{key:r,attrs:{item:t,"is-collapsed":e.isCollapsed,"active-show":e.activeShow,"show-one-child":e.showOneChild,"show-child":e.showChild,rtl:e.rtl,"mobile-item":e.mobileItem,"disable-hover":e.disableHover},on:{"set-mobile-item":e.setMobileItem,"unset-mobile-item":e.unsetMobileItem}},[e._t("dropdown-icon",null,{slot:"dropdown-icon"})],2)})),1),e._v(" "),e.isCollapsed?n("div",{staticClass:"vsm--mobile-item",style:e.mobileItemStyle.item},[e.mobileItem?n("sidebar-menu-item",{attrs:{item:e.mobileItem,"is-mobile-item":!0,"mobile-item-style":e.mobileItemStyle,"is-collapsed":e.isCollapsed,"show-child":e.showChild,rtl:e.rtl,"disable-hover":e.disableHover}},[e._t("dropdown-icon",null,{slot:"dropdown-icon"})],2):e._e(),e._v(" "),n("transition",{attrs:{name:"slide-animation"}},[e.mobileItem?n("div",{staticClass:"vsm--mobile-bg",style:e.mobileItemStyle.background}):e._e()])],1):e._e()]),e._v(" "),e._t("footer"),e._v(" "),e.hideToggle?e._e():n("button",{staticClass:"vsm--toggle-btn",class:{"vsm--toggle-btn_slot":e.$slots["toggle-icon"]},on:{click:e.onToggleClick}},[e._t("toggle-icon")],2)],2)}),[],!1,null,null,null));p.options.__file="SidebarMenu.vue";var h=p.exports;t.default={install:function(e){e.component("sidebar-menu",h)}}}])}))},4795:function(e,t,n){var r=n("23e7"),i=n("da84"),o=n("342f"),a=[].slice,s=/MSIE .\./.test(o),c=function(e){return function(t,n){var r=arguments.length>2,i=r?a.call(arguments,2):void 0;return e(r?function(){("function"==typeof t?t:Function(t)).apply(this,i)}:t,n)}};r({global:!0,bind:!0,forced:s},{setTimeout:c(i.setTimeout),setInterval:c(i.setInterval)})},4840:function(e,t,n){var r=n("825a"),i=n("1c0b"),o=n("b622"),a=o("species");e.exports=function(e,t){var n,o=r(e).constructor;return void 0===o||void 0==(n=r(o)[a])?t:i(n)}},4930:function(e,t,n){var r=n("2d00"),i=n("d039");e.exports=!!Object.getOwnPropertySymbols&&!i((function(){return!String(Symbol())||!Symbol.sham&&r&&r<41}))},"498a":function(e,t,n){"use strict";var r=n("23e7"),i=n("58a8").trim,o=n("c8d2");r({target:"String",proto:!0,forced:o("trim")},{trim:function(){return i(this)}})},"4a9b":function(e,t,n){var r=n("74e8");r("Float64",(function(e){return function(t,n,r){return e(this,t,n,r)}}))},"4ae1":function(e,t,n){var r=n("23e7"),i=n("d066"),o=n("1c0b"),a=n("825a"),s=n("861d"),c=n("7c73"),u=n("0538"),l=n("d039"),f=i("Reflect","construct"),d=l((function(){function e(){}return!(f((function(){}),[],e)instanceof e)})),p=!l((function(){f((function(){}))})),h=d||p;r({target:"Reflect",stat:!0,forced:h,sham:h},{construct:function(e,t){o(e),a(t);var n=arguments.length<3?e:o(arguments[2]);if(p&&!d)return f(e,t,n);if(e==n){switch(t.length){case 0:return new e;case 1:return new e(t[0]);case 2:return new e(t[0],t[1]);case 3:return new e(t[0],t[1],t[2]);case 4:return new e(t[0],t[1],t[2],t[3])}var r=[null];return r.push.apply(r,t),new(u.apply(e,r))}var i=n.prototype,l=c(s(i)?i:Object.prototype),h=Function.apply.call(e,l,t);return s(h)?h:l}})},"4b90":function(e,t,n){"use strict";const r=n("201b"),i=n("4ba8");e.exports=(e,t,n)=>i(r(e),t||0,n)},"4ba8":function(e,t,n){"use strict";e.exports=(e,t,n)=>{const r="object"===typeof n?Object.assign({indent:" "},n):{indent:n||" "};if(t=void 0===t?1:t,"string"!==typeof e)throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof e}\``);if("number"!==typeof t)throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof t}\``);if("string"!==typeof r.indent)throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof r.indent}\``);if(0===t)return e;const i=r.includeEmptyLines?/^/gm:/^(?!\s*$)/gm;return e.replace(i,r.indent.repeat(t))}},"4c53":function(e,t,n){"use strict";var r=n("23e7"),i=n("857a"),o=n("af03");r({target:"String",proto:!0,forced:o("sub")},{sub:function(){return i(this,"sub","","")}})},"4d63":function(e,t,n){var r=n("83ab"),i=n("da84"),o=n("94ca"),a=n("7156"),s=n("9bf2").f,c=n("241c").f,u=n("44e7"),l=n("ad6d"),f=n("9f7f"),d=n("6eeb"),p=n("d039"),h=n("69f3").enforce,v=n("2626"),g=n("b622"),b=g("match"),m=i.RegExp,y=m.prototype,w=/a/g,_=/a/g,x=new m(w)!==w,E=f.UNSUPPORTED_Y,S=r&&o("RegExp",!x||E||p((function(){return _[b]=!1,m(w)!=w||m(_)==_||"/a/i"!=m(w,"i")})));if(S){var A=function(e,t){var n,r=this instanceof A,i=u(e),o=void 0===t;if(!r&&i&&e.constructor===A&&o)return e;x?i&&!o&&(e=e.source):e instanceof A&&(o&&(t=l.call(e)),e=e.source),E&&(n=!!t&&t.indexOf("y")>-1,n&&(t=t.replace(/y/g,"")));var s=a(x?new m(e,t):m(e,t),r?this:y,A);if(E&&n){var c=h(s);c.sticky=!0}return s},k=function(e){e in A||s(A,e,{configurable:!0,get:function(){return m[e]},set:function(t){m[e]=t}})},O=c(m),C=0;while(O.length>C)k(O[C++]);y.constructor=A,A.prototype=y,d(i,"RegExp",A)}v("RegExp")},"4d64":function(e,t,n){var r=n("fc6a"),i=n("50c4"),o=n("23cb"),a=function(e){return function(t,n,a){var s,c=r(t),u=i(c.length),l=o(a,u);if(e&&n!=n){while(u>l)if(s=c[l++],s!=s)return!0}else for(;u>l;l++)if((e||l in c)&&c[l]===n)return e||l||0;return!e&&-1}};e.exports={includes:a(!0),indexOf:a(!1)}},"4d90":function(e,t,n){"use strict";var r=n("23e7"),i=n("0ccb").start,o=n("9a0c");r({target:"String",proto:!0,forced:o},{padStart:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0)}})},"4dd1":function(e,t){e.exports=function(e){var t={begin:"<>",end:""},n={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/},r="[A-Za-z$_][0-9A-Za-z$_]*",i={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},o={className:"number",variants:[{begin:"\\b(0[bB][01]+)n?"},{begin:"\\b(0[oO][0-7]+)n?"},{begin:e.C_NUMBER_RE+"n?"}],relevance:0},a={className:"subst",begin:"\\$\\{",end:"\\}",keywords:i,contains:[]},s={begin:"html`",end:"",starts:{end:"`",returnEnd:!1,contains:[e.BACKSLASH_ESCAPE,a],subLanguage:"xml"}},c={begin:"css`",end:"",starts:{end:"`",returnEnd:!1,contains:[e.BACKSLASH_ESCAPE,a],subLanguage:"css"}},u={className:"string",begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE,a]};a.contains=[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,s,c,u,o,e.REGEXP_MODE];var l=a.contains.concat([e.C_BLOCK_COMMENT_MODE,e.C_LINE_COMMENT_MODE]);return{aliases:["js","jsx","mjs","cjs"],keywords:i,contains:[{className:"meta",relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},{className:"meta",begin:/^#!/,end:/$/},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,s,c,u,e.C_LINE_COMMENT_MODE,e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+",contains:[{className:"type",begin:"\\{",end:"\\}",relevance:0},{className:"variable",begin:r+"(?=\\s*(-)|$)",endsParent:!0,relevance:0},{begin:/(?=[^\n])\s/,relevance:0}]}]}),e.C_BLOCK_COMMENT_MODE,o,{begin:/[{,\n]\s*/,relevance:0,contains:[{begin:r+"\\s*:",returnBegin:!0,relevance:0,contains:[{className:"attr",begin:r,relevance:0}]}]},{begin:"("+e.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.REGEXP_MODE,{className:"function",begin:"(\\(.*?\\)|"+r+")\\s*=>",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:r},{begin:/\(\s*\)/},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:i,contains:l}]}]},{className:"",begin:/\s/,end:/\s*/,skip:!0},{variants:[{begin:t.begin,end:t.end},{begin:n.begin,end:n.end}],subLanguage:"xml",contains:[{begin:n.begin,end:n.end,skip:!0,contains:["self"]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/\{/,excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{begin:r}),{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,contains:l}],illegal:/\[|%/},{begin:/\$[(.]/},e.METHOD_GUARD,{className:"class",beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"constructor get set",end:/\{/,excludeEnd:!0}],illegal:/#(?!!)/}}},"4de4":function(e,t,n){"use strict";var r=n("23e7"),i=n("b727").filter,o=n("1dde"),a=o("filter");r({target:"Array",proto:!0,forced:!a},{filter:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0)}})},"4df4":function(e,t,n){"use strict";var r=n("0366"),i=n("7b0b"),o=n("9bdd"),a=n("e95a"),s=n("50c4"),c=n("8418"),u=n("35a1");e.exports=function(e){var t,n,l,f,d,p,h=i(e),v="function"==typeof this?this:Array,g=arguments.length,b=g>1?arguments[1]:void 0,m=void 0!==b,y=u(h),w=0;if(m&&(b=r(b,g>2?arguments[2]:void 0,2)),void 0==y||v==Array&&a(y))for(t=s(h.length),n=new v(t);t>w;w++)p=m?b(h[w],w):h[w],c(n,w,p);else for(f=y.call(h),d=f.next,n=new v;!(l=d.call(f)).done;w++)p=m?o(f,b,[l.value,w],!0):l.value,c(n,w,p);return n.length=w,n}},"4e82":function(e,t,n){"use strict";var r=n("23e7"),i=n("1c0b"),o=n("7b0b"),a=n("d039"),s=n("a640"),c=[],u=c.sort,l=a((function(){c.sort(void 0)})),f=a((function(){c.sort(null)})),d=s("sort"),p=l||!f||!d;r({target:"Array",proto:!0,forced:p},{sort:function(e){return void 0===e?u.call(o(this)):u.call(o(this),i(e))}})},"4ec9":function(e,t,n){"use strict";var r=n("6d61"),i=n("6566");e.exports=r("Map",(function(e){return function(){return e(this,arguments.length?arguments[0]:void 0)}}),i)},"4fad":function(e,t,n){var r=n("23e7"),i=n("6f53").entries;r({target:"Object",stat:!0},{entries:function(e){return i(e)}})},"50c4":function(e,t,n){var r=n("a691"),i=Math.min;e.exports=function(e){return e>0?i(r(e),9007199254740991):0}},5121:function(e,t,n){"use strict";e.exports=function(e){var t=e.utils.escapeRE,n=e.utils.arrayReplaceAt,r=" \r\n$+<=>^`|~",i=e.utils.lib.ucmicro.P.source,o=e.utils.lib.ucmicro.Z.source;function a(e,t,n,r){var i,o,a,s,c,u=e.bMarks[t]+e.tShift[t],l=e.eMarks[t];if(u+2>=l)return!1;if(42!==e.src.charCodeAt(u++))return!1;if(91!==e.src.charCodeAt(u++))return!1;for(s=u;u=0;a--)if(m=u[a],"text"===m.type&&(p=0,f=m.content,h.lastIndex=0,d=[],b.test(f))){while(v=h.exec(f))(v.index>0||v[1].length>0)&&(l=new e.Token("text","",0),l.content=f.slice(p,v.index+v[1].length),d.push(l)),l=new e.Token("abbr_open","abbr",1),l.attrs=[["title",e.env.abbreviations[":"+v[2]]]],d.push(l),l=new e.Token("text","",0),l.content=v[2],d.push(l),l=new e.Token("abbr_close","abbr",-1),d.push(l),h.lastIndex-=v[3].length,p=h.lastIndex;d.length&&(p=k&&(A+=m.slice(k,M)+j,k=M+C.length)}return A+m.slice(k)}]}))},5327:function(e,t,n){var r=n("23e7"),i=n("1ec1"),o=Math.acosh,a=Math.log,s=Math.sqrt,c=Math.LN2,u=!o||710!=Math.floor(o(Number.MAX_VALUE))||o(1/0)!=1/0;r({target:"Math",stat:!0,forced:u},{acosh:function(e){return(e=+e)<1?NaN:e>94906265.62425156?a(e)+c:i(e-1+s(e-1)*s(e+1))}})},5377:function(e,t,n){var r=n("83ab"),i=n("9bf2"),o=n("ad6d"),a=n("9f7f").UNSUPPORTED_Y;r&&("g"!=/./g.flags||a)&&i.f(RegExp.prototype,"flags",{configurable:!0,get:o})},"542d":function(e,t,n){"use strict";var r=n("23e7"),i=n("d039"),o=n("408a"),a=1..toPrecision,s=i((function(){return"1"!==a.call(1,void 0)}))||!i((function(){a.call({})}));r({target:"Number",proto:!0,forced:s},{toPrecision:function(e){return void 0===e?a.call(o(this)):a.call(o(this),e)}})},5692:function(e,t,n){var r=n("c430"),i=n("c6cd");(e.exports=function(e,t){return i[e]||(i[e]=void 0!==t?t:{})})("versions",[]).push({version:"3.12.0",mode:r?"pure":"global",copyright:"© 2021 Denis Pushkarev (zloirock.ru)"})},"56ef":function(e,t,n){var r=n("d066"),i=n("241c"),o=n("7418"),a=n("825a");e.exports=r("Reflect","ownKeys")||function(e){var t=i.f(a(e)),n=o.f;return n?t.concat(n(e)):t}},"572f":function(e,t){var n=function(e,t){var n=document.querySelector("#"+e+" > .particles-js-canvas-el");this.pJS={canvas:{el:n,w:n.offsetWidth,h:n.offsetHeight},particles:{number:{value:400,density:{enable:!0,value_area:800}},color:{value:"#fff"},shape:{type:"circle",stroke:{width:0,color:"#ff0000"},polygon:{nb_sides:5},image:{src:"",width:100,height:100}},opacity:{value:1,random:!1,anim:{enable:!1,speed:2,opacity_min:0,sync:!1}},size:{value:20,random:!1,anim:{enable:!1,speed:20,size_min:0,sync:!1}},line_linked:{enable:!0,distance:100,color:"#fff",opacity:1,width:1},move:{enable:!0,speed:2,direction:"none",random:!1,straight:!1,out_mode:"out",bounce:!1,attract:{enable:!1,rotateX:3e3,rotateY:3e3}},array:[]},interactivity:{detect_on:"canvas",events:{onhover:{enable:!0,mode:"grab"},onclick:{enable:!0,mode:"push"},resize:!0},modes:{grab:{distance:100,line_linked:{opacity:1}},bubble:{distance:200,size:80,duration:.4},repulse:{distance:200,duration:.4},push:{particles_nb:4},remove:{particles_nb:2}},mouse:{}},retina_detect:!1,fn:{interact:{},modes:{},vendors:{}},tmp:{}};var a=this.pJS;t&&Object.deepExtend(a,t),a.tmp.obj={size_value:a.particles.size.value,size_anim_speed:a.particles.size.anim.speed,move_speed:a.particles.move.speed,line_linked_distance:a.particles.line_linked.distance,line_linked_width:a.particles.line_linked.width,mode_grab_distance:a.interactivity.modes.grab.distance,mode_bubble_distance:a.interactivity.modes.bubble.distance,mode_bubble_size:a.interactivity.modes.bubble.size,mode_repulse_distance:a.interactivity.modes.repulse.distance},a.fn.retinaInit=function(){a.retina_detect&&window.devicePixelRatio>1?(a.canvas.pxratio=window.devicePixelRatio,a.tmp.retina=!0):(a.canvas.pxratio=1,a.tmp.retina=!1),a.canvas.w=a.canvas.el.offsetWidth*a.canvas.pxratio,a.canvas.h=a.canvas.el.offsetHeight*a.canvas.pxratio,a.particles.size.value=a.tmp.obj.size_value*a.canvas.pxratio,a.particles.size.anim.speed=a.tmp.obj.size_anim_speed*a.canvas.pxratio,a.particles.move.speed=a.tmp.obj.move_speed*a.canvas.pxratio,a.particles.line_linked.distance=a.tmp.obj.line_linked_distance*a.canvas.pxratio,a.interactivity.modes.grab.distance=a.tmp.obj.mode_grab_distance*a.canvas.pxratio,a.interactivity.modes.bubble.distance=a.tmp.obj.mode_bubble_distance*a.canvas.pxratio,a.particles.line_linked.width=a.tmp.obj.line_linked_width*a.canvas.pxratio,a.interactivity.modes.bubble.size=a.tmp.obj.mode_bubble_size*a.canvas.pxratio,a.interactivity.modes.repulse.distance=a.tmp.obj.mode_repulse_distance*a.canvas.pxratio},a.fn.canvasInit=function(){a.canvas.ctx=a.canvas.el.getContext("2d")},a.fn.canvasSize=function(){a.canvas.el.width=a.canvas.w,a.canvas.el.height=a.canvas.h,a&&a.interactivity.events.resize&&window.addEventListener("resize",(function(){a.canvas.w=a.canvas.el.offsetWidth,a.canvas.h=a.canvas.el.offsetHeight,a.tmp.retina&&(a.canvas.w*=a.canvas.pxratio,a.canvas.h*=a.canvas.pxratio),a.canvas.el.width=a.canvas.w,a.canvas.el.height=a.canvas.h,a.particles.move.enable||(a.fn.particlesEmpty(),a.fn.particlesCreate(),a.fn.particlesDraw(),a.fn.vendors.densityAutoParticles()),a.fn.vendors.densityAutoParticles()}))},a.fn.canvasPaint=function(){a.canvas.ctx.fillRect(0,0,a.canvas.w,a.canvas.h)},a.fn.canvasClear=function(){a.canvas.ctx.clearRect(0,0,a.canvas.w,a.canvas.h)},a.fn.particle=function(e,t,n){if(this.radius=(a.particles.size.random?Math.random():1)*a.particles.size.value,a.particles.size.anim.enable&&(this.size_status=!1,this.vs=a.particles.size.anim.speed/100,a.particles.size.anim.sync||(this.vs=this.vs*Math.random())),this.x=n?n.x:Math.random()*a.canvas.w,this.y=n?n.y:Math.random()*a.canvas.h,this.x>a.canvas.w-2*this.radius?this.x=this.x-this.radius:this.x<2*this.radius&&(this.x=this.x+this.radius),this.y>a.canvas.h-2*this.radius?this.y=this.y-this.radius:this.y<2*this.radius&&(this.y=this.y+this.radius),a.particles.move.bounce&&a.fn.vendors.checkOverlap(this,n),this.color={},"object"==typeof e.value)if(e.value instanceof Array){var i=e.value[Math.floor(Math.random()*a.particles.color.value.length)];this.color.rgb=r(i)}else void 0!=e.value.r&&void 0!=e.value.g&&void 0!=e.value.b&&(this.color.rgb={r:e.value.r,g:e.value.g,b:e.value.b}),void 0!=e.value.h&&void 0!=e.value.s&&void 0!=e.value.l&&(this.color.hsl={h:e.value.h,s:e.value.s,l:e.value.l});else"random"==e.value?this.color.rgb={r:Math.floor(256*Math.random())+0,g:Math.floor(256*Math.random())+0,b:Math.floor(256*Math.random())+0}:"string"==typeof e.value&&(this.color=e,this.color.rgb=r(this.color.value));this.opacity=(a.particles.opacity.random?Math.random():1)*a.particles.opacity.value,a.particles.opacity.anim.enable&&(this.opacity_status=!1,this.vo=a.particles.opacity.anim.speed/100,a.particles.opacity.anim.sync||(this.vo=this.vo*Math.random()));var o={};switch(a.particles.move.direction){case"top":o={x:0,y:-1};break;case"top-right":o={x:.5,y:-.5};break;case"right":o={x:1,y:-0};break;case"bottom-right":o={x:.5,y:.5};break;case"bottom":o={x:0,y:1};break;case"bottom-left":o={x:-.5,y:1};break;case"left":o={x:-1,y:0};break;case"top-left":o={x:-.5,y:-.5};break;default:o={x:0,y:0};break}a.particles.move.straight?(this.vx=o.x,this.vy=o.y,a.particles.move.random&&(this.vx=this.vx*Math.random(),this.vy=this.vy*Math.random())):(this.vx=o.x+Math.random()-.5,this.vy=o.y+Math.random()-.5),this.vx_i=this.vx,this.vy_i=this.vy;var s=a.particles.shape.type;if("object"==typeof s){if(s instanceof Array){var c=s[Math.floor(Math.random()*s.length)];this.shape=c}}else this.shape=s;if("image"==this.shape){var u=a.particles.shape;this.img={src:u.image.src,ratio:u.image.width/u.image.height},this.img.ratio||(this.img.ratio=1),"svg"==a.tmp.img_type&&void 0!=a.tmp.source_svg&&(a.fn.vendors.createSvgImg(this),a.tmp.pushing&&(this.img.loaded=!1))}},a.fn.particle.prototype.draw=function(){var e=this;if(void 0!=e.radius_bubble)var t=e.radius_bubble;else t=e.radius;if(void 0!=e.opacity_bubble)var n=e.opacity_bubble;else n=e.opacity;if(e.color.rgb)var r="rgba("+e.color.rgb.r+","+e.color.rgb.g+","+e.color.rgb.b+","+n+")";else r="hsla("+e.color.hsl.h+","+e.color.hsl.s+"%,"+e.color.hsl.l+"%,"+n+")";switch(a.canvas.ctx.fillStyle=r,a.canvas.ctx.beginPath(),e.shape){case"circle":a.canvas.ctx.arc(e.x,e.y,t,0,2*Math.PI,!1);break;case"edge":a.canvas.ctx.rect(e.x-t,e.y-t,2*t,2*t);break;case"triangle":a.fn.vendors.drawShape(a.canvas.ctx,e.x-t,e.y+t/1.66,2*t,3,2);break;case"polygon":a.fn.vendors.drawShape(a.canvas.ctx,e.x-t/(a.particles.shape.polygon.nb_sides/3.5),e.y-t/.76,2.66*t/(a.particles.shape.polygon.nb_sides/3),a.particles.shape.polygon.nb_sides,1);break;case"star":a.fn.vendors.drawShape(a.canvas.ctx,e.x-2*t/(a.particles.shape.polygon.nb_sides/4),e.y-t/1.52,2*t*2.66/(a.particles.shape.polygon.nb_sides/3),a.particles.shape.polygon.nb_sides,2);break;case"image":function i(){a.canvas.ctx.drawImage(o,e.x-t,e.y-t,2*t,2*t/e.img.ratio)}if("svg"==a.tmp.img_type)var o=e.img.obj;else o=a.tmp.img_obj;o&&i();break}a.canvas.ctx.closePath(),a.particles.shape.stroke.width>0&&(a.canvas.ctx.strokeStyle=a.particles.shape.stroke.color,a.canvas.ctx.lineWidth=a.particles.shape.stroke.width,a.canvas.ctx.stroke()),a.canvas.ctx.fill()},a.fn.particlesCreate=function(){for(var e=0;e=a.particles.opacity.value&&(t.opacity_status=!1),t.opacity+=t.vo):(t.opacity<=a.particles.opacity.anim.opacity_min&&(t.opacity_status=!0),t.opacity-=t.vo),t.opacity<0&&(t.opacity=0)),a.particles.size.anim.enable&&(1==t.size_status?(t.radius>=a.particles.size.value&&(t.size_status=!1),t.radius+=t.vs):(t.radius<=a.particles.size.anim.size_min&&(t.size_status=!0),t.radius-=t.vs),t.radius<0&&(t.radius=0)),"bounce"==a.particles.move.out_mode)var r={x_left:t.radius,x_right:a.canvas.w,y_top:t.radius,y_bottom:a.canvas.h};else r={x_left:-t.radius,x_right:a.canvas.w+t.radius,y_top:-t.radius,y_bottom:a.canvas.h+t.radius};switch(t.x-t.radius>a.canvas.w?(t.x=r.x_left,t.y=Math.random()*a.canvas.h):t.x+t.radius<0&&(t.x=r.x_right,t.y=Math.random()*a.canvas.h),t.y-t.radius>a.canvas.h?(t.y=r.y_top,t.x=Math.random()*a.canvas.w):t.y+t.radius<0&&(t.y=r.y_bottom,t.x=Math.random()*a.canvas.w),a.particles.move.out_mode){case"bounce":(t.x+t.radius>a.canvas.w||t.x-t.radius<0)&&(t.vx=-t.vx),(t.y+t.radius>a.canvas.h||t.y-t.radius<0)&&(t.vy=-t.vy);break}if(o("grab",a.interactivity.events.onhover.mode)&&a.fn.modes.grabParticle(t),(o("bubble",a.interactivity.events.onhover.mode)||o("bubble",a.interactivity.events.onclick.mode))&&a.fn.modes.bubbleParticle(t),(o("repulse",a.interactivity.events.onhover.mode)||o("repulse",a.interactivity.events.onclick.mode))&&a.fn.modes.repulseParticle(t),a.particles.line_linked.enable||a.particles.move.attract.enable)for(var i=e+1;i0){var s=a.particles.line_linked.color_rgb_line;a.canvas.ctx.strokeStyle="rgba("+s.r+","+s.g+","+s.b+","+o+")",a.canvas.ctx.lineWidth=a.particles.line_linked.width,a.canvas.ctx.beginPath(),a.canvas.ctx.moveTo(e.x,e.y),a.canvas.ctx.lineTo(t.x,t.y),a.canvas.ctx.stroke(),a.canvas.ctx.closePath()}}},a.fn.interact.attractParticles=function(e,t){var n=e.x-t.x,r=e.y-t.y,i=Math.sqrt(n*n+r*r);if(i<=a.particles.line_linked.distance){var o=n/(1e3*a.particles.move.attract.rotateX),s=r/(1e3*a.particles.move.attract.rotateY);e.vx-=o,e.vy-=s,t.vx+=o,t.vy+=s}},a.fn.interact.bounceParticles=function(e,t){var n=e.x-t.x,r=e.y-t.y,i=Math.sqrt(n*n+r*r),o=e.radius+t.radius;i<=o&&(e.vx=-e.vx,e.vy=-e.vy,t.vx=-t.vx,t.vy=-t.vy)},a.fn.modes.pushParticles=function(e,t){a.tmp.pushing=!0;for(var n=0;n=0&&"mousemove"==a.interactivity.status){if(a.interactivity.modes.bubble.size!=a.particles.size.value)if(a.interactivity.modes.bubble.size>a.particles.size.value){var c=e.radius+a.interactivity.modes.bubble.size*i;c>=0&&(e.radius_bubble=c)}else{var u=e.radius-a.interactivity.modes.bubble.size;c=e.radius-u*i;e.radius_bubble=c>0?c:0}if(a.interactivity.modes.bubble.opacity!=a.particles.opacity.value)if(a.interactivity.modes.bubble.opacity>a.particles.opacity.value){var l=a.interactivity.modes.bubble.opacity*i;l>e.opacity&&l<=a.interactivity.modes.bubble.opacity&&(e.opacity_bubble=l)}else{l=e.opacity-(a.particles.opacity.value-a.interactivity.modes.bubble.opacity)*i;l=a.interactivity.modes.bubble.opacity&&(e.opacity_bubble=l)}}}else s();"mouseleave"==a.interactivity.status&&s()}else if(a.interactivity.events.onclick.enable&&o("bubble",a.interactivity.events.onclick.mode)){if(a.tmp.bubble_clicking){t=e.x-a.interactivity.mouse.click_pos_x,n=e.y-a.interactivity.mouse.click_pos_y,r=Math.sqrt(t*t+n*n);var f=((new Date).getTime()-a.interactivity.mouse.click_time)/1e3;f>a.interactivity.modes.bubble.duration&&(a.tmp.bubble_duration_end=!0),f>2*a.interactivity.modes.bubble.duration&&(a.tmp.bubble_clicking=!1,a.tmp.bubble_duration_end=!1)}function d(t,n,i,o,s){if(t!=n)if(a.tmp.bubble_duration_end){if(void 0!=i){var c=o-f*(o-t)/a.interactivity.modes.bubble.duration,u=t-c;d=t+u,"size"==s&&(e.radius_bubble=d),"opacity"==s&&(e.opacity_bubble=d)}}else if(r<=a.interactivity.modes.bubble.distance){if(void 0!=i)var l=i;else l=o;if(l!=t){var d=o-f*(o-t)/a.interactivity.modes.bubble.duration;"size"==s&&(e.radius_bubble=d),"opacity"==s&&(e.opacity_bubble=d)}}else"size"==s&&(e.radius_bubble=void 0),"opacity"==s&&(e.opacity_bubble=void 0)}a.tmp.bubble_clicking&&(d(a.interactivity.modes.bubble.size,a.particles.size.value,e.radius_bubble,e.radius,"size"),d(a.interactivity.modes.bubble.opacity,a.particles.opacity.value,e.opacity_bubble,e.opacity,"opacity"))}},a.fn.modes.repulseParticle=function(e){if(a.interactivity.events.onhover.enable&&o("repulse",a.interactivity.events.onhover.mode)&&"mousemove"==a.interactivity.status){var t=e.x-a.interactivity.mouse.pos_x,n=e.y-a.interactivity.mouse.pos_y,r=Math.sqrt(t*t+n*n),s={x:t/r,y:n/r},c=a.interactivity.modes.repulse.distance,u=100,l=i(1/c*(-1*Math.pow(r/c,2)+1)*c*u,0,50),f={x:e.x+s.x*l,y:e.y+s.y*l};"bounce"==a.particles.move.out_mode?(f.x-e.radius>0&&f.x+e.radius0&&f.y+e.radiusa.canvas.w||n.x-e.radius<0)&&(e.vx=-e.vx),(n.y+e.radius>a.canvas.h||n.y-e.radius<0)&&(e.vy=-e.vy)}}h<=c&&g()}else 0==a.tmp.repulse_clicking&&(e.vx=e.vx_i,e.vy=e.vy_i)},a.fn.modes.grabParticle=function(e){if(a.interactivity.events.onhover.enable&&"mousemove"==a.interactivity.status){var t=e.x-a.interactivity.mouse.pos_x,n=e.y-a.interactivity.mouse.pos_y,r=Math.sqrt(t*t+n*n);if(r<=a.interactivity.modes.grab.distance){var i=a.interactivity.modes.grab.line_linked.opacity-r/(1/a.interactivity.modes.grab.line_linked.opacity)/a.interactivity.modes.grab.distance;if(i>0){var o=a.particles.line_linked.color_rgb_line;a.canvas.ctx.strokeStyle="rgba("+o.r+","+o.g+","+o.b+","+i+")",a.canvas.ctx.lineWidth=a.particles.line_linked.width,a.canvas.ctx.beginPath(),a.canvas.ctx.moveTo(e.x,e.y),a.canvas.ctx.lineTo(a.interactivity.mouse.pos_x,a.interactivity.mouse.pos_y),a.canvas.ctx.stroke(),a.canvas.ctx.closePath()}}}},a.fn.vendors.eventsListeners=function(){"window"==a.interactivity.detect_on?a.interactivity.el=window:a.interactivity.el=a.canvas.el,(a.interactivity.events.onhover.enable||a.interactivity.events.onclick.enable)&&(a.interactivity.el.addEventListener("mousemove",(function(e){if(a.interactivity.el==window)var t=e.clientX,n=e.clientY;else t=e.offsetX||e.clientX,n=e.offsetY||e.clientY;a.interactivity.mouse.pos_x=t,a.interactivity.mouse.pos_y=n,a.tmp.retina&&(a.interactivity.mouse.pos_x*=a.canvas.pxratio,a.interactivity.mouse.pos_y*=a.canvas.pxratio),a.interactivity.status="mousemove"})),a.interactivity.el.addEventListener("mouseleave",(function(e){a.interactivity.mouse.pos_x=null,a.interactivity.mouse.pos_y=null,a.interactivity.status="mouseleave"}))),a.interactivity.events.onclick.enable&&a.interactivity.el.addEventListener("click",(function(){if(a.interactivity.mouse.click_pos_x=a.interactivity.mouse.pos_x,a.interactivity.mouse.click_pos_y=a.interactivity.mouse.pos_y,a.interactivity.mouse.click_time=(new Date).getTime(),a.interactivity.events.onclick.enable)switch(a.interactivity.events.onclick.mode){case"push":a.particles.move.enable||1==a.interactivity.modes.push.particles_nb?a.fn.modes.pushParticles(a.interactivity.modes.push.particles_nb,a.interactivity.mouse):a.interactivity.modes.push.particles_nb>1&&a.fn.modes.pushParticles(a.interactivity.modes.push.particles_nb);break;case"remove":a.fn.modes.removeParticles(a.interactivity.modes.remove.particles_nb);break;case"bubble":a.tmp.bubble_clicking=!0;break;case"repulse":a.tmp.repulse_clicking=!0,a.tmp.repulse_count=0,a.tmp.repulse_finish=!1,setTimeout((function(){a.tmp.repulse_clicking=!1}),1e3*a.interactivity.modes.repulse.duration);break}}))},a.fn.vendors.densityAutoParticles=function(){if(a.particles.number.density.enable){var e=a.canvas.el.width*a.canvas.el.height/1e3;a.tmp.retina&&(e/=2*a.canvas.pxratio);var t=e*a.particles.number.value/a.particles.number.density.value_area,n=a.particles.array.length-t;n<0?a.fn.modes.pushParticles(Math.abs(n)):a.fn.modes.removeParticles(n)}},a.fn.vendors.checkOverlap=function(e,t){for(var n=0;n=a.particles.number.value?(a.fn.particlesDraw(),a.particles.move.enable?a.fn.drawAnimFrame=requestAnimFrame(a.fn.vendors.draw):cancelRequestAnimFrame(a.fn.drawAnimFrame)):a.tmp.img_error||(a.fn.drawAnimFrame=requestAnimFrame(a.fn.vendors.draw)):void 0!=a.tmp.img_obj?(a.fn.particlesDraw(),a.particles.move.enable?a.fn.drawAnimFrame=requestAnimFrame(a.fn.vendors.draw):cancelRequestAnimFrame(a.fn.drawAnimFrame)):a.tmp.img_error||(a.fn.drawAnimFrame=requestAnimFrame(a.fn.vendors.draw)):(a.fn.particlesDraw(),a.particles.move.enable?a.fn.drawAnimFrame=requestAnimFrame(a.fn.vendors.draw):cancelRequestAnimFrame(a.fn.drawAnimFrame))},a.fn.vendors.checkBeforeDraw=function(){"image"==a.particles.shape.type?"svg"==a.tmp.img_type&&void 0==a.tmp.source_svg?a.tmp.checkAnimFrame=requestAnimFrame(check):(cancelRequestAnimFrame(a.tmp.checkAnimFrame),a.tmp.img_error||(a.fn.vendors.init(),a.fn.vendors.draw())):(a.fn.vendors.init(),a.fn.vendors.draw())},a.fn.vendors.init=function(){a.fn.retinaInit(),a.fn.canvasInit(),a.fn.canvasSize(),a.fn.canvasPaint(),a.fn.particlesCreate(),a.fn.vendors.densityAutoParticles(),a.particles.line_linked.color_rgb_line=r(a.particles.line_linked.color)},a.fn.vendors.start=function(){o("image",a.particles.shape.type)?(a.tmp.img_type=a.particles.shape.image.src.substr(a.particles.shape.image.src.length-3),a.fn.vendors.loadImg(a.tmp.img_type)):a.fn.vendors.checkBeforeDraw()},a.fn.vendors.eventsListeners(),a.fn.vendors.start()};function r(e){var t=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;e=e.replace(t,(function(e,t,n,r){return t+t+n+n+r+r}));var n=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return n?{r:parseInt(n[1],16),g:parseInt(n[2],16),b:parseInt(n[3],16)}:null}function i(e,t,n){return Math.min(Math.max(e,t),n)}function o(e,t){return t.indexOf(e)>-1}Object.deepExtend=function(e,t){for(var n in t)t[n]&&t[n].constructor&&t[n].constructor===Object?(e[n]=e[n]||{},arguments.callee(e[n],t[n])):e[n]=t[n];return e},window.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)}}(),window.cancelRequestAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelRequestAnimationFrame||window.mozCancelRequestAnimationFrame||window.oCancelRequestAnimationFrame||window.msCancelRequestAnimationFrame||clearTimeout}(),window.pJSDom=[],window.particlesJS=function(e,t){"string"!=typeof e&&(t=e,e="particles-js"),e||(e="particles-js");var r=document.getElementById(e),i="particles-js-canvas-el",o=r.getElementsByClassName(i);if(o.length)while(o.length>0)r.removeChild(o[0]);var a=document.createElement("canvas");a.className=i,a.style.width="100%",a.style.height="100%";var s=document.getElementById(e).appendChild(a);null!=s&&pJSDom.push(new n(e,t))},window.particlesJS.load=function(e,t,n){var r=new XMLHttpRequest;r.open("GET",t),r.onreadystatechange=function(t){if(4==r.readyState)if(200==r.status){var i=JSON.parse(t.currentTarget.response);window.particlesJS(e,i),n&&n()}else console.log("Error pJS - XMLHttpRequest status: "+r.status),console.log("Error pJS - File config not found")},r.send()}},"583b":function(e,t,n){var r=n("23e7"),i=n("5e89"),o=Math.abs;r({target:"Number",stat:!0},{isSafeInteger:function(e){return i(e)&&o(e)<=9007199254740991}})},5899:function(e,t){e.exports="\t\n\v\f\r                 \u2028\u2029\ufeff"},"58a8":function(e,t,n){var r=n("1d80"),i=n("5899"),o="["+i+"]",a=RegExp("^"+o+o+"*"),s=RegExp(o+o+"*$"),c=function(e){return function(t){var n=String(r(t));return 1&e&&(n=n.replace(a,"")),2&e&&(n=n.replace(s,"")),n}};e.exports={start:c(1),end:c(2),trim:c(3)}},"5a34":function(e,t,n){var r=n("44e7");e.exports=function(e){if(r(e))throw TypeError("The method doesn't accept regular expressions");return e}},"5b81":function(e,t,n){"use strict";var r=n("23e7"),i=n("1d80"),o=n("44e7"),a=n("ad6d"),s=n("0cb2"),c=n("b622"),u=n("c430"),l=c("replace"),f=RegExp.prototype,d=Math.max,p=function(e,t,n){return n>e.length?-1:""===t?n:e.indexOf(t,n)};r({target:"String",proto:!0},{replaceAll:function(e,t){var n,r,c,h,v,g,b,m,y,w=i(this),_=0,x=0,E="";if(null!=e){if(n=o(e),n&&(r=String(i("flags"in f?e.flags:a.call(e))),!~r.indexOf("g")))throw TypeError("`.replaceAll` does not allow non-global regexes");if(c=e[l],void 0!==c)return c.call(e,w,t);if(u&&n)return String(w).replace(e,t)}h=String(w),v=String(e),g="function"===typeof t,g||(t=String(t)),b=v.length,m=d(1,b),_=p(h,v,0);while(-1!==_)y=g?String(t(v,_,h)):s(v,h,_,[],void 0,t),E+=h.slice(x,_)+y,x=_+b,_=p(h,v,_+m);return x1?arguments[1]:void 0),t}})},"5ded":function(e,t,n){"use strict";var r=n("23e7"),i=n("d039"),o=n("8418"),a=i((function(){function e(){}return!(Array.of.call(e)instanceof e)}));r({target:"Array",stat:!0,forced:a},{of:function(){var e=0,t=arguments.length,n=new("function"==typeof this?this:Array)(t);while(t>e)o(n,e,arguments[e++]);return n.length=t,n}})},"5e89":function(e,t,n){var r=n("861d"),i=Math.floor;e.exports=function(e){return!r(e)&&isFinite(e)&&i(e)===e}},"5f96":function(e,t,n){"use strict";var r=n("ebb5"),i=r.aTypedArray,o=r.exportTypedArrayMethod,a=[].join;o("join",(function(e){return a.apply(i(this),arguments)}))},"5fb2":function(e,t,n){"use strict";var r=2147483647,i=36,o=1,a=26,s=38,c=700,u=72,l=128,f="-",d=/[^\0-\u007E]/,p=/[.\u3002\uFF0E\uFF61]/g,h="Overflow: input needs wider integers to process",v=i-o,g=Math.floor,b=String.fromCharCode,m=function(e){var t=[],n=0,r=e.length;while(n=55296&&i<=56319&&n>1,e+=g(e/t);e>v*a>>1;r+=i)e=g(e/v);return g(r+(v+1)*e/(e+s))},_=function(e){var t=[];e=m(e);var n,s,c=e.length,d=l,p=0,v=u;for(n=0;n=d&&sg((r-p)/S))throw RangeError(h);for(p+=(E-d)*S,d=E,n=0;nr)throw RangeError(h);if(s==d){for(var A=p,k=i;;k+=i){var O=k<=v?o:k>=v+a?a:k-v;if(Al){var p,h=u(arguments[l++]),v=f?o(h).concat(f(h)):o(h),g=v.length,b=0;while(g>b)p=v[b++],r&&!d.call(h,p)||(n[p]=h[p])}return n}:l},"621a":function(e,t,n){"use strict";var r=n("da84"),i=n("83ab"),o=n("a981"),a=n("9112"),s=n("e2cc"),c=n("d039"),u=n("19aa"),l=n("a691"),f=n("50c4"),d=n("0b25"),p=n("77a7"),h=n("e163"),v=n("d2bb"),g=n("241c").f,b=n("9bf2").f,m=n("81d5"),y=n("d44e"),w=n("69f3"),_=w.get,x=w.set,E="ArrayBuffer",S="DataView",A="prototype",k="Wrong length",O="Wrong index",C=r[E],M=C,T=r[S],R=T&&T[A],I=Object.prototype,N=r.RangeError,j=p.pack,P=p.unpack,L=function(e){return[255&e]},$=function(e){return[255&e,e>>8&255]},D=function(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]},F=function(e){return e[3]<<24|e[2]<<16|e[1]<<8|e[0]},B=function(e){return j(e,23,4)},U=function(e){return j(e,52,8)},z=function(e,t){b(e[A],t,{get:function(){return _(this)[t]}})},H=function(e,t,n,r){var i=d(n),o=_(e);if(i+t>o.byteLength)throw N(O);var a=_(o.buffer).bytes,s=i+o.byteOffset,c=a.slice(s,s+t);return r?c:c.reverse()},q=function(e,t,n,r,i,o){var a=d(n),s=_(e);if(a+t>s.byteLength)throw N(O);for(var c=_(s.buffer).bytes,u=a+s.byteOffset,l=r(+i),f=0;fG;)(W=K[G++])in M||a(M,W,C[W]);V.constructor=M}v&&h(R)!==I&&v(R,I);var J=new T(new M(2)),X=R.setInt8;J.setInt8(0,2147483648),J.setInt8(1,2147483649),!J.getInt8(0)&&J.getInt8(1)||s(R,{setInt8:function(e,t){X.call(this,e,t<<24>>24)},setUint8:function(e,t){X.call(this,e,t<<24>>24)}},{unsafe:!0})}else M=function(e){u(this,M,E);var t=d(e);x(this,{bytes:m.call(new Array(t),0),byteLength:t}),i||(this.byteLength=t)},T=function(e,t,n){u(this,T,S),u(e,M,S);var r=_(e).byteLength,o=l(t);if(o<0||o>r)throw N("Wrong offset");if(n=void 0===n?r-o:f(n),o+n>r)throw N(k);x(this,{buffer:e,byteLength:n,byteOffset:o}),i||(this.buffer=e,this.byteLength=n,this.byteOffset=o)},i&&(z(M,"byteLength"),z(T,"buffer"),z(T,"byteLength"),z(T,"byteOffset")),s(T[A],{getInt8:function(e){return H(this,1,e)[0]<<24>>24},getUint8:function(e){return H(this,1,e)[0]},getInt16:function(e){var t=H(this,2,e,arguments.length>1?arguments[1]:void 0);return(t[1]<<8|t[0])<<16>>16},getUint16:function(e){var t=H(this,2,e,arguments.length>1?arguments[1]:void 0);return t[1]<<8|t[0]},getInt32:function(e){return F(H(this,4,e,arguments.length>1?arguments[1]:void 0))},getUint32:function(e){return F(H(this,4,e,arguments.length>1?arguments[1]:void 0))>>>0},getFloat32:function(e){return P(H(this,4,e,arguments.length>1?arguments[1]:void 0),23)},getFloat64:function(e){return P(H(this,8,e,arguments.length>1?arguments[1]:void 0),52)},setInt8:function(e,t){q(this,1,e,L,t)},setUint8:function(e,t){q(this,1,e,L,t)},setInt16:function(e,t){q(this,2,e,$,t,arguments.length>2?arguments[2]:void 0)},setUint16:function(e,t){q(this,2,e,$,t,arguments.length>2?arguments[2]:void 0)},setInt32:function(e,t){q(this,4,e,D,t,arguments.length>2?arguments[2]:void 0)},setUint32:function(e,t){q(this,4,e,D,t,arguments.length>2?arguments[2]:void 0)},setFloat32:function(e,t){q(this,4,e,B,t,arguments.length>2?arguments[2]:void 0)},setFloat64:function(e,t){q(this,8,e,U,t,arguments.length>2?arguments[2]:void 0)}});y(M,E),y(T,S),e.exports={ArrayBuffer:M,DataView:T}},"649e":function(e,t,n){"use strict";var r=n("ebb5"),i=n("b727").some,o=r.aTypedArray,a=r.exportTypedArrayMethod;a("some",(function(e){return i(o(this),e,arguments.length>1?arguments[1]:void 0)}))},"64e5":function(e,t,n){"use strict";var r=n("d039"),i=n("0ccb").start,o=Math.abs,a=Date.prototype,s=a.getTime,c=a.toISOString;e.exports=r((function(){return"0385-07-25T07:06:39.999Z"!=c.call(new Date(-50000000000001))}))||!r((function(){c.call(new Date(NaN))}))?function(){if(!isFinite(s.call(this)))throw RangeError("Invalid time value");var e=this,t=e.getUTCFullYear(),n=e.getUTCMilliseconds(),r=t<0?"-":t>9999?"+":"";return r+i(o(t),r?6:4,0)+"-"+i(e.getUTCMonth()+1,2,0)+"-"+i(e.getUTCDate(),2,0)+"T"+i(e.getUTCHours(),2,0)+":"+i(e.getUTCMinutes(),2,0)+":"+i(e.getUTCSeconds(),2,0)+"."+i(n,3,0)+"Z"}:c},6547:function(e,t,n){var r=n("a691"),i=n("1d80"),o=function(e){return function(t,n){var o,a,s=String(i(t)),c=r(n),u=s.length;return c<0||c>=u?e?"":void 0:(o=s.charCodeAt(c),o<55296||o>56319||c+1===u||(a=s.charCodeAt(c+1))<56320||a>57343?e?s.charAt(c):o:e?s.slice(c,c+2):a-56320+(o-55296<<10)+65536)}};e.exports={codeAt:o(!1),charAt:o(!0)}},6566:function(e,t,n){"use strict";var r=n("9bf2").f,i=n("7c73"),o=n("e2cc"),a=n("0366"),s=n("19aa"),c=n("2266"),u=n("7dd0"),l=n("2626"),f=n("83ab"),d=n("f183").fastKey,p=n("69f3"),h=p.set,v=p.getterFor;e.exports={getConstructor:function(e,t,n,u){var l=e((function(e,r){s(e,l,t),h(e,{type:t,index:i(null),first:void 0,last:void 0,size:0}),f||(e.size=0),void 0!=r&&c(r,e[u],{that:e,AS_ENTRIES:n})})),p=v(t),g=function(e,t,n){var r,i,o=p(e),a=b(e,t);return a?a.value=n:(o.last=a={index:i=d(t,!0),key:t,value:n,previous:r=o.last,next:void 0,removed:!1},o.first||(o.first=a),r&&(r.next=a),f?o.size++:e.size++,"F"!==i&&(o.index[i]=a)),e},b=function(e,t){var n,r=p(e),i=d(t);if("F"!==i)return r.index[i];for(n=r.first;n;n=n.next)if(n.key==t)return n};return o(l.prototype,{clear:function(){var e=this,t=p(e),n=t.index,r=t.first;while(r)r.removed=!0,r.previous&&(r.previous=r.previous.next=void 0),delete n[r.index],r=r.next;t.first=t.last=void 0,f?t.size=0:e.size=0},delete:function(e){var t=this,n=p(t),r=b(t,e);if(r){var i=r.next,o=r.previous;delete n.index[r.index],r.removed=!0,o&&(o.next=i),i&&(i.previous=o),n.first==r&&(n.first=i),n.last==r&&(n.last=o),f?n.size--:t.size--}return!!r},forEach:function(e){var t,n=p(this),r=a(e,arguments.length>1?arguments[1]:void 0,3);while(t=t?t.next:n.first){r(t.value,t.key,this);while(t&&t.removed)t=t.previous}},has:function(e){return!!b(this,e)}}),o(l.prototype,n?{get:function(e){var t=b(this,e);return t&&t.value},set:function(e,t){return g(this,0===e?0:e,t)}}:{add:function(e){return g(this,e=0===e?0:e,e)}}),f&&r(l.prototype,"size",{get:function(){return p(this).size}}),l},setStrong:function(e,t,n){var r=t+" Iterator",i=v(t),o=v(r);u(e,t,(function(e,t){h(this,{type:r,target:e,state:i(e),kind:t,last:void 0})}),(function(){var e=o(this),t=e.kind,n=e.last;while(n&&n.removed)n=n.previous;return e.target&&(e.last=n=n?n.next:e.state.first)?"keys"==t?{value:n.key,done:!1}:"values"==t?{value:n.value,done:!1}:{value:[n.key,n.value],done:!1}:(e.target=void 0,{value:void 0,done:!0})}),n?"entries":"values",!n,!0),l(t)}}},"65f0":function(e,t,n){var r=n("861d"),i=n("e8b5"),o=n("b622"),a=o("species");e.exports=function(e,t){var n;return i(e)&&(n=e.constructor,"function"!=typeof n||n!==Array&&!i(n.prototype)?r(n)&&(n=n[a],null===n&&(n=void 0)):n=void 0),new(void 0===n?Array:n)(0===t?0:t)}},"664f":function(e,t,n){"use strict";var r=n("23e7"),i=n("857a"),o=n("af03");r({target:"String",proto:!0,forced:o("sup")},{sup:function(){return i(this,"sup","","")}})},"66d5":function(e,t){t.N=[48,49,50,51,52,53,54,55,56,57,178,179,185,188,189,190,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2548,2549,2550,2551,2552,2553,2662,2663,2664,2665,2666,2667,2668,2669,2670,2671,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2930,2931,2932,2933,2934,2935,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3056,3057,3058,3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3192,3193,3194,3195,3196,3197,3198,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,3445,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,4160,4161,4162,4163,4164,4165,4166,4167,4168,4169,4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4969,4970,4971,4972,4973,4974,4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,5870,5871,5872,6112,6113,6114,6115,6116,6117,6118,6119,6120,6121,6128,6129,6130,6131,6132,6133,6134,6135,6136,6137,6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6470,6471,6472,6473,6474,6475,6476,6477,6478,6479,6608,6609,6610,6611,6612,6613,6614,6615,6616,6617,6618,6784,6785,6786,6787,6788,6789,6790,6791,6792,6793,6800,6801,6802,6803,6804,6805,6806,6807,6808,6809,6992,6993,6994,6995,6996,6997,6998,6999,7e3,7001,7088,7089,7090,7091,7092,7093,7094,7095,7096,7097,7232,7233,7234,7235,7236,7237,7238,7239,7240,7241,7248,7249,7250,7251,7252,7253,7254,7255,7256,7257,8304,8308,8309,8310,8311,8312,8313,8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,8540,8541,8542,8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,8570,8571,8572,8573,8574,8575,8576,8577,8578,8581,8582,8583,8584,8585,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,9327,9328,9329,9330,9331,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,9350,9351,9352,9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,9368,9369,9370,9371,9450,9451,9452,9453,9454,9455,9456,9457,9458,9459,9460,9461,9462,9463,9464,9465,9466,9467,9468,9469,9470,9471,10102,10103,10104,10105,10106,10107,10108,10109,10110,10111,10112,10113,10114,10115,10116,10117,10118,10119,10120,10121,10122,10123,10124,10125,10126,10127,10128,10129,10130,10131,11517,12295,12321,12322,12323,12324,12325,12326,12327,12328,12329,12344,12345,12346,12690,12691,12692,12693,12832,12833,12834,12835,12836,12837,12838,12839,12840,12841,12872,12873,12874,12875,12876,12877,12878,12879,12881,12882,12883,12884,12885,12886,12887,12888,12889,12890,12891,12892,12893,12894,12895,12928,12929,12930,12931,12932,12933,12934,12935,12936,12937,12977,12978,12979,12980,12981,12982,12983,12984,12985,12986,12987,12988,12989,12990,12991,42528,42529,42530,42531,42532,42533,42534,42535,42536,42537,42726,42727,42728,42729,42730,42731,42732,42733,42734,42735,43056,43057,43058,43059,43060,43061,43216,43217,43218,43219,43220,43221,43222,43223,43224,43225,43264,43265,43266,43267,43268,43269,43270,43271,43272,43273,43472,43473,43474,43475,43476,43477,43478,43479,43480,43481,43504,43505,43506,43507,43508,43509,43510,43511,43512,43513,43600,43601,43602,43603,43604,43605,43606,43607,43608,43609,44016,44017,44018,44019,44020,44021,44022,44023,44024,44025,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,65799,65800,65801,65802,65803,65804,65805,65806,65807,65808,65809,65810,65811,65812,65813,65814,65815,65816,65817,65818,65819,65820,65821,65822,65823,65824,65825,65826,65827,65828,65829,65830,65831,65832,65833,65834,65835,65836,65837,65838,65839,65840,65841,65842,65843,65856,65857,65858,65859,65860,65861,65862,65863,65864,65865,65866,65867,65868,65869,65870,65871,65872,65873,65874,65875,65876,65877,65878,65879,65880,65881,65882,65883,65884,65885,65886,65887,65888,65889,65890,65891,65892,65893,65894,65895,65896,65897,65898,65899,65900,65901,65902,65903,65904,65905,65906,65907,65908,65909,65910,65911,65912,65930,65931,66273,66274,66275,66276,66277,66278,66279,66280,66281,66282,66283,66284,66285,66286,66287,66288,66289,66290,66291,66292,66293,66294,66295,66296,66297,66298,66299,66336,66337,66338,66339,66369,66378,66513,66514,66515,66516,66517,66720,66721,66722,66723,66724,66725,66726,66727,66728,66729,67672,67673,67674,67675,67676,67677,67678,67679,67705,67706,67707,67708,67709,67710,67711,67751,67752,67753,67754,67755,67756,67757,67758,67759,67835,67836,67837,67838,67839,67862,67863,67864,67865,67866,67867,68028,68029,68032,68033,68034,68035,68036,68037,68038,68039,68040,68041,68042,68043,68044,68045,68046,68047,68050,68051,68052,68053,68054,68055,68056,68057,68058,68059,68060,68061,68062,68063,68064,68065,68066,68067,68068,68069,68070,68071,68072,68073,68074,68075,68076,68077,68078,68079,68080,68081,68082,68083,68084,68085,68086,68087,68088,68089,68090,68091,68092,68093,68094,68095,68160,68161,68162,68163,68164,68165,68166,68167,68221,68222,68253,68254,68255,68331,68332,68333,68334,68335,68440,68441,68442,68443,68444,68445,68446,68447,68472,68473,68474,68475,68476,68477,68478,68479,68521,68522,68523,68524,68525,68526,68527,68858,68859,68860,68861,68862,68863,69216,69217,69218,69219,69220,69221,69222,69223,69224,69225,69226,69227,69228,69229,69230,69231,69232,69233,69234,69235,69236,69237,69238,69239,69240,69241,69242,69243,69244,69245,69246,69714,69715,69716,69717,69718,69719,69720,69721,69722,69723,69724,69725,69726,69727,69728,69729,69730,69731,69732,69733,69734,69735,69736,69737,69738,69739,69740,69741,69742,69743,69872,69873,69874,69875,69876,69877,69878,69879,69880,69881,69942,69943,69944,69945,69946,69947,69948,69949,69950,69951,70096,70097,70098,70099,70100,70101,70102,70103,70104,70105,70113,70114,70115,70116,70117,70118,70119,70120,70121,70122,70123,70124,70125,70126,70127,70128,70129,70130,70131,70132,70384,70385,70386,70387,70388,70389,70390,70391,70392,70393,70864,70865,70866,70867,70868,70869,70870,70871,70872,70873,71248,71249,71250,71251,71252,71253,71254,71255,71256,71257,71360,71361,71362,71363,71364,71365,71366,71367,71368,71369,71472,71473,71474,71475,71476,71477,71478,71479,71480,71481,71482,71483,71904,71905,71906,71907,71908,71909,71910,71911,71912,71913,71914,71915,71916,71917,71918,71919,71920,71921,71922,74752,74753,74754,74755,74756,74757,74758,74759,74760,74761,74762,74763,74764,74765,74766,74767,74768,74769,74770,74771,74772,74773,74774,74775,74776,74777,74778,74779,74780,74781,74782,74783,74784,74785,74786,74787,74788,74789,74790,74791,74792,74793,74794,74795,74796,74797,74798,74799,74800,74801,74802,74803,74804,74805,74806,74807,74808,74809,74810,74811,74812,74813,74814,74815,74816,74817,74818,74819,74820,74821,74822,74823,74824,74825,74826,74827,74828,74829,74830,74831,74832,74833,74834,74835,74836,74837,74838,74839,74840,74841,74842,74843,74844,74845,74846,74847,74848,74849,74850,74851,74852,74853,74854,74855,74856,74857,74858,74859,74860,74861,74862,92768,92769,92770,92771,92772,92773,92774,92775,92776,92777,93008,93009,93010,93011,93012,93013,93014,93015,93016,93017,93019,93020,93021,93022,93023,93024,93025,119648,119649,119650,119651,119652,119653,119654,119655,119656,119657,119658,119659,119660,119661,119662,119663,119664,119665,120782,120783,120784,120785,120786,120787,120788,120789,120790,120791,120792,120793,120794,120795,120796,120797,120798,120799,120800,120801,120802,120803,120804,120805,120806,120807,120808,120809,120810,120811,120812,120813,120814,120815,120816,120817,120818,120819,120820,120821,120822,120823,120824,120825,120826,120827,120828,120829,120830,120831,125127,125128,125129,125130,125131,125132,125133,125134,125135,127232,127233,127234,127235,127236,127237,127238,127239,127240,127241,127242,127243,127244]},"69f3":function(e,t,n){var r,i,o,a=n("7f9a"),s=n("da84"),c=n("861d"),u=n("9112"),l=n("5135"),f=n("c6cd"),d=n("f772"),p=n("d012"),h="Object already initialized",v=s.WeakMap,g=function(e){return o(e)?i(e):r(e,{})},b=function(e){return function(t){var n;if(!c(t)||(n=i(t)).type!==e)throw TypeError("Incompatible receiver, "+e+" required");return n}};if(a){var m=f.state||(f.state=new v),y=m.get,w=m.has,_=m.set;r=function(e,t){if(w.call(m,e))throw new TypeError(h);return t.facade=e,_.call(m,e,t),t},i=function(e){return y.call(m,e)||{}},o=function(e){return w.call(m,e)}}else{var x=d("state");p[x]=!0,r=function(e,t){if(l(e,x))throw new TypeError(h);return t.facade=e,u(e,x,t),t},i=function(e){return l(e,x)?e[x]:{}},o=function(e){return l(e,x)}}e.exports={set:r,get:i,has:o,enforce:g,getterFor:b}},"6b93":function(e,t,n){var r=n("23e7"),i=Math.log,o=Math.LOG10E;r({target:"Math",stat:!0},{log10:function(e){return i(e)*o}})},"6b9e":function(e,t,n){var r=n("746f");r("search")},"6c57":function(e,t,n){var r=n("23e7"),i=n("da84");r({global:!0},{globalThis:i})},"6d61":function(e,t,n){"use strict";var r=n("23e7"),i=n("da84"),o=n("94ca"),a=n("6eeb"),s=n("f183"),c=n("2266"),u=n("19aa"),l=n("861d"),f=n("d039"),d=n("1c7e"),p=n("d44e"),h=n("7156");e.exports=function(e,t,n){var v=-1!==e.indexOf("Map"),g=-1!==e.indexOf("Weak"),b=v?"set":"add",m=i[e],y=m&&m.prototype,w=m,_={},x=function(e){var t=y[e];a(y,e,"add"==e?function(e){return t.call(this,0===e?0:e),this}:"delete"==e?function(e){return!(g&&!l(e))&&t.call(this,0===e?0:e)}:"get"==e?function(e){return g&&!l(e)?void 0:t.call(this,0===e?0:e)}:"has"==e?function(e){return!(g&&!l(e))&&t.call(this,0===e?0:e)}:function(e,n){return t.call(this,0===e?0:e,n),this})},E=o(e,"function"!=typeof m||!(g||y.forEach&&!f((function(){(new m).entries().next()}))));if(E)w=n.getConstructor(t,e,v,b),s.REQUIRED=!0;else if(o(e,!0)){var S=new w,A=S[b](g?{}:-0,1)!=S,k=f((function(){S.has(1)})),O=d((function(e){new m(e)})),C=!g&&f((function(){var e=new m,t=5;while(t--)e[b](t,t);return!e.has(-0)}));O||(w=t((function(t,n){u(t,w,e);var r=h(new m,t,w);return void 0!=n&&c(n,r[b],{that:r,AS_ENTRIES:v}),r})),w.prototype=y,y.constructor=w),(k||C)&&(x("delete"),x("has"),v&&x("get")),(C||A)&&x(b),g&&y.clear&&delete y.clear}return _[e]=w,r({global:!0,forced:w!=m},_),p(w,e),g||n.setStrong(w,e,v),w}},"6eba":function(e,t,n){var r=n("23e7");r({target:"Date",stat:!0},{now:function(){return(new Date).getTime()}})},"6eeb":function(e,t,n){var r=n("da84"),i=n("9112"),o=n("5135"),a=n("ce4e"),s=n("8925"),c=n("69f3"),u=c.get,l=c.enforce,f=String(String).split("String");(e.exports=function(e,t,n,s){var c,u=!!s&&!!s.unsafe,d=!!s&&!!s.enumerable,p=!!s&&!!s.noTargetGet;"function"==typeof n&&("string"!=typeof t||o(n,"name")||i(n,"name",t),c=l(n),c.source||(c.source=f.join("string"==typeof t?t:""))),e!==r?(u?!p&&e[t]&&(d=!0):delete e[t],d?e[t]=n:i(e,t,n)):d?e[t]=n:a(t,n)})(Function.prototype,"toString",(function(){return"function"==typeof this&&u(this).source||s(this)}))},"6f53":function(e,t,n){var r=n("83ab"),i=n("df75"),o=n("fc6a"),a=n("d1e7").f,s=function(e){return function(t){var n,s=o(t),c=i(s),u=c.length,l=0,f=[];while(u>l)n=c[l++],r&&!a.call(s,n)||f.push(e?[n,s[n]]:s[n]);return f}};e.exports={entries:s(!0),values:s(!1)}},7039:function(e,t,n){var r=n("23e7"),i=n("d039"),o=n("057f").f,a=i((function(){return!Object.getOwnPropertyNames(1)}));r({target:"Object",stat:!0,forced:a},{getOwnPropertyNames:o})},7156:function(e,t,n){var r=n("861d"),i=n("d2bb");e.exports=function(e,t,n){var o,a;return i&&"function"==typeof(o=t.constructor)&&o!==n&&r(a=o.prototype)&&a!==n.prototype&&i(e,a),e}},"72f7":function(e,t,n){"use strict";var r=n("ebb5").exportTypedArrayMethod,i=n("d039"),o=n("da84"),a=o.Uint8Array,s=a&&a.prototype||{},c=[].toString,u=[].join;i((function(){c.call({})}))&&(c=function(){return u.call(this)});var l=s.toString!=c;r("toString",c,l)},"735e":function(e,t,n){"use strict";var r=n("ebb5"),i=n("81d5"),o=r.aTypedArray,a=r.exportTypedArrayMethod;a("fill",(function(e){return i.apply(o(this),arguments)}))},"73d9":function(e,t,n){var r=n("44d2");r("flatMap")},7418:function(e,t){t.f=Object.getOwnPropertySymbols},"746a":function(e,t,n){"use strict";e.exports=function(e,t,n){function r(e){return e.trim().split(" ",2)[0]===t}function i(e,n,r,i,o){return 1===e[n].nesting&&e[n].attrJoin("class",t),o.renderToken(e,n,r,i,o)}n=n||{};var o=3,a=n.marker||":",s=a.charCodeAt(0),c=a.length,u=n.validate||r,l=n.render||i;function f(e,n,r,i){var l,f,d,p,h,v,g,b,m=!1,y=e.bMarks[n]+e.tShift[n],w=e.eMarks[n];if(s!==e.src.charCodeAt(y))return!1;for(l=y+1;l<=w;l++)if(a[(l-y)%c]!==e.src[l])break;if(d=Math.floor((l-y)/c),d=r)break;if(y=e.bMarks[f]+e.tShift[f],w=e.eMarks[f],y=4)){for(l=y+1;l<=w;l++)if(a[(l-y)%c]!==e.src[l])break;if(!(Math.floor((l-y)/c)n)i[n]=t[n++];return i},V=function(e,t){R(e,t,{get:function(){return M(this)[t]}})},K=function(e){var t;return e instanceof P||"ArrayBuffer"==(t=b(e))||"SharedArrayBuffer"==t},G=function(e,t){return z(e)&&"symbol"!=typeof t&&t in e&&String(+t)==String(t)},J=function(e,t){return G(e,t=v(t,!0))?l(2,e[t]):I(e,t)},X=function(e,t,n){return!(G(e,t=v(t,!0))&&m(n)&&g(n,"value"))||g(n,"get")||g(n,"set")||n.configurable||g(n,"writable")&&!n.writable||g(n,"enumerable")&&!n.enumerable?R(e,t,n):(e[t]=n.value,e)};o?($||(k.f=J,A.f=X,V(B,"buffer"),V(B,"byteOffset"),V(B,"byteLength"),V(B,"length")),r({target:"Object",stat:!0,forced:!$},{getOwnPropertyDescriptor:J,defineProperty:X}),e.exports=function(e,t,n){var o=e.match(/\d+$/)[0]/8,s=e+(n?"Clamped":"")+"Array",c="get"+e,l="set"+e,v=i[s],g=v,b=g&&g.prototype,A={},k=function(e,t){var n=M(e);return n.view[c](t*o+n.byteOffset,!0)},O=function(e,t,r){var i=M(e);n&&(r=(r=N(r))<0?0:r>255?255:255&r),i.view[l](t*o+i.byteOffset,r,!0)},I=function(e,t){R(e,t,{get:function(){return k(this,t)},set:function(e){return O(this,t,e)},enumerable:!0})};$?a&&(g=t((function(e,t,n,r){return u(e,g,s),C(function(){return m(t)?K(t)?void 0!==r?new v(t,h(n,o),r):void 0!==n?new v(t,h(n,o)):new v(t):z(t)?W(g,t):x.call(g,t):new v(p(t))}(),e,g)})),w&&w(g,F),E(_(v),(function(e){e in g||f(g,e,v[e])})),g.prototype=b):(g=t((function(e,t,n,r){u(e,g,s);var i,a,c,l=0,f=0;if(m(t)){if(!K(t))return z(t)?W(g,t):x.call(g,t);i=t,f=h(n,o);var v=t.byteLength;if(void 0===r){if(v%o)throw j(q);if(a=v-f,a<0)throw j(q)}else if(a=d(r)*o,a+f>v)throw j(q);c=a/o}else c=p(t),a=c*o,i=new P(a);T(e,{buffer:i,byteOffset:f,byteLength:a,length:c,view:new L(i)});while(l/}]}]}]},s={className:"string",begin:"~[A-Z](?="+o+")",contains:[{begin:/"/,end:/"/},{begin:/'/,end:/'/},{begin:/\//,end:/\//},{begin:/\|/,end:/\|/},{begin:/\(/,end:/\)/},{begin:/\[/,end:/\]/},{begin:/\{/,end:/\}/},{begin:/\/}]},c={className:"string",contains:[e.BACKSLASH_ESCAPE,i],variants:[{begin:/"""/,end:/"""/},{begin:/'''/,end:/'''/},{begin:/~S"""/,end:/"""/,contains:[]},{begin:/~S"/,end:/"/,contains:[]},{begin:/~S'''/,end:/'''/,contains:[]},{begin:/~S'/,end:/'/,contains:[]},{begin:/'/,end:/'/},{begin:/"/,end:/"/}]},u={className:"function",beginKeywords:"def defp defmacro",end:/\B\b/,contains:[e.inherit(e.TITLE_MODE,{begin:t,endsParent:!0})]},l=e.inherit(u,{className:"class",beginKeywords:"defimpl defmodule defprotocol defrecord",end:/\bdo\b|$|;/}),f=[c,s,a,e.HASH_COMMENT_MODE,l,u,{begin:"::"},{className:"symbol",begin:":(?![\\s:])",contains:[c,{begin:n}],relevance:0},{className:"symbol",begin:t+":(?!:)",relevance:0},{className:"number",begin:"(\\b0o[0-7_]+)|(\\b0b[01_]+)|(\\b0x[0-9a-fA-F_]+)|(-?\\b[1-9][0-9_]*(.[0-9_]+([eE][-+]?[0-9]+)?)?)",relevance:0},{className:"variable",begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{begin:"->"},{begin:"("+e.RE_STARTERS_RE+")\\s*",contains:[e.HASH_COMMENT_MODE,{className:"regexp",illegal:"\\n",contains:[e.BACKSLASH_ESCAPE,i],variants:[{begin:"/",end:"/[a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}],relevance:0}];return i.contains=f,{lexemes:t,keywords:r,contains:f}}},"77a7":function(e,t){var n=Math.abs,r=Math.pow,i=Math.floor,o=Math.log,a=Math.LN2,s=function(e,t,s){var c,u,l,f=new Array(s),d=8*s-t-1,p=(1<>1,v=23===t?r(2,-24)-r(2,-77):0,g=e<0||0===e&&1/e<0?1:0,b=0;for(e=n(e),e!=e||e===1/0?(u=e!=e?1:0,c=p):(c=i(o(e)/a),e*(l=r(2,-c))<1&&(c--,l*=2),e+=c+h>=1?v/l:v*r(2,1-h),e*l>=2&&(c++,l/=2),c+h>=p?(u=0,c=p):c+h>=1?(u=(e*l-1)*r(2,t),c+=h):(u=e*r(2,h-1)*r(2,t),c=0));t>=8;f[b++]=255&u,u/=256,t-=8);for(c=c<0;f[b++]=255&c,c/=256,d-=8);return f[--b]|=128*g,f},c=function(e,t){var n,i=e.length,o=8*i-t-1,a=(1<>1,c=o-7,u=i-1,l=e[u--],f=127&l;for(l>>=7;c>0;f=256*f+e[u],u--,c-=8);for(n=f&(1<<-c)-1,f>>=-c,c+=t;c>0;n=256*n+e[u],u--,c-=8);if(0===f)f=1-s;else{if(f===a)return n?NaN:l?-1/0:1/0;n+=r(2,t),f-=s}return(l?-1:1)*n*r(2,f-t)};e.exports={pack:s,unpack:c}},7839:function(e,t){e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},7898:function(e,t,n){var r=n("23e7"),i=n("8eb5"),o=Math.exp;r({target:"Math",stat:!0},{tanh:function(e){var t=i(e=+e),n=i(-e);return t==1/0?1:n==1/0?-1:(t-n)/(o(e)+o(-e))}})},"79a8":function(e,t,n){var r=n("23e7"),i=Math.asinh,o=Math.log,a=Math.sqrt;function s(e){return isFinite(e=+e)&&0!=e?e<0?-s(-e):o(e+a(e*e+1)):e}r({target:"Math",stat:!0,forced:!(i&&1/i(0)>0)},{asinh:s})},"7a82":function(e,t,n){var r=n("23e7"),i=n("83ab"),o=n("9bf2");r({target:"Object",stat:!0,forced:!i,sham:!i},{defineProperty:o.f})},"7b0b":function(e,t,n){var r=n("1d80");e.exports=function(e){return Object(r(e))}},"7c73":function(e,t,n){var r,i=n("825a"),o=n("37e8"),a=n("7839"),s=n("d012"),c=n("1be4"),u=n("cc12"),l=n("f772"),f=">",d="<",p="prototype",h="script",v=l("IE_PROTO"),g=function(){},b=function(e){return d+h+f+e+d+"/"+h+f},m=function(e){e.write(b("")),e.close();var t=e.parentWindow.Object;return e=null,t},y=function(){var e,t=u("iframe"),n="java"+h+":";return t.style.display="none",c.appendChild(t),t.src=String(n),e=t.contentWindow.document,e.open(),e.write(b("document.F=Object")),e.close(),e.F},w=function(){try{r=document.domain&&new ActiveXObject("htmlfile")}catch(t){}w=r?m(r):y();var e=a.length;while(e--)delete w[p][a[e]];return w()};s[v]=!0,e.exports=Object.create||function(e,t){var n;return null!==e?(g[p]=i(e),n=new g,g[p]=null,n[v]=e):n=w(),void 0===t?n:o(n,t)}},"7db0":function(e,t,n){"use strict";var r=n("23e7"),i=n("b727").find,o=n("44d2"),a="find",s=!0;a in[]&&Array(1)[a]((function(){s=!1})),r({target:"Array",proto:!0,forced:s},{find:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0)}}),o(a)},"7dd0":function(e,t,n){"use strict";var r=n("23e7"),i=n("9ed3"),o=n("e163"),a=n("d2bb"),s=n("d44e"),c=n("9112"),u=n("6eeb"),l=n("b622"),f=n("c430"),d=n("3f8c"),p=n("ae93"),h=p.IteratorPrototype,v=p.BUGGY_SAFARI_ITERATORS,g=l("iterator"),b="keys",m="values",y="entries",w=function(){return this};e.exports=function(e,t,n,l,p,_,x){i(n,t,l);var E,S,A,k=function(e){if(e===p&&R)return R;if(!v&&e in M)return M[e];switch(e){case b:return function(){return new n(this,e)};case m:return function(){return new n(this,e)};case y:return function(){return new n(this,e)}}return function(){return new n(this)}},O=t+" Iterator",C=!1,M=e.prototype,T=M[g]||M["@@iterator"]||p&&M[p],R=!v&&T||k(p),I="Array"==t&&M.entries||T;if(I&&(E=o(I.call(new e)),h!==Object.prototype&&E.next&&(f||o(E)===h||(a?a(E,h):"function"!=typeof E[g]&&c(E,g,w)),s(E,O,!0,!0),f&&(d[O]=w))),p==m&&T&&T.name!==m&&(C=!0,R=function(){return T.call(this)}),f&&!x||M[g]===R||c(M,g,R),d[t]=R,p)if(S={values:k(m),keys:_?R:k(b),entries:k(y)},x)for(A in S)(v||C||!(A in M))&&u(M,A,S[A]);else r({target:t,proto:!0,forced:v||C},S);return S}},"7e12":function(e,t,n){var r=n("da84"),i=n("58a8").trim,o=n("5899"),a=r.parseFloat,s=1/a(o+"-0")!==-1/0;e.exports=s?function(e){var t=i(String(e)),n=a(t);return 0===n&&"-"==t.charAt(0)?-0:n}:a},"7ed3":function(e,t,n){var r=n("23e7"),i=n("825a"),o=n("861d"),a=n("5135"),s=n("d039"),c=n("9bf2"),u=n("06cf"),l=n("e163"),f=n("5c6c");function d(e,t,n){var r,s,p=arguments.length<4?e:arguments[3],h=u.f(i(e),t);if(!h){if(o(s=l(e)))return d(s,t,n,p);h=f(0)}if(a(h,"value")){if(!1===h.writable||!o(p))return!1;if(r=u.f(p,t)){if(r.get||r.set||!1===r.writable)return!1;r.value=n,c.f(p,t,r)}else c.f(p,t,f(0,n));return!0}return void 0!==h.set&&(h.set.call(p,n),!0)}var p=s((function(){var e=function(){},t=c.f(new e,"a",{configurable:!0});return!1!==Reflect.set(e.prototype,"a",1,t)}));r({target:"Reflect",stat:!0,forced:p},{set:d})},"7f55":function(e,t){t.M=[768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,1155,1156,1157,1158,1159,1160,1161,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1471,1473,1474,1476,1477,1479,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1648,1750,1751,1752,1753,1754,1755,1756,1759,1760,1761,1762,1763,1764,1767,1768,1770,1771,1772,1773,1809,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,2027,2028,2029,2030,2031,2032,2033,2034,2035,2070,2071,2072,2073,2075,2076,2077,2078,2079,2080,2081,2082,2083,2085,2086,2087,2089,2090,2091,2092,2093,2137,2138,2139,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,2305,2306,2307,2362,2363,2364,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,2385,2386,2387,2388,2389,2390,2391,2402,2403,2433,2434,2435,2492,2494,2495,2496,2497,2498,2499,2500,2503,2504,2507,2508,2509,2519,2530,2531,2561,2562,2563,2620,2622,2623,2624,2625,2626,2631,2632,2635,2636,2637,2641,2672,2673,2677,2689,2690,2691,2748,2750,2751,2752,2753,2754,2755,2756,2757,2759,2760,2761,2763,2764,2765,2786,2787,2817,2818,2819,2876,2878,2879,2880,2881,2882,2883,2884,2887,2888,2891,2892,2893,2902,2903,2914,2915,2946,3006,3007,3008,3009,3010,3014,3015,3016,3018,3019,3020,3021,3031,3072,3073,3074,3075,3134,3135,3136,3137,3138,3139,3140,3142,3143,3144,3146,3147,3148,3149,3157,3158,3170,3171,3201,3202,3203,3260,3262,3263,3264,3265,3266,3267,3268,3270,3271,3272,3274,3275,3276,3277,3285,3286,3298,3299,3329,3330,3331,3390,3391,3392,3393,3394,3395,3396,3398,3399,3400,3402,3403,3404,3405,3415,3426,3427,3458,3459,3530,3535,3536,3537,3538,3539,3540,3542,3544,3545,3546,3547,3548,3549,3550,3551,3570,3571,3633,3636,3637,3638,3639,3640,3641,3642,3655,3656,3657,3658,3659,3660,3661,3662,3761,3764,3765,3766,3767,3768,3769,3771,3772,3784,3785,3786,3787,3788,3789,3864,3865,3893,3895,3897,3902,3903,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3974,3975,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,3993,3994,3995,3996,3997,3998,3999,4e3,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4038,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4182,4183,4184,4185,4190,4191,4192,4194,4195,4196,4199,4200,4201,4202,4203,4204,4205,4209,4210,4211,4212,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4239,4250,4251,4252,4253,4957,4958,4959,5906,5907,5908,5938,5939,5940,5970,5971,6002,6003,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6109,6155,6156,6157,6313,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,6679,6680,6681,6682,6683,6741,6742,6743,6744,6745,6746,6747,6748,6749,6750,6752,6753,6754,6755,6756,6757,6758,6759,6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,6779,6780,6783,6832,6833,6834,6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6912,6913,6914,6915,6916,6964,6965,6966,6967,6968,6969,6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,7019,7020,7021,7022,7023,7024,7025,7026,7027,7040,7041,7042,7073,7074,7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7142,7143,7144,7145,7146,7147,7148,7149,7150,7151,7152,7153,7154,7155,7204,7205,7206,7207,7208,7209,7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7376,7377,7378,7380,7381,7382,7383,7384,7385,7386,7387,7388,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7405,7410,7411,7412,7416,7417,7616,7617,7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7676,7677,7678,7679,8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,8420,8421,8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,11503,11504,11505,11647,11744,11745,11746,11747,11748,11749,11750,11751,11752,11753,11754,11755,11756,11757,11758,11759,11760,11761,11762,11763,11764,11765,11766,11767,11768,11769,11770,11771,11772,11773,11774,11775,12330,12331,12332,12333,12334,12335,12441,12442,42607,42608,42609,42610,42612,42613,42614,42615,42616,42617,42618,42619,42620,42621,42654,42655,42736,42737,43010,43014,43019,43043,43044,43045,43046,43047,43136,43137,43188,43189,43190,43191,43192,43193,43194,43195,43196,43197,43198,43199,43200,43201,43202,43203,43204,43232,43233,43234,43235,43236,43237,43238,43239,43240,43241,43242,43243,43244,43245,43246,43247,43248,43249,43302,43303,43304,43305,43306,43307,43308,43309,43335,43336,43337,43338,43339,43340,43341,43342,43343,43344,43345,43346,43347,43392,43393,43394,43395,43443,43444,43445,43446,43447,43448,43449,43450,43451,43452,43453,43454,43455,43456,43493,43561,43562,43563,43564,43565,43566,43567,43568,43569,43570,43571,43572,43573,43574,43587,43596,43597,43643,43644,43645,43696,43698,43699,43700,43703,43704,43710,43711,43713,43755,43756,43757,43758,43759,43765,43766,44003,44004,44005,44006,44007,44008,44009,44010,44012,44013,64286,65024,65025,65026,65027,65028,65029,65030,65031,65032,65033,65034,65035,65036,65037,65038,65039,65056,65057,65058,65059,65060,65061,65062,65063,65064,65065,65066,65067,65068,65069,65070,65071,66045,66272,66422,66423,66424,66425,66426,68097,68098,68099,68101,68102,68108,68109,68110,68111,68152,68153,68154,68159,68325,68326,69632,69633,69634,69688,69689,69690,69691,69692,69693,69694,69695,69696,69697,69698,69699,69700,69701,69702,69759,69760,69761,69762,69808,69809,69810,69811,69812,69813,69814,69815,69816,69817,69818,69888,69889,69890,69927,69928,69929,69930,69931,69932,69933,69934,69935,69936,69937,69938,69939,69940,70003,70016,70017,70018,70067,70068,70069,70070,70071,70072,70073,70074,70075,70076,70077,70078,70079,70080,70090,70091,70092,70188,70189,70190,70191,70192,70193,70194,70195,70196,70197,70198,70199,70367,70368,70369,70370,70371,70372,70373,70374,70375,70376,70377,70378,70400,70401,70402,70403,70460,70462,70463,70464,70465,70466,70467,70468,70471,70472,70475,70476,70477,70487,70498,70499,70502,70503,70504,70505,70506,70507,70508,70512,70513,70514,70515,70516,70832,70833,70834,70835,70836,70837,70838,70839,70840,70841,70842,70843,70844,70845,70846,70847,70848,70849,70850,70851,71087,71088,71089,71090,71091,71092,71093,71096,71097,71098,71099,71100,71101,71102,71103,71104,71132,71133,71216,71217,71218,71219,71220,71221,71222,71223,71224,71225,71226,71227,71228,71229,71230,71231,71232,71339,71340,71341,71342,71343,71344,71345,71346,71347,71348,71349,71350,71351,71453,71454,71455,71456,71457,71458,71459,71460,71461,71462,71463,71464,71465,71466,71467,92912,92913,92914,92915,92916,92976,92977,92978,92979,92980,92981,92982,94033,94034,94035,94036,94037,94038,94039,94040,94041,94042,94043,94044,94045,94046,94047,94048,94049,94050,94051,94052,94053,94054,94055,94056,94057,94058,94059,94060,94061,94062,94063,94064,94065,94066,94067,94068,94069,94070,94071,94072,94073,94074,94075,94076,94077,94078,94095,94096,94097,94098,113821,113822,119141,119142,119143,119144,119145,119149,119150,119151,119152,119153,119154,119163,119164,119165,119166,119167,119168,119169,119170,119173,119174,119175,119176,119177,119178,119179,119210,119211,119212,119213,119362,119363,119364,121344,121345,121346,121347,121348,121349,121350,121351,121352,121353,121354,121355,121356,121357,121358,121359,121360,121361,121362,121363,121364,121365,121366,121367,121368,121369,121370,121371,121372,121373,121374,121375,121376,121377,121378,121379,121380,121381,121382,121383,121384,121385,121386,121387,121388,121389,121390,121391,121392,121393,121394,121395,121396,121397,121398,121403,121404,121405,121406,121407,121408,121409,121410,121411,121412,121413,121414,121415,121416,121417,121418,121419,121420,121421,121422,121423,121424,121425,121426,121427,121428,121429,121430,121431,121432,121433,121434,121435,121436,121437,121438,121439,121440,121441,121442,121443,121444,121445,121446,121447,121448,121449,121450,121451,121452,121461,121476,121499,121500,121501,121502,121503,121505,121506,121507,121508,121509,121510,121511,121512,121513,121514,121515,121516,121517,121518,121519,125136,125137,125138,125139,125140,125141,125142,917760,917761,917762,917763,917764,917765,917766,917767,917768,917769,917770,917771,917772,917773,917774,917775,917776,917777,917778,917779,917780,917781,917782,917783,917784,917785,917786,917787,917788,917789,917790,917791,917792,917793,917794,917795,917796,917797,917798,917799,917800,917801,917802,917803,917804,917805,917806,917807,917808,917809,917810,917811,917812,917813,917814,917815,917816,917817,917818,917819,917820,917821,917822,917823,917824,917825,917826,917827,917828,917829,917830,917831,917832,917833,917834,917835,917836,917837,917838,917839,917840,917841,917842,917843,917844,917845,917846,917847,917848,917849,917850,917851,917852,917853,917854,917855,917856,917857,917858,917859,917860,917861,917862,917863,917864,917865,917866,917867,917868,917869,917870,917871,917872,917873,917874,917875,917876,917877,917878,917879,917880,917881,917882,917883,917884,917885,917886,917887,917888,917889,917890,917891,917892,917893,917894,917895,917896,917897,917898,917899,917900,917901,917902,917903,917904,917905,917906,917907,917908,917909,917910,917911,917912,917913,917914,917915,917916,917917,917918,917919,917920,917921,917922,917923,917924,917925,917926,917927,917928,917929,917930,917931,917932,917933,917934,917935,917936,917937,917938,917939,917940,917941,917942,917943,917944,917945,917946,917947,917948,917949,917950,917951,917952,917953,917954,917955,917956,917957,917958,917959,917960,917961,917962,917963,917964,917965,917966,917967,917968,917969,917970,917971,917972,917973,917974,917975,917976,917977,917978,917979,917980,917981,917982,917983,917984,917985,917986,917987,917988,917989,917990,917991,917992,917993,917994,917995,917996,917997,917998,917999]},"7f78":function(e,t,n){var r=n("23e7"),i=n("825a"),o=n("e163"),a=n("e177");r({target:"Reflect",stat:!0,sham:!a},{getPrototypeOf:function(e){return o(i(e))}})},"7f9a":function(e,t,n){var r=n("da84"),i=n("8925"),o=r.WeakMap;e.exports="function"===typeof o&&/native code/.test(i(o))},"80e0":function(e,t,n){var r=n("746f");r("replace")},8172:function(e,t,n){var r=n("746f");r("toPrimitive")},"81b8":function(e,t,n){var r=n("746f");r("unscopables")},"81d5":function(e,t,n){"use strict";var r=n("7b0b"),i=n("23cb"),o=n("50c4");e.exports=function(e){var t=r(this),n=o(t.length),a=arguments.length,s=i(a>1?arguments[1]:void 0,n),c=a>2?arguments[2]:void 0,u=void 0===c?n:i(c,n);while(u>s)t[s++]=e;return t}},"820e":function(e,t,n){"use strict";var r=n("23e7"),i=n("1c0b"),o=n("f069"),a=n("e667"),s=n("2266");r({target:"Promise",stat:!0},{allSettled:function(e){var t=this,n=o.f(t),r=n.resolve,c=n.reject,u=a((function(){var n=i(t.resolve),o=[],a=0,c=1;s(e,(function(e){var i=a++,s=!1;o.push(void 0),c++,n.call(t,e).then((function(e){s||(s=!0,o[i]={status:"fulfilled",value:e},--c||r(o))}),(function(e){s||(s=!0,o[i]={status:"rejected",reason:e},--c||r(o))}))})),--c||r(o)}));return u.error&&c(u.value),n.promise}})},"825a":function(e,t,n){var r=n("861d");e.exports=function(e){if(!r(e))throw TypeError(String(e)+" is not an object");return e}},"82cb":function(e,t){e.exports=function(e){var t="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",n={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},r={className:"doctag",begin:"@[A-Za-z]+"},i={begin:"#<",end:">"},o=[e.COMMENT("#","$",{contains:[r]}),e.COMMENT("^\\=begin","^\\=end",{contains:[r],relevance:10}),e.COMMENT("^__END__","\\n$")],a={className:"subst",begin:"#\\{",end:"}",keywords:n},s={className:"string",contains:[e.BACKSLASH_ESCAPE,a],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:"%[qQwWx]?\\(",end:"\\)"},{begin:"%[qQwWx]?\\[",end:"\\]"},{begin:"%[qQwWx]?{",end:"}"},{begin:"%[qQwWx]?<",end:">"},{begin:"%[qQwWx]?/",end:"/"},{begin:"%[qQwWx]?%",end:"%"},{begin:"%[qQwWx]?-",end:"-"},{begin:"%[qQwWx]?\\|",end:"\\|"},{begin:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{begin:/<<[-~]?'?(\w+)(?:.|\n)*?\n\s*\1\b/,returnBegin:!0,contains:[{begin:/<<[-~]?'?/},{begin:/\w+/,endSameAsBegin:!0,contains:[e.BACKSLASH_ESCAPE,a]}]}]},c={className:"params",begin:"\\(",end:"\\)",endsParent:!0,keywords:n},u=[s,i,{className:"class",beginKeywords:"class module",end:"$|;",illegal:/=/,contains:[e.inherit(e.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{begin:"<\\s*",contains:[{begin:"("+e.IDENT_RE+"::)?"+e.IDENT_RE}]}].concat(o)},{className:"function",beginKeywords:"def",end:"$|;",contains:[e.inherit(e.TITLE_MODE,{begin:t}),c].concat(o)},{begin:e.IDENT_RE+"::"},{className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"(\\!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[s,{begin:t}],relevance:0},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{className:"params",begin:/\|/,end:/\|/,keywords:n},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[i,{className:"regexp",contains:[e.BACKSLASH_ESCAPE,a],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:"%r{",end:"}[a-z]*"},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(o),relevance:0}].concat(o);a.contains=u,c.contains=u;var l="[>?]>",f="[\\w#]+\\(\\w+\\):\\d+:\\d+>",d="(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>",p=[{begin:/^\s*=>/,starts:{end:"$",contains:u}},{className:"meta",begin:"^("+l+"|"+f+"|"+d+")",starts:{end:"$",contains:u}}];return{aliases:["rb","gemspec","podspec","thor","irb"],keywords:n,illegal:/\/\*/,contains:o.concat(p).concat(u)}}},"82da":function(e,t,n){var r=n("23e7"),i=n("ebb5"),o=i.NATIVE_ARRAY_BUFFER_VIEWS;r({target:"ArrayBuffer",stat:!0,forced:!o},{isView:i.isView})},"82f8":function(e,t,n){"use strict";var r=n("ebb5"),i=n("4d64").includes,o=r.aTypedArray,a=r.exportTypedArrayMethod;a("includes",(function(e){return i(o(this),e,arguments.length>1?arguments[1]:void 0)}))},"83ab":function(e,t,n){var r=n("d039");e.exports=!r((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},8418:function(e,t,n){"use strict";var r=n("c04e"),i=n("9bf2"),o=n("5c6c");e.exports=function(e,t,n){var a=r(t);a in e?i.f(e,a,o(0,n)):e[a]=n}},"841c":function(e,t,n){"use strict";var r=n("d784"),i=n("825a"),o=n("1d80"),a=n("129f"),s=n("14c3");r("search",1,(function(e,t,n){return[function(t){var n=o(this),r=void 0==t?void 0:t[e];return void 0!==r?r.call(t,n):new RegExp(t)[e](String(n))},function(e){var r=n(t,e,this);if(r.done)return r.value;var o=i(e),c=String(this),u=o.lastIndex;a(u,0)||(o.lastIndex=0);var l=s(o,c);return a(o.lastIndex,u)||(o.lastIndex=u),null===l?-1:l.index}]}))},"843c":function(e,t,n){"use strict";var r=n("23e7"),i=n("0ccb").end,o=n("9a0c");r({target:"String",proto:!0,forced:o},{padEnd:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0)}})},"84c3":function(e,t,n){var r=n("74e8");r("Uint16",(function(e){return function(t,n,r){return e(this,t,n,r)}}))},8512:function(e,t,n){},"857a":function(e,t,n){var r=n("1d80"),i=/"/g;e.exports=function(e,t,n,o){var a=String(r(e)),s="<"+t;return""!==n&&(s+=" "+n+'="'+String(o).replace(i,""")+'"'),s+">"+a+""}},"861d":function(e,t){e.exports=function(e){return"object"===typeof e?null!==e:"function"===typeof e}},8925:function(e,t,n){var r=n("c6cd"),i=Function.toString;"function"!=typeof r.inspectSource&&(r.inspectSource=function(e){return i.call(e)}),e.exports=r.inspectSource},"8a59":function(e,t,n){var r=n("74e8");r("Uint8",(function(e){return function(t,n,r){return e(this,t,n,r)}}),!0)},"8a79":function(e,t,n){"use strict";var r=n("23e7"),i=n("06cf").f,o=n("50c4"),a=n("5a34"),s=n("1d80"),c=n("ab13"),u=n("c430"),l="".endsWith,f=Math.min,d=c("endsWith"),p=!u&&!d&&!!function(){var e=i(String.prototype,"endsWith");return e&&!e.writable}();r({target:"String",proto:!0,forced:!p&&!d},{endsWith:function(e){var t=String(s(this));a(e);var n=arguments.length>1?arguments[1]:void 0,r=o(t.length),i=void 0===n?r:f(o(n),r),c=String(e);return l?l.call(t,c,i):t.slice(i-c.length,i)===c}})},"8aa5":function(e,t,n){"use strict";var r=n("6547").charAt;e.exports=function(e,t,n){return t+(n?r(e,t).length:1)}},"8aa7":function(e,t,n){var r=n("da84"),i=n("d039"),o=n("1c7e"),a=n("ebb5").NATIVE_ARRAY_BUFFER_VIEWS,s=r.ArrayBuffer,c=r.Int8Array;e.exports=!a||!i((function(){c(1)}))||!i((function(){new c(-1)}))||!o((function(e){new c,new c(null),new c(1.5),new c(e)}),!0)||i((function(){return 1!==new c(new s(2),1,void 0).length}))},"8b09":function(e,t,n){var r=n("74e8");r("Int16",(function(e){return function(t,n,r){return e(this,t,n,r)}}))},"8b9a":function(e,t,n){var r=n("23e7"),i=n("825a"),o=n("3bbe"),a=n("d2bb");a&&r({target:"Reflect",stat:!0},{setPrototypeOf:function(e,t){i(e),o(t);try{return a(e,t),!0}catch(n){return!1}}})},"8ba4":function(e,t,n){var r=n("23e7"),i=n("5e89");r({target:"Number",stat:!0},{isInteger:i})},"8c4f":function(e,t,n){"use strict"; +/*! + * vue-router v3.5.1 + * (c) 2021 Evan You + * @license MIT + */function r(e,t){0}function i(e,t){for(var n in t)e[n]=t[n];return e}var o=/[!'()*]/g,a=function(e){return"%"+e.charCodeAt(0).toString(16)},s=/%2C/g,c=function(e){return encodeURIComponent(e).replace(o,a).replace(s,",")};function u(e){try{return decodeURIComponent(e)}catch(t){0}return e}function l(e,t,n){void 0===t&&(t={});var r,i=n||d;try{r=i(e||"")}catch(s){r={}}for(var o in t){var a=t[o];r[o]=Array.isArray(a)?a.map(f):f(a)}return r}var f=function(e){return null==e||"object"===typeof e?e:String(e)};function d(e){var t={};return e=e.trim().replace(/^(\?|#|&)/,""),e?(e.split("&").forEach((function(e){var n=e.replace(/\+/g," ").split("="),r=u(n.shift()),i=n.length>0?u(n.join("=")):null;void 0===t[r]?t[r]=i:Array.isArray(t[r])?t[r].push(i):t[r]=[t[r],i]})),t):t}function p(e){var t=e?Object.keys(e).map((function(t){var n=e[t];if(void 0===n)return"";if(null===n)return c(t);if(Array.isArray(n)){var r=[];return n.forEach((function(e){void 0!==e&&(null===e?r.push(c(t)):r.push(c(t)+"="+c(e)))})),r.join("&")}return c(t)+"="+c(n)})).filter((function(e){return e.length>0})).join("&"):null;return t?"?"+t:""}var h=/\/?$/;function v(e,t,n,r){var i=r&&r.options.stringifyQuery,o=t.query||{};try{o=g(o)}catch(s){}var a={name:t.name||e&&e.name,meta:e&&e.meta||{},path:t.path||"/",hash:t.hash||"",query:o,params:t.params||{},fullPath:y(t,i),matched:e?m(e):[]};return n&&(a.redirectedFrom=y(n,i)),Object.freeze(a)}function g(e){if(Array.isArray(e))return e.map(g);if(e&&"object"===typeof e){var t={};for(var n in e)t[n]=g(e[n]);return t}return e}var b=v(null,{path:"/"});function m(e){var t=[];while(e)t.unshift(e),e=e.parent;return t}function y(e,t){var n=e.path,r=e.query;void 0===r&&(r={});var i=e.hash;void 0===i&&(i="");var o=t||p;return(n||"/")+o(r)+i}function w(e,t,n){return t===b?e===t:!!t&&(e.path&&t.path?e.path.replace(h,"")===t.path.replace(h,"")&&(n||e.hash===t.hash&&_(e.query,t.query)):!(!e.name||!t.name)&&(e.name===t.name&&(n||e.hash===t.hash&&_(e.query,t.query)&&_(e.params,t.params))))}function _(e,t){if(void 0===e&&(e={}),void 0===t&&(t={}),!e||!t)return e===t;var n=Object.keys(e).sort(),r=Object.keys(t).sort();return n.length===r.length&&n.every((function(n,i){var o=e[n],a=r[i];if(a!==n)return!1;var s=t[n];return null==o||null==s?o===s:"object"===typeof o&&"object"===typeof s?_(o,s):String(o)===String(s)}))}function x(e,t){return 0===e.path.replace(h,"/").indexOf(t.path.replace(h,"/"))&&(!t.hash||e.hash===t.hash)&&E(e.query,t.query)}function E(e,t){for(var n in t)if(!(n in e))return!1;return!0}function S(e){for(var t=0;t=0&&(t=e.slice(r),e=e.slice(0,r));var i=e.indexOf("?");return i>=0&&(n=e.slice(i+1),e=e.slice(0,i)),{path:e,query:n,hash:t}}function T(e){return e.replace(/\/\//g,"/")}var R=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)},I=Y,N=D,j=F,P=z,L=X,$=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function D(e,t){var n,r=[],i=0,o=0,a="",s=t&&t.delimiter||"/";while(null!=(n=$.exec(e))){var c=n[0],u=n[1],l=n.index;if(a+=e.slice(o,l),o=l+c.length,u)a+=u[1];else{var f=e[o],d=n[2],p=n[3],h=n[4],v=n[5],g=n[6],b=n[7];a&&(r.push(a),a="");var m=null!=d&&null!=f&&f!==d,y="+"===g||"*"===g,w="?"===g||"*"===g,_=n[2]||s,x=h||v;r.push({name:p||i++,prefix:d||"",delimiter:_,optional:w,repeat:y,partial:m,asterisk:!!b,pattern:x?q(x):b?".*":"[^"+H(_)+"]+?"})}}return o1||!S.length)return 0===S.length?e():e("span",{},S)}if("a"===this.tag)E.on=_,E.attrs={href:c,"aria-current":m};else{var A=se(this.$slots.default);if(A){A.isStatic=!1;var k=A.data=i({},A.data);for(var O in k.on=k.on||{},k.on){var C=k.on[O];O in _&&(k.on[O]=Array.isArray(C)?C:[C])}for(var M in _)M in k.on?k.on[M].push(_[M]):k.on[M]=y;var T=A.data.attrs=i({},A.data.attrs);T.href=c,T["aria-current"]=m}else E.on=_}return e(this.tag,E,this.$slots.default)}};function ae(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&(void 0===e.button||0===e.button)){if(e.currentTarget&&e.currentTarget.getAttribute){var t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function se(e){if(e)for(var t,n=0;n-1&&(s.params[f]=n.params[f]);return s.path=Q(u.path,s.params,'named route "'+c+'"'),d(u,s,a)}if(s.path){s.params={};for(var p=0;p=e.length?n():e[i]?t(e[i],(function(){r(i+1)})):r(i+1)};r(0)}var Fe={redirected:2,aborted:4,cancelled:8,duplicated:16};function Be(e,t){return qe(e,t,Fe.redirected,'Redirected when going from "'+e.fullPath+'" to "'+Ve(t)+'" via a navigation guard.')}function Ue(e,t){var n=qe(e,t,Fe.duplicated,'Avoided redundant navigation to current location: "'+e.fullPath+'".');return n.name="NavigationDuplicated",n}function ze(e,t){return qe(e,t,Fe.cancelled,'Navigation cancelled from "'+e.fullPath+'" to "'+t.fullPath+'" with a new navigation.')}function He(e,t){return qe(e,t,Fe.aborted,'Navigation aborted from "'+e.fullPath+'" to "'+t.fullPath+'" via a navigation guard.')}function qe(e,t,n,r){var i=new Error(r);return i._isRouter=!0,i.from=e,i.to=t,i.type=n,i}var We=["params","query","hash"];function Ve(e){if("string"===typeof e)return e;if("path"in e)return e.path;var t={};return We.forEach((function(n){n in e&&(t[n]=e[n])})),JSON.stringify(t,null,2)}function Ke(e){return Object.prototype.toString.call(e).indexOf("Error")>-1}function Ge(e,t){return Ke(e)&&e._isRouter&&(null==t||e.type===t)}function Je(e){return function(t,n,r){var i=!1,o=0,a=null;Xe(e,(function(e,t,n,s){if("function"===typeof e&&void 0===e.cid){i=!0,o++;var c,u=et((function(t){Qe(t)&&(t=t.default),e.resolved="function"===typeof t?t:te.extend(t),n.components[s]=t,o--,o<=0&&r()})),l=et((function(e){var t="Failed to resolve async component "+s+": "+e;a||(a=Ke(e)?e:new Error(t),r(a))}));try{c=e(u,l)}catch(d){l(d)}if(c)if("function"===typeof c.then)c.then(u,l);else{var f=c.component;f&&"function"===typeof f.then&&f.then(u,l)}}})),i||r()}}function Xe(e,t){return Ye(e.map((function(e){return Object.keys(e.components).map((function(n){return t(e.components[n],e.instances[n],e,n)}))})))}function Ye(e){return Array.prototype.concat.apply([],e)}var Ze="function"===typeof Symbol&&"symbol"===typeof Symbol.toStringTag;function Qe(e){return e.__esModule||Ze&&"Module"===e[Symbol.toStringTag]}function et(e){var t=!1;return function(){var n=[],r=arguments.length;while(r--)n[r]=arguments[r];if(!t)return t=!0,e.apply(this,n)}}var tt=function(e,t){this.router=e,this.base=nt(t),this.current=b,this.pending=null,this.ready=!1,this.readyCbs=[],this.readyErrorCbs=[],this.errorCbs=[],this.listeners=[]};function nt(e){if(!e)if(ue){var t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^https?:\/\/[^\/]+/,"")}else e="/";return"/"!==e.charAt(0)&&(e="/"+e),e.replace(/\/$/,"")}function rt(e,t){var n,r=Math.max(e.length,t.length);for(n=0;n0)){var t=this.router,n=t.options.scrollBehavior,r=Pe&&n;r&&this.listeners.push(Ee());var i=function(){var n=e.current,i=dt(e.base);e.current===b&&i===e._startLocation||e.transitionTo(i,(function(e){r&&Se(t,e,n,!0)}))};window.addEventListener("popstate",i),this.listeners.push((function(){window.removeEventListener("popstate",i)}))}},t.prototype.go=function(e){window.history.go(e)},t.prototype.push=function(e,t,n){var r=this,i=this,o=i.current;this.transitionTo(e,(function(e){Le(T(r.base+e.fullPath)),Se(r.router,e,o,!1),t&&t(e)}),n)},t.prototype.replace=function(e,t,n){var r=this,i=this,o=i.current;this.transitionTo(e,(function(e){$e(T(r.base+e.fullPath)),Se(r.router,e,o,!1),t&&t(e)}),n)},t.prototype.ensureURL=function(e){if(dt(this.base)!==this.current.fullPath){var t=T(this.base+this.current.fullPath);e?Le(t):$e(t)}},t.prototype.getCurrentLocation=function(){return dt(this.base)},t}(tt);function dt(e){var t=window.location.pathname;return e&&0===t.toLowerCase().indexOf(e.toLowerCase())&&(t=t.slice(e.length)),(t||"/")+window.location.search+window.location.hash}var pt=function(e){function t(t,n,r){e.call(this,t,n),r&&ht(this.base)||vt()}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.setupListeners=function(){var e=this;if(!(this.listeners.length>0)){var t=this.router,n=t.options.scrollBehavior,r=Pe&&n;r&&this.listeners.push(Ee());var i=function(){var t=e.current;vt()&&e.transitionTo(gt(),(function(n){r&&Se(e.router,n,t,!0),Pe||yt(n.fullPath)}))},o=Pe?"popstate":"hashchange";window.addEventListener(o,i),this.listeners.push((function(){window.removeEventListener(o,i)}))}},t.prototype.push=function(e,t,n){var r=this,i=this,o=i.current;this.transitionTo(e,(function(e){mt(e.fullPath),Se(r.router,e,o,!1),t&&t(e)}),n)},t.prototype.replace=function(e,t,n){var r=this,i=this,o=i.current;this.transitionTo(e,(function(e){yt(e.fullPath),Se(r.router,e,o,!1),t&&t(e)}),n)},t.prototype.go=function(e){window.history.go(e)},t.prototype.ensureURL=function(e){var t=this.current.fullPath;gt()!==t&&(e?mt(t):yt(t))},t.prototype.getCurrentLocation=function(){return gt()},t}(tt);function ht(e){var t=dt(e);if(!/^\/#/.test(t))return window.location.replace(T(e+"/#"+t)),!0}function vt(){var e=gt();return"/"===e.charAt(0)||(yt("/"+e),!1)}function gt(){var e=window.location.href,t=e.indexOf("#");return t<0?"":(e=e.slice(t+1),e)}function bt(e){var t=window.location.href,n=t.indexOf("#"),r=n>=0?t.slice(0,n):t;return r+"#"+e}function mt(e){Pe?Le(bt(e)):window.location.hash=e}function yt(e){Pe?$e(bt(e)):window.location.replace(bt(e))}var wt=function(e){function t(t,n){e.call(this,t,n),this.stack=[],this.index=-1}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.push=function(e,t,n){var r=this;this.transitionTo(e,(function(e){r.stack=r.stack.slice(0,r.index+1).concat(e),r.index++,t&&t(e)}),n)},t.prototype.replace=function(e,t,n){var r=this;this.transitionTo(e,(function(e){r.stack=r.stack.slice(0,r.index).concat(e),t&&t(e)}),n)},t.prototype.go=function(e){var t=this,n=this.index+e;if(!(n<0||n>=this.stack.length)){var r=this.stack[n];this.confirmTransition(r,(function(){var e=t.current;t.index=n,t.updateRoute(r),t.router.afterHooks.forEach((function(t){t&&t(r,e)}))}),(function(e){Ge(e,Fe.duplicated)&&(t.index=n)}))}},t.prototype.getCurrentLocation=function(){var e=this.stack[this.stack.length-1];return e?e.fullPath:"/"},t.prototype.ensureURL=function(){},t}(tt),_t=function(e){void 0===e&&(e={}),this.app=null,this.apps=[],this.options=e,this.beforeHooks=[],this.resolveHooks=[],this.afterHooks=[],this.matcher=he(e.routes||[],this);var t=e.mode||"hash";switch(this.fallback="history"===t&&!Pe&&!1!==e.fallback,this.fallback&&(t="hash"),ue||(t="abstract"),this.mode=t,t){case"history":this.history=new ft(this,e.base);break;case"hash":this.history=new pt(this,e.base,this.fallback);break;case"abstract":this.history=new wt(this,e.base);break;default:0}},xt={currentRoute:{configurable:!0}};function Et(e,t){return e.push(t),function(){var n=e.indexOf(t);n>-1&&e.splice(n,1)}}function St(e,t,n){var r="hash"===n?"#"+t:t;return e?T(e+"/"+r):r}_t.prototype.match=function(e,t,n){return this.matcher.match(e,t,n)},xt.currentRoute.get=function(){return this.history&&this.history.current},_t.prototype.init=function(e){var t=this;if(this.apps.push(e),e.$once("hook:destroyed",(function(){var n=t.apps.indexOf(e);n>-1&&t.apps.splice(n,1),t.app===e&&(t.app=t.apps[0]||null),t.app||t.history.teardown()})),!this.app){this.app=e;var n=this.history;if(n instanceof ft||n instanceof pt){var r=function(e){var r=n.current,i=t.options.scrollBehavior,o=Pe&&i;o&&"fullPath"in e&&Se(t,e,r,!1)},i=function(e){n.setupListeners(),r(e)};n.transitionTo(n.getCurrentLocation(),i,i)}n.listen((function(e){t.apps.forEach((function(t){t._route=e}))}))}},_t.prototype.beforeEach=function(e){return Et(this.beforeHooks,e)},_t.prototype.beforeResolve=function(e){return Et(this.resolveHooks,e)},_t.prototype.afterEach=function(e){return Et(this.afterHooks,e)},_t.prototype.onReady=function(e,t){this.history.onReady(e,t)},_t.prototype.onError=function(e){this.history.onError(e)},_t.prototype.push=function(e,t,n){var r=this;if(!t&&!n&&"undefined"!==typeof Promise)return new Promise((function(t,n){r.history.push(e,t,n)}));this.history.push(e,t,n)},_t.prototype.replace=function(e,t,n){var r=this;if(!t&&!n&&"undefined"!==typeof Promise)return new Promise((function(t,n){r.history.replace(e,t,n)}));this.history.replace(e,t,n)},_t.prototype.go=function(e){this.history.go(e)},_t.prototype.back=function(){this.go(-1)},_t.prototype.forward=function(){this.go(1)},_t.prototype.getMatchedComponents=function(e){var t=e?e.matched?e:this.resolve(e).route:this.currentRoute;return t?[].concat.apply([],t.matched.map((function(e){return Object.keys(e.components).map((function(t){return e.components[t]}))}))):[]},_t.prototype.resolve=function(e,t,n){t=t||this.history.current;var r=ee(e,t,n,this),i=this.match(r,t),o=i.redirectedFrom||i.fullPath,a=this.history.base,s=St(a,o,this.mode);return{location:r,route:i,href:s,normalizedTo:r,resolved:i}},_t.prototype.getRoutes=function(){return this.matcher.getRoutes()},_t.prototype.addRoute=function(e,t){this.matcher.addRoute(e,t),this.history.current!==b&&this.history.transitionTo(this.history.getCurrentLocation())},_t.prototype.addRoutes=function(e){this.matcher.addRoutes(e),this.history.current!==b&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(_t.prototype,xt),_t.install=ce,_t.version="3.5.1",_t.isNavigationFailure=Ge,_t.NavigationFailureType=Fe,_t.START_LOCATION=b,ue&&window.Vue&&window.Vue.use(_t),t["a"]=_t},"8dcb":function(e,t){e.exports=function(e){var t="[A-Za-z0-9\\._:-]+",n={className:"symbol",begin:"&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;"},r={begin:"\\s",contains:[{className:"meta-keyword",begin:"#?[a-z_][a-z1-9_-]+",illegal:"\\n"}]},i=e.inherit(r,{begin:"\\(",end:"\\)"}),o=e.inherit(e.APOS_STRING_MODE,{className:"meta-string"}),a=e.inherit(e.QUOTE_STRING_MODE,{className:"meta-string"}),s={endsWithParent:!0,illegal:/`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin:"",relevance:10,contains:[r,a,o,i,{begin:"\\[",end:"\\]",contains:[{className:"meta",begin:"",contains:[r,i,a,o]}]}]},e.COMMENT("\x3c!--","--\x3e",{relevance:10}),{begin:"<\\!\\[CDATA\\[",end:"\\]\\]>",relevance:10},n,{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{begin:/<\?(php)?/,end:/\?>/,subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0},{begin:'b"',end:'"',skip:!0},{begin:"b'",end:"'",skip:!0},e.inherit(e.APOS_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0})]},{className:"tag",begin:")",end:">",keywords:{name:"style"},contains:[s],starts:{end:"",returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:")",end:">",keywords:{name:"script"},contains:[s],starts:{end:"<\/script>",returnEnd:!0,subLanguage:["actionscript","javascript","handlebars","xml"]}},{className:"tag",begin:"",contains:[{className:"name",begin:/[^\/><\s]+/,relevance:0},s]}]}}},"8eb5":function(e,t){var n=Math.expm1,r=Math.exp;e.exports=!n||n(10)>22025.465794806718||n(10)<22025.465794806718||-2e-17!=n(-2e-17)?function(e){return 0==(e=+e)?e:e>-1e-6&&e<1e-6?e+e*e/2:r(e)-1}:n},"8ed1":function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}},i=r(n("8dcb"));e.exports=i.default},"8edd":function(e,t,n){var r=n("746f");r("matchAll")},"90d7":function(e,t,n){var r=n("23e7"),i=Math.log,o=Math.LN2;r({target:"Math",stat:!0},{log2:function(e){return i(e)/o}})},"90e3":function(e,t){var n=0,r=Math.random();e.exports=function(e){return"Symbol("+String(void 0===e?"":e)+")_"+(++n+r).toString(36)}},9112:function(e,t,n){var r=n("83ab"),i=n("9bf2"),o=n("5c6c");e.exports=r?function(e,t,n){return i.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},9129:function(e,t,n){var r=n("23e7");r({target:"Number",stat:!0},{isNaN:function(e){return e!=e}})},9263:function(e,t,n){"use strict";var r=n("ad6d"),i=n("9f7f"),o=n("5692"),a=RegExp.prototype.exec,s=o("native-string-replace",String.prototype.replace),c=a,u=function(){var e=/a/,t=/b*/g;return a.call(e,"a"),a.call(t,"a"),0!==e.lastIndex||0!==t.lastIndex}(),l=i.UNSUPPORTED_Y||i.BROKEN_CARET,f=void 0!==/()??/.exec("")[1],d=u||f||l;d&&(c=function(e){var t,n,i,o,c=this,d=l&&c.sticky,p=r.call(c),h=c.source,v=0,g=e;return d&&(p=p.replace("y",""),-1===p.indexOf("g")&&(p+="g"),g=String(e).slice(c.lastIndex),c.lastIndex>0&&(!c.multiline||c.multiline&&"\n"!==e[c.lastIndex-1])&&(h="(?: "+h+")",g=" "+g,v++),n=new RegExp("^(?:"+h+")",p)),f&&(n=new RegExp("^"+h+"$(?!\\s)",p)),u&&(t=c.lastIndex),i=a.call(d?n:c,g),d?i?(i.input=i.input.slice(v),i[0]=i[0].slice(v),i.index=c.lastIndex,c.lastIndex+=i[0].length):c.lastIndex=0:u&&i&&(c.lastIndex=c.global?i.index+i[0].length:t),f&&i&&i.length>1&&s.call(i[0],n,(function(){for(o=1;o>>|\.\.\.) /},r={className:"subst",begin:/\{/,end:/\}/,keywords:t,illegal:/#/},i={begin:/\{\{/,relevance:0},o={className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:/(u|b)?r?'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,n],relevance:10},{begin:/(u|b)?r?"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,n],relevance:10},{begin:/(fr|rf|f)'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,n,i,r]},{begin:/(fr|rf|f)"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,n,i,r]},{begin:/(u|r|ur)'/,end:/'/,relevance:10},{begin:/(u|r|ur)"/,end:/"/,relevance:10},{begin:/(b|br)'/,end:/'/},{begin:/(b|br)"/,end:/"/},{begin:/(fr|rf|f)'/,end:/'/,contains:[e.BACKSLASH_ESCAPE,i,r]},{begin:/(fr|rf|f)"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,i,r]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},a={className:"number",relevance:0,variants:[{begin:e.BINARY_NUMBER_RE+"[lLjJ]?"},{begin:"\\b(0o[0-7]+)[lLjJ]?"},{begin:e.C_NUMBER_RE+"[lLjJ]?"}]},s={className:"params",begin:/\(/,end:/\)/,contains:["self",n,a,o,e.HASH_COMMENT_MODE]};return r.contains=[o,a,n],{aliases:["py","gyp","ipython"],keywords:t,illegal:/(<\/|->|\?)|=>/,contains:[n,a,{beginKeywords:"if",relevance:0},o,e.HASH_COMMENT_MODE,{variants:[{className:"function",beginKeywords:"def"},{className:"class",beginKeywords:"class"}],end:/:/,illegal:/[${=;\n,]/,contains:[e.UNDERSCORE_TITLE_MODE,s,{begin:/->/,endsWithParent:!0,keywords:"None"}]},{className:"meta",begin:/^[\t ]*@/,end:/$/},{begin:/\b(print|exec)\(/}]}}},"967a":function(e,t,n){"use strict";var r=n("23e7"),i=n("e163"),o=n("d2bb"),a=n("7c73"),s=n("9112"),c=n("5c6c"),u=n("2266"),l=function(e,t){var n=this;if(!(n instanceof l))return new l(e,t);o&&(n=o(new Error(void 0),i(n))),void 0!==t&&s(n,"message",String(t));var r=[];return u(e,r.push,{that:r}),s(n,"errors",r),n};l.prototype=a(Error.prototype,{constructor:c(5,l),message:c(5,""),name:c(5,"AggregateError")}),r({global:!0},{AggregateError:l})},9767:function(e,t,n){"use strict";var r=n("23e7"),i=n("857a"),o=n("af03");r({target:"String",proto:!0,forced:o("fontcolor")},{fontcolor:function(e){return i(this,"font","color",e)}})},9861:function(e,t,n){"use strict";n("e260");var r=n("23e7"),i=n("d066"),o=n("0d3b"),a=n("6eeb"),s=n("e2cc"),c=n("d44e"),u=n("9ed3"),l=n("69f3"),f=n("19aa"),d=n("5135"),p=n("0366"),h=n("f5df"),v=n("825a"),g=n("861d"),b=n("7c73"),m=n("5c6c"),y=n("9a1f"),w=n("35a1"),_=n("b622"),x=i("fetch"),E=i("Headers"),S=_("iterator"),A="URLSearchParams",k=A+"Iterator",O=l.set,C=l.getterFor(A),M=l.getterFor(k),T=/\+/g,R=Array(4),I=function(e){return R[e-1]||(R[e-1]=RegExp("((?:%[\\da-f]{2}){"+e+"})","gi"))},N=function(e){try{return decodeURIComponent(e)}catch(t){return e}},j=function(e){var t=e.replace(T," "),n=4;try{return decodeURIComponent(t)}catch(r){while(n)t=t.replace(I(n--),N);return t}},P=/[!'()~]|%20/g,L={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+"},$=function(e){return L[e]},D=function(e){return encodeURIComponent(e).replace(P,$)},F=function(e,t){if(t){var n,r,i=t.split("&"),o=0;while(o0?arguments[0]:void 0,l=this,p=[];if(O(l,{type:A,entries:p,updateURL:function(){},updateSearchParams:B}),void 0!==u)if(g(u))if(e=w(u),"function"===typeof e){t=e.call(u),n=t.next;while(!(r=n.call(t)).done){if(i=y(v(r.value)),o=i.next,(a=o.call(i)).done||(s=o.call(i)).done||!o.call(i).done)throw TypeError("Expected sequence with length 2");p.push({key:a.value+"",value:s.value+""})}}else for(c in u)d(u,c)&&p.push({key:c,value:u[c]+""});else F(p,"string"===typeof u?"?"===u.charAt(0)?u.slice(1):u:u+"")},q=H.prototype;s(q,{append:function(e,t){U(arguments.length,2);var n=C(this);n.entries.push({key:e+"",value:t+""}),n.updateURL()},delete:function(e){U(arguments.length,1);var t=C(this),n=t.entries,r=e+"",i=0;while(ie.key){i.splice(t,0,e);break}t===n&&i.push(e)}r.updateURL()},forEach:function(e){var t,n=C(this).entries,r=p(e,arguments.length>1?arguments[1]:void 0,3),i=0;while(i1&&(t=arguments[1],g(t)&&(n=t.body,h(n)===A&&(r=t.headers?new E(t.headers):new E,r.has("content-type")||r.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"),t=b(t,{body:m(0,String(n)),headers:m(0,r)}))),i.push(t)),x.apply(this,i)}}),e.exports={URLSearchParams:H,getState:C}},"98c9":function(e,t,n){"use strict";var r=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{attrs:{id:"particles-js",color:e.color,particleOpacity:e.particleOpacity,linesColor:e.linesColor,particlesNumber:e.particlesNumber,shapeType:e.shapeType,particleSize:e.particleSize,linesWidth:e.linesWidth,lineLinked:e.lineLinked,lineOpacity:e.lineOpacity,linesDistance:e.linesDistance,moveSpeed:e.moveSpeed,hoverEffect:e.hoverEffect,hoverMode:e.hoverMode,clickEffect:e.clickEffect,clickMode:e.clickMode}})},i=[],o=(n("a9e3"),{name:"vue-particles",props:{color:{type:String,default:"#dedede"},particleOpacity:{type:Number,default:.7},particlesNumber:{type:Number,default:80},shapeType:{type:String,default:"circle"},particleSize:{type:Number,default:4},linesColor:{type:String,default:"#dedede"},linesWidth:{type:Number,default:1},lineLinked:{type:Boolean,default:!0},lineOpacity:{type:Number,default:.4},linesDistance:{type:Number,default:150},moveSpeed:{type:Number,default:3},hoverEffect:{type:Boolean,default:!0},hoverMode:{type:String,default:"grab"},clickEffect:{type:Boolean,default:!0},clickMode:{type:String,default:"push"}},mounted:function(){var e=this;n("572f"),this.$nextTick((function(){e.initParticleJS(e.color,e.particleOpacity,e.particlesNumber,e.shapeType,e.particleSize,e.linesColor,e.linesWidth,e.lineLinked,e.lineOpacity,e.linesDistance,e.moveSpeed,e.hoverEffect,e.hoverMode,e.clickEffect,e.clickMode)}))},methods:{initParticleJS:function(e,t,n,r,i,o,a,s,c,u,l,f,d,p,h){particlesJS("particles-js",{particles:{number:{value:n,density:{enable:!0,value_area:800}},color:{value:e},shape:{type:r,stroke:{width:0,color:"#192231"},polygon:{nb_sides:5}},opacity:{value:t,random:!1,anim:{enable:!1,speed:1,opacity_min:.1,sync:!1}},size:{value:i,random:!0,anim:{enable:!1,speed:40,size_min:.1,sync:!1}},line_linked:{enable:s,distance:u,color:o,opacity:c,width:a},move:{enable:!0,speed:l,direction:"none",random:!1,straight:!1,out_mode:"out",bounce:!1,attract:{enable:!1,rotateX:600,rotateY:1200}}},interactivity:{detect_on:"canvas",events:{onhover:{enable:f,mode:d},onclick:{enable:p,mode:h},onresize:{enable:!0,density_auto:!0,density_area:400}},modes:{grab:{distance:140,line_linked:{opacity:1}},bubble:{distance:400,size:40,duration:2,opacity:8,speed:3},repulse:{distance:200,duration:.4},push:{particles_nb:4},remove:{particles_nb:2}}},retina_detect:!0})}}}),a=o,s=n("2877"),c=Object(s["a"])(a,r,i,!1,null,null,null),u=c.exports;const l={install(e,t){e.component("vue-particles",u)}};t["a"]=l},9911:function(e,t,n){"use strict";var r=n("23e7"),i=n("857a"),o=n("af03");r({target:"String",proto:!0,forced:o("link")},{link:function(e){return i(this,"a","href",e)}})},"99af":function(e,t,n){"use strict";var r=n("23e7"),i=n("d039"),o=n("e8b5"),a=n("861d"),s=n("7b0b"),c=n("50c4"),u=n("8418"),l=n("65f0"),f=n("1dde"),d=n("b622"),p=n("2d00"),h=d("isConcatSpreadable"),v=9007199254740991,g="Maximum allowed index exceeded",b=p>=51||!i((function(){var e=[];return e[h]=!1,e.concat()[0]!==e})),m=f("concat"),y=function(e){if(!a(e))return!1;var t=e[h];return void 0!==t?!!t:o(e)},w=!b||!m;r({target:"Array",proto:!0,forced:w},{concat:function(e){var t,n,r,i,o,a=s(this),f=l(a,0),d=0;for(t=-1,r=arguments.length;tv)throw TypeError(g);for(n=0;n=v)throw TypeError(g);u(f,d++,o)}return f.length=d,f}})},"9a0c":function(e,t,n){var r=n("342f");e.exports=/Version\/10(?:\.\d+){1,2}(?: [\w./]+)?(?: Mobile\/\w+)? Safari\//.test(r)},"9a1f":function(e,t,n){var r=n("825a"),i=n("35a1");e.exports=function(e){var t=i(e);if("function"!=typeof t)throw TypeError(String(e)+" is not iterable");return r(t.call(e))}},"9a8c":function(e,t,n){"use strict";var r=n("ebb5"),i=n("145e"),o=r.aTypedArray,a=r.exportTypedArrayMethod;a("copyWithin",(function(e,t){return i.call(o(this),e,t,arguments.length>2?arguments[2]:void 0)}))},"9bdd":function(e,t,n){var r=n("825a"),i=n("2a62");e.exports=function(e,t,n,o){try{return o?t(r(n)[0],n[1]):t(n)}catch(a){throw i(e),a}}},"9bf2":function(e,t,n){var r=n("83ab"),i=n("0cfb"),o=n("825a"),a=n("c04e"),s=Object.defineProperty;t.f=r?s:function(e,t,n){if(o(e),t=a(t,!0),o(n),i)try{return s(e,t,n)}catch(r){}if("get"in n||"set"in n)throw TypeError("Accessors not supported");return"value"in n&&(e[t]=n.value),e}},"9e4a":function(e,t,n){var r=n("23e7"),i=n("83ab"),o=n("825a"),a=n("06cf");r({target:"Reflect",stat:!0,sham:!i},{getOwnPropertyDescriptor:function(e,t){return a.f(o(e),t)}})},"9ed3":function(e,t,n){"use strict";var r=n("ae93").IteratorPrototype,i=n("7c73"),o=n("5c6c"),a=n("d44e"),s=n("3f8c"),c=function(){return this};e.exports=function(e,t,n){var u=t+" Iterator";return e.prototype=i(r,{next:o(1,n)}),a(e,u,!1,!0),s[u]=c,e}},"9f7f":function(e,t,n){"use strict";var r=n("d039");function i(e,t){return RegExp(e,t)}t.UNSUPPORTED_Y=r((function(){var e=i("a","y");return e.lastIndex=2,null!=e.exec("abcd")})),t.BROKEN_CARET=r((function(){var e=i("^r","gy");return e.lastIndex=2,null!=e.exec("str")}))},"9f7fc":function(e,t){e.exports=function(e){var t={className:"meta",begin:"@[A-Za-z]+"},n={className:"subst",variants:[{begin:"\\$[A-Za-z0-9_]+"},{begin:"\\${",end:"}"}]},r={className:"string",variants:[{begin:'"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:'"""',end:'"""',relevance:10},{begin:'[a-z]+"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE,n]},{className:"string",begin:'[a-z]+"""',end:'"""',contains:[n],relevance:10}]},i={className:"symbol",begin:"'\\w[\\w\\d_]*(?!')"},o={className:"type",begin:"\\b[A-Z][A-Za-z0-9_]*",relevance:0},a={className:"title",begin:/[^0-9\n\t "'(),.`{}\[\]:;][^\n\t "'(),.`{}\[\]:;]+|[^0-9\n\t "'(),.`{}\[\]:;=]/,relevance:0},s={className:"class",beginKeywords:"class object trait type",end:/[:={\[\n;]/,excludeEnd:!0,contains:[{beginKeywords:"extends with",relevance:10},{begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[o]},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[o]},a]},c={className:"function",beginKeywords:"def",end:/[:={\[(\n;]/,excludeEnd:!0,contains:[a]};return{keywords:{literal:"true false null",keyword:"type yield lazy override def with val var sealed abstract private trait object if forSome for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit"},contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,r,i,o,c,s,e.C_NUMBER_MODE,t]}}},"9f96":function(e,t,n){var r=n("23e7"),i=n("da84"),o=n("b575"),a=n("605d"),s=i.process;r({global:!0,enumerable:!0,noTargetGet:!0},{queueMicrotask:function(e){var t=a&&s.domain;o(t?t.bind(e):e)}})},"9ff9":function(e,t,n){var r=n("23e7"),i=Math.atanh,o=Math.log;r({target:"Math",stat:!0,forced:!(i&&1/i(-0)<0)},{atanh:function(e){return 0==(e=+e)?e:o((1+e)/(1-e))/2}})},a078:function(e,t,n){var r=n("7b0b"),i=n("50c4"),o=n("35a1"),a=n("e95a"),s=n("0366"),c=n("ebb5").aTypedArrayConstructor;e.exports=function(e){var t,n,u,l,f,d,p=r(e),h=arguments.length,v=h>1?arguments[1]:void 0,g=void 0!==v,b=o(p);if(void 0!=b&&!a(b)){f=b.call(p),d=f.next,p=[];while(!(l=d.call(f)).done)p.push(l.value)}for(g&&h>2&&(v=s(v,arguments[2],2)),n=i(p.length),u=new(c(this))(n),t=0;n>t;t++)u[t]=g?v(p[t],t):p[t];return u}},a15b:function(e,t,n){"use strict";var r=n("23e7"),i=n("44ad"),o=n("fc6a"),a=n("a640"),s=[].join,c=i!=Object,u=a("join",",");r({target:"Array",proto:!0,forced:c||!u},{join:function(e){return s.call(o(this),void 0===e?",":e)}})},a1f0:function(e,t,n){"use strict";var r=n("23e7"),i=n("9ed3"),o=n("1d80"),a=n("50c4"),s=n("1c0b"),c=n("825a"),u=n("c6b6"),l=n("44e7"),f=n("ad6d"),d=n("9112"),p=n("d039"),h=n("b622"),v=n("4840"),g=n("8aa5"),b=n("69f3"),m=n("c430"),y=h("matchAll"),w="RegExp String",_=w+" Iterator",x=b.set,E=b.getterFor(_),S=RegExp.prototype,A=S.exec,k="".matchAll,O=!!k&&!p((function(){"a".matchAll(/./)})),C=function(e,t){var n,r=e.exec;if("function"==typeof r){if(n=r.call(e,t),"object"!=typeof n)throw TypeError("Incorrect exec result");return n}return A.call(e,t)},M=i((function(e,t,n,r){x(this,{type:_,regexp:e,string:t,global:n,unicode:r,done:!1})}),w,(function(){var e=E(this);if(e.done)return{value:void 0,done:!0};var t=e.regexp,n=e.string,r=C(t,n);return null===r?{value:void 0,done:e.done=!0}:e.global?(""==String(r[0])&&(t.lastIndex=g(n,a(t.lastIndex),e.unicode)),{value:r,done:!1}):(e.done=!0,{value:r,done:!1})})),T=function(e){var t,n,r,i,o,s,u=c(this),l=String(e);return t=v(u,RegExp),n=u.flags,void 0===n&&u instanceof RegExp&&!("flags"in S)&&(n=f.call(u)),r=void 0===n?"":String(n),i=new t(t===RegExp?u.source:u,r),o=!!~r.indexOf("g"),s=!!~r.indexOf("u"),i.lastIndex=a(u.lastIndex),new M(i,l,o,s)};r({target:"String",proto:!0,forced:O},{matchAll:function(e){var t,n,r,i,a=o(this);if(null!=e){if(l(e)&&(t=String(o("flags"in S?e.flags:f.call(e))),!~t.indexOf("g")))throw TypeError("`.matchAll` does not allow non-global regexes");if(O)return k.apply(a,arguments);if(r=e[y],void 0===r&&m&&"RegExp"==u(e)&&(r=T),null!=r)return s(r).call(e,a)}else if(O)return k.apply(a,arguments);return n=String(a),i=new RegExp(e,"g"),m?T.call(i,n):i[y](n)}}),m||y in S||d(S,y,T)},a2bf:function(e,t,n){"use strict";var r=n("e8b5"),i=n("50c4"),o=n("0366"),a=function(e,t,n,s,c,u,l,f){var d,p=c,h=0,v=!!l&&o(l,f,3);while(h0&&r(d))p=a(e,t,d,i(d.length),p,u-1)-1;else{if(p>=9007199254740991)throw TypeError("Exceed the acceptable array length");e[p]=d}p++}h++}return p};e.exports=a},a434:function(e,t,n){"use strict";var r=n("23e7"),i=n("23cb"),o=n("a691"),a=n("50c4"),s=n("7b0b"),c=n("65f0"),u=n("8418"),l=n("1dde"),f=l("splice"),d=Math.max,p=Math.min,h=9007199254740991,v="Maximum allowed length exceeded";r({target:"Array",proto:!0,forced:!f},{splice:function(e,t){var n,r,l,f,g,b,m=s(this),y=a(m.length),w=i(e,y),_=arguments.length;if(0===_?n=r=0:1===_?(n=0,r=y-w):(n=_-2,r=p(d(o(t),0),y-w)),y+n-r>h)throw TypeError(v);for(l=c(m,r),f=0;fy-r+n;f--)delete m[f-1]}else if(n>r)for(f=y-r;f>w;f--)g=f+r-1,b=f+n-1,g in m?m[b]=m[g]:delete m[b];for(f=0;fo)i.push(arguments[o++]);if(r=t,(p(t)||void 0!==e)&&!se(e))return d(t)||(t=function(e,t){if("function"==typeof r&&(t=r.call(this,e,t)),!se(t))return t}),i[1]=t,K.apply(null,i)}})}V[U][z]||O(V[U],z,V[U].valueOf),L(V,B),R[F]=!0},a623:function(e,t,n){"use strict";var r=n("23e7"),i=n("b727").every,o=n("a640"),a=o("every");r({target:"Array",proto:!0,forced:!a},{every:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0)}})},a630:function(e,t,n){var r=n("23e7"),i=n("4df4"),o=n("1c7e"),a=!o((function(e){Array.from(e)}));r({target:"Array",stat:!0,forced:a},{from:i})},a640:function(e,t,n){"use strict";var r=n("d039");e.exports=function(e,t){var n=[][e];return!!n&&r((function(){n.call(null,t||function(){throw 1},1)}))}},a691:function(e,t){var n=Math.ceil,r=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?r:n)(e)}},a6fd:function(e,t,n){var r=n("23e7"),i=n("d066"),o=n("1c0b"),a=n("825a"),s=n("d039"),c=i("Reflect","apply"),u=Function.apply,l=!s((function(){c((function(){}))}));r({target:"Reflect",stat:!0,forced:l},{apply:function(e,t,n){return o(e),a(n),c?c(e,t,n):u.call(e,t,n)}})},a70e:function(e,t,n){(function(n){var r,i;(function(n){var o="object"===typeof window&&window||"object"===typeof self&&self;t.nodeType?o&&(o.hljs=n({}),r=[],i=function(){return o.hljs}.apply(t,r),void 0===i||(e.exports=i)):n(t)})((function(e){var t,r=!1,i=[],o=Object.keys,a=Object.create(null),s=Object.create(null),c=!0,u=/^(no-?highlight|plain|text)$/i,l=/\blang(?:uage)?-([\w-]+)\b/i,f=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,d="",p="Could not find the language '{}', did you forget to load/include a language module?",h={hideUpgradeWarningAcceptNoSupportOrSecurityUpdates:!1,classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},v="of and for in not or if then".split(" ");function g(e){return e.replace(/&/g,"&").replace(//g,">")}function b(e){return e.nodeName.toLowerCase()}function m(e,t){var n=e&&e.exec(t);return n&&0===n.index}function y(e){return u.test(e)}function w(e){var t,n,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",n=l.exec(o),n){var a=q(n[1]);return a||(console.warn(p.replace("{}",n[1])),console.warn("Falling back to no-highlight mode for this block.",e)),a?n[1]:"no-highlight"}for(o=o.split(/\s+/),t=0,r=o.length;t"}function u(e){o+=""}function l(e){("start"===e.event?c:u)(e.node)}while(e.length||t.length){var f=s();if(o+=g(n.substring(r,f[0].offset)),r=f[0].offset,f===e){a.reverse().forEach(u);do{l(f.splice(0,1)[0]),f=s()}while(f===e&&f.length&&f[0].offset===r);a.reverse().forEach(c)}else"start"===f[0].event?a.push(f[0].node):a.pop(),l(f.splice(0,1)[0])}return o+g(n.substr(r))}function S(e){return!!e&&(e.endsWithParent||S(e.starts))}function A(e){return e.variants&&!e.cached_variants&&(e.cached_variants=e.variants.map((function(t){return _(e,{variants:null},t)}))),e.cached_variants?e.cached_variants:S(e)?[_(e,{starts:e.starts?_(e.starts):null})]:Object.isFrozen(e)?[_(e)]:[e]}function k(e){if(t&&!e.langApiRestored){for(var n in e.langApiRestored=!0,t)e[n]&&(e[t[n]]=e[n]);(e.contains||[]).concat(e.variants||[]).forEach(k)}}function O(e,t){var n={};return"string"===typeof e?r("keyword",e):o(e).forEach((function(t){r(t,e[t])})),n;function r(e,r){t&&(r=r.toLowerCase()),r.split(" ").forEach((function(t){var r=t.split("|");n[r[0]]=[e,C(r[0],r[1])]}))}}function C(e,t){return t?Number(t):M(e)?0:1}function M(e){return-1!=v.indexOf(e.toLowerCase())}function T(e){function t(e){return e&&e.source||e}function n(n,r){return new RegExp(t(n),"m"+(e.case_insensitive?"i":"")+(r?"g":""))}function r(e){return new RegExp(e.toString()+"|").exec("").length-1}function i(e,n){for(var r=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,i=0,o="",a=0;a0&&(o+=n),o+="(";while(c.length>0){var u=r.exec(c);if(null==u){o+=c;break}o+=c.substring(0,u.index),c=c.substring(u.index+u[0].length),"\\"==u[0][0]&&u[1]?o+="\\"+String(Number(u[1])+s):(o+=u[0],"("==u[0]&&i++)}o+=")"}return o}function o(e){var t,o,a={},s=[],c={},u=1;function l(e,t){a[u]=e,s.push([e,t]),u+=r(t)+1}for(var f=0;f',o+t+a}function v(){var e,t,n,r;if(!O.keywords)return g(j);r="",t=0,O.lexemesRe.lastIndex=0,n=O.lexemesRe.exec(j);while(n)r+=g(j.substring(t,n.index)),e=l(O,n),e?(P+=e[1],r+=f(e[0],g(n[0]))):r+=g(n[0]),t=O.lexemesRe.lastIndex,n=O.lexemesRe.exec(j);return r+g(j.substr(t))}function b(){var e="string"===typeof O.subLanguage;if(e&&!a[O.subLanguage])return g(j);var t=e?I(O.subLanguage,j,!0,C[O.subLanguage]):N(j,O.subLanguage.length?O.subLanguage:void 0);return O.relevance>0&&(P+=t.relevance),e&&(C[O.subLanguage]=t.top),f(t.language,t.value,!1,!0)}function y(){M+=null!=O.subLanguage?b():v(),j=""}function w(e){M+=e.className?f(e.className,"",!0):"",O=Object.create(e,{parent:{value:O}})}function _(e){var t=e[0],n=e.rule;return n&&n.endSameAsBegin&&(n.endRe=s(t)),n.skip?j+=t:(n.excludeBegin&&(j+=t),y(),n.returnBegin||n.excludeBegin||(j=t)),w(n),n.returnBegin?0:t.length}function x(e){var t=e[0],n=o.substr(e.index),r=u(O,n);if(r){var i=O;i.skip?j+=t:(i.returnEnd||i.excludeEnd||(j+=t),y(),i.excludeEnd&&(j=t));do{O.className&&(M+=d),O.skip||O.subLanguage||(P+=O.relevance),O=O.parent}while(O!==r.parent);return r.starts&&(r.endSameAsBegin&&(r.starts.endRe=r.endRe),w(r.starts)),i.returnEnd?0:t.length}}var E={};function S(e,t){var r=t&&t[0];if(j+=e,null==r)return y(),0;if("begin"==E.type&&"end"==t.type&&E.index==t.index&&""===r)return j+=o.slice(t.index,t.index+1),1;if("illegal"===E.type&&""===r)return j+=o.slice(t.index,t.index+1),1;if(E=t,"begin"===t.type)return _(t);if("illegal"===t.type&&!n)throw new Error('Illegal lexeme "'+r+'" for mode "'+(O.className||"")+'"');if("end"===t.type){var i=x(t);if(void 0!=i)return i}return j+=r,r.length}var A=q(e);if(!A)throw console.error(p.replace("{}",e)),new Error('Unknown language: "'+e+'"');T(A);var k,O=i||A,C={},M="";for(k=O;k!==A;k=k.parent)k.className&&(M=f(k.className,"",!0)+M);var j="",P=0;try{var L,$,D=0;while(1){if(O.terminators.lastIndex=D,L=O.terminators.exec(o),!L)break;$=S(o.substring(D,L.index),L),D=L.index+$}for(S(o.substr(D)),k=O;k.parent;k=k.parent)k.className&&(M+=d);return{relevance:P,value:M,illegal:!1,language:e,top:O}}catch(F){if(F.message&&-1!==F.message.indexOf("Illegal"))return{illegal:!0,relevance:0,value:g(o)};if(c)return{relevance:0,value:g(o),language:e,top:O,errorRaised:F};throw F}}function N(e,t){t=t||h.languages||o(a);var n={relevance:0,value:g(e)},r=n;return t.filter(q).filter(W).forEach((function(t){var i=I(t,e,!1);i.language=t,i.relevance>r.relevance&&(r=i),i.relevance>n.relevance&&(r=n,n=i)})),r.language&&(n.second_best=r),n}function j(e){return h.tabReplace||h.useBR?e.replace(f,(function(e,t){return h.useBR&&"\n"===e?"
":h.tabReplace?t.replace(/\t/g,h.tabReplace):""})):e}function P(e,t,n){var r=t?s[t]:n,i=[e.trim()];return e.match(/\bhljs\b/)||i.push("hljs"),-1===e.indexOf(r)&&i.push(r),i.join(" ").trim()}function L(e){var t,n,r,i,o,a=w(e);y(a)||(h.useBR?(t=document.createElement("div"),t.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):t=e,o=t.textContent,r=a?I(a,o,!0):N(o),n=x(t),n.length&&(i=document.createElement("div"),i.innerHTML=r.value,r.value=E(n,x(i),o)),r.value=j(r.value),e.innerHTML=r.value,e.className=P(e.className,a,r.language),e.result={language:r.language,re:r.relevance},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.relevance}))}function $(e){h=_(h,e)}function D(){if(!D.called){D.called=!0;var e=document.querySelectorAll("pre code");i.forEach.call(e,L)}}function F(){window.addEventListener("DOMContentLoaded",D,!1),window.addEventListener("load",D,!1)}var B={disableAutodetect:!0};function U(t,n){var r;try{r=n(e)}catch(i){if(console.error("Language definition for '{}' could not be registered.".replace("{}",t)),!c)throw i;console.error(i),r=B}a[t]=r,k(r),r.rawDefinition=n.bind(null,e),r.aliases&&r.aliases.forEach((function(e){s[e]=t}))}function z(){return o(a)}function H(e){var t=q(e);if(t)return t;var n=new Error("The '{}' language is required, but not loaded.".replace("{}",e));throw n}function q(e){return e=(e||"").toLowerCase(),a[e]||a[s[e]]}function W(e){var t=q(e);return t&&!t.disableAutodetect}e.highlight=I,e.highlightAuto=N,e.fixMarkup=j,e.highlightBlock=L,e.configure=$,e.initHighlighting=D,e.initHighlightingOnLoad=F,e.registerLanguage=U,e.listLanguages=z,e.getLanguage=q,e.requireLanguage=H,e.autoDetection=W,e.inherit=_,e.debugMode=function(){c=!1},e.IDENT_RE="[a-zA-Z]\\w*",e.UNDERSCORE_IDENT_RE="[a-zA-Z_]\\w*",e.NUMBER_RE="\\b\\d+(\\.\\d+)?",e.C_NUMBER_RE="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BINARY_NUMBER_RE="\\b(0b[01]+)",e.RE_STARTERS_RE="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BACKSLASH_ESCAPE={begin:"\\\\[\\s\\S]",relevance:0},e.APOS_STRING_MODE={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},e.QUOTE_STRING_MODE={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},e.PHRASAL_WORDS_MODE={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.COMMENT=function(t,n,r){var i=e.inherit({className:"comment",begin:t,end:n,contains:[]},r||{});return i.contains.push(e.PHRASAL_WORDS_MODE),i.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|XXX):",relevance:0}),i},e.C_LINE_COMMENT_MODE=e.COMMENT("//","$"),e.C_BLOCK_COMMENT_MODE=e.COMMENT("/\\*","\\*/"),e.HASH_COMMENT_MODE=e.COMMENT("#","$"),e.NUMBER_MODE={className:"number",begin:e.NUMBER_RE,relevance:0},e.C_NUMBER_MODE={className:"number",begin:e.C_NUMBER_RE,relevance:0},e.BINARY_NUMBER_MODE={className:"number",begin:e.BINARY_NUMBER_RE,relevance:0},e.CSS_NUMBER_MODE={className:"number",begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},e.REGEXP_MODE={className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[e.BACKSLASH_ESCAPE,{begin:/\[/,end:/\]/,relevance:0,contains:[e.BACKSLASH_ESCAPE]}]},e.TITLE_MODE={className:"title",begin:e.IDENT_RE,relevance:0},e.UNDERSCORE_TITLE_MODE={className:"title",begin:e.UNDERSCORE_IDENT_RE,relevance:0},e.METHOD_GUARD={begin:"\\.\\s*"+e.UNDERSCORE_IDENT_RE,relevance:0};var V=[e.BACKSLASH_ESCAPE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.PHRASAL_WORDS_MODE,e.COMMENT,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.HASH_COMMENT_MODE,e.NUMBER_MODE,e.C_NUMBER_MODE,e.BINARY_NUMBER_MODE,e.CSS_NUMBER_MODE,e.REGEXP_MODE,e.TITLE_MODE,e.UNDERSCORE_TITLE_MODE,e.METHOD_GUARD];function K(e){Object.freeze(e);var t="function"===typeof e;return Object.getOwnPropertyNames(e).forEach((function(n){!e.hasOwnProperty(n)||null===e[n]||"object"!==typeof e[n]&&"function"!==typeof e[n]||t&&("caller"===n||"callee"===n||"arguments"===n)||Object.isFrozen(e[n])||K(e[n])})),e}return V.forEach((function(e){K(e)})),e}))}).call(this,n("4362"))},a79d:function(e,t,n){"use strict";var r=n("23e7"),i=n("c430"),o=n("fea9"),a=n("d039"),s=n("d066"),c=n("4840"),u=n("cdf9"),l=n("6eeb"),f=!!o&&a((function(){o.prototype["finally"].call({then:function(){}},(function(){}))}));if(r({target:"Promise",proto:!0,real:!0,forced:f},{finally:function(e){var t=c(this,s("Promise")),n="function"==typeof e;return this.then(n?function(n){return u(t,e()).then((function(){return n}))}:e,n?function(n){return u(t,e()).then((function(){throw n}))}:e)}}),!i&&"function"==typeof o){var d=s("Promise").prototype["finally"];o.prototype["finally"]!==d&&l(o.prototype,"finally",d,{unsafe:!0})}},a874:function(e,t,n){var r=n("23e7"),i=n("145e"),o=n("44d2");r({target:"Array",proto:!0},{copyWithin:i}),o("copyWithin")},a975:function(e,t,n){"use strict";var r=n("ebb5"),i=n("b727").every,o=r.aTypedArray,a=r.exportTypedArrayMethod;a("every",(function(e){return i(o(this),e,arguments.length>1?arguments[1]:void 0)}))},a981:function(e,t){e.exports="undefined"!==typeof ArrayBuffer&&"undefined"!==typeof DataView},a9e3:function(e,t,n){"use strict";var r=n("83ab"),i=n("da84"),o=n("94ca"),a=n("6eeb"),s=n("5135"),c=n("c6b6"),u=n("7156"),l=n("c04e"),f=n("d039"),d=n("7c73"),p=n("241c").f,h=n("06cf").f,v=n("9bf2").f,g=n("58a8").trim,b="Number",m=i[b],y=m.prototype,w=c(d(y))==b,_=function(e){var t,n,r,i,o,a,s,c,u=l(e,!1);if("string"==typeof u&&u.length>2)if(u=g(u),t=u.charCodeAt(0),43===t||45===t){if(n=u.charCodeAt(2),88===n||120===n)return NaN}else if(48===t){switch(u.charCodeAt(1)){case 66:case 98:r=2,i=49;break;case 79:case 111:r=8,i=55;break;default:return+u}for(o=u.slice(2),a=o.length,s=0;si)return NaN;return parseInt(o,r)}return+u};if(o(b,!m(" 0o1")||!m("0b1")||m("+0x1"))){for(var x,E=function(e){var t=arguments.length<1?0:e,n=this;return n instanceof E&&(w?f((function(){y.valueOf.call(n)})):c(n)!=b)?u(new m(_(t)),n,E):_(t)},S=r?p(m):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger,fromString,range".split(","),A=0;S.length>A;A++)s(m,x=S[A])&&!s(E,x)&&v(E,x,h(m,x));E.prototype=y,y.constructor=E,a(i,b,E)}},ab13:function(e,t,n){var r=n("b622"),i=r("match");e.exports=function(e){var t=/./;try{"/./"[e](t)}catch(n){try{return t[i]=!1,"/./"[e](t)}catch(r){}}return!1}},ab8b:function(e,t,n){},ac16:function(e,t,n){var r=n("23e7"),i=n("825a"),o=n("06cf").f;r({target:"Reflect",stat:!0},{deleteProperty:function(e,t){var n=o(i(e),t);return!(n&&!n.configurable)&&delete e[t]}})},ac1f:function(e,t,n){"use strict";var r=n("23e7"),i=n("9263");r({target:"RegExp",proto:!0,forced:/./.exec!==i},{exec:i})},acac:function(e,t,n){"use strict";var r=n("e2cc"),i=n("f183").getWeakData,o=n("825a"),a=n("861d"),s=n("19aa"),c=n("2266"),u=n("b727"),l=n("5135"),f=n("69f3"),d=f.set,p=f.getterFor,h=u.find,v=u.findIndex,g=0,b=function(e){return e.frozen||(e.frozen=new m)},m=function(){this.entries=[]},y=function(e,t){return h(e.entries,(function(e){return e[0]===t}))};m.prototype={get:function(e){var t=y(this,e);if(t)return t[1]},has:function(e){return!!y(this,e)},set:function(e,t){var n=y(this,e);n?n[1]=t:this.entries.push([e,t])},delete:function(e){var t=v(this.entries,(function(t){return t[0]===e}));return~t&&this.entries.splice(t,1),!!~t}},e.exports={getConstructor:function(e,t,n,u){var f=e((function(e,r){s(e,f,t),d(e,{type:t,id:g++,frozen:void 0}),void 0!=r&&c(r,e[u],{that:e,AS_ENTRIES:n})})),h=p(t),v=function(e,t,n){var r=h(e),a=i(o(t),!0);return!0===a?b(r).set(t,n):a[r.id]=n,e};return r(f.prototype,{delete:function(e){var t=h(this);if(!a(e))return!1;var n=i(e);return!0===n?b(t)["delete"](e):n&&l(n,t.id)&&delete n[t.id]},has:function(e){var t=h(this);if(!a(e))return!1;var n=i(e);return!0===n?b(t).has(e):n&&l(n,t.id)}}),r(f.prototype,n?{get:function(e){var t=h(this);if(a(e)){var n=i(e);return!0===n?b(t).get(e):n?n[t.id]:void 0}},set:function(e,t){return v(this,e,t)}}:{add:function(e){return v(this,e,!0)}}),f}}},accc:function(e,t,n){var r=n("23e7"),i=n("64e5");r({target:"Date",proto:!0,forced:Date.prototype.toISOString!==i},{toISOString:i})},acd8:function(e,t,n){var r=n("23e7"),i=n("7e12");r({global:!0,forced:parseFloat!=i},{parseFloat:i})},ace4:function(e,t,n){"use strict";var r=n("23e7"),i=n("d039"),o=n("621a"),a=n("825a"),s=n("23cb"),c=n("50c4"),u=n("4840"),l=o.ArrayBuffer,f=o.DataView,d=l.prototype.slice,p=i((function(){return!new l(2).slice(1,void 0).byteLength}));r({target:"ArrayBuffer",proto:!0,unsafe:!0,forced:p},{slice:function(e,t){if(void 0!==d&&void 0===t)return d.call(a(this),e);var n=a(this).byteLength,r=s(e,n),i=s(void 0===t?n:t,n),o=new(u(this,l))(c(i-r)),p=new f(this),h=new f(o),v=0;while(r3}))}},af93:function(e,t,n){var r=n("23e7"),i=n("861d"),o=n("f183").onFreeze,a=n("bb2f"),s=n("d039"),c=Object.seal,u=s((function(){c(1)}));r({target:"Object",stat:!0,forced:u,sham:!a},{seal:function(e){return c&&i(e)?c(o(e)):e}})},aff5:function(e,t,n){var r=n("23e7");r({target:"Number",stat:!0},{MAX_SAFE_INTEGER:9007199254740991})},b041:function(e,t,n){"use strict";var r=n("00ee"),i=n("f5df");e.exports=r?{}.toString:function(){return"[object "+i(this)+"]"}},b0c0:function(e,t,n){var r=n("83ab"),i=n("9bf2").f,o=Function.prototype,a=o.toString,s=/^\s*function ([^ (]*)/,c="name";r&&!(c in o)&&i(o,c,{configurable:!0,get:function(){try{return a.call(this).match(s)[1]}catch(e){return""}}})},b15b:function(e,t,n){},b39a:function(e,t,n){"use strict";var r=n("da84"),i=n("ebb5"),o=n("d039"),a=r.Int8Array,s=i.aTypedArray,c=i.exportTypedArrayMethod,u=[].toLocaleString,l=[].slice,f=!!a&&o((function(){u.call(new a(1))})),d=o((function(){return[1,2].toLocaleString()!=new a([1,2]).toLocaleString()}))||!o((function(){a.prototype.toLocaleString.call([1,2])}));c("toLocaleString",(function(){return u.apply(f?l.call(s(this)):s(this),arguments)}),d)},b420:function(e,t,n){var r=n("23e7"),i=n("621a"),o=n("a981");r({global:!0,forced:!o},{DataView:i.DataView})},b56e:function(e,t,n){"use strict";var r=n("861d"),i=n("9bf2"),o=n("e163"),a=n("b622"),s=a("hasInstance"),c=Function.prototype;s in c||i.f(c,s,{value:function(e){if("function"!=typeof this||!r(e))return!1;if(!r(this.prototype))return e instanceof this;while(e=o(e))if(this.prototype===e)return!0;return!1}})},b575:function(e,t,n){var r,i,o,a,s,c,u,l,f=n("da84"),d=n("06cf").f,p=n("2cf4").set,h=n("1cdc"),v=n("a4b4"),g=n("605d"),b=f.MutationObserver||f.WebKitMutationObserver,m=f.document,y=f.process,w=f.Promise,_=d(f,"queueMicrotask"),x=_&&_.value;x||(r=function(){var e,t;g&&(e=y.domain)&&e.exit();while(i){t=i.fn,i=i.next;try{t()}catch(n){throw i?a():o=void 0,n}}o=void 0,e&&e.enter()},h||g||v||!b||!m?w&&w.resolve?(u=w.resolve(void 0),u.constructor=w,l=u.then,a=function(){l.call(u,r)}):a=g?function(){y.nextTick(r)}:function(){p.call(f,r)}:(s=!0,c=m.createTextNode(""),new b(r).observe(c,{characterData:!0}),a=function(){c.data=s=!s})),e.exports=x||function(e){var t={fn:e,next:void 0};o&&(o.next=t),i||(i=t,a()),o=t}},b622:function(e,t,n){var r=n("da84"),i=n("5692"),o=n("5135"),a=n("90e3"),s=n("4930"),c=n("fdbf"),u=i("wks"),l=r.Symbol,f=c?l:l&&l.withoutSetter||a;e.exports=function(e){return o(u,e)&&(s||"string"==typeof u[e])||(s&&o(l,e)?u[e]=l[e]:u[e]=f("Symbol."+e)),u[e]}},b636:function(e,t,n){var r=n("746f");r("asyncIterator")},b64b:function(e,t,n){var r=n("23e7"),i=n("7b0b"),o=n("df75"),a=n("d039"),s=a((function(){o(1)}));r({target:"Object",stat:!0,forced:s},{keys:function(e){return o(i(e))}})},b65f:function(e,t,n){var r=n("23e7"),i=Math.ceil,o=Math.floor;r({target:"Math",stat:!0},{trunc:function(e){return(e>0?o:i)(e)}})},b680:function(e,t,n){"use strict";var r=n("23e7"),i=n("a691"),o=n("408a"),a=n("1148"),s=n("d039"),c=1..toFixed,u=Math.floor,l=function(e,t,n){return 0===t?n:t%2===1?l(e,t-1,n*e):l(e*e,t/2,n)},f=function(e){var t=0,n=e;while(n>=4096)t+=12,n/=4096;while(n>=2)t+=1,n/=2;return t},d=function(e,t,n){var r=-1,i=n;while(++r<6)i+=t*e[r],e[r]=i%1e7,i=u(i/1e7)},p=function(e,t){var n=6,r=0;while(--n>=0)r+=e[n],e[n]=u(r/t),r=r%t*1e7},h=function(e){var t=6,n="";while(--t>=0)if(""!==n||0===t||0!==e[t]){var r=String(e[t]);n=""===n?r:n+a.call("0",7-r.length)+r}return n},v=c&&("0.000"!==8e-5.toFixed(3)||"1"!==.9.toFixed(0)||"1.25"!==1.255.toFixed(2)||"1000000000000000128"!==(0xde0b6b3a7640080).toFixed(0))||!s((function(){c.call({})}));r({target:"Number",proto:!0,forced:v},{toFixed:function(e){var t,n,r,s,c=o(this),u=i(e),v=[0,0,0,0,0,0],g="",b="0";if(u<0||u>20)throw RangeError("Incorrect fraction digits");if(c!=c)return"NaN";if(c<=-1e21||c>=1e21)return String(c);if(c<0&&(g="-",c=-c),c>1e-21)if(t=f(c*l(2,69,1))-69,n=t<0?c*l(2,-t,1):c/l(2,t,1),n*=4503599627370496,t=52-t,t>0){d(v,0,n),r=u;while(r>=7)d(v,1e7,0),r-=7;d(v,l(10,r,1),0),r=t-1;while(r>=23)p(v,1<<23),r-=23;p(v,1<0?(s=b.length,b=g+(s<=u?"0."+a.call("0",u-s)+b:b.slice(0,s-u)+"."+b.slice(s-u))):b=g+b,b}})},b6de:function(e,t,n){"use strict";const r=/^(?:( )+|\t+)/;function i(e){let t=0,n=0,r=0;for(const i of e){const e=i[0],o=i[1],a=o[0],s=o[1];(a>n||a===n&&s>r)&&(n=a,r=s,t=Number(e))}return t}e.exports=e=>{if("string"!==typeof e)throw new TypeError("Expected a string");let t=0,n=0,o=0;const a=new Map;let s,c;for(const i of e.split(/\n/g)){if(!i)continue;let e;const u=i.match(r);u?(e=u[0].length,u[1]?n++:t++):e=0;const l=e-o;o=e,l?(c=l>0,s=a.get(c?l:-l),s?s[0]++:(s=[1,0],a.set(l,s))):s&&(s[1]+=Number(c))}const u=i(a);let l,f;return u?n>=t?(l="space",f=" ".repeat(u)):(l="tab",f="\t".repeat(u)):(l=null,f=""),{amount:u,type:l,indent:f}}},b727:function(e,t,n){var r=n("0366"),i=n("44ad"),o=n("7b0b"),a=n("50c4"),s=n("65f0"),c=[].push,u=function(e){var t=1==e,n=2==e,u=3==e,l=4==e,f=6==e,d=7==e,p=5==e||f;return function(h,v,g,b){for(var m,y,w=o(h),_=i(w),x=r(v,g,3),E=a(_.length),S=0,A=b||s,k=t?A(h,E):n||d?A(h,0):void 0;E>S;S++)if((p||S in _)&&(m=_[S],y=x(m,S,w),e))if(t)k[S]=y;else if(y)switch(e){case 3:return!0;case 5:return m;case 6:return S;case 2:c.call(k,m)}else switch(e){case 4:return!1;case 7:c.call(k,m)}return f?-1:u||l?l:k}};e.exports={forEach:u(0),map:u(1),filter:u(2),some:u(3),every:u(4),find:u(5),findIndex:u(6),filterOut:u(7)}},b8bf:function(e,t,n){var r=n("23e7"),i=n("83ab"),o=n("7c73");r({target:"Object",stat:!0,sham:!i},{create:o})},baa5:function(e,t,n){var r=n("23e7"),i=n("e58c");r({target:"Array",proto:!0,forced:i!==[].lastIndexOf},{lastIndexOf:i})},bb2f:function(e,t,n){var r=n("d039");e.exports=!r((function(){return Object.isExtensible(Object.preventExtensions({}))}))},bc01:function(e,t,n){var r=n("23e7"),i=n("d039"),o=Math.imul,a=i((function(){return-5!=o(4294967295,5)||2!=o.length}));r({target:"Math",stat:!0,forced:a},{imul:function(e,t){var n=65535,r=+e,i=+t,o=n&r,a=n&i;return 0|o*a+((n&r>>>16)*a+o*(n&i>>>16)<<16>>>0)}})},be8e:function(e,t,n){var r=n("f748"),i=Math.abs,o=Math.pow,a=o(2,-52),s=o(2,-23),c=o(2,127)*(2-s),u=o(2,-126),l=function(e){return e+1/a-1/a};e.exports=Math.fround||function(e){var t,n,o=i(e),f=r(e);return oc||n!=n?f*(1/0):f*n)}},bf19:function(e,t,n){"use strict";var r=n("23e7");r({target:"URL",proto:!0,enumerable:!0},{toJSON:function(){return URL.prototype.toString.call(this)}})},bf96:function(e,t,n){"use strict";var r=n("23e7"),i=n("83ab"),o=n("eb1d"),a=n("7b0b"),s=n("c04e"),c=n("e163"),u=n("06cf").f;i&&r({target:"Object",proto:!0,forced:o},{__lookupGetter__:function(e){var t,n=a(this),r=s(e,!0);do{if(t=u(n,r))return t.get}while(n=c(n))}})},c04e:function(e,t,n){var r=n("861d");e.exports=function(e,t){if(!r(e))return e;var n,i;if(t&&"function"==typeof(n=e.toString)&&!r(i=n.call(e)))return i;if("function"==typeof(n=e.valueOf)&&!r(i=n.call(e)))return i;if(!t&&"function"==typeof(n=e.toString)&&!r(i=n.call(e)))return i;throw TypeError("Can't convert object to primitive value")}},c0b6:function(e,t,n){var r=n("23e7"),i=n("0538");r({target:"Function",proto:!0},{bind:i})},c19f:function(e,t,n){"use strict";var r=n("23e7"),i=n("da84"),o=n("621a"),a=n("2626"),s="ArrayBuffer",c=o[s],u=i[s];r({global:!0,forced:u!==c},{ArrayBuffer:c}),a(s)},c1ac:function(e,t,n){"use strict";var r=n("ebb5"),i=n("b727").filter,o=n("1448"),a=r.aTypedArray,s=r.exportTypedArrayMethod;s("filter",(function(e){var t=i(a(this),e,arguments.length>1?arguments[1]:void 0);return o(this,t)}))},c1f9:function(e,t,n){var r=n("23e7"),i=n("2266"),o=n("8418");r({target:"Object",stat:!0},{fromEntries:function(e){var t={};return i(e,(function(e,n){o(t,e,n)}),{AS_ENTRIES:!0}),t}})},c20d:function(e,t,n){var r=n("da84"),i=n("58a8").trim,o=n("5899"),a=r.parseInt,s=/^[+-]?0[Xx]/,c=8!==a(o+"08")||22!==a(o+"0x16");e.exports=c?function(e,t){var n=i(String(e));return a(n,t>>>0||(s.test(n)?16:10))}:a},c35a:function(e,t,n){var r=n("23e7"),i=n("7e12");r({target:"Number",stat:!0,forced:Number.parseFloat!=i},{parseFloat:i})},c430:function(e,t){e.exports=!1},c5d0:function(e,t,n){"use strict";var r=n("23e7"),i=n("857a"),o=n("af03");r({target:"String",proto:!0,forced:o("italics")},{italics:function(){return i(this,"i","","")}})},c6b6:function(e,t){var n={}.toString;e.exports=function(e){return n.call(e).slice(8,-1)}},c6cd:function(e,t,n){var r=n("da84"),i=n("ce4e"),o="__core-js_shared__",a=r[o]||i(o,{});e.exports=a},c740:function(e,t,n){"use strict";var r=n("23e7"),i=n("b727").findIndex,o=n("44d2"),a="findIndex",s=!0;a in[]&&Array(1)[a]((function(){s=!1})),r({target:"Array",proto:!0,forced:s},{findIndex:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0)}}),o(a)},c760:function(e,t,n){var r=n("23e7");r({target:"Reflect",stat:!0},{has:function(e,t){return t in e}})},c7cd:function(e,t,n){"use strict";var r=n("23e7"),i=n("857a"),o=n("af03");r({target:"String",proto:!0,forced:o("fixed")},{fixed:function(){return i(this,"tt","","")}})},c8ba:function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(r){"object"===typeof window&&(n=window)}e.exports=n},c8d2:function(e,t,n){var r=n("d039"),i=n("5899"),o="​…᠎";e.exports=function(e){return r((function(){return!!i[e]()||o[e]()!=o||i[e].name!==e}))}},c906:function(e,t,n){var r=n("23e7"),i=n("d039"),o=n("861d"),a=Object.isExtensible,s=i((function(){a(1)}));r({target:"Object",stat:!0,forced:s},{isExtensible:function(e){return!!o(e)&&(!a||a(e))}})},c964:function(e,t,n){"use strict"; +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},r(e,t)};function i(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}function o(e,t,n,r){var i,o=arguments.length,a=o<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"===typeof Reflect&&"function"===typeof Reflect.decorate)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(i=e[s])&&(a=(o<3?i(a):o>3?i(t,n,a):i(t,n))||a);return o>3&&a&&Object.defineProperty(t,n,a),a}var a=n("a70e"),s=n.n(a),c=n("2b0e"),u=n("b6de"),l=n.n(u),f=n("4b90"),d=n.n(f);function p(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function h(e,t){return t={exports:{}},e(t,t.exports),t.exports}var v=h((function(e,t){function n(e){return e&&"object"===typeof e&&"default"in e?e["default"]:e}Object.defineProperty(t,"__esModule",{value:!0});var r=n(c["a"]),i="undefined"!==typeof Reflect&&Reflect.defineMetadata;function o(e,t){a(e,t),Object.getOwnPropertyNames(t.prototype).forEach((function(n){a(e.prototype,t.prototype,n)})),Object.getOwnPropertyNames(t).forEach((function(n){a(e,t,n)}))}function a(e,t,n){var r=n?Reflect.getOwnMetadataKeys(t,n):Reflect.getOwnMetadataKeys(t);r.forEach((function(r){var i=n?Reflect.getOwnMetadata(r,t,n):Reflect.getOwnMetadata(r,t);n?Reflect.defineMetadata(r,i,e,n):Reflect.defineMetadata(r,i,e)}))}var s={__proto__:[]},u=s instanceof Array;function l(e){return function(t,n,r){var i="function"===typeof t?t:t.constructor;i.__decorators__||(i.__decorators__=[]),"number"!==typeof r&&(r=void 0),i.__decorators__.push((function(t){return e(t,n,r)}))}}function f(){for(var e=[],t=0;t-1)t[e]=n[e];else{var r=Object.getOwnPropertyDescriptor(n,e);void 0!==r.value?"function"===typeof r.value?(t.methods||(t.methods={}))[e]=r.value:(t.mixins||(t.mixins=[])).push({data:function(){var t;return t={},t[e]=r.value,t}}):(r.get||r.set)&&((t.computed||(t.computed={}))[e]={get:r.get,set:r.set})}})),(t.mixins||(t.mixins=[])).push({data:function(){return p(this,e)}});var a=e.__decorators__;a&&(a.forEach((function(e){return e(t)})),delete e.__decorators__);var s=Object.getPrototypeOf(e.prototype),c=s instanceof r?s.constructor:r,u=c.extend(t);return g(u,e,c),i&&o(u,e),u}function g(e,t,n){Object.getOwnPropertyNames(t).forEach((function(r){if("prototype"!==r){var i=Object.getOwnPropertyDescriptor(e,r);if(!i||i.configurable){var o=Object.getOwnPropertyDescriptor(t,r);if(!u){if("cid"===r)return;var a=Object.getOwnPropertyDescriptor(n,r);if(!d(o.value)&&a&&a.value===o.value)return}Object.defineProperty(e,r,o)}}}))}function b(e){return"function"===typeof e?v(e):function(t){return v(t,e)}}b.registerHooks=function(e){h.push.apply(h,e)},t.default=b,t.createDecorator=l,t.mixins=f})),g=p(v),b=v.createDecorator;v.mixins;function m(e){return void 0===e&&(e={}),b((function(t,n){(t.props||(t.props={}))[n]=e}))}function y(e){return"string"===typeof e?e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">"):e}function w(e){return Array.isArray(e)?e.map((function(e){return Array.isArray(e.children)&&e.children.length>0?w(e.children):e.text})).join(""):""}function _(e){if("string"===typeof e){var t=l()(e).indent||"\t";return e=d()(e,0,t),e.trim()}return e}function x(e){"object"===typeof e&&Object.keys(e).forEach((function(t){var n=e[t];s.a.registerLanguage(t,n)}))}var E={display:"inline !important","vertical-align":"middle"},S=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return i(t,e),Object.defineProperty(t.prototype,"hasCode",{get:function(){return"string"===typeof this.code&&this.code.length>0},enumerable:!0,configurable:!0}),t.prototype.render=function(e){var t,n,r=this,i=r.hasCode,o=r.inline,a=r.auto,c=this.lang,u=i?this.code:w(this.$slots.default);o||(u=_(u));try{a?(t=s.a.highlightAuto(u),c=t.language,n=t.value):n=c?s.a.highlight(c,u).value:y(u)}catch(l){n=y(u),console.error(l)}return e(o?"span":"pre",[e("code",{class:["hljs"].concat(c?[c]:[]),style:o?E:{},domProps:{innerHTML:n}})])},o([m(String)],t.prototype,"lang",void 0),o([m({type:Boolean,default:!1})],t.prototype,"inline",void 0),o([m(String)],t.prototype,"code",void 0),o([m(Boolean)],t.prototype,"auto",void 0),t=o([g({name:"HighlightCode"})],t),t}(c["a"]),A=function(e,t){void 0===t&&(t={languages:{}});var n=t.languages;x(n),e.component("highlight-code",S)};"undefined"!==typeof window&&window.Vue&&A(window.Vue);var k={install:A};t["a"]=k},c96a:function(e,t,n){"use strict";var r=n("23e7"),i=n("857a"),o=n("af03");r({target:"String",proto:!0,forced:o("small")},{small:function(){return i(this,"small","","")}})},c975:function(e,t,n){"use strict";var r=n("23e7"),i=n("4d64").indexOf,o=n("a640"),a=[].indexOf,s=!!a&&1/[1].indexOf(1,-0)<0,c=o("indexOf");r({target:"Array",proto:!0,forced:s||!c},{indexOf:function(e){return s?a.apply(this,arguments)||0:i(this,e,arguments.length>1?arguments[1]:void 0)}})},ca21:function(e,t,n){var r=n("23e7"),i=n("1ec1");r({target:"Math",stat:!0},{log1p:i})},ca84:function(e,t,n){var r=n("5135"),i=n("fc6a"),o=n("4d64").indexOf,a=n("d012");e.exports=function(e,t){var n,s=i(e),c=0,u=[];for(n in s)!r(a,n)&&r(s,n)&&u.push(n);while(t.length>c)r(s,n=t[c++])&&(~o(u,n)||u.push(n));return u}},ca91:function(e,t,n){"use strict";var r=n("ebb5"),i=n("d58f").left,o=r.aTypedArray,a=r.exportTypedArrayMethod;a("reduce",(function(e){return i(o(this),e,arguments.length,arguments.length>1?arguments[1]:void 0)}))},caad:function(e,t,n){"use strict";var r=n("23e7"),i=n("4d64").includes,o=n("44d2");r({target:"Array",proto:!0},{includes:function(e){return i(this,e,arguments.length>1?arguments[1]:void 0)}}),o("includes")},cb29:function(e,t,n){var r=n("23e7"),i=n("81d5"),o=n("44d2");r({target:"Array",proto:!0},{fill:i}),o("fill")},cc12:function(e,t,n){var r=n("da84"),i=n("861d"),o=r.document,a=i(o)&&i(o.createElement);e.exports=function(e){return a?o.createElement(e):{}}},cc71:function(e,t,n){"use strict";var r=n("23e7"),i=n("857a"),o=n("af03");r({target:"String",proto:!0,forced:o("bold")},{bold:function(){return i(this,"b","","")}})},cca6:function(e,t,n){var r=n("23e7"),i=n("60da");r({target:"Object",stat:!0,forced:Object.assign!==i},{assign:i})},cd26:function(e,t,n){"use strict";var r=n("ebb5"),i=r.aTypedArray,o=r.exportTypedArrayMethod,a=Math.floor;o("reverse",(function(){var e,t=this,n=i(t).length,r=a(n/2),o=0;while(o1?arguments[1]:void 0)}))},d1e7:function(e,t,n){"use strict";var r={}.propertyIsEnumerable,i=Object.getOwnPropertyDescriptor,o=i&&!r.call({1:2},1);t.f=o?function(e){var t=i(this,e);return!!t&&t.enumerable}:r},d28b:function(e,t,n){var r=n("746f");r("iterator")},d2bb:function(e,t,n){var r=n("825a"),i=n("3bbe");e.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var e,t=!1,n={};try{e=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set,e.call(n,[]),t=n instanceof Array}catch(o){}return function(n,o){return r(n),i(o),t?e.call(n,o):n.__proto__=o,n}}():void 0)},d3b7:function(e,t,n){var r=n("00ee"),i=n("6eeb"),o=n("b041");r||i(Object.prototype,"toString",o,{unsafe:!0})},d44e:function(e,t,n){var r=n("9bf2").f,i=n("5135"),o=n("b622"),a=o("toStringTag");e.exports=function(e,t,n){e&&!i(e=n?e:e.prototype,a)&&r(e,a,{configurable:!0,value:t})}},d58f:function(e,t,n){var r=n("1c0b"),i=n("7b0b"),o=n("44ad"),a=n("50c4"),s=function(e){return function(t,n,s,c){r(n);var u=i(t),l=o(u),f=a(u.length),d=e?f-1:0,p=e?-1:1;if(s<2)while(1){if(d in l){c=l[d],d+=p;break}if(d+=p,e?d<0:f<=d)throw TypeError("Reduce of empty array with no initial value")}for(;e?d>=0:f>d;d+=p)d in l&&(c=n(c,l[d],d,u));return c}};e.exports={left:s(!1),right:s(!0)}},d5d6:function(e,t,n){"use strict";var r=n("ebb5"),i=n("b727").forEach,o=r.aTypedArray,a=r.exportTypedArrayMethod;a("forEach",(function(e){i(o(this),e,arguments.length>1?arguments[1]:void 0)}))},d6dd:function(e,t,n){var r=n("23e7"),i=n("d066"),o=n("825a"),a=n("bb2f");r({target:"Reflect",stat:!0,sham:!a},{preventExtensions:function(e){o(e);try{var t=i("Object","preventExtensions");return t&&t(e),!0}catch(n){return!1}}})},d784:function(e,t,n){"use strict";n("ac1f");var r=n("6eeb"),i=n("d039"),o=n("b622"),a=n("9112"),s=o("species"),c=!i((function(){var e=/./;return e.exec=function(){var e=[];return e.groups={a:"7"},e},"7"!=="".replace(e,"$")})),u=function(){return"$0"==="a".replace(/./,"$0")}(),l=o("replace"),f=function(){return!!/./[l]&&""===/./[l]("a","$0")}(),d=!i((function(){var e=/(?:)/,t=e.exec;e.exec=function(){return t.apply(this,arguments)};var n="ab".split(e);return 2!==n.length||"a"!==n[0]||"b"!==n[1]}));e.exports=function(e,t,n,l){var p=o(e),h=!i((function(){var t={};return t[p]=function(){return 7},7!=""[e](t)})),v=h&&!i((function(){var t=!1,n=/a/;return"split"===e&&(n={},n.constructor={},n.constructor[s]=function(){return n},n.flags="",n[p]=/./[p]),n.exec=function(){return t=!0,null},n[p](""),!t}));if(!h||!v||"replace"===e&&(!c||!u||f)||"split"===e&&!d){var g=/./[p],b=n(p,""[e],(function(e,t,n,r,i){return t.exec===RegExp.prototype.exec?h&&!i?{done:!0,value:g.call(t,n,r)}:{done:!0,value:e.call(n,t,r)}:{done:!1}}),{REPLACE_KEEPS_$0:u,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:f}),m=b[0],y=b[1];r(String.prototype,e,m),r(RegExp.prototype,p,2==t?function(e,t){return y.call(e,this,t)}:function(e){return y.call(e,this)})}l&&a(RegExp.prototype[p],"sham",!0)}},d80f:function(e,t,n){var r=n("23e7"),i=n("fc6a"),o=n("50c4");r({target:"String",stat:!0},{raw:function(e){var t=i(e.raw),n=o(t.length),r=arguments.length,a=[],s=0;while(n>s)a.push(String(t[s++])),s1?arguments[1]:void 0)}})},da84:function(e,t,n){(function(t){var n=function(e){return e&&e.Math==Math&&e};e.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof t&&t)||function(){return this}()||Function("return this")()}).call(this,n("c8ba"))},db96:function(e,t,n){var r=n("23e7"),i=n("825a"),o=Object.isExtensible;r({target:"Reflect",stat:!0},{isExtensible:function(e){return i(e),!o||o(e)}})},dbb4:function(e,t,n){var r=n("23e7"),i=n("83ab"),o=n("56ef"),a=n("fc6a"),s=n("06cf"),c=n("8418");r({target:"Object",stat:!0,sham:!i},{getOwnPropertyDescriptors:function(e){var t,n,r=a(e),i=s.f,u=o(r),l={},f=0;while(u.length>f)n=i(r,t=u[f++]),void 0!==n&&c(l,t,n);return l}})},dbfa:function(e,t,n){"use strict";var r=n("23e7"),i=n("1c0b"),o=n("d066"),a=n("f069"),s=n("e667"),c=n("2266"),u="No one promise resolved";r({target:"Promise",stat:!0},{any:function(e){var t=this,n=a.f(t),r=n.resolve,l=n.reject,f=s((function(){var n=i(t.resolve),a=[],s=0,f=1,d=!1;c(e,(function(e){var i=s++,c=!1;a.push(void 0),f++,n.call(t,e).then((function(e){c||d||(d=!0,r(e))}),(function(e){c||d||(c=!0,a[i]=e,--f||l(new(o("AggregateError"))(a,u)))}))})),--f||l(new(o("AggregateError"))(a,u))}));return f.error&&l(f.value),n.promise}})},dc8d:function(e,t,n){var r=n("746f");r("hasInstance")},dca8:function(e,t,n){var r=n("23e7"),i=n("bb2f"),o=n("d039"),a=n("861d"),s=n("f183").onFreeze,c=Object.freeze,u=o((function(){c(1)}));r({target:"Object",stat:!0,forced:u,sham:!i},{freeze:function(e){return c&&a(e)?c(s(e)):e}})},ddb0:function(e,t,n){var r=n("da84"),i=n("fdbc"),o=n("e260"),a=n("9112"),s=n("b622"),c=s("iterator"),u=s("toStringTag"),l=o.values;for(var f in i){var d=r[f],p=d&&d.prototype;if(p){if(p[c]!==l)try{a(p,c,l)}catch(v){p[c]=l}if(p[u]||a(p,u,f),i[f])for(var h in o)if(p[h]!==o[h])try{a(p,h,o[h])}catch(v){p[h]=o[h]}}}},df75:function(e,t,n){var r=n("ca84"),i=n("7839");e.exports=Object.keys||function(e){return r(e,i)}},df7c:function(e,t,n){(function(e){function n(e,t){for(var n=0,r=e.length-1;r>=0;r--){var i=e[r];"."===i?e.splice(r,1):".."===i?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}function r(e){"string"!==typeof e&&(e+="");var t,n=0,r=-1,i=!0;for(t=e.length-1;t>=0;--t)if(47===e.charCodeAt(t)){if(!i){n=t+1;break}}else-1===r&&(i=!1,r=t+1);return-1===r?"":e.slice(n,r)}function i(e,t){if(e.filter)return e.filter(t);for(var n=[],r=0;r=-1&&!r;o--){var a=o>=0?arguments[o]:e.cwd();if("string"!==typeof a)throw new TypeError("Arguments to path.resolve must be strings");a&&(t=a+"/"+t,r="/"===a.charAt(0))}return t=n(i(t.split("/"),(function(e){return!!e})),!r).join("/"),(r?"/":"")+t||"."},t.normalize=function(e){var r=t.isAbsolute(e),a="/"===o(e,-1);return e=n(i(e.split("/"),(function(e){return!!e})),!r).join("/"),e||r||(e="."),e&&a&&(e+="/"),(r?"/":"")+e},t.isAbsolute=function(e){return"/"===e.charAt(0)},t.join=function(){var e=Array.prototype.slice.call(arguments,0);return t.normalize(i(e,(function(e,t){if("string"!==typeof e)throw new TypeError("Arguments to path.join must be strings");return e})).join("/"))},t.relative=function(e,n){function r(e){for(var t=0;t=0;n--)if(""!==e[n])break;return t>n?[]:e.slice(t,n-t+1)}e=t.resolve(e).substr(1),n=t.resolve(n).substr(1);for(var i=r(e.split("/")),o=r(n.split("/")),a=Math.min(i.length,o.length),s=a,c=0;c=1;--o)if(t=e.charCodeAt(o),47===t){if(!i){r=o;break}}else i=!1;return-1===r?n?"/":".":n&&1===r?"/":e.slice(0,r)},t.basename=function(e,t){var n=r(e);return t&&n.substr(-1*t.length)===t&&(n=n.substr(0,n.length-t.length)),n},t.extname=function(e){"string"!==typeof e&&(e+="");for(var t=-1,n=0,r=-1,i=!0,o=0,a=e.length-1;a>=0;--a){var s=e.charCodeAt(a);if(47!==s)-1===r&&(i=!1,r=a+1),46===s?-1===t?t=a:1!==o&&(o=1):-1!==t&&(o=-1);else if(!i){n=a+1;break}}return-1===t||-1===r||0===o||1===o&&t===r-1&&t===n+1?"":e.slice(t,r)};var o="b"==="ab".substr(-1)?function(e,t,n){return e.substr(t,n)}:function(e,t,n){return t<0&&(t=e.length+t),e.substr(t,n)}}).call(this,n("4362"))},e01a:function(e,t,n){"use strict";var r=n("23e7"),i=n("83ab"),o=n("da84"),a=n("5135"),s=n("861d"),c=n("9bf2").f,u=n("e893"),l=o.Symbol;if(i&&"function"==typeof l&&(!("description"in l.prototype)||void 0!==l().description)){var f={},d=function(){var e=arguments.length<1||void 0===arguments[0]?void 0:String(arguments[0]),t=this instanceof d?new l(e):void 0===e?l():l(e);return""===e&&(f[t]=!0),t};u(d,l);var p=d.prototype=l.prototype;p.constructor=d;var h=p.toString,v="Symbol(test)"==String(l("test")),g=/^Symbol\((.*)\)[^)]+$/;c(p,"description",{configurable:!0,get:function(){var e=s(this)?this.valueOf():this,t=h.call(e);if(a(f,e))return"";var n=v?t.slice(7,-1):t.replace(g,"$1");return""===n?void 0:n}}),r({global:!0,forced:!0},{Symbol:d})}},e163:function(e,t,n){var r=n("5135"),i=n("7b0b"),o=n("f772"),a=n("e177"),s=o("IE_PROTO"),c=Object.prototype;e.exports=a?Object.getPrototypeOf:function(e){return e=i(e),r(e,s)?e[s]:"function"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?c:null}},e177:function(e,t,n){var r=n("d039");e.exports=!r((function(){function e(){}return e.prototype.constructor=null,Object.getPrototypeOf(new e)!==e.prototype}))},e21d:function(e,t,n){var r=n("23e7"),i=n("d039"),o=n("861d"),a=Object.isFrozen,s=i((function(){a(1)}));r({target:"Object",stat:!0,forced:s},{isFrozen:function(e){return!o(e)||!!a&&a(e)}})},e25e:function(e,t,n){var r=n("23e7"),i=n("c20d");r({global:!0,forced:parseInt!=i},{parseInt:i})},e260:function(e,t,n){"use strict";var r=n("fc6a"),i=n("44d2"),o=n("3f8c"),a=n("69f3"),s=n("7dd0"),c="Array Iterator",u=a.set,l=a.getterFor(c);e.exports=s(Array,"Array",(function(e,t){u(this,{type:c,target:r(e),index:0,kind:t})}),(function(){var e=l(this),t=e.target,n=e.kind,r=e.index++;return!t||r>=t.length?(e.target=void 0,{value:void 0,done:!0}):"keys"==n?{value:r,done:!1}:"values"==n?{value:t[r],done:!1}:{value:[r,t[r]],done:!1}}),"values"),o.Arguments=o.Array,i("keys"),i("values"),i("entries")},e285:function(e,t,n){var r=n("da84"),i=r.isFinite;e.exports=Number.isFinite||function(e){return"number"==typeof e&&i(e)}},e2cc:function(e,t,n){var r=n("6eeb");e.exports=function(e,t,n){for(var i in t)r(e,i,t[i],n);return e}},e439:function(e,t,n){var r=n("23e7"),i=n("d039"),o=n("fc6a"),a=n("06cf").f,s=n("83ab"),c=i((function(){a(1)})),u=!s||c;r({target:"Object",stat:!0,forced:u,sham:!s},{getOwnPropertyDescriptor:function(e,t){return a(o(e),t)}})},e43e:function(e,t,n){var r=n("23e7"),i=n("d039"),o=n("861d"),a=Object.isSealed,s=i((function(){a(1)}));r({target:"Object",stat:!0,forced:s},{isSealed:function(e){return!o(e)||!!a&&a(e)}})},e4cb:function(e,t,n){(function(){var t=n("3393").L,r=n("66d5").N,i=n("2d93").Z,o=n("7f55").M,a=n("2ce5"),s=function(e){return~t.indexOf(e)?"L":~r.indexOf(e)?"N":~i.indexOf(e)?"Z":~o.indexOf(e)?"M":void 0};e.exports=function(e,t){e=e||"",t=t||{};for(var n=t.allowedChars||"-_~",r="boolean"!==typeof t.lower||t.lower,i="boolean"===typeof t.spaces&&t.spaces,o=[],c=a.nfkc(e),u=0;u1&&(a=s(a,i(arguments[1]))),a<0&&(a=n+a);a>=0;a--)if(a in t&&t[a]===e)return a||0;return-1}:c},e667:function(e,t){e.exports=function(e){try{return{error:!1,value:e()}}catch(t){return{error:!0,value:t}}}},e6cf:function(e,t,n){"use strict";var r,i,o,a,s=n("23e7"),c=n("c430"),u=n("da84"),l=n("d066"),f=n("fea9"),d=n("6eeb"),p=n("e2cc"),h=n("d2bb"),v=n("d44e"),g=n("2626"),b=n("861d"),m=n("1c0b"),y=n("19aa"),w=n("8925"),_=n("2266"),x=n("1c7e"),E=n("4840"),S=n("2cf4").set,A=n("b575"),k=n("cdf9"),O=n("44de"),C=n("f069"),M=n("e667"),T=n("69f3"),R=n("94ca"),I=n("b622"),N=n("6069"),j=n("605d"),P=n("2d00"),L=I("species"),$="Promise",D=T.get,F=T.set,B=T.getterFor($),U=f&&f.prototype,z=f,H=U,q=u.TypeError,W=u.document,V=u.process,K=C.f,G=K,J=!!(W&&W.createEvent&&u.dispatchEvent),X="function"==typeof PromiseRejectionEvent,Y="unhandledrejection",Z="rejectionhandled",Q=0,ee=1,te=2,ne=1,re=2,ie=!1,oe=R($,(function(){var e=w(z)!==String(z);if(!e&&66===P)return!0;if(c&&!H["finally"])return!0;if(P>=51&&/native code/.test(z))return!1;var t=new z((function(e){e(1)})),n=function(e){e((function(){}),(function(){}))},r=t.constructor={};return r[L]=n,ie=t.then((function(){}))instanceof n,!ie||!e&&N&&!X})),ae=oe||!x((function(e){z.all(e)["catch"]((function(){}))})),se=function(e){var t;return!(!b(e)||"function"!=typeof(t=e.then))&&t},ce=function(e,t){if(!e.notified){e.notified=!0;var n=e.reactions;A((function(){var r=e.value,i=e.state==ee,o=0;while(n.length>o){var a,s,c,u=n[o++],l=i?u.ok:u.fail,f=u.resolve,d=u.reject,p=u.domain;try{l?(i||(e.rejection===re&&de(e),e.rejection=ne),!0===l?a=r:(p&&p.enter(),a=l(r),p&&(p.exit(),c=!0)),a===u.promise?d(q("Promise-chain cycle")):(s=se(a))?s.call(a,f,d):f(a)):d(r)}catch(h){p&&!c&&p.exit(),d(h)}}e.reactions=[],e.notified=!1,t&&!e.rejection&&le(e)}))}},ue=function(e,t,n){var r,i;J?(r=W.createEvent("Event"),r.promise=t,r.reason=n,r.initEvent(e,!1,!0),u.dispatchEvent(r)):r={promise:t,reason:n},!X&&(i=u["on"+e])?i(r):e===Y&&O("Unhandled promise rejection",n)},le=function(e){S.call(u,(function(){var t,n=e.facade,r=e.value,i=fe(e);if(i&&(t=M((function(){j?V.emit("unhandledRejection",r,n):ue(Y,n,r)})),e.rejection=j||fe(e)?re:ne,t.error))throw t.value}))},fe=function(e){return e.rejection!==ne&&!e.parent},de=function(e){S.call(u,(function(){var t=e.facade;j?V.emit("rejectionHandled",t):ue(Z,t,e.value)}))},pe=function(e,t,n){return function(r){e(t,r,n)}},he=function(e,t,n){e.done||(e.done=!0,n&&(e=n),e.value=t,e.state=te,ce(e,!0))},ve=function(e,t,n){if(!e.done){e.done=!0,n&&(e=n);try{if(e.facade===t)throw q("Promise can't be resolved itself");var r=se(t);r?A((function(){var n={done:!1};try{r.call(t,pe(ve,n,e),pe(he,n,e))}catch(i){he(n,i,e)}})):(e.value=t,e.state=ee,ce(e,!1))}catch(i){he({done:!1},i,e)}}};if(oe&&(z=function(e){y(this,z,$),m(e),r.call(this);var t=D(this);try{e(pe(ve,t),pe(he,t))}catch(n){he(t,n)}},H=z.prototype,r=function(e){F(this,{type:$,done:!1,notified:!1,parent:!1,reactions:[],rejection:!1,state:Q,value:void 0})},r.prototype=p(H,{then:function(e,t){var n=B(this),r=K(E(this,z));return r.ok="function"!=typeof e||e,r.fail="function"==typeof t&&t,r.domain=j?V.domain:void 0,n.parent=!0,n.reactions.push(r),n.state!=Q&&ce(n,!1),r.promise},catch:function(e){return this.then(void 0,e)}}),i=function(){var e=new r,t=D(e);this.promise=e,this.resolve=pe(ve,t),this.reject=pe(he,t)},C.f=K=function(e){return e===z||e===o?new i(e):G(e)},!c&&"function"==typeof f&&U!==Object.prototype)){a=U.then,ie||(d(U,"then",(function(e,t){var n=this;return new z((function(e,t){a.call(n,e,t)})).then(e,t)}),{unsafe:!0}),d(U,"catch",H["catch"],{unsafe:!0}));try{delete U.constructor}catch(ge){}h&&h(U,H)}s({global:!0,wrap:!0,forced:oe},{Promise:z}),v(z,$,!1,!0),g($),o=l($),s({target:$,stat:!0,forced:oe},{reject:function(e){var t=K(this);return t.reject.call(void 0,e),t.promise}}),s({target:$,stat:!0,forced:c||oe},{resolve:function(e){return k(c&&this===o?z:this,e)}}),s({target:$,stat:!0,forced:ae},{all:function(e){var t=this,n=K(t),r=n.resolve,i=n.reject,o=M((function(){var n=m(t.resolve),o=[],a=0,s=1;_(e,(function(e){var c=a++,u=!1;o.push(void 0),s++,n.call(t,e).then((function(e){u||(u=!0,o[c]=e,--s||r(o))}),i)})),--s||r(o)}));return o.error&&i(o.value),n.promise},race:function(e){var t=this,n=K(t),r=n.reject,i=M((function(){var i=m(t.resolve);_(e,(function(e){i.call(t,e).then(n.resolve,r)}))}));return i.error&&r(i.value),n.promise}})},e6e1:function(e,t,n){var r=n("23e7");r({target:"Number",stat:!0},{MIN_SAFE_INTEGER:-9007199254740991})},e6f9:function(e,t,n){"use strict";function r(e,t,n,r){var i=Number(e[t].meta.id+1).toString(),o="";return"string"===typeof r.docId&&(o="-"+r.docId+"-"),o+i}function i(e,t){var n=Number(e[t].meta.id+1).toString();return e[t].meta.subId>0&&(n+=":"+e[t].meta.subId),"["+n+"]"}function o(e,t,n,r,i){var o=i.rules.footnote_anchor_name(e,t,n,r,i),a=i.rules.footnote_caption(e,t,n,r,i),s=o;return e[t].meta.subId>0&&(s+=":"+e[t].meta.subId),''+a+""}function a(e,t,n){return(n.xhtmlOut?'
\n':'
\n')+'
\n
    \n'}function s(){return"
\n
\n"}function c(e,t,n,r,i){var o=i.rules.footnote_anchor_name(e,t,n,r,i);return e[t].meta.subId>0&&(o+=":"+e[t].meta.subId),'
  • '}function u(){return"
  • \n"}function l(e,t,n,r,i){var o=i.rules.footnote_anchor_name(e,t,n,r,i);return e[t].meta.subId>0&&(o+=":"+e[t].meta.subId),' ↩︎'}e.exports=function(e){var t=e.helpers.parseLinkLabel,n=e.utils.isSpace;function f(e,t,r,i){var o,a,s,c,u,l,f,d,p,h,v,g=e.bMarks[t]+e.tShift[t],b=e.eMarks[t];if(g+4>b)return!1;if(91!==e.src.charCodeAt(g))return!1;if(94!==e.src.charCodeAt(g+1))return!1;for(u=g+2;u=b||58!==e.src.charCodeAt(++u))return!1;if(i)return!0;u++,e.env.footnotes||(e.env.footnotes={}),e.env.footnotes.refs||(e.env.footnotes.refs={}),l=e.src.slice(g+2,u-2),e.env.footnotes.refs[":"+l]=-1,f=new e.Token("footnote_reference_open","",1),f.meta={label:l},f.level=e.level++,e.tokens.push(f),o=e.bMarks[t],a=e.tShift[t],s=e.sCount[t],c=e.parentType,v=u,d=p=e.sCount[t]+u-(e.bMarks[t]+e.tShift[t]);while(u=c)&&(94===e.src.charCodeAt(u)&&(91===e.src.charCodeAt(u+1)&&(r=u+2,i=t(e,u+1),!(i<0)&&(n||(e.env.footnotes||(e.env.footnotes={}),e.env.footnotes.list||(e.env.footnotes.list=[]),o=e.env.footnotes.list.length,e.md.inline.parse(e.src.slice(r,i),e.md,e.env,s=[]),a=e.push("footnote_ref","",0),a.meta={id:o},e.env.footnotes.list[o]={content:e.src.slice(r,i),tokens:s}),e.pos=i+1,e.posMax=c,!0))))}function p(e,t){var n,r,i,o,a,s=e.posMax,c=e.pos;if(c+3>s)return!1;if(!e.env.footnotes||!e.env.footnotes.refs)return!1;if(91!==e.src.charCodeAt(c))return!1;if(94!==e.src.charCodeAt(c+1))return!1;for(r=c+2;r=s)&&(r++,n=e.src.slice(c+2,r-1),"undefined"!==typeof e.env.footnotes.refs[":"+n]&&(t||(e.env.footnotes.list||(e.env.footnotes.list=[]),e.env.footnotes.refs[":"+n]<0?(i=e.env.footnotes.list.length,e.env.footnotes.list[i]={label:n,count:0},e.env.footnotes.refs[":"+n]=i):i=e.env.footnotes.refs[":"+n],o=e.env.footnotes.list[i].count,e.env.footnotes.list[i].count++,a=e.push("footnote_ref","",0),a.meta={id:i,subId:o,label:n}),e.pos=r,e.posMax=s,!0)))}function h(e){var t,n,r,i,o,a,s,c,u,l,f=!1,d={};if(e.env.footnotes&&(e.tokens=e.tokens.filter((function(e){return"footnote_reference_open"===e.type?(f=!0,u=[],l=e.meta.label,!1):"footnote_reference_close"===e.type?(f=!1,d[":"+l]=u,!1):(f&&u.push(e),!f)})),e.env.footnotes.list)){for(a=e.env.footnotes.list,s=new e.Token("footnote_block_open","",1),e.tokens.push(s),t=0,n=a.length;t0?a[t].count:1,r=0;r1?arguments[1]:void 0)}))},e95a:function(e,t,n){var r=n("b622"),i=n("3f8c"),o=r("iterator"),a=Array.prototype;e.exports=function(e){return void 0!==e&&(i.Array===e||a[o]===e)}},e9c4:function(e,t,n){var r=n("23e7"),i=n("d066"),o=n("d039"),a=i("JSON","stringify"),s=/[\uD800-\uDFFF]/g,c=/^[\uD800-\uDBFF]$/,u=/^[\uDC00-\uDFFF]$/,l=function(e,t,n){var r=n.charAt(t-1),i=n.charAt(t+1);return c.test(e)&&!u.test(i)||u.test(e)&&!c.test(r)?"\\u"+e.charCodeAt(0).toString(16):e},f=o((function(){return'"\\udf06\\ud834"'!==a("\udf06\ud834")||'"\\udead"'!==a("\udead")}));a&&r({target:"JSON",stat:!0,forced:f},{stringify:function(e,t,n){var r=a.apply(null,arguments);return"string"==typeof r?r.replace(s,l):r}})},eb1d:function(e,t,n){"use strict";var r=n("c430"),i=n("da84"),o=n("d039");e.exports=r||!o((function(){var e=Math.random();__defineSetter__.call(null,e,(function(){})),delete i[e]}))},ebb5:function(e,t,n){"use strict";var r,i=n("a981"),o=n("83ab"),a=n("da84"),s=n("861d"),c=n("5135"),u=n("f5df"),l=n("9112"),f=n("6eeb"),d=n("9bf2").f,p=n("e163"),h=n("d2bb"),v=n("b622"),g=n("90e3"),b=a.Int8Array,m=b&&b.prototype,y=a.Uint8ClampedArray,w=y&&y.prototype,_=b&&p(b),x=m&&p(m),E=Object.prototype,S=E.isPrototypeOf,A=v("toStringTag"),k=g("TYPED_ARRAY_TAG"),O=i&&!!h&&"Opera"!==u(a.opera),C=!1,M={Int8Array:1,Uint8Array:1,Uint8ClampedArray:1,Int16Array:2,Uint16Array:2,Int32Array:4,Uint32Array:4,Float32Array:4,Float64Array:8},T={BigInt64Array:8,BigUint64Array:8},R=function(e){if(!s(e))return!1;var t=u(e);return"DataView"===t||c(M,t)||c(T,t)},I=function(e){if(!s(e))return!1;var t=u(e);return c(M,t)||c(T,t)},N=function(e){if(I(e))return e;throw TypeError("Target is not a typed array")},j=function(e){if(h){if(S.call(_,e))return e}else for(var t in M)if(c(M,r)){var n=a[t];if(n&&(e===n||S.call(n,e)))return e}throw TypeError("Target is not a typed array constructor")},P=function(e,t,n){if(o){if(n)for(var r in M){var i=a[r];if(i&&c(i.prototype,e))try{delete i.prototype[e]}catch(s){}}x[e]&&!n||f(x,e,n?t:O&&m[e]||t)}},L=function(e,t,n){var r,i;if(o){if(h){if(n)for(r in M)if(i=a[r],i&&c(i,e))try{delete i[e]}catch(s){}if(_[e]&&!n)return;try{return f(_,e,n?t:O&&_[e]||t)}catch(s){}}for(r in M)i=a[r],!i||i[e]&&!n||f(i,e,t)}};for(r in M)a[r]||(O=!1);if((!O||"function"!=typeof _||_===Function.prototype)&&(_=function(){throw TypeError("Incorrect invocation")},O))for(r in M)a[r]&&h(a[r],_);if((!O||!x||x===E)&&(x=_.prototype,O))for(r in M)a[r]&&h(a[r].prototype,x);if(O&&p(w)!==x&&h(w,x),o&&!c(x,A))for(r in C=!0,d(x,A,{get:function(){return s(this)?this[k]:void 0}}),M)a[r]&&l(a[r],k,r);e.exports={NATIVE_ARRAY_BUFFER_VIEWS:O,TYPED_ARRAY_TAG:C&&k,aTypedArray:N,aTypedArrayConstructor:j,exportTypedArrayMethod:P,exportTypedArrayStaticMethod:L,isView:R,isTypedArray:I,TypedArray:_,TypedArrayPrototype:x}},ec97:function(e,t,n){"use strict";var r=n("ebb5"),i=n("8aa7"),o=r.aTypedArrayConstructor,a=r.exportTypedArrayStaticMethod;a("of",(function(){var e=0,t=arguments.length,n=new(o(this))(t);while(t>e)n[e]=arguments[e++];return n}),i)},eee7:function(e,t,n){"use strict";var r=n("23e7"),i=n("58a8").start,o=n("c8d2"),a=o("trimStart"),s=a?function(){return i(this)}:"".trimStart;r({target:"String",proto:!0,forced:a},{trimStart:s,trimLeft:s})},efe9:function(e,t,n){var r=n("746f");r("isConcatSpreadable")},efec:function(e,t,n){var r=n("9112"),i=n("51eb"),o=n("b622"),a=o("toPrimitive"),s=Date.prototype;a in s||r(s,a,i)},f00c:function(e,t,n){var r=n("23e7"),i=n("e285");r({target:"Number",stat:!0},{isFinite:i})},f069:function(e,t,n){"use strict";var r=n("1c0b"),i=function(e){var t,n;this.promise=new e((function(e,r){if(void 0!==t||void 0!==n)throw TypeError("Bad Promise constructor");t=e,n=r})),this.resolve=r(t),this.reject=r(n)};e.exports.f=function(e){return new i(e)}},f183:function(e,t,n){var r=n("d012"),i=n("861d"),o=n("5135"),a=n("9bf2").f,s=n("90e3"),c=n("bb2f"),u=s("meta"),l=0,f=Object.isExtensible||function(){return!0},d=function(e){a(e,u,{value:{objectID:"O"+ ++l,weakData:{}}})},p=function(e,t){if(!i(e))return"symbol"==typeof e?e:("string"==typeof e?"S":"P")+e;if(!o(e,u)){if(!f(e))return"F";if(!t)return"E";d(e)}return e[u].objectID},h=function(e,t){if(!o(e,u)){if(!f(e))return!0;if(!t)return!1;d(e)}return e[u].weakData},v=function(e){return c&&g.REQUIRED&&f(e)&&!o(e,u)&&d(e),e},g=e.exports={REQUIRED:!1,fastKey:p,getWeakData:h,onFreeze:v};r[u]=!0},f4b3:function(e,t,n){"use strict";var r=n("23e7"),i=n("d039"),o=n("7b0b"),a=n("c04e"),s=i((function(){return null!==new Date(NaN).toJSON()||1!==Date.prototype.toJSON.call({toISOString:function(){return 1}})}));r({target:"Date",proto:!0,forced:s},{toJSON:function(e){var t=o(this),n=a(t);return"number"!=typeof n||isFinite(n)?t.toISOString():null}})},f4dd:function(e,t,n){"use strict";var r=n("23e7"),i=n("d58f").right,o=n("a640"),a=n("2d00"),s=n("605d"),c=o("reduceRight"),u=!s&&a>79&&a<83;r({target:"Array",proto:!0,forced:!c||u},{reduceRight:function(e){return i(this,e,arguments.length,arguments.length>1?arguments[1]:void 0)}})},f5b2:function(e,t,n){"use strict";var r=n("23e7"),i=n("6547").codeAt;r({target:"String",proto:!0},{codePointAt:function(e){return i(this,e)}})},f5df:function(e,t,n){var r=n("00ee"),i=n("c6b6"),o=n("b622"),a=o("toStringTag"),s="Arguments"==i(function(){return arguments}()),c=function(e,t){try{return e[t]}catch(n){}};e.exports=r?i:function(e){var t,n,r;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=c(t=Object(e),a))?n:s?i(t):"Object"==(r=i(t))&&"function"==typeof t.callee?"Arguments":r}},f664:function(e,t,n){var r=n("23e7"),i=n("be8e");r({target:"Math",stat:!0},{fround:i})},f6d6:function(e,t,n){var r=n("23e7"),i=n("23cb"),o=String.fromCharCode,a=String.fromCodePoint,s=!!a&&1!=a.length;r({target:"String",stat:!0,forced:s},{fromCodePoint:function(e){var t,n=[],r=arguments.length,a=0;while(r>a){if(t=+arguments[a++],i(t,1114111)!==t)throw RangeError(t+" is not a valid code point");n.push(t<65536?o(t):o(55296+((t-=65536)>>10),t%1024+56320))}return n.join("")}})},f748:function(e,t){e.exports=Math.sign||function(e){return 0==(e=+e)||e!=e?e:e<0?-1:1}},f772:function(e,t,n){var r=n("5692"),i=n("90e3"),o=r("keys");e.exports=function(e){return o[e]||(o[e]=i(e))}},f785:function(e,t,n){var r=n("2626");r("Array")},f8c9:function(e,t,n){var r=n("23e7"),i=n("da84"),o=n("d44e");r({global:!0},{Reflect:{}}),o(i.Reflect,"Reflect",!0)},f8cd:function(e,t,n){var r=n("a691");e.exports=function(e){var t=r(e);if(t<0)throw RangeError("The argument can't be less than 0");return t}},fb2c:function(e,t,n){var r=n("74e8");r("Uint32",(function(e){return function(t,n,r){return e(this,t,n,r)}}))},fb6a:function(e,t,n){"use strict";var r=n("23e7"),i=n("861d"),o=n("e8b5"),a=n("23cb"),s=n("50c4"),c=n("fc6a"),u=n("8418"),l=n("b622"),f=n("1dde"),d=f("slice"),p=l("species"),h=[].slice,v=Math.max;r({target:"Array",proto:!0,forced:!d},{slice:function(e,t){var n,r,l,f=c(this),d=s(f.length),g=a(e,d),b=a(void 0===t?d:t,d);if(o(f)&&(n=f.constructor,"function"!=typeof n||n!==Array&&!o(n.prototype)?i(n)&&(n=n[p],null===n&&(n=void 0)):n=void 0,n===Array||void 0===n))return h.call(f,g,b);for(r=new(void 0===n?Array:n)(v(b-g,0)),l=0;g]*>)/g;\nvar SUBSTITUTION_SYMBOLS_NO_NAMED = /\\$([$&'`]|\\d{1,2})/g;\n\n// https://tc39.es/ecma262/#sec-getsubstitution\nmodule.exports = function (matched, str, position, captures, namedCaptures, replacement) {\n var tailPos = position + matched.length;\n var m = captures.length;\n var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;\n if (namedCaptures !== undefined) {\n namedCaptures = toObject(namedCaptures);\n symbols = SUBSTITUTION_SYMBOLS;\n }\n return replace.call(replacement, symbols, function (match, ch) {\n var capture;\n switch (ch.charAt(0)) {\n case '$': return '$';\n case '&': return matched;\n case '`': return str.slice(0, position);\n case \"'\": return str.slice(tailPos);\n case '<':\n capture = namedCaptures[ch.slice(1, -1)];\n break;\n default: // \\d\\d?\n var n = +ch;\n if (n === 0) return match;\n if (n > m) {\n var f = floor(n / 10);\n if (f === 0) return match;\n if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1);\n return match;\n }\n capture = captures[n - 1];\n }\n return capture === undefined ? '' : capture;\n });\n};\n","// https://github.com/tc39/proposal-string-pad-start-end\nvar toLength = require('../internals/to-length');\nvar repeat = require('../internals/string-repeat');\nvar requireObjectCoercible = require('../internals/require-object-coercible');\n\nvar ceil = Math.ceil;\n\n// `String.prototype.{ padStart, padEnd }` methods implementation\nvar createMethod = function (IS_END) {\n return function ($this, maxLength, fillString) {\n var S = String(requireObjectCoercible($this));\n var stringLength = S.length;\n var fillStr = fillString === undefined ? ' ' : String(fillString);\n var intMaxLength = toLength(maxLength);\n var fillLen, stringFiller;\n if (intMaxLength <= stringLength || fillStr == '') return S;\n fillLen = intMaxLength - stringLength;\n stringFiller = repeat.call(fillStr, ceil(fillLen / fillStr.length));\n if (stringFiller.length > fillLen) stringFiller = stringFiller.slice(0, fillLen);\n return IS_END ? S + stringFiller : stringFiller + S;\n };\n};\n\nmodule.exports = {\n // `String.prototype.padStart` method\n // https://tc39.es/ecma262/#sec-string.prototype.padstart\n start: createMethod(false),\n // `String.prototype.padEnd` method\n // https://tc39.es/ecma262/#sec-string.prototype.padend\n end: createMethod(true)\n};\n","// mutationobserver-shim v0.3.3 (github.com/megawac/MutationObserver.js)\n// Authors: Graeme Yeates (github.com/megawac) \n/*\n Shim for MutationObserver interface\n Author: Graeme Yeates (github.com/megawac)\n Repository: https://github.com/megawac/MutationObserver.js\n License: WTFPL V2, 2004 (wtfpl.net).\n Though credit and staring the repo will make me feel pretty, you can modify and redistribute as you please.\n Attempts to follow spec (https://www.w3.org/TR/dom/#mutation-observers) as closely as possible for native javascript\n See https://github.com/WebKit/webkit/blob/master/Source/WebCore/dom/MutationObserver.cpp for current webkit source c++ implementation\n*/\nwindow.MutationObserver||(window.MutationObserver=function(y){function z(a){this.i=[];this.m=a}function K(a){(function c(){var d=a.takeRecords();d.length&&a.m(d,a);a.h=setTimeout(c,z._period)})()}function r(a){var b={type:null,target:null,addedNodes:[],removedNodes:[],previousSibling:null,nextSibling:null,attributeName:null,attributeNamespace:null,oldValue:null},c;for(c in a)b[c]!==y&&a[c]!==y&&(b[c]=a[c]);return b}function L(a,b){var c=E(a,b);return function(d){var f=d.length;b.a&&3===a.nodeType&&\na.nodeValue!==c.a&&d.push(new r({type:\"characterData\",target:a,oldValue:c.a}));b.b&&c.b&&C(d,a,c.b,b.f);if(b.c||b.g)var m=M(d,a,c,b);if(m||d.length!==f)c=E(a,b)}}function N(a,b){return b.value}function O(a,b){return\"style\"!==b.name?b.value:a.style.cssText}function C(a,b,c,d){for(var f={},m=b.attributes,k,g,p=m.length;p--;)k=m[p],g=k.name,d&&d[g]===y||(F(b,k)!==c[g]&&a.push(r({type:\"attributes\",target:b,attributeName:g,oldValue:c[g],attributeNamespace:k.namespaceURI})),f[g]=!0);for(g in c)f[g]||a.push(r({target:b,\ntype:\"attributes\",attributeName:g,oldValue:c[g]}))}function M(a,b,c,d){function f(g,p,t,q,x){var A=g.length-1;x=-~((A-x)/2);for(var h,l,e;e=g.pop();)h=t[e.j],l=q[e.l],d.c&&x&&Math.abs(e.j-e.l)>=A&&(a.push(r({type:\"childList\",target:p,addedNodes:[h],removedNodes:[h],nextSibling:h.nextSibling,previousSibling:h.previousSibling})),x--),d.b&&l.b&&C(a,h,l.b,d.f),d.a&&3===h.nodeType&&h.nodeValue!==l.a&&a.push(r({type:\"characterData\",target:h,oldValue:l.a})),d.g&&m(h,l)}function m(g,p){for(var t=g.childNodes,\nq=p.c,x=t.length,A=q?q.length:0,h,l,e,n,v,B=0,w=0,u=0;w 0; (n >>>= 1) && (str += str)) if (n & 1) result += str;\n return result;\n};\n","'use strict';\nvar fixRegExpWellKnownSymbolLogic = require('../internals/fix-regexp-well-known-symbol-logic');\nvar isRegExp = require('../internals/is-regexp');\nvar anObject = require('../internals/an-object');\nvar requireObjectCoercible = require('../internals/require-object-coercible');\nvar speciesConstructor = require('../internals/species-constructor');\nvar advanceStringIndex = require('../internals/advance-string-index');\nvar toLength = require('../internals/to-length');\nvar callRegExpExec = require('../internals/regexp-exec-abstract');\nvar regexpExec = require('../internals/regexp-exec');\nvar stickyHelpers = require('../internals/regexp-sticky-helpers');\n\nvar UNSUPPORTED_Y = stickyHelpers.UNSUPPORTED_Y;\nvar arrayPush = [].push;\nvar min = Math.min;\nvar MAX_UINT32 = 0xFFFFFFFF;\n\n// @@split logic\nfixRegExpWellKnownSymbolLogic('split', 2, function (SPLIT, nativeSplit, maybeCallNative) {\n var internalSplit;\n if (\n 'abbc'.split(/(b)*/)[1] == 'c' ||\n // eslint-disable-next-line regexp/no-empty-group -- required for testing\n 'test'.split(/(?:)/, -1).length != 4 ||\n 'ab'.split(/(?:ab)*/).length != 2 ||\n '.'.split(/(.?)(.?)/).length != 4 ||\n // eslint-disable-next-line regexp/no-assertion-capturing-group, regexp/no-empty-group -- required for testing\n '.'.split(/()()/).length > 1 ||\n ''.split(/.?/).length\n ) {\n // based on es5-shim implementation, need to rework it\n internalSplit = function (separator, limit) {\n var string = String(requireObjectCoercible(this));\n var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;\n if (lim === 0) return [];\n if (separator === undefined) return [string];\n // If `separator` is not a regex, use native split\n if (!isRegExp(separator)) {\n return nativeSplit.call(string, separator, lim);\n }\n var output = [];\n var flags = (separator.ignoreCase ? 'i' : '') +\n (separator.multiline ? 'm' : '') +\n (separator.unicode ? 'u' : '') +\n (separator.sticky ? 'y' : '');\n var lastLastIndex = 0;\n // Make `global` and avoid `lastIndex` issues by working with a copy\n var separatorCopy = new RegExp(separator.source, flags + 'g');\n var match, lastIndex, lastLength;\n while (match = regexpExec.call(separatorCopy, string)) {\n lastIndex = separatorCopy.lastIndex;\n if (lastIndex > lastLastIndex) {\n output.push(string.slice(lastLastIndex, match.index));\n if (match.length > 1 && match.index < string.length) arrayPush.apply(output, match.slice(1));\n lastLength = match[0].length;\n lastLastIndex = lastIndex;\n if (output.length >= lim) break;\n }\n if (separatorCopy.lastIndex === match.index) separatorCopy.lastIndex++; // Avoid an infinite loop\n }\n if (lastLastIndex === string.length) {\n if (lastLength || !separatorCopy.test('')) output.push('');\n } else output.push(string.slice(lastLastIndex));\n return output.length > lim ? output.slice(0, lim) : output;\n };\n // Chakra, V8\n } else if ('0'.split(undefined, 0).length) {\n internalSplit = function (separator, limit) {\n return separator === undefined && limit === 0 ? [] : nativeSplit.call(this, separator, limit);\n };\n } else internalSplit = nativeSplit;\n\n return [\n // `String.prototype.split` method\n // https://tc39.es/ecma262/#sec-string.prototype.split\n function split(separator, limit) {\n var O = requireObjectCoercible(this);\n var splitter = separator == undefined ? undefined : separator[SPLIT];\n return splitter !== undefined\n ? splitter.call(separator, O, limit)\n : internalSplit.call(String(O), separator, limit);\n },\n // `RegExp.prototype[@@split]` method\n // https://tc39.es/ecma262/#sec-regexp.prototype-@@split\n //\n // NOTE: This cannot be properly polyfilled in engines that don't support\n // the 'y' flag.\n function (regexp, limit) {\n var res = maybeCallNative(internalSplit, regexp, this, limit, internalSplit !== nativeSplit);\n if (res.done) return res.value;\n\n var rx = anObject(regexp);\n var S = String(this);\n var C = speciesConstructor(rx, RegExp);\n\n var unicodeMatching = rx.unicode;\n var flags = (rx.ignoreCase ? 'i' : '') +\n (rx.multiline ? 'm' : '') +\n (rx.unicode ? 'u' : '') +\n (UNSUPPORTED_Y ? 'g' : 'y');\n\n // ^(? + rx + ) is needed, in combination with some S slicing, to\n // simulate the 'y' flag.\n var splitter = new C(UNSUPPORTED_Y ? '^(?:' + rx.source + ')' : rx, flags);\n var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;\n if (lim === 0) return [];\n if (S.length === 0) return callRegExpExec(splitter, S) === null ? [S] : [];\n var p = 0;\n var q = 0;\n var A = [];\n while (q < S.length) {\n splitter.lastIndex = UNSUPPORTED_Y ? 0 : q;\n var z = callRegExpExec(splitter, UNSUPPORTED_Y ? S.slice(q) : S);\n var e;\n if (\n z === null ||\n (e = min(toLength(splitter.lastIndex + (UNSUPPORTED_Y ? q : 0)), S.length)) === p\n ) {\n q = advanceStringIndex(S, q, unicodeMatching);\n } else {\n A.push(S.slice(p, q));\n if (A.length === lim) return A;\n for (var i = 1; i <= z.length - 1; i++) {\n A.push(z[i]);\n if (A.length === lim) return A;\n }\n q = p = e;\n }\n }\n A.push(S.slice(p));\n return A;\n }\n ];\n}, UNSUPPORTED_Y);\n","// `SameValue` abstract operation\n// https://tc39.es/ecma262/#sec-samevalue\n// eslint-disable-next-line es/no-object-is -- safe\nmodule.exports = Object.is || function is(x, y) {\n // eslint-disable-next-line no-self-compare -- NaN check\n return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar DESCRIPTORS = require('../internals/descriptors');\nvar FORCED = require('../internals/object-prototype-accessors-forced');\nvar toObject = require('../internals/to-object');\nvar aFunction = require('../internals/a-function');\nvar definePropertyModule = require('../internals/object-define-property');\n\n// `Object.prototype.__defineGetter__` method\n// https://tc39.es/ecma262/#sec-object.prototype.__defineGetter__\nif (DESCRIPTORS) {\n $({ target: 'Object', proto: true, forced: FORCED }, {\n __defineGetter__: function __defineGetter__(P, getter) {\n definePropertyModule.f(toObject(this), P, { get: aFunction(getter), enumerable: true, configurable: true });\n }\n });\n}\n","var $ = require('../internals/export');\nvar global = require('../internals/global');\nvar task = require('../internals/task');\n\nvar FORCED = !global.setImmediate || !global.clearImmediate;\n\n// http://w3c.github.io/setImmediate/\n$({ global: true, bind: true, enumerable: true, forced: FORCED }, {\n // `setImmediate` method\n // http://w3c.github.io/setImmediate/#si-setImmediate\n setImmediate: task.set,\n // `clearImmediate` method\n // http://w3c.github.io/setImmediate/#si-clearImmediate\n clearImmediate: task.clear\n});\n","var $ = require('../internals/export');\nvar setPrototypeOf = require('../internals/object-set-prototype-of');\n\n// `Object.setPrototypeOf` method\n// https://tc39.es/ecma262/#sec-object.setprototypeof\n$({ target: 'Object', stat: true }, {\n setPrototypeOf: setPrototypeOf\n});\n","'use strict';\nvar $ = require('../internals/export');\nvar createHTML = require('../internals/create-html');\nvar forcedStringHTMLMethod = require('../internals/string-html-forced');\n\n// `String.prototype.big` method\n// https://tc39.es/ecma262/#sec-string.prototype.big\n$({ target: 'String', proto: true, forced: forcedStringHTMLMethod('big') }, {\n big: function big() {\n return createHTML(this, 'big', '', '');\n }\n});\n","'use strict';\nvar $ = require('../internals/export');\nvar $reduce = require('../internals/array-reduce').left;\nvar arrayMethodIsStrict = require('../internals/array-method-is-strict');\nvar CHROME_VERSION = require('../internals/engine-v8-version');\nvar IS_NODE = require('../internals/engine-is-node');\n\nvar STRICT_METHOD = arrayMethodIsStrict('reduce');\n// Chrome 80-82 has a critical bug\n// https://bugs.chromium.org/p/chromium/issues/detail?id=1049982\nvar CHROME_BUG = !IS_NODE && CHROME_VERSION > 79 && CHROME_VERSION < 83;\n\n// `Array.prototype.reduce` method\n// https://tc39.es/ecma262/#sec-array.prototype.reduce\n$({ target: 'Array', proto: true, forced: !STRICT_METHOD || CHROME_BUG }, {\n reduce: function reduce(callbackfn /* , initialValue */) {\n return $reduce(this, callbackfn, arguments.length, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\n","var createTypedArrayConstructor = require('../internals/typed-array-constructor');\n\n// `Int32Array` constructor\n// https://tc39.es/ecma262/#sec-typedarray-objects\ncreateTypedArrayConstructor('Int32', function (init) {\n return function Int32Array(data, byteOffset, length) {\n return init(this, data, byteOffset, length);\n };\n});\n","var aTypedArrayConstructor = require('../internals/array-buffer-view-core').aTypedArrayConstructor;\nvar speciesConstructor = require('../internals/species-constructor');\n\nmodule.exports = function (instance, list) {\n var C = speciesConstructor(instance, instance.constructor);\n var index = 0;\n var length = list.length;\n var result = new (aTypedArrayConstructor(C))(length);\n while (length > index) result[index] = list[index++];\n return result;\n};\n","'use strict';\nvar toObject = require('../internals/to-object');\nvar toAbsoluteIndex = require('../internals/to-absolute-index');\nvar toLength = require('../internals/to-length');\n\nvar min = Math.min;\n\n// `Array.prototype.copyWithin` method implementation\n// https://tc39.es/ecma262/#sec-array.prototype.copywithin\n// eslint-disable-next-line es/no-array-prototype-copywithin -- safe\nmodule.exports = [].copyWithin || function copyWithin(target /* = 0 */, start /* = 0, end = @length */) {\n var O = toObject(this);\n var len = toLength(O.length);\n var to = toAbsoluteIndex(target, len);\n var from = toAbsoluteIndex(start, len);\n var end = arguments.length > 2 ? arguments[2] : undefined;\n var count = min((end === undefined ? len : toAbsoluteIndex(end, len)) - from, len - to);\n var inc = 1;\n if (from < to && to < from + count) {\n inc = -1;\n from += count - 1;\n to += count - 1;\n }\n while (count-- > 0) {\n if (from in O) O[to] = O[from];\n else delete O[to];\n to += inc;\n from += inc;\n } return O;\n};\n","var classof = require('./classof-raw');\nvar regexpExec = require('./regexp-exec');\n\n// `RegExpExec` abstract operation\n// https://tc39.es/ecma262/#sec-regexpexec\nmodule.exports = function (R, S) {\n var exec = R.exec;\n if (typeof exec === 'function') {\n var result = exec.call(R, S);\n if (typeof result !== 'object') {\n throw TypeError('RegExp exec method returned something other than an Object or null');\n }\n return result;\n }\n\n if (classof(R) !== 'RegExp') {\n throw TypeError('RegExp#exec called on incompatible receiver');\n }\n\n return regexpExec.call(R, S);\n};\n\n","var global = require('../internals/global');\nvar DOMIterables = require('../internals/dom-iterables');\nvar forEach = require('../internals/array-for-each');\nvar createNonEnumerableProperty = require('../internals/create-non-enumerable-property');\n\nfor (var COLLECTION_NAME in DOMIterables) {\n var Collection = global[COLLECTION_NAME];\n var CollectionPrototype = Collection && Collection.prototype;\n // some Chrome versions have non-configurable methods on DOMTokenList\n if (CollectionPrototype && CollectionPrototype.forEach !== forEach) try {\n createNonEnumerableProperty(CollectionPrototype, 'forEach', forEach);\n } catch (error) {\n CollectionPrototype.forEach = forEach;\n }\n}\n","'use strict';\nvar ArrayBufferViewCore = require('../internals/array-buffer-view-core');\nvar toLength = require('../internals/to-length');\nvar toAbsoluteIndex = require('../internals/to-absolute-index');\nvar speciesConstructor = require('../internals/species-constructor');\n\nvar aTypedArray = ArrayBufferViewCore.aTypedArray;\nvar exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;\n\n// `%TypedArray%.prototype.subarray` method\n// https://tc39.es/ecma262/#sec-%typedarray%.prototype.subarray\nexportTypedArrayMethod('subarray', function subarray(begin, end) {\n var O = aTypedArray(this);\n var length = O.length;\n var beginIndex = toAbsoluteIndex(begin, length);\n return new (speciesConstructor(O, O.constructor))(\n O.buffer,\n O.byteOffset + beginIndex * O.BYTES_PER_ELEMENT,\n toLength((end === undefined ? length : toAbsoluteIndex(end, length)) - beginIndex)\n );\n});\n","'use strict';\nvar $forEach = require('../internals/array-iteration').forEach;\nvar arrayMethodIsStrict = require('../internals/array-method-is-strict');\n\nvar STRICT_METHOD = arrayMethodIsStrict('forEach');\n\n// `Array.prototype.forEach` method implementation\n// https://tc39.es/ecma262/#sec-array.prototype.foreach\nmodule.exports = !STRICT_METHOD ? function forEach(callbackfn /* , thisArg */) {\n return $forEach(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n// eslint-disable-next-line es/no-array-prototype-foreach -- safe\n} : [].forEach;\n","var toPositiveInteger = require('../internals/to-positive-integer');\n\nmodule.exports = function (it, BYTES) {\n var offset = toPositiveInteger(it);\n if (offset % BYTES) throw RangeError('Wrong offset');\n return offset;\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar createHTML = require('../internals/create-html');\nvar forcedStringHTMLMethod = require('../internals/string-html-forced');\n\n// `String.prototype.anchor` method\n// https://tc39.es/ecma262/#sec-string.prototype.anchor\n$({ target: 'String', proto: true, forced: forcedStringHTMLMethod('anchor') }, {\n anchor: function anchor(name) {\n return createHTML(this, 'a', 'name', name);\n }\n});\n","'use strict';\nvar $ = require('../internals/export');\nvar createHTML = require('../internals/create-html');\nvar forcedStringHTMLMethod = require('../internals/string-html-forced');\n\n// `String.prototype.fontsize` method\n// https://tc39.es/ecma262/#sec-string.prototype.fontsize\n$({ target: 'String', proto: true, forced: forcedStringHTMLMethod('fontsize') }, {\n fontsize: function fontsize(size) {\n return createHTML(this, 'font', 'size', size);\n }\n});\n","var defineWellKnownSymbol = require('../internals/define-well-known-symbol');\n\n// `Symbol.species` well-known symbol\n// https://tc39.es/ecma262/#sec-symbol.species\ndefineWellKnownSymbol('species');\n","module.exports = function (it, Constructor, name) {\n if (!(it instanceof Constructor)) {\n throw TypeError('Incorrect ' + (name ? name + ' ' : '') + 'invocation');\n } return it;\n};\n","module.exports = require('./lib/uslug');","var getBuiltIn = require('../internals/get-built-in');\n\nmodule.exports = getBuiltIn('document', 'documentElement');\n","var $ = require('../internals/export');\nvar ownKeys = require('../internals/own-keys');\n\n// `Reflect.ownKeys` method\n// https://tc39.es/ecma262/#sec-reflect.ownkeys\n$({ target: 'Reflect', stat: true }, {\n ownKeys: ownKeys\n});\n","module.exports = function (it) {\n if (typeof it != 'function') {\n throw TypeError(String(it) + ' is not a function');\n } return it;\n};\n","var n={false:\"push\",true:\"unshift\"},e=Object.prototype.hasOwnProperty,t=function(n,t,r,i){var u=n,o=i;if(r&&e.call(t,u))throw Error(\"User defined id attribute '\"+n+\"' is NOT unique. Please fix it in your markdown to continue.\");for(;e.call(t,u);)u=n+\"-\"+o++;return t[u]=!0,u},r=function n(e,r){r=Object.assign({},n.defaults,r),e.core.ruler.push(\"anchor\",function(n){var e,i={},u=n.tokens,o=Array.isArray(r.level)?(e=r.level,function(n){return e.includes(n)}):function(n){return function(e){return e>=n}}(r.level);u.filter(function(n){return\"heading_open\"===n.type}).filter(function(n){return o(Number(n.tag.substr(1)))}).forEach(function(e){var o=u[u.indexOf(e)+1].children.filter(function(n){return\"text\"===n.type||\"code_inline\"===n.type}).reduce(function(n,e){return n+e.content},\"\"),c=e.attrGet(\"id\");c=null==c?t(r.slugify(o),i,!1,r.uniqueSlugStartIndex):t(c,i,!0,r.uniqueSlugStartIndex),e.attrSet(\"id\",c),r.permalink&&r.renderPermalink(c,r,n,u.indexOf(e)),r.callback&&r.callback(e,{slug:c,title:o})})})};r.defaults={level:1,slugify:function(n){return encodeURIComponent(String(n).trim().toLowerCase().replace(/\\s+/g,\"-\"))},uniqueSlugStartIndex:1,permalink:!1,renderPermalink:function(e,t,r,i){var u,o=[Object.assign(new r.Token(\"link_open\",\"a\",1),{attrs:[].concat(t.permalinkClass?[[\"class\",t.permalinkClass]]:[],[[\"href\",t.permalinkHref(e,r)]],Object.entries(t.permalinkAttrs(e,r)))}),Object.assign(new r.Token(\"html_block\",\"\",0),{content:t.permalinkSymbol}),new r.Token(\"link_close\",\"a\",-1)];t.permalinkSpace&&o[n[!t.permalinkBefore]](Object.assign(new r.Token(\"text\",\"\",0),{content:\" \"})),(u=r.tokens[i+1].children)[n[t.permalinkBefore]].apply(u,o)},permalinkClass:\"header-anchor\",permalinkSpace:!0,permalinkSymbol:\"¶\",permalinkBefore:!1,permalinkHref:function(n){return\"#\"+n},permalinkAttrs:function(n){return{}}};export default r;\n//# sourceMappingURL=markdownItAnchor.mjs.map\n","var wellKnownSymbol = require('../internals/well-known-symbol');\n\nvar ITERATOR = wellKnownSymbol('iterator');\nvar SAFE_CLOSING = false;\n\ntry {\n var called = 0;\n var iteratorWithReturn = {\n next: function () {\n return { done: !!called++ };\n },\n 'return': function () {\n SAFE_CLOSING = true;\n }\n };\n iteratorWithReturn[ITERATOR] = function () {\n return this;\n };\n // eslint-disable-next-line es/no-array-from, no-throw-literal -- required for testing\n Array.from(iteratorWithReturn, function () { throw 2; });\n} catch (error) { /* empty */ }\n\nmodule.exports = function (exec, SKIP_CLOSING) {\n if (!SKIP_CLOSING && !SAFE_CLOSING) return false;\n var ITERATION_SUPPORT = false;\n try {\n var object = {};\n object[ITERATOR] = function () {\n return {\n next: function () {\n return { done: ITERATION_SUPPORT = true };\n }\n };\n };\n exec(object);\n } catch (error) { /* empty */ }\n return ITERATION_SUPPORT;\n};\n","var userAgent = require('../internals/engine-user-agent');\n\nmodule.exports = /(?:iphone|ipod|ipad).*applewebkit/i.test(userAgent);\n","var $ = require('../internals/export');\nvar DESCRIPTORS = require('../internals/descriptors');\nvar defineProperties = require('../internals/object-define-properties');\n\n// `Object.defineProperties` method\n// https://tc39.es/ecma262/#sec-object.defineproperties\n$({ target: 'Object', stat: true, forced: !DESCRIPTORS, sham: !DESCRIPTORS }, {\n defineProperties: defineProperties\n});\n","// `RequireObjectCoercible` abstract operation\n// https://tc39.es/ecma262/#sec-requireobjectcoercible\nmodule.exports = function (it) {\n if (it == undefined) throw TypeError(\"Can't call method on \" + it);\n return it;\n};\n","var fails = require('../internals/fails');\nvar wellKnownSymbol = require('../internals/well-known-symbol');\nvar V8_VERSION = require('../internals/engine-v8-version');\n\nvar SPECIES = wellKnownSymbol('species');\n\nmodule.exports = function (METHOD_NAME) {\n // We can't use this feature detection in V8 since it causes\n // deoptimization and serious performance degradation\n // https://github.com/zloirock/core-js/issues/677\n return V8_VERSION >= 51 || !fails(function () {\n var array = [];\n var constructor = array.constructor = {};\n constructor[SPECIES] = function () {\n return { foo: 1 };\n };\n return array[METHOD_NAME](Boolean).foo !== 1;\n });\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar $trimEnd = require('../internals/string-trim').end;\nvar forcedStringTrimMethod = require('../internals/string-trim-forced');\n\nvar FORCED = forcedStringTrimMethod('trimEnd');\n\nvar trimEnd = FORCED ? function trimEnd() {\n return $trimEnd(this);\n// eslint-disable-next-line es/no-string-prototype-trimstart-trimend -- safe\n} : ''.trimEnd;\n\n// `String.prototype.{ trimEnd, trimRight }` methods\n// https://tc39.es/ecma262/#sec-string.prototype.trimend\n// https://tc39.es/ecma262/#String.prototype.trimright\n$({ target: 'String', proto: true, forced: FORCED }, {\n trimEnd: trimEnd,\n trimRight: trimEnd\n});\n","var log = Math.log;\n\n// `Math.log1p` method implementation\n// https://tc39.es/ecma262/#sec-math.log1p\n// eslint-disable-next-line es/no-math-log1p -- safe\nmodule.exports = Math.log1p || function log1p(x) {\n return (x = +x) > -1e-8 && x < 1e-8 ? x - x * x / 2 : log(1 + x);\n};\n","'use strict';\nvar collection = require('../internals/collection');\nvar collectionWeak = require('../internals/collection-weak');\n\n// `WeakSet` constructor\n// https://tc39.es/ecma262/#sec-weakset-constructor\ncollection('WeakSet', function (init) {\n return function WeakSet() { return init(this, arguments.length ? arguments[0] : undefined); };\n}, collectionWeak);\n","'use strict';\nmodule.exports = str => {\n\tconst match = str.match(/^[ \\t]*(?=\\S)/gm);\n\n\tif (!match) {\n\t\treturn str;\n\t}\n\n\t// TODO: use spread operator when targeting Node.js 6\n\tconst indent = Math.min.apply(Math, match.map(x => x.length)); // eslint-disable-line\n\tconst re = new RegExp(`^[ \\\\t]{${indent}}`, 'gm');\n\n\treturn indent > 0 ? str.replace(re, '') : str;\n};\n","'use strict';\nvar TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS = require('../internals/typed-array-constructors-require-wrappers');\nvar exportTypedArrayStaticMethod = require('../internals/array-buffer-view-core').exportTypedArrayStaticMethod;\nvar typedArrayFrom = require('../internals/typed-array-from');\n\n// `%TypedArray%.from` method\n// https://tc39.es/ecma262/#sec-%typedarray%.from\nexportTypedArrayStaticMethod('from', typedArrayFrom, TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS);\n","'use strict';\nvar ArrayBufferViewCore = require('../internals/array-buffer-view-core');\n\nvar aTypedArray = ArrayBufferViewCore.aTypedArray;\nvar exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;\nvar $sort = [].sort;\n\n// `%TypedArray%.prototype.sort` method\n// https://tc39.es/ecma262/#sec-%typedarray%.prototype.sort\nexportTypedArrayMethod('sort', function sort(comparefn) {\n return $sort.call(aTypedArray(this), comparefn);\n});\n","var anObject = require('../internals/an-object');\nvar isArrayIteratorMethod = require('../internals/is-array-iterator-method');\nvar toLength = require('../internals/to-length');\nvar bind = require('../internals/function-bind-context');\nvar getIteratorMethod = require('../internals/get-iterator-method');\nvar iteratorClose = require('../internals/iterator-close');\n\nvar Result = function (stopped, result) {\n this.stopped = stopped;\n this.result = result;\n};\n\nmodule.exports = function (iterable, unboundFunction, options) {\n var that = options && options.that;\n var AS_ENTRIES = !!(options && options.AS_ENTRIES);\n var IS_ITERATOR = !!(options && options.IS_ITERATOR);\n var INTERRUPTED = !!(options && options.INTERRUPTED);\n var fn = bind(unboundFunction, that, 1 + AS_ENTRIES + INTERRUPTED);\n var iterator, iterFn, index, length, result, next, step;\n\n var stop = function (condition) {\n if (iterator) iteratorClose(iterator);\n return new Result(true, condition);\n };\n\n var callFn = function (value) {\n if (AS_ENTRIES) {\n anObject(value);\n return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]);\n } return INTERRUPTED ? fn(value, stop) : fn(value);\n };\n\n if (IS_ITERATOR) {\n iterator = iterable;\n } else {\n iterFn = getIteratorMethod(iterable);\n if (typeof iterFn != 'function') throw TypeError('Target is not iterable');\n // optimisation for array iterators\n if (isArrayIteratorMethod(iterFn)) {\n for (index = 0, length = toLength(iterable.length); length > index; index++) {\n result = callFn(iterable[index]);\n if (result && result instanceof Result) return result;\n } return new Result(false);\n }\n iterator = iterFn.call(iterable);\n }\n\n next = iterator.next;\n while (!(step = next.call(iterator)).done) {\n try {\n result = callFn(step.value);\n } catch (error) {\n iteratorClose(iterator);\n throw error;\n }\n if (typeof result == 'object' && result && result instanceof Result) return result;\n } return new Result(false);\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar createHTML = require('../internals/create-html');\nvar forcedStringHTMLMethod = require('../internals/string-html-forced');\n\n// `String.prototype.strike` method\n// https://tc39.es/ecma262/#sec-string.prototype.strike\n$({ target: 'String', proto: true, forced: forcedStringHTMLMethod('strike') }, {\n strike: function strike() {\n return createHTML(this, 'strike', '', '');\n }\n});\n","var defineWellKnownSymbol = require('../internals/define-well-known-symbol');\n\n// `Symbol.split` well-known symbol\n// https://tc39.es/ecma262/#sec-symbol.split\ndefineWellKnownSymbol('split');\n","var toInteger = require('../internals/to-integer');\n\nvar max = Math.max;\nvar min = Math.min;\n\n// Helper for a popular repeating case of the spec:\n// Let integer be ? ToInteger(index).\n// If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).\nmodule.exports = function (index, length) {\n var integer = toInteger(index);\n return integer < 0 ? max(integer + length, 0) : min(integer, length);\n};\n","var setToStringTag = require('../internals/set-to-string-tag');\n\n// Math[@@toStringTag] property\n// https://tc39.es/ecma262/#sec-math-@@tostringtag\nsetToStringTag(Math, 'Math', true);\n","var global = require('../internals/global');\nvar getOwnPropertyDescriptor = require('../internals/object-get-own-property-descriptor').f;\nvar createNonEnumerableProperty = require('../internals/create-non-enumerable-property');\nvar redefine = require('../internals/redefine');\nvar setGlobal = require('../internals/set-global');\nvar copyConstructorProperties = require('../internals/copy-constructor-properties');\nvar isForced = require('../internals/is-forced');\n\n/*\n options.target - name of the target object\n options.global - target is the global object\n options.stat - export as static methods of target\n options.proto - export as prototype methods of target\n options.real - real prototype method for the `pure` version\n options.forced - export even if the native feature is available\n options.bind - bind methods to the target, required for the `pure` version\n options.wrap - wrap constructors to preventing global pollution, required for the `pure` version\n options.unsafe - use the simple assignment of property instead of delete + defineProperty\n options.sham - add a flag to not completely full polyfills\n options.enumerable - export as enumerable property\n options.noTargetGet - prevent calling a getter on target\n*/\nmodule.exports = function (options, source) {\n var TARGET = options.target;\n var GLOBAL = options.global;\n var STATIC = options.stat;\n var FORCED, target, key, targetProperty, sourceProperty, descriptor;\n if (GLOBAL) {\n target = global;\n } else if (STATIC) {\n target = global[TARGET] || setGlobal(TARGET, {});\n } else {\n target = (global[TARGET] || {}).prototype;\n }\n if (target) for (key in source) {\n sourceProperty = source[key];\n if (options.noTargetGet) {\n descriptor = getOwnPropertyDescriptor(target, key);\n targetProperty = descriptor && descriptor.value;\n } else targetProperty = target[key];\n FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);\n // contained in target\n if (!FORCED && targetProperty !== undefined) {\n if (typeof sourceProperty === typeof targetProperty) continue;\n copyConstructorProperties(sourceProperty, targetProperty);\n }\n // add a flag to not completely full polyfills\n if (options.sham || (targetProperty && targetProperty.sham)) {\n createNonEnumerableProperty(sourceProperty, 'sham', true);\n }\n // extend global\n redefine(target, key, sourceProperty, options);\n }\n};\n","var internalObjectKeys = require('../internals/object-keys-internal');\nvar enumBugKeys = require('../internals/enum-bug-keys');\n\nvar hiddenKeys = enumBugKeys.concat('length', 'prototype');\n\n// `Object.getOwnPropertyNames` method\n// https://tc39.es/ecma262/#sec-object.getownpropertynames\n// eslint-disable-next-line es/no-object-getownpropertynames -- safe\nexports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {\n return internalObjectKeys(O, hiddenKeys);\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar notARegExp = require('../internals/not-a-regexp');\nvar requireObjectCoercible = require('../internals/require-object-coercible');\nvar correctIsRegExpLogic = require('../internals/correct-is-regexp-logic');\n\n// `String.prototype.includes` method\n// https://tc39.es/ecma262/#sec-string.prototype.includes\n$({ target: 'String', proto: true, forced: !correctIsRegExpLogic('includes') }, {\n includes: function includes(searchString /* , position = 0 */) {\n return !!~String(requireObjectCoercible(this))\n .indexOf(notARegExp(searchString), arguments.length > 1 ? arguments[1] : undefined);\n }\n});\n","'use strict';\nvar ArrayBufferViewCore = require('../internals/array-buffer-view-core');\nvar $reduceRight = require('../internals/array-reduce').right;\n\nvar aTypedArray = ArrayBufferViewCore.aTypedArray;\nvar exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;\n\n// `%TypedArray%.prototype.reduceRicht` method\n// https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduceright\nexportTypedArrayMethod('reduceRight', function reduceRight(callbackfn /* , initialValue */) {\n return $reduceRight(aTypedArray(this), callbackfn, arguments.length, arguments.length > 1 ? arguments[1] : undefined);\n});\n","var $ = require('../internals/export');\nvar parseInt = require('../internals/number-parse-int');\n\n// `Number.parseInt` method\n// https://tc39.es/ecma262/#sec-number.parseint\n// eslint-disable-next-line es/no-number-parseint -- required for testing\n$({ target: 'Number', stat: true, forced: Number.parseInt != parseInt }, {\n parseInt: parseInt\n});\n","'use strict';\nvar redefine = require('../internals/redefine');\nvar anObject = require('../internals/an-object');\nvar fails = require('../internals/fails');\nvar flags = require('../internals/regexp-flags');\n\nvar TO_STRING = 'toString';\nvar RegExpPrototype = RegExp.prototype;\nvar nativeToString = RegExpPrototype[TO_STRING];\n\nvar NOT_GENERIC = fails(function () { return nativeToString.call({ source: 'a', flags: 'b' }) != '/a/b'; });\n// FF44- RegExp#toString has a wrong name\nvar INCORRECT_NAME = nativeToString.name != TO_STRING;\n\n// `RegExp.prototype.toString` method\n// https://tc39.es/ecma262/#sec-regexp.prototype.tostring\nif (NOT_GENERIC || INCORRECT_NAME) {\n redefine(RegExp.prototype, TO_STRING, function toString() {\n var R = anObject(this);\n var p = String(R.source);\n var rf = R.flags;\n var f = String(rf === undefined && R instanceof RegExp && !('flags' in RegExpPrototype) ? flags.call(R) : rf);\n return '/' + p + '/' + f;\n }, { unsafe: true });\n}\n","'use strict';\nvar getBuiltIn = require('../internals/get-built-in');\nvar definePropertyModule = require('../internals/object-define-property');\nvar wellKnownSymbol = require('../internals/well-known-symbol');\nvar DESCRIPTORS = require('../internals/descriptors');\n\nvar SPECIES = wellKnownSymbol('species');\n\nmodule.exports = function (CONSTRUCTOR_NAME) {\n var Constructor = getBuiltIn(CONSTRUCTOR_NAME);\n var defineProperty = definePropertyModule.f;\n\n if (DESCRIPTORS && Constructor && !Constructor[SPECIES]) {\n defineProperty(Constructor, SPECIES, {\n configurable: true,\n get: function () { return this; }\n });\n }\n};\n","'use strict';\nvar $ = require('../internals/export');\nvar isArray = require('../internals/is-array');\n\nvar nativeReverse = [].reverse;\nvar test = [1, 2];\n\n// `Array.prototype.reverse` method\n// https://tc39.es/ecma262/#sec-array.prototype.reverse\n// fix for Safari 12.0 bug\n// https://bugs.webkit.org/show_bug.cgi?id=188794\n$({ target: 'Array', proto: true, forced: String(test) === String(test.reverse()) }, {\n reverse: function reverse() {\n // eslint-disable-next-line no-self-assign -- dirty hack\n if (isArray(this)) this.length = this.length;\n return nativeReverse.call(this);\n }\n});\n","var $ = require('../internals/export');\nvar isArray = require('../internals/is-array');\n\n// `Array.isArray` method\n// https://tc39.es/ecma262/#sec-array.isarray\n$({ target: 'Array', stat: true }, {\n isArray: isArray\n});\n","/* globals __VUE_SSR_CONTEXT__ */\n\n// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).\n// This module is a runtime utility for cleaner component module output and will\n// be included in the final webpack user bundle.\n\nexport default function normalizeComponent (\n scriptExports,\n render,\n staticRenderFns,\n functionalTemplate,\n injectStyles,\n scopeId,\n moduleIdentifier, /* server only */\n shadowMode /* vue-cli only */\n) {\n // Vue.extend constructor export interop\n var options = typeof scriptExports === 'function'\n ? scriptExports.options\n : scriptExports\n\n // render functions\n if (render) {\n options.render = render\n options.staticRenderFns = staticRenderFns\n options._compiled = true\n }\n\n // functional template\n if (functionalTemplate) {\n options.functional = true\n }\n\n // scopedId\n if (scopeId) {\n options._scopeId = 'data-v-' + scopeId\n }\n\n var hook\n if (moduleIdentifier) { // server build\n hook = function (context) {\n // 2.3 injection\n context =\n context || // cached call\n (this.$vnode && this.$vnode.ssrContext) || // stateful\n (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional\n // 2.2 with runInNewContext: true\n if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {\n context = __VUE_SSR_CONTEXT__\n }\n // inject component styles\n if (injectStyles) {\n injectStyles.call(this, context)\n }\n // register component module identifier for async chunk inferrence\n if (context && context._registeredComponents) {\n context._registeredComponents.add(moduleIdentifier)\n }\n }\n // used by ssr in case component is cached and beforeCreate\n // never gets called\n options._ssrRegister = hook\n } else if (injectStyles) {\n hook = shadowMode\n ? function () {\n injectStyles.call(\n this,\n (options.functional ? this.parent : this).$root.$options.shadowRoot\n )\n }\n : injectStyles\n }\n\n if (hook) {\n if (options.functional) {\n // for template-only hot-reload because in that case the render fn doesn't\n // go through the normalizer\n options._injectStyles = hook\n // register for functional component in vue file\n var originalRender = options.render\n options.render = function renderWithStyleInjection (h, context) {\n hook.call(context)\n return originalRender(h, context)\n }\n } else {\n // inject component registration as beforeCreate hook\n var existing = options.beforeCreate\n options.beforeCreate = existing\n ? [].concat(existing, hook)\n : [hook]\n }\n }\n\n return {\n exports: scriptExports,\n options: options\n }\n}\n","export default function _arrayLikeToArray(arr, len) {\n if (len == null || len > arr.length) len = arr.length;\n\n for (var i = 0, arr2 = new Array(len); i < len; i++) {\n arr2[i] = arr[i];\n }\n\n return arr2;\n}","import arrayLikeToArray from \"./arrayLikeToArray.js\";\nexport default function _arrayWithoutHoles(arr) {\n if (Array.isArray(arr)) return arrayLikeToArray(arr);\n}","export default function _iterableToArray(iter) {\n if (typeof Symbol !== \"undefined\" && iter[Symbol.iterator] != null || iter[\"@@iterator\"] != null) return Array.from(iter);\n}","import arrayLikeToArray from \"./arrayLikeToArray.js\";\nexport default function _unsupportedIterableToArray(o, minLen) {\n if (!o) return;\n if (typeof o === \"string\") return arrayLikeToArray(o, minLen);\n var n = Object.prototype.toString.call(o).slice(8, -1);\n if (n === \"Object\" && o.constructor) n = o.constructor.name;\n if (n === \"Map\" || n === \"Set\") return Array.from(o);\n if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return arrayLikeToArray(o, minLen);\n}","export default function _nonIterableSpread() {\n throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}","import arrayWithoutHoles from \"./arrayWithoutHoles.js\";\nimport iterableToArray from \"./iterableToArray.js\";\nimport unsupportedIterableToArray from \"./unsupportedIterableToArray.js\";\nimport nonIterableSpread from \"./nonIterableSpread.js\";\nexport default function _toConsumableArray(arr) {\n return arrayWithoutHoles(arr) || iterableToArray(arr) || unsupportedIterableToArray(arr) || nonIterableSpread();\n}","'use strict';\nvar ArrayBufferViewCore = require('../internals/array-buffer-view-core');\nvar speciesConstructor = require('../internals/species-constructor');\nvar fails = require('../internals/fails');\n\nvar aTypedArray = ArrayBufferViewCore.aTypedArray;\nvar aTypedArrayConstructor = ArrayBufferViewCore.aTypedArrayConstructor;\nvar exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;\nvar $slice = [].slice;\n\nvar FORCED = fails(function () {\n // eslint-disable-next-line es/no-typed-arrays -- required for testing\n new Int8Array(1).slice();\n});\n\n// `%TypedArray%.prototype.slice` method\n// https://tc39.es/ecma262/#sec-%typedarray%.prototype.slice\nexportTypedArrayMethod('slice', function slice(start, end) {\n var list = $slice.call(aTypedArray(this), start, end);\n var C = speciesConstructor(this, this.constructor);\n var index = 0;\n var length = list.length;\n var result = new (aTypedArrayConstructor(C))(length);\n while (length > index) result[index] = list[index++];\n return result;\n}, FORCED);\n","var defineWellKnownSymbol = require('../internals/define-well-known-symbol');\n\n// `Symbol.match` well-known symbol\n// https://tc39.es/ecma262/#sec-symbol.match\ndefineWellKnownSymbol('match');\n","var anObject = require('../internals/an-object');\n\nmodule.exports = function (iterator) {\n var returnMethod = iterator['return'];\n if (returnMethod !== undefined) {\n return anObject(returnMethod.call(iterator)).value;\n }\n};\n","var $ = require('../internals/export');\nvar sign = require('../internals/math-sign');\n\n// `Math.sign` method\n// https://tc39.es/ecma262/#sec-math.sign\n$({ target: 'Math', stat: true }, {\n sign: sign\n});\n","/*!\n * Vue.js v2.6.12\n * (c) 2014-2020 Evan You\n * Released under the MIT License.\n */\n/* */\n\nvar emptyObject = Object.freeze({});\n\n// These helpers produce better VM code in JS engines due to their\n// explicitness and function inlining.\nfunction isUndef (v) {\n return v === undefined || v === null\n}\n\nfunction isDef (v) {\n return v !== undefined && v !== null\n}\n\nfunction isTrue (v) {\n return v === true\n}\n\nfunction isFalse (v) {\n return v === false\n}\n\n/**\n * Check if value is primitive.\n */\nfunction isPrimitive (value) {\n return (\n typeof value === 'string' ||\n typeof value === 'number' ||\n // $flow-disable-line\n typeof value === 'symbol' ||\n typeof value === 'boolean'\n )\n}\n\n/**\n * Quick object check - this is primarily used to tell\n * Objects from primitive values when we know the value\n * is a JSON-compliant type.\n */\nfunction isObject (obj) {\n return obj !== null && typeof obj === 'object'\n}\n\n/**\n * Get the raw type string of a value, e.g., [object Object].\n */\nvar _toString = Object.prototype.toString;\n\nfunction toRawType (value) {\n return _toString.call(value).slice(8, -1)\n}\n\n/**\n * Strict object type check. Only returns true\n * for plain JavaScript objects.\n */\nfunction isPlainObject (obj) {\n return _toString.call(obj) === '[object Object]'\n}\n\nfunction isRegExp (v) {\n return _toString.call(v) === '[object RegExp]'\n}\n\n/**\n * Check if val is a valid array index.\n */\nfunction isValidArrayIndex (val) {\n var n = parseFloat(String(val));\n return n >= 0 && Math.floor(n) === n && isFinite(val)\n}\n\nfunction isPromise (val) {\n return (\n isDef(val) &&\n typeof val.then === 'function' &&\n typeof val.catch === 'function'\n )\n}\n\n/**\n * Convert a value to a string that is actually rendered.\n */\nfunction toString (val) {\n return val == null\n ? ''\n : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)\n ? JSON.stringify(val, null, 2)\n : String(val)\n}\n\n/**\n * Convert an input value to a number for persistence.\n * If the conversion fails, return original string.\n */\nfunction toNumber (val) {\n var n = parseFloat(val);\n return isNaN(n) ? val : n\n}\n\n/**\n * Make a map and return a function for checking if a key\n * is in that map.\n */\nfunction makeMap (\n str,\n expectsLowerCase\n) {\n var map = Object.create(null);\n var list = str.split(',');\n for (var i = 0; i < list.length; i++) {\n map[list[i]] = true;\n }\n return expectsLowerCase\n ? function (val) { return map[val.toLowerCase()]; }\n : function (val) { return map[val]; }\n}\n\n/**\n * Check if a tag is a built-in tag.\n */\nvar isBuiltInTag = makeMap('slot,component', true);\n\n/**\n * Check if an attribute is a reserved attribute.\n */\nvar isReservedAttribute = makeMap('key,ref,slot,slot-scope,is');\n\n/**\n * Remove an item from an array.\n */\nfunction remove (arr, item) {\n if (arr.length) {\n var index = arr.indexOf(item);\n if (index > -1) {\n return arr.splice(index, 1)\n }\n }\n}\n\n/**\n * Check whether an object has the property.\n */\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nfunction hasOwn (obj, key) {\n return hasOwnProperty.call(obj, key)\n}\n\n/**\n * Create a cached version of a pure function.\n */\nfunction cached (fn) {\n var cache = Object.create(null);\n return (function cachedFn (str) {\n var hit = cache[str];\n return hit || (cache[str] = fn(str))\n })\n}\n\n/**\n * Camelize a hyphen-delimited string.\n */\nvar camelizeRE = /-(\\w)/g;\nvar camelize = cached(function (str) {\n return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; })\n});\n\n/**\n * Capitalize a string.\n */\nvar capitalize = cached(function (str) {\n return str.charAt(0).toUpperCase() + str.slice(1)\n});\n\n/**\n * Hyphenate a camelCase string.\n */\nvar hyphenateRE = /\\B([A-Z])/g;\nvar hyphenate = cached(function (str) {\n return str.replace(hyphenateRE, '-$1').toLowerCase()\n});\n\n/**\n * Simple bind polyfill for environments that do not support it,\n * e.g., PhantomJS 1.x. Technically, we don't need this anymore\n * since native bind is now performant enough in most browsers.\n * But removing it would mean breaking code that was able to run in\n * PhantomJS 1.x, so this must be kept for backward compatibility.\n */\n\n/* istanbul ignore next */\nfunction polyfillBind (fn, ctx) {\n function boundFn (a) {\n var l = arguments.length;\n return l\n ? l > 1\n ? fn.apply(ctx, arguments)\n : fn.call(ctx, a)\n : fn.call(ctx)\n }\n\n boundFn._length = fn.length;\n return boundFn\n}\n\nfunction nativeBind (fn, ctx) {\n return fn.bind(ctx)\n}\n\nvar bind = Function.prototype.bind\n ? nativeBind\n : polyfillBind;\n\n/**\n * Convert an Array-like object to a real Array.\n */\nfunction toArray (list, start) {\n start = start || 0;\n var i = list.length - start;\n var ret = new Array(i);\n while (i--) {\n ret[i] = list[i + start];\n }\n return ret\n}\n\n/**\n * Mix properties into target object.\n */\nfunction extend (to, _from) {\n for (var key in _from) {\n to[key] = _from[key];\n }\n return to\n}\n\n/**\n * Merge an Array of Objects into a single Object.\n */\nfunction toObject (arr) {\n var res = {};\n for (var i = 0; i < arr.length; i++) {\n if (arr[i]) {\n extend(res, arr[i]);\n }\n }\n return res\n}\n\n/* eslint-disable no-unused-vars */\n\n/**\n * Perform no operation.\n * Stubbing args to make Flow happy without leaving useless transpiled code\n * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/).\n */\nfunction noop (a, b, c) {}\n\n/**\n * Always return false.\n */\nvar no = function (a, b, c) { return false; };\n\n/* eslint-enable no-unused-vars */\n\n/**\n * Return the same value.\n */\nvar identity = function (_) { return _; };\n\n/**\n * Check if two values are loosely equal - that is,\n * if they are plain objects, do they have the same shape?\n */\nfunction looseEqual (a, b) {\n if (a === b) { return true }\n var isObjectA = isObject(a);\n var isObjectB = isObject(b);\n if (isObjectA && isObjectB) {\n try {\n var isArrayA = Array.isArray(a);\n var isArrayB = Array.isArray(b);\n if (isArrayA && isArrayB) {\n return a.length === b.length && a.every(function (e, i) {\n return looseEqual(e, b[i])\n })\n } else if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime()\n } else if (!isArrayA && !isArrayB) {\n var keysA = Object.keys(a);\n var keysB = Object.keys(b);\n return keysA.length === keysB.length && keysA.every(function (key) {\n return looseEqual(a[key], b[key])\n })\n } else {\n /* istanbul ignore next */\n return false\n }\n } catch (e) {\n /* istanbul ignore next */\n return false\n }\n } else if (!isObjectA && !isObjectB) {\n return String(a) === String(b)\n } else {\n return false\n }\n}\n\n/**\n * Return the first index at which a loosely equal value can be\n * found in the array (if value is a plain object, the array must\n * contain an object of the same shape), or -1 if it is not present.\n */\nfunction looseIndexOf (arr, val) {\n for (var i = 0; i < arr.length; i++) {\n if (looseEqual(arr[i], val)) { return i }\n }\n return -1\n}\n\n/**\n * Ensure a function is called only once.\n */\nfunction once (fn) {\n var called = false;\n return function () {\n if (!called) {\n called = true;\n fn.apply(this, arguments);\n }\n }\n}\n\nvar SSR_ATTR = 'data-server-rendered';\n\nvar ASSET_TYPES = [\n 'component',\n 'directive',\n 'filter'\n];\n\nvar LIFECYCLE_HOOKS = [\n 'beforeCreate',\n 'created',\n 'beforeMount',\n 'mounted',\n 'beforeUpdate',\n 'updated',\n 'beforeDestroy',\n 'destroyed',\n 'activated',\n 'deactivated',\n 'errorCaptured',\n 'serverPrefetch'\n];\n\n/* */\n\n\n\nvar config = ({\n /**\n * Option merge strategies (used in core/util/options)\n */\n // $flow-disable-line\n optionMergeStrategies: Object.create(null),\n\n /**\n * Whether to suppress warnings.\n */\n silent: false,\n\n /**\n * Show production mode tip message on boot?\n */\n productionTip: process.env.NODE_ENV !== 'production',\n\n /**\n * Whether to enable devtools\n */\n devtools: process.env.NODE_ENV !== 'production',\n\n /**\n * Whether to record perf\n */\n performance: false,\n\n /**\n * Error handler for watcher errors\n */\n errorHandler: null,\n\n /**\n * Warn handler for watcher warns\n */\n warnHandler: null,\n\n /**\n * Ignore certain custom elements\n */\n ignoredElements: [],\n\n /**\n * Custom user key aliases for v-on\n */\n // $flow-disable-line\n keyCodes: Object.create(null),\n\n /**\n * Check if a tag is reserved so that it cannot be registered as a\n * component. This is platform-dependent and may be overwritten.\n */\n isReservedTag: no,\n\n /**\n * Check if an attribute is reserved so that it cannot be used as a component\n * prop. This is platform-dependent and may be overwritten.\n */\n isReservedAttr: no,\n\n /**\n * Check if a tag is an unknown element.\n * Platform-dependent.\n */\n isUnknownElement: no,\n\n /**\n * Get the namespace of an element\n */\n getTagNamespace: noop,\n\n /**\n * Parse the real tag name for the specific platform.\n */\n parsePlatformTagName: identity,\n\n /**\n * Check if an attribute must be bound using property, e.g. value\n * Platform-dependent.\n */\n mustUseProp: no,\n\n /**\n * Perform updates asynchronously. Intended to be used by Vue Test Utils\n * This will significantly reduce performance if set to false.\n */\n async: true,\n\n /**\n * Exposed for legacy reasons\n */\n _lifecycleHooks: LIFECYCLE_HOOKS\n});\n\n/* */\n\n/**\n * unicode letters used for parsing html tags, component names and property paths.\n * using https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname\n * skipping \\u10000-\\uEFFFF due to it freezing up PhantomJS\n */\nvar unicodeRegExp = /a-zA-Z\\u00B7\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u203F-\\u2040\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD/;\n\n/**\n * Check if a string starts with $ or _\n */\nfunction isReserved (str) {\n var c = (str + '').charCodeAt(0);\n return c === 0x24 || c === 0x5F\n}\n\n/**\n * Define a property.\n */\nfunction def (obj, key, val, enumerable) {\n Object.defineProperty(obj, key, {\n value: val,\n enumerable: !!enumerable,\n writable: true,\n configurable: true\n });\n}\n\n/**\n * Parse simple path.\n */\nvar bailRE = new RegExp((\"[^\" + (unicodeRegExp.source) + \".$_\\\\d]\"));\nfunction parsePath (path) {\n if (bailRE.test(path)) {\n return\n }\n var segments = path.split('.');\n return function (obj) {\n for (var i = 0; i < segments.length; i++) {\n if (!obj) { return }\n obj = obj[segments[i]];\n }\n return obj\n }\n}\n\n/* */\n\n// can we use __proto__?\nvar hasProto = '__proto__' in {};\n\n// Browser environment sniffing\nvar inBrowser = typeof window !== 'undefined';\nvar inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform;\nvar weexPlatform = inWeex && WXEnvironment.platform.toLowerCase();\nvar UA = inBrowser && window.navigator.userAgent.toLowerCase();\nvar isIE = UA && /msie|trident/.test(UA);\nvar isIE9 = UA && UA.indexOf('msie 9.0') > 0;\nvar isEdge = UA && UA.indexOf('edge/') > 0;\nvar isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android');\nvar isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios');\nvar isChrome = UA && /chrome\\/\\d+/.test(UA) && !isEdge;\nvar isPhantomJS = UA && /phantomjs/.test(UA);\nvar isFF = UA && UA.match(/firefox\\/(\\d+)/);\n\n// Firefox has a \"watch\" function on Object.prototype...\nvar nativeWatch = ({}).watch;\n\nvar supportsPassive = false;\nif (inBrowser) {\n try {\n var opts = {};\n Object.defineProperty(opts, 'passive', ({\n get: function get () {\n /* istanbul ignore next */\n supportsPassive = true;\n }\n })); // https://github.com/facebook/flow/issues/285\n window.addEventListener('test-passive', null, opts);\n } catch (e) {}\n}\n\n// this needs to be lazy-evaled because vue may be required before\n// vue-server-renderer can set VUE_ENV\nvar _isServer;\nvar isServerRendering = function () {\n if (_isServer === undefined) {\n /* istanbul ignore if */\n if (!inBrowser && !inWeex && typeof global !== 'undefined') {\n // detect presence of vue-server-renderer and avoid\n // Webpack shimming the process\n _isServer = global['process'] && global['process'].env.VUE_ENV === 'server';\n } else {\n _isServer = false;\n }\n }\n return _isServer\n};\n\n// detect devtools\nvar devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__;\n\n/* istanbul ignore next */\nfunction isNative (Ctor) {\n return typeof Ctor === 'function' && /native code/.test(Ctor.toString())\n}\n\nvar hasSymbol =\n typeof Symbol !== 'undefined' && isNative(Symbol) &&\n typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys);\n\nvar _Set;\n/* istanbul ignore if */ // $flow-disable-line\nif (typeof Set !== 'undefined' && isNative(Set)) {\n // use native Set when available.\n _Set = Set;\n} else {\n // a non-standard Set polyfill that only works with primitive keys.\n _Set = /*@__PURE__*/(function () {\n function Set () {\n this.set = Object.create(null);\n }\n Set.prototype.has = function has (key) {\n return this.set[key] === true\n };\n Set.prototype.add = function add (key) {\n this.set[key] = true;\n };\n Set.prototype.clear = function clear () {\n this.set = Object.create(null);\n };\n\n return Set;\n }());\n}\n\n/* */\n\nvar warn = noop;\nvar tip = noop;\nvar generateComponentTrace = (noop); // work around flow check\nvar formatComponentName = (noop);\n\nif (process.env.NODE_ENV !== 'production') {\n var hasConsole = typeof console !== 'undefined';\n var classifyRE = /(?:^|[-_])(\\w)/g;\n var classify = function (str) { return str\n .replace(classifyRE, function (c) { return c.toUpperCase(); })\n .replace(/[-_]/g, ''); };\n\n warn = function (msg, vm) {\n var trace = vm ? generateComponentTrace(vm) : '';\n\n if (config.warnHandler) {\n config.warnHandler.call(null, msg, vm, trace);\n } else if (hasConsole && (!config.silent)) {\n console.error((\"[Vue warn]: \" + msg + trace));\n }\n };\n\n tip = function (msg, vm) {\n if (hasConsole && (!config.silent)) {\n console.warn(\"[Vue tip]: \" + msg + (\n vm ? generateComponentTrace(vm) : ''\n ));\n }\n };\n\n formatComponentName = function (vm, includeFile) {\n if (vm.$root === vm) {\n return ''\n }\n var options = typeof vm === 'function' && vm.cid != null\n ? vm.options\n : vm._isVue\n ? vm.$options || vm.constructor.options\n : vm;\n var name = options.name || options._componentTag;\n var file = options.__file;\n if (!name && file) {\n var match = file.match(/([^/\\\\]+)\\.vue$/);\n name = match && match[1];\n }\n\n return (\n (name ? (\"<\" + (classify(name)) + \">\") : \"\") +\n (file && includeFile !== false ? (\" at \" + file) : '')\n )\n };\n\n var repeat = function (str, n) {\n var res = '';\n while (n) {\n if (n % 2 === 1) { res += str; }\n if (n > 1) { str += str; }\n n >>= 1;\n }\n return res\n };\n\n generateComponentTrace = function (vm) {\n if (vm._isVue && vm.$parent) {\n var tree = [];\n var currentRecursiveSequence = 0;\n while (vm) {\n if (tree.length > 0) {\n var last = tree[tree.length - 1];\n if (last.constructor === vm.constructor) {\n currentRecursiveSequence++;\n vm = vm.$parent;\n continue\n } else if (currentRecursiveSequence > 0) {\n tree[tree.length - 1] = [last, currentRecursiveSequence];\n currentRecursiveSequence = 0;\n }\n }\n tree.push(vm);\n vm = vm.$parent;\n }\n return '\\n\\nfound in\\n\\n' + tree\n .map(function (vm, i) { return (\"\" + (i === 0 ? '---> ' : repeat(' ', 5 + i * 2)) + (Array.isArray(vm)\n ? ((formatComponentName(vm[0])) + \"... (\" + (vm[1]) + \" recursive calls)\")\n : formatComponentName(vm))); })\n .join('\\n')\n } else {\n return (\"\\n\\n(found in \" + (formatComponentName(vm)) + \")\")\n }\n };\n}\n\n/* */\n\nvar uid = 0;\n\n/**\n * A dep is an observable that can have multiple\n * directives subscribing to it.\n */\nvar Dep = function Dep () {\n this.id = uid++;\n this.subs = [];\n};\n\nDep.prototype.addSub = function addSub (sub) {\n this.subs.push(sub);\n};\n\nDep.prototype.removeSub = function removeSub (sub) {\n remove(this.subs, sub);\n};\n\nDep.prototype.depend = function depend () {\n if (Dep.target) {\n Dep.target.addDep(this);\n }\n};\n\nDep.prototype.notify = function notify () {\n // stabilize the subscriber list first\n var subs = this.subs.slice();\n if (process.env.NODE_ENV !== 'production' && !config.async) {\n // subs aren't sorted in scheduler if not running async\n // we need to sort them now to make sure they fire in correct\n // order\n subs.sort(function (a, b) { return a.id - b.id; });\n }\n for (var i = 0, l = subs.length; i < l; i++) {\n subs[i].update();\n }\n};\n\n// The current target watcher being evaluated.\n// This is globally unique because only one watcher\n// can be evaluated at a time.\nDep.target = null;\nvar targetStack = [];\n\nfunction pushTarget (target) {\n targetStack.push(target);\n Dep.target = target;\n}\n\nfunction popTarget () {\n targetStack.pop();\n Dep.target = targetStack[targetStack.length - 1];\n}\n\n/* */\n\nvar VNode = function VNode (\n tag,\n data,\n children,\n text,\n elm,\n context,\n componentOptions,\n asyncFactory\n) {\n this.tag = tag;\n this.data = data;\n this.children = children;\n this.text = text;\n this.elm = elm;\n this.ns = undefined;\n this.context = context;\n this.fnContext = undefined;\n this.fnOptions = undefined;\n this.fnScopeId = undefined;\n this.key = data && data.key;\n this.componentOptions = componentOptions;\n this.componentInstance = undefined;\n this.parent = undefined;\n this.raw = false;\n this.isStatic = false;\n this.isRootInsert = true;\n this.isComment = false;\n this.isCloned = false;\n this.isOnce = false;\n this.asyncFactory = asyncFactory;\n this.asyncMeta = undefined;\n this.isAsyncPlaceholder = false;\n};\n\nvar prototypeAccessors = { child: { configurable: true } };\n\n// DEPRECATED: alias for componentInstance for backwards compat.\n/* istanbul ignore next */\nprototypeAccessors.child.get = function () {\n return this.componentInstance\n};\n\nObject.defineProperties( VNode.prototype, prototypeAccessors );\n\nvar createEmptyVNode = function (text) {\n if ( text === void 0 ) text = '';\n\n var node = new VNode();\n node.text = text;\n node.isComment = true;\n return node\n};\n\nfunction createTextVNode (val) {\n return new VNode(undefined, undefined, undefined, String(val))\n}\n\n// optimized shallow clone\n// used for static nodes and slot nodes because they may be reused across\n// multiple renders, cloning them avoids errors when DOM manipulations rely\n// on their elm reference.\nfunction cloneVNode (vnode) {\n var cloned = new VNode(\n vnode.tag,\n vnode.data,\n // #7975\n // clone children array to avoid mutating original in case of cloning\n // a child.\n vnode.children && vnode.children.slice(),\n vnode.text,\n vnode.elm,\n vnode.context,\n vnode.componentOptions,\n vnode.asyncFactory\n );\n cloned.ns = vnode.ns;\n cloned.isStatic = vnode.isStatic;\n cloned.key = vnode.key;\n cloned.isComment = vnode.isComment;\n cloned.fnContext = vnode.fnContext;\n cloned.fnOptions = vnode.fnOptions;\n cloned.fnScopeId = vnode.fnScopeId;\n cloned.asyncMeta = vnode.asyncMeta;\n cloned.isCloned = true;\n return cloned\n}\n\n/*\n * not type checking this file because flow doesn't play well with\n * dynamically accessing methods on Array prototype\n */\n\nvar arrayProto = Array.prototype;\nvar arrayMethods = Object.create(arrayProto);\n\nvar methodsToPatch = [\n 'push',\n 'pop',\n 'shift',\n 'unshift',\n 'splice',\n 'sort',\n 'reverse'\n];\n\n/**\n * Intercept mutating methods and emit events\n */\nmethodsToPatch.forEach(function (method) {\n // cache original method\n var original = arrayProto[method];\n def(arrayMethods, method, function mutator () {\n var args = [], len = arguments.length;\n while ( len-- ) args[ len ] = arguments[ len ];\n\n var result = original.apply(this, args);\n var ob = this.__ob__;\n var inserted;\n switch (method) {\n case 'push':\n case 'unshift':\n inserted = args;\n break\n case 'splice':\n inserted = args.slice(2);\n break\n }\n if (inserted) { ob.observeArray(inserted); }\n // notify change\n ob.dep.notify();\n return result\n });\n});\n\n/* */\n\nvar arrayKeys = Object.getOwnPropertyNames(arrayMethods);\n\n/**\n * In some cases we may want to disable observation inside a component's\n * update computation.\n */\nvar shouldObserve = true;\n\nfunction toggleObserving (value) {\n shouldObserve = value;\n}\n\n/**\n * Observer class that is attached to each observed\n * object. Once attached, the observer converts the target\n * object's property keys into getter/setters that\n * collect dependencies and dispatch updates.\n */\nvar Observer = function Observer (value) {\n this.value = value;\n this.dep = new Dep();\n this.vmCount = 0;\n def(value, '__ob__', this);\n if (Array.isArray(value)) {\n if (hasProto) {\n protoAugment(value, arrayMethods);\n } else {\n copyAugment(value, arrayMethods, arrayKeys);\n }\n this.observeArray(value);\n } else {\n this.walk(value);\n }\n};\n\n/**\n * Walk through all properties and convert them into\n * getter/setters. This method should only be called when\n * value type is Object.\n */\nObserver.prototype.walk = function walk (obj) {\n var keys = Object.keys(obj);\n for (var i = 0; i < keys.length; i++) {\n defineReactive$$1(obj, keys[i]);\n }\n};\n\n/**\n * Observe a list of Array items.\n */\nObserver.prototype.observeArray = function observeArray (items) {\n for (var i = 0, l = items.length; i < l; i++) {\n observe(items[i]);\n }\n};\n\n// helpers\n\n/**\n * Augment a target Object or Array by intercepting\n * the prototype chain using __proto__\n */\nfunction protoAugment (target, src) {\n /* eslint-disable no-proto */\n target.__proto__ = src;\n /* eslint-enable no-proto */\n}\n\n/**\n * Augment a target Object or Array by defining\n * hidden properties.\n */\n/* istanbul ignore next */\nfunction copyAugment (target, src, keys) {\n for (var i = 0, l = keys.length; i < l; i++) {\n var key = keys[i];\n def(target, key, src[key]);\n }\n}\n\n/**\n * Attempt to create an observer instance for a value,\n * returns the new observer if successfully observed,\n * or the existing observer if the value already has one.\n */\nfunction observe (value, asRootData) {\n if (!isObject(value) || value instanceof VNode) {\n return\n }\n var ob;\n if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {\n ob = value.__ob__;\n } else if (\n shouldObserve &&\n !isServerRendering() &&\n (Array.isArray(value) || isPlainObject(value)) &&\n Object.isExtensible(value) &&\n !value._isVue\n ) {\n ob = new Observer(value);\n }\n if (asRootData && ob) {\n ob.vmCount++;\n }\n return ob\n}\n\n/**\n * Define a reactive property on an Object.\n */\nfunction defineReactive$$1 (\n obj,\n key,\n val,\n customSetter,\n shallow\n) {\n var dep = new Dep();\n\n var property = Object.getOwnPropertyDescriptor(obj, key);\n if (property && property.configurable === false) {\n return\n }\n\n // cater for pre-defined getter/setters\n var getter = property && property.get;\n var setter = property && property.set;\n if ((!getter || setter) && arguments.length === 2) {\n val = obj[key];\n }\n\n var childOb = !shallow && observe(val);\n Object.defineProperty(obj, key, {\n enumerable: true,\n configurable: true,\n get: function reactiveGetter () {\n var value = getter ? getter.call(obj) : val;\n if (Dep.target) {\n dep.depend();\n if (childOb) {\n childOb.dep.depend();\n if (Array.isArray(value)) {\n dependArray(value);\n }\n }\n }\n return value\n },\n set: function reactiveSetter (newVal) {\n var value = getter ? getter.call(obj) : val;\n /* eslint-disable no-self-compare */\n if (newVal === value || (newVal !== newVal && value !== value)) {\n return\n }\n /* eslint-enable no-self-compare */\n if (process.env.NODE_ENV !== 'production' && customSetter) {\n customSetter();\n }\n // #7981: for accessor properties without setter\n if (getter && !setter) { return }\n if (setter) {\n setter.call(obj, newVal);\n } else {\n val = newVal;\n }\n childOb = !shallow && observe(newVal);\n dep.notify();\n }\n });\n}\n\n/**\n * Set a property on an object. Adds the new property and\n * triggers change notification if the property doesn't\n * already exist.\n */\nfunction set (target, key, val) {\n if (process.env.NODE_ENV !== 'production' &&\n (isUndef(target) || isPrimitive(target))\n ) {\n warn((\"Cannot set reactive property on undefined, null, or primitive value: \" + ((target))));\n }\n if (Array.isArray(target) && isValidArrayIndex(key)) {\n target.length = Math.max(target.length, key);\n target.splice(key, 1, val);\n return val\n }\n if (key in target && !(key in Object.prototype)) {\n target[key] = val;\n return val\n }\n var ob = (target).__ob__;\n if (target._isVue || (ob && ob.vmCount)) {\n process.env.NODE_ENV !== 'production' && warn(\n 'Avoid adding reactive properties to a Vue instance or its root $data ' +\n 'at runtime - declare it upfront in the data option.'\n );\n return val\n }\n if (!ob) {\n target[key] = val;\n return val\n }\n defineReactive$$1(ob.value, key, val);\n ob.dep.notify();\n return val\n}\n\n/**\n * Delete a property and trigger change if necessary.\n */\nfunction del (target, key) {\n if (process.env.NODE_ENV !== 'production' &&\n (isUndef(target) || isPrimitive(target))\n ) {\n warn((\"Cannot delete reactive property on undefined, null, or primitive value: \" + ((target))));\n }\n if (Array.isArray(target) && isValidArrayIndex(key)) {\n target.splice(key, 1);\n return\n }\n var ob = (target).__ob__;\n if (target._isVue || (ob && ob.vmCount)) {\n process.env.NODE_ENV !== 'production' && warn(\n 'Avoid deleting properties on a Vue instance or its root $data ' +\n '- just set it to null.'\n );\n return\n }\n if (!hasOwn(target, key)) {\n return\n }\n delete target[key];\n if (!ob) {\n return\n }\n ob.dep.notify();\n}\n\n/**\n * Collect dependencies on array elements when the array is touched, since\n * we cannot intercept array element access like property getters.\n */\nfunction dependArray (value) {\n for (var e = (void 0), i = 0, l = value.length; i < l; i++) {\n e = value[i];\n e && e.__ob__ && e.__ob__.dep.depend();\n if (Array.isArray(e)) {\n dependArray(e);\n }\n }\n}\n\n/* */\n\n/**\n * Option overwriting strategies are functions that handle\n * how to merge a parent option value and a child option\n * value into the final value.\n */\nvar strats = config.optionMergeStrategies;\n\n/**\n * Options with restrictions\n */\nif (process.env.NODE_ENV !== 'production') {\n strats.el = strats.propsData = function (parent, child, vm, key) {\n if (!vm) {\n warn(\n \"option \\\"\" + key + \"\\\" can only be used during instance \" +\n 'creation with the `new` keyword.'\n );\n }\n return defaultStrat(parent, child)\n };\n}\n\n/**\n * Helper that recursively merges two data objects together.\n */\nfunction mergeData (to, from) {\n if (!from) { return to }\n var key, toVal, fromVal;\n\n var keys = hasSymbol\n ? Reflect.ownKeys(from)\n : Object.keys(from);\n\n for (var i = 0; i < keys.length; i++) {\n key = keys[i];\n // in case the object is already observed...\n if (key === '__ob__') { continue }\n toVal = to[key];\n fromVal = from[key];\n if (!hasOwn(to, key)) {\n set(to, key, fromVal);\n } else if (\n toVal !== fromVal &&\n isPlainObject(toVal) &&\n isPlainObject(fromVal)\n ) {\n mergeData(toVal, fromVal);\n }\n }\n return to\n}\n\n/**\n * Data\n */\nfunction mergeDataOrFn (\n parentVal,\n childVal,\n vm\n) {\n if (!vm) {\n // in a Vue.extend merge, both should be functions\n if (!childVal) {\n return parentVal\n }\n if (!parentVal) {\n return childVal\n }\n // when parentVal & childVal are both present,\n // we need to return a function that returns the\n // merged result of both functions... no need to\n // check if parentVal is a function here because\n // it has to be a function to pass previous merges.\n return function mergedDataFn () {\n return mergeData(\n typeof childVal === 'function' ? childVal.call(this, this) : childVal,\n typeof parentVal === 'function' ? parentVal.call(this, this) : parentVal\n )\n }\n } else {\n return function mergedInstanceDataFn () {\n // instance merge\n var instanceData = typeof childVal === 'function'\n ? childVal.call(vm, vm)\n : childVal;\n var defaultData = typeof parentVal === 'function'\n ? parentVal.call(vm, vm)\n : parentVal;\n if (instanceData) {\n return mergeData(instanceData, defaultData)\n } else {\n return defaultData\n }\n }\n }\n}\n\nstrats.data = function (\n parentVal,\n childVal,\n vm\n) {\n if (!vm) {\n if (childVal && typeof childVal !== 'function') {\n process.env.NODE_ENV !== 'production' && warn(\n 'The \"data\" option should be a function ' +\n 'that returns a per-instance value in component ' +\n 'definitions.',\n vm\n );\n\n return parentVal\n }\n return mergeDataOrFn(parentVal, childVal)\n }\n\n return mergeDataOrFn(parentVal, childVal, vm)\n};\n\n/**\n * Hooks and props are merged as arrays.\n */\nfunction mergeHook (\n parentVal,\n childVal\n) {\n var res = childVal\n ? parentVal\n ? parentVal.concat(childVal)\n : Array.isArray(childVal)\n ? childVal\n : [childVal]\n : parentVal;\n return res\n ? dedupeHooks(res)\n : res\n}\n\nfunction dedupeHooks (hooks) {\n var res = [];\n for (var i = 0; i < hooks.length; i++) {\n if (res.indexOf(hooks[i]) === -1) {\n res.push(hooks[i]);\n }\n }\n return res\n}\n\nLIFECYCLE_HOOKS.forEach(function (hook) {\n strats[hook] = mergeHook;\n});\n\n/**\n * Assets\n *\n * When a vm is present (instance creation), we need to do\n * a three-way merge between constructor options, instance\n * options and parent options.\n */\nfunction mergeAssets (\n parentVal,\n childVal,\n vm,\n key\n) {\n var res = Object.create(parentVal || null);\n if (childVal) {\n process.env.NODE_ENV !== 'production' && assertObjectType(key, childVal, vm);\n return extend(res, childVal)\n } else {\n return res\n }\n}\n\nASSET_TYPES.forEach(function (type) {\n strats[type + 's'] = mergeAssets;\n});\n\n/**\n * Watchers.\n *\n * Watchers hashes should not overwrite one\n * another, so we merge them as arrays.\n */\nstrats.watch = function (\n parentVal,\n childVal,\n vm,\n key\n) {\n // work around Firefox's Object.prototype.watch...\n if (parentVal === nativeWatch) { parentVal = undefined; }\n if (childVal === nativeWatch) { childVal = undefined; }\n /* istanbul ignore if */\n if (!childVal) { return Object.create(parentVal || null) }\n if (process.env.NODE_ENV !== 'production') {\n assertObjectType(key, childVal, vm);\n }\n if (!parentVal) { return childVal }\n var ret = {};\n extend(ret, parentVal);\n for (var key$1 in childVal) {\n var parent = ret[key$1];\n var child = childVal[key$1];\n if (parent && !Array.isArray(parent)) {\n parent = [parent];\n }\n ret[key$1] = parent\n ? parent.concat(child)\n : Array.isArray(child) ? child : [child];\n }\n return ret\n};\n\n/**\n * Other object hashes.\n */\nstrats.props =\nstrats.methods =\nstrats.inject =\nstrats.computed = function (\n parentVal,\n childVal,\n vm,\n key\n) {\n if (childVal && process.env.NODE_ENV !== 'production') {\n assertObjectType(key, childVal, vm);\n }\n if (!parentVal) { return childVal }\n var ret = Object.create(null);\n extend(ret, parentVal);\n if (childVal) { extend(ret, childVal); }\n return ret\n};\nstrats.provide = mergeDataOrFn;\n\n/**\n * Default strategy.\n */\nvar defaultStrat = function (parentVal, childVal) {\n return childVal === undefined\n ? parentVal\n : childVal\n};\n\n/**\n * Validate component names\n */\nfunction checkComponents (options) {\n for (var key in options.components) {\n validateComponentName(key);\n }\n}\n\nfunction validateComponentName (name) {\n if (!new RegExp((\"^[a-zA-Z][\\\\-\\\\.0-9_\" + (unicodeRegExp.source) + \"]*$\")).test(name)) {\n warn(\n 'Invalid component name: \"' + name + '\". Component names ' +\n 'should conform to valid custom element name in html5 specification.'\n );\n }\n if (isBuiltInTag(name) || config.isReservedTag(name)) {\n warn(\n 'Do not use built-in or reserved HTML elements as component ' +\n 'id: ' + name\n );\n }\n}\n\n/**\n * Ensure all props option syntax are normalized into the\n * Object-based format.\n */\nfunction normalizeProps (options, vm) {\n var props = options.props;\n if (!props) { return }\n var res = {};\n var i, val, name;\n if (Array.isArray(props)) {\n i = props.length;\n while (i--) {\n val = props[i];\n if (typeof val === 'string') {\n name = camelize(val);\n res[name] = { type: null };\n } else if (process.env.NODE_ENV !== 'production') {\n warn('props must be strings when using array syntax.');\n }\n }\n } else if (isPlainObject(props)) {\n for (var key in props) {\n val = props[key];\n name = camelize(key);\n res[name] = isPlainObject(val)\n ? val\n : { type: val };\n }\n } else if (process.env.NODE_ENV !== 'production') {\n warn(\n \"Invalid value for option \\\"props\\\": expected an Array or an Object, \" +\n \"but got \" + (toRawType(props)) + \".\",\n vm\n );\n }\n options.props = res;\n}\n\n/**\n * Normalize all injections into Object-based format\n */\nfunction normalizeInject (options, vm) {\n var inject = options.inject;\n if (!inject) { return }\n var normalized = options.inject = {};\n if (Array.isArray(inject)) {\n for (var i = 0; i < inject.length; i++) {\n normalized[inject[i]] = { from: inject[i] };\n }\n } else if (isPlainObject(inject)) {\n for (var key in inject) {\n var val = inject[key];\n normalized[key] = isPlainObject(val)\n ? extend({ from: key }, val)\n : { from: val };\n }\n } else if (process.env.NODE_ENV !== 'production') {\n warn(\n \"Invalid value for option \\\"inject\\\": expected an Array or an Object, \" +\n \"but got \" + (toRawType(inject)) + \".\",\n vm\n );\n }\n}\n\n/**\n * Normalize raw function directives into object format.\n */\nfunction normalizeDirectives (options) {\n var dirs = options.directives;\n if (dirs) {\n for (var key in dirs) {\n var def$$1 = dirs[key];\n if (typeof def$$1 === 'function') {\n dirs[key] = { bind: def$$1, update: def$$1 };\n }\n }\n }\n}\n\nfunction assertObjectType (name, value, vm) {\n if (!isPlainObject(value)) {\n warn(\n \"Invalid value for option \\\"\" + name + \"\\\": expected an Object, \" +\n \"but got \" + (toRawType(value)) + \".\",\n vm\n );\n }\n}\n\n/**\n * Merge two option objects into a new one.\n * Core utility used in both instantiation and inheritance.\n */\nfunction mergeOptions (\n parent,\n child,\n vm\n) {\n if (process.env.NODE_ENV !== 'production') {\n checkComponents(child);\n }\n\n if (typeof child === 'function') {\n child = child.options;\n }\n\n normalizeProps(child, vm);\n normalizeInject(child, vm);\n normalizeDirectives(child);\n\n // Apply extends and mixins on the child options,\n // but only if it is a raw options object that isn't\n // the result of another mergeOptions call.\n // Only merged options has the _base property.\n if (!child._base) {\n if (child.extends) {\n parent = mergeOptions(parent, child.extends, vm);\n }\n if (child.mixins) {\n for (var i = 0, l = child.mixins.length; i < l; i++) {\n parent = mergeOptions(parent, child.mixins[i], vm);\n }\n }\n }\n\n var options = {};\n var key;\n for (key in parent) {\n mergeField(key);\n }\n for (key in child) {\n if (!hasOwn(parent, key)) {\n mergeField(key);\n }\n }\n function mergeField (key) {\n var strat = strats[key] || defaultStrat;\n options[key] = strat(parent[key], child[key], vm, key);\n }\n return options\n}\n\n/**\n * Resolve an asset.\n * This function is used because child instances need access\n * to assets defined in its ancestor chain.\n */\nfunction resolveAsset (\n options,\n type,\n id,\n warnMissing\n) {\n /* istanbul ignore if */\n if (typeof id !== 'string') {\n return\n }\n var assets = options[type];\n // check local registration variations first\n if (hasOwn(assets, id)) { return assets[id] }\n var camelizedId = camelize(id);\n if (hasOwn(assets, camelizedId)) { return assets[camelizedId] }\n var PascalCaseId = capitalize(camelizedId);\n if (hasOwn(assets, PascalCaseId)) { return assets[PascalCaseId] }\n // fallback to prototype chain\n var res = assets[id] || assets[camelizedId] || assets[PascalCaseId];\n if (process.env.NODE_ENV !== 'production' && warnMissing && !res) {\n warn(\n 'Failed to resolve ' + type.slice(0, -1) + ': ' + id,\n options\n );\n }\n return res\n}\n\n/* */\n\n\n\nfunction validateProp (\n key,\n propOptions,\n propsData,\n vm\n) {\n var prop = propOptions[key];\n var absent = !hasOwn(propsData, key);\n var value = propsData[key];\n // boolean casting\n var booleanIndex = getTypeIndex(Boolean, prop.type);\n if (booleanIndex > -1) {\n if (absent && !hasOwn(prop, 'default')) {\n value = false;\n } else if (value === '' || value === hyphenate(key)) {\n // only cast empty string / same name to boolean if\n // boolean has higher priority\n var stringIndex = getTypeIndex(String, prop.type);\n if (stringIndex < 0 || booleanIndex < stringIndex) {\n value = true;\n }\n }\n }\n // check default value\n if (value === undefined) {\n value = getPropDefaultValue(vm, prop, key);\n // since the default value is a fresh copy,\n // make sure to observe it.\n var prevShouldObserve = shouldObserve;\n toggleObserving(true);\n observe(value);\n toggleObserving(prevShouldObserve);\n }\n if (\n process.env.NODE_ENV !== 'production' &&\n // skip validation for weex recycle-list child component props\n !(false)\n ) {\n assertProp(prop, key, value, vm, absent);\n }\n return value\n}\n\n/**\n * Get the default value of a prop.\n */\nfunction getPropDefaultValue (vm, prop, key) {\n // no default, return undefined\n if (!hasOwn(prop, 'default')) {\n return undefined\n }\n var def = prop.default;\n // warn against non-factory defaults for Object & Array\n if (process.env.NODE_ENV !== 'production' && isObject(def)) {\n warn(\n 'Invalid default value for prop \"' + key + '\": ' +\n 'Props with type Object/Array must use a factory function ' +\n 'to return the default value.',\n vm\n );\n }\n // the raw prop value was also undefined from previous render,\n // return previous default value to avoid unnecessary watcher trigger\n if (vm && vm.$options.propsData &&\n vm.$options.propsData[key] === undefined &&\n vm._props[key] !== undefined\n ) {\n return vm._props[key]\n }\n // call factory function for non-Function types\n // a value is Function if its prototype is function even across different execution context\n return typeof def === 'function' && getType(prop.type) !== 'Function'\n ? def.call(vm)\n : def\n}\n\n/**\n * Assert whether a prop is valid.\n */\nfunction assertProp (\n prop,\n name,\n value,\n vm,\n absent\n) {\n if (prop.required && absent) {\n warn(\n 'Missing required prop: \"' + name + '\"',\n vm\n );\n return\n }\n if (value == null && !prop.required) {\n return\n }\n var type = prop.type;\n var valid = !type || type === true;\n var expectedTypes = [];\n if (type) {\n if (!Array.isArray(type)) {\n type = [type];\n }\n for (var i = 0; i < type.length && !valid; i++) {\n var assertedType = assertType(value, type[i]);\n expectedTypes.push(assertedType.expectedType || '');\n valid = assertedType.valid;\n }\n }\n\n if (!valid) {\n warn(\n getInvalidTypeMessage(name, value, expectedTypes),\n vm\n );\n return\n }\n var validator = prop.validator;\n if (validator) {\n if (!validator(value)) {\n warn(\n 'Invalid prop: custom validator check failed for prop \"' + name + '\".',\n vm\n );\n }\n }\n}\n\nvar simpleCheckRE = /^(String|Number|Boolean|Function|Symbol)$/;\n\nfunction assertType (value, type) {\n var valid;\n var expectedType = getType(type);\n if (simpleCheckRE.test(expectedType)) {\n var t = typeof value;\n valid = t === expectedType.toLowerCase();\n // for primitive wrapper objects\n if (!valid && t === 'object') {\n valid = value instanceof type;\n }\n } else if (expectedType === 'Object') {\n valid = isPlainObject(value);\n } else if (expectedType === 'Array') {\n valid = Array.isArray(value);\n } else {\n valid = value instanceof type;\n }\n return {\n valid: valid,\n expectedType: expectedType\n }\n}\n\n/**\n * Use function string name to check built-in types,\n * because a simple equality check will fail when running\n * across different vms / iframes.\n */\nfunction getType (fn) {\n var match = fn && fn.toString().match(/^\\s*function (\\w+)/);\n return match ? match[1] : ''\n}\n\nfunction isSameType (a, b) {\n return getType(a) === getType(b)\n}\n\nfunction getTypeIndex (type, expectedTypes) {\n if (!Array.isArray(expectedTypes)) {\n return isSameType(expectedTypes, type) ? 0 : -1\n }\n for (var i = 0, len = expectedTypes.length; i < len; i++) {\n if (isSameType(expectedTypes[i], type)) {\n return i\n }\n }\n return -1\n}\n\nfunction getInvalidTypeMessage (name, value, expectedTypes) {\n var message = \"Invalid prop: type check failed for prop \\\"\" + name + \"\\\".\" +\n \" Expected \" + (expectedTypes.map(capitalize).join(', '));\n var expectedType = expectedTypes[0];\n var receivedType = toRawType(value);\n var expectedValue = styleValue(value, expectedType);\n var receivedValue = styleValue(value, receivedType);\n // check if we need to specify expected value\n if (expectedTypes.length === 1 &&\n isExplicable(expectedType) &&\n !isBoolean(expectedType, receivedType)) {\n message += \" with value \" + expectedValue;\n }\n message += \", got \" + receivedType + \" \";\n // check if we need to specify received value\n if (isExplicable(receivedType)) {\n message += \"with value \" + receivedValue + \".\";\n }\n return message\n}\n\nfunction styleValue (value, type) {\n if (type === 'String') {\n return (\"\\\"\" + value + \"\\\"\")\n } else if (type === 'Number') {\n return (\"\" + (Number(value)))\n } else {\n return (\"\" + value)\n }\n}\n\nfunction isExplicable (value) {\n var explicitTypes = ['string', 'number', 'boolean'];\n return explicitTypes.some(function (elem) { return value.toLowerCase() === elem; })\n}\n\nfunction isBoolean () {\n var args = [], len = arguments.length;\n while ( len-- ) args[ len ] = arguments[ len ];\n\n return args.some(function (elem) { return elem.toLowerCase() === 'boolean'; })\n}\n\n/* */\n\nfunction handleError (err, vm, info) {\n // Deactivate deps tracking while processing error handler to avoid possible infinite rendering.\n // See: https://github.com/vuejs/vuex/issues/1505\n pushTarget();\n try {\n if (vm) {\n var cur = vm;\n while ((cur = cur.$parent)) {\n var hooks = cur.$options.errorCaptured;\n if (hooks) {\n for (var i = 0; i < hooks.length; i++) {\n try {\n var capture = hooks[i].call(cur, err, vm, info) === false;\n if (capture) { return }\n } catch (e) {\n globalHandleError(e, cur, 'errorCaptured hook');\n }\n }\n }\n }\n }\n globalHandleError(err, vm, info);\n } finally {\n popTarget();\n }\n}\n\nfunction invokeWithErrorHandling (\n handler,\n context,\n args,\n vm,\n info\n) {\n var res;\n try {\n res = args ? handler.apply(context, args) : handler.call(context);\n if (res && !res._isVue && isPromise(res) && !res._handled) {\n res.catch(function (e) { return handleError(e, vm, info + \" (Promise/async)\"); });\n // issue #9511\n // avoid catch triggering multiple times when nested calls\n res._handled = true;\n }\n } catch (e) {\n handleError(e, vm, info);\n }\n return res\n}\n\nfunction globalHandleError (err, vm, info) {\n if (config.errorHandler) {\n try {\n return config.errorHandler.call(null, err, vm, info)\n } catch (e) {\n // if the user intentionally throws the original error in the handler,\n // do not log it twice\n if (e !== err) {\n logError(e, null, 'config.errorHandler');\n }\n }\n }\n logError(err, vm, info);\n}\n\nfunction logError (err, vm, info) {\n if (process.env.NODE_ENV !== 'production') {\n warn((\"Error in \" + info + \": \\\"\" + (err.toString()) + \"\\\"\"), vm);\n }\n /* istanbul ignore else */\n if ((inBrowser || inWeex) && typeof console !== 'undefined') {\n console.error(err);\n } else {\n throw err\n }\n}\n\n/* */\n\nvar isUsingMicroTask = false;\n\nvar callbacks = [];\nvar pending = false;\n\nfunction flushCallbacks () {\n pending = false;\n var copies = callbacks.slice(0);\n callbacks.length = 0;\n for (var i = 0; i < copies.length; i++) {\n copies[i]();\n }\n}\n\n// Here we have async deferring wrappers using microtasks.\n// In 2.5 we used (macro) tasks (in combination with microtasks).\n// However, it has subtle problems when state is changed right before repaint\n// (e.g. #6813, out-in transitions).\n// Also, using (macro) tasks in event handler would cause some weird behaviors\n// that cannot be circumvented (e.g. #7109, #7153, #7546, #7834, #8109).\n// So we now use microtasks everywhere, again.\n// A major drawback of this tradeoff is that there are some scenarios\n// where microtasks have too high a priority and fire in between supposedly\n// sequential events (e.g. #4521, #6690, which have workarounds)\n// or even between bubbling of the same event (#6566).\nvar timerFunc;\n\n// The nextTick behavior leverages the microtask queue, which can be accessed\n// via either native Promise.then or MutationObserver.\n// MutationObserver has wider support, however it is seriously bugged in\n// UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It\n// completely stops working after triggering a few times... so, if native\n// Promise is available, we will use it:\n/* istanbul ignore next, $flow-disable-line */\nif (typeof Promise !== 'undefined' && isNative(Promise)) {\n var p = Promise.resolve();\n timerFunc = function () {\n p.then(flushCallbacks);\n // In problematic UIWebViews, Promise.then doesn't completely break, but\n // it can get stuck in a weird state where callbacks are pushed into the\n // microtask queue but the queue isn't being flushed, until the browser\n // needs to do some other work, e.g. handle a timer. Therefore we can\n // \"force\" the microtask queue to be flushed by adding an empty timer.\n if (isIOS) { setTimeout(noop); }\n };\n isUsingMicroTask = true;\n} else if (!isIE && typeof MutationObserver !== 'undefined' && (\n isNative(MutationObserver) ||\n // PhantomJS and iOS 7.x\n MutationObserver.toString() === '[object MutationObserverConstructor]'\n)) {\n // Use MutationObserver where native Promise is not available,\n // e.g. PhantomJS, iOS7, Android 4.4\n // (#6466 MutationObserver is unreliable in IE11)\n var counter = 1;\n var observer = new MutationObserver(flushCallbacks);\n var textNode = document.createTextNode(String(counter));\n observer.observe(textNode, {\n characterData: true\n });\n timerFunc = function () {\n counter = (counter + 1) % 2;\n textNode.data = String(counter);\n };\n isUsingMicroTask = true;\n} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {\n // Fallback to setImmediate.\n // Technically it leverages the (macro) task queue,\n // but it is still a better choice than setTimeout.\n timerFunc = function () {\n setImmediate(flushCallbacks);\n };\n} else {\n // Fallback to setTimeout.\n timerFunc = function () {\n setTimeout(flushCallbacks, 0);\n };\n}\n\nfunction nextTick (cb, ctx) {\n var _resolve;\n callbacks.push(function () {\n if (cb) {\n try {\n cb.call(ctx);\n } catch (e) {\n handleError(e, ctx, 'nextTick');\n }\n } else if (_resolve) {\n _resolve(ctx);\n }\n });\n if (!pending) {\n pending = true;\n timerFunc();\n }\n // $flow-disable-line\n if (!cb && typeof Promise !== 'undefined') {\n return new Promise(function (resolve) {\n _resolve = resolve;\n })\n }\n}\n\n/* */\n\n/* not type checking this file because flow doesn't play well with Proxy */\n\nvar initProxy;\n\nif (process.env.NODE_ENV !== 'production') {\n var allowedGlobals = makeMap(\n 'Infinity,undefined,NaN,isFinite,isNaN,' +\n 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +\n 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +\n 'require' // for Webpack/Browserify\n );\n\n var warnNonPresent = function (target, key) {\n warn(\n \"Property or method \\\"\" + key + \"\\\" is not defined on the instance but \" +\n 'referenced during render. Make sure that this property is reactive, ' +\n 'either in the data option, or for class-based components, by ' +\n 'initializing the property. ' +\n 'See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.',\n target\n );\n };\n\n var warnReservedPrefix = function (target, key) {\n warn(\n \"Property \\\"\" + key + \"\\\" must be accessed with \\\"$data.\" + key + \"\\\" because \" +\n 'properties starting with \"$\" or \"_\" are not proxied in the Vue instance to ' +\n 'prevent conflicts with Vue internals. ' +\n 'See: https://vuejs.org/v2/api/#data',\n target\n );\n };\n\n var hasProxy =\n typeof Proxy !== 'undefined' && isNative(Proxy);\n\n if (hasProxy) {\n var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact');\n config.keyCodes = new Proxy(config.keyCodes, {\n set: function set (target, key, value) {\n if (isBuiltInModifier(key)) {\n warn((\"Avoid overwriting built-in modifier in config.keyCodes: .\" + key));\n return false\n } else {\n target[key] = value;\n return true\n }\n }\n });\n }\n\n var hasHandler = {\n has: function has (target, key) {\n var has = key in target;\n var isAllowed = allowedGlobals(key) ||\n (typeof key === 'string' && key.charAt(0) === '_' && !(key in target.$data));\n if (!has && !isAllowed) {\n if (key in target.$data) { warnReservedPrefix(target, key); }\n else { warnNonPresent(target, key); }\n }\n return has || !isAllowed\n }\n };\n\n var getHandler = {\n get: function get (target, key) {\n if (typeof key === 'string' && !(key in target)) {\n if (key in target.$data) { warnReservedPrefix(target, key); }\n else { warnNonPresent(target, key); }\n }\n return target[key]\n }\n };\n\n initProxy = function initProxy (vm) {\n if (hasProxy) {\n // determine which proxy handler to use\n var options = vm.$options;\n var handlers = options.render && options.render._withStripped\n ? getHandler\n : hasHandler;\n vm._renderProxy = new Proxy(vm, handlers);\n } else {\n vm._renderProxy = vm;\n }\n };\n}\n\n/* */\n\nvar seenObjects = new _Set();\n\n/**\n * Recursively traverse an object to evoke all converted\n * getters, so that every nested property inside the object\n * is collected as a \"deep\" dependency.\n */\nfunction traverse (val) {\n _traverse(val, seenObjects);\n seenObjects.clear();\n}\n\nfunction _traverse (val, seen) {\n var i, keys;\n var isA = Array.isArray(val);\n if ((!isA && !isObject(val)) || Object.isFrozen(val) || val instanceof VNode) {\n return\n }\n if (val.__ob__) {\n var depId = val.__ob__.dep.id;\n if (seen.has(depId)) {\n return\n }\n seen.add(depId);\n }\n if (isA) {\n i = val.length;\n while (i--) { _traverse(val[i], seen); }\n } else {\n keys = Object.keys(val);\n i = keys.length;\n while (i--) { _traverse(val[keys[i]], seen); }\n }\n}\n\nvar mark;\nvar measure;\n\nif (process.env.NODE_ENV !== 'production') {\n var perf = inBrowser && window.performance;\n /* istanbul ignore if */\n if (\n perf &&\n perf.mark &&\n perf.measure &&\n perf.clearMarks &&\n perf.clearMeasures\n ) {\n mark = function (tag) { return perf.mark(tag); };\n measure = function (name, startTag, endTag) {\n perf.measure(name, startTag, endTag);\n perf.clearMarks(startTag);\n perf.clearMarks(endTag);\n // perf.clearMeasures(name)\n };\n }\n}\n\n/* */\n\nvar normalizeEvent = cached(function (name) {\n var passive = name.charAt(0) === '&';\n name = passive ? name.slice(1) : name;\n var once$$1 = name.charAt(0) === '~'; // Prefixed last, checked first\n name = once$$1 ? name.slice(1) : name;\n var capture = name.charAt(0) === '!';\n name = capture ? name.slice(1) : name;\n return {\n name: name,\n once: once$$1,\n capture: capture,\n passive: passive\n }\n});\n\nfunction createFnInvoker (fns, vm) {\n function invoker () {\n var arguments$1 = arguments;\n\n var fns = invoker.fns;\n if (Array.isArray(fns)) {\n var cloned = fns.slice();\n for (var i = 0; i < cloned.length; i++) {\n invokeWithErrorHandling(cloned[i], null, arguments$1, vm, \"v-on handler\");\n }\n } else {\n // return handler return value for single handlers\n return invokeWithErrorHandling(fns, null, arguments, vm, \"v-on handler\")\n }\n }\n invoker.fns = fns;\n return invoker\n}\n\nfunction updateListeners (\n on,\n oldOn,\n add,\n remove$$1,\n createOnceHandler,\n vm\n) {\n var name, def$$1, cur, old, event;\n for (name in on) {\n def$$1 = cur = on[name];\n old = oldOn[name];\n event = normalizeEvent(name);\n if (isUndef(cur)) {\n process.env.NODE_ENV !== 'production' && warn(\n \"Invalid handler for event \\\"\" + (event.name) + \"\\\": got \" + String(cur),\n vm\n );\n } else if (isUndef(old)) {\n if (isUndef(cur.fns)) {\n cur = on[name] = createFnInvoker(cur, vm);\n }\n if (isTrue(event.once)) {\n cur = on[name] = createOnceHandler(event.name, cur, event.capture);\n }\n add(event.name, cur, event.capture, event.passive, event.params);\n } else if (cur !== old) {\n old.fns = cur;\n on[name] = old;\n }\n }\n for (name in oldOn) {\n if (isUndef(on[name])) {\n event = normalizeEvent(name);\n remove$$1(event.name, oldOn[name], event.capture);\n }\n }\n}\n\n/* */\n\nfunction mergeVNodeHook (def, hookKey, hook) {\n if (def instanceof VNode) {\n def = def.data.hook || (def.data.hook = {});\n }\n var invoker;\n var oldHook = def[hookKey];\n\n function wrappedHook () {\n hook.apply(this, arguments);\n // important: remove merged hook to ensure it's called only once\n // and prevent memory leak\n remove(invoker.fns, wrappedHook);\n }\n\n if (isUndef(oldHook)) {\n // no existing hook\n invoker = createFnInvoker([wrappedHook]);\n } else {\n /* istanbul ignore if */\n if (isDef(oldHook.fns) && isTrue(oldHook.merged)) {\n // already a merged invoker\n invoker = oldHook;\n invoker.fns.push(wrappedHook);\n } else {\n // existing plain hook\n invoker = createFnInvoker([oldHook, wrappedHook]);\n }\n }\n\n invoker.merged = true;\n def[hookKey] = invoker;\n}\n\n/* */\n\nfunction extractPropsFromVNodeData (\n data,\n Ctor,\n tag\n) {\n // we are only extracting raw values here.\n // validation and default values are handled in the child\n // component itself.\n var propOptions = Ctor.options.props;\n if (isUndef(propOptions)) {\n return\n }\n var res = {};\n var attrs = data.attrs;\n var props = data.props;\n if (isDef(attrs) || isDef(props)) {\n for (var key in propOptions) {\n var altKey = hyphenate(key);\n if (process.env.NODE_ENV !== 'production') {\n var keyInLowerCase = key.toLowerCase();\n if (\n key !== keyInLowerCase &&\n attrs && hasOwn(attrs, keyInLowerCase)\n ) {\n tip(\n \"Prop \\\"\" + keyInLowerCase + \"\\\" is passed to component \" +\n (formatComponentName(tag || Ctor)) + \", but the declared prop name is\" +\n \" \\\"\" + key + \"\\\". \" +\n \"Note that HTML attributes are case-insensitive and camelCased \" +\n \"props need to use their kebab-case equivalents when using in-DOM \" +\n \"templates. You should probably use \\\"\" + altKey + \"\\\" instead of \\\"\" + key + \"\\\".\"\n );\n }\n }\n checkProp(res, props, key, altKey, true) ||\n checkProp(res, attrs, key, altKey, false);\n }\n }\n return res\n}\n\nfunction checkProp (\n res,\n hash,\n key,\n altKey,\n preserve\n) {\n if (isDef(hash)) {\n if (hasOwn(hash, key)) {\n res[key] = hash[key];\n if (!preserve) {\n delete hash[key];\n }\n return true\n } else if (hasOwn(hash, altKey)) {\n res[key] = hash[altKey];\n if (!preserve) {\n delete hash[altKey];\n }\n return true\n }\n }\n return false\n}\n\n/* */\n\n// The template compiler attempts to minimize the need for normalization by\n// statically analyzing the template at compile time.\n//\n// For plain HTML markup, normalization can be completely skipped because the\n// generated render function is guaranteed to return Array. There are\n// two cases where extra normalization is needed:\n\n// 1. When the children contains components - because a functional component\n// may return an Array instead of a single root. In this case, just a simple\n// normalization is needed - if any child is an Array, we flatten the whole\n// thing with Array.prototype.concat. It is guaranteed to be only 1-level deep\n// because functional components already normalize their own children.\nfunction simpleNormalizeChildren (children) {\n for (var i = 0; i < children.length; i++) {\n if (Array.isArray(children[i])) {\n return Array.prototype.concat.apply([], children)\n }\n }\n return children\n}\n\n// 2. When the children contains constructs that always generated nested Arrays,\n// e.g.