{"version":3,"sources":["Intro.tsx","Equipment.ts","EquipmentModel.ts","EquipmentContext.tsx","NumberInput.tsx","Table.tsx","EquipmentEditor.tsx","Service.ts","InfoTip.tsx","LocationPicker.tsx","Wizard.tsx","Outro.tsx","App.tsx","serviceWorker.ts","index.tsx"],"names":["InfoTip","children","useState","show","setShow","className","href","onClick","_","StepTip","description","title","CollapsibleSection","expanded","iconStyle","marginBottom","style","cursor","Intro","target","blankProfile","Profiles","allProfiles","slice","getEquipmentList","profile","categories","flatMap","x","items","map","name","power","averagePower","quantity","hours","initialEquipmentModel","equipmentReducer","state","action","kind","profileIndex","categoryIndex","length","category","newCategory","concat","id","uuidv4","nameplatePower","d","custom","newProfile","replace","findIndex","categoryId","filter","itemId","newCategories","item","itemIndex","newItem","value","newHours","index","pre","suf","getItemEnergy","getCategoryEnergy","reduce","acc","getCategoriesEnergy","xs","EquipmentContext","createContext","dispatch","EquipmentProvider","useReducer","Provider","NumberInput","onChange","max","toString","setState","error","setError","useEffect","s","e","newState","handleChange","onBlur","n","Number","isNaN","handleBlur","TableGroup","context","useContext","setExpanded","total","colSpan","format1","format","key","format0","Intl","NumberFormat","maximumFractionDigits","minimumFractionDigits","TableRow","totalEnergy","isAlwaysOn","onSetHour","defaultValue","ev","onstyle","onlabel","offlabel","size","checked","TotalRow","TableHeader","width","zIndex","Table","EquipmentEditor","calculate","model","a","fetch","method","headers","body","JSON","stringify","rv","json","response","getStatus","delay","ms","Promise","resolve","setTimeout","text","OverlayTrigger","placement","overlay","Tooltip","height","LocationAddress","query","setQuery","inputEl","useRef","element","current","autocomplete","google","maps","places","Autocomplete","types","addListener","place","getPlace","formatted_address","geometry","address","coords","lat","location","lng","handleSearch","findLocation","val","ref","onKeyUp","type","geocode","complete","Geocoder","results","status","GeocoderStatus","OK","addr","Map","center","zoom","mapContainerStyle","latLng","position","draggable","onDragEnd","LocationCoords","LocationPicker","Field","label","placeholder","unit","tip","disabled","ErrorNote","message","fuelOptions","storageOptions","defaultModel","interestRate","gridStart","gridDuration","gridCost","fuelCost","pvCost","storageCost","converterCost","generatorCost","fuelName","storageName","getInputFromModel","latitude","longitude","equipment","validateInput","errors","h1","some","h2","h3","push","Array","from","i","Wizard","setModel","equipmentContext","progress","setProgress","setId","wait","setWait","ready","setReady","setErrors","onStart","validation","isValid","input","cancel","it","p","Math","window","open","run","locationLabel","toFixed","onSubmit","preventDefault","readOnly","Modal","centered","onHide","Header","closeButton","Title","Body","role","aria-valuemin","aria-valuemax","aria-valuenow","Outro","src","alt","App","Date","getFullYear","Boolean","hostname","match","ReactDOM","render","StrictMode","document","getElementById","navigator","serviceWorker","then","registration","unregister","catch","console"],"mappings":"4xsEAMMA,EAAU,SAAC,GAA8B,IAA7BC,EAA4B,EAA5BA,SAA4B,EACpBC,oBAAS,GADW,mBACrCC,EADqC,KAC/BC,EAD+B,KAG5C,OACE,oCACE,uBAAGC,UAAU,eAAeC,KAAK,KAAKC,QAAS,SAAAC,GAAC,OAAIJ,GAASD,KAA7D,eACCA,GACD,yBAAKE,UAAU,gBAAgBJ,KAW/BQ,EAAU,SAAC,GAAkD,IAAjDR,EAAgD,EAAhDA,SAAUS,EAAsC,EAAtCA,YAAaC,EAAyB,EAAzBA,MACvC,OACE,4BACE,2BAAIA,GADN,MACoBD,EAClB,kBAAC,EAAD,KACGT,KAaHW,EAAqB,SAAC,GAA0D,IAAzDD,EAAwD,EAAxDA,MAAOV,EAAiD,EAAjDA,SAAUY,EAAuC,EAAvCA,SAAuC,EAC3DX,mBAASW,GADkD,mBAC5EV,EAD4E,KACtEC,EADsE,KAG7EU,EAAY,CAACC,aAAc,OAEjC,OACE,oCACE,wBAAIR,QALO,WAAQH,GAASD,IAKPa,MAAO,CAACC,OAAQ,YACnC,8BACGd,EACC,kBAAC,IAAD,CAAea,MAAOF,IACtB,kBAAC,IAAD,CAAgBE,MAAOF,KAE3B,8BAAOH,IAERR,GAAQF,IAkFAiB,EA5ED,WACZ,OACE,yBAAKb,UAAU,QACb,0DAEA,kBAAC,EAAD,CAAoBM,MAAM,yBAAyBE,UAAU,GAC3D,o2BAKF,kBAAC,EAAD,CAAoBF,MAAM,uBAAuBE,UAAU,GACzD,uCACW,iDADX,KAC2C,uBAAGP,KAAK,0EAA0Ea,OAAO,UAAzF,QAD3C,KACuJ,uBAAGb,KAAK,yEAAyEa,OAAO,UAAxF,OADvJ,+NAGA,4BACE,kBAAC,EAAD,CACER,MAAM,yBACND,YAAY,sDACZ,uWAKF,kBAAC,EAAD,CACEC,MAAM,oBACND,YAAY,4LACZ,k2BACs0B,uBAAGJ,KAAK,wCAAR,wCADt0B,OACi6B,uBAAGA,KAAK,sCAAR,sCADj6B,MAKF,kBAAC,EAAD,CACEK,MAAM,wBACND,YAAY,iCACZ,8bAKF,kBAAC,EAAD,CACEC,MAAM,uBACND,YAAY,uQACZ,yXAC6V,8GAD7V,2WAKF,kBAAC,EAAD,CACEC,MAAM,2EACND,YAAY,IACZ,2KAMJ,2BACE,2OAEF,4BACE,8TAGA,mPAGA,+P,gDCnGGU,EAAeC,EAAS,GACxBC,EAAyBD,EAASE,MAAM,GAGxCC,EAAmB,SAACC,GAC/B,OAAOA,EAAQC,WAAWC,SAAQ,SAAAC,GAAC,OAAIA,EAAEC,SAAOC,KAAI,SAAAF,GAClD,MAAO,CACLG,KAAMH,EAAEG,KACRC,MAAOJ,EAAEK,aACTC,SAAUN,EAAEM,SACZC,MAAOP,EAAEO,W,gBCtCFC,EAAwC,CACnDX,QAASL,GAsBEiB,EAAmB,SAACC,EAAuBC,GACtD,OAAQA,EAAOC,MACb,IAAK,SACH,OAAO,eACFF,EADL,CAEEb,QAASH,EAAYiB,EAAOE,gBAEhC,IAAK,MACH,IAAMhB,EAAUa,EAAMb,QAChBiB,EAAgBjB,EAAQC,WAAWiB,OAAS,EAC5CC,EAAWnB,EAAQC,WAAWgB,GAC9BG,EAAW,eAAOD,EAAP,CAAiBf,MAAOe,EAASf,MAAMiB,OAAO,CDW5D,CACLC,GAAIC,cACJjB,KAAM,mBACNkB,eAAgB,EAChBhB,aAAc,EACdiB,EAAG,EACHhB,SAAU,EACVC,MAAO,CAAC,EAAG,EAAG,GACdgB,QAAQ,OClBAC,EAAU,eAAO3B,EAAP,CAAgBC,WAAY2B,EAAQ5B,EAAQC,WAAYgB,EAAeG,KACvF,OAAO,eACFP,EADL,CAEEb,QAAS2B,IAGb,IAAK,SACH,IAAM3B,EAAUa,EAAMb,QAChBiB,EAAgBjB,EAAQC,WAAW4B,WAAU,SAAA1B,GAAC,OAAIA,EAAEmB,KAAOR,EAAOgB,cAClEX,EAAWnB,EAAQC,WAAWgB,GAC9BG,EAAW,eAAOD,EAAP,CAAiBf,MAAOe,EAASf,MAAM2B,QAAO,SAAA5B,GAAC,OAAIA,EAAEmB,KAAOR,EAAOkB,YAC9EL,EAAU,eAAO3B,EAAP,CAAgBC,WAAY2B,EAAQ5B,EAAQC,WAAYgB,EAAeG,KACvF,OAAO,eACFP,EADL,CAEEb,QAAS2B,IAGb,IAAK,QACH,IAAM3B,EAAUa,EAAMb,QAChBiC,EAAgBjC,EAAQC,WAAWI,KAAI,SAAAc,GAC3C,OAAO,eACFA,EADL,CAEEf,MAAOe,EAASf,MAAMC,KAAI,SAAA6B,GAAU,OAAO,eAAIA,EAAX,CAAiBzB,SAAU,YAG7DkB,EAAU,eAAO3B,EAAP,CAAgBC,WAAYgC,IAC5C,OAAO,eACFpB,EADL,CAEEb,QAAS2B,IAIb,IAAK,OACH,IAAM3B,EAAUa,EAAMb,QAChBiB,EAAgBjB,EAAQC,WAAW4B,WAAU,SAAA1B,GAAC,OAAIA,EAAEmB,KAAOR,EAAOgB,cAClEX,EAAWnB,EAAQC,WAAWgB,GAC9BkB,EAAYhB,EAASf,MAAMyB,WAAU,SAAA1B,GAAC,OAAIA,EAAEmB,KAAOR,EAAOkB,UAC1DE,EAAOf,EAASf,MAAM+B,GACtBC,EAAO,eAAOF,EAAP,CAAa5B,KAAMQ,EAAOuB,QACjCjB,EAAW,eAAOD,EAAP,CAAiBf,MAAOwB,EAAQT,EAASf,MAAO+B,EAAWC,KACtET,EAAU,eAAO3B,EAAP,CAAgBC,WAAY2B,EAAQ5B,EAAQC,WAAYgB,EAAeG,KACvF,OAAO,eACFP,EADL,CAEEb,QAAS2B,IAGb,IAAK,iBACH,IAAM3B,EAAUa,EAAMb,QAChBiB,EAAgBjB,EAAQC,WAAW4B,WAAU,SAAA1B,GAAC,OAAIA,EAAEmB,KAAOR,EAAOgB,cAClEX,EAAWnB,EAAQC,WAAWgB,GAC9BkB,EAAYhB,EAASf,MAAMyB,WAAU,SAAA1B,GAAC,OAAIA,EAAEmB,KAAOR,EAAOkB,UAC1DE,EAAOf,EAASf,MAAM+B,GAEtBX,EAAiBV,EAAOuB,MAExB7B,EAAe0B,EAAKR,OAASQ,EAAK1B,aAAegB,EAAiBU,EAAKT,EACvEW,EAAO,eAAOF,EAAP,CAAaV,iBAAgBhB,iBACpCY,EAAW,eAAOD,EAAP,CAAiBf,MAAOwB,EAAQT,EAASf,MAAO+B,EAAWC,KACtET,EAAU,eAAO3B,EAAP,CAAgBC,WAAY2B,EAAQ5B,EAAQC,WAAYgB,EAAeG,KACvF,OAAO,eACFP,EADL,CAEEb,QAAS2B,IAGb,IAAK,eACH,IAAM3B,EAAUa,EAAMb,QAChBiB,EAAgBjB,EAAQC,WAAW4B,WAAU,SAAA1B,GAAC,OAAIA,EAAEmB,KAAOR,EAAOgB,cAClEX,EAAWnB,EAAQC,WAAWgB,GAC9BkB,EAAYhB,EAASf,MAAMyB,WAAU,SAAA1B,GAAC,OAAIA,EAAEmB,KAAOR,EAAOkB,UAC1DE,EAAOf,EAASf,MAAM+B,GAG5B,IAAKD,EAAKR,OAAU,OAAOb,EAC3B,IAAML,EAAeM,EAAOuB,MACtBD,EAAO,eAAOF,EAAP,CAAa1B,iBACpBY,EAAW,eAAOD,EAAP,CAAiBf,MAAOwB,EAAQT,EAASf,MAAO+B,EAAWC,KACtET,EAAU,eAAO3B,EAAP,CAAgBC,WAAY2B,EAAQ5B,EAAQC,WAAYgB,EAAeG,KACvF,OAAO,eACFP,EADL,CAEEb,QAAS2B,IAGb,IAAK,WACH,IAAM3B,EAAUa,EAAMb,QAChBiB,EAAgBjB,EAAQC,WAAW4B,WAAU,SAAA1B,GAAC,OAAIA,EAAEmB,KAAOR,EAAOgB,cAClEX,EAAWnB,EAAQC,WAAWgB,GAC9BkB,EAAYhB,EAASf,MAAMyB,WAAU,SAAA1B,GAAC,OAAIA,EAAEmB,KAAOR,EAAOkB,UAC1DE,EAAOf,EAASf,MAAM+B,GACtBC,EAAO,eAAOF,EAAP,CAAazB,SAAUK,EAAOuB,QACrCjB,EAAW,eAAOD,EAAP,CAAiBf,MAAOwB,EAAQT,EAASf,MAAO+B,EAAWC,KACtET,GAAU,eAAO3B,EAAP,CAAgBC,WAAY2B,EAAQ5B,EAAQC,WAAYgB,EAAeG,KACvF,OAAO,eACFP,EADL,CAEEb,QAAS2B,KAGb,IAAK,KACH,IAAM3B,GAAUa,EAAMb,QAChBiB,GAAgBjB,GAAQC,WAAW4B,WAAU,SAAA1B,GAAC,OAAIA,EAAEmB,KAAOR,EAAOgB,cAClEX,GAAWnB,GAAQC,WAAWgB,IAC9BkB,GAAYhB,GAASf,MAAMyB,WAAU,SAAA1B,GAAC,OAAIA,EAAEmB,KAAOR,EAAOkB,UAC1DE,GAAOf,GAASf,MAAM+B,IACtBC,GAAO,eAAOF,GAAP,CAAaxB,MAAO,CAAC,GAAI,EAAG,KACnCU,GAAW,eAAOD,GAAP,CAAiBf,MAAOwB,EAAQT,GAASf,MAAO+B,GAAWC,MACtET,GAAU,eAAO3B,GAAP,CAAgBC,WAAY2B,EAAQ5B,GAAQC,WAAYgB,GAAeG,MACvF,OAAO,eACFP,EADL,CAEEb,QAAS2B,KAGb,IAAK,OACH,IAAM3B,GAAUa,EAAMb,QAChBiB,GAAgBjB,GAAQC,WAAW4B,WAAU,SAAA1B,GAAC,OAAIA,EAAEmB,KAAOR,EAAOgB,cAClEX,GAAWnB,GAAQC,WAAWgB,IAC9BkB,GAAYhB,GAASf,MAAMyB,WAAU,SAAA1B,GAAC,OAAIA,EAAEmB,KAAOR,EAAOkB,UAC1DE,GAAOf,GAASf,MAAM+B,IACtBG,GAAQ,YAAOJ,GAAKxB,OAC1B4B,GAASxB,EAAOyB,OAASzB,EAAOuB,MAChC,IAAMD,GAAO,eAAOF,GAAP,CAAaxB,MAAO4B,KAC3BlB,GAAW,eAAOD,GAAP,CAAiBf,MAAOwB,EAAQT,GAASf,MAAO+B,GAAWC,MACtET,GAAU,eAAO3B,GAAP,CAAgBC,WAAY2B,EAAQ5B,GAAQC,WAAYgB,GAAeG,MACvF,OAAO,eACFP,EADL,CAEEb,QAAS2B,KAIb,QACE,OAAOd,IAKPe,EAAU,SAAIxB,EAAYmC,EAAeL,GAC7C,IAAMM,EAAMpC,EAAMN,MAAM,EAAGyC,GACrBE,EAAMrC,EAAMN,MAAMyC,EAAQ,GAChC,OAAOC,EAAInB,OAAO,CAACa,GAAOO,IAIfC,EAAgB,SAACvC,GAAD,OAAqBA,EAAEK,aAAeL,EAAEM,UAAYN,EAAEO,MAAM,GAAKP,EAAEO,MAAM,GAAKP,EAAEO,MAAM,IAAM,KAE5GiC,EAAoB,SAACxC,GAAD,OAAyBA,EAAEC,MACzDC,KAAI,SAAAF,GAAC,OAAIuC,EAAcvC,MACvByC,QAAO,SAACC,EAAK1C,GAAN,OAAY0C,EAAM1C,IAAG,IAElB2C,EAAsB,SAACC,GAAD,OAA4BA,EAC5D1C,KAAI,SAAAF,GAAC,OAAIwC,EAAkBxC,MAC3ByC,QAAO,SAACC,EAAK1C,GAAN,OAAY0C,EAAM1C,IAAG,ICjLlB6C,EAAmBC,wBAAqC,CAACpC,MAAOF,EAAuBuC,SAAU,kBAAM,QAEvGC,EAA8B,SAAC,GAAgB,IAAf3E,EAAc,EAAdA,SAAc,EAC/B4E,qBAAWxC,EAAkBD,GADE,mBAClDE,EADkD,KAC3CqC,EAD2C,KAEzD,OACE,kBAACF,EAAiBK,SAAlB,CAA2BhB,MAAO,CAACxB,QAAOqC,aACvC1E,ICsCQ8E,EA1CK,SAAC,GAA4C,IAA3ChC,EAA0C,EAA1CA,GAAIe,EAAsC,EAAtCA,MAAOkB,EAA+B,EAA/BA,SAAUC,EAAqB,EAArBA,IAAqB,EACpC/E,mBAAS4D,EAAMoB,YADqB,mBACvD5C,EADuD,KAChD6C,EADgD,OAEpCjF,oBAAS,GAF2B,mBAEvDkF,EAFuD,KAEhDC,EAFgD,KAI9DC,qBAAU,WACRH,EAASrB,EAAMoB,YACXD,GACFI,EAASvB,EAAQmB,KAElB,CAACnB,IAEJ,IAoBMyB,EAAC,uCAAmCH,EAAQ,aAAe,IAEjE,OACE,2BAAO/E,UAAWkF,EACXxD,KAAMgB,EACNe,MAAOxB,EACP0C,SAAU,SAACQ,GAAD,OA1BE,SAACA,GACpB,IAAMC,EAAWD,EAAErE,OAAO2C,MAC1BqB,EAASM,GACTJ,GAAS,GAuBeK,CAAaF,IAC9BG,OAAQ,SAACH,GAAD,OArBE,SAACA,GAClB,IAAMC,EAAWD,EAAErE,OAAO2C,MAC1BqB,EAASM,GACT,IAAMG,EAAIC,OAAOJ,GACZK,MAAMF,GAMTP,GAAS,IALLJ,GACFI,EAASvB,EAAQmB,GAEnBD,EAASY,IAaWG,CAAWP,O,iBClB/BQ,EAAa,SAAC,GAAiC,IAAhCpD,EAA+B,EAA/BA,SACbqD,EAAUC,qBAAWzB,GADuB,EAElBvE,oBAAS,GAFS,mBAE3CW,EAF2C,KAEjCsF,EAFiC,KAO5CC,EAAQhC,EAAkBxB,GAEhC,OAAQ,oCACN,wBAAIrC,QAPS,kBAAM4F,GAAatF,IAOXR,UAAU,kBAAkBW,MAAO,CAACC,OAAQ,YAC/D,wBAAIoF,QAAS,GACVxF,EAAW,kBAAC,IAAD,CAAeR,UAAU,SAAW,kBAAC,IAAD,CAAgBA,UAAU,SAC1E,gCAASuC,EAASb,OAEpB,wBAAI1B,UAAU,4BAA2B,gCAASiG,EAAQC,OAAOH,MAElEvF,GAAY,oCACV+B,EAASf,MAAMC,KAAI,SAAA6B,GAAI,OAAI,kBAAC,EAAD,CAAUf,SAAUA,EAAUe,KAAMA,EAAM6C,IAAK7C,EAAKZ,QAC/EH,EAASO,QACV,4BACE,wBAAIkD,QAAS,GACX,4BAAQhG,UAAU,iCAAiCE,QAjBzC,WAAQ0F,EAAQtB,SAAS,CAACnC,KAAM,UAkBxC,kBAAC,IAAD,MAAS,0BAAMnC,UAAU,gBAAhB,cAQfoG,EAAU,IAAIC,KAAKC,aAAa,KAAM,CAACC,sBAAuB,IAC9DN,EAAU,IAAII,KAAKC,aAAa,KAAM,CAACC,sBAAuB,EAAGC,sBAAuB,IAIxFC,EAAW,SAAC,GAAqC,IAApClE,EAAmC,EAAnCA,SAAUe,EAAyB,EAAzBA,KACpBgB,EAAYuB,qBAAWzB,GAAvBE,SACDoC,EAAc5C,EAAcR,GAG5BqD,EADarD,EAAKxB,MAAM,GAAKwB,EAAKxB,MAAM,GAAKwB,EAAKxB,MAAM,IAC7B,GAM3B8E,EAAY,SAACjD,EAAeF,GAAoBa,EAAS,CAACnC,KAAM,OAAQwB,QAAOF,QAAOP,WAAYX,EAASG,GAAIU,OAAQE,EAAKZ,MAIlI,OAAQ,4BACN,wBAAI1C,UAAU,gBACXsD,EAAKR,OACJ,yBAAK9C,UAAU,mBACb,2BAAOA,UAAU,+BAA+B6G,aAAcvD,EAAK5B,KAAMiD,SAAU,SAAAmC,GAAE,OAZ1ErD,EAYwFqD,EAAGhG,OAAO2C,WAZ9Ea,EAAS,CAACnC,KAAM,OAAQsB,QAAOP,WAAYX,EAASG,GAAIU,OAAQE,EAAKZ,KAA1F,IAACe,KAaX,4BAAQzD,UAAU,qCAAqCE,QAP9C,WAAQoE,EAAS,CAACnC,KAAM,SAAUe,WAAYX,EAASG,GAAIU,OAAQE,EAAKZ,OAQ/E,kBAAC,IAAD,CAAK/B,MAAO,CAACD,aAAc,WAG/B4C,EAAK5B,MAET,4BACE,kBAAC,EAAD,CAAagB,GAAG,WAAWe,MAAOH,EAAKzB,SAAU8C,SAnB/B,SAAClB,GAAoBa,EAAS,CAACnC,KAAM,WAAYsB,QAAOP,WAAYX,EAASG,GAAIU,OAAQE,EAAKZ,SAqBlH,4BACE,kBAAC,EAAD,CAAaA,GAAG,iBAAiBe,MAAOH,EAAKV,eAAgB+B,SArBrC,SAAClB,GAAoBa,EAAS,CAACnC,KAAM,iBAAkBsB,QAAOP,WAAYX,EAASG,GAAIU,OAAQE,EAAKZ,SAuB9H,wBAAI1C,UAAU,4BACXsD,EAAKR,OACJ,6BACE,kBAAC,EAAD,CAAaJ,GAAG,eAAee,MAAOH,EAAK1B,aAAc+C,SAzBvC,SAAClB,GAAoBa,EAAS,CAACnC,KAAM,eAAgBsB,QAAOP,WAAYX,EAASG,GAAIU,OAAQE,EAAKZ,MAyB9BkC,IAAKtB,EAAKV,kBAElGwD,EAAQF,OAAO5C,EAAK1B,eACxB,wBAAI5B,UAAU,4BACZ,kBAAC,IAAD,CAAuB+G,QAAQ,UAAUC,QAAQ,MAAMC,SAAS,KAAKC,KAAK,KACnDC,QAASR,EAAYhC,SA5B/B,WAAQL,EAAS,CAACnC,KAAM,KAAMe,WAAYX,EAASG,GAAIU,OAAQE,EAAKZ,SA8BnF,4BACE,kBAAC,EAAD,CAAaA,GAAG,KAAKe,MAAOH,EAAKxB,MAAM,GAAI6C,SAAU,SAAApD,GAAC,OAAIqF,EAAU,EAAGrF,IAAIqD,IAAK,MAElF,4BACE,kBAAC,EAAD,CAAalC,GAAG,KAAKe,MAAOH,EAAKxB,MAAM,GAAI6C,SAAU,SAAApD,GAAC,OAAIqF,EAAU,EAAGrF,IAAIqD,IAAK,KAElF,4BACE,kBAAC,EAAD,CAAalC,GAAG,KAAKe,MAAOH,EAAKxB,MAAM,GAAI6C,SAAU,SAAApD,GAAC,OAAIqF,EAAU,EAAGrF,IAAIqD,IAAK,KAElF,wBAAI5E,UAAU,4BAA4BiG,EAAQC,OAAOQ,MAQvDU,EAAW,SAAC,GAAiC,IAAhC/F,EAA+B,EAA/BA,WACX0E,EAAQ7B,EAAoB7C,GAClC,OAAQ,wBAAIrB,UAAU,mBACpB,wBAAIgG,QAAS,GACX,0CAEF,wBAAIhG,UAAU,4BAA2B,gCAASiG,EAAQC,OAAOH,OAI/DsB,EAAc,WAClB,OAAQ,4BACN,yCACA,wBAAI1G,MAAO,CAAC2G,MAAO,UAAnB,YACA,wBAAI3G,MAAO,CAAC2G,MAAO,UAAnB,kBAA4C,6BAA5C,OACA,wBAAI3G,MAAO,CAAC2G,MAAO,UAAnB,gBAA0C,6BAA1C,OACA,wBAAI3G,MAAO,CAAC2G,MAAO,OAAQC,OAAQ,OAAnC,cACA,wBAAI5G,MAAO,CAAC2G,MAAO,SAAnB,UAAmC,6BAAnC,WAAgD,6BAAhD,QAA0D,6BAA1D,SACA,wBAAI3G,MAAO,CAAC2G,MAAO,SAAnB,UAAmC,6BAAnC,WAAgD,6BAAhD,SAA2D,6BAA3D,SACA,wBAAI3G,MAAO,CAAC2G,MAAO,SAAnB,QAAiC,6BAAjC,WAA8C,6BAA9C,SAAyD,6BAAzD,QACA,wBAAI3G,MAAO,CAAC2G,MAAO,UAAnB,eAAyC,6BAAzC,mBAIWE,EAvID,SAAC,GAA6B,IAA5BnG,EAA2B,EAA3BA,WAEd,OAAQ,2BAAOrB,UAAU,+CACvB,+BACE,kBAAC,EAAD,OAEF,+BACGqB,EAAWI,KAAI,SAAAc,GAAc,OAAQ,kBAAC,EAAD,CAAYA,SAAUA,EAAU4D,IAAK5D,EAASG,QACpF,kBAAC,EAAD,CAAUrB,WAAYA,OCjBfoG,EAAkB,WAAO,IAAD,EACT5B,qBAAWzB,GAA9BnC,EAD4B,EAC5BA,MAAOqC,EADqB,EACrBA,SAKd,OACE,oCACE,6BACGrD,EAAYQ,KAAI,SAACF,EAAGoC,GAAJ,OACf,4BAAQwC,IAAKxC,EAAO3D,UAAU,oCAAoCE,QAAS,WAPtCoE,EAAS,CAACnC,KAAM,SAAUC,aAO2BuB,MACvFpC,EAAEG,KAAK,6BAAMH,EAAElB,gBAEnB4B,EAAMb,SACP,4BAAQpB,UAAU,sCAAsCE,QAV9C,WAAQoE,EAAS,CAACnC,KAAM,YAUlC,QAA+E,6BAA/E,eAEDF,EAAMb,SACP,kBAAC,EAAD,CAAOC,WAAYY,EAAMb,QAAQC,e,QCR1BqG,EAAS,uCAAG,WAAOC,GAAP,iBAAAC,EAAA,sEACNC,MAAM,wBAAyB,CAC9CC,OAAQ,OACRC,QAAS,CAAC,eAAgB,oBAC1BC,KAAMC,KAAKC,UAAUP,KAJA,cACjBQ,EADiB,gBAMAA,EAAGC,OANH,cAMjBC,EANiB,yBAOhBA,GAPgB,2CAAH,sDAUTC,EAAS,uCAAG,WAAO5F,GAAP,iBAAAkF,EAAA,sEACNC,MAAM,sBAAD,OAAuBnF,GAAM,CACjDoF,OAAQ,OACRC,QAAS,CAAC,eAAgB,oBAC1BC,KAAM,KAJe,cACjBG,EADiB,gBAMAA,EAAGC,OANH,cAMjBC,EANiB,yBAOhBA,GAPgB,2CAAH,sDAWTE,EAAQ,SAACC,GACpB,OAAO,IAAIC,SAAQ,SAAAC,GAAO,OAAIC,WAAWD,EAASF,O,gBCRrC7I,EAfC,SAAC,GAAuB,IAAtB+C,EAAqB,EAArBA,GAAIkG,EAAiB,EAAjBA,KACpB,OACE,kBAACC,EAAA,EAAD,CACEC,UAAU,OACVC,QACE,kBAACC,EAAA,EAAD,CAAStG,GAAIA,GACX,yBAAK1C,UAAU,cAAc4I,KAGjC,kBAAC,IAAD,CAAQ5I,UAAU,eAAeW,MAAO,CAACsI,OAAQ,Y,QCFjDC,EAAkB,SAAC,GAA6B,EAA5BzF,MAA6B,IAAtBkB,EAAqB,EAArBA,SAAqB,EAC1B9E,mBAAS,IADiB,mBAC7CsJ,EAD6C,KACtCC,EADsC,KAE9CC,EAAUC,iBAAyB,MAEzCrE,qBAAU,WACR,IAAMsE,EAAUF,EAAQG,QAClBC,EAAe,IAAIC,OAAOC,KAAKC,OAAOC,aAAaN,EAAS,CAACO,MAAO,CAAC,aAY3EL,EAAaM,YAAY,iBAVE,WACzB,IAAMC,EAAQP,EAAaQ,WAC3B,GAAID,EAAME,mBAAqBF,EAAMG,SAAU,CAC7C,IAAMC,EAAUJ,EAAME,kBAChBG,EAAS,CAACC,IAAKN,EAAMG,SAASI,SAASD,MAAOE,IAAKR,EAAMG,SAASI,SAASC,OACjFpB,EAASgB,GACTzF,EAAS,CAACyF,UAASC,kBAOzB,IAIMI,EAAe,WAEnBC,EAAavB,GAAO,SAACwB,GACnB,IAAMlH,EAAQ,CAAC2G,QAASO,EAAIP,QAASC,OAAQM,EAAIN,QACjD1F,EAASlB,MAEX2F,EAAS,KAOX,OACE,yBAAKpJ,UAAU,eACb,2BAAOA,UAAU,eACV4K,IAAKvB,EACL5F,MAAO0F,EACPxE,SAAU,SAACmC,GAAD,OAtBCvF,EAsBoBuF,EAAGhG,OAAO2C,WArBlD2F,EAAS7H,GADU,IAACA,GAuBXsJ,QAVS,SAAC/D,GACJ,UAAXA,EAAGX,KAAmBsE,OAUxB,yBAAKzK,UAAU,sBACb,4BAAQA,UAAU,4BAA4B8K,KAAK,SAAS5K,QAASuK,GAArE,aASFM,EAAU,SAAC,EAAoBC,GAAyC,IAA5DV,EAA2D,EAA3DA,IAAKE,EAAsD,EAAtDA,KAEN,IAAId,OAAOC,KAAKsB,UACtBF,QAAQ,CAAC,SAAY,CAACT,MAAKE,SAAO,SAACU,EAASC,GACnD,GAAIA,IAAWzB,OAAOC,KAAKyB,eAAeC,IAAMH,EAAQ,GAAI,CAC1D,IAAMd,EAAUc,EAAQ,GAAGhB,kBAC3Bc,EAASZ,GAEX,MAAO,OAILM,EAAe,SAACvB,EAAe6B,IAEpB,IAAItB,OAAOC,KAAKsB,UACtBF,QAAQ,CAACX,QAASjB,IAAQ,SAAC+B,EAASC,GAC3C,GAAIA,IAAWzB,OAAOC,KAAKyB,eAAeC,IAAMH,EAAQ,GAAI,CAC1D,IAAMb,EAASa,EAAQ,GAAGf,SAASI,SAC7Be,EAAOJ,EAAQ,GAAGhB,kBACxBc,EAAS,CAACZ,QAASkB,EAAMjB,OAAQ,CAACC,IAAKD,EAAOC,MAAOE,IAAKH,EAAOG,SAEnE,MAAQ,CAACF,IAAK,EAAGE,IAAK,OAIpBe,EAAM,SAAC,GAA8B,IAA7B9H,EAA4B,EAA5BA,MAAOkB,EAAqB,EAArBA,SAAqB,EACXlB,EAAtB4G,OAASC,EADwB,EACxBA,IAAKE,EADmB,EACnBA,IAarB,OACE,kBAAC,IAAD,CAAWgB,OAAQ,CAAClB,MAAKE,OAAMiB,KAAM,EAAGC,kBAAmB,CAACzC,OAAQ,SACzD/I,QAAS,SAAA4G,GAAE,OARR,SAACA,GACf,IAAMuD,EAAS,CAACC,IAAKxD,EAAG6E,OAAOrB,MAAOE,IAAK1D,EAAG6E,OAAOnB,OACrDO,EAAQV,GAAQ,SAACD,GACfzF,EAAS,CAACyF,UAASC,cAKKnK,CAAQ4G,KAChC,kBAAC,IAAD,CAAQ8E,SAAU,CAACtB,MAAKE,OAAMqB,WAAW,EACjCC,UAAW,SAAAhF,GAAE,OAhBP,SAACA,GACjB,IAAMuD,EAAS,CAACC,IAAKxD,EAAG6E,OAAOrB,MAAOE,IAAK1D,EAAG6E,OAAOnB,OACrDO,EAAQV,GAAQ,SAACD,GACfzF,EAAS,CAACyF,UAASC,cAaMyB,CAAUhF,QAKnCiF,GAAiB,SAAC,GAAD,IAAEtI,EAAF,EAAEA,MAAOkB,EAAT,EAASA,SAAT,OACrB,kBAAC,EAAD,CAAKlB,MAAOA,EAAOkB,SAAUA,KAWhBqH,GARQ,SAAC,GAA8B,IAA7BvI,EAA4B,EAA5BA,MAAOkB,EAAqB,EAArBA,SAC9B,OAAQ,6BACN,kBAAC,EAAD,CAAiBlB,MAAOA,EAAOkB,SAAUA,IACzC,yBAAK3E,UAAU,SACf,kBAAC,GAAD,CAAgByD,MAAOA,EAAOkB,SAAUA,MCrGtCsH,GAAQ,SAAC,GAAgF,IAA/EC,EAA8E,EAA9EA,MAAOxJ,EAAuE,EAAvEA,GAAIyJ,EAAmE,EAAnEA,YAAaC,EAAsD,EAAtDA,KAAMC,EAAgD,EAAhDA,IAAK5I,EAA2C,EAA3CA,MAAO6I,EAAoC,EAApCA,SAAU3H,EAA0B,EAA1BA,SAA0B,EAClE9E,mBAAS4D,EAAMoB,YADmD,mBACrF5C,EADqF,KAC9E6C,EAD8E,OAElEjF,oBAAS,GAFyD,mBAErFkF,EAFqF,KAE9EC,EAF8E,KAI5FC,qBAAU,WACRH,EAASrB,EAAMoB,cACd,CAACpB,IAEJ,IAiBMyB,EAAC,mCAA+BH,EAAQ,aAAe,IAE7D,OACE,yBAAK/E,UAAU,kBACb,yBAAKA,UAAU,oBACb,2BAAOA,UAAU,kBAAkBkM,IAErC,yBAAKlM,UAAU,SACb,yBAAKA,UAAU,eACb,2BAAOA,UAAWkF,EACXxD,KAAMgB,EACNyJ,YAAaA,EACbG,SAAUA,EACV7I,MAAOxB,EACP0C,SAAU,SAACQ,GAAD,OA/BJ,SAACA,GACpB,IAAMC,EAAWD,EAAErE,OAAO2C,MAC1BqB,EAASM,GACTJ,GAAS,GA4BqBK,CAAaF,IAC9BG,OAAQ,SAACH,GAAD,OA1BJ,SAACA,GAClB,IAAMC,EAAWD,EAAErE,OAAO2C,MAC1BqB,EAASM,GACT,IAAMG,EAAIC,OAAOJ,GACZK,MAAMF,GAGTP,GAAS,GAFTL,EAASY,GAqBiBG,CAAWP,MAChCiH,GACD,yBAAKpM,UAAU,sBACb,yBAAKA,UAAU,oBAAoBoM,MAIxCC,GACD,yBAAKrM,UAAU,6CACb,kBAAC,EAAD,CAAS0C,GAAE,UAAKA,EAAL,QAAekG,KAAMyD,OAWlCE,GAAY,SAAC,GAA+B,IAA9BC,EAA6B,EAA7BA,QAClB,OACE,uBAAGrG,IAAKqG,EAASxM,UAAU,oBACzB,kBAAC,IAAD,CAASA,UAAU,QACnB,0BAAMA,UAAU,gBAAgBwM,KAOhCC,GAAc,CAAC,SAAU,WAAY,WACrCC,GAAiB,CAAC,iBAAkB,qBAGpCC,GAAe,CACnBpC,SAAU,CACRF,OAAQ,CAACC,IAAK,UAAWE,IAAK,WAC9BJ,QAAS,WAEXwC,aAAc,EAEdC,UAAW,EACXC,aAAc,EACdC,SAAU,IACVC,SAAU,EACVC,OAAQ,KACRC,YAAa,IACbC,cAAe,IACfC,cAAe,IAEfC,SAAUZ,GAAY,GACtBa,YAAaZ,GAAe,IAMxBa,GAAoB,SAAC5F,EAAcvG,GACvC,MAAO,CACLoM,SAAU7F,EAAM4C,SAASF,OAAOC,IAChCmD,UAAW9F,EAAM4C,SAASF,OAAOG,IACjCJ,QAASzC,EAAM4C,SAASH,QACxBwC,aAAcjF,EAAMiF,aAEpBC,UAAWlF,EAAMkF,UACjBC,aAAcnF,EAAMmF,aACpBC,SAAUpF,EAAMoF,SAChBC,SAAUrF,EAAMqF,SAChBC,OAAQtF,EAAMsF,OACdC,YAAavF,EAAMuF,YACnBC,cAAexF,EAAMwF,cACrBC,cAAezF,EAAMyF,cAErBC,SAAU1F,EAAM0F,SAChBC,YAAa3F,EAAM2F,YAEnBI,UAAWvM,EAAiBC,KAI1BuM,GAAgB,SAAChG,EAAcvG,GACnC,IAAMI,EAAQJ,EAAQC,WAAWC,SAAQ,SAAAC,GAAC,OAAIA,EAAEC,SAC1CoM,EAAS,GAITC,EAAKrM,EAAMC,KAAI,SAAAF,GAAC,OAAIA,EAAEO,MAAM,MAAIgM,MAAK,SAAAvM,GAAC,OAAIA,EAAI,MAC9CwM,EAAKvM,EAAMC,KAAI,SAAAF,GAAC,OAAIA,EAAEO,MAAM,MAAIgM,MAAK,SAAAvM,GAAC,OAAIA,EAAI,KAC9CyM,EAAKxM,EAAMC,KAAI,SAAAF,GAAC,OAAIA,EAAEO,MAAM,MAAIgM,MAAK,SAAAvM,GAAC,OAAIA,EAAI,KAWpD,OAVIsM,GAAME,GAAMC,IAAMJ,EAAOK,KAAK,uDAGpB/J,EAAoB9C,EAAQC,YAT9B,MAUOuM,EAAOK,KAAK,oBAGrBzM,EAAMsM,MAAK,SAAAvM,GAAC,OAAIA,EAAEK,aAAeL,EAAEqB,eAbjC,SAcHgL,EAAOK,KAAK,2EAEdL,GAIH9L,GAAQoM,MAAMC,KAAK,CAAC7L,OAAQ,KAAK,SAACnC,EAAGiO,GAAJ,OAAUA,KA4OlCC,GA1OA,WAAO,IAAD,EACOxO,mBAAS8M,IADhB,mBACZhF,EADY,KACL2G,EADK,KAGbC,EAAmB1I,qBAAWzB,GAHjB,EAKavE,mBAAS,GALtB,mBAKZ2O,EALY,KAKFC,EALE,OAMC5O,mBAAwB,MANzB,mBAMZ6C,EANY,KAMRgM,EANQ,OAOK7O,oBAAS,GAPd,mBAOZ8O,EAPY,KAONC,EAPM,OAQO/O,oBAAS,GARhB,mBAQZgP,EARY,KAQLC,EARK,OAUSjP,mBAAmB,IAV5B,mBAUZ+N,EAVY,KAUJmB,EAVI,KAYbpK,EAAW,SAAClB,GAChB,IAAMyB,EAAC,eAAOyC,EAAP,GAAiBlE,GACxB6K,EAASpJ,IAGL8J,EAAO,uCAAG,kCAAApH,EAAA,yDAERqH,EAAatB,GAAchG,EAAO4G,EAAiBtM,MAAMb,SACzD8N,EAAgC,IAAtBD,EAAW3M,OAC3ByM,EAAUE,GACLC,EALS,wDAQdJ,GAAS,GACTL,EAAY,GAGZG,GAAQ,GACFO,EAAQ5B,GAAkB5F,EAAO4G,EAAiBtM,MAAMb,SAbhD,UAcGsG,EAAUyH,GAdb,QAcRhH,EAdQ,OAeduG,EAAMvG,EAAGzF,IAfK,4CAAH,qDAkBbuC,qBAAU,WACR,GAAW,OAAPvC,EAAJ,CAEA,IAAI0M,GAAS,EAuBb,OArBS,uCAAG,gCAAAxH,EAAA,sDAENyH,EAAK,EACLC,EAAI,EAHE,YAIHD,EAAK,KAJF,qBAKJD,EALI,iEAMF7G,EAAM,KANJ,uBAOSD,EAAU5F,GAPnB,UAOFyF,EAPE,OAQRmH,EAAIC,KAAK3K,IAAI0K,EAAGnH,EAAGqG,UACnBC,EAAYa,KACM,cAAdnH,EAAGgD,QAA0BmE,GAAK,KAV9B,qDAWRD,IAXQ,uBAeVP,GAAS,GACTU,OAAOC,KAAP,iBAAsB/M,GAAM,UAhBlB,4CAAH,oDAmBTgN,GAEO,WACLN,GAAS,MAEV,CAAC1M,IAGJuC,qBACE,WAAQ8J,EAAU,MAClB,CAACR,EAAiBtM,MAAMb,QAAQsB,KAGlC,IAxEmB,EA4EUiF,EAAM4C,SAA5BF,OAASC,EA5EG,EA4EHA,IAAKE,EA5EF,EA4EEA,IACfmF,EAAgBrF,EAAIsF,QAAQ,GAAK,KAAOpF,EAAIoF,QAAQ,GAE1D,OAAQ,oCACJ,yBAAK5P,UAAU,OAAO6P,SAAU,SAAA/I,GAAE,OAAIA,EAAGgJ,mBAEvC,kCACE,+CAEA,kBAAC,GAAD,CAAgBrM,MAAOkE,EAAM4C,SAAU5F,SAAU,SAAApD,GAAC,OAAIoD,EAAS,CAAC4F,SAAUhJ,OAE1E,yBAAKvB,UAAU,kBACb,yBAAKA,UAAU,oBACb,2BAAOA,UAAU,kBAAjB,YAEF,yBAAKA,UAAU,SACb,2BAAO8K,KAAK,OAAOiF,UAAQ,EAAC/P,UAAU,yBAAyB0C,GAAG,WAAWe,MAAOkE,EAAM4C,SAASH,WAErG,yBAAKpK,UAAU,oBACb,2BAAOA,UAAU,kBAAjB,aAEF,yBAAKA,UAAU,SACb,2BAAO8K,KAAK,OAAOiF,UAAQ,EAAC/P,UAAU,yBAAyB0C,GAAG,WAAWe,MAAOkM,OAM1F,kCACE,wDAEA,4DACA,yBAAK3P,UAAU,kBACb,yBAAKA,UAAU,oBACb,2BAAOA,UAAU,kBAAjB,sBAEF,yBAAKA,UAAU,SACb,4BAAQA,UAAU,eACV6G,aAAcc,EAAMkF,UACpBlI,SAAU,SAAAmC,GAAE,OAAInC,EAAS,CAACkI,UAAWrH,OAAOsB,EAAGhG,OAAO2C,WAC3D3B,GAAML,KAAI,SAAAF,GAAC,OAAI,4BAAQ4E,IAAK5E,EAAGkC,MAAOlC,GAAvB,UAA8BA,EAA9B,cAItB,yBAAKvB,UAAU,kBACb,yBAAKA,UAAU,oBACb,2BAAOA,UAAU,kBAAjB,wBAEF,yBAAKA,UAAU,SACb,4BAAQA,UAAU,eACV6G,aAAcc,EAAMmF,aACpBnI,SAAU,SAAAmC,GAAE,OAAInC,EAAS,CAACmI,aAActH,OAAOsB,EAAGhG,OAAO2C,WAC9D3B,GAAML,KAAI,SAAAF,GAAC,OAAI,4BAAQ4E,IAAK5E,EAAGkC,MAAOlC,GAAIA,SAKjD,kBAAC,GAAD,CAAO2K,MAAM,sBAAsBE,KAAK,YAAS1J,GAAG,WAC7Ce,MAAOkE,EAAMoF,SACbpI,SAAU,SAAApD,GAAC,OAAIoD,EAAS,CAACoI,SAAUxL,OAG1C,kDAEA,yBAAKvB,UAAU,kBACb,yBAAKA,UAAU,oBACb,2BAAOA,UAAU,kBAAjB,iBAEF,yBAAKA,UAAU,SACb,4BAAQA,UAAU,eACV6G,aAAcc,EAAM0F,SACpB1I,SAAU,SAAAmC,GAAE,OAAInC,EAAS,CAAC0I,SAAUvG,EAAGhG,OAAO2C,UACnDgJ,GAAYhL,KAAI,SAAAF,GAAC,OAAI,4BAAQ4E,IAAK5E,EAAGkC,MAAOlC,GAAIA,SAKvD,kBAAC,GAAD,CAAO2K,MAAM,eAAeE,KAAK,UAAU1J,GAAG,WACvCe,MAAOkE,EAAMqF,SACbrI,SAAU,SAAApD,GAAC,OAAIoD,EAAS,CAACqI,SAAUzL,OAE1C,kBAAC,GAAD,CAAO2K,MAAM,oBAAoBE,KAAK,OAAO1J,GAAG,SAAS2J,IAAI,yCACtD5I,MAAOkE,EAAMsF,OACbtI,SAAU,SAAApD,GAAC,OAAIoD,EAAS,CAACsI,OAAQ1L,OAExC,yBAAKvB,UAAU,kBACb,yBAAKA,UAAU,oBACb,2BAAOA,UAAU,kBAAjB,oBAEF,yBAAKA,UAAU,SACb,4BAAQA,UAAU,eACV6G,aAAcc,EAAM2F,YACpB3I,SAAU,SAAAmC,GAAE,OAAInC,EAAS,CAAC2I,YAAaxG,EAAGhG,OAAO2C,UACtDiJ,GAAejL,KAAI,SAAAF,GAAC,OAAI,4BAAQ4E,IAAK5E,EAAGkC,MAAOlC,GAAIA,SAK1D,kBAAC,GAAD,CAAO2K,MAAM,oBAAoBE,KAAK,YAAS1J,GAAG,cAC3Ce,MAAOkE,EAAMuF,YACbvI,SAAU,SAAApD,GAAC,OAAIoD,EAAS,CAACuI,YAAa3L,OAE7C,kBAAC,GAAD,CAAO2K,MAAM,kCAAkCE,KAAK,OAAO1J,GAAG,cAAc2J,IAAI,6BACzE5I,MAAOkE,EAAMwF,cACbxI,SAAU,SAAApD,GAAC,OAAIoD,EAAS,CAACwI,cAAe5L,OAE/C,kBAAC,GAAD,CAAO2K,MAAM,2BAA2BE,KAAK,OAAO1J,GAAG,cAChDe,MAAOkE,EAAMyF,cACbzI,SAAU,SAAApD,GAAC,OAAIoD,EAAS,CAACyI,cAAe7L,QAIjD,kCACE,4DAEA,kBAAC,GAAD,CAAO2K,MAAM,gBAAgBE,KAAK,SAAS1J,GAAG,eACvCe,MAAOkE,EAAMiF,aACbjI,SAAU,SAAApD,GAAC,OAAIoD,EAAS,CAACiI,aAAcrL,QAGhD,kCACE,2DAEA,kBAAC,EAAD,OAGF,kCACE,oDAECqM,EAAOnM,KAAI,SAAAF,GAAC,OAAI,kBAAC,GAAD,CAAWiL,QAASjL,OAErC,4BAAQvB,UAAU,kBAAkBE,QAAS8O,GAA7C,eAKJ,kBAACgB,EAAA,EAAD,CAAOlQ,KAAM6O,EAAMsB,UAAQ,EAACC,OA5Ib,WACbrB,GAASD,GAAQ,KA4IjB,kBAACoB,EAAA,EAAMG,OAAP,CAAcC,YAAavB,GACzB,kBAACmB,EAAA,EAAMK,MAAP,KAAexB,EAA2B,YAAnB,mBAEzB,kBAACmB,EAAA,EAAMM,KAAP,KACIzB,EAMA,oCACE,6BACE,uBAAG5O,KAAI,iBAAYyC,GAAM5B,OAAO,UAAhC,kBAPJ,yBAAKd,UAAU,YACb,yBAAKA,UAAU,qEACVuQ,KAAK,cAAcC,gBAAe,EAAGC,gBAAe,IAAKC,gBAAelC,EACxE7N,MAAO,CAAC2G,MAAM,GAAD,OAAKkH,EAAL,aCtXjBmC,GAtBD,WACZ,OACE,oCACE,yBAAK3Q,UAAU,QACb,8CACA,oSACwQ,uBAAGC,KAAK,gCAAR,sBADxQ,uHACyb,uBAAGA,KAAK,0BAAR,SADzb,SACye,uBAAGA,KAAK,0BAAR,uDADze,uDACqnB,uBAAGA,KAAK,sEAAR,8BADrnB,QACquB,uBAAGA,KAAK,4BAAR,iBADruB,6HACm5B,uBAAGA,KAAK,kCAAR,2BADn5B,KAIA,2BACE,+CADF,0rCAIF,yBAAKD,UAAU,eACb,uBAAGC,KAAK,gCACN,yBAAK2Q,IAAI,SAASC,IAAI,cC2BjBC,GAnCH,WACV,OACE,oCACE,4BAAQ9Q,UAAU,iCAChB,yBAAK0C,GAAG,SAAS1C,UAAU,sCACzB,uBAAGC,KAAK,+CAA+Ca,OAAO,UAC5D,yBAAK8P,IAAI,0BAA0BC,IAAI,kBAAkBnO,GAAG,oBAC9D,uBAAGzC,KAAK,+CAA+Ca,OAAO,UAC5D,yBAAK8P,IAAI,iBAAiBC,IAAI,QAAQnO,GAAG,WAC3C,uBAAGzC,KAAK,yBAAyBa,OAAO,UACtC,yBAAK8P,IAAI,iBAAiBC,IAAI,QAAQnO,GAAG,WAC3C,uBAAGzC,KAAK,+BAA+Ba,OAAO,UAC5C,yBAAK8P,IAAI,iBAAiBC,IAAI,QAAQnO,GAAG,WAC3C,uBAAGzC,KAAK,+BAA+Ba,OAAO,UAC5C,yBAAK8P,IAAI,uBAAuBC,IAAI,cAAcnO,GAAG,mBAI3D,0BAAM1C,UAAU,yDACd,kBAAC,EAAD,MACA,6BACA,kBAAC,EAAD,KACE,kBAAC,GAAD,OAEF,6BACA,kBAAC,GAAD,OAGF,gCACE,yBAAKA,UAAU,OAAM,uBAAGC,KAAK,+BAAR,2BAA2D,IAAI8Q,MAAOC,mBC1B/EC,QACW,cAA7BzB,OAAOjF,SAAS2G,UAEe,UAA7B1B,OAAOjF,SAAS2G,UAEhB1B,OAAOjF,SAAS2G,SAASC,MACvB,2DCZNC,IAASC,OACP,kBAAC,IAAMC,WAAP,KACE,kBAAC,GAAD,OAEFC,SAASC,eAAe,SDiIpB,kBAAmBC,WACrBA,UAAUC,cAAc7C,MACrB8C,MAAK,SAAAC,GACJA,EAAaC,gBAEdC,OAAM,SAAA/M,GACLgN,QAAQhN,MAAMA,EAAMyH,c","file":"static/js/main.def86c5d.chunk.js","sourcesContent":["import React, {ReactNode, useState} from 'react'\nimport {GoChevronDown, GoChevronRight} from 'react-icons/go'\n\n\ntype InfoTipProps = { children: ReactNode }\n\nconst InfoTip = ({children}: InfoTipProps) => {\n const [show, setShow] = useState(false)\n\n return (\n <>\n setShow(!show)}>[more info]\n {show &&\n
{children}
}\n )\n}\n\n\ntype StepTipProps = {\n title: string\n description: string\n children: ReactNode\n}\n\nconst StepTip = ({children, description, title}: StepTipProps) => {\n return (\n
  • \n {title} - {description}\n \n {children}\n \n
  • \n )\n}\n\n\ntype CollapsibleSectionProps = {\n title: string,\n children: ReactNode,\n expanded: boolean,\n}\n\nconst CollapsibleSection = ({title, children, expanded}: CollapsibleSectionProps) => {\n const [show, setShow] = useState(expanded)\n const toggle = () => { setShow(!show) }\n const iconStyle = {marginBottom: '3px'}\n\n return (\n <>\n
    \n \n {show ?\n :\n }\n \n {title}\n
    \n {show && children}\n \n )\n}\n\n\nconst Intro = () => {\n return (\n
    \n

    HOMER Powering Health Tool

    \n\n \n

    \n The HOMER Powering Health Tool is a free online model to create initial designs of electric power systems for health care facilities that have no other power supply or have grid electricity available for a predictable period of hours each day. The tool is intended for project managers, engineers and financiers in the energy industry to simplify the design process for such systems. The tool models optimal combinations of power supply options to meet electrical loads of a health facility at least cost based on the given inputs. It compares combinations of grid electricity (if available), batteries (lithium-ion or lead-acid), solar photovoltaics (PV), and generator sets fueled by diesel, gasoline or propane. The model runs entirely online and can be used an unlimited number of times with no need to sign in or download software.\n

    \n
    \n\n \n

    \n Read the guidance note (Word, PDF) for important information on using the tool, including in context of health care facilities responding to COVID-19. Follow the steps below to input data on local energy costs and health care facility electrical loads.\n

    \n
      \n \n

      \n The amount of energy available from the sun is directly related to location. HOMER obtains monthly average solar resource values from a variety of databases at NREL and NASA to synthesize a year of hourly data. These are calculated based on the latitude and longitude of a site and satellite measurements of annual cloud cover.\n

      \n \n\n \n

      \n In areas where the electricity grid is available only part of the day, the scheduling of the grid can have a significant impact on the design of a suitable power supply system. The availability and cost of supply and installation of PV panels, batteries and diesel fuel will vary by location. The default cost values entered here are roughly accurate for much of Africa but should not be relied upon without verification. Grid electricity costs may be estimated from a recent bill (e.g. total cost divided by kilowatt-hours consumed). When calculating the cost of PV, include the cost of all related components (the cost of the panels, installation, mounting frames and other hardware), but not the inverter or batteries, which are sized separately by HOMER. Retail pump prices by country for petrol/gasoline and diesel can be found at https://data.worldbank.org/indicator or https://www.globalpetrolprices.com.\n

      \n \n\n \n

      \n HOMER minimizes the discounted cash flow of the project. The interest rate determines the tradeoff between the initial capital cost and future operating costs. It has a significant effect on the optimal system design. Lower interest rates will favor PV over diesel generators. The real interest rate can be approximated as the difference between a bank's interest rate on loans and the estimated rate of inflation.\n

      \n \n\n \n

      \n The table is populated with common equipment types found in rural health facilities including typical power ratings. The time of day that power is needed and the peak power demand have an impact on the sizing of equipment and the optimal configuration. For the most accurate simulation, this step may require a walk-through of an existing clinic. Note: The tool is not intended to design the health facilities themselves. In all cases, the equipment quantity, power, and hours of use are inputs that should be reviewed and adjusted as needed to meet the needs of a given facility, based on an energy audit for the specific site where possible. If there is no health facility yet, the information provided in the User Guide can inform an estimate of the potential electrical load.\n

      \n \n\n \n

      \n Once you have defined all the necessary inputs HOMER will analyze every possible combination of power supply options that meet the demand.\n

      \n \n
    \n\n

    \n Note: The results will appear as a new page if your browser allows pop-ups or you will have the opportunity to open the results in a new page by clicking on a link after the calculation is complete.\n

    \n \n
    \n
    \n )\n}\n\nexport default Intro\n","import Profiles from './profiles.json'\nimport {EquipmentItem} from './Model'\nimport {v4 as uuidv4} from 'uuid'\n\n\nexport interface Profile {\n id: string,\n name: string,\n description: string,\n categories: Category[],\n}\n\nexport interface Category {\n id: string,\n name: string,\n items: Item[],\n custom?: boolean,\n}\n\nexport interface Item {\n id: string,\n name: string,\n nameplatePower: number,\n averagePower: number,\n d: number,\n quantity: number,\n hours: number[], // [day,evening,night]\n custom?: boolean,\n}\n\n\nexport const blankProfile = Profiles[0]\nexport const allProfiles: Profile[] = Profiles.slice(1)\n\n\nexport const getEquipmentList = (profile: Profile): EquipmentItem[] => {\n return profile.categories.flatMap(x => x.items).map(x => {\n return {\n name: x.name,\n power: x.averagePower,\n quantity: x.quantity,\n hours: x.hours,\n }\n })\n}\n\n\nexport const makeItem = (): Item => {\n return {\n id: uuidv4(),\n name: 'Custom Equipment',\n nameplatePower: 0,\n averagePower: 0,\n d: 1.0,\n quantity: 1,\n hours: [0, 0, 0],\n custom: true,\n }\n}\n\n\n// TODO: find item and category index by ID\n","import {Category, Item, makeItem, Profile, allProfiles, blankProfile} from './Equipment'\n\n\nexport const initialEquipmentModel: EquipmentModel = {\n profile: blankProfile,\n}\n\nexport interface EquipmentModel {\n profile: Profile\n}\n\nexport type EquipmentAction\n = { kind: 'select', profileIndex: number }\n | { kind: 'new' }\n | { kind: 'delete', categoryId: string, itemId: string }\n | { kind: 'clear' }\n // update items fields\n | { kind: 'name', value: string, categoryId: string, itemId: string }\n | { kind: 'nameplatePower', value: number, categoryId: string, itemId: string }\n | { kind: 'averagePower', value: number, categoryId: string, itemId: string }\n | { kind: 'quantity', value: number, categoryId: string, itemId: string }\n | { kind: 'on', categoryId: string, itemId: string }\n | { kind: 'hour', index: number, value: number, categoryId: string, itemId: string }\n\n\n// TODO: refactor to use immutable.js to simplify deep updates\nexport const equipmentReducer = (state: EquipmentModel, action: EquipmentAction): EquipmentModel => {\n switch (action.kind) {\n case 'select':\n return {\n ...state,\n profile: allProfiles[action.profileIndex],\n }\n case 'new': {\n const profile = state.profile\n const categoryIndex = profile.categories.length - 1\n const category = profile.categories[categoryIndex]\n const newCategory = {...category, items: category.items.concat([makeItem()])}\n const newProfile = {...profile, categories: replace(profile.categories, categoryIndex, newCategory)}\n return {\n ...state,\n profile: newProfile,\n }\n }\n case 'delete': {\n const profile = state.profile\n const categoryIndex = profile.categories.findIndex(x => x.id === action.categoryId)\n const category = profile.categories[categoryIndex]\n const newCategory = {...category, items: category.items.filter(x => x.id !== action.itemId)}\n const newProfile = {...profile, categories: replace(profile.categories, categoryIndex, newCategory)}\n return {\n ...state,\n profile: newProfile,\n }\n }\n case 'clear': {\n const profile = state.profile\n const newCategories = profile.categories.map(category => {\n return {\n ...category,\n items: category.items.map(item => { return {...item, quantity: 0}}),\n }\n })\n const newProfile = {...profile, categories: newCategories}\n return {\n ...state,\n profile: newProfile,\n }\n }\n\n case 'name': {\n const profile = state.profile\n const categoryIndex = profile.categories.findIndex(x => x.id === action.categoryId)\n const category = profile.categories[categoryIndex]\n const itemIndex = category.items.findIndex(x => x.id === action.itemId)\n const item = category.items[itemIndex]\n const newItem = {...item, name: action.value}\n const newCategory = {...category, items: replace(category.items, itemIndex, newItem)}\n const newProfile = {...profile, categories: replace(profile.categories, categoryIndex, newCategory)}\n return {\n ...state,\n profile: newProfile,\n }\n }\n case 'nameplatePower': {\n const profile = state.profile\n const categoryIndex = profile.categories.findIndex(x => x.id === action.categoryId)\n const category = profile.categories[categoryIndex]\n const itemIndex = category.items.findIndex(x => x.id === action.itemId)\n const item = category.items[itemIndex]\n\n const nameplatePower = action.value\n // for not custom items update average power using duty cycle\n const averagePower = item.custom ? item.averagePower : nameplatePower * item.d\n const newItem = {...item, nameplatePower, averagePower}\n const newCategory = {...category, items: replace(category.items, itemIndex, newItem)}\n const newProfile = {...profile, categories: replace(profile.categories, categoryIndex, newCategory)}\n return {\n ...state,\n profile: newProfile,\n }\n }\n case 'averagePower': {\n const profile = state.profile\n const categoryIndex = profile.categories.findIndex(x => x.id === action.categoryId)\n const category = profile.categories[categoryIndex]\n const itemIndex = category.items.findIndex(x => x.id === action.itemId)\n const item = category.items[itemIndex]\n\n // do not update average powr for not custom items\n if (!item.custom) { return state }\n const averagePower = action.value\n const newItem = {...item, averagePower}\n const newCategory = {...category, items: replace(category.items, itemIndex, newItem)}\n const newProfile = {...profile, categories: replace(profile.categories, categoryIndex, newCategory)}\n return {\n ...state,\n profile: newProfile,\n }\n }\n case 'quantity': {\n const profile = state.profile\n const categoryIndex = profile.categories.findIndex(x => x.id === action.categoryId)\n const category = profile.categories[categoryIndex]\n const itemIndex = category.items.findIndex(x => x.id === action.itemId)\n const item = category.items[itemIndex]\n const newItem = {...item, quantity: action.value}\n const newCategory = {...category, items: replace(category.items, itemIndex, newItem)}\n const newProfile = {...profile, categories: replace(profile.categories, categoryIndex, newCategory)}\n return {\n ...state,\n profile: newProfile,\n }\n }\n case 'on': {\n const profile = state.profile\n const categoryIndex = profile.categories.findIndex(x => x.id === action.categoryId)\n const category = profile.categories[categoryIndex]\n const itemIndex = category.items.findIndex(x => x.id === action.itemId)\n const item = category.items[itemIndex]\n const newItem = {...item, hours: [11, 4, 9]}\n const newCategory = {...category, items: replace(category.items, itemIndex, newItem)}\n const newProfile = {...profile, categories: replace(profile.categories, categoryIndex, newCategory)}\n return {\n ...state,\n profile: newProfile,\n }\n }\n case 'hour': {\n const profile = state.profile\n const categoryIndex = profile.categories.findIndex(x => x.id === action.categoryId)\n const category = profile.categories[categoryIndex]\n const itemIndex = category.items.findIndex(x => x.id === action.itemId)\n const item = category.items[itemIndex]\n const newHours = [...item.hours]\n newHours[action.index] = action.value\n const newItem = {...item, hours: newHours}\n const newCategory = {...category, items: replace(category.items, itemIndex, newItem)}\n const newProfile = {...profile, categories: replace(profile.categories, categoryIndex, newCategory)}\n return {\n ...state,\n profile: newProfile,\n }\n }\n\n default:\n return state\n }\n}\n\n\nconst replace = (items: T[], index: number, item: T): T[] => {\n const pre = items.slice(0, index)\n const suf = items.slice(index + 1)\n return pre.concat([item], suf)\n}\n\n\nexport const getItemEnergy = (x: Item): number => x.averagePower * x.quantity * (x.hours[0] + x.hours[1] + x.hours[2]) / 1000\n\nexport const getCategoryEnergy = (x: Category): number => x.items\n .map(x => getItemEnergy(x))\n .reduce((acc, x) => acc + x, 0)\n\nexport const getCategoriesEnergy = (xs: Category[]): number => xs\n .map(x => getCategoryEnergy(x))\n .reduce((acc, x) => acc + x, 0)\n","import React, {createContext, useReducer} from 'react'\nimport {EquipmentAction, EquipmentModel, equipmentReducer, initialEquipmentModel} from './EquipmentModel'\n\n\ntype EquipmentContextValue = {\n state: EquipmentModel,\n dispatch: React.Dispatch,\n}\n\nexport const EquipmentContext = createContext({state: initialEquipmentModel, dispatch: () => null})\n\nexport const EquipmentProvider: React.FC = ({children}) => {\n const [state, dispatch] = useReducer(equipmentReducer, initialEquipmentModel)\n return (\n \n {children}\n \n )\n}\n","import React, {useEffect, useState} from 'react'\n\n\ntype FieldProps = {\n id: string\n value: number\n onChange: (value: number) => void\n max?: number\n}\n\n\nconst NumberInput = ({id, value, onChange, max}: FieldProps) => {\n const [state, setState] = useState(value.toString())\n const [error, setError] = useState(false)\n\n useEffect(() => {\n setState(value.toString())\n if (max) {\n setError(value > max)\n }\n }, [value])\n\n const handleChange = (e: React.ChangeEvent) => {\n const newState = e.target.value\n setState(newState)\n setError(false)\n }\n\n const handleBlur = (e: React.FocusEvent) => {\n const newState = e.target.value\n setState(newState)\n const n = Number(newState)\n if (!isNaN(n)) {\n if (max) {\n setError(value > max)\n }\n onChange(n)\n } else {\n setError(true)\n }\n }\n\n const s = `form-control form-control-sm ${error ? 'is-invalid' : ''}`\n\n return (\n handleChange(e)}\n onBlur={(e) => handleBlur(e)}/>\n )\n}\n\nexport default NumberInput\n","import './Table.css'\nimport React, {useContext, useState} from 'react'\nimport {Category, Item} from './Equipment'\nimport {GoChevronDown, GoChevronRight, GoPlus, GoX} from 'react-icons/go'\nimport {EquipmentContext} from './EquipmentContext'\nimport NumberInput from './NumberInput'\nimport BootstrapSwitchButton from 'bootstrap-switch-button-react/lib/bootstrap-switch-button-react'\nimport {getCategoriesEnergy, getCategoryEnergy, getItemEnergy} from './EquipmentModel'\n\n\nexport interface TableProp {\n categories: Category[]\n}\n\n\nconst Table = ({categories}: TableProp) => {\n\n return (\n \n \n \n \n {categories.map(category => { return ()})}\n \n \n
    )\n}\n\n\ntype TableGroupProps = { category: Category }\n\nconst TableGroup = ({category}: TableGroupProps) => {\n const context = useContext(EquipmentContext)\n const [expanded, setExpanded] = useState(true)\n const toggle = () => setExpanded(!expanded)\n\n const handleAdd = () => { context.dispatch({kind: 'new'})}\n\n const total = getCategoryEnergy(category)\n\n return (<>\n \n \n {expanded ? : }\n {category.name}\n \n {format1.format(total)}\n \n {expanded && <>\n {category.items.map(item => )}\n {category.custom &&\n \n \n \n \n }\n }\n )\n}\n\nconst format0 = new Intl.NumberFormat('en', {maximumFractionDigits: 0})\nconst format1 = new Intl.NumberFormat('en', {maximumFractionDigits: 1, minimumFractionDigits: 1})\n\ntype TableRowProps = { category: Category, item: Item }\n\nconst TableRow = ({category, item}: TableRowProps) => {\n const {dispatch} = useContext(EquipmentContext)\n const totalEnergy = getItemEnergy(item)\n\n const totalHours = item.hours[0] + item.hours[1] + item.hours[2]\n const isAlwaysOn = totalHours >= 24\n\n const onSetName = (value: string) => { dispatch({kind: 'name', value, categoryId: category.id, itemId: item.id}) }\n const onSetQuantity = (value: number) => { dispatch({kind: 'quantity', value, categoryId: category.id, itemId: item.id}) }\n const onSetNameplatePower = (value: number) => { dispatch({kind: 'nameplatePower', value, categoryId: category.id, itemId: item.id}) }\n const onSetAveragePower = (value: number) => { dispatch({kind: 'averagePower', value, categoryId: category.id, itemId: item.id}) }\n const onSetHour = (index: number, value: number) => { dispatch({kind: 'hour', index, value, categoryId: category.id, itemId: item.id}) }\n const onAlways = () => { dispatch({kind: 'on', categoryId: category.id, itemId: item.id}) }\n const onDelete = () => { dispatch({kind: 'delete', categoryId: category.id, itemId: item.id}) }\n\n return (\n \n {item.custom ?\n
    \n onSetName(ev.target.value)}/>\n \n
    :\n item.name}\n \n \n \n \n \n \n \n \n {item.custom ?\n
    \n \n
    :\n format0.format(item.averagePower)}\n \n \n \n \n onSetHour(0, x)} max={11}/>\n \n \n onSetHour(1, x)} max={4}/>\n \n \n onSetHour(2, x)} max={9}/>\n \n {format1.format(totalEnergy)}\n )\n}\n\ninterface TotalRowProps {\n categories: Category[]\n}\n\nconst TotalRow = ({categories}: TotalRowProps) => {\n const total = getCategoriesEnergy(categories)\n return (\n \n Total\n \n {format1.format(total)}\n )\n}\n\nconst TableHeader = () => {\n return (\n Equipment\n Quantity\n Nameplate Power
    (W)\n Average Power
    (W)\n Always on?\n Daytime
    Hours on
    7:00-
    17:59\n Evening
    Hours on
    18:00-
    21:59\n Night
    Hours on
    22:00-
    6:59\n Total Energy
    (kW·h/day)\n )\n}\n\nexport default Table\n","import React, {useContext} from 'react'\nimport {allProfiles} from './Equipment'\nimport Table from './Table'\nimport {EquipmentContext} from './EquipmentContext'\n\n\nexport const EquipmentEditor = () => {\n const {state, dispatch} = useContext(EquipmentContext)\n\n const onSelect = (profileIndex: number) => { dispatch({kind: 'select', profileIndex}) }\n const onClear = () => { dispatch({kind: 'clear'}) }\n\n return (\n <>\n
    \n {allProfiles.map((x, index) =>\n )}\n {state.profile &&\n }\n
    \n {state.profile &&\n }\n \n )\n}\n","import Model from './Model'\n\n\ninterface CalculateResponse {\n success: boolean,\n id: string,\n error: string | null,\n}\n\ninterface StatusResponse {\n status: string,\n progress: number,\n error: string | null,\n}\n\nexport const calculate = async (model: Model): Promise => {\n const rv = await fetch('api/project/calculate', {\n method: 'POST',\n headers: {'Content-Type': 'application/json'},\n body: JSON.stringify(model),\n })\n const response = await rv.json()\n return response as CalculateResponse\n}\n\nexport const getStatus = async (id: string): Promise => {\n const rv = await fetch(`api/project/status/${id}`, {\n method: 'POST',\n headers: {'Content-Type': 'application/json'},\n body: '',\n })\n const response = await rv.json()\n return response as StatusResponse\n}\n\n// utils\nexport const delay = (ms: number) => {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n","import React, {ReactNode} from 'react'\nimport OverlayTrigger from 'react-bootstrap/OverlayTrigger'\nimport Tooltip from 'react-bootstrap/Tooltip'\nimport {GoInfo} from 'react-icons/go'\n\n\nconst defaultValue = {\n id: '',\n text: '' as ReactNode,\n}\n\ntype Props = typeof defaultValue\n\n\nconst InfoTip = ({id, text}: Props) => {\n return (\n \n
    {text}
    \n \n }>\n \n \n )\n}\n\n\nexport default InfoTip\n","/* global google */\nimport React, {KeyboardEvent, useEffect, useRef, useState} from 'react'\nimport {StepProps} from './Wizard'\nimport {GoogleMap, LoadScript, Marker} from '@react-google-maps/api'\n\n\ninterface Coords {\n lat: number,\n lng: number\n}\n\ninterface Location {\n coords: Coords,\n address: string\n}\n\ntype Props = StepProps\n\n\n// address\n\nconst LocationAddress = ({value, onChange}: Props) => {\n const [query, setQuery] = useState('')\n const inputEl = useRef(null)\n\n useEffect(() => {\n const element = inputEl.current!\n const autocomplete = new google.maps.places.Autocomplete(element, {types: ['address']})\n\n const handlePlaceChanged = () => {\n const place = autocomplete.getPlace()\n if (place.formatted_address && place.geometry) {\n const address = place.formatted_address\n const coords = {lat: place.geometry.location.lat(), lng: place.geometry.location.lng()}\n setQuery(address)\n onChange({address, coords})\n }\n }\n\n autocomplete.addListener('place_changed', handlePlaceChanged)\n })\n\n const handleChange = (x: string) => {\n setQuery(x)\n }\n\n const handleSearch = () => {\n // clear query & search\n findLocation(query, (val: Location) => {\n const value = {address: val.address, coords: val.coords}\n onChange(value)\n })\n setQuery('')\n }\n\n const handleKeyUp = (ev: KeyboardEvent) => {\n if (ev.key === 'Enter') { handleSearch() }\n }\n\n return (\n
    \n handleChange(ev.target.value)}\n onKeyUp={handleKeyUp}/>\n
    \n \n
    \n
    \n )\n}\n\n\n// coords\n\nconst geocode = ({lat, lng}: Coords, complete: (address: string) => void) => {\n // reverse geocoding\n let geocoder = new google.maps.Geocoder()\n geocoder.geocode({'location': {lat, lng}}, (results, status) => {\n if (status === google.maps.GeocoderStatus.OK && results[0]) {\n const address = results[0].formatted_address\n complete(address)\n }\n return ''\n })\n}\n\nconst findLocation = (query: string, complete: (rv: Location) => void) => {\n // geocoding\n let geocoder = new google.maps.Geocoder()\n geocoder.geocode({address: query}, (results, status) => {\n if (status === google.maps.GeocoderStatus.OK && results[0]) {\n const coords = results[0].geometry.location\n const addr = results[0].formatted_address\n complete({address: addr, coords: {lat: coords.lat(), lng: coords.lng()}})\n }\n return ({lat: 0, lng: 0})\n })\n}\n\nconst Map = ({value, onChange}: Props) => {\n const {coords: {lat, lng}} = value\n const onDragEnd = (ev: google.maps.MouseEvent) => {\n const coords = {lat: ev.latLng.lat(), lng: ev.latLng.lng()}\n geocode(coords, (address) => {\n onChange({address, coords})\n })\n }\n const onClick = (ev: google.maps.MouseEvent) => {\n const coords = {lat: ev.latLng.lat(), lng: ev.latLng.lng()}\n geocode(coords, (address) => {\n onChange({address, coords})\n })\n }\n return (\n onClick(ev)}>\n onDragEnd(ev)}/>\n \n )\n}\n\nconst LocationCoords = ({value, onChange}: Props) =>\n \n\n\nconst LocationPicker = ({value, onChange}: Props) => {\n return (
    \n \n
    \n \n
    )\n}\n\nexport default LocationPicker\n","import React, {useContext, useEffect, useState} from 'react'\nimport {EquipmentEditor} from './EquipmentEditor'\nimport Modal from 'react-bootstrap/Modal'\nimport InputModel from './Model'\nimport {calculate, delay, getStatus} from './Service'\nimport {EquipmentContext} from './EquipmentContext'\nimport {getEquipmentList, Profile} from './Equipment'\nimport {GoAlert} from 'react-icons/all'\nimport InfoTip from './InfoTip'\nimport LocationPicker from './LocationPicker'\nimport {getCategoriesEnergy} from './EquipmentModel'\n\n\nexport type StepProps = {\n value: T;\n onChange: (value: T, isValid?: boolean) => void;\n}\n\n\ntype FieldProps = {\n label: string\n id: string\n placeholder?: string\n unit?: string\n tip?: string\n value: number\n disabled?: boolean\n onChange: (value: number) => void\n}\n\n\nconst Field = ({label, id, placeholder, unit, tip, value, disabled, onChange}: FieldProps) => {\n const [state, setState] = useState(value.toString())\n const [error, setError] = useState(false)\n\n useEffect(() => {\n setState(value.toString())\n }, [value])\n\n const handleChange = (e: React.ChangeEvent) => {\n const newState = e.target.value\n setState(newState)\n setError(false)\n }\n\n const handleBlur = (e: React.FocusEvent) => {\n const newState = e.target.value\n setState(newState)\n const n = Number(newState)\n if (!isNaN(n)) {\n onChange(n)\n } else {\n setError(true)\n }\n }\n\n const s = `form-control field-small ${error ? 'is-invalid' : ''}`\n\n return (\n
    \n
    \n \n
    \n
    \n
    \n handleChange(e)}\n onBlur={(e) => handleBlur(e)}/>\n {unit &&\n
    \n
    {unit}
    \n
    }\n
    \n
    \n {tip &&\n
    \n \n
    }\n
    \n )\n}\n\n\ninterface ErrorNoteProps {\n message: string,\n}\n\nconst ErrorNote = ({message}: ErrorNoteProps) => {\n return (\n

    \n \n {message}\n

    \n )\n}\n\n\n// all\nconst fuelOptions = ['Diesel', 'Gasoline', 'Propane']\nconst storageOptions = ['Li-Ion Battery', 'Lead Acid Battery']\n\n\nconst defaultModel = {\n location: {\n coords: {lat: 9.0324919, lng: 6.4341224},\n address: 'Nigeria',\n },\n interestRate: 5,\n\n gridStart: 0,\n gridDuration: 0,\n gridCost: 0.15,\n fuelCost: 1, // Diesel: 1, Gasoline: ?, Propane: ?\n pvCost: 1147,\n storageCost: 432, // Li-Ion Battery: 432, Lead Acid Battery: 270\n converterCost: 608,\n generatorCost: 378,\n\n fuelName: fuelOptions[0],\n storageName: storageOptions[0],\n}\n\n\ntype Model = typeof defaultModel\n\nconst getInputFromModel = (model: Model, profile: Profile): InputModel => {\n return {\n latitude: model.location.coords.lat,\n longitude: model.location.coords.lng,\n address: model.location.address,\n interestRate: model.interestRate,\n\n gridStart: model.gridStart,\n gridDuration: model.gridDuration,\n gridCost: model.gridCost,\n fuelCost: model.fuelCost,\n pvCost: model.pvCost,\n storageCost: model.storageCost,\n converterCost: model.converterCost,\n generatorCost: model.generatorCost,\n\n fuelName: model.fuelName,\n storageName: model.storageName,\n\n equipment: getEquipmentList(profile),\n }\n}\n\nconst validateInput = (model: Model, profile: Profile): string[] => {\n const items = profile.categories.flatMap(x => x.items)\n const errors = []\n const eps = 0.001\n\n // number of hours\n const h1 = items.map(x => x.hours[0]).some(x => x > 11)\n const h2 = items.map(x => x.hours[1]).some(x => x > 4)\n const h3 = items.map(x => x.hours[2]).some(x => x > 9)\n if (h1 || h2 || h3) { errors.push('Incorrect number of hours for some equipment items.')}\n\n // total load > 0\n const total = getCategoriesEnergy(profile.categories)\n if (total < eps) { errors.push('Total load is 0.') }\n\n // average power <= nameplate power\n const p = items.some(x => x.averagePower > x.nameplatePower + eps)\n if (p) { errors.push('Average power is greater than nameplate power for some equipment items.')}\n\n return errors\n}\n\n\nconst hours = Array.from({length: 24}, (_, i) => i)\n\nconst Wizard = () => {\n const [model, setModel] = useState(defaultModel)\n\n const equipmentContext = useContext(EquipmentContext)\n\n const [progress, setProgress] = useState(0)\n const [id, setId] = useState(null)\n const [wait, setWait] = useState(false)\n const [ready, setReady] = useState(false)\n\n const [errors, setErrors] = useState([])\n\n const onChange = (value: Partial) => {\n const s = {...model, ...value}\n setModel(s)\n }\n\n const onStart = async () => {\n // validate model\n const validation = validateInput(model, equipmentContext.state.profile)\n const isValid = validation.length === 0\n setErrors(validation)\n if (!isValid) { return }\n\n // reset status\n setReady(false)\n setProgress(0)\n\n // calculate model\n setWait(true)\n const input = getInputFromModel(model, equipmentContext.state.profile)\n const rv = await calculate(input)\n setId(rv.id)\n }\n\n useEffect(() => {\n if (id === null) { return }\n\n let cancel = false\n\n const run = async () => {\n // check status\n let it = 0\n let p = 0\n while (it < 100) {\n if (cancel) { return }\n await delay(5000)\n const rv = await getStatus(id)\n p = Math.max(p, rv.progress)\n setProgress(p)\n if (rv.status === 'Completed' || p >= 100) { break }\n it++\n }\n\n // redirect if ready\n setReady(true)\n window.open(`result/${id}`, '_blank')\n }\n\n run()\n\n return () => {\n cancel = true\n }\n }, [id])\n\n // reset errors when profile changed\n useEffect(\n () => { setErrors([]) },\n [equipmentContext.state.profile.id],\n )\n\n const handleHide = () => {\n if (ready) { setWait(false) }\n }\n\n const {coords: {lat, lng}} = model.location\n const locationLabel = lat.toFixed(3) + ', ' + lng.toFixed(3)\n\n return (<>\n
    ev.preventDefault()}>\n\n
    \n 1) Location\n\n onChange({location: x})}/>\n\n
    \n
    \n \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n\n
    \n\n
    \n 2) Power Assumptions\n\n
    Electric Grid (if available)
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n
    \n
    \n \n
    \n
    \n \n
    \n
    \n\n onChange({gridCost: x})}/>\n\n\n
    On-site generation
    \n\n
    \n
    \n \n
    \n
    \n \n
    \n
    \n\n onChange({fuelCost: x})}/>\n\n onChange({pvCost: x})}/>\n\n
    \n
    \n \n
    \n
    \n \n
    \n
    \n\n onChange({storageCost: x})}/>\n\n onChange({converterCost: x})}/>\n\n onChange({generatorCost: x})}/>\n\n
    \n\n
    \n 3) Financial Assumptions\n\n onChange({interestRate: x})}/>\n
    \n\n
    \n 4) Electric Load Inputs\n\n \n
    \n\n
    \n 5) Run HOMER®\n\n {errors.map(x => )}\n\n \n
    \n\n
    \n\n \n \n {!ready ? 'Calculating...' : 'Completed'}\n \n \n {!ready ?\n
    \n
    \n
    :\n <>\n \n }\n \n \n \n )\n}\n\nexport default Wizard\n","import React from 'react'\n\nconst Outro = () => {\n return (\n <>\n
    \n
    About the tool
    \n

    \n The HOMER Powering Health Tool uses the proprietary optimization algorithm of HOMER (Hybrid Optimization Model for Multiple Energy Resources), originally developed at the United States National Renewable Energy Laboratory (NREL), and enhanced and distributed by HOMER Energy by UL, a subsidiary of UL. The model has been made available online in this tool with funding and technical support from USAID, the Energy Sector Management Assistance Program (ESMAP) through the World Bank including in context of the Energy Storage Partnership and We Care Solaras well as contributions from numerous health and energy experts. Feedback on the tool is welcome and can be addressed to support@homerenergy.com.\n

    \n\n

    \n Disclaimer. The services of the website are provided strictly on an “as is” basis. There are no warranties, express or implied, including, but not limited to, any implied warranties of merchantability or fitness for a particular purpose, originality, results to be derived from the services or non-infringement of third party rights with respect to this agreement or the services. HOMER Energy by UL makes no representation, warranty, or guaranty as to the reliability, quality, suitability, availability, accuracy or completeness of the services provided by this tool. By using this tool, users expressly acknowledge that the services are still in the development process, have not been fully tested, and may not operate error-free. By agreeing to participate in the testing of the services, the user accepts all risks associated with the services and the operation thereof without limitation. Service providers should ensure that systems follow codes of practice for electrical safety and comply with all applicable national and local laws. Specialized codes for electrical installations in medical locations (e.g. IEC 60364-7-710) may also be relevant. This tool is not designed to meet a specific code.\n

    \n
    \n
    \n \n HOMER\n \n
    \n \n )\n}\n\nexport default Outro\n","import React from 'react'\nimport './App.css'\nimport 'bootstrap/dist/css/bootstrap.css'\nimport Intro from './Intro'\nimport Wizard from './Wizard'\nimport Outro from './Outro'\nimport {EquipmentProvider} from './EquipmentContext'\n\n\nconst App = () => {\n return (\n <>\n
    \n \n
    \n\n
    \n \n
    \n \n \n \n
    \n \n
    \n\n \n \n )\n}\n\nexport default App\n","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read https://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.0/8 are considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\ntype Config = {\n onSuccess?: (registration: ServiceWorkerRegistration) => void;\n onUpdate?: (registration: ServiceWorkerRegistration) => void;\n};\n\nexport function register(config?: Config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(\n process.env.PUBLIC_URL,\n window.location.href\n );\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit https://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl: string, config?: Config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl: string, config?: Config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl, {\n headers: { 'Service-Worker': 'script' }\n })\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready\n .then(registration => {\n registration.unregister();\n })\n .catch(error => {\n console.error(error.message);\n });\n }\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport * as serviceWorker from './serviceWorker';\n\nReactDOM.render(\n \n \n ,\n document.getElementById('root')\n);\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://bit.ly/CRA-PWA\nserviceWorker.unregister();\n"],"sourceRoot":""}